如何通过代码将EFI应用设为引导加载程序?免Shell创建可引导EFI镜像
Great questions! Let's break this down step by step for each scenario you asked about:
1. 将EFI应用通过代码设置为引导加载程序
To programmatically set your EFI app as a boot loader, you'll use UEFI's EFI_BOOT_MANAGER_PROTOCOL to manage boot options. Here's a practical code example that adds your app to the boot sequence and sets it as the default:
#include <Uefi.h> #include <Protocol/BootManager.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/UefiLib.h> #include <Library/DevicePathLib.h> EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_STATUS Status; EFI_BOOT_MANAGER_PROTOCOL *BootManager = NULL; EFI_LOAD_OPTION BootOption; UINT16 BootOptionDesc[] = L"Hello World Boot Loader"; EFI_DEVICE_PATH_PROTOCOL *AppDevicePath = NULL; // 1. Locate the Boot Manager Protocol Status = gBS->LocateProtocol(&gEfiBootManagerProtocolGuid, NULL, (VOID**)&BootManager); if (EFI_ERROR(Status)) { Print(L"Failed to locate Boot Manager Protocol: %r\n", Status); return Status; } // 2. Construct the device path to your EFI app (adjust path to match your app's location) // This example assumes the app is at \EFI\Hello\Hello.efi on the same volume as the app itself AppDevicePath = FileDevicePath(ImageHandle, L"\\EFI\\Hello\\Hello.efi"); if (AppDevicePath == NULL) { Print(L"Failed to create device path\n"); return EFI_OUT_OF_RESOURCES; } // 3. Initialize the EFI_LOAD_OPTION structure BootOption.Attributes = LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT; BootOption.FilePathListLength = GetDevicePathSize(AppDevicePath); BootOption.Description = BootOptionDesc; BootOption.FilePath = AppDevicePath; BootOption.OptionalDataSize = 0; BootOption.OptionalData = NULL; // 4. Add the boot option to the system's boot sequence UINT32 BootOptionIndex; Status = BootManager->AddBootOption(&BootOption, &BootOptionIndex); if (EFI_ERROR(Status)) { Print(L"Failed to add boot option: %r\n", Status); FreePool(AppDevicePath); return Status; } // 5. Set the new option as the default boot entry Status = BootManager->SetDefaultBootOption(BootOptionIndex); if (EFI_ERROR(Status)) { Print(L"Failed to set default boot option: %r\n", Status); BootManager->DeleteBootOption(BootOptionIndex); FreePool(AppDevicePath); return Status; } Print(L"Successfully set app as default boot loader!\n"); FreePool(AppDevicePath); return EFI_SUCCESS; }
Important notes:
- Ensure your app's
.inffile declares a dependency ongEfiBootManagerProtocolGuidso the UEFI loader resolves it correctly. - The device path must point to your app's actual location on the EFI System Partition (ESP).
2. 无需进入UEFI Shell创建可引导EFI镜像
The core trick here is following UEFI's default boot path convention: UEFI firmware automatically scans for EFI/BOOT/BOOT<ARCH>.EFI (e.g., BOOTX64.EFI for x86_64 systems) on removable media or ESP partitions. Here are two reliable methods:
Method 1: Create a bootable ISO with xorriso
- Create a directory structure matching UEFI's requirements:
efi_boot/ └── EFI └── BOOT └── BOOTX64.EFI # Rename your Hello World app to this - Run this command to generate the ISO:
This ISO will be recognized as bootable by any UEFI-compatible system.xorriso -as mkisofs -o hello_boot.iso -efi-boot EFI/BOOT/BOOTX64.EFI -no-emul-boot -boot-load-size 4 -boot-info-table efi_boot/
Method 2: Create a bootable USB/raw disk image
- Create a blank image file:
dd if=/dev/zero of=hello_usb.img bs=1M count=64 - Partition it with GPT, marking the partition as an EFI System Partition (type code
EF00). Use tools likefdiskorgdiskfor this. - Format the partition as FAT32:
mkfs.vfat -F 32 hello_usb.img1 # Adjust the partition number as needed - Mount the partition, copy your app to
EFI/BOOT/BOOTX64.EFI, then unmount. The image can now be written to a USB drive withddor loaded directly in a VM.
3. 自行构建固件时创建可引导EFI镜像并设置默认启动项
If you're building your own UEFI firmware (e.g., with EDK2's OVMF), you have two main approaches:
Approach 1: Embed your app directly in the firmware
- Add your EFI app's source code to your EDK2 workspace (e.g., create a new package under
OvmfPkg). - Update your DSC file (e.g.,
OvmfPkg/OvmfPkgX64.dsc) to include your app in the[Components]section so it compiles with the firmware. - Modify the FDF file (e.g.,
OvmfPkg/OvmfPkgX64.fdf) to place your app's binary in a firmware volume (FV) likeFV_MAIN. - Set the default boot option via EDK2's Platform Configuration Database (PCD):
- Add a PCD entry in your DSC file to specify your app's device path or GUID as the default boot entry.
- Alternatively, modify the
PlatformBdsmodule (responsible for firmware boot sequence) to prioritize your app.
Approach 2: Build a firmware with a bundled bootable ESP
- Create a bootable ESP image using the method from Section 2.
- When building OVMF, configure it to load this ESP image as the default storage device. For example, adjust firmware parameters to include the ESP image as part of the firmware's virtual disk.
- When launching the firmware in a VM, attach the ESP image as a virtual disk—the firmware will automatically boot your app from
EFI/BOOT/BOOTX64.EFI.
内容的提问来源于stack exchange,提问作者Andrew Shi




