Создайте загрузочный ISO-образ UEFI

Я пытаюсь создать загрузочный ISO-образ UEFI, но Hyper-V не видит его как допустимую файловую систему UEFI. Что я делаю не так?

Создание ISO:

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

isoFiles содержит единственный файл boot/hello.efi. При монтировании или открытии в диспетчере архивов файл существует.

Вывод Hyper-V: Снимок экрана Hyper-V

Редактировать: Давайте иметь гораздо больше контекста для этого, не так ли?

Это код EFI, он использует 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;
}

Это Makefile для него:

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)

Это Makefile, который создает 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)

Я знаю, что Makefiles действительно плохи в данный момент, но я просто пытаюсь заставить его работать в данный момент. Я сделаю их лучше позже.

Изменить: после дополнительных исследований у меня есть этот Makefile:

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)

Но не могу сообразить, как сделать с ним образ GPT, так как mkgpt вроде не существует.


person gudenau    schedule 08.06.2018    source источник
comment
В GNU/Linux вы можете использовать gdisk для свежесозданного файла образа, чтобы создать GPT с разделом типа ef00. Затем используйте lossup со смещением байтов -o, соответствующим началу раздела, чтобы создать устройство цикла, в котором вы создаете и заполняете файловую систему FAT. Затем отправьте образ на виртуальную машину как на жесткий диск.   -  person Thomas Schmitt    schedule 12.06.2018


Ответы (1)


В зависимости от типа (виртуального) носителя вам понадобится таблица разделов или загрузочный каталог El Torito, которые помечают системный раздел EFI. Внутри этого раздела должна быть файловая система FAT с программой запуска. Название этой программы зависит от типа процессора. Например. \EFI\BOOT\BOOTX64.EFI для 64-разрядной версии Intel/AMD. Для 32-разрядной версии Intel/AMD это BOOTIA32.EFI.

Итак, прежде всего вам нужно создать этот образ файловой системы FAT с вашей программой, имеющей заданное имя. Назовем файл изображения «efi.img» и поместим его в текущий рабочий каталог. Затем вы помещаете файл образа FAT в качестве файла данных в ISO и помечаете его как загрузочный образ EFI El Torito, чтобы EFI нашла его на (виртуальном) носителе DVD.

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

(Обратите внимание, что опция -e предполагает адрес файла внутри ISO.)

Для загрузки с (виртуального) жесткого диска или USB-накопителя вы должны добавить образ файловой системы FAT в качестве раздела MBR типа 0xEF:

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

(Обратите внимание, что опция -append_partition предполагает адрес файла как на локальном жестком диске.)

Оба дополнения можно комбинировать за счет наличия двух копий образа FAT в ISO. Версии xorriso >= 1.4.6 могут избежать этого дублирования с помощью специального псевдо-пути "--interval:..." с опцией -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
person Thomas Schmitt    schedule 08.06.2018
comment
Я создал образ, содержащий EFI/BOOT/BOOTX64.IMG, отформатированный с помощью mkfs.vfat и созданный с помощью dd if=/dev/zero of=efi.img bs=1024 count=1024. Hyper-V по-прежнему не работает с ISO-образом, созданным с помощью xorriso, в качестве допустимой UEFI FS. - person gudenau; 11.06.2018
comment
Могу поспорить, что ему не нравится ваш FAT-образ или он не интерпретирует El Torito, хотя говорит о DVD. Я вижу довольно похожую процедуру, чем ваша, на wiki.osdev.org/UEFI_Bare_Bones#Creating_the_FAT_image. с OVMF в качестве прошивки, которая, как известно, весьма толерантна. - person Thomas Schmitt; 12.06.2018