Reputation: 11
How do I get a Unique Partition GUID from a device path in GNU-EFI? I have acquired the Device Path and also have been able to convert it to a text form.
I have tried to Get the Device Path from the BLOCK I/O Protocol, print out the amount of Block I/O handles and convert it to a device path and then convert it to text and print it out.
#include <efi.h>
#include <efilib.h>
// Function to print a device path node
VOID PrintDevicePathNode(EFI_DEVICE_PATH_PROTOCOL* Node) {
CHAR16* Text = NULL;
Text = DevicePathToStr(Node);
if (Text != NULL) {
Print(L"%s", Text);
FreePool(Text);
}
}
// Function to print the entire device path
VOID PrintDevicePath(EFI_DEVICE_PATH_PROTOCOL* DevicePath) {
while (!IsDevicePathEnd(DevicePath)) {
PrintDevicePathNode(DevicePath);
DevicePath = NextDevicePathNode(DevicePath);
if (!IsDevicePathEnd(DevicePath)) {
Print(L"\\");
}
}
Print(L"\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);
}
}
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;
}
Upvotes: 1
Views: 154
Reputation: 1538
You can search for a HARDDRIVE_DEVICE_PATH node with SignatureType == 0x02. The partition/disk signature is stored in this struct.
EFI_STATUS GetFirstGptSignature(CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath, EFI_GUID* GptSignature) {
CONST HARDDRIVE_DEVICE_PATH* DevicePathMask;
if(!DevicePath || !GptSignature) {
return EFI_INVALID_PARAMETER;
}
while (!IsDevicePathEnd(DevicePath)) {
DevicePathMask = (CONST HARDDRIVE_DEVICE_PATH*)DevicePath;
DevicePath = NextDevicePathNode(DevicePath);
if(DevicePathMask->Header.Type != MEDIA_DEVICE_PATH) {
continue;
}
if(DevicePathMask->Header.SubType != MEDIA_HARDDRIVE_DP) {
continue;
}
// Check if the device path describes a GPT partition or disk
if(DevicePathMask->SignatureType != 2) {
continue;
}
CopyMem(GptSignature, DevicePathMask->Signature, sizeof(EFI_GUID));
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
Upvotes: 1