Créer une clé bootable pour x86 64-bits

02 juillet 2022 ― Pierre-Loup GOSSE

Résumé ― Le démarrage d'un système depuis une clé USB, dit clé bootable, peut être utile dans plusieurs cas de figure notamment pour l'installation d'un système cible sur une machine ou le dépannage de celle-ci. Nous verrons dans cette article les étapes pour créer une clé USB bootable UEFI pour l'architecture x86 64-bits : la compilation du kernel Linux, la création d'un petit système de fichiers Busybox avec son processus init, la génération du bootloader et la configuration de l'UEFI pour démarrer sur la clé USB.

Processus de démarrage

Avant de passer à la pratique, il est nécessaire de savoir comment une machine passe de sa mise sous tension à l'exécution de notre kernel.

BIOS/UEFI

Sous x86 64-bits, la mise sous tension de la machine se suit par l'exécution d'un BIOS/UEFI, firmware présent sur la carte mère de la machine. Son rôle principal est de charger en mémoire et d'exécuter un binaire sur la machine.

note
Magré leurs similitudes, le BIOS et l'UEFI restent différent. L'UEFI est une version améliorée remplaçant le BIOS tout en proposant un mode legacy assurant une rétrocompatibilité avec celui-ci. Nous utiliserons l'UEFI par la suite.

L'UEFI cherche dans plusieurs emplacements le binaire à exécuter. Généralement ces emplacements sont des périphériques de stockage tel qu'un disque dur ou une clé USB, mais cela peut aussi être un serveur comme PXE. Une liste de ses emplacements peut être définie et ordonnée par l'utilisateur, c'est ce qu'on appelle le bootorder. Les emplacements indiqués à l'UEFI doivent suivre une spécification lui permettant d'exécuter le bon binaire. On dit alors que l'emplacement est bootable.

Partition EFI

Pour qu'un périphérique de stockage, comme notre futur clé USB, soit bootable celle-ci doit avoir une partition EFI. C'est un format de système de fichiers qui suit les spécifications FAT, nous y placerons notre binaire à exécuter.

note
Une partition est un section d'un périphérique de stockage. Cela permet au sein d'un même périphérique de faire cohabiter plusieurs système de fichiers.

Binaire .efi

Une fois la partiton EFI detectée, l'UEFI va essayer d'exécuter le binaire se trouvant à l'emplacement /EFI/Boot/bootx64.efi pour une architecture 64 bits et /EFI/Boot/bootx32.efi en 32 bits. Le binaire bootx64.efi exécuté par l'UEFI peut être libre tant qu'il est au format .efi.

Bootloader

Généralement le binaire exécuté par l'UEFI est un bootloader. Son rôle est de charger en mémoire et d'exécuter un système d'exploitation présent sur la machine. Le bootloader propose aussi des alternatives de démarrage, permettant de démarrer sur un autre système pour réparer le principal par exemple. L'usage d'un bootloader est donc recommandé. En effet, l'UEFI est capable de démarrer l'image kernel sans passer par un bootloader. Cela demande quelques modifications au niveau de la configuration kernel. Malgré le gain de performance au démarrage, cette solution perd les avantages du bootloader.

Nous utiliserons le bootloader GRUB, globalement utilisé sur les distributions Debian, pour démarrer notre kernel Linux. Nous verrons comment configurer le bootloader GRUB pour charger notre kernel.

Kernel

Le bootloader passe l'exécution au kernel. Ce dernier rentre dans sa phase d'initialisation essayant de monter le système de fichiers racine, le rootfs, surlequel il compte exécuter le processus init. Sans système de fichiers ou de processus init, le kernel tombe en erreur et s'arrête. Nous allons voir comment générer un petit système de fichiers valide.

Système de fichiers

