« Hello, world! » en UEFI¶
Source: https://wiki.osdev.org/UEFI_ISO_Bare_Bones
Récupération du source pour EFI¶
curl -O http://ftp.debian.org/debian/pool/main/g/gnu-efi/gnu-efi_3.0v.orig.tar.xz
tar jxvf gnu-efi_3.0v.orig.tar.xz
Edition manuelle de lib/data.c
, suppression des références à LibStubStriCmp
, LibStubMetaiMatch
, LibStubStrLwrUpr
:
EFI_UNICODE_COLLATION_INTERFACE LibStubUnicodeInterface = {
NULL, //LibStubStriCmp,
NULL, //LibStubMetaiMatch,
NULL, //LibStubStrLwrUpr,
NULL, //LibStubStrLwrUpr,
Construction du bootloader¶
Fichier assembleur source:
#include <efi.h>
#include <efilib.h>
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status;
EFI_INPUT_KEY Key;
/* Store the system table for future use in other functions */
ST = SystemTable;
/* Say hi */
Status = ST->ConOut->OutputString(ST->ConOut, L"Hello World\r\n"); // EFI Applications use Unicode and CRLF, a la Windows
if (EFI_ERROR(Status))
return Status;
/* Now wait for a keystroke before continuing, otherwise your
message will flash off the screen before you see it.
First, we need to empty the console input buffer to flush
out any keystrokes entered before this point */
Status = ST->ConIn->Reset(ST->ConIn, FALSE);
if (EFI_ERROR(Status))
return Status;
/* Now wait until a key becomes available. This is a simple
polling implementation. You could try and use the WaitForKey
event instead if you like */
while ((Status = ST->ConIn->ReadKeyStroke(ST->ConIn, &Key)) == EFI_NOT_READY) ;
return Status;
}
Fichier Makefile:
name=uefihello
.PHONY: uefi-shell hello
all: uefi-shell hello
hello: BOOTX64.EFI OVMF.fd
BOOTX64.EFI: hello.c build_hello.sh
./build_hello.sh
OVMF.fd: /usr/share/ovmf/OVMF.fd
cp $^ $@
clean:
rm -f OVMF.fd BOOTX64.EFI *.o hdimage.bin fat.img
(cd mkgpt; make clean)
run-shell: uefi-shell
qemu-system-x86_64 -boot menu=on -bios OVMF.fd -net none
run-hello: hello
qemu-system-x86_64 -boot menu=on -bios OVMF.fd -net none -hda hdimage.bin
Fichier Makefile (version Docker):
name=uefihello
.PHONY: uefi-shell hello container
all: uefi-shell hello
hello: BOOTX64.EFI OVMF.fd
BOOTX64.EFI: hello.c build_hello.sh container
docker run -v `pwd`:/mnt $(name) /mnt/build_hello.sh /mnt
uefi-shell: OVMF.fd
OVMF.fd: container
docker run -v `pwd`:/mnt $(name) cp /usr/share/ovmf/OVMF.fd /mnt
container: container.build
container.build: Dockerfile
docker build -t $(name) .
touch container.build
clean:
rm -f OVMF.fd BOOTX64.EFI *.o hdimage.bin fat.img container.build
run-shell: uefi-shell
qemu-system-x86_64 -boot menu=on -bios OVMF.fd -net none
run-hello: hello
qemu-system-x86_64 -boot menu=on -bios OVMF.fd -net none -hda hdimage.bin
FROM debian
LABEL author="gas@mines.paris"
RUN apt-get update
RUN apt-get install -y ovmf binutils-mingw-w64 gcc-mingw-w64-x86-64 xorriso mtools
RUN apt-get install -y git automake build-essential
RUN git clone https://github.com/jncronin/mkgpt.git
WORKDIR mkgpt
RUN automake --add-missing; exit 0
RUN autoreconf
RUN ./configure
RUN make
RUN pwd
CMD ["ls", "-l"]
Ecriture sur USB¶
Écriture sur une clef USB du bootloader sous Linux:
lsblk
sudo dd if=hellokernel.bin of=/dev/sdb