【问题标题】:Create Bootable UEFI ISO创建可引导 UEFI ISO
【发布时间】:2023-04-08 11:25:01
【问题描述】:

我正在尝试创建一个可引导的 UEFI ISO,但 Hyper-V 不认为它是一个有效的 UEFI 文件系统。我做错了什么?

创建 ISO:

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

isoFiles 有一个文件,boot/hello.efi。在存档管理器中安装或打开时,该文件存在。

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)

这是创建 ISO 的 Makefile:

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)

我知道 Makefile 目前真的很糟糕,但我现在只是想让它工作。以后我会改进的。

编辑: 经过更多研究,我现在有了这个 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 似乎不存在。

【问题讨论】:

  • 在 GNU/Linux 上,您可以在新 dd'ed 映像文件上使用 gdisk 来创建具有“ef00”类型分区的 GPT。然后使用带有字节偏移量的 losttup -o 匹配分区开始来创建一个循环设备,您可以在其中创建和填充 FAT 文件系统。然后将镜像作为硬盘提交给虚拟机。

标签: hyper-v uefi


【解决方案1】:

根据(虚拟)介质类型,您需要一个分区表或 标记 EFI 系统分区的 El Torito 引导目录。 该分区内必须是带有启动程序的 FAT 文件系统。 该程序的名称取决于 CPU 类型。例如。 \EFI\BOOT\BOOTX64.EFI 适用于 64 位英特尔/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 中的文件地址。)

对于从(虚拟)硬盘或 U 盘启动,您需要附加 FAT 文件系统映像为 0xEF 类型的 MBR 分区:

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

(请注意,选项 -append_partition 期望文件地址为 本地硬盘。)

两个附加组件可以组合在一起,但需要拥有两个副本 ISO 中的 FAT 映像。 xorriso 版本 >= 1.4.6 可以避免这种重复 通过带有选项 -e:

的特殊伪路径“--interval:...”
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

【讨论】:

  • 我创建了一个包含EFI/BOOT/BOOTX64.IMG 的图像,该图像使用mkfs.vfat 格式化并使用dd if=/dev/zero of=efi.img bs=1024 count=1024 创建。 Hyper-V 仍然无法使用使用xorriso 创建的 ISO 作为有效的 UEFI FS。
  • 我最好的选择是它不喜欢您的 FAT 映像或不解释 El Torito,尽管它谈到“DVD”。我在wiki.osdev.org/UEFI_Bare_Bones#Creating_the_FAT_image 看到了与您的过程非常相似的过程,但这是使用 OVMF 作为固件,众所周知,它非常宽容。
猜你喜欢
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
  • 2019-04-20
  • 2015-01-01
  • 1970-01-01
  • 2020-01-19
  • 2020-01-24
相关资源
最近更新 更多