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