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