Introduction
Le BIOS est une interface relativement connue. Ce fameux panneau de configuration qui apparaît si on se roule sur son clavier au démarrage d’un ordinateur.
Néanmoins, comme toute logiciel, le BIOS peut contenir des vulnérabilités.
C’est pourquoi, aux alentours de 2006, le Unified Extensible Firmware Interface Forum[1], principalement porté par Intel sors la première spécification publique de l’UEFI, de sorte à proposer à tous les industriels concepteurs de carte mère une conception unifiée du démarrage, de l’intégrité et de la sécurité.
Cela a eu plusieurs effets de bord, le premier a été de complexifier le changement d’OS sur les machines, notamment pour Linux. Mais cela a également ouvert à la voie à des approche de sécurité alors peu commune, notamment le Secure Boot.
Cela a également contribué à rendre plus clair et commune la notion de Platform Initialization (PI) qui est la notion de démarrage sécurisé et sûr d’une machine.

Figure 1 – Intel PI global schema
Dans cet approche, on voit que l’UEFI va intervenir du démarrage électrique de l’ensemble des composants jusqu’au lancement d’un Système d’explOitation (OS).
Comme l’UEFI est une spécification, chaque industriel (Dell, Lenovo, Nokia, HP, …) y est allé de son implémentation spécifique et closed-source. Néanmoins, dans une approche de généralisation des sécurité pre-boot, une implémentation open-source est sorti du lot et est progressivement devenu une référence. Cette implémentation est EDK-II (qu’on prononce « EDK-2 ») et c’est le sujet de cet article.
Le framework EDK-II
EDK II[2] signifie EFI Developpment Kit, il s’agit d’une framework permettant de créer son propre environnement de Boot réalisant un certain nombre d’étape de sécurité et d’intégrité avant de donner la main au système d’exploitation (Windows, Linux, …).
Ça n’est pas le seul framework implémentant l’EFI, on pourrait par exemple citer Coreboot[3] et Libreboot[4] comme alternative. Néanmoins, à l’exception de Google, EDK semble être le framework le plus utilisé par les constructeurs de carte mère.
Ce type de framework est aussi beaucoup utilisé pour la communication avec des TPM (Trusted Platform Module), qui sont des petits composants présents sur les cartes mères dont le but est de stocker et fournir des clefs de chiffrement/signature et des fonctions cryptographiques associés. Mais nous y reviendrons sans doute dans un futur article.
Le principal élément différenciant d’EDK-II est son aspect simple. Il s’agit réellement d’un framework conçu pour être extensible à volonté et permettre toutes les adaptations spécifiques d’un constructeur, là où les autres implémentation EFI sont plus restreintes et orientés sur une approche spécifique.
Tianocore, l’organisation maintenant EDK-II présente aussi un ensemble de ressources, un wiki très complet et une formation standard sur le sujet.
Pour s’en convaincre, on peut réaliser l’exercice de créer une démo EDK-II sur un environnement virtuel.
Compiler pour une VM QEMU
Pour réaliser cet environnement, on utilise couramment QEMU qui dispose de fonctions d’émulation hardware permettant d’émuler assez finement un démarrage de machine et donc d’observer le fonctionnement d’un firmware au démarrage.
On suppose qu’on est sur un environnement Ubuntu classique. On va donc y récupérer une version de QEMU classique avec un environnement Ubuntu dessus :
|
mkdir test_ubuntu mv test_ubuntu wget https://old-releases.ubuntu.com/releases/24.04/ubuntu-24.04.2-live-server-amd64.iso apt install qemu-system-x86_64 qemu-img create -f qcow2 example.qcow2 32G |
Pour se simplifier la vie, on peut créer un template Ubuntu qu’on pourra réutiliser au besoin :
| #!/usr/bin/env bash# ## Host #QEMU_BIN=qemu-system-x86_64if [[ -x « $(command -v ${QEMU_BIN}) » ]]; then echo « [x] Found ${QEMU_BIN} » ${QEMU_BIN} –version else echo « [!] ${QEMU_BIN} not found on the system! Make sure it is installed » exit -1 fi# END Host # # Guest # # 0. Meta NAME= »-name QEMU_Starter_Ubuntu_Server_24.04″# 1. Machine selection MACHINE= »-machine pc »# 2. CPU override CPU= »-cpu host » SMP= »-smp 2″ ACCELERATOR= »-accel kvm »# 3. Memory override MEMORY= »-m 4G »# 4. BIOS/UEFI settingsEFI_FLASH_PATH= » » EFI_VARS_PATH= » »EFI_FLASH_DRV= »-drive if=pflash,format=raw,readonly=on,file=${EFI_FLASH_PATH} » EFI_VARS_DRV= »-drive if=pflash,format=raw,file=${EFI_VARS_PATH} »# 5. Device selection # 5.1. Input INPUT_DEV= »-device usb-ehci -device usb-kbd -device usb-mouse »# 5.2. Network #NETWORK_DEV= »-device virtio-net-device,netdev=net0 -netdev user,id=net0″ NETWORK_DEV= » »# 5.3 Storage STORAGE_DEV= »-device nvme,drive=hd0,serial=super-fast-boi »# 5.4. Display DISPLAY_DEV= »-device virtio-gpu,xres=1280,yres=720″# 5.5. Sound SOUND_DEV= »-device intel-hda »# 5.6. Misc MISC_DEV= » »# 6. Drive settings (a.k.a disk images) ISO_PATH= »./ubuntu-24.04.2-live-server-amd64.iso » DISK_PATH= »./example.qcow2″CD_DRV= »-drive id=cd0,media=cdrom,file=${ISO_PATH} » MAIN_DRV= »-drive id=hd0,if=none,format=qcow2,file=${DISK_PATH} »# END Guest# Launch the machine set -x ${QEMU_BIN} ${NAME} ${MACHINE} ${CPU} ${SMP} ${ACCELERATOR} ${MEMORY} \ ${INPUT_DEV} ${NETWORK_DEV} ${STORAGE_DEV} ${DISPLAY_DEV} ${SOUND_DEV} ${MISC_DEV} \ |
Pour le moment, il n’y a pas d’EFI, mais les variables EFI existes et ont juste à être remplies pour qu’il y a un UEFI qui se lance avant l’OS.
Ensuite, EDK-II va pouvoir être installé :
| git clone https://github.com/tianocore/edk2cd edk2 git submodule update –init make -C BaseTools . edksetup.sh |
Une fois cela fait, normalement, un fichier « Conf/target.txt » est apparu dans le dossier edk2, il faut l’éditer pour spécifier l’architecture matérielle souhaité.
Dans cet exemple, on spécifie :
| ACTIVE_PLATFORM = OvmfPkg/OvmfPkgX64.dsc TARGET = RELEASE TARGET_ARCH = X64 TOOL_CHAIN_TAG = GCC5 |
Une fois cela fait, on peut lancer un build à la racine de edk2 via la commande « build », ce qui donnerait au bout de quelques minutes un résultat de cette nature :