Nous allons dans cette partie nous concentrer sur la création d'un petit système de fichiers pour notre kernel. Avec son Process ID (PID) n°1, le processus init est le père de tous les processus, ça mort équivaut à l'arrêt du kernel (par un kernel panic). Ce processus init peut différer en fonction des utilisations. Sur la majorité des distributions Linux le processus init est Systemd. Ainsi, il est évident que le processus init n'est pas embarqué dans le binaire du kernel : ce sont deux choses à part entière. Le processus init est, comme le reste des applicatifs, présent dans le système de fichiers.

note
Le systèmes de fichiers peut cependant être embarqué dans le kernel. C'est notamment le cas lorsque le Secure Boot de l'UEFI est activé et que le kernel à besoin d'un initramfs à son démarrage. La vérification de la signature n'étant réalisé que sur le binaire exécuté, l'initramfs doit alors être inclut dans l'image kernel signée.

Nous allons donc générer un système de fichiers, qui contiendra notre fameux processus init, mais aussi un ensemble de binaire, bibliothèque, fichiers de configurations, etc, dont le processus init et ses processus enfant sont éventuellement dépendant. Le contenu d'un système de fichiers est une arborescence de fichier avec un dossier racine. Vous pouvez donc naturellement créer ce contenu en amont à partir d'une machine existante en créant un dossier racine, root par exemple, et y placer l'ensemble des fichiers nécessaires. Plutôt que de générer le contenu de notre système de fichier à la main, des outils nous existent pour nous simplifier la tâche.

Busybox

Pour cette article nous allons utiliser l'outil BusyBox. Cet outil nous permet de générer le contenu d'un système de fichiers minimaliste, souvent utilisé dans l'informatique embarqué où les espaces mémoire peuvent être restreint.

Téléchargez la dernière version de BusyBox (1.35.0 à la rédaction) dans le dossier ~/usb-bootable :

$ mkdir usb-bootable
$ cd usb-bootable
$ wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2
$ tar -xvf busybox-1.35.0.tar.bz2
$ busybox-1.35.0

Pour éviter des dépendances et s'assurer du bon fonctionnement de notre système de fichier, nous allons produire des binaires statiques. Pour ce faire, nous devons modifier la configuration de BusyBox. Son fonctionnement étant similaire au kernel, un fichier .config définit les variables et un menuconfig permet de les modifiers via une interface graphique :

$ cd busybox-1.35.0
$ make menu-config

Allez dans Settings et activez Build static binary. Quittez et sauvegardez la configuration (dans .config).

Capture d'écran du menuconfig BusyBox

note
Tout comme le menuconfig du kernel, bous pouvez faire des recherches avec / et avoir de l'aide ? pour chaque options.

Voici la configuration busybox générée de mon côté. Lancez la production des fichiers via la commande suivante :

$ make busybox install -j12

Cette commande produit l'arborescence de notre système de fichiers dans _install. Ce dernier contient les dossiers bin, sbin et usr. Exécutez la commande tree dans le dossier :

$ tree _install

_install/
├── bin
│   ├── arch -> busybox
│   ├── ash -> busybox
│   ├── base32 -> busybox
│   ├── base64 -> busybox
│   ├── busybox
│   ├── cat -> busybox
│   ├── chattr -> busybox
│   ├── chgrp -> busybox
│   ├── chmod -> busybox
...

Vous remarquerez que chaque binaire est un lien symbolique vers le binaire bin/busybox. La raison ? L'ensemble des binaires sont unifiés dans le binaire busybox permettant un gain de place (suppression de l'overhead ) dû au format de fichier d'exécution comme ELF. Les binaires cp, echo, dd, etc, se succèdent dans l'espace mémoire. Ainsi, exécuter la commande cp revient à se brancher à l'addresse mémoire du binaire cp dans le binaire bin/busybox. De part sa taille légère (2,7M), ce type de génération de système de fichiers minimaliste est très souvent utilisé dans l'informatique embarqué.

Processus init

