大多数 UEFI 协议被报告为 "unsupported"
Most UEFI protocols are reported as "unsupported"
我正在 SoC 设备(Up Board)上编写 EFI 可执行文件,以帮助我们自动执行 BIOS 更新和 PXE 启动,以便在众多设备上安装我们的软件。
我遇到的问题是,似乎规范中的大多数协议都在这个平台上 "unsupported",甚至是基本的文件系统任务。我唯一成功使用的是 LOADED_IMAGE_PROTOCOL。我正在使用 gnu-efi 编译代码,将我的代码基于此示例 https://mjg59.dreamwidth.org/18773.html。是我做错了什么,还是固件完全没有实现任何协议?
American Megatrends 实用程序 "AfuEfix64.efi" 能够检索 BIOS 信息,SoC BIOS 更新是使用 Intel 的 EFI 可执行文件完成的。不幸的是,两者都是封闭源代码。我最初的想法是编写一个脚本来解析这些可执行文件的输出,但我认为 EFI shell 对此类任务没有太多功能,因此我继续编写 EFI 可执行文件以执行此操作。
显示此内容的最少代码:
#include <efi.h>
#include <efilib.h>
#include <x86_64/efibind.h>
// gnu-efi does not currently define firmware management
// https://raw.githubusercontent.com/tianocore/edk2/master/MdePkg/Include/Protocol/FirmwareManagement.h
#include "efifirmware.h"
// gnu-efi does not currently define this
#define EFI_LOAD_FILE2_PROTOCOL_GUID \
{ 0x4006c0c1, 0xfcb3, 0x403e, \
{ 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d }}
typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE2_PROTOCOL;
void tryProtocol(EFI_GUID proto_guid, void** out, const CHAR16* name,
EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
EFI_STATUS status;
status = uefi_call_wrapper(systemTable->BootServices->HandleProtocol, 3,
imageHandle, &proto_guid, out);
if (EFI_ERROR(status)) {
Print(L"HandleProtocol error for %s: %r\n", name, status);
} else {
Print(L"Protocol %s is supported\n", name);
}
}
void tryProtocols(EFI_HANDLE imgh, EFI_SYSTEM_TABLE* syst) {
EFI_LOADED_IMAGE* loaded_image = NULL;
EFI_GUID guid_imgprot = LOADED_IMAGE_PROTOCOL;
tryProtocol(guid_imgprot, (void**)&loaded_image,
L"LOADED_IMAGE_PROTOCOL", imgh, syst);
Print(L"Image base: %lx\n", loaded_image->ImageBase);
Print(L"Image size: %lx\n", loaded_image->ImageSize);
Print(L"Image file: %s\n", DevicePathToStr(loaded_image->FilePath));
EFI_FIRMWARE_MANAGEMENT_PROTOCOL* fw_manage = NULL;
EFI_GUID guid_fwman_prot = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
tryProtocol(guid_fwman_prot, (void**)&fw_manage,
L"FIRMWARE_MANAGEMENT_PROTOCOL", imgh, syst);
EFI_LOAD_FILE_PROTOCOL* load_file = NULL;
EFI_GUID guid_loadf_prot = EFI_LOAD_FILE_PROTOCOL_GUID;
tryProtocol(guid_loadf_prot, (void**)&load_file,
L"LOAD_FILE_PROTOCOL", imgh, syst);
EFI_LOAD_FILE2_PROTOCOL* load_file2 = NULL;
EFI_GUID guid_loadf2_prot = EFI_LOAD_FILE2_PROTOCOL_GUID;
tryProtocol(guid_loadf2_prot, (void**)&load_file2,
L"LOAD_FILE2_PROTOCOL", imgh, syst);
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* simple_fs = NULL;
EFI_GUID guid_simple_fs_prot = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
tryProtocol(guid_simple_fs_prot, (void**)&simple_fs,
L"SIMPLE_FILE_SYSTEM_PROTOCOL", imgh, syst);
EFI_DISK_IO_PROTOCOL* disk = NULL;
EFI_GUID guid_disk_io_prot = EFI_DISK_IO_PROTOCOL_GUID;
tryProtocol(guid_disk_io_prot, (void**)&disk,
L"DISK_IO_PROTOCOL", imgh, syst);
EFI_BLOCK_IO_PROTOCOL* block = NULL;
EFI_GUID guid_block_io_prot = EFI_BLOCK_IO_PROTOCOL_GUID;
tryProtocol(guid_block_io_prot, (void**)&block,
L"BLOCK_IO_PROTOCOL", imgh, syst);
}
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
InitializeLib(imageHandle, systemTable);
Print(L"Image loaded\n");
tryProtocols(imageHandle, systemTable);
return EFI_SUCCESS;
}
这是 运行 它的输出:
EFI Shell version 2.40 [5.11]
Current running mode 1.1.2
Device mapping table
fs0 :HardDisk - Alias hd6b blk0
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(1,GPT,2DCDDADD-8F3A-4A77-94A9-010A8C700BB8,0x800,0x100000)
fs1 :Removable HardDisk - Alias hd9g0a0b blk1
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)/HD(1,MBR,0x528E6A1F,0x800,0x1CDE800)
blk0 :HardDisk - Alias hd6b fs0
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(1,GPT,2DCDDADD-8F3A-4A77-94A9-010A8C700BB8,0x800,0x100000)
blk1 :Removable HardDisk - Alias hd9g0a0b fs1
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)/HD(1,MBR,0x528E6A1F,0x800,0x1CDE800)
blk2 :HardDisk - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(2,GPT,8AC0F94E-3CA2-4C03-BE00-3A69721CC391,0x100800,0x1C1F7DF)
blk3 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)
blk4 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x1)
blk5 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x2)
blk6 :Removable BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)
Press ESC in 4 seconds to skip startup.nsh, any other key to continue.
fs1:\> tryprotocols.efi
Image loaded
Protocol LOADED_IMAGE_PROTOCOL is supported
Image base: 55BA6000
Image size: F000
Image file: \/tryprotocols.efi
HandleProtocol error for FIRMWARE_MANAGEMENT_PROTOCOL: Unsupported
HandleProtocol error for LOAD_FILE_PROTOCOL: Unsupported
HandleProtocol error for LOAD_FILE2_PROTOCOL: Unsupported
HandleProtocol error for SIMPLE_FILE_SYSTEM_PROTOCOL: Unsupported
HandleProtocol error for DISK_IO_PROTOCOL: Unsupported
HandleProtocol error for BLOCK_IO_PROTOCOL: Unsupported
fs1:\>
这是我用来编译它的 Makefile:
ARCH=x86_64
OBJS=tryprotocols.o
TARGET=tryprotocols.efi
TARGET_SO=$(TARGET:.efi=.so)
GNUEFIDIR=/home/gekko/gnu-efi-3.0.8
EFIINC=$(GNUEFIDIR)/inc
EFIINCS=-I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
LIB=$(GNUEFIDIR)/$(ARCH)/lib
EFILIB=$(GNUEFIDIR)/gnuefi
EFI_CRT_OBJS=$(GNUEFIDIR)/$(ARCH)/gnuefi/crt0-efi-$(ARCH).o
EFI_LDS=$(EFILIB)/elf_$(ARCH)_efi.lds
CFLAGS=$(EFIINCS) -fno-stack-protector -fpic \
-fshort-wchar -mno-red-zone -Wall
ifeq ($(ARCH),x86_64)
CFLAGS += -DEFI_FUNCTION_WRAPPER
endif
LDFLAGS=-nostdlib -znocombreloc -T $(EFI_LDS) -shared \
-Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)
all: $(TARGET)
$(TARGET_SO): $(OBJS)
ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi
%.efi: %.so
objcopy -j .text -j .sdata -j .data -j .dynamic \
-j .dynsym -j .rel -j .rela -j .reloc \
--target=efi-app-$(ARCH) $^ $@
clean:
rm -f *.o
rm -f $(TARGET)
rm -f $(TARGET_SO)
编辑:正确使用 LocateProtocol() 查找协议并使用它们打开和关闭文件的修改版本。
#include <efi.h>
#include <efilib.h>
#include <x86_64/efibind.h>
BOOLEAN tryProtocol(EFI_GUID proto_guid, void** out, const CHAR16* name,
EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
*out = NULL;
EFI_STATUS status;
EFI_HANDLE interface = NULL;
status = uefi_call_wrapper(systemTable->BootServices->LocateProtocol, 3,
&proto_guid, NULL, &interface);
if (EFI_ERROR(status)) {
Print(L"LocateProtocol error for %s: %r\n", name, status);
return FALSE;
}
Print(L"Locate protocol address: %s, %x\n", name, interface);
*out = interface;
return TRUE;
}
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
InitializeLib(imageHandle, systemTable);
Print(L"Image loaded\n");
EFI_LOADED_IMAGE* loaded_image = NULL;
EFI_GUID guid_imgprot = LOADED_IMAGE_PROTOCOL;
if (tryProtocol(guid_imgprot, (void**)&loaded_image,
L"LOADED_IMAGE_PROTOCOL", imageHandle, systemTable) != TRUE) {
Print(L"Missing required protocol. Aborting\n");
return EFI_SUCCESS;
}
Print(L"Image base: %lx\n", loaded_image->ImageBase);
Print(L"Image size: %lx\n", loaded_image->ImageSize);
Print(L"Image file: %s\n", DevicePathToStr(loaded_image->FilePath));
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* simple_fs = NULL;
EFI_GUID guid_simple_fs_prot = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
if (tryProtocol(guid_simple_fs_prot, (void**)&simple_fs,
L"EFI_SIMPLE_FILE_SYSTEM_PROTOCOL", imageHandle, systemTable) != TRUE) {
Print(L"Missing required protocol. Aborting\n");
return EFI_SUCCESS;
}
EFI_FILE_PROTOCOL* vol_proto = NULL;
EFI_STATUS status;
Print(L"dereffing\n");
Print(L"address of OpenVolume: %x\n", simple_fs->OpenVolume);
status = uefi_call_wrapper(simple_fs->OpenVolume, 2, simple_fs, &vol_proto);
if (EFI_ERROR(status)) {
Print(L"Error opening volume: %r\n", status);
return EFI_SUCCESS;
}
Print(L"SIMPLE_FILE_SYSTEM volume opened\n");
EFI_FILE_PROTOCOL* f;
CHAR16 fname[10] = L"foo.txt[=14=]";
UINT64 openmode = EFI_FILE_MODE_READ;
UINT64 attr = 0;
status = uefi_call_wrapper(vol_proto->Open, 5, vol_proto, &f, fname, openmode, attr);
if (EFI_ERROR(status)) {
Print(L"Error opening file: %r\n", status);
return EFI_SUCCESS;
}
Print(L"opened file %s\n", fname);
// Spec says can only return EFI_SUCCESS
status = uefi_call_wrapper(vol_proto->Close, 1, f);
Print(L"Closed file\n");
return EFI_SUCCESS;
}
UEFI 规范并未静态定义访问特定协议的位置和方式,而是需要在运行时发现的内容。虽然有点费力,但它使得编写 applications/drivers 可移植到完全符合规范的完全不同的 UEFI 实现成为可能。
因此,在使用 HandleProtocol() 之前,您需要在您打算使用的每个协议上找到 LocateProtocol()。
你逃脱了 LOADED_IMAGE_PROTOCOL 因为那个是用你的 ImageHandle 初始化的,引用当前正在执行的图像(你的程序)的实例。
这在 Matthew 的 post 部分 下进行了介绍,该部分介绍了如何使用附加到图像句柄的协议。附加到其他句柄的协议怎么样?。
我正在 SoC 设备(Up Board)上编写 EFI 可执行文件,以帮助我们自动执行 BIOS 更新和 PXE 启动,以便在众多设备上安装我们的软件。
我遇到的问题是,似乎规范中的大多数协议都在这个平台上 "unsupported",甚至是基本的文件系统任务。我唯一成功使用的是 LOADED_IMAGE_PROTOCOL。我正在使用 gnu-efi 编译代码,将我的代码基于此示例 https://mjg59.dreamwidth.org/18773.html。是我做错了什么,还是固件完全没有实现任何协议?
American Megatrends 实用程序 "AfuEfix64.efi" 能够检索 BIOS 信息,SoC BIOS 更新是使用 Intel 的 EFI 可执行文件完成的。不幸的是,两者都是封闭源代码。我最初的想法是编写一个脚本来解析这些可执行文件的输出,但我认为 EFI shell 对此类任务没有太多功能,因此我继续编写 EFI 可执行文件以执行此操作。
显示此内容的最少代码:
#include <efi.h>
#include <efilib.h>
#include <x86_64/efibind.h>
// gnu-efi does not currently define firmware management
// https://raw.githubusercontent.com/tianocore/edk2/master/MdePkg/Include/Protocol/FirmwareManagement.h
#include "efifirmware.h"
// gnu-efi does not currently define this
#define EFI_LOAD_FILE2_PROTOCOL_GUID \
{ 0x4006c0c1, 0xfcb3, 0x403e, \
{ 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d }}
typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE2_PROTOCOL;
void tryProtocol(EFI_GUID proto_guid, void** out, const CHAR16* name,
EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
EFI_STATUS status;
status = uefi_call_wrapper(systemTable->BootServices->HandleProtocol, 3,
imageHandle, &proto_guid, out);
if (EFI_ERROR(status)) {
Print(L"HandleProtocol error for %s: %r\n", name, status);
} else {
Print(L"Protocol %s is supported\n", name);
}
}
void tryProtocols(EFI_HANDLE imgh, EFI_SYSTEM_TABLE* syst) {
EFI_LOADED_IMAGE* loaded_image = NULL;
EFI_GUID guid_imgprot = LOADED_IMAGE_PROTOCOL;
tryProtocol(guid_imgprot, (void**)&loaded_image,
L"LOADED_IMAGE_PROTOCOL", imgh, syst);
Print(L"Image base: %lx\n", loaded_image->ImageBase);
Print(L"Image size: %lx\n", loaded_image->ImageSize);
Print(L"Image file: %s\n", DevicePathToStr(loaded_image->FilePath));
EFI_FIRMWARE_MANAGEMENT_PROTOCOL* fw_manage = NULL;
EFI_GUID guid_fwman_prot = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
tryProtocol(guid_fwman_prot, (void**)&fw_manage,
L"FIRMWARE_MANAGEMENT_PROTOCOL", imgh, syst);
EFI_LOAD_FILE_PROTOCOL* load_file = NULL;
EFI_GUID guid_loadf_prot = EFI_LOAD_FILE_PROTOCOL_GUID;
tryProtocol(guid_loadf_prot, (void**)&load_file,
L"LOAD_FILE_PROTOCOL", imgh, syst);
EFI_LOAD_FILE2_PROTOCOL* load_file2 = NULL;
EFI_GUID guid_loadf2_prot = EFI_LOAD_FILE2_PROTOCOL_GUID;
tryProtocol(guid_loadf2_prot, (void**)&load_file2,
L"LOAD_FILE2_PROTOCOL", imgh, syst);
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* simple_fs = NULL;
EFI_GUID guid_simple_fs_prot = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
tryProtocol(guid_simple_fs_prot, (void**)&simple_fs,
L"SIMPLE_FILE_SYSTEM_PROTOCOL", imgh, syst);
EFI_DISK_IO_PROTOCOL* disk = NULL;
EFI_GUID guid_disk_io_prot = EFI_DISK_IO_PROTOCOL_GUID;
tryProtocol(guid_disk_io_prot, (void**)&disk,
L"DISK_IO_PROTOCOL", imgh, syst);
EFI_BLOCK_IO_PROTOCOL* block = NULL;
EFI_GUID guid_block_io_prot = EFI_BLOCK_IO_PROTOCOL_GUID;
tryProtocol(guid_block_io_prot, (void**)&block,
L"BLOCK_IO_PROTOCOL", imgh, syst);
}
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
InitializeLib(imageHandle, systemTable);
Print(L"Image loaded\n");
tryProtocols(imageHandle, systemTable);
return EFI_SUCCESS;
}
这是 运行 它的输出:
EFI Shell version 2.40 [5.11]
Current running mode 1.1.2
Device mapping table
fs0 :HardDisk - Alias hd6b blk0
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(1,GPT,2DCDDADD-8F3A-4A77-94A9-010A8C700BB8,0x800,0x100000)
fs1 :Removable HardDisk - Alias hd9g0a0b blk1
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)/HD(1,MBR,0x528E6A1F,0x800,0x1CDE800)
blk0 :HardDisk - Alias hd6b fs0
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(1,GPT,2DCDDADD-8F3A-4A77-94A9-010A8C700BB8,0x800,0x100000)
blk1 :Removable HardDisk - Alias hd9g0a0b fs1
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)/HD(1,MBR,0x528E6A1F,0x800,0x1CDE800)
blk2 :HardDisk - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(2,GPT,8AC0F94E-3CA2-4C03-BE00-3A69721CC391,0x100800,0x1C1F7DF)
blk3 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)
blk4 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x1)
blk5 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x2)
blk6 :Removable BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)
Press ESC in 4 seconds to skip startup.nsh, any other key to continue.
fs1:\> tryprotocols.efi
Image loaded
Protocol LOADED_IMAGE_PROTOCOL is supported
Image base: 55BA6000
Image size: F000
Image file: \/tryprotocols.efi
HandleProtocol error for FIRMWARE_MANAGEMENT_PROTOCOL: Unsupported
HandleProtocol error for LOAD_FILE_PROTOCOL: Unsupported
HandleProtocol error for LOAD_FILE2_PROTOCOL: Unsupported
HandleProtocol error for SIMPLE_FILE_SYSTEM_PROTOCOL: Unsupported
HandleProtocol error for DISK_IO_PROTOCOL: Unsupported
HandleProtocol error for BLOCK_IO_PROTOCOL: Unsupported
fs1:\>
这是我用来编译它的 Makefile:
ARCH=x86_64
OBJS=tryprotocols.o
TARGET=tryprotocols.efi
TARGET_SO=$(TARGET:.efi=.so)
GNUEFIDIR=/home/gekko/gnu-efi-3.0.8
EFIINC=$(GNUEFIDIR)/inc
EFIINCS=-I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
LIB=$(GNUEFIDIR)/$(ARCH)/lib
EFILIB=$(GNUEFIDIR)/gnuefi
EFI_CRT_OBJS=$(GNUEFIDIR)/$(ARCH)/gnuefi/crt0-efi-$(ARCH).o
EFI_LDS=$(EFILIB)/elf_$(ARCH)_efi.lds
CFLAGS=$(EFIINCS) -fno-stack-protector -fpic \
-fshort-wchar -mno-red-zone -Wall
ifeq ($(ARCH),x86_64)
CFLAGS += -DEFI_FUNCTION_WRAPPER
endif
LDFLAGS=-nostdlib -znocombreloc -T $(EFI_LDS) -shared \
-Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)
all: $(TARGET)
$(TARGET_SO): $(OBJS)
ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi
%.efi: %.so
objcopy -j .text -j .sdata -j .data -j .dynamic \
-j .dynsym -j .rel -j .rela -j .reloc \
--target=efi-app-$(ARCH) $^ $@
clean:
rm -f *.o
rm -f $(TARGET)
rm -f $(TARGET_SO)
编辑:正确使用 LocateProtocol() 查找协议并使用它们打开和关闭文件的修改版本。
#include <efi.h>
#include <efilib.h>
#include <x86_64/efibind.h>
BOOLEAN tryProtocol(EFI_GUID proto_guid, void** out, const CHAR16* name,
EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
*out = NULL;
EFI_STATUS status;
EFI_HANDLE interface = NULL;
status = uefi_call_wrapper(systemTable->BootServices->LocateProtocol, 3,
&proto_guid, NULL, &interface);
if (EFI_ERROR(status)) {
Print(L"LocateProtocol error for %s: %r\n", name, status);
return FALSE;
}
Print(L"Locate protocol address: %s, %x\n", name, interface);
*out = interface;
return TRUE;
}
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
InitializeLib(imageHandle, systemTable);
Print(L"Image loaded\n");
EFI_LOADED_IMAGE* loaded_image = NULL;
EFI_GUID guid_imgprot = LOADED_IMAGE_PROTOCOL;
if (tryProtocol(guid_imgprot, (void**)&loaded_image,
L"LOADED_IMAGE_PROTOCOL", imageHandle, systemTable) != TRUE) {
Print(L"Missing required protocol. Aborting\n");
return EFI_SUCCESS;
}
Print(L"Image base: %lx\n", loaded_image->ImageBase);
Print(L"Image size: %lx\n", loaded_image->ImageSize);
Print(L"Image file: %s\n", DevicePathToStr(loaded_image->FilePath));
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* simple_fs = NULL;
EFI_GUID guid_simple_fs_prot = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
if (tryProtocol(guid_simple_fs_prot, (void**)&simple_fs,
L"EFI_SIMPLE_FILE_SYSTEM_PROTOCOL", imageHandle, systemTable) != TRUE) {
Print(L"Missing required protocol. Aborting\n");
return EFI_SUCCESS;
}
EFI_FILE_PROTOCOL* vol_proto = NULL;
EFI_STATUS status;
Print(L"dereffing\n");
Print(L"address of OpenVolume: %x\n", simple_fs->OpenVolume);
status = uefi_call_wrapper(simple_fs->OpenVolume, 2, simple_fs, &vol_proto);
if (EFI_ERROR(status)) {
Print(L"Error opening volume: %r\n", status);
return EFI_SUCCESS;
}
Print(L"SIMPLE_FILE_SYSTEM volume opened\n");
EFI_FILE_PROTOCOL* f;
CHAR16 fname[10] = L"foo.txt[=14=]";
UINT64 openmode = EFI_FILE_MODE_READ;
UINT64 attr = 0;
status = uefi_call_wrapper(vol_proto->Open, 5, vol_proto, &f, fname, openmode, attr);
if (EFI_ERROR(status)) {
Print(L"Error opening file: %r\n", status);
return EFI_SUCCESS;
}
Print(L"opened file %s\n", fname);
// Spec says can only return EFI_SUCCESS
status = uefi_call_wrapper(vol_proto->Close, 1, f);
Print(L"Closed file\n");
return EFI_SUCCESS;
}
UEFI 规范并未静态定义访问特定协议的位置和方式,而是需要在运行时发现的内容。虽然有点费力,但它使得编写 applications/drivers 可移植到完全符合规范的完全不同的 UEFI 实现成为可能。
因此,在使用 HandleProtocol() 之前,您需要在您打算使用的每个协议上找到 LocateProtocol()。 你逃脱了 LOADED_IMAGE_PROTOCOL 因为那个是用你的 ImageHandle 初始化的,引用当前正在执行的图像(你的程序)的实例。
这在 Matthew 的 post 部分 下进行了介绍,该部分介绍了如何使用附加到图像句柄的协议。附加到其他句柄的协议怎么样?。