Figure 2 – résultat de compilation EDK-II
Une fois cela fait, il faut se rendre dans « Build/OvmfX64/RELEASE_GCC5/FV » et on y trouve deux fichiers indispensables :
- OVMF.fd
- OVMF_VARS.fd
Le fichier OVMF est le « firmware », quant à OVMF_VARS, il s’agit d’un agrégat de l’ensemble des données d’environnement nécessaires à la découverte et à la communication avec les composants hardware.
On récupère donc ces deux fichiers que l’on va renommer pour les rendre explicites :
- OVMF.fd ➔ bios.bin
- OVMF_VARS.fd ➔ efi-vars.raw
Et enfin, on les place dans le dossier du template de VM QEMU ubuntu et on édite le template de la sorte :
| # 4. BIOS/UEFI settings EFI_FLASH_PATH= »bios.bin » EFI_VARS_PATH= »efi-vars.raw » # […]# Launch the machine set -x${QEMU_BIN} ${NAME} ${MACHINE} ${CPU} ${SMP} ${ACCELERATOR} ${MEMORY}
${EFI_FLASH_DRV} ${EFI_VARS_DRV} ${INPUT_DEV} ${NETWORK_DEV} ${STORAGE_DEV} ${DISPLAY_DEV} ${SOUND_DEV} ${MISC_DEV} \${CD_DRV} ${MAIN_DRV} $* |
A partir de là, on peut lancer une machine QEMU avec un UEFI EDK-II, ce qui donne :

Figure 3 – lancement d’une VM avec UEFI EDK-II
On voit clairement le logo de TianoCore au démarrage avant le lancement de l’OS, tout comme on verrait un logo de constructeur tels que Dell, Lenovo ou HP sur une machine d’un de ces constructeurs.
Si l’on regarde la sortie de l’EFI, on peut aussi voir qu’il a vérifié l’ordre de boot et sélectionné le bootloader qu’il a identifié :

Figure 4 – Sélection de bootloader par l’EFI
L’EFI d’EDK-2 pourrait faire beaucoup plus avec de la configuration, mais cela rendrait cet article très indigeste.
Conclusion
On a vu au travers de cet article que la création et la configuration d’un UEFI n’est plus réservé à une élite technique de constructeur de machine. Le framework open-source EDK-II rend la chose accessible aux personnes ayant un background technique et souhaitant tester et développer des environnement pré-OS.
QEMU demeure un environnement prépondérant pour ce type de développement du fait de sa facilité de lancement.
La difficulté pour son usage en cas réel réside dans le test sur environnement physique, où il y a un risque de « bricker » une machine, c’est à dire la rendre inutilisable en cas de mauvais fonctionnement.
Pour aller plus loin
A partir du moment où un environnement UEFI peut être placé, de nombreuses sécurités peuvent être ajoutés dessus tels que :
- Vérification d’intégrité des systèmes physiques
- Communication avec un TPM
- Déchiffrement hardware d’un disque de stockage
- Authentification pre-boot via un composant FIDO/Smartcard
Ces capacités sont encore mal documentées aujourd’hui, mais fournissent pour beaucoup de sociétés spécialisés des avantages techniques considérables face au vol physique de donnée, aux compromissions de matériel et à la sécurité de l’authentification.
[2] https://github.com/tianocore/edk2
Auteur : Pacome Tisserand | Technical Presales & Integrator at SERMA Safety and Security