Home | History | Annotate | Download | only in UefiShellCommandLib
      1 /** @file
      2   Main file for support of shell consist mapping.
      3 
      4   Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution. The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 **/
     13 
     14 #include "UefiShellCommandLib.h"
     15 #include <Library/DevicePathLib.h>
     16 #include <Library/SortLib.h>
     17 #include <Library/UefiLib.h>
     18 #include <Protocol/UsbIo.h>
     19 #include <Protocol/BlockIo.h>
     20 #include <Protocol/SimpleFileSystem.h>
     21 
     22 
     23 
     24 typedef enum {
     25   MTDTypeUnknown,
     26   MTDTypeFloppy,
     27   MTDTypeHardDisk,
     28   MTDTypeCDRom,
     29   MTDTypeEnd
     30 } MTD_TYPE;
     31 
     32 typedef struct {
     33   CHAR16  *Str;
     34   UINTN   Len;
     35 } POOL_PRINT;
     36 
     37 typedef struct {
     38   UINTN       Hi;
     39   MTD_TYPE    Mtd;
     40   POOL_PRINT  Csd;
     41   BOOLEAN     Digital;
     42 } DEVICE_CONSIST_MAPPING_INFO;
     43 
     44 typedef struct {
     45   MTD_TYPE  MTDType;
     46   CHAR16    *Name;
     47 } MTD_NAME;
     48 
     49 /**
     50   Serial Decode function.
     51 
     52   @param  DevPath          The Device path info.
     53   @param  MapInfo          The map info.
     54   @param  OrigDevPath      The original device path protocol.
     55 
     56 **/
     57 typedef
     58 VOID
     59 (EFIAPI *SERIAL_DECODE_FUNCTION) (
     60   EFI_DEVICE_PATH_PROTOCOL    *DevPath,
     61   DEVICE_CONSIST_MAPPING_INFO *MapInfo,
     62   EFI_DEVICE_PATH_PROTOCOL    *OrigDevPath
     63   );
     64 
     65 typedef struct {
     66   UINT8 Type;
     67   UINT8 SubType;
     68   SERIAL_DECODE_FUNCTION SerialFun;
     69   INTN (EFIAPI *CompareFun) (EFI_DEVICE_PATH_PROTOCOL *DevPath, EFI_DEVICE_PATH_PROTOCOL *DevPath2);
     70 } DEV_PATH_CONSIST_MAPPING_TABLE;
     71 
     72 
     73 /**
     74   Concatenates a formatted unicode string to allocated pool.
     75   The caller must free the resulting buffer.
     76 
     77   @param  Str      Tracks the allocated pool, size in use, and amount of pool allocated.
     78   @param  Fmt      The format string
     79   @param  ...      The data will be printed.
     80 
     81   @return Allocated buffer with the formatted string printed in it.
     82           The caller must free the allocated buffer.
     83           The buffer allocation is not packed.
     84 
     85 **/
     86 CHAR16 *
     87 EFIAPI
     88 CatPrint (
     89   IN OUT POOL_PRINT   *Str,
     90   IN CHAR16           *Fmt,
     91   ...
     92   )
     93 {
     94   UINT16  *AppendStr;
     95   VA_LIST Args;
     96   UINTN   StringSize;
     97 
     98   AppendStr = AllocateZeroPool (0x1000);
     99   if (AppendStr == NULL) {
    100     ASSERT(FALSE);
    101     return Str->Str;
    102   }
    103 
    104   VA_START (Args, Fmt);
    105   UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
    106   VA_END (Args);
    107   if (NULL == Str->Str) {
    108     StringSize   = StrSize (AppendStr);
    109     Str->Str  = AllocateZeroPool (StringSize);
    110     ASSERT (Str->Str != NULL);
    111   } else {
    112     StringSize = StrSize (AppendStr);
    113     StringSize += (StrSize (Str->Str) - sizeof (UINT16));
    114 
    115     Str->Str = ReallocatePool (
    116                 StrSize (Str->Str),
    117                 StringSize,
    118                 Str->Str
    119                );
    120     ASSERT (Str->Str != NULL);
    121   }
    122 
    123   StrCatS (Str->Str, StringSize/sizeof(CHAR16), AppendStr);
    124   Str->Len = StringSize;
    125 
    126   FreePool (AppendStr);
    127   return Str->Str;
    128 }
    129 
    130 MTD_NAME  mMTDName[] = {
    131   {
    132     MTDTypeUnknown,
    133     L"F"
    134   },
    135   {
    136     MTDTypeFloppy,
    137     L"FP"
    138   },
    139   {
    140     MTDTypeHardDisk,
    141     L"HD"
    142   },
    143   {
    144     MTDTypeCDRom,
    145     L"CD"
    146   },
    147   {
    148     MTDTypeEnd,
    149     NULL
    150   }
    151 };
    152 
    153 /**
    154   Function to append a 64 bit number / 25 onto the string.
    155 
    156   @param[in, out] Str          The string so append onto.
    157   @param[in]      Num          The number to divide and append.
    158 
    159   @retval EFI_INVALID_PARAMETER   A parameter was NULL.
    160   @retval EFI_SUCCESS             The appending was successful.
    161 **/
    162 EFI_STATUS
    163 EFIAPI
    164 AppendCSDNum2 (
    165   IN OUT POOL_PRINT       *Str,
    166   IN UINT64               Num
    167   )
    168 {
    169   UINT64  Result;
    170   UINT32   Rem;
    171 
    172   if (Str == NULL) {
    173     return (EFI_INVALID_PARAMETER);
    174   }
    175 
    176   Result = DivU64x32Remainder (Num, 25, &Rem);
    177   if (Result > 0) {
    178     AppendCSDNum2 (Str, Result);
    179   }
    180 
    181   CatPrint (Str, L"%c", Rem + 'a');
    182   return (EFI_SUCCESS);
    183 }
    184 
    185 /**
    186   Function to append a 64 bit number onto the mapping info.
    187 
    188   @param[in, out] MappingItem  The mapping info object to append onto.
    189   @param[in]      Num          The info to append.
    190 
    191   @retval EFI_INVALID_PARAMETER   A parameter was NULL.
    192   @retval EFI_SUCCESS             The appending was successful.
    193 **/
    194 EFI_STATUS
    195 EFIAPI
    196 AppendCSDNum (
    197   IN OUT DEVICE_CONSIST_MAPPING_INFO            *MappingItem,
    198   IN     UINT64                                 Num
    199   )
    200 {
    201   if (MappingItem == NULL) {
    202     return EFI_INVALID_PARAMETER;
    203   }
    204 
    205   if (MappingItem->Digital) {
    206     CatPrint (&MappingItem->Csd, L"%ld", Num);
    207   } else {
    208     AppendCSDNum2 (&MappingItem->Csd, Num);
    209   }
    210 
    211   MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital);
    212 
    213   return (EFI_SUCCESS);
    214 }
    215 
    216 /**
    217   Function to append string into the mapping info.
    218 
    219   @param[in, out] MappingItem  The mapping info object to append onto.
    220   @param[in]      Str          The info to append.
    221 
    222   @retval EFI_INVALID_PARAMETER   A parameter was NULL.
    223   @retval EFI_SUCCESS             The appending was successful.
    224 **/
    225 EFI_STATUS
    226 EFIAPI
    227 AppendCSDStr (
    228   IN OUT DEVICE_CONSIST_MAPPING_INFO            *MappingItem,
    229   IN     CHAR16                                 *Str
    230   )
    231 {
    232   CHAR16  *Index;
    233 
    234   if (Str == NULL || MappingItem == NULL) {
    235     return (EFI_INVALID_PARAMETER);
    236   }
    237 
    238   if (MappingItem->Digital) {
    239     //
    240     // To aVOID mult-meaning, the mapping is:
    241     //  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    242     //  0  16 2  3  4  5  6  7  8  9  10 11 12 13 14 15
    243     //
    244     for (Index = Str; *Index != 0; Index++) {
    245       switch (*Index) {
    246       case '0':
    247       case '2':
    248       case '3':
    249       case '4':
    250       case '5':
    251       case '6':
    252       case '7':
    253       case '8':
    254       case '9':
    255         CatPrint (&MappingItem->Csd, L"%c", *Index);
    256         break;
    257 
    258       case '1':
    259         CatPrint (&MappingItem->Csd, L"16");
    260         break;
    261 
    262       case 'a':
    263       case 'b':
    264       case 'c':
    265       case 'd':
    266       case 'e':
    267       case 'f':
    268         CatPrint (&MappingItem->Csd, L"1%c", *Index - 'a' + '0');
    269         break;
    270 
    271       case 'A':
    272       case 'B':
    273       case 'C':
    274       case 'D':
    275       case 'E':
    276       case 'F':
    277         CatPrint (&MappingItem->Csd, L"1%c", *Index - 'A' + '0');
    278         break;
    279       }
    280     }
    281   } else {
    282     for (Index = Str; *Index != 0; Index++) {
    283       //
    284       //  The mapping is:
    285       //  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    286       //  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p
    287       //
    288       if (*Index >= '0' && *Index <= '9') {
    289         CatPrint (&MappingItem->Csd, L"%c", *Index - '0' + 'a');
    290       } else if (*Index >= 'a' && *Index <= 'f') {
    291         CatPrint (&MappingItem->Csd, L"%c", *Index - 'a' + 'k');
    292       } else if (*Index >= 'A' && *Index <= 'F') {
    293         CatPrint (&MappingItem->Csd, L"%c", *Index - 'A' + 'k');
    294       }
    295     }
    296   }
    297 
    298   MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital);
    299 
    300   return (EFI_SUCCESS);
    301 }
    302 
    303 /**
    304   Function to append a Guid to the mapping item.
    305 
    306   @param[in, out] MappingItem  The item to append onto.
    307   @param[in]      Guid         The guid to append.
    308 
    309   @retval EFI_SUCCESS           The appending operation was successful.
    310   @retval EFI_INVALID_PARAMETER A parameter was NULL.
    311 **/
    312 EFI_STATUS
    313 EFIAPI
    314 AppendCSDGuid (
    315   DEVICE_CONSIST_MAPPING_INFO            *MappingItem,
    316   EFI_GUID                               *Guid
    317   )
    318 {
    319   CHAR16  Buffer[64];
    320 
    321   if (Guid == NULL || MappingItem == NULL) {
    322     return (EFI_INVALID_PARAMETER);
    323   }
    324 
    325   UnicodeSPrint (
    326     Buffer,
    327     0,
    328     L"%g",
    329     Guid
    330    );
    331 
    332   AppendCSDStr (MappingItem, Buffer);
    333 
    334   return (EFI_SUCCESS);
    335 }
    336 
    337 /**
    338   Function to compare 2 APCI device paths.
    339 
    340   @param[in] DevicePath1        The first device path to compare.
    341   @param[in] DevicePath2        The second device path to compare.
    342 
    343   @retval 0 The device paths represent the same device.
    344   @return   Non zero if the devices are different, zero otherwise.
    345 **/
    346 INTN
    347 EFIAPI
    348 DevPathCompareAcpi (
    349   IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath1,
    350   IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath2
    351   )
    352 {
    353   ACPI_HID_DEVICE_PATH  *Acpi1;
    354   ACPI_HID_DEVICE_PATH  *Acpi2;
    355 
    356   if (DevicePath1 == NULL || DevicePath2 == NULL) {
    357     return (-2);
    358   }
    359 
    360   Acpi1 = (ACPI_HID_DEVICE_PATH *) DevicePath1;
    361   Acpi2 = (ACPI_HID_DEVICE_PATH *) DevicePath2;
    362   if (Acpi1->HID > Acpi2->HID || (Acpi1->HID == Acpi2->HID && Acpi1->UID > Acpi2->UID)) {
    363     return 1;
    364   }
    365 
    366   if (Acpi1->HID == Acpi2->HID && Acpi1->UID == Acpi2->UID) {
    367     return 0;
    368   }
    369 
    370   return -1;
    371 }
    372 
    373 /**
    374   Function to compare 2 PCI device paths.
    375 
    376   @param[in] DevicePath1        The first device path to compare.
    377   @param[in] DevicePath2        The second device path to compare.
    378 
    379   @retval 0 The device paths represent the same device.
    380   @return   Non zero if the devices are different, zero otherwise.
    381 **/
    382 INTN
    383 EFIAPI
    384 DevPathComparePci (
    385   IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath1,
    386   IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath2
    387   )
    388 {
    389   PCI_DEVICE_PATH *Pci1;
    390   PCI_DEVICE_PATH *Pci2;
    391 
    392   ASSERT(DevicePath1 != NULL);
    393   ASSERT(DevicePath2 != NULL);
    394 
    395   Pci1  = (PCI_DEVICE_PATH *) DevicePath1;
    396   Pci2  = (PCI_DEVICE_PATH *) DevicePath2;
    397   if (Pci1->Device > Pci2->Device || (Pci1->Device == Pci2->Device && Pci1->Function > Pci2->Function)) {
    398     return 1;
    399   }
    400 
    401   if (Pci1->Device == Pci2->Device && Pci1->Function == Pci2->Function) {
    402     return 0;
    403   }
    404 
    405   return -1;
    406 }
    407 
    408 /**
    409   Do a comparison on 2 device paths.
    410 
    411   @param[in] DevicePath1   The first device path.
    412   @param[in] DevicePath2   The second device path.
    413 
    414   @retval 0 The 2 device paths are the same.
    415   @retval <0  DevicePath2 is greater than DevicePath1.
    416   @retval >0  DevicePath1 is greater than DevicePath2.
    417 **/
    418 INTN
    419 EFIAPI
    420 DevPathCompareDefault (
    421   IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath1,
    422   IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath2
    423   )
    424 {
    425   UINTN DevPathSize1;
    426   UINTN DevPathSize2;
    427 
    428   ASSERT(DevicePath1 != NULL);
    429   ASSERT(DevicePath2 != NULL);
    430 
    431   DevPathSize1  = DevicePathNodeLength (DevicePath1);
    432   DevPathSize2  = DevicePathNodeLength (DevicePath2);
    433   if (DevPathSize1 > DevPathSize2) {
    434     return 1;
    435   } else if (DevPathSize1 < DevPathSize2) {
    436     return -1;
    437   } else {
    438     return CompareMem (DevicePath1, DevicePath2, DevPathSize1);
    439   }
    440 }
    441 
    442 /**
    443   DevicePathNode must be SerialHDD Channel type and this will populate the MappingItem.
    444 
    445   @param[in] DevicePathNode   The node to get info on.
    446   @param[in] MappingItem      The info item to populate.
    447   @param[in] DevicePath       Ignored.
    448 **/
    449 VOID
    450 EFIAPI
    451 DevPathSerialHardDrive (
    452   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    453   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    454   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    455   )
    456 {
    457   HARDDRIVE_DEVICE_PATH *Hd;
    458 
    459   ASSERT(DevicePathNode != NULL);
    460   ASSERT(MappingItem != NULL);
    461 
    462   Hd = (HARDDRIVE_DEVICE_PATH *) DevicePathNode;
    463   if (MappingItem->Mtd == MTDTypeUnknown) {
    464     MappingItem->Mtd = MTDTypeHardDisk;
    465   }
    466 
    467   AppendCSDNum (MappingItem, Hd->PartitionNumber);
    468 }
    469 
    470 /**
    471   DevicePathNode must be SerialAtapi Channel type and this will populate the MappingItem.
    472 
    473   @param[in] DevicePathNode   The node to get info on.
    474   @param[in] MappingItem      The info item to populate.
    475   @param[in] DevicePath       Ignored.
    476 **/
    477 VOID
    478 EFIAPI
    479 DevPathSerialAtapi (
    480   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    481   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    482   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    483   )
    484 {
    485   ATAPI_DEVICE_PATH *Atapi;
    486 
    487   ASSERT(DevicePathNode != NULL);
    488   ASSERT(MappingItem != NULL);
    489 
    490   Atapi = (ATAPI_DEVICE_PATH *) DevicePathNode;
    491   AppendCSDNum (MappingItem, (Atapi->PrimarySecondary * 2 + Atapi->SlaveMaster));
    492 }
    493 
    494 /**
    495   DevicePathNode must be SerialCDROM Channel type and this will populate the MappingItem.
    496 
    497   @param[in] DevicePathNode   The node to get info on.
    498   @param[in] MappingItem      The info item to populate.
    499   @param[in] DevicePath       Ignored.
    500 **/
    501 VOID
    502 EFIAPI
    503 DevPathSerialCdRom (
    504   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    505   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    506   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    507   )
    508 {
    509   CDROM_DEVICE_PATH *Cd;
    510 
    511   ASSERT(DevicePathNode != NULL);
    512   ASSERT(MappingItem != NULL);
    513 
    514   Cd                = (CDROM_DEVICE_PATH *) DevicePathNode;
    515   MappingItem->Mtd  = MTDTypeCDRom;
    516   AppendCSDNum (MappingItem, Cd->BootEntry);
    517 }
    518 
    519 /**
    520   DevicePathNode must be SerialFibre Channel type and this will populate the MappingItem.
    521 
    522   @param[in] DevicePathNode   The node to get info on.
    523   @param[in] MappingItem      The info item to populate.
    524   @param[in] DevicePath       Ignored.
    525 **/
    526 VOID
    527 EFIAPI
    528 DevPathSerialFibre (
    529   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    530   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    531   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    532   )
    533 {
    534   FIBRECHANNEL_DEVICE_PATH  *Fibre;
    535 
    536   ASSERT(DevicePathNode != NULL);
    537   ASSERT(MappingItem != NULL);
    538 
    539   Fibre = (FIBRECHANNEL_DEVICE_PATH *) DevicePathNode;
    540   AppendCSDNum (MappingItem, Fibre->WWN);
    541   AppendCSDNum (MappingItem, Fibre->Lun);
    542 }
    543 
    544 /**
    545   DevicePathNode must be SerialUart type and this will populate the MappingItem.
    546 
    547   @param[in] DevicePathNode   The node to get info on.
    548   @param[in] MappingItem      The info item to populate.
    549   @param[in] DevicePath       Ignored.
    550 **/
    551 VOID
    552 EFIAPI
    553 DevPathSerialUart (
    554   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    555   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    556   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    557   )
    558 {
    559   UART_DEVICE_PATH  *Uart;
    560 
    561   ASSERT(DevicePathNode != NULL);
    562   ASSERT(MappingItem != NULL);
    563 
    564   Uart = (UART_DEVICE_PATH *) DevicePathNode;
    565   AppendCSDNum (MappingItem, Uart->BaudRate);
    566   AppendCSDNum (MappingItem, Uart->DataBits);
    567   AppendCSDNum (MappingItem, Uart->Parity);
    568   AppendCSDNum (MappingItem, Uart->StopBits);
    569 }
    570 
    571 /**
    572   DevicePathNode must be SerialUSB type and this will populate the MappingItem.
    573 
    574   @param[in] DevicePathNode   The node to get info on.
    575   @param[in] MappingItem      The info item to populate.
    576   @param[in] DevicePath       Ignored.
    577 **/
    578 VOID
    579 EFIAPI
    580 DevPathSerialUsb (
    581   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    582   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    583   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    584   )
    585 {
    586   USB_DEVICE_PATH           *Usb;
    587   EFI_USB_IO_PROTOCOL       *UsbIo;
    588   EFI_HANDLE                TempHandle;
    589   EFI_STATUS                Status;
    590   USB_INTERFACE_DESCRIPTOR  InterfaceDesc;
    591 
    592 
    593   ASSERT(DevicePathNode != NULL);
    594   ASSERT(MappingItem != NULL);
    595 
    596   Usb = (USB_DEVICE_PATH *) DevicePathNode;
    597   AppendCSDNum (MappingItem, Usb->ParentPortNumber);
    598   AppendCSDNum (MappingItem, Usb->InterfaceNumber);
    599 
    600   if (PcdGetBool(PcdUsbExtendedDecode)) {
    601     Status = gBS->LocateDevicePath( &gEfiUsbIoProtocolGuid, &DevicePath, &TempHandle );
    602     UsbIo = NULL;
    603     if (!EFI_ERROR(Status)) {
    604       Status = gBS->OpenProtocol(TempHandle, &gEfiUsbIoProtocolGuid, (VOID**)&UsbIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    605     }
    606 
    607     if (!EFI_ERROR(Status)) {
    608       ASSERT(UsbIo != NULL);
    609       Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDesc);
    610       if (!EFI_ERROR(Status)) {
    611         if (InterfaceDesc.InterfaceClass == USB_MASS_STORE_CLASS && MappingItem->Mtd == MTDTypeUnknown) {
    612           switch (InterfaceDesc.InterfaceSubClass){
    613             case USB_MASS_STORE_SCSI:
    614               MappingItem->Mtd = MTDTypeHardDisk;
    615               break;
    616             case USB_MASS_STORE_8070I:
    617             case USB_MASS_STORE_UFI:
    618               MappingItem->Mtd = MTDTypeFloppy;
    619               break;
    620             case USB_MASS_STORE_8020I:
    621               MappingItem->Mtd  = MTDTypeCDRom;
    622               break;
    623           }
    624         }
    625       }
    626     }
    627   }
    628 }
    629 
    630 /**
    631   DevicePathNode must be SerialVendor type and this will populate the MappingItem.
    632 
    633   @param[in] DevicePathNode   The node to get info on.
    634   @param[in] MappingItem      The info item to populate.
    635   @param[in] DevicePath       Ignored.
    636 
    637 **/
    638 VOID
    639 EFIAPI
    640 DevPathSerialVendor (
    641   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    642   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    643   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    644   )
    645 {
    646   VENDOR_DEVICE_PATH  *Vendor;
    647   SAS_DEVICE_PATH     *Sas;
    648   UINTN               TargetNameLength;
    649   UINTN               Index;
    650   CHAR16              *Buffer;
    651 
    652   if (DevicePathNode == NULL || MappingItem == NULL) {
    653     return;
    654   }
    655 
    656   Vendor = (VENDOR_DEVICE_PATH *) DevicePathNode;
    657   AppendCSDGuid (MappingItem, &Vendor->Guid);
    658 
    659   if (CompareGuid (&gEfiSasDevicePathGuid, &Vendor->Guid)) {
    660     Sas = (SAS_DEVICE_PATH *) Vendor;
    661     AppendCSDNum (MappingItem, Sas->SasAddress);
    662     AppendCSDNum (MappingItem, Sas->Lun);
    663     AppendCSDNum (MappingItem, Sas->DeviceTopology);
    664     AppendCSDNum (MappingItem, Sas->RelativeTargetPort);
    665   } else {
    666     TargetNameLength = MIN(DevicePathNodeLength (DevicePathNode) - sizeof (VENDOR_DEVICE_PATH), PcdGet32(PcdShellVendorExtendedDecode));
    667     if (TargetNameLength != 0) {
    668       //
    669       // String is 2 chars per data byte, plus NULL terminator
    670       //
    671       Buffer = AllocateZeroPool (((TargetNameLength * 2) + 1) * sizeof(CHAR16));
    672       ASSERT(Buffer != NULL);
    673       if (Buffer == NULL) {
    674         return;
    675   }
    676 
    677       //
    678       // Build the string data
    679       //
    680       for (Index = 0; Index < TargetNameLength; Index++) {
    681         Buffer = CatSPrint (Buffer, L"%02x", *((UINT8*)Vendor + sizeof (VENDOR_DEVICE_PATH) + Index));
    682 }
    683 
    684       //
    685       // Append the new data block
    686       //
    687       AppendCSDStr (MappingItem, Buffer);
    688 
    689       FreePool(Buffer);
    690     }
    691   }
    692 }
    693 
    694 /**
    695   DevicePathNode must be SerialLun type and this will populate the MappingItem.
    696 
    697   @param[in] DevicePathNode   The node to get info on.
    698   @param[in] MappingItem      The info item to populate.
    699   @param[in] DevicePath       Ignored.
    700 **/
    701 VOID
    702 EFIAPI
    703 DevPathSerialLun (
    704   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    705   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    706   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    707   )
    708 {
    709   DEVICE_LOGICAL_UNIT_DEVICE_PATH *Lun;
    710 
    711   ASSERT(DevicePathNode != NULL);
    712   ASSERT(MappingItem != NULL);
    713 
    714   Lun = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) DevicePathNode;
    715   AppendCSDNum (MappingItem, Lun->Lun);
    716 }
    717 
    718 /**
    719   DevicePathNode must be SerialSata type and this will populate the MappingItem.
    720 
    721   @param[in] DevicePathNode   The node to get info on.
    722   @param[in] MappingItem      The info item to populate.
    723   @param[in] DevicePath       Ignored.
    724 **/
    725 VOID
    726 EFIAPI
    727 DevPathSerialSata (
    728   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    729   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    730   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    731   )
    732 {
    733   SATA_DEVICE_PATH  *Sata;
    734 
    735   ASSERT(DevicePathNode != NULL);
    736   ASSERT(MappingItem != NULL);
    737 
    738   Sata = (SATA_DEVICE_PATH  *) DevicePathNode;
    739   AppendCSDNum (MappingItem, Sata->HBAPortNumber);
    740   AppendCSDNum (MappingItem, Sata->PortMultiplierPortNumber);
    741   AppendCSDNum (MappingItem, Sata->Lun);
    742 }
    743 
    744 /**
    745   DevicePathNode must be SerialSCSI type and this will populate the MappingItem.
    746 
    747   @param[in] DevicePathNode   The node to get info on.
    748   @param[in] MappingItem      The info item to populate.
    749   @param[in] DevicePath       Ignored.
    750 **/
    751 VOID
    752 EFIAPI
    753 DevPathSerialIScsi (
    754   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    755   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    756   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    757   )
    758 {
    759   ISCSI_DEVICE_PATH  *IScsi;
    760   UINT8              *IScsiTargetName;
    761   CHAR16             *TargetName;
    762   UINTN              TargetNameLength;
    763   UINTN              Index;
    764 
    765   ASSERT(DevicePathNode != NULL);
    766   ASSERT(MappingItem != NULL);
    767 
    768   if (PcdGetBool(PcdShellDecodeIScsiMapNames)) {
    769     IScsi = (ISCSI_DEVICE_PATH  *) DevicePathNode;
    770     AppendCSDNum (MappingItem, IScsi->NetworkProtocol);
    771     AppendCSDNum (MappingItem, IScsi->LoginOption);
    772     AppendCSDNum (MappingItem, IScsi->Lun);
    773     AppendCSDNum (MappingItem, IScsi->TargetPortalGroupTag);
    774     TargetNameLength = DevicePathNodeLength (DevicePathNode) - sizeof (ISCSI_DEVICE_PATH);
    775     if (TargetNameLength > 0) {
    776       TargetName = AllocateZeroPool ((TargetNameLength + 1) * sizeof (CHAR16));
    777       if (TargetName != NULL) {
    778         IScsiTargetName = (UINT8 *) (IScsi + 1);
    779         for (Index = 0; Index < TargetNameLength; Index++) {
    780           TargetName[Index] = (CHAR16) IScsiTargetName[Index];
    781         }
    782         AppendCSDStr (MappingItem, TargetName);
    783         FreePool (TargetName);
    784       }
    785     }
    786   }
    787 }
    788 
    789 /**
    790   DevicePathNode must be SerialI20 type and this will populate the MappingItem.
    791 
    792   @param[in] DevicePathNode   The node to get info on.
    793   @param[in] MappingItem      The info item to populate.
    794   @param[in] DevicePath       Ignored.
    795 **/
    796 VOID
    797 EFIAPI
    798 DevPathSerialI2O (
    799   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    800   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    801   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    802   )
    803 {
    804   I2O_DEVICE_PATH *DevicePath_I20;
    805 
    806   ASSERT(DevicePathNode != NULL);
    807   ASSERT(MappingItem != NULL);
    808 
    809   DevicePath_I20 = (I2O_DEVICE_PATH *) DevicePathNode;
    810   AppendCSDNum (MappingItem, DevicePath_I20->Tid);
    811 }
    812 
    813 /**
    814   DevicePathNode must be Mac Address type and this will populate the MappingItem.
    815 
    816   @param[in] DevicePathNode   The node to get info on.
    817   @param[in] MappingItem      The info item to populate.
    818   @param[in] DevicePath       Ignored.
    819 **/
    820 VOID
    821 EFIAPI
    822 DevPathSerialMacAddr (
    823   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    824   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    825   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    826   )
    827 {
    828   MAC_ADDR_DEVICE_PATH  *Mac;
    829   UINTN                 HwAddressSize;
    830   UINTN                 Index;
    831   CHAR16                Buffer[64];
    832   CHAR16                *PBuffer;
    833 
    834   ASSERT(DevicePathNode != NULL);
    835   ASSERT(MappingItem != NULL);
    836 
    837   Mac           = (MAC_ADDR_DEVICE_PATH *) DevicePathNode;
    838 
    839   HwAddressSize = sizeof (EFI_MAC_ADDRESS);
    840   if (Mac->IfType == 0x01 || Mac->IfType == 0x00) {
    841     HwAddressSize = 6;
    842   }
    843 
    844   for (Index = 0, PBuffer = Buffer; Index < HwAddressSize; Index++, PBuffer += 2) {
    845     UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Mac->MacAddress.Addr[Index]);
    846   }
    847 
    848   AppendCSDStr (MappingItem, Buffer);
    849 }
    850 
    851 /**
    852   DevicePathNode must be InfiniBand type and this will populate the MappingItem.
    853 
    854   @param[in] DevicePathNode   The node to get info on.
    855   @param[in] MappingItem      The info item to populate.
    856   @param[in] DevicePath       Ignored.
    857 **/
    858 VOID
    859 EFIAPI
    860 DevPathSerialInfiniBand (
    861   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    862   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    863   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    864   )
    865 {
    866   INFINIBAND_DEVICE_PATH  *InfiniBand;
    867   UINTN                   Index;
    868   CHAR16                  Buffer[64];
    869   CHAR16                  *PBuffer;
    870 
    871   ASSERT(DevicePathNode != NULL);
    872   ASSERT(MappingItem != NULL);
    873 
    874   InfiniBand = (INFINIBAND_DEVICE_PATH *) DevicePathNode;
    875   for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
    876     UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) InfiniBand->PortGid[Index]);
    877   }
    878 
    879   AppendCSDStr (MappingItem, Buffer);
    880   AppendCSDNum (MappingItem, InfiniBand->ServiceId);
    881   AppendCSDNum (MappingItem, InfiniBand->TargetPortId);
    882   AppendCSDNum (MappingItem, InfiniBand->DeviceId);
    883 }
    884 
    885 /**
    886   DevicePathNode must be IPv4 type and this will populate the MappingItem.
    887 
    888   @param[in] DevicePathNode   The node to get info on.
    889   @param[in] MappingItem      The info item to populate.
    890   @param[in] DevicePath       Ignored.
    891 **/
    892 VOID
    893 EFIAPI
    894 DevPathSerialIPv4 (
    895   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    896   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    897   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    898   )
    899 {
    900   IPv4_DEVICE_PATH  *Ip;
    901   CHAR16            Buffer[10];
    902 
    903   ASSERT(DevicePathNode != NULL);
    904   ASSERT(MappingItem != NULL);
    905 
    906   Ip = (IPv4_DEVICE_PATH *) DevicePathNode;
    907   UnicodeSPrint (
    908     Buffer,
    909     0,
    910     L"%02x%02x%02x%02x",
    911     (UINTN) Ip->LocalIpAddress.Addr[0],
    912     (UINTN) Ip->LocalIpAddress.Addr[1],
    913     (UINTN) Ip->LocalIpAddress.Addr[2],
    914     (UINTN) Ip->LocalIpAddress.Addr[3]
    915    );
    916   AppendCSDStr (MappingItem, Buffer);
    917   AppendCSDNum (MappingItem, Ip->LocalPort);
    918   UnicodeSPrint (
    919     Buffer,
    920     0,
    921     L"%02x%02x%02x%02x",
    922     (UINTN) Ip->RemoteIpAddress.Addr[0],
    923     (UINTN) Ip->RemoteIpAddress.Addr[1],
    924     (UINTN) Ip->RemoteIpAddress.Addr[2],
    925     (UINTN) Ip->RemoteIpAddress.Addr[3]
    926    );
    927   AppendCSDStr (MappingItem, Buffer);
    928   AppendCSDNum (MappingItem, Ip->RemotePort);
    929 }
    930 
    931 /**
    932   DevicePathNode must be IPv6 type and this will populate the MappingItem.
    933 
    934   @param[in] DevicePathNode   The node to get info on.
    935   @param[in] MappingItem      The info item to populate.
    936   @param[in] DevicePath       Ignored.
    937 
    938 **/
    939 VOID
    940 EFIAPI
    941 DevPathSerialIPv6 (
    942   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    943   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    944   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    945   )
    946 {
    947   IPv6_DEVICE_PATH  *Ip;
    948   UINTN             Index;
    949   CHAR16            Buffer[64];
    950   CHAR16            *PBuffer;
    951 
    952   ASSERT(DevicePathNode != NULL);
    953   ASSERT(MappingItem != NULL);
    954 
    955   Ip = (IPv6_DEVICE_PATH *) DevicePathNode;
    956   for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
    957     UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->LocalIpAddress.Addr[Index]);
    958   }
    959 
    960   AppendCSDStr (MappingItem, Buffer);
    961   AppendCSDNum (MappingItem, Ip->LocalPort);
    962   for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
    963     UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->RemoteIpAddress.Addr[Index]);
    964   }
    965 
    966   AppendCSDStr (MappingItem, Buffer);
    967   AppendCSDNum (MappingItem, Ip->RemotePort);
    968 }
    969 
    970 /**
    971   DevicePathNode must be SCSI type and this will populate the MappingItem.
    972 
    973   @param[in] DevicePathNode   The node to get info on.
    974   @param[in] MappingItem      The info item to populate.
    975   @param[in] DevicePath       Ignored.
    976 
    977 **/
    978 VOID
    979 EFIAPI
    980 DevPathSerialScsi (
    981   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
    982   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
    983   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
    984   )
    985 {
    986   SCSI_DEVICE_PATH  *Scsi;
    987 
    988   ASSERT(DevicePathNode != NULL);
    989   ASSERT(MappingItem != NULL);
    990 
    991   Scsi = (SCSI_DEVICE_PATH *) DevicePathNode;
    992   AppendCSDNum (MappingItem, Scsi->Pun);
    993   AppendCSDNum (MappingItem, Scsi->Lun);
    994 }
    995 
    996 /**
    997   DevicePathNode must be 1394 type and this will populate the MappingItem.
    998 
    999   @param[in] DevicePathNode   The node to get info on.
   1000   @param[in] MappingItem      The info item to populate.
   1001   @param[in] DevicePath       Ignored.
   1002 **/
   1003 VOID
   1004 EFIAPI
   1005 DevPathSerial1394 (
   1006   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
   1007   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
   1008   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
   1009   )
   1010 {
   1011   F1394_DEVICE_PATH *DevicePath_F1394;
   1012   CHAR16            Buffer[20];
   1013 
   1014   ASSERT(DevicePathNode != NULL);
   1015   ASSERT(MappingItem != NULL);
   1016 
   1017   DevicePath_F1394 = (F1394_DEVICE_PATH *) DevicePathNode;
   1018   UnicodeSPrint (Buffer, 0, L"%lx", DevicePath_F1394->Guid);
   1019   AppendCSDStr (MappingItem, Buffer);
   1020 }
   1021 
   1022 /**
   1023   If the node is floppy type then populate the MappingItem.
   1024 
   1025   @param[in] DevicePathNode   The node to get info on.
   1026   @param[in] MappingItem      The info item to populate.
   1027   @param[in] DevicePath       Ignored.
   1028 **/
   1029 VOID
   1030 EFIAPI
   1031 DevPathSerialAcpi (
   1032   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
   1033   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
   1034   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
   1035   )
   1036 {
   1037   ACPI_HID_DEVICE_PATH  *Acpi;
   1038 
   1039   ASSERT(DevicePathNode != NULL);
   1040   ASSERT(MappingItem != NULL);
   1041 
   1042   Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
   1043   if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
   1044     if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
   1045       MappingItem->Mtd = MTDTypeFloppy;
   1046       AppendCSDNum (MappingItem, Acpi->UID);
   1047     }
   1048   }
   1049 }
   1050 
   1051 /**
   1052   Empty function used for unknown devices.
   1053 
   1054   @param[in] DevicePathNode       Ignored.
   1055   @param[in] MappingItem          Ignored.
   1056   @param[in] DevicePath           Ignored.
   1057 
   1058   Does nothing.
   1059 **/
   1060 VOID
   1061 EFIAPI
   1062 DevPathSerialDefault (
   1063   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,
   1064   IN DEVICE_CONSIST_MAPPING_INFO  *MappingItem,
   1065   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
   1066   )
   1067 {
   1068   return;
   1069 }
   1070 
   1071 DEV_PATH_CONSIST_MAPPING_TABLE  DevPathConsistMappingTable[] = {
   1072   {
   1073     HARDWARE_DEVICE_PATH,
   1074     HW_PCI_DP,
   1075     DevPathSerialDefault,
   1076     DevPathComparePci
   1077   },
   1078   {
   1079     ACPI_DEVICE_PATH,
   1080     ACPI_DP,
   1081     DevPathSerialAcpi,
   1082     DevPathCompareAcpi
   1083   },
   1084   {
   1085     MESSAGING_DEVICE_PATH,
   1086     MSG_ATAPI_DP,
   1087     DevPathSerialAtapi,
   1088     DevPathCompareDefault
   1089   },
   1090   {
   1091     MESSAGING_DEVICE_PATH,
   1092     MSG_SCSI_DP,
   1093     DevPathSerialScsi,
   1094     DevPathCompareDefault
   1095   },
   1096   {
   1097     MESSAGING_DEVICE_PATH,
   1098     MSG_FIBRECHANNEL_DP,
   1099     DevPathSerialFibre,
   1100     DevPathCompareDefault
   1101   },
   1102   {
   1103     MESSAGING_DEVICE_PATH,
   1104     MSG_1394_DP,
   1105     DevPathSerial1394,
   1106     DevPathCompareDefault
   1107   },
   1108   {
   1109     MESSAGING_DEVICE_PATH,
   1110     MSG_USB_DP,
   1111     DevPathSerialUsb,
   1112     DevPathCompareDefault
   1113   },
   1114   {
   1115     MESSAGING_DEVICE_PATH,
   1116     MSG_I2O_DP,
   1117     DevPathSerialI2O,
   1118     DevPathCompareDefault
   1119   },
   1120   {
   1121     MESSAGING_DEVICE_PATH,
   1122     MSG_MAC_ADDR_DP,
   1123     DevPathSerialMacAddr,
   1124     DevPathCompareDefault
   1125   },
   1126   {
   1127     MESSAGING_DEVICE_PATH,
   1128     MSG_IPv4_DP,
   1129     DevPathSerialIPv4,
   1130     DevPathCompareDefault
   1131   },
   1132   {
   1133     MESSAGING_DEVICE_PATH,
   1134     MSG_IPv6_DP,
   1135     DevPathSerialIPv6,
   1136     DevPathCompareDefault
   1137   },
   1138   {
   1139     MESSAGING_DEVICE_PATH,
   1140     MSG_INFINIBAND_DP,
   1141     DevPathSerialInfiniBand,
   1142     DevPathCompareDefault
   1143   },
   1144   {
   1145     MESSAGING_DEVICE_PATH,
   1146     MSG_UART_DP,
   1147     DevPathSerialUart,
   1148     DevPathCompareDefault
   1149   },
   1150   {
   1151     MESSAGING_DEVICE_PATH,
   1152     MSG_VENDOR_DP,
   1153     DevPathSerialVendor,
   1154     DevPathCompareDefault
   1155   },
   1156   {
   1157     MESSAGING_DEVICE_PATH,
   1158     MSG_DEVICE_LOGICAL_UNIT_DP,
   1159     DevPathSerialLun,
   1160     DevPathCompareDefault
   1161   },
   1162   {
   1163     MESSAGING_DEVICE_PATH,
   1164     MSG_SATA_DP,
   1165     DevPathSerialSata,
   1166     DevPathCompareDefault
   1167   },
   1168   {
   1169     MESSAGING_DEVICE_PATH,
   1170     MSG_ISCSI_DP,
   1171     DevPathSerialIScsi,
   1172     DevPathCompareDefault
   1173   },
   1174   {
   1175     MEDIA_DEVICE_PATH,
   1176     MEDIA_HARDDRIVE_DP,
   1177     DevPathSerialHardDrive,
   1178     DevPathCompareDefault
   1179   },
   1180   {
   1181     MEDIA_DEVICE_PATH,
   1182     MEDIA_CDROM_DP,
   1183     DevPathSerialCdRom,
   1184     DevPathCompareDefault
   1185   },
   1186   {
   1187     MEDIA_DEVICE_PATH,
   1188     MEDIA_VENDOR_DP,
   1189     DevPathSerialVendor,
   1190     DevPathCompareDefault
   1191   },
   1192   {
   1193     0,
   1194     0,
   1195     NULL,
   1196     NULL
   1197   }
   1198 };
   1199 
   1200 /**
   1201   Function to determine if a device path node is Hi or not.
   1202 
   1203   @param[in] DevicePathNode   The node to check.
   1204 
   1205   @retval TRUE    The node is Hi.
   1206   @retval FALSE   The node is not Hi.
   1207 **/
   1208 BOOLEAN
   1209 EFIAPI
   1210 IsHIDevicePathNode (
   1211   IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
   1212   )
   1213 {
   1214   ACPI_HID_DEVICE_PATH  *Acpi;
   1215 
   1216   ASSERT(DevicePathNode != NULL);
   1217 
   1218   if (DevicePathNode->Type == HARDWARE_DEVICE_PATH) {
   1219     return TRUE;
   1220   }
   1221 
   1222   if (DevicePathNode->Type == ACPI_DEVICE_PATH) {
   1223     Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
   1224     switch (EISA_ID_TO_NUM (Acpi->HID)) {
   1225     case 0x0301:
   1226     case 0x0401:
   1227     case 0x0501:
   1228     case 0x0604:
   1229       return FALSE;
   1230     }
   1231 
   1232     return TRUE;
   1233   }
   1234 
   1235   return FALSE;
   1236 }
   1237 
   1238 /**
   1239   Function to convert a standard device path structure into a Hi version.
   1240 
   1241   @param[in] DevicePath   The device path to convert.
   1242 
   1243   @return   the device path portion that is Hi.
   1244 **/
   1245 EFI_DEVICE_PATH_PROTOCOL *
   1246 EFIAPI
   1247 GetHIDevicePath (
   1248   IN EFI_DEVICE_PATH_PROTOCOL        *DevicePath
   1249   )
   1250 {
   1251   UINTN                     NonHIDevicePathNodeCount;
   1252   UINTN                     Index;
   1253   EFI_DEV_PATH              Node;
   1254   EFI_DEVICE_PATH_PROTOCOL  *HIDevicePath;
   1255   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
   1256 
   1257   ASSERT(DevicePath != NULL);
   1258 
   1259   NonHIDevicePathNodeCount  = 0;
   1260 
   1261   HIDevicePath              = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));
   1262   SetDevicePathEndNode (HIDevicePath);
   1263 
   1264   Node.DevPath.Type       = END_DEVICE_PATH_TYPE;
   1265   Node.DevPath.SubType    = END_INSTANCE_DEVICE_PATH_SUBTYPE;
   1266   Node.DevPath.Length[0]  = (UINT8)sizeof (EFI_DEVICE_PATH_PROTOCOL);
   1267   Node.DevPath.Length[1]  = 0;
   1268 
   1269   while (!IsDevicePathEnd (DevicePath)) {
   1270     if (IsHIDevicePathNode (DevicePath)) {
   1271       for (Index = 0; Index < NonHIDevicePathNodeCount; Index++) {
   1272         TempDevicePath = AppendDevicePathNode (HIDevicePath, &Node.DevPath);
   1273         FreePool (HIDevicePath);
   1274         HIDevicePath = TempDevicePath;
   1275       }
   1276 
   1277       TempDevicePath = AppendDevicePathNode (HIDevicePath, DevicePath);
   1278       FreePool (HIDevicePath);
   1279       HIDevicePath = TempDevicePath;
   1280     } else {
   1281       NonHIDevicePathNodeCount++;
   1282     }
   1283     //
   1284     // Next device path node
   1285     //
   1286     DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
   1287   }
   1288 
   1289   return HIDevicePath;
   1290 }
   1291 
   1292 /**
   1293   Function to walk the device path looking for a dumpable node.
   1294 
   1295   @param[in] MappingItem      The Item to fill with data.
   1296   @param[in] DevicePath       The path of the item to get data on.
   1297 
   1298   @return EFI_SUCCESS         Always returns success.
   1299 **/
   1300 EFI_STATUS
   1301 EFIAPI
   1302 GetDeviceConsistMappingInfo (
   1303   IN DEVICE_CONSIST_MAPPING_INFO    *MappingItem,
   1304   IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath
   1305   )
   1306 {
   1307   SERIAL_DECODE_FUNCTION    SerialFun;
   1308   UINTN                     Index;
   1309   EFI_DEVICE_PATH_PROTOCOL  *OriginalDevicePath;
   1310 
   1311   ASSERT(DevicePath != NULL);
   1312   ASSERT(MappingItem != NULL);
   1313 
   1314   SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0);
   1315   OriginalDevicePath = DevicePath;
   1316 
   1317   while (!IsDevicePathEnd (DevicePath)) {
   1318     //
   1319     // Find the handler to dump this device path node and
   1320     // initialize with generic function in case nothing is found
   1321     //
   1322     for (SerialFun = DevPathSerialDefault, Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) {
   1323 
   1324       if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type &&
   1325           DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType
   1326          ) {
   1327         SerialFun = DevPathConsistMappingTable[Index].SerialFun;
   1328         break;
   1329       }
   1330     }
   1331 
   1332     SerialFun (DevicePath, MappingItem, OriginalDevicePath);
   1333 
   1334     //
   1335     // Next device path node
   1336     //
   1337     DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
   1338   }
   1339 
   1340   return EFI_SUCCESS;
   1341 }
   1342 
   1343 /**
   1344   Function to initialize the table for creating consistent map names.
   1345 
   1346   @param[out] Table             The pointer to pointer to pointer to DevicePathProtocol object.
   1347 
   1348   @retval EFI_SUCCESS           The table was created successfully.
   1349 **/
   1350 EFI_STATUS
   1351 EFIAPI
   1352 ShellCommandConsistMappingInitialize (
   1353   OUT EFI_DEVICE_PATH_PROTOCOL           ***Table
   1354   )
   1355 {
   1356   EFI_HANDLE                      *HandleBuffer;
   1357   UINTN                           HandleNum;
   1358   UINTN                           HandleLoop;
   1359   EFI_DEVICE_PATH_PROTOCOL        **TempTable;
   1360   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
   1361   EFI_DEVICE_PATH_PROTOCOL        *HIDevicePath;
   1362   EFI_BLOCK_IO_PROTOCOL           *BlockIo;
   1363   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
   1364   UINTN                           Index;
   1365   EFI_STATUS                      Status;
   1366 
   1367   HandleBuffer              = NULL;
   1368 
   1369   Status = gBS->LocateHandleBuffer (
   1370               ByProtocol,
   1371               &gEfiDevicePathProtocolGuid,
   1372               NULL,
   1373               &HandleNum,
   1374               &HandleBuffer
   1375              );
   1376   ASSERT_EFI_ERROR(Status);
   1377 
   1378   TempTable     = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_DEVICE_PATH_PROTOCOL *));
   1379   if (TempTable == NULL) {
   1380     return EFI_OUT_OF_RESOURCES;
   1381   }
   1382 
   1383   for (HandleLoop = 0 ; HandleLoop < HandleNum ; HandleLoop++) {
   1384     DevicePath = DevicePathFromHandle (HandleBuffer[HandleLoop]);
   1385     if (DevicePath == NULL) {
   1386       continue;
   1387     }
   1388 
   1389     HIDevicePath = GetHIDevicePath (DevicePath);
   1390     if (HIDevicePath == NULL) {
   1391       continue;
   1392     }
   1393 
   1394     Status = gBS->HandleProtocol( HandleBuffer[HandleLoop],
   1395                                   &gEfiBlockIoProtocolGuid,
   1396                                   (VOID **)&BlockIo
   1397                                   );
   1398     if (EFI_ERROR(Status)) {
   1399       Status = gBS->HandleProtocol( HandleBuffer[HandleLoop],
   1400                                     &gEfiSimpleFileSystemProtocolGuid,
   1401                                     (VOID **)&SimpleFileSystem
   1402                                     );
   1403       if (EFI_ERROR(Status)) {
   1404         FreePool (HIDevicePath);
   1405         continue;
   1406       }
   1407     }
   1408 
   1409     for (Index = 0; TempTable[Index] != NULL; Index++) {
   1410       if (DevicePathCompare (&TempTable[Index], &HIDevicePath) == 0) {
   1411         FreePool (HIDevicePath);
   1412         break;
   1413       }
   1414     }
   1415 
   1416     if (TempTable[Index] == NULL) {
   1417       TempTable[Index] = HIDevicePath;
   1418     }
   1419   }
   1420 
   1421   for (Index = 0; TempTable[Index] != NULL; Index++);
   1422   PerformQuickSort(TempTable, Index, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
   1423   *Table = TempTable;
   1424 
   1425   if (HandleBuffer != NULL) {
   1426     FreePool (HandleBuffer);
   1427   }
   1428 
   1429   return EFI_SUCCESS;
   1430 }
   1431 
   1432 /**
   1433   Function to uninitialize the table for creating consistent map names.
   1434 
   1435   The parameter must have been received from ShellCommandConsistMappingInitialize.
   1436 
   1437   @param[out] Table             The pointer to pointer to DevicePathProtocol object.
   1438 
   1439   @retval EFI_SUCCESS           The table was deleted successfully.
   1440 **/
   1441 EFI_STATUS
   1442 EFIAPI
   1443 ShellCommandConsistMappingUnInitialize (
   1444   EFI_DEVICE_PATH_PROTOCOL **Table
   1445   )
   1446 {
   1447   UINTN Index;
   1448 
   1449   ASSERT(Table  != NULL);
   1450 
   1451   for (Index = 0; Table[Index] != NULL; Index++) {
   1452     FreePool (Table[Index]);
   1453   }
   1454 
   1455   FreePool (Table);
   1456   return EFI_SUCCESS;
   1457 }
   1458 
   1459 /**
   1460   Create a consistent mapped name for the device specified by DevicePath
   1461   based on the Table.
   1462 
   1463   This must be called after ShellCommandConsistMappingInitialize() and
   1464   before ShellCommandConsistMappingUnInitialize() is called.
   1465 
   1466   @param[in] DevicePath   The pointer to the dev path for the device.
   1467   @param[in] Table        The Table of mapping information.
   1468 
   1469   @retval NULL            A consistent mapped name could not be created.
   1470   @return                 A pointer to a string allocated from pool with the device name.
   1471 **/
   1472 CHAR16 *
   1473 EFIAPI
   1474 ShellCommandConsistMappingGenMappingName (
   1475   IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
   1476   IN EFI_DEVICE_PATH_PROTOCOL    **Table
   1477   )
   1478 {
   1479   POOL_PRINT                  Str;
   1480   DEVICE_CONSIST_MAPPING_INFO MappingInfo;
   1481   EFI_DEVICE_PATH_PROTOCOL    *HIDevicePath;
   1482   UINTN                       Index;
   1483   UINTN                       NewSize;
   1484 
   1485   ASSERT(DevicePath         != NULL);
   1486   ASSERT(Table  != NULL);
   1487 
   1488   HIDevicePath = GetHIDevicePath (DevicePath);
   1489   if (HIDevicePath == NULL) {
   1490     return NULL;
   1491   }
   1492 
   1493   for (Index = 0; Table[Index] != NULL; Index++) {
   1494     if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) {
   1495       break;
   1496     }
   1497   }
   1498 
   1499   FreePool (HIDevicePath);
   1500   if (Table[Index] == NULL) {
   1501     return NULL;
   1502   }
   1503 
   1504   MappingInfo.Hi      = Index;
   1505   MappingInfo.Mtd     = MTDTypeUnknown;
   1506   MappingInfo.Digital = FALSE;
   1507 
   1508   GetDeviceConsistMappingInfo (&MappingInfo, DevicePath);
   1509 
   1510   SetMem (&Str, sizeof (Str), 0);
   1511   for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) {
   1512     if (MappingInfo.Mtd == mMTDName[Index].MTDType) {
   1513       break;
   1514     }
   1515   }
   1516 
   1517   if (mMTDName[Index].MTDType != MTDTypeEnd) {
   1518     CatPrint (&Str, L"%s", mMTDName[Index].Name);
   1519   }
   1520 
   1521   CatPrint (&Str, L"%d", (UINTN) MappingInfo.Hi);
   1522   if (MappingInfo.Csd.Str != NULL) {
   1523     CatPrint (&Str, L"%s", MappingInfo.Csd.Str);
   1524     FreePool (MappingInfo.Csd.Str);
   1525   }
   1526 
   1527   if (Str.Str != NULL) {
   1528     CatPrint (&Str, L":");
   1529   }
   1530 
   1531   NewSize           = (Str.Len + 1) * sizeof (CHAR16);
   1532   Str.Str           = ReallocatePool (Str.Len, NewSize, Str.Str);
   1533   if (Str.Str == NULL) {
   1534     return (NULL);
   1535   }
   1536   Str.Str[Str.Len]  = CHAR_NULL;
   1537   return Str.Str;
   1538 }
   1539 
   1540 /**
   1541   Function to search the list of mappings for the node on the list based on the key.
   1542 
   1543   @param[in] MapKey       String Key to search for on the map
   1544 
   1545   @return the node on the list.
   1546 **/
   1547 SHELL_MAP_LIST *
   1548 EFIAPI
   1549 ShellCommandFindMapItem (
   1550   IN CONST CHAR16 *MapKey
   1551   )
   1552 {
   1553   SHELL_MAP_LIST *MapListItem;
   1554 
   1555   for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
   1556       ; !IsNull(&gShellMapList.Link, &MapListItem->Link)
   1557       ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link)
   1558      ){
   1559     if (gUnicodeCollation->StriColl(gUnicodeCollation,MapListItem->MapName,(CHAR16*)MapKey) == 0) {
   1560       return (MapListItem);
   1561     }
   1562   }
   1563   return (NULL);
   1564 }
   1565 
   1566 
   1567