Par défaut le processus init généré se nomme linuxrc. Pour notre utilisation, nous allons créer notre propre processus init. Copiez et renommez le dossier du rootfs _install dans ~/usb-bootable :

$ cp -a busybox-1.35.0/_install rootfs

Depuis la copie du rootfs, supprimez le fichier linuxrc et créez un nouveau fichier init à la racine de votre rootfs et ajoutez-y le contenu suivant :

~/usb-bootable/rootfs/init

#!/bin/sh

mkdir -p /dev
mount -t devtmpfs none /dev
mkdir -p /proc
mount -t proc none /proc
mkdir -p /sys
mount -t sysfs none /sys
setsid cttyhack /bin/sh

Dans ce processus init nous allons créer 3 dossiers à la racine :

  • /dev : dossier listant les périphériques détectés par le kernel.
  • /proc : dossier donnant des informations temps réel sur le kernel.
  • /sys : dossier permettant de contrôler les périphériques.

Le contenu de ces dossiers sont générés par le kernel, il s'agit de pseudo-système de fichiers, ils doivent être montés via la commande mount au démarrage. La dernière commande cttyhack /bin/sh lance un shell.

Approfondir
Voici une bonne documentation en ligne sur la hiérachie du sytème de fichier Linux.

Archive CPIO

Une fois notre rootfs minimal prêt il suffit de le compresser en une archive cpio. Il ne faut pas oublier au préalable de donner les droits d'exécution à nos fichiers :

$ chmod 777 -R rootfs
$ cd rootfs
$ find . | cpio -H newc -o | gzip > ../rootfs.gz

Notre système de fichiers rootfs.gz est prêt à l'utilisation.

Compilation d'un kernel Linux x86 64-bits

Une fois le système de fichiers prêt, compilons notre image kernel Linux mainline. Dans un premier temps, téléchargez la dernière version du kernel Linux :

$ git clone https://github.com/torvalds/linux.git

Puisque nous souhaitons exécuter notre kernel sur un ordinateur portable, nous voulons avoir accès à la console système directement sur son écran. Par défaut, le kernel n'affiche pas celle-ci sur l'écran. La console peut aussi être redirigée sur un port série avec l'argument console dans la commandline du kernel. L'affichage de contenu sur l'écran passe par le framebuffer du kernel. Cette couche d'abstraction, représentée par le device /dev/fb0, permet d'afficher des éléments graphiques.

note
Écrire dans le périphérique /dev/fb0 reviendra à écrire du contenu sur l'écran. Par exemple, $ cat /dev/random > /dev/fb0 affichera de la "neige", tandis que $ cat /dev/zero > /dev/fb0 "effacera" le contenu du framebuffer.

Pour activer l'affichage de la console sur le framebuffer et donc sur l'écran de notre ordinateur, il faut activer les options suivantes dans la configuration du kernel :

  • CONFIG_FRAMEBUFFER_CONSOLE
  • CONFIG_SYSFB_SIMPLEFB
  • CONFIG_FB

Depuis un ordinateur en x86 64-bits vous pouvez directement charger la configuration du kernel x86_64 avec :

$ make defconfig

Sinon en spécifiant le fichier :

$ make x86_64_defconfig

Ouvrez le menuconfig et activez les options. Affichez l'aide pour comprendre leur utilité. Si besoin, activez aussi les dépendances nécessaires. Voici la configuration kernel générée de mon côté. Une fois la configuration modifiée et sauvegardée, construisez le kernel :

$ make -j12

Notre image kernel ~/usb-bootable/linux/arch/x86/boot/bzImage est prête.

Génération du bootloader GRUB

Pour générer notre bootloader GRUB nous utiliserons l'outil grub-mkimage. Sous Debian, l'outil est présent dans le paquet grub-common.

Binaire bootx64.efi

Une fois le binaire installé, nous pouvons générer facilement un binaire bootx64.efi de notre bootloader :

