EFI_DEVICE_PATH * LibDuplicateDevicePathInstance ( IN EFI_DEVICE_PATH *DevPath ) { EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp; UINTN Size = 0; // // get the size of an instance from the input // Temp = DevPath; DevicePathInst = DevicePathInstance (&Temp, &Size); // // Make a copy and set proper end type // NewDevPath = NULL; if (Size) { NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH)); } if (NewDevPath) { CopyMem (NewDevPath, DevicePathInst, Size); Temp = NextDevicePathNode(NewDevPath); SetDevicePathEndNode(Temp); } return NewDevPath; }
UINTN DevicePathInstanceCount ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) /*++ Routine Description: Function is used to determine the number of device path instances that exist in a device path. Arguments: DevicePath - A pointer to a device path data structure. Returns: This function counts and returns the number of device path instances in DevicePath. --*/ { UINTN Count, Size; Count = 0; while (DevicePathInstance(&DevicePath, &Size)) { Count += 1; } return Count; }
BOOLEAN LibMatchDevicePaths ( IN EFI_DEVICE_PATH_PROTOCOL *Multi, IN EFI_DEVICE_PATH_PROTOCOL *Single ) /*++ Routine Description: Function compares a device path data structure to that of all the nodes of a second device path instance. Arguments: Multi - A pointer to a multi-instance device path data structure. Single - A pointer to a single-instance device path data structure. Returns: The function returns TRUE if the Single is contained within Multi. Otherwise, FALSE is returned. --*/ { EFI_DEVICE_PATH_PROTOCOL *DevicePath, *DevicePathInst; UINTN Size; if (!Multi || !Single) { return FALSE; } DevicePath = Multi; DevicePathInst = DevicePathInstance (&DevicePath, &Size); while (DevicePathInst) { if (CompareMem (Single, DevicePathInst, Size - sizeof(EFI_DEVICE_PATH_PROTOCOL)) == 0) { return TRUE; } DevicePathInst = DevicePathInstance (&DevicePath, &Size); } return FALSE; }
UINTN DevicePathInstanceCount ( IN EFI_DEVICE_PATH *DevicePath ) { UINTN Count, Size; Count = 0; while (DevicePathInstance(&DevicePath, &Size)) { Count += 1; } return Count; }
EFI_DEVICE_PATH_PROTOCOL * LibDuplicateDevicePathInstance ( IN EFI_DEVICE_PATH_PROTOCOL *DevPath ) /*++ Routine Description: Function creates a device path data structure that identically matches the device path passed in. Arguments: DevPath - A pointer to a device path data structure. Returns: The new copy of DevPath is created to identically match the input. Otherwise, NULL is returned. --*/ { EFI_DEVICE_PATH_PROTOCOL *NewDevPath,*DevicePathInst,*Temp; UINTN Size; // // get the size of an instance from the input // Temp = DevPath; DevicePathInst = DevicePathInstance (&Temp, &Size); // // Make a copy // NewDevPath = NULL; if (Size) { NewDevPath = AllocatePool (Size); } if (NewDevPath) { CopyMem (NewDevPath, DevicePathInst, Size); // Temp = NextDevicePathNode(NewDevPath); // SetDevicePathEndNode(Temp); } return NewDevPath; }
BOOLEAN LibMatchDevicePaths ( IN EFI_DEVICE_PATH *Multi, IN EFI_DEVICE_PATH *Single ) { EFI_DEVICE_PATH *DevicePath, *DevicePathInst; UINTN Size; if (!Multi || !Single) { return FALSE; } DevicePath = Multi; while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) { if (CompareMem (Single, DevicePathInst, Size) == 0) { return TRUE; } } return FALSE; }
EFI_IMAGE_EXECUTION_INFO * configtable_find_image(const EFI_DEVICE_PATH *DevicePath) { EFI_IMAGE_EXECUTION_INFO_TABLE *t = configtable_get_image_table(); if (!t) return NULL; int entries = t->NumberOfImages; EFI_IMAGE_EXECUTION_INFO *e = t->InformationInfo; int i; for (i = 0; i < entries; i++) { #ifdef DEBUG_CONFIG console_print(L"InfoSize = %d Action = %d\n", e->InfoSize, e->Action); /* print what we have for debugging */ UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); #endif CHAR16 *name = (CHAR16 *)(e->Data); int skip = 0; /* There's a bug in a lot of EFI platforms and they forget to * put the name here. The only real way of detecting it is to * look for either a UC16 NULL or ASCII as UC16 */ if (name[0] == '\0' || (e->Data[1] == 0 && e->Data[3] == 0)) { skip = StrSize(name); #ifdef DEBUG_CONFIG console_print(L"FOUND NAME %s (%d)\n", name, skip); #endif } EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp; if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0 || ((unsigned)((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) { /* Parse error, table corrupt, bail */ console_print(L"Image Execution Information table corrupt\n"); break; } UINTN Size; DevicePathInstance(&dpn, &Size); #ifdef DEBUG_CONFIG console_print(L"Path: %s\n", DevicePathToStr(dp)); console_print(L"Device Path Size %d\n", Size); #endif if (Size > e->InfoSize) { /* parse error; the platform obviously has a * corrupted image table; bail */ console_print(L"Image Execution Information table corrupt\n"); break; } if (CompareMem(dp, (void *)DevicePath, Size) == 0) { #ifdef DEBUG_CONFIG console_print(L"***FOUND\n"); console_get_keystroke(); #endif return e; } e = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)e + e->InfoSize); } #ifdef DEBUG_CONFIG console_print(L"***NOT FOUND\n"); console_get_keystroke(); #endif return NULL; }
EFI_DEVICE_PATH * AppendDevicePath ( IN EFI_DEVICE_PATH *Src1, IN EFI_DEVICE_PATH *Src2 ) // Src1 may have multiple "instances" and each instance is appended // Src2 is appended to each instance is Src1. (E.g., it's possible // to append a new instance to the complete device path by passing // it in Src2) { UINTN Src1Size, Src1Inst, Src2Size, Size; EFI_DEVICE_PATH *Dst, *Inst; UINT8 *DstPos; // // If there's only 1 path, just duplicate it // if (!Src1) { ASSERT (!IsDevicePathUnpacked (Src2)); return DuplicateDevicePath (Src2); } if (!Src2) { ASSERT (!IsDevicePathUnpacked (Src1)); return DuplicateDevicePath (Src1); } // // Verify we're not working with unpacked paths // // ASSERT (!IsDevicePathUnpacked (Src1)); // ASSERT (!IsDevicePathUnpacked (Src2)); // // Append Src2 to every instance in Src1 // Src1Size = DevicePathSize(Src1); Src1Inst = DevicePathInstanceCount(Src1); Src2Size = DevicePathSize(Src2); Size = Src1Size * Src1Inst + Src2Size; Dst = (EFI_DEVICE_PATH *) AllocatePool (Size); if (Dst) { DstPos = (UINT8 *) Dst; // // Copy all device path instances // while (Inst = DevicePathInstance (&Src1, &Size)) { BS->CopyMem(DstPos, Inst, Size); DstPos += Size; BS->CopyMem(DstPos, Src2, Src2Size); DstPos += Src2Size; BS->CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH)); DstPos += sizeof(EFI_DEVICE_PATH); } // Change last end marker DstPos -= sizeof(EFI_DEVICE_PATH); BS->CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH)); } return Dst; }
EFI_DEVICE_PATH_PROTOCOL * AppendDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *Src1, IN EFI_DEVICE_PATH_PROTOCOL *Src2 ) /*++ Routine Description: Function is used to append a device path to all the instances in another device path. Arguments: Src1 - A pointer to a device path data structure. Src2 - A pointer to a device path data structure. Returns: A pointer to the new device path is returned. NULL is returned if space for the new device path could not be allocated from pool. It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed. Src1 may have multiple "instances" and each instance is appended Src2 is appended to each instance is Src1. (E.g., it's possible to append a new instance to the complete device path by passing it in Src2) --*/ { UINTN Src1Size, Src1Inst, Src2Size, Size; EFI_DEVICE_PATH_PROTOCOL *Dst, *Inst; UINT8 *DstPos; // // If there's only 1 path, just duplicate it // if (!Src1) { ASSERT (!IsDevicePathUnpacked (Src2)); return DuplicateDevicePath (Src2); } if (!Src2) { ASSERT (!IsDevicePathUnpacked (Src1)); return DuplicateDevicePath (Src1); } // // Verify we're not working with unpacked paths // // ASSERT (!IsDevicePathUnpacked (Src1)); // ASSERT (!IsDevicePathUnpacked (Src2)); // // Append Src2 to every instance in Src1 // Src1Size = DevicePathSize(Src1); Src1Inst = DevicePathInstanceCount(Src1); Src2Size = DevicePathSize(Src2); Size = Src1Size * Src1Inst + Src2Size; Size -= Src1Inst * sizeof(EFI_DEVICE_PATH_PROTOCOL); Dst = AllocatePool (Size); if (Dst) { DstPos = (UINT8 *) Dst; // // Copy all device path instances // Inst = DevicePathInstance (&Src1, &Size); while (Inst) { CopyMem(DstPos, Inst, Size); DstPos += Size - sizeof(EFI_DEVICE_PATH_PROTOCOL); CopyMem(DstPos, Src2, Src2Size); DstPos += Src2Size - sizeof(EFI_DEVICE_PATH_PROTOCOL); CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH_PROTOCOL)); DstPos += sizeof(EFI_DEVICE_PATH_PROTOCOL); Inst = DevicePathInstance (&Src1, &Size); } // // Change last end marker // DstPos -= sizeof(EFI_DEVICE_PATH_PROTOCOL); CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH_PROTOCOL)); } return Dst; }