std::string getCanonicalEfiDevicePath(const CFDataRef& data) { std::string path; // Iterate through the EFI_DEVICE_PATH_PROTOCOL stacked structs. auto bytes = CFDataGetBytePtr((CFDataRef)data); size_t length = CFDataGetLength((CFDataRef)data); size_t search_offset = 0; while ((search_offset + sizeof(EFI_DEVICE_PATH_PROTOCOL)) < length) { auto node = (const EFI_DEVICE_PATH_PROTOCOL*)(bytes + search_offset); if (EfiIsDevicePathEnd(node)) { // End of the EFI device path stacked structs. break; } if (EfiDevicePathNodeLength(node) + search_offset > length) { // Malformed EFI device header. break; } // Only support paths and hard drive partitions. if (EfiDevicePathType(node) == MEDIA_DEVICE_PATH) { if (node->SubType == MEDIA_FILEPATH_DP) { for (int i = 0; i < EfiDevicePathNodeLength(node); i += 2) { // Strip UTF16 characters to UTF8. path += (((char*)(node)) + sizeof(EFI_DEVICE_PATH_PROTOCOL))[i]; } } else if (node->SubType == MEDIA_HARDDRIVE_DP) { // Extract the device UUID to later join with block devices. auto uuid = ((const HARDDRIVE_DEVICE_PATH*)node)->Signature; boost::uuids::uuid hdd_signature = {{ uuid[3], uuid[2], uuid[1], uuid[0], uuid[5], uuid[4], uuid[7], uuid[6], uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15], }}; path += boost::to_upper_copy(boost::uuids::to_string(hdd_signature)); } } search_offset += EfiDevicePathNodeLength(node); } return path; }
// // get partition handle by number // EFI_HANDLE DevPathGetPartitionHandleByNumber(EFI_DEVICE_PATH_PROTOCOL* referencePath, UINT32 number) { UINTN nodeCount = DevPathGetNodeCount(referencePath); if(!nodeCount) return nullptr; UINTN count = 0; EFI_HANDLE* handleArray = nullptr; if(EFI_ERROR(EfiBootServices->LocateHandleBuffer(ByProtocol, &EfiBlockIoProtocolGuid, nullptr, &count, &handleArray))) return nullptr; EFI_HANDLE retValue = nullptr; for(UINTN i = 0; i < count; i ++) { EFI_HANDLE theHandle = handleArray[i]; if(!theHandle) continue; EFI_DEVICE_PATH_PROTOCOL* devicePath = DevPathGetDevicePathProtocol(theHandle); if(!devicePath) continue; if(DevPathGetNodeCount(devicePath) != nodeCount) continue; EFI_DEVICE_PATH_PROTOCOL* pathA = referencePath; EFI_DEVICE_PATH_PROTOCOL* pathB = devicePath; BOOLEAN checkResult = TRUE; for(UINTN i = 0; i < nodeCount && !EfiIsDevicePathEnd(pathA) && !EfiIsDevicePathEnd(pathB); i ++) { if(EfiDevicePathNodeLength(pathA) != EfiDevicePathNodeLength(pathB)) { checkResult = FALSE; break; } #if 0 if(pathA->Type == MESSAGING_DEVICE_PATH && pathA->SubType == MSG_VENDOR_DP && !memcmp(pathA + 1, &EfiDevicePathMessagingSASGuid, sizeof(EFI_GUID))) { SAS_DEVICE_PATH* sasA = _CR(pathA, SAS_DEVICE_PATH, Header); SAS_DEVICE_PATH* sasB = _CR(pathB, SAS_DEVICE_PATH, Header); if(sasA->SasAddress != sasB->SasAddress || sasA->Lun != sasB->Lun || sasA->RelativeTargetPort != sasB->RelativeTargetPort) { checkResult = FALSE; break; } } #endif if(memcmp(pathA, pathB, EfiDevicePathNodeLength(pathA))) { checkResult = FALSE; break; } } if(!checkResult) continue; if(DevPathGetPartitionNumber(devicePath) != number) continue; retValue = theHandle; break; } MmFreePool(handleArray); return retValue; }