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
CatPrint(IN OUT POOL_PRINT * Str,IN CHAR16 * Fmt,...)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
AppendCSDNum2(IN OUT POOL_PRINT * Str,IN UINT64 Num)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
AppendCSDNum(IN OUT DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN UINT64 Num)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
AppendCSDStr(IN OUT DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN CHAR16 * Str)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
AppendCSDGuid(DEVICE_CONSIST_MAPPING_INFO * MappingItem,EFI_GUID * Guid)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
DevPathCompareAcpi(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath1,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath2)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
DevPathComparePci(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath1,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath2)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
DevPathCompareDefault(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath1,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath2)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
DevPathSerialHardDrive(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialAtapi(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialCdRom(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialFibre(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialUart(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialUsb(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialVendor(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialLun(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialSata(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialIScsi(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialI2O(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialMacAddr(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialInfiniBand(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialIPv4(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialIPv6(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialScsi(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerial1394(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialAcpi(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
DevPathSerialDefault(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode,IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
IsHIDevicePathNode(IN EFI_DEVICE_PATH_PROTOCOL * DevicePathNode)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 *
GetHIDevicePath(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
GetDeviceConsistMappingInfo(IN DEVICE_CONSIST_MAPPING_INFO * MappingItem,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
ShellCommandConsistMappingInitialize(OUT EFI_DEVICE_PATH_PROTOCOL *** Table)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
ShellCommandConsistMappingUnInitialize(EFI_DEVICE_PATH_PROTOCOL ** Table)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
ShellCommandConsistMappingGenMappingName(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN EFI_DEVICE_PATH_PROTOCOL ** Table)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
ShellCommandFindMapItem(IN CONST CHAR16 * MapKey)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