Firmware Linux, comment implémenter un bon moyen de mettre à jour?

Je développe un appareil basé sur Linux utilisant un alix 2d13.

J’ai développé un script qui s’occupe de créer un fichier image, de créer les partitions, d’installer le chargeur de démarrage (syslinux), le kernel et l’initrd et de placer les fichiers du système de fichiers racine dans la bonne partition.

Les fichiers de configuration se trouvent sur le système de fichiers tmpfs et sont créés au démarrage du système par un logiciel qui lit un fichier XML qui réside sur une propre partition.

Je cherche un moyen de mettre à jour le système de fichiers et j’ai considéré deux solutions:

  • la mise à jour du firmware est un fichier compressé pouvant contenir le kernel, initrd et / ou la partition rootfs, de cette façon, au redémarrage, initrd fera attention à placer l’image rootfs sur la bonne partition;
  • la mise à jour du firmware est un fichier compressé pouvant contenir deux archives tar, une pour le démarrage et une pour le système de fichiers racine.

Chaque solution a ses propres avantages: – une image de système de fichiers me permet de supprimer tous les fichiers inutilisés mais nécessite beaucoup de temps et cela va rapidement tuer la mémoire compacte; – une archive est plus petite, nécessite moins de temps pour la mise à jour, mais j’aurai les caos sur le système de fichiers racine en peu de temps.

Une autre solution pourrait consister à mettre une liste de fichiers et à placer un script de pré / post-mise à jour dans l’archive tar afin que tout fichier ne résidant pas dans la liste de fichiers soit supprimé.

Qu’est-ce que tu penses?

J’ai utilisé l’approche suivante. Il était quelque peu basé sur le document “Construire des systèmes Linux embarqués compatibles avec Murphy”, disponible ici . J’ai utilisé les fichiers versions.conf décrits dans ce document, pas les fichiers cfgsh.

  • Utilisez un kernel de démarrage dont le travail consiste à remonter en boucle le système de fichiers racine “principal”. Si vous avez besoin d’un kernel plus récent, alors kexec dans ce nouveau kernel juste après le assembly en boucle. J’ai choisi de mettre l’initialisation complète du kernel de démarrage dans initramfs, avec busybox et kexec (les deux liés statiquement), et mon init était un simple script shell que j’ai écrit.
  • Un ou plusieurs systèmes de fichiers racine “OS principaux” existent sur un système de fichiers “image OS” en tant que fichiers image disque. Le kernel de démarrage en choisit un basé sur un fichier versions.conf. Je ne gère que deux fichiers image principaux du système d’exploitation, le fichier courant et le fichier de secours. Si l’actuel échoue (plus sur la détection des pannes plus tard), le kernel de démarrage initialise la reprise. Si les deux échouent ou s’il n’y a pas de solution de secours, le kernel de démarrage fournit un shell.
  • La configuration du système est sur une partition séparée. Ceci n’est normalement pas mis à jour, mais il n’y a aucune raison pour que ce ne soit pas le cas.
  • Il existe quatre partitions au total: boot, image du système d’exploitation, configuration et données. La partition de données est destinée aux applications utilisateur destinées à une écriture fréquente. boot n’est jamais monté en lecture / écriture. L’image du système d’exploitation est uniquement (ré) montée en lecture / écriture lors des mises à niveau. config est seulement monté en lecture / écriture lorsque les éléments de configuration doivent changer (espérons-le jamais). les données sont toujours montées en lecture / écriture.
  • Les fichiers d’image disque contiennent chacun un système Linux complet, y compris un kernel, des scripts d’initialisation, des programmes utilisateur (par exemple, busybox, applications produit) et une configuration par défaut copiée sur la partition de configuration au premier démarrage. Les fichiers sont de la taille nécessaire pour y intégrer tout. Aussi longtemps que je laissais une marge de développement suffisante pour que la partition d’image du système d’exploitation soit toujours assez grande pour contenir trois fichiers d’image principaux du système d’exploitation (pendant la mise à niveau, je ne supprime pas les anciens permettre à l’image principale du système d’exploitation de croître au besoin. Ces fichiers image sont toujours (en boucle) montés en lecture seule. L’utilisation de ces fichiers élimine également la difficulté de faire face aux échecs de la mise à niveau de fichiers individuels dans un rootfs.
  • Les mises à niveau sont effectuées en transférant une archive tar à extraction automatique vers un fichier tmpfs. Le début de ce script remonte l’image en lecture / écriture du système d’exploitation, puis extrait la nouvelle image principale du système d’exploitation sur le système de fichiers image du système d’exploitation, puis met à jour le fichier versions.conf (en utilisant la méthode rename décrite dans le papier “murphy”). Une fois cela fait, je touche un fichier de tampon indiquant qu’une mise à niveau est survenue, puis redémarre.
  • Le kernel de démarrage recherche ce fichier de tampon. S’il le trouve, il le déplace vers un autre fichier de tampon, puis démarre le nouveau fichier image du système d’exploitation principal. Le fichier image du système d’exploitation principal doit supprimer le fichier de tampon lorsqu’il démarre correctement. Si ce n’est pas le cas, le chien de garde déclenchera un redémarrage, puis le kernel de démarrage le verra et détectera un échec.
  • Vous remarquerez que quelques points d’échec sont possibles lors d’une mise à niveau: synchronisation de versions.conf pendant la mise à niveau et effacement / suppression des fichiers de tampon (trois instances). Je ne pouvais pas trouver un moyen de les réduire davantage et de réaliser tout ce que je voulais. Si quelqu’un a une meilleure suggestion, j’adorerais l’entendre. Des erreurs de système de fichiers ou des pannes de courant lors de l’écriture de l’image du système d’exploitation peuvent également se produire, mais j’espère que le système de fichiers ext3 offrira une chance de survie dans ce cas.

Vous pouvez avoir une partition séparée pour la mise à jour (Say Side1 / Side2). Le kernel existant, rootfs, se trouve dans Side1, puis placez la mise à jour dans Side2 et basculez. Vous pouvez ainsi réduire l’usure et augmenter la durée de vie, mais l’appareil devient plus coûteux.

Vous pouvez formater rapidement les partitions avant d’extraire les fichiers tar. Ou allez avec la solution d’image mais utilisez la plus petite image possible et après dd faites un redimensionnement du système de fichiers (bien que ce ne soit pas nécessaire pour le stockage en lecture seule)