gudenau
gudenau

Reputation: 540

Create Bootable UEFI ISO

I am trying to create a bootable UEFI ISO, but Hyper-V does not see it as a valid UEFI filesystem. What am I doing wrong?

ISO creation:

xorriso -as mkisofs -o uefi.iso -iso-level 3 -V UEFI isoFiles

isoFiles has a single file, boot/hello.efi. When mounted or opened in an archive manager the file exists.

Hyper-V output: Hyper-V screenshot

Edit: Let's have a lot more context for this shall we?

This is the EFI code, it uses gnu-efi v3.0.8:

#include <efi.h>
#include <efilib.h>

EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable){
    EFI_STATUS Status;
    EFI_INPUT_KEY Key;

    ST = SystemTable;

    Status = ST->ConOut->OutputString(ST->ConOut, L"Hello world!\n\r");
    if(EFI_ERROR(Status)){
        return Status;
    }

    Status = ST->ConIn->Reset(ST->ConIn, FALSE);
    if(EFI_ERROR(Status)){
        return Status;
    }

    while((Status = ST->ConIn->ReadKeyStroke(ST->ConIn, &Key)) == EFI_NOT_READY){}

    return Status;
}

This is the Makefile for it:

DIR_OUT     := ..
TARGET      := uefi
OUT         := $(DIR_OUT)/out/boot

DIR_SRC     := src
DIR_BLD     := build

EFI_DIR     := gnu-efi-3.0.8
EFI_LIB     := $(EFI_DIR)/x86_64/gnuefi/ $(EFI_DIR)/x86_64/lib
EFI_INC     := $(EFI_DIR)/inc $(EFI_DIR)/inc/x86_64 $(EFI_DIR)/inc/protocol
EFI_CRT     := $(EFI_DIR)/x86_64/gnuefi/crt0-efi-x86_64.o
EFI_LDS     := $(EFI_DIR)/gnuefi/elf_x86_64_efi.lds

