Home | History | Annotate | Line # | Download | only in lib
dpath.c revision 1.1
      1 /*	$NetBSD: dpath.c,v 1.1 2014/04/01 16:16:06 jakllsch Exp $	*/
      2 
      3 /*++
      4 
      5 Copyright (c) 1998  Intel Corporation
      6 
      7 Module Name:
      8 
      9     dpath.c
     10 
     11 Abstract:
     12     MBR & Device Path functions
     13 
     14 
     15 
     16 Revision History
     17 
     18 --*/
     19 
     20 #include "lib.h"
     21 
     22 #define ALIGN_SIZE(a)   ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
     23 
     24 
     25 
     26 EFI_DEVICE_PATH *
     27 DevicePathFromHandle (
     28     IN EFI_HANDLE       Handle
     29     )
     30 {
     31     EFI_STATUS          Status;
     32     EFI_DEVICE_PATH     *DevicePath;
     33 
     34     Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath);
     35     if (EFI_ERROR(Status)) {
     36         DevicePath = NULL;
     37     }
     38 
     39     return DevicePath;
     40 }
     41 
     42 
     43 EFI_DEVICE_PATH *
     44 DevicePathInstance (
     45     IN OUT EFI_DEVICE_PATH  **DevicePath,
     46     OUT UINTN               *Size
     47     )
     48 {
     49     EFI_DEVICE_PATH         *Start, *Next, *DevPath;
     50     UINTN                   Count;
     51 
     52     DevPath = *DevicePath;
     53     Start = DevPath;
     54 
     55     if (!DevPath) {
     56         return NULL;
     57     }
     58 
     59     //
     60     // Check for end of device path type
     61     //
     62 
     63     for (Count = 0; ; Count++) {
     64         Next = NextDevicePathNode(DevPath);
     65 
     66         if (IsDevicePathEndType(DevPath)) {
     67             break;
     68         }
     69 
     70         if (Count > 01000) {
     71             //
     72             // BugBug: Debug code to catch bogus device paths
     73             //
     74             DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
     75             DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
     76             break;
     77         }
     78 
     79         DevPath = Next;
     80     }
     81 
     82     ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
     83             DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
     84 
     85     //
     86     // Set next position
     87     //
     88 
     89     if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
     90         Next = NULL;
     91     }
     92 
     93     *DevicePath = Next;
     94 
     95     //
     96     // Return size and start of device path instance
     97     //
     98 
     99     *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
    100     return Start;
    101 }
    102 
    103 UINTN
    104 DevicePathInstanceCount (
    105     IN EFI_DEVICE_PATH      *DevicePath
    106     )
    107 {
    108     UINTN       Count, Size;
    109 
    110     Count = 0;
    111     while (DevicePathInstance(&DevicePath, &Size)) {
    112         Count += 1;
    113     }
    114 
    115     return Count;
    116 }
    117 
    118 
    119 EFI_DEVICE_PATH *
    120 AppendDevicePath (
    121     IN EFI_DEVICE_PATH  *Src1,
    122     IN EFI_DEVICE_PATH  *Src2
    123     )
    124 // Src1 may have multiple "instances" and each instance is appended
    125 // Src2 is appended to each instance is Src1.  (E.g., it's possible
    126 // to append a new instance to the complete device path by passing
    127 // it in Src2)
    128 {
    129     UINTN               Src1Size, Src1Inst, Src2Size, Size;
    130     EFI_DEVICE_PATH     *Dst, *Inst;
    131     UINT8               *DstPos;
    132 
    133     //
    134     // If there's only 1 path, just duplicate it
    135     //
    136 
    137     if (!Src1) {
    138         ASSERT (!IsDevicePathUnpacked (Src2));
    139         return DuplicateDevicePath (Src2);
    140     }
    141 
    142     if (!Src2) {
    143         ASSERT (!IsDevicePathUnpacked (Src1));
    144         return DuplicateDevicePath (Src1);
    145     }
    146 
    147     //
    148     // Verify we're not working with unpacked paths
    149     //
    150 
    151 //    ASSERT (!IsDevicePathUnpacked (Src1));
    152 //    ASSERT (!IsDevicePathUnpacked (Src2));
    153 
    154     //
    155     // Append Src2 to every instance in Src1
    156     //
    157 
    158     Src1Size = DevicePathSize(Src1);
    159     Src1Inst = DevicePathInstanceCount(Src1);
    160     Src2Size = DevicePathSize(Src2);
    161     Size = Src1Size * Src1Inst + Src2Size;
    162 
    163     Dst = AllocatePool (Size);
    164     if (Dst) {
    165         DstPos = (UINT8 *) Dst;
    166 
    167         //
    168         // Copy all device path instances
    169         //
    170 
    171         while ((Inst = DevicePathInstance (&Src1, &Size))) {
    172 
    173             CopyMem(DstPos, Inst, Size);
    174             DstPos += Size;
    175 
    176             CopyMem(DstPos, Src2, Src2Size);
    177             DstPos += Src2Size;
    178 
    179             CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
    180             DstPos += sizeof(EFI_DEVICE_PATH);
    181         }
    182 
    183         // Change last end marker
    184         DstPos -= sizeof(EFI_DEVICE_PATH);
    185         CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
    186     }
    187 
    188     return Dst;
    189 }
    190 
    191 
    192 EFI_DEVICE_PATH *
    193 AppendDevicePathNode (
    194     IN EFI_DEVICE_PATH  *Src1,
    195     IN EFI_DEVICE_PATH  *Src2
    196     )
    197 // Src1 may have multiple "instances" and each instance is appended
    198 // Src2 is a signal device path node (without a terminator) that is
    199 // appended to each instance is Src1.
    200 {
    201     EFI_DEVICE_PATH     *Temp, *Eop;
    202     UINTN               Length;
    203 
    204     //
    205     // Build a Src2 that has a terminator on it
    206     //
    207 
    208     Length = DevicePathNodeLength(Src2);
    209     Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
    210     if (!Temp) {
    211         return NULL;
    212     }
    213 
    214     CopyMem (Temp, Src2, Length);
    215     Eop = NextDevicePathNode(Temp);
    216     SetDevicePathEndNode(Eop);
    217 
    218     //
    219     // Append device paths
    220     //
    221 
    222     Src1 = AppendDevicePath (Src1, Temp);
    223     FreePool (Temp);
    224     return Src1;
    225 }
    226 
    227 
    228 EFI_DEVICE_PATH *
    229 FileDevicePath (
    230     IN EFI_HANDLE       Device  OPTIONAL,
    231     IN CHAR16           *FileName
    232     )
    233 /*++
    234 
    235     N.B. Results are allocated from pool.  The caller must FreePool
    236     the resulting device path structure
    237 
    238 --*/
    239 {
    240     UINTN                   Size;
    241     FILEPATH_DEVICE_PATH    *FilePath;
    242     EFI_DEVICE_PATH         *Eop, *DevicePath;
    243 
    244     Size = StrSize(FileName);
    245     FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
    246     DevicePath = NULL;
    247 
    248     if (FilePath) {
    249 
    250         //
    251         // Build a file path
    252         //
    253 
    254         FilePath->Header.Type = MEDIA_DEVICE_PATH;
    255         FilePath->Header.SubType = MEDIA_FILEPATH_DP;
    256         SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
    257         CopyMem (FilePath->PathName, FileName, Size);
    258         Eop = NextDevicePathNode(&FilePath->Header);
    259         SetDevicePathEndNode(Eop);
    260 
    261         //
    262         // Append file path to device's device path
    263         //
    264 
    265         DevicePath = (EFI_DEVICE_PATH *) FilePath;
    266         if (Device) {
    267             DevicePath = AppendDevicePath (
    268                             DevicePathFromHandle(Device),
    269                             DevicePath
    270                             );
    271 
    272             FreePool(FilePath);
    273         }
    274     }
    275 
    276     return DevicePath;
    277 }
    278 
    279 
    280 
    281 UINTN
    282 DevicePathSize (
    283     IN EFI_DEVICE_PATH  *DevPath
    284     )
    285 {
    286     EFI_DEVICE_PATH     *Start;
    287 
    288     //
    289     // Search for the end of the device path structure
    290     //
    291 
    292     Start = DevPath;
    293     while (!IsDevicePathEnd(DevPath)) {
    294         DevPath = NextDevicePathNode(DevPath);
    295     }
    296 
    297     //
    298     // Compute the size
    299     //
    300 
    301     return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
    302 }
    303 
    304 EFI_DEVICE_PATH *
    305 DuplicateDevicePath (
    306     IN EFI_DEVICE_PATH  *DevPath
    307     )
    308 {
    309     EFI_DEVICE_PATH     *NewDevPath;
    310     UINTN               Size;
    311 
    312 
    313     //
    314     // Compute the size
    315     //
    316 
    317     Size = DevicePathSize (DevPath);
    318 
    319     //
    320     // Make a copy
    321     //
    322 
    323     NewDevPath = AllocatePool (Size);
    324     if (NewDevPath) {
    325         CopyMem (NewDevPath, DevPath, Size);
    326     }
    327 
    328     return NewDevPath;
    329 }
    330 
    331 EFI_DEVICE_PATH *
    332 UnpackDevicePath (
    333     IN EFI_DEVICE_PATH  *DevPath
    334     )
    335 {
    336     EFI_DEVICE_PATH     *Src, *Dest, *NewPath;
    337     UINTN               Size;
    338 
    339     //
    340     // Walk device path and round sizes to valid boundries
    341     //
    342 
    343     Src = DevPath;
    344     Size = 0;
    345     for (; ;) {
    346         Size += DevicePathNodeLength(Src);
    347         Size += ALIGN_SIZE(Size);
    348 
    349         if (IsDevicePathEnd(Src)) {
    350             break;
    351         }
    352 
    353         Src = NextDevicePathNode(Src);
    354     }
    355 
    356 
    357     //
    358     // Allocate space for the unpacked path
    359     //
    360 
    361     NewPath = AllocateZeroPool (Size);
    362     if (NewPath) {
    363 
    364         ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
    365 
    366         //
    367         // Copy each node
    368         //
    369 
    370         Src = DevPath;
    371         Dest = NewPath;
    372         for (; ;) {
    373             Size = DevicePathNodeLength(Src);
    374             CopyMem (Dest, Src, Size);
    375             Size += ALIGN_SIZE(Size);
    376             SetDevicePathNodeLength (Dest, Size);
    377             Dest->Type |= EFI_DP_TYPE_UNPACKED;
    378             Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
    379 
    380             if (IsDevicePathEnd(Src)) {
    381                 break;
    382             }
    383 
    384             Src = NextDevicePathNode(Src);
    385         }
    386     }
    387 
    388     return NewPath;
    389 }
    390 
    391 
    392 EFI_DEVICE_PATH*
    393 AppendDevicePathInstance (
    394     IN EFI_DEVICE_PATH  *Src,
    395     IN EFI_DEVICE_PATH  *Instance
    396     )
    397 {
    398     UINT8           *Ptr;
    399     EFI_DEVICE_PATH *DevPath;
    400     UINTN           SrcSize;
    401     UINTN           InstanceSize;
    402 
    403     if (Src == NULL) {
    404         return DuplicateDevicePath (Instance);
    405     }
    406     SrcSize = DevicePathSize(Src);
    407     InstanceSize = DevicePathSize(Instance);
    408     Ptr = AllocatePool (SrcSize + InstanceSize);
    409     DevPath = (EFI_DEVICE_PATH *)Ptr;
    410     ASSERT(DevPath);
    411 
    412     CopyMem (Ptr, Src, SrcSize);
    413 //    FreePool (Src);
    414 
    415     while (!IsDevicePathEnd(DevPath)) {
    416         DevPath = NextDevicePathNode(DevPath);
    417     }
    418     //
    419     // Convert the End to an End Instance, since we are
    420     //  appending another instacne after this one its a good
    421     //  idea.
    422     //
    423     DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
    424 
    425     DevPath = NextDevicePathNode(DevPath);
    426     CopyMem (DevPath, Instance, InstanceSize);
    427     return (EFI_DEVICE_PATH *)Ptr;
    428 }
    429 
    430 EFI_STATUS
    431 LibDevicePathToInterface (
    432     IN EFI_GUID             *Protocol,
    433     IN EFI_DEVICE_PATH      *FilePath,
    434     OUT VOID                **Interface
    435     )
    436 {
    437     EFI_STATUS              Status;
    438     EFI_HANDLE              Device;
    439 
    440     Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device);
    441 
    442     if (!EFI_ERROR(Status)) {
    443 
    444         // If we didn't get a direct match return not found
    445         Status = EFI_NOT_FOUND;
    446 
    447         if (IsDevicePathEnd(FilePath)) {
    448 
    449             //
    450             // It was a direct match, lookup the protocol interface
    451             //
    452 
    453             Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface);
    454         }
    455     }
    456 
    457     //
    458     // If there was an error, do not return an interface
    459     //
    460 
    461     if (EFI_ERROR(Status)) {
    462         *Interface = NULL;
    463     }
    464 
    465     return Status;
    466 }
    467 
    468 VOID
    469 _DevPathPci (
    470     IN OUT POOL_PRINT       *Str,
    471     IN VOID                 *DevPath
    472     )
    473 {
    474     PCI_DEVICE_PATH         *Pci;
    475 
    476     Pci = DevPath;
    477     CatPrint(Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);
    478 }
    479 
    480 VOID
    481 _DevPathPccard (
    482     IN OUT POOL_PRINT       *Str,
    483     IN VOID                 *DevPath
    484     )
    485 {
    486     PCCARD_DEVICE_PATH      *Pccard;
    487 
    488     Pccard = DevPath;
    489     CatPrint(Str, L"Pccard(Socket%x)", Pccard->SocketNumber);
    490 }
    491 
    492 VOID
    493 _DevPathMemMap (
    494     IN OUT POOL_PRINT       *Str,
    495     IN VOID                 *DevPath
    496     )
    497 {
    498     MEMMAP_DEVICE_PATH      *MemMap;
    499 
    500     MemMap = DevPath;
    501     CatPrint(Str, L"MemMap(%d:%x-%x)",
    502         MemMap->MemoryType,
    503         MemMap->StartingAddress,
    504         MemMap->EndingAddress
    505         );
    506 }
    507 
    508 VOID
    509 _DevPathController (
    510     IN OUT POOL_PRINT       *Str,
    511     IN VOID                 *DevPath
    512     )
    513 {
    514     CONTROLLER_DEVICE_PATH  *Controller;
    515 
    516     Controller = DevPath;
    517     CatPrint(Str, L"Ctrl(%d)",
    518         Controller->Controller
    519         );
    520 }
    521 
    522 VOID
    523 _DevPathVendor (
    524     IN OUT POOL_PRINT       *Str,
    525     IN VOID                 *DevPath
    526     )
    527 {
    528     VENDOR_DEVICE_PATH                  *Vendor;
    529     CHAR16                              *Type;
    530     UNKNOWN_DEVICE_VENDOR_DEVICE_PATH   *UnknownDevPath;
    531 
    532     Vendor = DevPath;
    533     switch (DevicePathType(&Vendor->Header)) {
    534     case HARDWARE_DEVICE_PATH:  Type = L"Hw";        break;
    535     case MESSAGING_DEVICE_PATH: Type = L"Msg";       break;
    536     case MEDIA_DEVICE_PATH:     Type = L"Media";     break;
    537     default:                    Type = L"?";         break;
    538     }
    539 
    540     CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
    541     if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
    542         //
    543         // GUID used by EFI to enumerate an EDD 1.1 device
    544         //
    545         UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
    546         CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
    547     } else {
    548         CatPrint(Str, L")");
    549     }
    550 }
    551 
    552 
    553 VOID
    554 _DevPathAcpi (
    555     IN OUT POOL_PRINT       *Str,
    556     IN VOID                 *DevPath
    557     )
    558 {
    559     ACPI_HID_DEVICE_PATH        *Acpi;
    560 
    561     Acpi = DevPath;
    562     if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
    563         CatPrint(Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
    564     } else {
    565         CatPrint(Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
    566     }
    567 }
    568 
    569 
    570 VOID
    571 _DevPathAtapi (
    572     IN OUT POOL_PRINT       *Str,
    573     IN VOID                 *DevPath
    574     )
    575 {
    576     ATAPI_DEVICE_PATH       *Atapi;
    577 
    578     Atapi = DevPath;
    579     CatPrint(Str, L"Ata(%s,%s)",
    580         Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
    581         Atapi->SlaveMaster ? L"Slave" : L"Master"
    582         );
    583 }
    584 
    585 VOID
    586 _DevPathScsi (
    587     IN OUT POOL_PRINT       *Str,
    588     IN VOID                 *DevPath
    589     )
    590 {
    591     SCSI_DEVICE_PATH        *Scsi;
    592 
    593     Scsi = DevPath;
    594     CatPrint(Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);
    595 }
    596 
    597 
    598 VOID
    599 _DevPathFibre (
    600     IN OUT POOL_PRINT       *Str,
    601     IN VOID                 *DevPath
    602     )
    603 {
    604     FIBRECHANNEL_DEVICE_PATH    *Fibre;
    605 
    606     Fibre = DevPath;
    607     CatPrint(Str, L"Fibre(%lx)", Fibre->WWN);
    608 }
    609 
    610 VOID
    611 _DevPath1394 (
    612     IN OUT POOL_PRINT       *Str,
    613     IN VOID                 *DevPath
    614     )
    615 {
    616     F1394_DEVICE_PATH       *F1394;
    617 
    618     F1394 = DevPath;
    619     CatPrint(Str, L"1394(%g)", &F1394->Guid);
    620 }
    621 
    622 
    623 
    624 VOID
    625 _DevPathUsb (
    626     IN OUT POOL_PRINT       *Str,
    627     IN VOID                 *DevPath
    628     )
    629 {
    630     USB_DEVICE_PATH         *Usb;
    631 
    632     Usb = DevPath;
    633     CatPrint(Str, L"Usb(%x)", Usb->Port);
    634 }
    635 
    636 
    637 VOID
    638 _DevPathI2O (
    639     IN OUT POOL_PRINT       *Str,
    640     IN VOID                 *DevPath
    641     )
    642 {
    643     I2O_DEVICE_PATH         *I2O;
    644 
    645     I2O = DevPath;
    646     CatPrint(Str, L"I2O(%x)", I2O->Tid);
    647 }
    648 
    649 VOID
    650 _DevPathMacAddr (
    651     IN OUT POOL_PRINT       *Str,
    652     IN VOID                 *DevPath
    653     )
    654 {
    655     MAC_ADDR_DEVICE_PATH    *MAC;
    656     UINTN                   HwAddressSize;
    657     UINTN                   Index;
    658 
    659     MAC = DevPath;
    660 
    661     HwAddressSize = sizeof(EFI_MAC_ADDRESS);
    662     if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
    663         HwAddressSize = 6;
    664     }
    665 
    666     CatPrint(Str, L"Mac(");
    667 
    668     for(Index = 0; Index < HwAddressSize; Index++) {
    669         CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
    670     }
    671     CatPrint(Str, L")");
    672 }
    673 
    674 VOID
    675 _DevPathIPv4 (
    676     IN OUT POOL_PRINT       *Str,
    677     IN VOID                 *DevPath
    678     )
    679 {
    680     IPv4_DEVICE_PATH     *IP;
    681 
    682     IP = DevPath;
    683     CatPrint(Str, L"IPv4(not-done)");
    684 }
    685 
    686 VOID
    687 _DevPathIPv6 (
    688     IN OUT POOL_PRINT       *Str,
    689     IN VOID                 *DevPath
    690     )
    691 {
    692     IPv6_DEVICE_PATH     *IP;
    693 
    694     IP = DevPath;
    695     CatPrint(Str, L"IP-v6(not-done)");
    696 }
    697 
    698 VOID
    699 _DevPathInfiniBand (
    700     IN OUT POOL_PRINT       *Str,
    701     IN VOID                 *DevPath
    702     )
    703 {
    704     INFINIBAND_DEVICE_PATH  *InfiniBand;
    705 
    706     InfiniBand = DevPath;
    707     CatPrint(Str, L"InfiniBand(not-done)");
    708 }
    709 
    710 VOID
    711 _DevPathUart (
    712     IN OUT POOL_PRINT       *Str,
    713     IN VOID                 *DevPath
    714     )
    715 {
    716     UART_DEVICE_PATH  *Uart;
    717     CHAR8             Parity;
    718 
    719     Uart = DevPath;
    720     switch (Uart->Parity) {
    721         case 0  : Parity = 'D'; break;
    722         case 1  : Parity = 'N'; break;
    723         case 2  : Parity = 'E'; break;
    724         case 3  : Parity = 'O'; break;
    725         case 4  : Parity = 'M'; break;
    726         case 5  : Parity = 'S'; break;
    727         default : Parity = 'x'; break;
    728     }
    729 
    730     if (Uart->BaudRate == 0) {
    731         CatPrint(Str, L"Uart(DEFAULT %c",Uart->BaudRate,Parity);
    732     } else {
    733         CatPrint(Str, L"Uart(%d %c",Uart->BaudRate,Parity);
    734     }
    735 
    736     if (Uart->DataBits == 0) {
    737         CatPrint(Str, L"D");
    738     } else {
    739         CatPrint(Str, L"%d",Uart->DataBits);
    740     }
    741 
    742     switch (Uart->StopBits) {
    743         case 0  : CatPrint(Str, L"D)");   break;
    744         case 1  : CatPrint(Str, L"1)");   break;
    745         case 2  : CatPrint(Str, L"1.5)"); break;
    746         case 3  : CatPrint(Str, L"2)");   break;
    747         default : CatPrint(Str, L"x)");   break;
    748     }
    749 }
    750 
    751 
    752 VOID
    753 _DevPathHardDrive (
    754     IN OUT POOL_PRINT       *Str,
    755     IN VOID                 *DevPath
    756     )
    757 {
    758     HARDDRIVE_DEVICE_PATH   *Hd;
    759 
    760     Hd = DevPath;
    761     switch (Hd->SignatureType) {
    762         case SIGNATURE_TYPE_MBR:
    763             CatPrint(Str, L"HD(Part%d,Sig%08X)",
    764                 Hd->PartitionNumber,
    765                 *((UINT32 *)(&(Hd->Signature[0])))
    766                 );
    767             break;
    768         case SIGNATURE_TYPE_GUID:
    769             CatPrint(Str, L"HD(Part%d,Sig%g)",
    770                 Hd->PartitionNumber,
    771                 (EFI_GUID *) &(Hd->Signature[0])
    772                 );
    773             break;
    774         default:
    775             CatPrint(Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)",
    776                 Hd->PartitionNumber,
    777                 Hd->MBRType,
    778                 Hd->SignatureType
    779                 );
    780             break;
    781     }
    782 }
    783 
    784 VOID
    785 _DevPathCDROM (
    786     IN OUT POOL_PRINT       *Str,
    787     IN VOID                 *DevPath
    788     )
    789 {
    790     CDROM_DEVICE_PATH       *Cd;
    791 
    792     Cd = DevPath;
    793     CatPrint(Str, L"CDROM(Entry%x)", Cd->BootEntry);
    794 }
    795 
    796 VOID
    797 _DevPathFilePath (
    798     IN OUT POOL_PRINT       *Str,
    799     IN VOID                 *DevPath
    800     )
    801 {
    802     FILEPATH_DEVICE_PATH    *Fp;
    803 
    804     Fp = DevPath;
    805     CatPrint(Str, L"%s", Fp->PathName);
    806 }
    807 
    808 VOID
    809 _DevPathMediaProtocol (
    810     IN OUT POOL_PRINT       *Str,
    811     IN VOID                 *DevPath
    812     )
    813 {
    814     MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
    815 
    816     MediaProt = DevPath;
    817     CatPrint(Str, L"%g", &MediaProt->Protocol);
    818 }
    819 
    820 VOID
    821 _DevPathBssBss (
    822     IN OUT POOL_PRINT       *Str,
    823     IN VOID                 *DevPath
    824     )
    825 {
    826     BBS_BBS_DEVICE_PATH     *Bss;
    827     CHAR16                  *Type;
    828 
    829     Bss = DevPath;
    830     switch (Bss->DeviceType) {
    831     case BBS_TYPE_FLOPPY:               Type = L"Floppy";       break;
    832     case BBS_TYPE_HARDDRIVE:            Type = L"Harddrive";    break;
    833     case BBS_TYPE_CDROM:                Type = L"CDROM";        break;
    834     case BBS_TYPE_PCMCIA:               Type = L"PCMCIA";       break;
    835     case BBS_TYPE_USB:                  Type = L"Usb";          break;
    836     case BBS_TYPE_EMBEDDED_NETWORK:     Type = L"Net";          break;
    837     default:                            Type = L"?";            break;
    838     }
    839 
    840     CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
    841 }
    842 
    843 
    844 VOID
    845 _DevPathEndInstance (
    846     IN OUT POOL_PRINT       *Str,
    847     IN VOID                 *DevPath
    848     )
    849 {
    850     CatPrint(Str, L",");
    851 }
    852 
    853 VOID
    854 _DevPathNodeUnknown (
    855     IN OUT POOL_PRINT       *Str,
    856     IN VOID                 *DevPath
    857     )
    858 {
    859     CatPrint(Str, L"?");
    860 }
    861 
    862 
    863 struct {
    864     UINT8   Type;
    865     UINT8   SubType;
    866     VOID    (*Function)(POOL_PRINT *, VOID *);
    867 } DevPathTable[] = {
    868 	{ HARDWARE_DEVICE_PATH,   HW_PCI_DP,                        _DevPathPci},
    869 	{ HARDWARE_DEVICE_PATH,   HW_PCCARD_DP,                     _DevPathPccard},
    870 	{ HARDWARE_DEVICE_PATH,   HW_MEMMAP_DP,                     _DevPathMemMap},
    871 	{ HARDWARE_DEVICE_PATH,   HW_VENDOR_DP,                     _DevPathVendor},
    872 	{ HARDWARE_DEVICE_PATH,   HW_CONTROLLER_DP,                 _DevPathController},
    873 	{ ACPI_DEVICE_PATH,       ACPI_DP,                          _DevPathAcpi},
    874 	{ MESSAGING_DEVICE_PATH,  MSG_ATAPI_DP,                     _DevPathAtapi},
    875 	{ MESSAGING_DEVICE_PATH,  MSG_SCSI_DP,                      _DevPathScsi},
    876 	{ MESSAGING_DEVICE_PATH,  MSG_FIBRECHANNEL_DP,              _DevPathFibre},
    877 	{ MESSAGING_DEVICE_PATH,  MSG_1394_DP,                      _DevPath1394},
    878 	{ MESSAGING_DEVICE_PATH,  MSG_USB_DP,                       _DevPathUsb},
    879 	{ MESSAGING_DEVICE_PATH,  MSG_I2O_DP,                       _DevPathI2O},
    880 	{ MESSAGING_DEVICE_PATH,  MSG_MAC_ADDR_DP,                  _DevPathMacAddr},
    881 	{ MESSAGING_DEVICE_PATH,  MSG_IPv4_DP,                      _DevPathIPv4},
    882 	{ MESSAGING_DEVICE_PATH,  MSG_IPv6_DP,                      _DevPathIPv6},
    883 	{ MESSAGING_DEVICE_PATH,  MSG_INFINIBAND_DP,                _DevPathInfiniBand},
    884 	{ MESSAGING_DEVICE_PATH,  MSG_UART_DP,                      _DevPathUart},
    885 	{ MESSAGING_DEVICE_PATH,  MSG_VENDOR_DP,                    _DevPathVendor},
    886 	{ MEDIA_DEVICE_PATH,      MEDIA_HARDDRIVE_DP,               _DevPathHardDrive},
    887 	{ MEDIA_DEVICE_PATH,      MEDIA_CDROM_DP,                   _DevPathCDROM},
    888 	{ MEDIA_DEVICE_PATH,      MEDIA_VENDOR_DP,                  _DevPathVendor},
    889 	{ MEDIA_DEVICE_PATH,      MEDIA_FILEPATH_DP,                _DevPathFilePath},
    890 	{ MEDIA_DEVICE_PATH,      MEDIA_PROTOCOL_DP,                _DevPathMediaProtocol},
    891 	{ BBS_DEVICE_PATH,        BBS_BBS_DP,                       _DevPathBssBss},
    892 	{ END_DEVICE_PATH_TYPE,   END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
    893 	{ 0,                      0,                          NULL}
    894 };
    895 
    896 
    897 CHAR16 *
    898 DevicePathToStr (
    899     EFI_DEVICE_PATH     *DevPath
    900     )
    901 /*++
    902 
    903     Turns the Device Path into a printable string.  Allcoates
    904     the string from pool.  The caller must FreePool the returned
    905     string.
    906 
    907 --*/
    908 {
    909     POOL_PRINT          Str;
    910     EFI_DEVICE_PATH     *DevPathNode;
    911     VOID                (*DumpNode)(POOL_PRINT *, VOID *);
    912     UINTN               Index, NewSize;
    913 
    914     ZeroMem(&Str, sizeof(Str));
    915 
    916     //
    917     // Unpacked the device path
    918     //
    919 
    920     DevPath = UnpackDevicePath(DevPath);
    921     ASSERT (DevPath);
    922 
    923 
    924     //
    925     // Process each device path node
    926     //
    927 
    928     DevPathNode = DevPath;
    929     while (!IsDevicePathEnd(DevPathNode)) {
    930         //
    931         // Find the handler to dump this device path node
    932         //
    933 
    934         DumpNode = NULL;
    935         for (Index = 0; DevPathTable[Index].Function; Index += 1) {
    936 
    937             if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
    938                 DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
    939                 DumpNode = DevPathTable[Index].Function;
    940                 break;
    941             }
    942         }
    943 
    944         //
    945         // If not found, use a generic function
    946         //
    947 
    948         if (!DumpNode) {
    949             DumpNode = _DevPathNodeUnknown;
    950         }
    951 
    952         //
    953         //  Put a path seperator in if needed
    954         //
    955 
    956         if (Str.len  &&  DumpNode != _DevPathEndInstance) {
    957             CatPrint (&Str, L"/");
    958         }
    959 
    960         //
    961         // Print this node of the device path
    962         //
    963 
    964         DumpNode (&Str, DevPathNode);
    965 
    966         //
    967         // Next device path node
    968         //
    969 
    970         DevPathNode = NextDevicePathNode(DevPathNode);
    971     }
    972 
    973     //
    974     // Shrink pool used for string allocation
    975     //
    976 
    977     FreePool (DevPath);
    978     NewSize = (Str.len + 1) * sizeof(CHAR16);
    979     Str.str = ReallocatePool (Str.str, NewSize, NewSize);
    980     Str.str[Str.len] = 0;
    981     return Str.str;
    982 }
    983 
    984 BOOLEAN
    985 LibMatchDevicePaths (
    986     IN  EFI_DEVICE_PATH *Multi,
    987     IN  EFI_DEVICE_PATH *Single
    988     )
    989 {
    990     EFI_DEVICE_PATH     *DevicePath, *DevicePathInst;
    991     UINTN               Size;
    992 
    993     if (!Multi || !Single) {
    994         return FALSE;
    995     }
    996 
    997     DevicePath = Multi;
    998     while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
    999         if (CompareMem (Single, DevicePathInst, Size) == 0) {
   1000             return TRUE;
   1001         }
   1002     }
   1003     return FALSE;
   1004 }
   1005 
   1006 EFI_DEVICE_PATH *
   1007 LibDuplicateDevicePathInstance (
   1008     IN EFI_DEVICE_PATH  *DevPath
   1009     )
   1010 {
   1011     EFI_DEVICE_PATH     *NewDevPath,*DevicePathInst,*Temp;
   1012     UINTN               Size;
   1013 
   1014     //
   1015     // get the size of an instance from the input
   1016     //
   1017 
   1018     Temp = DevPath;
   1019     DevicePathInst = DevicePathInstance (&Temp, &Size);
   1020 
   1021     //
   1022     // Make a copy and set proper end type
   1023     //
   1024     NewDevPath = NULL;
   1025     if (Size) {
   1026         NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
   1027     }
   1028 
   1029     if (NewDevPath) {
   1030         CopyMem (NewDevPath, DevicePathInst, Size);
   1031         Temp = NextDevicePathNode(NewDevPath);
   1032         SetDevicePathEndNode(Temp);
   1033     }
   1034 
   1035     return NewDevPath;
   1036 }
   1037 
   1038