如何从 gnu-efi 中的设备路径获取唯一的分区 GUID?

问题描述 投票:0回答:1

如何从 GNU-EFI 中的设备路径获取唯一的分区 GUID?我已经获得了设备路径,并且还能够将其转换为文本形式。

我尝试从BLOCK I/O协议获取设备路径,打印出Block I/O句柄的数量并将其转换为设备路径,然后将其转换为文本并打印出来。

#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;
}
c gnu uefi gnu-efi
1个回答
0
投票

您可以使用 SignatureType == 0x02 搜索 HARDDDRIVE_DEVICE_PATH 节点。 分区/磁盘签名存储在该结构中。

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.