3
Copyright (c) 1998 Intel Corporation
10
MBR & Device Path functions
20
#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
25
DevicePathFromHandle (
30
EFI_DEVICE_PATH *DevicePath;
32
Status = BS->HandleProtocol (Handle, &DevicePathProtocol, (VOID*)&DevicePath);
33
if (EFI_ERROR(Status)) {
43
IN OUT EFI_DEVICE_PATH **DevicePath,
47
EFI_DEVICE_PATH *Start, *Next, *DevPath;
50
DevPath = *DevicePath;
58
// Check for end of device path type
61
for (Count = 0; ; Count++) {
62
Next = NextDevicePathNode(DevPath);
64
if (IsDevicePathEndType(DevPath)) {
70
// BugBug: Debug code to catch bogus device paths
72
DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
73
DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
80
ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
81
DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
87
if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
94
// Return size and start of device path instance
97
*Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
102
DevicePathInstanceCount (
103
IN EFI_DEVICE_PATH *DevicePath
109
while (DevicePathInstance(&DevicePath, &Size)) {
119
IN EFI_DEVICE_PATH *Src1,
120
IN EFI_DEVICE_PATH *Src2
122
// Src1 may have multiple "instances" and each instance is appended
123
// Src2 is appended to each instance is Src1. (E.g., it's possible
124
// to append a new instance to the complete device path by passing
127
UINTN Src1Size, Src1Inst, Src2Size, Size;
128
EFI_DEVICE_PATH *Dst, *Inst;
132
// If there's only 1 path, just duplicate it
136
ASSERT (!IsDevicePathUnpacked (Src2));
137
return DuplicateDevicePath (Src2);
141
ASSERT (!IsDevicePathUnpacked (Src1));
142
return DuplicateDevicePath (Src1);
146
// Verify we're not working with unpacked paths
149
// ASSERT (!IsDevicePathUnpacked (Src1));
150
// ASSERT (!IsDevicePathUnpacked (Src2));
153
// Append Src2 to every instance in Src1
156
Src1Size = DevicePathSize(Src1);
157
Src1Inst = DevicePathInstanceCount(Src1);
158
Src2Size = DevicePathSize(Src2);
159
Size = Src1Size * Src1Inst + Src2Size;
161
Dst = AllocatePool (Size);
163
DstPos = (UINT8 *) Dst;
166
// Copy all device path instances
169
while ((Inst = DevicePathInstance (&Src1, &Size))) {
171
CopyMem(DstPos, Inst, Size);
174
CopyMem(DstPos, Src2, Src2Size);
177
CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
178
DstPos += sizeof(EFI_DEVICE_PATH);
181
// Change last end marker
182
DstPos -= sizeof(EFI_DEVICE_PATH);
183
CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
191
AppendDevicePathNode (
192
IN EFI_DEVICE_PATH *Src1,
193
IN EFI_DEVICE_PATH *Src2
195
// Src1 may have multiple "instances" and each instance is appended
196
// Src2 is a signal device path node (without a terminator) that is
197
// appended to each instance is Src1.
199
EFI_DEVICE_PATH *Temp, *Eop;
203
// Build a Src2 that has a terminator on it
206
Length = DevicePathNodeLength(Src2);
207
Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
212
CopyMem (Temp, Src2, Length);
213
Eop = NextDevicePathNode(Temp);
214
SetDevicePathEndNode(Eop);
217
// Append device paths
220
Src1 = AppendDevicePath (Src1, Temp);
228
IN EFI_HANDLE Device OPTIONAL,
233
N.B. Results are allocated from pool. The caller must FreePool
234
the resulting device path structure
239
FILEPATH_DEVICE_PATH *FilePath;
240
EFI_DEVICE_PATH *Eop, *DevicePath;
242
Size = StrSize(FileName);
243
FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
252
FilePath->Header.Type = MEDIA_DEVICE_PATH;
253
FilePath->Header.SubType = MEDIA_FILEPATH_DP;
254
SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
255
CopyMem (FilePath->PathName, FileName, Size);
256
Eop = NextDevicePathNode(&FilePath->Header);
257
SetDevicePathEndNode(Eop);
260
// Append file path to device's device path
263
DevicePath = (EFI_DEVICE_PATH *) FilePath;
265
DevicePath = AppendDevicePath (
266
DevicePathFromHandle(Device),
281
IN EFI_DEVICE_PATH *DevPath
284
EFI_DEVICE_PATH *Start;
287
// Search for the end of the device path structure
291
while (!IsDevicePathEnd(DevPath)) {
292
DevPath = NextDevicePathNode(DevPath);
299
return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
303
DuplicateDevicePath (
304
IN EFI_DEVICE_PATH *DevPath
307
EFI_DEVICE_PATH *NewDevPath;
315
Size = DevicePathSize (DevPath);
321
NewDevPath = AllocatePool (Size);
323
CopyMem (NewDevPath, DevPath, Size);
331
IN EFI_DEVICE_PATH *DevPath
334
EFI_DEVICE_PATH *Src, *Dest, *NewPath;
338
// Walk device path and round sizes to valid boundries
344
Size += DevicePathNodeLength(Src);
345
Size += ALIGN_SIZE(Size);
347
if (IsDevicePathEnd(Src)) {
351
Src = NextDevicePathNode(Src);
356
// Allocate space for the unpacked path
359
NewPath = AllocateZeroPool (Size);
362
ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
371
Size = DevicePathNodeLength(Src);
372
CopyMem (Dest, Src, Size);
373
Size += ALIGN_SIZE(Size);
374
SetDevicePathNodeLength (Dest, Size);
375
Dest->Type |= EFI_DP_TYPE_UNPACKED;
376
Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
378
if (IsDevicePathEnd(Src)) {
382
Src = NextDevicePathNode(Src);
391
AppendDevicePathInstance (
392
IN EFI_DEVICE_PATH *Src,
393
IN EFI_DEVICE_PATH *Instance
397
EFI_DEVICE_PATH *DevPath;
402
return DuplicateDevicePath (Instance);
404
SrcSize = DevicePathSize(Src);
405
InstanceSize = DevicePathSize(Instance);
406
Ptr = AllocatePool (SrcSize + InstanceSize);
407
DevPath = (EFI_DEVICE_PATH *)Ptr;
410
CopyMem (Ptr, Src, SrcSize);
413
while (!IsDevicePathEnd(DevPath)) {
414
DevPath = NextDevicePathNode(DevPath);
417
// Convert the End to an End Instance, since we are
418
// appending another instacne after this one its a good
421
DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
423
DevPath = NextDevicePathNode(DevPath);
424
CopyMem (DevPath, Instance, InstanceSize);
425
return (EFI_DEVICE_PATH *)Ptr;
429
LibDevicePathToInterface (
430
IN EFI_GUID *Protocol,
431
IN EFI_DEVICE_PATH *FilePath,
438
Status = BS->LocateDevicePath (Protocol, &FilePath, &Device);
440
if (!EFI_ERROR(Status)) {
442
// If we didn't get a direct match return not found
443
Status = EFI_NOT_FOUND;
445
if (IsDevicePathEnd(FilePath)) {
448
// It was a direct match, lookup the protocol interface
451
Status = BS->HandleProtocol (Device, Protocol, Interface);
456
// If there was an error, do not return an interface
459
if (EFI_ERROR(Status)) {
468
IN OUT POOL_PRINT *Str,
472
PCI_DEVICE_PATH *Pci;
475
CatPrint(Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);
480
IN OUT POOL_PRINT *Str,
484
PCCARD_DEVICE_PATH *Pccard;
487
CatPrint(Str, L"Pccard(Socket%x)", Pccard->SocketNumber);
492
IN OUT POOL_PRINT *Str,
496
MEMMAP_DEVICE_PATH *MemMap;
499
CatPrint(Str, L"MemMap(%d:%x-%x)",
501
MemMap->StartingAddress,
502
MemMap->EndingAddress
508
IN OUT POOL_PRINT *Str,
512
CONTROLLER_DEVICE_PATH *Controller;
514
Controller = DevPath;
515
CatPrint(Str, L"Ctrl(%d)",
516
Controller->Controller
522
IN OUT POOL_PRINT *Str,
526
VENDOR_DEVICE_PATH *Vendor;
528
UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevPath;
531
switch (DevicePathType(&Vendor->Header)) {
532
case HARDWARE_DEVICE_PATH: Type = L"Hw"; break;
533
case MESSAGING_DEVICE_PATH: Type = L"Msg"; break;
534
case MEDIA_DEVICE_PATH: Type = L"Media"; break;
535
default: Type = L"?"; break;
538
CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
539
if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
541
// GUID used by EFI to enumerate an EDD 1.1 device
543
UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
544
CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
553
IN OUT POOL_PRINT *Str,
557
ACPI_HID_DEVICE_PATH *Acpi;
560
if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
561
CatPrint(Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
563
CatPrint(Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
570
IN OUT POOL_PRINT *Str,
574
ATAPI_DEVICE_PATH *Atapi;
577
CatPrint(Str, L"Ata(%s,%s)",
578
Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
579
Atapi->SlaveMaster ? L"Slave" : L"Master"
585
IN OUT POOL_PRINT *Str,
589
SCSI_DEVICE_PATH *Scsi;
592
CatPrint(Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);
598
IN OUT POOL_PRINT *Str,
602
FIBRECHANNEL_DEVICE_PATH *Fibre;
605
CatPrint(Str, L"Fibre(%lx)", Fibre->WWN);
610
IN OUT POOL_PRINT *Str,
614
F1394_DEVICE_PATH *F1394;
617
CatPrint(Str, L"1394(%g)", &F1394->Guid);
624
IN OUT POOL_PRINT *Str,
628
USB_DEVICE_PATH *Usb;
631
CatPrint(Str, L"Usb(%x)", Usb->Port);
637
IN OUT POOL_PRINT *Str,
641
I2O_DEVICE_PATH *I2O;
644
CatPrint(Str, L"I2O(%x)", I2O->Tid);
649
IN OUT POOL_PRINT *Str,
653
MAC_ADDR_DEVICE_PATH *MAC;
659
HwAddressSize = sizeof(EFI_MAC_ADDRESS);
660
if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
664
CatPrint(Str, L"Mac(");
666
for(Index = 0; Index < HwAddressSize; Index++) {
667
CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
674
IN OUT POOL_PRINT *Str,
678
IPv4_DEVICE_PATH *IP;
681
CatPrint(Str, L"IPv4(not-done)");
686
IN OUT POOL_PRINT *Str,
690
IPv6_DEVICE_PATH *IP;
693
CatPrint(Str, L"IP-v6(not-done)");
698
IN OUT POOL_PRINT *Str,
702
INFINIBAND_DEVICE_PATH *InfiniBand;
704
InfiniBand = DevPath;
705
CatPrint(Str, L"InfiniBand(not-done)");
710
IN OUT POOL_PRINT *Str,
714
UART_DEVICE_PATH *Uart;
718
switch (Uart->Parity) {
719
case 0 : Parity = 'D'; break;
720
case 1 : Parity = 'N'; break;
721
case 2 : Parity = 'E'; break;
722
case 3 : Parity = 'O'; break;
723
case 4 : Parity = 'M'; break;
724
case 5 : Parity = 'S'; break;
725
default : Parity = 'x'; break;
728
if (Uart->BaudRate == 0) {
729
CatPrint(Str, L"Uart(DEFAULT %c",Uart->BaudRate,Parity);
731
CatPrint(Str, L"Uart(%d %c",Uart->BaudRate,Parity);
734
if (Uart->DataBits == 0) {
737
CatPrint(Str, L"%d",Uart->DataBits);
740
switch (Uart->StopBits) {
741
case 0 : CatPrint(Str, L"D)"); break;
742
case 1 : CatPrint(Str, L"1)"); break;
743
case 2 : CatPrint(Str, L"1.5)"); break;
744
case 3 : CatPrint(Str, L"2)"); break;
745
default : CatPrint(Str, L"x)"); break;
752
IN OUT POOL_PRINT *Str,
756
HARDDRIVE_DEVICE_PATH *Hd;
759
switch (Hd->SignatureType) {
760
case SIGNATURE_TYPE_MBR:
761
CatPrint(Str, L"HD(Part%d,Sig%08X)",
763
*((UINT32 *)(&(Hd->Signature[0])))
766
case SIGNATURE_TYPE_GUID:
767
CatPrint(Str, L"HD(Part%d,Sig%g)",
769
(EFI_GUID *) &(Hd->Signature[0])
773
CatPrint(Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)",
784
IN OUT POOL_PRINT *Str,
788
CDROM_DEVICE_PATH *Cd;
791
CatPrint(Str, L"CDROM(Entry%x)", Cd->BootEntry);
796
IN OUT POOL_PRINT *Str,
800
FILEPATH_DEVICE_PATH *Fp;
803
CatPrint(Str, L"%s", Fp->PathName);
807
_DevPathMediaProtocol (
808
IN OUT POOL_PRINT *Str,
812
MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
815
CatPrint(Str, L"%g", &MediaProt->Protocol);
820
IN OUT POOL_PRINT *Str,
824
BBS_BBS_DEVICE_PATH *Bss;
828
switch (Bss->DeviceType) {
829
case BBS_TYPE_FLOPPY: Type = L"Floppy"; break;
830
case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break;
831
case BBS_TYPE_CDROM: Type = L"CDROM"; break;
832
case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break;
833
case BBS_TYPE_USB: Type = L"Usb"; break;
834
case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break;
835
default: Type = L"?"; break;
838
CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
843
_DevPathEndInstance (
844
IN OUT POOL_PRINT *Str,
852
_DevPathNodeUnknown (
853
IN OUT POOL_PRINT *Str,
864
VOID (*Function)(POOL_PRINT *, VOID *);
866
{ HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci},
867
{ HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard},
868
{ HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap},
869
{ HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor},
870
{ HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController},
871
{ ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi},
872
{ MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi},
873
{ MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi},
874
{ MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre},
875
{ MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394},
876
{ MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb},
877
{ MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O},
878
{ MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr},
879
{ MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4},
880
{ MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6},
881
{ MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand},
882
{ MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart},
883
{ MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor},
884
{ MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive},
885
{ MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM},
886
{ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor},
887
{ MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath},
888
{ MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol},
889
{ BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss},
890
{ END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
897
EFI_DEVICE_PATH *DevPath
901
Turns the Device Path into a printable string. Allcoates
902
the string from pool. The caller must FreePool the returned
908
EFI_DEVICE_PATH *DevPathNode;
909
VOID (*DumpNode)(POOL_PRINT *, VOID *);
910
UINTN Index, NewSize;
912
ZeroMem(&Str, sizeof(Str));
915
// Unpacked the device path
918
DevPath = UnpackDevicePath(DevPath);
923
// Process each device path node
926
DevPathNode = DevPath;
927
while (!IsDevicePathEnd(DevPathNode)) {
929
// Find the handler to dump this device path node
933
for (Index = 0; DevPathTable[Index].Function; Index += 1) {
935
if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
936
DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
937
DumpNode = DevPathTable[Index].Function;
943
// If not found, use a generic function
947
DumpNode = _DevPathNodeUnknown;
951
// Put a path seperator in if needed
954
if (Str.len && DumpNode != _DevPathEndInstance) {
955
CatPrint (&Str, L"/");
959
// Print this node of the device path
962
DumpNode (&Str, DevPathNode);
965
// Next device path node
968
DevPathNode = NextDevicePathNode(DevPathNode);
972
// Shrink pool used for string allocation
976
NewSize = (Str.len + 1) * sizeof(CHAR16);
977
Str.str = ReallocatePool (Str.str, NewSize, NewSize);
978
Str.str[Str.len] = 0;
983
LibMatchDevicePaths (
984
IN EFI_DEVICE_PATH *Multi,
985
IN EFI_DEVICE_PATH *Single
988
EFI_DEVICE_PATH *DevicePath, *DevicePathInst;
991
if (!Multi || !Single) {
996
while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
997
if (CompareMem (Single, DevicePathInst, Size) == 0) {
1005
LibDuplicateDevicePathInstance (
1006
IN EFI_DEVICE_PATH *DevPath
1009
EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp;
1013
// get the size of an instance from the input
1017
DevicePathInst = DevicePathInstance (&Temp, &Size);
1020
// Make a copy and set proper end type
1024
NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
1028
CopyMem (NewDevPath, DevicePathInst, Size);
1029
Temp = NextDevicePathNode(NewDevPath);
1030
SetDevicePathEndNode(Temp);