$ grub-mkimage -o bootx64.efi -p /efi/boot -O x86_64-efi fat iso9660 part_gpt part_msdos normal boot linux configfile loopback chain efifwsetup efi_gop efi_uga ls search search_label search_fs_uuid search_fs_file gfxterm gfxterm_background gfxterm_menu test all_video loadenv exfat ext2 ntfs btrfs hfsplus udf

Voici la signification des différentes arguments :

  • L'option -o définit le nom du binaire généré. Par convention le nom doit être bootx64.efi pour une architecture 64 bits et bootx32.efi pour une architecture 32 bits. Ce fichier sera détecté et exécutable par l'UEFI.
  • L'option -p définit le préfixe du répertoire où se situe le binaire. Nous verrons son utilité pour le fichier de configuration GRUB.
  • L'option -O définit le format généré, ici un binaire x86_64 pour UEFI.
  • Le reste des arguments sont les modules à embarquer dans le binaire. Par exemple le module linux nous permettra de charger l'image kernel, et le module boot de le démarrer.

Fichier de configuration grub.cfg

Au démarrage, le bootloader GRUB va proposer un interpréteur de commande. Cet interpréteur permet d'exécuter des commandes, tel que charger le kernel et l'exécuter. Pour simplifier la tâche et rendre l'utilisation du bootloader plus intuitif, nous allons créer un fichier de configuration GRUB pour proposer un menu d'entrée au démarrage. Chaque entrée du menu définit à des commandes à exécuter avant l'exécution de la commande boot qui lance l'exécution du kernel.

Nous allons créer une entrée pour charger notre kernel et son rootfs. Le rootfs n'étant pas présent sur le périphérique de stockage de la machine, mais sur notre clé USB avec l'image kernel, il est nécessaire de le charger en RAM via le bootloader. Le rootfs sera alors accessible au démarrage du kernel et notre processus init sera exécuté. Créez à la racine de votre dossier le fichier grub.cfg :

~/usb-bootable/grub.cfg

menuentry 'Boot Linux kernel' {
    linux /efi/boot/bzImage
    initrd /efi/boot/rootfs.gz
}

Remarquez ici l'utilisation du préfixe /efi/boot définit lors de la génération du bootloader GRUB.

note
La commande initrd GRUB permet de charger un système de fichiers en RAM. Le nom "initrd" fait référence à l'initial ramdisk, un système de fichiers temporaire d'initialisation permettant de monter le système de fichier final. Cependant l'utilisation de cette commande n'est pas réservée à l'initrd. En effet, du point de vue du bootloader notre rootfs ou un initrd reste un système de fichiers à charger en RAM.

Clé USB bootable

Les éléments constituant notre clé USB sont prêts : le kernel, le rootfs avec un processus init et le bootloader et sa configuration. Nous allons maintenant voir comment produire une clé USB bootable embarquant ces éléments.

Image

En informatique, une image désigne la réplique du contenu, bit à bit, d'un périphérique de stockage. L'image peut ensuite être stockée sur un autre périphérique de stockage. Par exemple, on peut créer l'image d'un disque dur et le stocker ailleurs (pour des sauvegardes) avec des binaires comme dd. Ainsi, plutôt que de manipuler directement le stockage de notre clé USB pour la rendre bootable ― c'est-à-dire, pour rappel, de créer une partition EFI au format FAT et d'y placer nos éléments ― nous allons créer une image de notre clé USB que nous copierons ensuite sur le stockage de celle-ci. Cela à plusieurs avantages, donc être capable de copier la même image sur plusieurs périphériques.

Fichier image

Commençons par créer le fichier image vide d'une taille de 34M. Nous verrons par la suite pourquoi la taille 34M est importante. Pour ce faire, on utilise la commande dd avec en entrée le fichier spécial /dev/zero générant un flux constant de cactère nul vers image :

$ sudo dd if=/dev/zero of=usb.img bs=1M count=34