CFILES      := $(wildcard $(DIR_SRC)/*.c)
OFILES      := $(patsubst $(DIR_SRC)/%.c,$(DIR_BLD)/%.o,$(CFILES))

PREFIX      := 
CC          := $(PREFIX)gcc
LD          := $(PREFIX)ld
OBJCPY      := $(PREFIX)objcopy

INCLUDES    := $(addprefix -I,$(EFI_INC))
CFLAGS      := -fno-stack-protector -fpic -fshort-wchar -mno-red-zone -Wall -ffreestanding -DEFI_FUNCTION_WRAPPER -c $(INCLUDES)
LDFLAGS     := -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic $(addprefix -L,$(EFI_LIB)) $(EFI_CRT)

all: builddir bootdir $(OUT)/$(TARGET).efi

.PRECIOUS: $(OFILES)

clean:
    rm -vrf $(OFILES) $(OUT)/$(TARGET).efi

$(OUT)/$(TARGET).efi: $(DIR_BLD)/$(TARGET).efi
    cp $< $@

%.efi: %.so
    $(OBJCPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym  -j .rel -j .rela -j .reloc --target=efi-app-x86_64 $^ $@

$(DIR_BLD)/$(TARGET).so: $(OFILES)
    $(LD) $(LDFLAGS) $< -o $@ -lefi -lgnuefi

$(DIR_BLD)/%.o: $(DIR_SRC)/%.c
    $(CC) $(CFLAGS) $< -o $@

bootdir:
    mkdir -p $(OUT)
builddir:
    mkdir -p $(DIR_BLD)

This is the Makefile that creates the ISO:

ISO_DIR     := ..
ISO_FILE    := uefi.iso
ISO_LABEL   := UEFI

DIR_BLD     := build

MKFSISO     := xorriso -as mkisofs

FATSIZE     := 8M
MKFSVFAT    := /sbin/mkfs.vfat
MOUNT       := sudo mount
UMOUNT      := sudo umount

UID         := $(shell id -u gudenau)
GID         := $(shell id -g gudenau)

all: buildDir $(ISO_DIR)/$(ISO_FILE)

.PRECIOUS: $(ISO_DIR)/$(ISO_FILE) $(DIR_BLD)/efi.img

$(ISO_DIR)/%.iso: $(DIR_BLD)/efi.img
    $(MKFSISO) -o $@ -iso-level 3 -V "$(ISO_LABEL)" $(DIR_BLD)/efi.img -e /efi.img -no-emul-boot

%.img:
    dd if=/dev/zero of=$@ bs=1024 count=1024
    $(MKFSVFAT) $@
    mkdir -p $(DIR_BLD)/image
    $(MOUNT) -o gid=$(GID),uid=$(UID) $@ $(DIR_BLD)/image
    mkdir -p $(DIR_BLD)/image/EFI/BOOT/
    cp ../bootloader/build/uefi.efi $(DIR_BLD)/image/EFI/BOOT/BOOTX64.EFI
    $(UMOUNT) $(DIR_BLD)/image
    rm -vfr $(DIR_BLD)/image

clean:
    rm -vf $(DIR_BLD)/efi.img $(ISO_DIR)/$(ISO_FILE)

buildDir:
    mkdir -p $(DIR_BLD)

I know the Makefiles are really bad at the moment, but I am just trying to get it to work at the moment. I will make them better later.

Edit: After more research I have this Makefile now:

ISO_DIR     := ..
ISO_FILE    := uefi.iso
ISO_LABEL   := UEFI

DIR_BLD     := build

MKFSISO     := xorriso -as mkisofs

FATHEADS    := 32
FATTRACKS   := 32
FATSECTOR   := 512
FATTHING    := 128
FATFORMAT   := mformat

MMD         := mmd
MCOPY       := mcopy

all: buildDir $(ISO_DIR)/$(ISO_FILE)

.PRECIOUS: $(ISO_DIR)/$(ISO_FILE) $(DIR_BLD)/efi.img

$(ISO_DIR)/%.iso: $(DIR_BLD)/efi.img
    $(MKFSISO) -o $@ -iso-level 3 -V "$(ISO_LABEL)" $(DIR_BLD)/efi.img -e /efi.img -no-emul-boot

%.img:
    $(FATFORMAT) -i $@ -F -h $(FATHEADS) -t $(FATTRACKS) -n $(FATTHING) -c 1 -C
    $(MDD) -i $@ ::/EFI
    $(MDD) -i $@ ::/EFI/BOOT
    $(MCOPY) -i $@ ../bootloader/build/uefi.efi ::/EFI/BOOT/BOOTX64.EFI

clean:
    rm -vf $(DIR_BLD)/efi.img $(ISO_DIR)/$(ISO_FILE)

buildDir:
    mkdir -p $(DIR_BLD)

But I can not figure out how to make a GPT image with it, as mkgpt does not seem to exist.

Upvotes: 1

Views: 7058

Answers (1)

Thomas Schmitt
Thomas Schmitt

Reputation: 344

Depending on the (virtual) medium type you need a partition table or an El Torito Boot Catalog which mark an EFI System Partition. Inside that partition must be a FAT filesystem with the start program. The name of this program depends on the CPU Type. E.g. \EFI\BOOT\BOOTX64.EFI for 64 bit Intel/AMD. For 32 bit Intel/AMD it's BOOTIA32.EFI.

So first of all you need to create that FAT filesystem image, with your program having the prescribed name. Let's name the image file "efi.img" and put it into the current working directory. Then you put the FAT image file as data file into the ISO and mark it as EFI El Torito boot image so that EFI will find it on a (virtual) DVD medium.

xorriso -as mkisofs -o uefi.iso -iso-level 3 -V UEFI isoFiles \
./efi.img -e /efi.img -no-emul-boot 

(Note that option -e expects the file address inside the ISO.)

For booting from (virtual) hard disk or USB stick, you'd append the FAT filesystem image as MBR partition of type 0xEF:

xorriso -as mkisofs -o uefi.iso -iso-level 3 -V UEFI isoFiles \
-append_partition 2 0xef ./efi.img

(Note that option -append_partition expects the file address as on local hard disk.)

Both add-ons can be combined at the cost of having two copies of the FAT image in the ISO. xorriso versions >= 1.4.6 can avoid this duplication by a special pseudo-path "--interval:..." with option -e:

xorriso -as mkisofs -o uefi.iso -iso-level 3 -V UEFI isoFiles \
-append_partition 2 0xef ./efi.img \
-e --interval:appended_partition_2:all:: -no-emul-boot

Upvotes: 1

Related Questions