Subversion Repositories HelenOS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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 = BS->HandleProtocol (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 = BS->LocateDevicePath (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 = BS->HandleProtocol (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;    
  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.