34+0 enregistrements lus
34+0 enregistrements écrits
35651584 octets (36 MB, 34 MiB) copiés, 0,022835 s, 1,6 GB/s

Loop device

Nous venons de créer le fichier image vierge. Pour ajouter notre contenu, nous allons rendre accessible notre image (qui est à l'état de fichier) en un loop device, c'est à dire un pseudo-périphérique accessible par bloc où nous serons désormais capable d'écrire correctement dans de notre image.

La première étape consiste à récupérer un pseudo-périphérique loop libre présent dans /dev :

$ losetup -f

/dev/loop0

Nous pouvons attacher, avec les droits super-utilisateur, notre image sur ce loopdevice (remplacez le /dev/loop0 par celui retourné à la commande précédente) :

# losetup /dev/loop0 usb.img

Notre image est maintenant attachée au pseudo-périphérique /dev/loop0. Affichez ses informations via la commande fdisk :

# fdisk -l /dev/loop0

Disque /dev/loop31 : 34 MiB, 35651584 octets, 69632 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets

Dans la suite des manipulations utilisez la commande fdisk pour votre les informations de votre image évoluer. Essayons de monter ce pseudo-périphérique dans un dossier pour accéder à son contenu :

$ mkdir img
# mount /dev/loop0 img

mount: ~/usb-bootable/img: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.

Voilà une jolie erreur tout à fait normale ! Notre image étant vide (remplie de caractère nul par /dev/zero) aucune partition ni système de fichiers ne sont présents comme en témoigne les informations affichées par fdisk. Le kernel est incapable de monter et manipuler notre image.

Formatage

Avant d'y copier nos éléments, nous allons devoir formater notre image en y ajoutant une partition EFI avec un système de fichiers FAT.

Table de partition

Pour ajouter des partitions il est nécessaire d'écrire une table de partitionnement. Créez une table de partition MBR msdos sur le pseudo-périprérique de notre image :

# parted -s /dev/loop0 mklabel msdos
# fdisk -l /dev/loop0

Disque /dev/loop31 : 34 MiB, 35651584 octets, 69632 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0xc22ab48d

Deux nouvelles lignes, le type et l'identifiant du disque, sont affichées par la commande fdisk.

Partition primaire

Pour simplifier, nous allons créer une seule partition FAT32 (de la famille FAT) pour notre image qui contiendra l'ensemble de nos éléments, c'est la partition primaire. Le format FAT32 est nécessaire pour que notre UEFI puisse considérer cette partition à explorer pour y trouver le binaire de notre bootloader GRUB.

note
À la différence des autres système de fichier tel que les ext, le format FAT32 possède moins de fonctionnalités comme les droits utilisateurs sur les fichiers. La taille minimum requise pour FAT32 est 32M.

Notre table de partition étant prête, nous pous ajotuer notre partition primaire. Pour une question d'alignement mémoire la partition doit commencer à 1 MiB :

# parted -s /dev/loop0 mkpart primary 1MiB 100%
# fdisk -l /dev/loop0

Disque /dev/loop31 : 34 MiB, 35651584 octets, 69632 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0xc22ab48d

Périphérique  Amorçage Début   Fin Secteurs Taille Id Type
/dev/loop0p1           2048 69631    67584    33M 83 Linux

On aperçoit dès à présent notre partition primaire p1 dans /dev/loop0 de type Linux. Elle commence au secteur n°2048. Un secteur faisant 512 octets, nous retrouvons notre alignement de 1MiB : 2048 * 512 = 1048576 octets = 1 MiB. La taille minimal d'une partition FAT 32 doit être supérieur à 32M, nous somme obligé avec l'alignement de dépasser un peu, d'où les 34M (histoire d'être sûr).

Flag ESP

