You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过代码将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 .inf file declares a dependency on gEfiBootManagerProtocolGuid so 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

  1. Create a directory structure matching UEFI's requirements:
    efi_boot/
    └── EFI
        └── BOOT
            └── BOOTX64.EFI  # Rename your Hello World app to this
    
  2. Run this command to generate the ISO:
    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/
    
    This ISO will be recognized as bootable by any UEFI-compatible system.

Method 2: Create a bootable USB/raw disk image

  1. Create a blank image file:
    dd if=/dev/zero of=hello_usb.img bs=1M count=64
    
  2. Partition it with GPT, marking the partition as an EFI System Partition (type code EF00). Use tools like fdisk or gdisk for this.
  3. Format the partition as FAT32:
    mkfs.vfat -F 32 hello_usb.img1  # Adjust the partition number as needed
    
  4. Mount the partition, copy your app to EFI/BOOT/BOOTX64.EFI, then unmount. The image can now be written to a USB drive with dd or 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

  1. Add your EFI app's source code to your EDK2 workspace (e.g., create a new package under OvmfPkg).
  2. Update your DSC file (e.g., OvmfPkg/OvmfPkgX64.dsc) to include your app in the [Components] section so it compiles with the firmware.
  3. Modify the FDF file (e.g., OvmfPkg/OvmfPkgX64.fdf) to place your app's binary in a firmware volume (FV) like FV_MAIN.
  4. 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 PlatformBds module (responsible for firmware boot sequence) to prioritize your app.

Approach 2: Build a firmware with a bundled bootable ESP

  1. Create a bootable ESP image using the method from Section 2.
  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.
  3. 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

火山引擎 最新活动