如何在GNU-EFI中从设备路径获取唯一分区GUID?
在GNU-EFI环境下从设备路径提取唯一分区GUID
要获取分区的唯一GUID,核心是识别设备路径中的分区设备路径节点,该节点直接存储了分区的GUID信息。以下是在你原有代码基础上修改后的完整实现,新增了提取并打印分区GUID的功能:
#include <efi.h> #include <efilib.h> // 打印单个设备路径节点 VOID PrintDevicePathNode(EFI_DEVICE_PATH_PROTOCOL* Node) { CHAR16* Text = NULL; Text = DevicePathToStr(Node); if (Text != NULL) { Print(L"%s", Text); FreePool(Text); } } // 打印完整设备路径 VOID PrintDevicePath(EFI_DEVICE_PATH_PROTOCOL* DevicePath) { while (!IsDevicePathEnd(DevicePath)) { PrintDevicePathNode(DevicePath); DevicePath = NextDevicePathNode(DevicePath); if (!IsDevicePathEnd(DevicePath)) { Print(L"\\"); } } Print(L"\n"); } // 从设备路径中提取并打印分区GUID VOID ExtractPartitionGuidFromDevicePath(EFI_DEVICE_PATH_PROTOCOL* DevicePath) { while (!IsDevicePathEnd(DevicePath)) { // 判断当前节点是否为分区设备路径节点 if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH && DevicePathSubType(DevicePath) == MEDIA_PARTITION_DP) { PARTITION_DEVICE_PATH* PartitionNode = (PARTITION_DEVICE_PATH*)DevicePath; EFI_GUID* PartitionGuid = &PartitionNode->PartitionGuid; // 按标准GUID格式输出:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Print(L" Partition GUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", PartitionGuid->Data1, PartitionGuid->Data2, PartitionGuid->Data3, PartitionGuid->Data4[0], PartitionGuid->Data4[1], PartitionGuid->Data4[2], PartitionGuid->Data4[3], PartitionGuid->Data4[4], PartitionGuid->Data4[5], PartitionGuid->Data4[6], PartitionGuid->Data4[7]); return; // 找到第一个分区节点后返回,若需处理多分区可调整逻辑 } DevicePath = NextDevicePathNode(DevicePath); } Print(L" No partition GUID found in device path\n"); } EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { InitializeLib(ImageHandle, SystemTable); EFI_STATUS Status; EFI_INPUT_KEY Key; EFI_BOOT_SERVICES* BS = SystemTable->BootServices; EFI_HANDLE* handles; UINTN HandleCount; Status = uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &handles); if (EFI_ERROR(Status)) { Print(L"Error locating handles with Block I/O Protocol: %r\n", Status); return Status; } Print(L"Number of handles with Block I/O Protocol: %d\n", HandleCount); for (UINTN i = 0; i < HandleCount; i++) { EFI_BLOCK_IO_PROTOCOL* blockIo; Status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &gEfiBlockIoProtocolGuid, (VOID**)&blockIo); if (EFI_ERROR(Status)) { Print(L"Error getting Block I/O Protocol from handle %d: %r\n", i, Status); continue; } EFI_BLOCK_IO_MEDIA* media = blockIo->Media; Print(L"Block Device %d\n", i); Print(L" Media ID: %lx\n", media->MediaId); Print(L" Block Size: %d\n", media->BlockSize); Print(L" Device Size: %ld MB\n", (media->LastBlock + 1) * media->BlockSize / (1024 * 1024)); EFI_DEVICE_PATH_PROTOCOL* devicePath; Status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &gEfiDevicePathProtocolGuid, (VOID**)&devicePath); if (!EFI_ERROR(Status)) { Print(L" Device Path:\n"); PrintDevicePath(devicePath); // 调用提取GUID的函数 ExtractPartitionGuidFromDevicePath(devicePath); } } 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; }
关键逻辑说明
- 识别分区节点:通过
DevicePathType和DevicePathSubType判断当前节点是否为MEDIA_PARTITION_DP类型(即分区专属的设备路径节点)。 - 提取GUID数据:将目标节点强制转换为
PARTITION_DEVICE_PATH结构体,其PartitionGuid字段就是分区的唯一标识。 - 格式化输出:拆分GUID的各个字节段,按照标准GUID字符串格式打印,保证输出的可读性。
内容的提问来源于stack exchange,提问作者CherryDev86
相关产品推荐
相关产品推荐