À ce stade, notre partition primaire est vierge et sans système de fichiers. Nous devons la transformer en une partition EFI capable d'être détecter et démarrer par l'UEFI. L'ajout du flag esp à la partition primaire permet de faire ce changement :

# parted -s /dev/loop0 set 1 esp on
# fdisk -l /dev/loop0

Disque /dev/loop0 : 34 MiB, 35651584 octets, 69632 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0x0957412c

Périphérique Amorçage Début   Fin Secteurs Taille Id Type
/dev/loop0p1           2048 69631    67584    33M ef EFI (FAT-12/16/32)

On remarque que le type est passé de Linux à EFI avec la supposition que la partition contient un système de fichiers FAT. Essayez de monter cette partition :

# mount /dev/loop0p1 img

mount: ~/usb-bootable/img: wrong fs type, bad option, bad superblock on /dev/loop1p1, missing codepage or helper program, or other error.

Même erreur que tout à l'heure ! En effet, bien que notre partition soit déclaré comme EFI elle ne contient cependant toujours pas de système de fichiers.

FAT 32

Formattons la partition primaire EFI en FAT 32 :

# mkfs.fat -F32 /dev/loop0p1

mkfs.fat 4.1 (2017-01-24)

# fdisk -l /dev/loop0

Disque /dev/loop31 : 34 MiB, 35651584 octets, 69632 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0xc22ab48d

Périphérique  Amorçage Début   Fin Secteurs Taille Id Type
/dev/loop0p1           2048 69631    67584    33M ef EFI (FAT-12/16/32)

Aucun changement n'est observable via fdisk, cependant notre kernel est maintenant en mesure de monter notre partition /dev/loop0p1.

Arborescence

Nous pouvons désormais monter correctement la partition dans le dossier img :

# mount /dev/loop0p1 img

La dernière étape consiste à copier dans notre image nos éléments produits dans les parties précédentes, à savoir : notre bootloader GRUB et sa configuration, l'image kernel et son rootfs compressé. Copier nos fichiers à la racine du système de fichiers de notre image ne fonctionnera pas. En effet, nous avons vu que l'UEFI va chercher le binaire bootx64.efi dans le dossier /EFI/Boot et que nous avons indiqué dans la configuration GRUB que notre image kernel et son rootfs se trouve dans ce même dossier avec le préfixe /efi/boot.

note
Le format FAT 32 est insensible à la casse, c'est-à-dire que le dossier /EFI/Boot et /efi/boot déclaré comme préfix dans GRUB pointe sur le même dossier.

Nous devons donc copier l'ensemble des éléments dans le dossier /EFI/Boot :

# mkdir -p img/EFI/Boot
# bootx64.efi grub.cfg linux/arch/x86/boot/bzImage rootfs.gz img/EFI/Boot
$ tree img

img
└── EFI
    └── Boot
        ├── bootx64.efi
        ├── bzImage
        ├── grub.cfg
        └── rootfs.gz

Le contenu de notre image est prêt !

Démontage

Démontez le pseudo-périphérique du dossier img et détachez l'image :

# umount img
# losetup -d /dev/loop0

note
La commande fdisk -l sur notre fichier image usb.img vous affichera le même contenu que lorsque la commande était exécutée sur le pseudo-périphérique, à savoir les partitions de notre image.

Notre fichier image usb.img est désormais prêt à être flashé sur un autre périphérique de stockage. Nous opterons pour une clé USB, de préférence vierge.

Flashage

Branchez la clé USB sur votre ordinateur et récupèrez le périphérique associé via lsblk ou en lisant les logs du kernel via dmesg | tail. Dans mon exemple, la clé USB est associé au périphérique /dev/sdd. Avec la commande fdisk -l /dev/sdd vous pouvez observer le partitionnement actuel de votre clé USB. Nous allons le remplacer avec notre image via la commande dd (n'oubliez pas de remplacer la destination d'écriture avec votre périphérique) :

# dd if=usb.img of=/dev/sdX status=progress

