diff --git a/include/storage.h b/include/storage.h old mode 100755 new mode 100644 index f633261a..7ee5e257 --- a/include/storage.h +++ b/include/storage.h @@ -93,5 +93,6 @@ BOOLEAN is_boot_device_virtual(void); EFI_STATUS set_logical_unit(UINT64 user_lun, UINT64 factory_lun); void print_progress(EFI_LBA done, EFI_LBA total, uint32_t sec, uint32_t *prev_sec, uint32_t *prev); void set_exclude_device(EFI_HANDLE device); +EFI_DEVICE_PATH *get_exclude_device(void); #endif /* _STORAGE_H_ */ diff --git a/libkernelflinger/gpt.c b/libkernelflinger/gpt.c index 2d18f0b8..06d70205 100644 --- a/libkernelflinger/gpt.c +++ b/libkernelflinger/gpt.c @@ -39,6 +39,7 @@ #include "gpt.h" #include "gpt_bin.h" #include "storage.h" +#include "pci.h" #define PROTECTIVE_MBR 0xEE @@ -437,6 +438,84 @@ static void copy_part(struct gpt_partition *in, struct gpt_partition *out) sizeof(out->name) - PREFIX_LEN * sizeof(CHAR16)); } +EFI_STATUS get_dedicated_disk(struct gpt_partition_interface *gpart) +{ + EFI_STATUS ret; + EFI_HANDLE *handles; + UINTN nb_handle = 0; + PCI_DEVICE_PATH *boot_device; + PCI_DEVICE_PATH *exclude_device; + EFI_DEVICE_PATH *device; + PCI_DEVICE_PATH *pci; + EFI_BLOCK_IO *bio; + UINTN i; + EFI_HANDLE boot_handle = get_boot_device_handle(); + EFI_DEVICE_PATH *exclude_device_path = get_exclude_device(); + + device = DevicePathFromHandle(boot_handle); + if (!device) + return EFI_NOT_FOUND; + + boot_device = get_pci_device_path(device); + if (boot_device == NULL) + return EFI_NOT_FOUND; + + if(exclude_device_path != NULL) { + exclude_device = get_pci_device_path(exclude_device_path); + if (exclude_device == NULL) + return EFI_NOT_FOUND; + } + else + exclude_device = NULL; + + ret = uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, + &BlockIoProtocol, NULL, &nb_handle, &handles); + if (EFI_ERROR(ret)) + return EFI_NOT_FOUND; + + gpart->bio = NULL; + gpart->handle = 0; + memset(&gpart->part, 0, sizeof(gpart->part)); + for (i = 0; i < nb_handle; i++) { + device = DevicePathFromHandle(handles[i]); + if (device == NULL) + continue; + + pci = get_pci_device_path(device); + if (pci == NULL) + continue; + + if (boot_device->Function == pci->Function && + boot_device->Device == pci->Device) + continue; + + if (exclude_device != NULL && exclude_device->Function == pci->Function && + exclude_device->Device == pci->Device) + continue; + + ret = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &BlockIoProtocol, (VOID *)&bio); + if (EFI_ERROR(ret)) + continue; + + ret = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &DiskIoProtocol, (VOID *)&gpart->dio); + if (EFI_ERROR(ret)) + continue; + + gpart->handle = handles[i]; + gpart->bio = bio; + gpart->part.starting_lba = 0; + gpart->part.ending_lba = bio->Media->LastBlock; + break; + } + FreePool(handles); + + if (gpart->handle == 0) + return EFI_NOT_FOUND; + + debug(L"dedicated data parition blocks: 0x%X", gpart->part.ending_lba + 1); + return EFI_SUCCESS; +} + EFI_STATUS gpt_get_partition_by_label(const CHAR16 *label, struct gpt_partition_interface *gpart, logical_unit_t log_unit) @@ -447,6 +526,17 @@ EFI_STATUS gpt_get_partition_by_label(const CHAR16 *label, if (!label || !gpart) return EFI_INVALID_PARAMETER; + /* if dynamic partition enabled, data partition's name is "userdata"; + * if dynamic partition disabled, data partition's name is "data" + */ + if (!StrCmp(label, L"userdata") || !StrCmp(label, L"data")) { + ret = get_dedicated_disk(gpart); + if (ret == EFI_SUCCESS) { + CopyMem(gpart->part.name, label, sizeof(gpart->part.name)); + return EFI_SUCCESS; + } + } + ret = gpt_cache_partition(log_unit); if (EFI_ERROR(ret)) return ret; diff --git a/libkernelflinger/storage.c b/libkernelflinger/storage.c index 800d2f01..8776c8d8 100644 --- a/libkernelflinger/storage.c +++ b/libkernelflinger/storage.c @@ -621,3 +621,9 @@ void set_exclude_device(EFI_HANDLE device) warning(L"Exclude device from installation: %s", dps); FreePool(dps); } + +EFI_DEVICE_PATH *get_exclude_device(void) +{ + return exclude_device; +} +