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