Avant de débranchez votre clé USB exécutez la commande sync pour assurer que toutes les écritures sur le périphérique soient faites.

Démarrage sur ordinateur x86 64-bits

Munissez-vous d'un ordinateur x86 64-bits et branchez-y votre clé USB bootable. Démarrez l'ordinateur et interrompez l'UEFI pour changer son bootorder et ainsi démarrer en premier sur votre clé USB bootable. Une fois la configuration modifiée, sauvegardez et quittez l'UEFI avec un redémarrage "Save and reset". Au redémarrage, l'UEFI détectera votre clé USB et sa partition ESP et exécutera votre bootloader. Vous devrez voir afficher le menu d'entrée GRUB avec le choix "Boot Linux kernel".

note
Dans GRUB la touche e vous permet de modifier l'entrée sélectionnée avant de l'exécuter. La touche c vous permet d'ouvrir la console GRUB pour exécuter des commandes manuelles.

Sélectionnez cette entrée en appuyant sur "Entrée" : votre kernel s'exécute !

Conclusion

Nous avons vu comment créer une simple clé USB bootable. Le format FAT 32 pose cependant certaines limites, tel que la taille maximale d'un fichier ou son insensibilité à la casse. Vous pouvez modifier le rootfs pour ajouter vos propres binaires (et ses dépendances) en fonction de vos besoins.

Bibliographie

Firmware, https://en.wikipedia.org/wiki/Firmware
Restent différent, https://www.thewindowsclub.com/difference-between-bios-and-uefi
PXE, https://fr.wikipedia.org/wiki/Preboot_Execution_Environment
EFI, https://en.wikipedia.org/wiki/EFI_system_partition
FAT, https://fr.wikipedia.org/wiki/File_Allocation_Table
Partition, https://fr.wikipedia.org/wiki/Partition_(informatique)
Bootloader, https://fr.wikipedia.org/wiki/Chargeur_d%27amor%C3%A7age
Démarrer l'image kernel sans passer par un bootloader, https://tecporto.pt/wiki/index.php/Booting_the_Linux_Kernel_without_a_bootloader
Process ID, https://en.wikipedia.org/wiki/Process_identifier
Systemd, https://en.wikipedia.org/wiki/Systemd
Secure Boot, https://fr.wikipedia.org/wiki/UEFI#Lancement_s%C3%A9curis%C3%A9_(secure_boot)
BusyBox, https://en.wikipedia.org/wiki/BusyBox
Version de BusyBox, https://busybox.net/downloads/
Binaires statiques, https://en.wikipedia.org/wiki/Static_build
Configuration busybox, busybox.config
Overhead, https://en.wikipedia.org/wiki/Overhead_(computing)
ELF, https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
/dev, https://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/dev.html
/proc, https://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/proc.html
/sys, https://linuxhint.com/using-sys-filesystem-in-linux/
Pseudo-système de fichiers, https://en.wikipedia.org/wiki/Synthetic_file_system
Bonne documentation, https://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/
Cpio, https://en.wikipedia.org/wiki/Cpio
Framebuffer, https://fr.wikipedia.org/wiki/Framebuffer_Linux
Configuration kernel, kernel.config
Grub-common, https://packages.debian.org/bullseye/grub-common
Initial ramdisk, https://fr.wikipedia.org/wiki/Initrd
Dd, https://fr.wikipedia.org/wiki/Dd_(Unix)
/dev/zero, https://en.wikipedia.org/wiki//dev/zero
Loop device, https://en.wikipedia.org/wiki/Loop_device
Table de partitionnement, https://fr.wikipedia.org/wiki/Table_de_partitionnement
MBR, https://fr.wikipedia.org/wiki/Master_boot_record
FAT32, https://fr.wikipedia.org/wiki/FAT32
Alignement mémoire, https://www.thomas-krenn.com/en/wiki/Partition_Alignment_detailed_explanation