xref: /freebsd/lib/libefivar/efivar-dp-format.c (revision 39d58c816068178515af0718c47f4f64d1cffc1d)
1 /*-
2  * Copyright (c) 2017 Netflix, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 /*
27  * Routines to format EFI_DEVICE_PATHs from the UEFI standard. Much of
28  * this file is taken from EDK2 and rototilled.
29  */
30 
31 #include <sys/cdefs.h>
32 #include <efivar.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 #include "efichar.h"
37 
38 #include "efi-osdep.h"
39 #include "efivar-dp.h"
40 
41 #include "uefi-dplib.h"
42 
43 /*
44  * This is a lie, but since we have converted everything
45  * from wide to narrow, it's the right lie now.
46  */
47 #define UnicodeSPrint snprintf
48 
49 /*
50  * Taken from MdePkg/Library/UefiDevicePathLib/DevicePathToText.c
51  * heavily modified:
52  *	wide strings converted to narrow
53  *	Low level printing code redone for narrow strings
54  *	Routines made static
55  *	%s -> %S in spots (where it is still UCS-2)
56  *	%a (ascii) -> %s
57  *	%g -> %36s hack to print guid (see above for caveat)
58  *	some tidying up of const and deconsting. It's evil, but const
59  *	  poisoning the whole file was too much.
60  */
61 
62 /** @file
63   DevicePathToText protocol as defined in the UEFI 2.0 specification.
64 
65   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
66 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
67 SPDX-License-Identifier: BSD-2-Clause-Patent
68 
69 **/
70 
71 // #include "UefiDevicePathLib.h"
72 
73 /**
74   Concatenates a formatted unicode string to allocated pool. The caller must
75   free the resulting buffer.
76 
77   @param Str             Tracks the allocated pool, size in use, and
78                          amount of pool allocated.
79   @param Fmt             The format string
80   @param ...             Variable arguments based on the format string.
81 
82   @return Allocated buffer with the formatted string printed in it.
83           The caller must free the allocated buffer. The buffer
84           allocation is not packed.
85 
86 **/
87 static char *
88 EFIAPI
UefiDevicePathLibCatPrint(IN OUT POOL_PRINT * Str,IN const char * Fmt,...)89 UefiDevicePathLibCatPrint (
90   IN OUT POOL_PRINT  *Str,
91   IN const char      *Fmt,
92   ...
93   )
94 {
95   UINTN    Count;
96   VA_LIST  Args;
97 
98   VA_START (Args, Fmt);
99   Count = vsnprintf (NULL, 0, Fmt, Args);
100   VA_END (Args);
101 
102   if ((Str->Count + (Count + 1)) > Str->Capacity) {
103     Str->Capacity = (Str->Count + (Count + 1) * 2);
104     Str->Str      = reallocf (
105                       Str->Str,
106                       Str->Capacity
107                       );
108     ASSERT (Str->Str != NULL);
109   }
110 
111   VA_START (Args, Fmt);
112   vsnprintf (Str->Str + Str->Count, Str->Capacity - Str->Count, Fmt, Args);
113   Str->Count += Count;
114 
115   VA_END (Args);
116   return Str->Str;
117 }
118 
119 /**
120   Converts a PCI device path structure to its string representative.
121 
122   @param Str             The string representative of input device.
123   @param DevPath         The input device path structure.
124   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
125                          of the display node is used, where applicable. If DisplayOnly
126                          is FALSE, then the longer text representation of the display node
127                          is used.
128   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
129                          representation for a device node can be used, where applicable.
130 
131 **/
132 static VOID
DevPathToTextPci(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)133 DevPathToTextPci (
134   IN OUT POOL_PRINT  *Str,
135   IN VOID            *DevPath,
136   IN BOOLEAN         DisplayOnly,
137   IN BOOLEAN         AllowShortcuts
138   )
139 {
140   PCI_DEVICE_PATH  *Pci;
141 
142   Pci = DevPath;
143   UefiDevicePathLibCatPrint (Str, "Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
144 }
145 
146 /**
147   Converts a PC Card device path structure to its string representative.
148 
149   @param Str             The string representative of input device.
150   @param DevPath         The input device path structure.
151   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
152                          of the display node is used, where applicable. If DisplayOnly
153                          is FALSE, then the longer text representation of the display node
154                          is used.
155   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
156                          representation for a device node can be used, where applicable.
157 
158 **/
159 static VOID
DevPathToTextPccard(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)160 DevPathToTextPccard (
161   IN OUT POOL_PRINT  *Str,
162   IN VOID            *DevPath,
163   IN BOOLEAN         DisplayOnly,
164   IN BOOLEAN         AllowShortcuts
165   )
166 {
167   PCCARD_DEVICE_PATH  *Pccard;
168 
169   Pccard = DevPath;
170   UefiDevicePathLibCatPrint (Str, "PcCard(0x%x)", Pccard->FunctionNumber);
171 }
172 
173 /**
174   Converts a Memory Map device path structure to its string representative.
175 
176   @param Str             The string representative of input device.
177   @param DevPath         The input device path structure.
178   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
179                          of the display node is used, where applicable. If DisplayOnly
180                          is FALSE, then the longer text representation of the display node
181                          is used.
182   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
183                          representation for a device node can be used, where applicable.
184 
185 **/
186 static VOID
DevPathToTextMemMap(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)187 DevPathToTextMemMap (
188   IN OUT POOL_PRINT  *Str,
189   IN VOID            *DevPath,
190   IN BOOLEAN         DisplayOnly,
191   IN BOOLEAN         AllowShortcuts
192   )
193 {
194   MEMMAP_DEVICE_PATH  *MemMap;
195 
196   MemMap = DevPath;
197   UefiDevicePathLibCatPrint (
198     Str,
199     "MemoryMapped(0x%x,0x%lx,0x%lx)",
200     MemMap->MemoryType,
201     MemMap->StartingAddress,
202     MemMap->EndingAddress
203     );
204 }
205 
206 /**
207   Converts a Vendor device path structure to its string representative.
208 
209   @param Str             The string representative of input device.
210   @param DevPath         The input device path structure.
211   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
212                          of the display node is used, where applicable. If DisplayOnly
213                          is FALSE, then the longer text representation of the display node
214                          is used.
215   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
216                          representation for a device node can be used, where applicable.
217 
218 **/
219 static VOID
DevPathToTextVendor(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)220 DevPathToTextVendor (
221   IN OUT POOL_PRINT  *Str,
222   IN VOID            *DevPath,
223   IN BOOLEAN         DisplayOnly,
224   IN BOOLEAN         AllowShortcuts
225   )
226 {
227   VENDOR_DEVICE_PATH  *Vendor;
228   const char          *Type;
229   UINTN               Index;
230   UINTN               DataLength;
231   UINT32              FlowControlMap;
232   UINT16              Info;
233 
234   Vendor = (VENDOR_DEVICE_PATH *)DevPath;
235   switch (DevicePathType (&Vendor->Header)) {
236     case HARDWARE_DEVICE_PATH:
237       Type = "Hw";
238       break;
239 
240     case MESSAGING_DEVICE_PATH:
241       Type = "Msg";
242       if (AllowShortcuts) {
243         if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
244           UefiDevicePathLibCatPrint (Str, "VenPcAnsi()");
245           return;
246         } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
247           UefiDevicePathLibCatPrint (Str, "VenVt100()");
248           return;
249         } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
250           UefiDevicePathLibCatPrint (Str, "VenVt100Plus()");
251           return;
252         } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
253           UefiDevicePathLibCatPrint (Str, "VenUtf8()");
254           return;
255         } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid)) {
256           FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *)Vendor)->FlowControlMap);
257           switch (FlowControlMap & 0x00000003) {
258             case 0:
259               UefiDevicePathLibCatPrint (Str, "UartFlowCtrl(%s)", "None");
260               break;
261 
262             case 1:
263               UefiDevicePathLibCatPrint (Str, "UartFlowCtrl(%s)", "Hardware");
264               break;
265 
266             case 2:
267               UefiDevicePathLibCatPrint (Str, "UartFlowCtrl(%s)", "XonXoff");
268               break;
269 
270             default:
271               break;
272           }
273 
274           return;
275         } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {
276           UefiDevicePathLibCatPrint (
277             Str,
278             "SAS(0x%lx,0x%lx,0x%x,",
279             ((SAS_DEVICE_PATH *)Vendor)->SasAddress,
280             ((SAS_DEVICE_PATH *)Vendor)->Lun,
281             ((SAS_DEVICE_PATH *)Vendor)->RelativeTargetPort
282             );
283           Info = (((SAS_DEVICE_PATH *)Vendor)->DeviceTopology);
284           if (((Info & 0x0f) == 0) && ((Info & BIT7) == 0)) {
285             UefiDevicePathLibCatPrint (Str, "NoTopology,0,0,0,");
286           } else if (((Info & 0x0f) <= 2) && ((Info & BIT7) == 0)) {
287             UefiDevicePathLibCatPrint (
288               Str,
289               "%s,%s,%s,",
290               ((Info & BIT4) != 0) ? "SATA" : "SAS",
291               ((Info & BIT5) != 0) ? "External" : "Internal",
292               ((Info & BIT6) != 0) ? "Expanded" : "Direct"
293               );
294             if ((Info & 0x0f) == 1) {
295               UefiDevicePathLibCatPrint (Str, "0,");
296             } else {
297               //
298               // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
299               //
300               UefiDevicePathLibCatPrint (Str, "0x%x,", ((Info >> 8) & 0xff) + 1);
301             }
302           } else {
303             UefiDevicePathLibCatPrint (Str, "0x%x,0,0,0,", Info);
304           }
305 
306           UefiDevicePathLibCatPrint (Str, "0x%x)", ((SAS_DEVICE_PATH *)Vendor)->Reserved);
307           return;
308         } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
309           UefiDevicePathLibCatPrint (Str, "DebugPort()");
310           return;
311         }
312       }
313 
314       break;
315 
316     case MEDIA_DEVICE_PATH:
317       Type = "Media";
318       break;
319 
320     default:
321       Type = "?";
322       break;
323   }
324 
325   DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
326   UefiDevicePathLibCatPrint (Str, "Ven%s(%36s", Type, G(&Vendor->Guid));
327   if (DataLength != 0) {
328     UefiDevicePathLibCatPrint (Str, ",");
329     for (Index = 0; Index < DataLength; Index++) {
330       UefiDevicePathLibCatPrint (Str, "%02x", ((VENDOR_DEVICE_PATH_WITH_DATA *)Vendor)->VendorDefinedData[Index]);
331     }
332   }
333 
334   UefiDevicePathLibCatPrint (Str, ")");
335 }
336 
337 /**
338   Converts a Controller device path structure to its string representative.
339 
340   @param Str             The string representative of input device.
341   @param DevPath         The input device path structure.
342   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
343                          of the display node is used, where applicable. If DisplayOnly
344                          is FALSE, then the longer text representation of the display node
345                          is used.
346   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
347                          representation for a device node can be used, where applicable.
348 
349 **/
350 static VOID
DevPathToTextController(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)351 DevPathToTextController (
352   IN OUT POOL_PRINT  *Str,
353   IN VOID            *DevPath,
354   IN BOOLEAN         DisplayOnly,
355   IN BOOLEAN         AllowShortcuts
356   )
357 {
358   CONTROLLER_DEVICE_PATH  *Controller;
359 
360   Controller = DevPath;
361   UefiDevicePathLibCatPrint (
362     Str,
363     "Ctrl(0x%x)",
364     Controller->ControllerNumber
365     );
366 }
367 
368 /**
369   Converts a BMC device path structure to its string representative.
370 
371   @param Str             The string representative of input device.
372   @param DevPath         The input device path structure.
373   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
374                          of the display node is used, where applicable. If DisplayOnly
375                          is FALSE, then the longer text representation of the display node
376                          is used.
377   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
378                          representation for a device node can be used, where applicable.
379 
380 **/
381 static VOID
DevPathToTextBmc(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)382 DevPathToTextBmc (
383   IN OUT POOL_PRINT  *Str,
384   IN VOID            *DevPath,
385   IN BOOLEAN         DisplayOnly,
386   IN BOOLEAN         AllowShortcuts
387   )
388 {
389   BMC_DEVICE_PATH  *Bmc;
390 
391   Bmc = DevPath;
392   UefiDevicePathLibCatPrint (
393     Str,
394     "BMC(0x%x,0x%lx)",
395     Bmc->InterfaceType,
396     ReadUnaligned64 ((&Bmc->BaseAddress))
397     );
398 }
399 
400 /**
401   Converts a ACPI device path structure to its string representative.
402 
403   @param Str             The string representative of input device.
404   @param DevPath         The input device path structure.
405   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
406                          of the display node is used, where applicable. If DisplayOnly
407                          is FALSE, then the longer text representation of the display node
408                          is used.
409   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
410                          representation for a device node can be used, where applicable.
411 
412 **/
413 static VOID
DevPathToTextAcpi(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)414 DevPathToTextAcpi (
415   IN OUT POOL_PRINT  *Str,
416   IN VOID            *DevPath,
417   IN BOOLEAN         DisplayOnly,
418   IN BOOLEAN         AllowShortcuts
419   )
420 {
421   ACPI_HID_DEVICE_PATH  *Acpi;
422 
423   Acpi = DevPath;
424   if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
425     switch (EISA_ID_TO_NUM (Acpi->HID)) {
426       case 0x0a03:
427         UefiDevicePathLibCatPrint (Str, "PciRoot(0x%x)", Acpi->UID);
428         break;
429 
430       case 0x0a08:
431         UefiDevicePathLibCatPrint (Str, "PcieRoot(0x%x)", Acpi->UID);
432         break;
433 
434       case 0x0604:
435         UefiDevicePathLibCatPrint (Str, "Floppy(0x%x)", Acpi->UID);
436         break;
437 
438       case 0x0301:
439         UefiDevicePathLibCatPrint (Str, "Keyboard(0x%x)", Acpi->UID);
440         break;
441 
442       case 0x0501:
443         UefiDevicePathLibCatPrint (Str, "Serial(0x%x)", Acpi->UID);
444         break;
445 
446       case 0x0401:
447         UefiDevicePathLibCatPrint (Str, "ParallelPort(0x%x)", Acpi->UID);
448         break;
449 
450       default:
451         UefiDevicePathLibCatPrint (Str, "Acpi(PNP%04x,0x%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
452         break;
453     }
454   } else {
455     UefiDevicePathLibCatPrint (Str, "Acpi(0x%08x,0x%x)", Acpi->HID, Acpi->UID);
456   }
457 }
458 
459 /**
460   Converts a ACPI extended HID device path structure to its string representative.
461 
462   @param Str             The string representative of input device.
463   @param DevPath         The input device path structure.
464   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
465                          of the display node is used, where applicable. If DisplayOnly
466                          is FALSE, then the longer text representation of the display node
467                          is used.
468   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
469                          representation for a device node can be used, where applicable.
470 
471 **/
472 static VOID
DevPathToTextAcpiEx(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)473 DevPathToTextAcpiEx (
474   IN OUT POOL_PRINT  *Str,
475   IN VOID            *DevPath,
476   IN BOOLEAN         DisplayOnly,
477   IN BOOLEAN         AllowShortcuts
478   )
479 {
480   ACPI_EXTENDED_HID_DEVICE_PATH  *AcpiEx;
481   char                           HIDText[11];
482   char                           CIDText[11];
483   UINTN                          CurrentLength;
484   CHAR8                          *CurrentPos;
485   UINTN                          NextStringOffset;
486   CHAR8                          *Strings[3];
487   UINT8                          HidStrIndex;
488   UINT8                          UidStrIndex;
489   UINT8                          CidStrIndex;
490   UINT8                          StrIndex;
491 
492   HidStrIndex          = 0;
493   UidStrIndex          = 1;
494   CidStrIndex          = 2;
495   AcpiEx               = DevPath;
496   Strings[HidStrIndex] = NULL;
497   Strings[UidStrIndex] = NULL;
498   Strings[CidStrIndex] = NULL;
499   CurrentLength        = sizeof (ACPI_EXTENDED_HID_DEVICE_PATH);
500   CurrentPos           = (CHAR8 *)(((UINT8 *)AcpiEx) + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
501   StrIndex             = 0;
502   while (CurrentLength < AcpiEx->Header.Length[0] && StrIndex < ARRAY_SIZE (Strings)) {
503     Strings[StrIndex] = CurrentPos;
504     NextStringOffset  = AsciiStrLen (CurrentPos) + 1;
505     CurrentLength    += NextStringOffset;
506     CurrentPos       += NextStringOffset;
507     StrIndex++;
508   }
509 
510   if (DisplayOnly) {
511     if ((EISA_ID_TO_NUM (AcpiEx->HID) == 0x0A03) ||
512         ((EISA_ID_TO_NUM (AcpiEx->CID) == 0x0A03) && (EISA_ID_TO_NUM (AcpiEx->HID) != 0x0A08)))
513     {
514       if (Strings[UidStrIndex] != NULL) {
515         UefiDevicePathLibCatPrint (Str, "PciRoot(%s)", Strings[UidStrIndex]);
516       } else {
517         UefiDevicePathLibCatPrint (Str, "PciRoot(0x%x)", AcpiEx->UID);
518       }
519 
520       return;
521     }
522 
523     if ((EISA_ID_TO_NUM (AcpiEx->HID) == 0x0A08) || (EISA_ID_TO_NUM (AcpiEx->CID) == 0x0A08)) {
524       if (Strings[UidStrIndex] != NULL) {
525         UefiDevicePathLibCatPrint (Str, "PcieRoot(%s)", Strings[UidStrIndex]);
526       } else {
527         UefiDevicePathLibCatPrint (Str, "PcieRoot(0x%x)", AcpiEx->UID);
528       }
529 
530       return;
531     }
532   }
533 
534   //
535   // Converts EISA identification to string.
536   //
537   UnicodeSPrint (
538     HIDText,
539     sizeof (HIDText),
540     "%c%c%c%04X",
541     ((AcpiEx->HID >> 10) & 0x1f) + 'A' - 1,
542     ((AcpiEx->HID >>  5) & 0x1f) + 'A' - 1,
543     ((AcpiEx->HID >>  0) & 0x1f) + 'A' - 1,
544     (AcpiEx->HID >> 16) & 0xFFFF
545     );
546   UnicodeSPrint (
547     CIDText,
548     sizeof (CIDText),
549     "%c%c%c%04X",
550     ((AcpiEx->CID >> 10) & 0x1f) + 'A' - 1,
551     ((AcpiEx->CID >>  5) & 0x1f) + 'A' - 1,
552     ((AcpiEx->CID >>  0) & 0x1f) + 'A' - 1,
553     (AcpiEx->CID >> 16) & 0xFFFF
554     );
555 
556   if (((Strings[HidStrIndex] != NULL) && (*Strings[HidStrIndex] == '\0')) &&
557       ((Strings[CidStrIndex] != NULL) && (*Strings[CidStrIndex] == '\0')) &&
558       ((Strings[UidStrIndex] != NULL) && (*Strings[UidStrIndex] != '\0')))
559   {
560     //
561     // use AcpiExp()
562     //
563     if (AcpiEx->CID == 0) {
564       UefiDevicePathLibCatPrint (
565         Str,
566         "AcpiExp(%s,0,%s)",
567         HIDText,
568         Strings[UidStrIndex]
569         );
570     } else {
571       UefiDevicePathLibCatPrint (
572         Str,
573         "AcpiExp(%s,%s,%s)",
574         HIDText,
575         CIDText,
576         Strings[UidStrIndex]
577         );
578     }
579   } else {
580     if (DisplayOnly) {
581       if (Strings[HidStrIndex] != NULL) {
582         UefiDevicePathLibCatPrint (Str, "AcpiEx(%s,", Strings[HidStrIndex]);
583       } else {
584         UefiDevicePathLibCatPrint (Str, "AcpiEx(%s,", HIDText);
585       }
586 
587       if (Strings[CidStrIndex] != NULL) {
588         UefiDevicePathLibCatPrint (Str, "%s,", Strings[CidStrIndex]);
589       } else {
590         UefiDevicePathLibCatPrint (Str, "%s,", CIDText);
591       }
592 
593       if (Strings[UidStrIndex] != NULL) {
594         UefiDevicePathLibCatPrint (Str, "%s)", Strings[UidStrIndex]);
595       } else {
596         UefiDevicePathLibCatPrint (Str, "0x%x)", AcpiEx->UID);
597       }
598     } else {
599       UefiDevicePathLibCatPrint (
600         Str,
601         "AcpiEx(%s,%s,0x%x,%s,%s,%s)",
602         HIDText,
603         CIDText,
604         AcpiEx->UID,
605         Strings[HidStrIndex] != NULL ? Strings[HidStrIndex] : '\0',
606         Strings[CidStrIndex] != NULL ? Strings[CidStrIndex] : '\0',
607         Strings[UidStrIndex] != NULL ? Strings[UidStrIndex] : '\0'
608         );
609     }
610   }
611 }
612 
613 /**
614   Converts a ACPI address device path structure to its string representative.
615 
616   @param Str             The string representative of input device.
617   @param DevPath         The input device path structure.
618   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
619                          of the display node is used, where applicable. If DisplayOnly
620                          is FALSE, then the longer text representation of the display node
621                          is used.
622   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
623                          representation for a device node can be used, where applicable.
624 
625 **/
626 static VOID
DevPathToTextAcpiAdr(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)627 DevPathToTextAcpiAdr (
628   IN OUT POOL_PRINT  *Str,
629   IN VOID            *DevPath,
630   IN BOOLEAN         DisplayOnly,
631   IN BOOLEAN         AllowShortcuts
632   )
633 {
634   ACPI_ADR_DEVICE_PATH  *AcpiAdr;
635   UINT32                *Addr;
636   UINT16                Index;
637   UINT16                Length;
638   UINT16                AdditionalAdrCount;
639 
640   AcpiAdr            = DevPath;
641   Length             = (UINT16)DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)AcpiAdr);
642   AdditionalAdrCount = (UINT16)((Length - 8) / 4);
643 
644   UefiDevicePathLibCatPrint (Str, "AcpiAdr(0x%x", AcpiAdr->ADR);
645   Addr = &AcpiAdr->ADR + 1;
646   for (Index = 0; Index < AdditionalAdrCount; Index++) {
647     UefiDevicePathLibCatPrint (Str, ",0x%x", Addr[Index]);
648   }
649 
650   UefiDevicePathLibCatPrint (Str, ")");
651 }
652 
653 /**
654   Converts a ATAPI device path structure to its string representative.
655 
656   @param Str             The string representative of input device.
657   @param DevPath         The input device path structure.
658   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
659                          of the display node is used, where applicable. If DisplayOnly
660                          is FALSE, then the longer text representation of the display node
661                          is used.
662   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
663                          representation for a device node can be used, where applicable.
664 
665 **/
666 static VOID
DevPathToTextAtapi(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)667 DevPathToTextAtapi (
668   IN OUT POOL_PRINT  *Str,
669   IN VOID            *DevPath,
670   IN BOOLEAN         DisplayOnly,
671   IN BOOLEAN         AllowShortcuts
672   )
673 {
674   ATAPI_DEVICE_PATH  *Atapi;
675 
676   Atapi = DevPath;
677 
678   if (DisplayOnly) {
679     UefiDevicePathLibCatPrint (Str, "Ata(0x%x)", Atapi->Lun);
680   } else {
681     UefiDevicePathLibCatPrint (
682       Str,
683       "Ata(%s,%s,0x%x)",
684       (Atapi->PrimarySecondary == 1) ? "Secondary" : "Primary",
685       (Atapi->SlaveMaster == 1) ? "Slave" : "Master",
686       Atapi->Lun
687       );
688   }
689 }
690 
691 /**
692   Converts a SCSI device path structure to its string representative.
693 
694   @param Str             The string representative of input device.
695   @param DevPath         The input device path structure.
696   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
697                          of the display node is used, where applicable. If DisplayOnly
698                          is FALSE, then the longer text representation of the display node
699                          is used.
700   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
701                          representation for a device node can be used, where applicable.
702 
703 **/
704 static VOID
DevPathToTextScsi(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)705 DevPathToTextScsi (
706   IN OUT POOL_PRINT  *Str,
707   IN VOID            *DevPath,
708   IN BOOLEAN         DisplayOnly,
709   IN BOOLEAN         AllowShortcuts
710   )
711 {
712   SCSI_DEVICE_PATH  *Scsi;
713 
714   Scsi = DevPath;
715   UefiDevicePathLibCatPrint (Str, "Scsi(0x%x,0x%x)", Scsi->Pun, Scsi->Lun);
716 }
717 
718 /**
719   Converts a Fibre device path structure to its string representative.
720 
721   @param Str             The string representative of input device.
722   @param DevPath         The input device path structure.
723   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
724                          of the display node is used, where applicable. If DisplayOnly
725                          is FALSE, then the longer text representation of the display node
726                          is used.
727   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
728                          representation for a device node can be used, where applicable.
729 
730 **/
731 static VOID
DevPathToTextFibre(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)732 DevPathToTextFibre (
733   IN OUT POOL_PRINT  *Str,
734   IN VOID            *DevPath,
735   IN BOOLEAN         DisplayOnly,
736   IN BOOLEAN         AllowShortcuts
737   )
738 {
739   FIBRECHANNEL_DEVICE_PATH  *Fibre;
740 
741   Fibre = DevPath;
742   UefiDevicePathLibCatPrint (Str, "Fibre(0x%lx,0x%lx)", Fibre->WWN, Fibre->Lun);
743 }
744 
745 /**
746   Converts a FibreEx device path structure to its string representative.
747 
748   @param Str             The string representative of input device.
749   @param DevPath         The input device path structure.
750   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
751                          of the display node is used, where applicable. If DisplayOnly
752                          is FALSE, then the longer text representation of the display node
753                          is used.
754   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
755                          representation for a device node can be used, where applicable.
756 
757 **/
758 static VOID
DevPathToTextFibreEx(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)759 DevPathToTextFibreEx (
760   IN OUT POOL_PRINT  *Str,
761   IN VOID            *DevPath,
762   IN BOOLEAN         DisplayOnly,
763   IN BOOLEAN         AllowShortcuts
764   )
765 {
766   FIBRECHANNELEX_DEVICE_PATH  *FibreEx;
767   UINTN                       Index;
768 
769   FibreEx = DevPath;
770   UefiDevicePathLibCatPrint (Str, "FibreEx(0x");
771   for (Index = 0; Index < sizeof (FibreEx->WWN) / sizeof (FibreEx->WWN[0]); Index++) {
772     UefiDevicePathLibCatPrint (Str, "%02x", FibreEx->WWN[Index]);
773   }
774 
775   UefiDevicePathLibCatPrint (Str, ",0x");
776   for (Index = 0; Index < sizeof (FibreEx->Lun) / sizeof (FibreEx->Lun[0]); Index++) {
777     UefiDevicePathLibCatPrint (Str, "%02x", FibreEx->Lun[Index]);
778   }
779 
780   UefiDevicePathLibCatPrint (Str, ")");
781 }
782 
783 /**
784   Converts a Sas Ex device path structure to its string representative.
785 
786   @param Str             The string representative of input device.
787   @param DevPath         The input device path structure.
788   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
789                          of the display node is used, where applicable. If DisplayOnly
790                          is FALSE, then the longer text representation of the display node
791                          is used.
792   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
793                          representation for a device node can be used, where applicable.
794 
795 **/
796 static VOID
DevPathToTextSasEx(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)797 DevPathToTextSasEx (
798   IN OUT POOL_PRINT  *Str,
799   IN VOID            *DevPath,
800   IN BOOLEAN         DisplayOnly,
801   IN BOOLEAN         AllowShortcuts
802   )
803 {
804   SASEX_DEVICE_PATH  *SasEx;
805   UINTN              Index;
806 
807   SasEx = DevPath;
808   UefiDevicePathLibCatPrint (Str, "SasEx(0x");
809 
810   for (Index = 0; Index < sizeof (SasEx->SasAddress) / sizeof (SasEx->SasAddress[0]); Index++) {
811     UefiDevicePathLibCatPrint (Str, "%02x", SasEx->SasAddress[Index]);
812   }
813 
814   UefiDevicePathLibCatPrint (Str, ",0x");
815   for (Index = 0; Index < sizeof (SasEx->Lun) / sizeof (SasEx->Lun[0]); Index++) {
816     UefiDevicePathLibCatPrint (Str, "%02x", SasEx->Lun[Index]);
817   }
818 
819   UefiDevicePathLibCatPrint (Str, ",0x%x,", SasEx->RelativeTargetPort);
820 
821   if (((SasEx->DeviceTopology & 0x0f) == 0) && ((SasEx->DeviceTopology & BIT7) == 0)) {
822     UefiDevicePathLibCatPrint (Str, "NoTopology,0,0,0");
823   } else if (((SasEx->DeviceTopology & 0x0f) <= 2) && ((SasEx->DeviceTopology & BIT7) == 0)) {
824     UefiDevicePathLibCatPrint (
825       Str,
826       "%s,%s,%s,",
827       ((SasEx->DeviceTopology & BIT4) != 0) ? "SATA" : "SAS",
828       ((SasEx->DeviceTopology & BIT5) != 0) ? "External" : "Internal",
829       ((SasEx->DeviceTopology & BIT6) != 0) ? "Expanded" : "Direct"
830       );
831     if ((SasEx->DeviceTopology & 0x0f) == 1) {
832       UefiDevicePathLibCatPrint (Str, "0");
833     } else {
834       //
835       // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
836       //
837       UefiDevicePathLibCatPrint (Str, "0x%x", ((SasEx->DeviceTopology >> 8) & 0xff) + 1);
838     }
839   } else {
840     UefiDevicePathLibCatPrint (Str, "0x%x,0,0,0", SasEx->DeviceTopology);
841   }
842 
843   UefiDevicePathLibCatPrint (Str, ")");
844   return;
845 }
846 
847 /**
848   Converts a NVM Express Namespace device path structure to its string representative.
849 
850   @param Str             The string representative of input device.
851   @param DevPath         The input device path structure.
852   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
853                          of the display node is used, where applicable. If DisplayOnly
854                          is FALSE, then the longer text representation of the display node
855                          is used.
856   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
857                          representation for a device node can be used, where applicable.
858 
859 **/
860 static VOID
DevPathToTextNVMe(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)861 DevPathToTextNVMe (
862   IN OUT POOL_PRINT  *Str,
863   IN VOID            *DevPath,
864   IN BOOLEAN         DisplayOnly,
865   IN BOOLEAN         AllowShortcuts
866   )
867 {
868   NVME_NAMESPACE_DEVICE_PATH  *Nvme;
869   UINT8                       *Uuid;
870 
871   Nvme = DevPath;
872   Uuid = (UINT8 *)&Nvme->NamespaceUuid;
873   UefiDevicePathLibCatPrint (
874     Str,
875     "NVMe(0x%x,%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)",
876     Nvme->NamespaceId,
877     Uuid[7],
878     Uuid[6],
879     Uuid[5],
880     Uuid[4],
881     Uuid[3],
882     Uuid[2],
883     Uuid[1],
884     Uuid[0]
885     );
886 }
887 
888 /**
889   Converts a UFS device path structure to its string representative.
890 
891   @param Str             The string representative of input device.
892   @param DevPath         The input device path structure.
893   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
894                          of the display node is used, where applicable. If DisplayOnly
895                          is FALSE, then the longer text representation of the display node
896                          is used.
897   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
898                          representation for a device node can be used, where applicable.
899 
900 **/
901 static VOID
DevPathToTextUfs(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)902 DevPathToTextUfs (
903   IN OUT POOL_PRINT  *Str,
904   IN VOID            *DevPath,
905   IN BOOLEAN         DisplayOnly,
906   IN BOOLEAN         AllowShortcuts
907   )
908 {
909   UFS_DEVICE_PATH  *Ufs;
910 
911   Ufs = DevPath;
912   UefiDevicePathLibCatPrint (Str, "UFS(0x%x,0x%x)", Ufs->Pun, Ufs->Lun);
913 }
914 
915 /**
916   Converts a SD (Secure Digital) device path structure to its string representative.
917 
918   @param Str             The string representative of input device.
919   @param DevPath         The input device path structure.
920   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
921                          of the display node is used, where applicable. If DisplayOnly
922                          is FALSE, then the longer text representation of the display node
923                          is used.
924   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
925                          representation for a device node can be used, where applicable.
926 
927 **/
928 static VOID
DevPathToTextSd(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)929 DevPathToTextSd (
930   IN OUT POOL_PRINT  *Str,
931   IN VOID            *DevPath,
932   IN BOOLEAN         DisplayOnly,
933   IN BOOLEAN         AllowShortcuts
934   )
935 {
936   SD_DEVICE_PATH  *Sd;
937 
938   Sd = DevPath;
939   UefiDevicePathLibCatPrint (
940     Str,
941     "SD(0x%x)",
942     Sd->SlotNumber
943     );
944 }
945 
946 /**
947   Converts a EMMC (Embedded MMC) device path structure to its string representative.
948 
949   @param Str             The string representative of input device.
950   @param DevPath         The input device path structure.
951   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
952                          of the display node is used, where applicable. If DisplayOnly
953                          is FALSE, then the longer text representation of the display node
954                          is used.
955   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
956                          representation for a device node can be used, where applicable.
957 
958 **/
959 static VOID
DevPathToTextEmmc(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)960 DevPathToTextEmmc (
961   IN OUT POOL_PRINT  *Str,
962   IN VOID            *DevPath,
963   IN BOOLEAN         DisplayOnly,
964   IN BOOLEAN         AllowShortcuts
965   )
966 {
967   EMMC_DEVICE_PATH  *Emmc;
968 
969   Emmc = DevPath;
970   UefiDevicePathLibCatPrint (
971     Str,
972     "eMMC(0x%x)",
973     Emmc->SlotNumber
974     );
975 }
976 
977 /**
978   Converts a 1394 device path structure to its string representative.
979 
980   @param Str             The string representative of input device.
981   @param DevPath         The input device path structure.
982   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
983                          of the display node is used, where applicable. If DisplayOnly
984                          is FALSE, then the longer text representation of the display node
985                          is used.
986   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
987                          representation for a device node can be used, where applicable.
988 
989 **/
990 static VOID
DevPathToText1394(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)991 DevPathToText1394 (
992   IN OUT POOL_PRINT  *Str,
993   IN VOID            *DevPath,
994   IN BOOLEAN         DisplayOnly,
995   IN BOOLEAN         AllowShortcuts
996   )
997 {
998   F1394_DEVICE_PATH  *F1394DevPath;
999 
1000   F1394DevPath = DevPath;
1001   //
1002   // Guid has format of IEEE-EUI64
1003   //
1004   UefiDevicePathLibCatPrint (Str, "I1394(%016lx)", F1394DevPath->Guid);
1005 }
1006 
1007 /**
1008   Converts a USB device path structure to its string representative.
1009 
1010   @param Str             The string representative of input device.
1011   @param DevPath         The input device path structure.
1012   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1013                          of the display node is used, where applicable. If DisplayOnly
1014                          is FALSE, then the longer text representation of the display node
1015                          is used.
1016   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1017                          representation for a device node can be used, where applicable.
1018 
1019 **/
1020 static VOID
DevPathToTextUsb(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1021 DevPathToTextUsb (
1022   IN OUT POOL_PRINT  *Str,
1023   IN VOID            *DevPath,
1024   IN BOOLEAN         DisplayOnly,
1025   IN BOOLEAN         AllowShortcuts
1026   )
1027 {
1028   USB_DEVICE_PATH  *Usb;
1029 
1030   Usb = DevPath;
1031   UefiDevicePathLibCatPrint (Str, "USB(0x%x,0x%x)", Usb->ParentPortNumber, Usb->InterfaceNumber);
1032 }
1033 
1034 /**
1035   Converts a USB WWID device path structure to its string representative.
1036 
1037   @param Str             The string representative of input device.
1038   @param DevPath         The input device path structure.
1039   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1040                          of the display node is used, where applicable. If DisplayOnly
1041                          is FALSE, then the longer text representation of the display node
1042                          is used.
1043   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1044                          representation for a device node can be used, where applicable.
1045 
1046 **/
1047 static VOID
DevPathToTextUsbWWID(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1048 DevPathToTextUsbWWID (
1049   IN OUT POOL_PRINT  *Str,
1050   IN VOID            *DevPath,
1051   IN BOOLEAN         DisplayOnly,
1052   IN BOOLEAN         AllowShortcuts
1053   )
1054 {
1055   USB_WWID_DEVICE_PATH  *UsbWWId;
1056   CHAR16                *SerialNumberStr;
1057   CHAR16                *NewStr;
1058   UINT16                Length;
1059 
1060   UsbWWId = DevPath;
1061 
1062   SerialNumberStr = (CHAR16 *)(&UsbWWId + 1);
1063   Length          = (UINT16)((DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)UsbWWId) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16));
1064   if ((Length >= 1) && (SerialNumberStr[Length - 1] != 0)) {
1065     //
1066     // In case no NULL terminator in SerialNumber, create a new one with NULL terminator
1067     //
1068     NewStr = AllocatePool ((Length + 1) * sizeof (CHAR16));
1069     ASSERT (NewStr != NULL);
1070     CopyMem (NewStr, SerialNumberStr, Length * sizeof (CHAR16));
1071     NewStr[Length]  = 0;
1072     SerialNumberStr = NewStr;
1073   }
1074 
1075   UefiDevicePathLibCatPrint (
1076     Str,
1077     "UsbWwid(0x%x,0x%x,0x%x,\"%S\")",
1078     UsbWWId->VendorId,
1079     UsbWWId->ProductId,
1080     UsbWWId->InterfaceNumber,
1081     SerialNumberStr
1082     );
1083 }
1084 
1085 /**
1086   Converts a Logic Unit device path structure to its string representative.
1087 
1088   @param Str             The string representative of input device.
1089   @param DevPath         The input device path structure.
1090   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1091                          of the display node is used, where applicable. If DisplayOnly
1092                          is FALSE, then the longer text representation of the display node
1093                          is used.
1094   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1095                          representation for a device node can be used, where applicable.
1096 
1097 **/
1098 static VOID
DevPathToTextLogicalUnit(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1099 DevPathToTextLogicalUnit (
1100   IN OUT POOL_PRINT  *Str,
1101   IN VOID            *DevPath,
1102   IN BOOLEAN         DisplayOnly,
1103   IN BOOLEAN         AllowShortcuts
1104   )
1105 {
1106   DEVICE_LOGICAL_UNIT_DEVICE_PATH  *LogicalUnit;
1107 
1108   LogicalUnit = DevPath;
1109   UefiDevicePathLibCatPrint (Str, "Unit(0x%x)", LogicalUnit->Lun);
1110 }
1111 
1112 /**
1113   Converts a USB class device path structure to its string representative.
1114 
1115   @param Str             The string representative of input device.
1116   @param DevPath         The input device path structure.
1117   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1118                          of the display node is used, where applicable. If DisplayOnly
1119                          is FALSE, then the longer text representation of the display node
1120                          is used.
1121   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1122                          representation for a device node can be used, where applicable.
1123 
1124 **/
1125 static VOID
DevPathToTextUsbClass(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1126 DevPathToTextUsbClass (
1127   IN OUT POOL_PRINT  *Str,
1128   IN VOID            *DevPath,
1129   IN BOOLEAN         DisplayOnly,
1130   IN BOOLEAN         AllowShortcuts
1131   )
1132 {
1133   USB_CLASS_DEVICE_PATH  *UsbClass;
1134   BOOLEAN                IsKnownSubClass;
1135 
1136   UsbClass = DevPath;
1137 
1138   IsKnownSubClass = TRUE;
1139   switch (UsbClass->DeviceClass) {
1140     case USB_CLASS_AUDIO:
1141       UefiDevicePathLibCatPrint (Str, "UsbAudio");
1142       break;
1143 
1144     case USB_CLASS_CDCCONTROL:
1145       UefiDevicePathLibCatPrint (Str, "UsbCDCControl");
1146       break;
1147 
1148     case USB_CLASS_HID:
1149       UefiDevicePathLibCatPrint (Str, "UsbHID");
1150       break;
1151 
1152     case USB_CLASS_IMAGE:
1153       UefiDevicePathLibCatPrint (Str, "UsbImage");
1154       break;
1155 
1156     case USB_CLASS_PRINTER:
1157       UefiDevicePathLibCatPrint (Str, "UsbPrinter");
1158       break;
1159 
1160     case USB_CLASS_MASS_STORAGE:
1161       UefiDevicePathLibCatPrint (Str, "UsbMassStorage");
1162       break;
1163 
1164     case USB_CLASS_HUB:
1165       UefiDevicePathLibCatPrint (Str, "UsbHub");
1166       break;
1167 
1168     case USB_CLASS_CDCDATA:
1169       UefiDevicePathLibCatPrint (Str, "UsbCDCData");
1170       break;
1171 
1172     case USB_CLASS_SMART_CARD:
1173       UefiDevicePathLibCatPrint (Str, "UsbSmartCard");
1174       break;
1175 
1176     case USB_CLASS_VIDEO:
1177       UefiDevicePathLibCatPrint (Str, "UsbVideo");
1178       break;
1179 
1180     case USB_CLASS_DIAGNOSTIC:
1181       UefiDevicePathLibCatPrint (Str, "UsbDiagnostic");
1182       break;
1183 
1184     case USB_CLASS_WIRELESS:
1185       UefiDevicePathLibCatPrint (Str, "UsbWireless");
1186       break;
1187 
1188     default:
1189       IsKnownSubClass = FALSE;
1190       break;
1191   }
1192 
1193   if (IsKnownSubClass) {
1194     UefiDevicePathLibCatPrint (
1195       Str,
1196       "(0x%x,0x%x,0x%x,0x%x)",
1197       UsbClass->VendorId,
1198       UsbClass->ProductId,
1199       UsbClass->DeviceSubClass,
1200       UsbClass->DeviceProtocol
1201       );
1202     return;
1203   }
1204 
1205   if (UsbClass->DeviceClass == USB_CLASS_RESERVE) {
1206     if (UsbClass->DeviceSubClass == USB_SUBCLASS_FW_UPDATE) {
1207       UefiDevicePathLibCatPrint (
1208         Str,
1209         "UsbDeviceFirmwareUpdate(0x%x,0x%x,0x%x)",
1210         UsbClass->VendorId,
1211         UsbClass->ProductId,
1212         UsbClass->DeviceProtocol
1213         );
1214       return;
1215     } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_IRDA_BRIDGE) {
1216       UefiDevicePathLibCatPrint (
1217         Str,
1218         "UsbIrdaBridge(0x%x,0x%x,0x%x)",
1219         UsbClass->VendorId,
1220         UsbClass->ProductId,
1221         UsbClass->DeviceProtocol
1222         );
1223       return;
1224     } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_TEST) {
1225       UefiDevicePathLibCatPrint (
1226         Str,
1227         "UsbTestAndMeasurement(0x%x,0x%x,0x%x)",
1228         UsbClass->VendorId,
1229         UsbClass->ProductId,
1230         UsbClass->DeviceProtocol
1231         );
1232       return;
1233     }
1234   }
1235 
1236   UefiDevicePathLibCatPrint (
1237     Str,
1238     "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
1239     UsbClass->VendorId,
1240     UsbClass->ProductId,
1241     UsbClass->DeviceClass,
1242     UsbClass->DeviceSubClass,
1243     UsbClass->DeviceProtocol
1244     );
1245 }
1246 
1247 /**
1248   Converts a SATA device path structure to its string representative.
1249 
1250   @param Str             The string representative of input device.
1251   @param DevPath         The input device path structure.
1252   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1253                          of the display node is used, where applicable. If DisplayOnly
1254                          is FALSE, then the longer text representation of the display node
1255                          is used.
1256   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1257                          representation for a device node can be used, where applicable.
1258 
1259 **/
1260 static VOID
DevPathToTextSata(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1261 DevPathToTextSata (
1262   IN OUT POOL_PRINT  *Str,
1263   IN VOID            *DevPath,
1264   IN BOOLEAN         DisplayOnly,
1265   IN BOOLEAN         AllowShortcuts
1266   )
1267 {
1268   SATA_DEVICE_PATH  *Sata;
1269 
1270   Sata = DevPath;
1271   UefiDevicePathLibCatPrint (
1272     Str,
1273     "Sata(0x%x,0x%x,0x%x)",
1274     Sata->HBAPortNumber,
1275     Sata->PortMultiplierPortNumber,
1276     Sata->Lun
1277     );
1278 }
1279 
1280 /**
1281   Converts a I20 device path structure to its string representative.
1282 
1283   @param Str             The string representative of input device.
1284   @param DevPath         The input device path structure.
1285   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1286                          of the display node is used, where applicable. If DisplayOnly
1287                          is FALSE, then the longer text representation of the display node
1288                          is used.
1289   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1290                          representation for a device node can be used, where applicable.
1291 
1292 **/
1293 static VOID
DevPathToTextI2O(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1294 DevPathToTextI2O (
1295   IN OUT POOL_PRINT  *Str,
1296   IN VOID            *DevPath,
1297   IN BOOLEAN         DisplayOnly,
1298   IN BOOLEAN         AllowShortcuts
1299   )
1300 {
1301   I2O_DEVICE_PATH  *I2ODevPath;
1302 
1303   I2ODevPath = DevPath;
1304   UefiDevicePathLibCatPrint (Str, "I2O(0x%x)", I2ODevPath->Tid);
1305 }
1306 
1307 /**
1308   Converts a MAC address device path structure to its string representative.
1309 
1310   @param Str             The string representative of input device.
1311   @param DevPath         The input device path structure.
1312   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1313                          of the display node is used, where applicable. If DisplayOnly
1314                          is FALSE, then the longer text representation of the display node
1315                          is used.
1316   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1317                          representation for a device node can be used, where applicable.
1318 
1319 **/
1320 static VOID
DevPathToTextMacAddr(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1321 DevPathToTextMacAddr (
1322   IN OUT POOL_PRINT  *Str,
1323   IN VOID            *DevPath,
1324   IN BOOLEAN         DisplayOnly,
1325   IN BOOLEAN         AllowShortcuts
1326   )
1327 {
1328   MAC_ADDR_DEVICE_PATH  *MacDevPath;
1329   UINTN                 HwAddressSize;
1330   UINTN                 Index;
1331 
1332   MacDevPath = DevPath;
1333 
1334   HwAddressSize = sizeof (EFI_MAC_ADDRESS);
1335   if ((MacDevPath->IfType == 0x01) || (MacDevPath->IfType == 0x00)) {
1336     HwAddressSize = 6;
1337   }
1338 
1339   UefiDevicePathLibCatPrint (Str, "MAC(");
1340 
1341   for (Index = 0; Index < HwAddressSize; Index++) {
1342     UefiDevicePathLibCatPrint (Str, "%02x", MacDevPath->MacAddress.Addr[Index]);
1343   }
1344 
1345   UefiDevicePathLibCatPrint (Str, ",0x%x)", MacDevPath->IfType);
1346 }
1347 
1348 /**
1349   Converts network protocol string to its text representation.
1350 
1351   @param Str             The string representative of input device.
1352   @param Protocol        The network protocol ID.
1353 
1354 **/
1355 static VOID
CatNetworkProtocol(IN OUT POOL_PRINT * Str,IN UINT16 Protocol)1356 CatNetworkProtocol (
1357   IN OUT POOL_PRINT  *Str,
1358   IN UINT16          Protocol
1359   )
1360 {
1361   if (Protocol == RFC_1700_TCP_PROTOCOL) {
1362     UefiDevicePathLibCatPrint (Str, "TCP");
1363   } else if (Protocol == RFC_1700_UDP_PROTOCOL) {
1364     UefiDevicePathLibCatPrint (Str, "UDP");
1365   } else {
1366     UefiDevicePathLibCatPrint (Str, "0x%x", Protocol);
1367   }
1368 }
1369 
1370 /**
1371   Converts IP v4 address to its text representation.
1372 
1373   @param Str             The string representative of input device.
1374   @param Address         The IP v4 address.
1375 **/
1376 static VOID
CatIPv4Address(IN OUT POOL_PRINT * Str,IN EFI_IPv4_ADDRESS * Address)1377 CatIPv4Address (
1378   IN OUT POOL_PRINT    *Str,
1379   IN EFI_IPv4_ADDRESS  *Address
1380   )
1381 {
1382   UefiDevicePathLibCatPrint (Str, "%d.%d.%d.%d", Address->Addr[0], Address->Addr[1], Address->Addr[2], Address->Addr[3]);
1383 }
1384 
1385 /**
1386   Converts IP v6 address to its text representation.
1387 
1388   @param Str             The string representative of input device.
1389   @param Address         The IP v6 address.
1390 **/
1391 static VOID
CatIPv6Address(IN OUT POOL_PRINT * Str,IN EFI_IPv6_ADDRESS * Address)1392 CatIPv6Address (
1393   IN OUT POOL_PRINT    *Str,
1394   IN EFI_IPv6_ADDRESS  *Address
1395   )
1396 {
1397   UefiDevicePathLibCatPrint (
1398     Str,
1399     "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
1400     Address->Addr[0],
1401     Address->Addr[1],
1402     Address->Addr[2],
1403     Address->Addr[3],
1404     Address->Addr[4],
1405     Address->Addr[5],
1406     Address->Addr[6],
1407     Address->Addr[7],
1408     Address->Addr[8],
1409     Address->Addr[9],
1410     Address->Addr[10],
1411     Address->Addr[11],
1412     Address->Addr[12],
1413     Address->Addr[13],
1414     Address->Addr[14],
1415     Address->Addr[15]
1416     );
1417 }
1418 
1419 /**
1420   Converts a IPv4 device path structure to its string representative.
1421 
1422   @param Str             The string representative of input device.
1423   @param DevPath         The input device path structure.
1424   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1425                          of the display node is used, where applicable. If DisplayOnly
1426                          is FALSE, then the longer text representation of the display node
1427                          is used.
1428   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1429                          representation for a device node can be used, where applicable.
1430 
1431 **/
1432 static VOID
DevPathToTextIPv4(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1433 DevPathToTextIPv4 (
1434   IN OUT POOL_PRINT  *Str,
1435   IN VOID            *DevPath,
1436   IN BOOLEAN         DisplayOnly,
1437   IN BOOLEAN         AllowShortcuts
1438   )
1439 {
1440   IPv4_DEVICE_PATH  *IPDevPath;
1441 
1442   IPDevPath = DevPath;
1443   UefiDevicePathLibCatPrint (Str, "IPv4(");
1444   CatIPv4Address (Str, &IPDevPath->RemoteIpAddress);
1445 
1446   if (DisplayOnly) {
1447     UefiDevicePathLibCatPrint (Str, ")");
1448     return;
1449   }
1450 
1451   UefiDevicePathLibCatPrint (Str, ",");
1452   CatNetworkProtocol (Str, IPDevPath->Protocol);
1453 
1454   UefiDevicePathLibCatPrint (Str, ",%s,", IPDevPath->StaticIpAddress ? "Static" : "DHCP");
1455   CatIPv4Address (Str, &IPDevPath->LocalIpAddress);
1456   if (DevicePathNodeLength (IPDevPath) == sizeof (IPv4_DEVICE_PATH)) {
1457     UefiDevicePathLibCatPrint (Str, ",");
1458     CatIPv4Address (Str, &IPDevPath->GatewayIpAddress);
1459     UefiDevicePathLibCatPrint (Str, ",");
1460     CatIPv4Address (Str, &IPDevPath->SubnetMask);
1461   }
1462 
1463   UefiDevicePathLibCatPrint (Str, ")");
1464 }
1465 
1466 /**
1467   Converts a IPv6 device path structure to its string representative.
1468 
1469   @param Str             The string representative of input device.
1470   @param DevPath         The input device path structure.
1471   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1472                          of the display node is used, where applicable. If DisplayOnly
1473                          is FALSE, then the longer text representation of the display node
1474                          is used.
1475   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1476                          representation for a device node can be used, where applicable.
1477 
1478 **/
1479 static VOID
DevPathToTextIPv6(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1480 DevPathToTextIPv6 (
1481   IN OUT POOL_PRINT  *Str,
1482   IN VOID            *DevPath,
1483   IN BOOLEAN         DisplayOnly,
1484   IN BOOLEAN         AllowShortcuts
1485   )
1486 {
1487   IPv6_DEVICE_PATH  *IPDevPath;
1488 
1489   IPDevPath = DevPath;
1490   UefiDevicePathLibCatPrint (Str, "IPv6(");
1491   CatIPv6Address (Str, &IPDevPath->RemoteIpAddress);
1492   if (DisplayOnly) {
1493     UefiDevicePathLibCatPrint (Str, ")");
1494     return;
1495   }
1496 
1497   UefiDevicePathLibCatPrint (Str, ",");
1498   CatNetworkProtocol (Str, IPDevPath->Protocol);
1499 
1500   switch (IPDevPath->IpAddressOrigin) {
1501     case 0:
1502       UefiDevicePathLibCatPrint (Str, ",Static,");
1503       break;
1504     case 1:
1505       UefiDevicePathLibCatPrint (Str, ",StatelessAutoConfigure,");
1506       break;
1507     default:
1508       UefiDevicePathLibCatPrint (Str, ",StatefulAutoConfigure,");
1509       break;
1510   }
1511 
1512   CatIPv6Address (Str, &IPDevPath->LocalIpAddress);
1513 
1514   if (DevicePathNodeLength (IPDevPath) == sizeof (IPv6_DEVICE_PATH)) {
1515     UefiDevicePathLibCatPrint (Str, ",0x%x,", IPDevPath->PrefixLength);
1516     CatIPv6Address (Str, &IPDevPath->GatewayIpAddress);
1517   }
1518 
1519   UefiDevicePathLibCatPrint (Str, ")");
1520 }
1521 
1522 /**
1523   Converts an Infini Band device path structure to its string representative.
1524 
1525   @param Str             The string representative of input device.
1526   @param DevPath         The input device path structure.
1527   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1528                          of the display node is used, where applicable. If DisplayOnly
1529                          is FALSE, then the longer text representation of the display node
1530                          is used.
1531   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1532                          representation for a device node can be used, where applicable.
1533 
1534 **/
1535 static VOID
DevPathToTextInfiniBand(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1536 DevPathToTextInfiniBand (
1537   IN OUT POOL_PRINT  *Str,
1538   IN VOID            *DevPath,
1539   IN BOOLEAN         DisplayOnly,
1540   IN BOOLEAN         AllowShortcuts
1541   )
1542 {
1543   INFINIBAND_DEVICE_PATH  *InfiniBand;
1544 
1545   InfiniBand = DevPath;
1546   UefiDevicePathLibCatPrint (
1547     Str,
1548     "Infiniband(0x%x,%36s,0x%lx,0x%lx,0x%lx)",
1549     InfiniBand->ResourceFlags,
1550     G(InfiniBand->PortGid),
1551     InfiniBand->ServiceId,
1552     InfiniBand->TargetPortId,
1553     InfiniBand->DeviceId
1554     );
1555 }
1556 
1557 /**
1558   Converts a UART device path structure to its string representative.
1559 
1560   @param Str             The string representative of input device.
1561   @param DevPath         The input device path structure.
1562   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1563                          of the display node is used, where applicable. If DisplayOnly
1564                          is FALSE, then the longer text representation of the display node
1565                          is used.
1566   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1567                          representation for a device node can be used, where applicable.
1568 
1569 **/
1570 static VOID
DevPathToTextUart(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1571 DevPathToTextUart (
1572   IN OUT POOL_PRINT  *Str,
1573   IN VOID            *DevPath,
1574   IN BOOLEAN         DisplayOnly,
1575   IN BOOLEAN         AllowShortcuts
1576   )
1577 {
1578   UART_DEVICE_PATH  *Uart;
1579   CHAR8             Parity;
1580 
1581   Uart = DevPath;
1582   switch (Uart->Parity) {
1583     case 0:
1584       Parity = 'D';
1585       break;
1586 
1587     case 1:
1588       Parity = 'N';
1589       break;
1590 
1591     case 2:
1592       Parity = 'E';
1593       break;
1594 
1595     case 3:
1596       Parity = 'O';
1597       break;
1598 
1599     case 4:
1600       Parity = 'M';
1601       break;
1602 
1603     case 5:
1604       Parity = 'S';
1605       break;
1606 
1607     default:
1608       Parity = 'x';
1609       break;
1610   }
1611 
1612   if (Uart->BaudRate == 0) {
1613     UefiDevicePathLibCatPrint (Str, "Uart(DEFAULT,");
1614   } else {
1615     UefiDevicePathLibCatPrint (Str, "Uart(%ld,", Uart->BaudRate);
1616   }
1617 
1618   if (Uart->DataBits == 0) {
1619     UefiDevicePathLibCatPrint (Str, "DEFAULT,");
1620   } else {
1621     UefiDevicePathLibCatPrint (Str, "%d,", Uart->DataBits);
1622   }
1623 
1624   UefiDevicePathLibCatPrint (Str, "%c,", Parity);
1625 
1626   switch (Uart->StopBits) {
1627     case 0:
1628       UefiDevicePathLibCatPrint (Str, "D)");
1629       break;
1630 
1631     case 1:
1632       UefiDevicePathLibCatPrint (Str, "1)");
1633       break;
1634 
1635     case 2:
1636       UefiDevicePathLibCatPrint (Str, "1.5)");
1637       break;
1638 
1639     case 3:
1640       UefiDevicePathLibCatPrint (Str, "2)");
1641       break;
1642 
1643     default:
1644       UefiDevicePathLibCatPrint (Str, "x)");
1645       break;
1646   }
1647 }
1648 
1649 /**
1650   Converts an iSCSI device path structure to its string representative.
1651 
1652   @param Str             The string representative of input device.
1653   @param DevPath         The input device path structure.
1654   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1655                          of the display node is used, where applicable. If DisplayOnly
1656                          is FALSE, then the longer text representation of the display node
1657                          is used.
1658   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1659                          representation for a device node can be used, where applicable.
1660 
1661 **/
1662 static VOID
DevPathToTextiSCSI(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1663 DevPathToTextiSCSI (
1664   IN OUT POOL_PRINT  *Str,
1665   IN VOID            *DevPath,
1666   IN BOOLEAN         DisplayOnly,
1667   IN BOOLEAN         AllowShortcuts
1668   )
1669 {
1670   ISCSI_DEVICE_PATH_WITH_NAME  *ISCSIDevPath;
1671   UINT16                       Options;
1672   UINTN                        Index;
1673 
1674   ISCSIDevPath = DevPath;
1675   UefiDevicePathLibCatPrint (
1676     Str,
1677     "iSCSI(%s,0x%x,0x",
1678     ISCSIDevPath->TargetName,
1679     ISCSIDevPath->TargetPortalGroupTag
1680     );
1681   for (Index = 0; Index < sizeof (ISCSIDevPath->Lun) / sizeof (UINT8); Index++) {
1682     UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *)&ISCSIDevPath->Lun)[Index]);
1683   }
1684 
1685   Options = ISCSIDevPath->LoginOption;
1686   UefiDevicePathLibCatPrint (Str, ",%s,", (((Options >> 1) & 0x0001) != 0) ? "CRC32C" : "None");
1687   UefiDevicePathLibCatPrint (Str, "%s,", (((Options >> 3) & 0x0001) != 0) ? "CRC32C" : "None");
1688   if (((Options >> 11) & 0x0001) != 0) {
1689     UefiDevicePathLibCatPrint (Str, "%s,", "None");
1690   } else if (((Options >> 12) & 0x0001) != 0) {
1691     UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_UNI");
1692   } else {
1693     UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_BI");
1694   }
1695 
1696   UefiDevicePathLibCatPrint (Str, "%s)", (ISCSIDevPath->NetworkProtocol == 0) ? "TCP" : "reserved");
1697 }
1698 
1699 /**
1700   Converts a VLAN device path structure to its string representative.
1701 
1702   @param Str             The string representative of input device.
1703   @param DevPath         The input device path structure.
1704   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1705                          of the display node is used, where applicable. If DisplayOnly
1706                          is FALSE, then the longer text representation of the display node
1707                          is used.
1708   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1709                          representation for a device node can be used, where applicable.
1710 
1711 **/
1712 static VOID
DevPathToTextVlan(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1713 DevPathToTextVlan (
1714   IN OUT POOL_PRINT  *Str,
1715   IN VOID            *DevPath,
1716   IN BOOLEAN         DisplayOnly,
1717   IN BOOLEAN         AllowShortcuts
1718   )
1719 {
1720   VLAN_DEVICE_PATH  *Vlan;
1721 
1722   Vlan = DevPath;
1723   UefiDevicePathLibCatPrint (Str, "Vlan(%d)", Vlan->VlanId);
1724 }
1725 
1726 /**
1727   Converts a Bluetooth device path structure to its string representative.
1728 
1729   @param Str             The string representative of input device.
1730   @param DevPath         The input device path structure.
1731   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1732                          of the display node is used, where applicable. If DisplayOnly
1733                          is FALSE, then the longer text representation of the display node
1734                          is used.
1735   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1736                          representation for a device node can be used, where applicable.
1737 
1738 **/
1739 static VOID
DevPathToTextBluetooth(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1740 DevPathToTextBluetooth (
1741   IN OUT POOL_PRINT  *Str,
1742   IN VOID            *DevPath,
1743   IN BOOLEAN         DisplayOnly,
1744   IN BOOLEAN         AllowShortcuts
1745   )
1746 {
1747   BLUETOOTH_DEVICE_PATH  *Bluetooth;
1748 
1749   Bluetooth = DevPath;
1750   UefiDevicePathLibCatPrint (
1751     Str,
1752     "Bluetooth(%02x%02x%02x%02x%02x%02x)",
1753     Bluetooth->BD_ADDR.Address[0],
1754     Bluetooth->BD_ADDR.Address[1],
1755     Bluetooth->BD_ADDR.Address[2],
1756     Bluetooth->BD_ADDR.Address[3],
1757     Bluetooth->BD_ADDR.Address[4],
1758     Bluetooth->BD_ADDR.Address[5]
1759     );
1760 }
1761 
1762 /**
1763   Converts a Wi-Fi device path structure to its string representative.
1764 
1765   @param Str             The string representative of input device.
1766   @param DevPath         The input device path structure.
1767   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1768                          of the display node is used, where applicable. If DisplayOnly
1769                          is FALSE, then the longer text representation of the display node
1770                          is used.
1771   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1772                          representation for a device node can be used, where applicable.
1773 
1774 **/
1775 static VOID
DevPathToTextWiFi(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1776 DevPathToTextWiFi (
1777   IN OUT POOL_PRINT  *Str,
1778   IN VOID            *DevPath,
1779   IN BOOLEAN         DisplayOnly,
1780   IN BOOLEAN         AllowShortcuts
1781   )
1782 {
1783   WIFI_DEVICE_PATH  *WiFi;
1784   UINT8             SSId[33];
1785 
1786   WiFi = DevPath;
1787 
1788   SSId[32] = '\0';
1789   CopyMem (SSId, WiFi->SSId, 32);
1790 
1791   UefiDevicePathLibCatPrint (Str, "Wi-Fi(%s)", SSId);
1792 }
1793 
1794 /**
1795   Converts a Bluetooth device path structure to its string representative.
1796 
1797   @param Str             The string representative of input device.
1798   @param DevPath         The input device path structure.
1799   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1800                          of the display node is used, where applicable. If DisplayOnly
1801                          is FALSE, then the longer text representation of the display node
1802                          is used.
1803   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1804                          representation for a device node can be used, where applicable.
1805 
1806 **/
1807 static VOID
DevPathToTextBluetoothLE(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1808 DevPathToTextBluetoothLE (
1809   IN OUT POOL_PRINT  *Str,
1810   IN VOID            *DevPath,
1811   IN BOOLEAN         DisplayOnly,
1812   IN BOOLEAN         AllowShortcuts
1813   )
1814 {
1815   BLUETOOTH_LE_DEVICE_PATH  *BluetoothLE;
1816 
1817   BluetoothLE = DevPath;
1818   UefiDevicePathLibCatPrint (
1819     Str,
1820     "BluetoothLE(%02x%02x%02x%02x%02x%02x,0x%02x)",
1821     BluetoothLE->Address.Address[0],
1822     BluetoothLE->Address.Address[1],
1823     BluetoothLE->Address.Address[2],
1824     BluetoothLE->Address.Address[3],
1825     BluetoothLE->Address.Address[4],
1826     BluetoothLE->Address.Address[5],
1827     BluetoothLE->Address.Type
1828     );
1829 }
1830 
1831 /**
1832   Converts a DNS device path structure to its string representative.
1833 
1834   @param Str             The string representative of input device.
1835   @param DevPath         The input device path structure.
1836   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1837                          of the display node is used, where applicable. If DisplayOnly
1838                          is FALSE, then the longer text representation of the display node
1839                          is used.
1840   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1841                          representation for a device node can be used, where applicable.
1842 
1843 **/
1844 static VOID
DevPathToTextDns(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1845 DevPathToTextDns (
1846   IN OUT POOL_PRINT  *Str,
1847   IN VOID            *DevPath,
1848   IN BOOLEAN         DisplayOnly,
1849   IN BOOLEAN         AllowShortcuts
1850   )
1851 {
1852   DNS_DEVICE_PATH  *DnsDevPath;
1853   UINT32           DnsServerIpCount;
1854   UINT32           DnsServerIpIndex;
1855 
1856   DnsDevPath       = DevPath;
1857   DnsServerIpCount = (UINT32)(DevicePathNodeLength (DnsDevPath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof (DnsDevPath->IsIPv6)) / sizeof (EFI_IP_ADDRESS);
1858 
1859   UefiDevicePathLibCatPrint (Str, "Dns(");
1860 
1861   for (DnsServerIpIndex = 0; DnsServerIpIndex < DnsServerIpCount; DnsServerIpIndex++) {
1862     if (DnsDevPath->IsIPv6 == 0x00) {
1863       CatIPv4Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v4));
1864     } else {
1865       CatIPv6Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v6));
1866     }
1867 
1868     if (DnsServerIpIndex < DnsServerIpCount - 1) {
1869       UefiDevicePathLibCatPrint (Str, ",");
1870     }
1871   }
1872 
1873   UefiDevicePathLibCatPrint (Str, ")");
1874 }
1875 
1876 /**
1877   Converts a URI device path structure to its string representative.
1878 
1879   @param Str             The string representative of input device.
1880   @param DevPath         The input device path structure.
1881   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1882                          of the display node is used, where applicable. If DisplayOnly
1883                          is FALSE, then the longer text representation of the display node
1884                          is used.
1885   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1886                          representation for a device node can be used, where applicable.
1887 
1888 **/
1889 static VOID
DevPathToTextUri(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1890 DevPathToTextUri (
1891   IN OUT POOL_PRINT  *Str,
1892   IN VOID            *DevPath,
1893   IN BOOLEAN         DisplayOnly,
1894   IN BOOLEAN         AllowShortcuts
1895   )
1896 {
1897   URI_DEVICE_PATH  *Uri;
1898   UINTN            UriLength;
1899   CHAR8            *UriStr;
1900 
1901   //
1902   // Uri in the device path may not be null terminated.
1903   //
1904   Uri       = DevPath;
1905   UriLength = DevicePathNodeLength (Uri) - sizeof (URI_DEVICE_PATH);
1906   UriStr    = AllocatePool (UriLength + 1);
1907 
1908   if (UriStr == NULL) {
1909     ASSERT (UriStr != NULL);
1910     return;
1911   }
1912 
1913   CopyMem (UriStr, Uri->Uri, UriLength);
1914   UriStr[UriLength] = '\0';
1915   UefiDevicePathLibCatPrint (Str, "Uri(%s)", UriStr);
1916   FreePool (UriStr);
1917 }
1918 
1919 /**
1920   Converts a Hard drive device path structure to its string representative.
1921 
1922   @param Str             The string representative of input device.
1923   @param DevPath         The input device path structure.
1924   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1925                          of the display node is used, where applicable. If DisplayOnly
1926                          is FALSE, then the longer text representation of the display node
1927                          is used.
1928   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1929                          representation for a device node can be used, where applicable.
1930 
1931 **/
1932 static VOID
DevPathToTextHardDrive(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1933 DevPathToTextHardDrive (
1934   IN OUT POOL_PRINT  *Str,
1935   IN VOID            *DevPath,
1936   IN BOOLEAN         DisplayOnly,
1937   IN BOOLEAN         AllowShortcuts
1938   )
1939 {
1940   HARDDRIVE_DEVICE_PATH  *Hd;
1941 
1942   Hd = DevPath;
1943   switch (Hd->SignatureType) {
1944     case SIGNATURE_TYPE_MBR:
1945       UefiDevicePathLibCatPrint (
1946         Str,
1947         "HD(%d,%s,0x%08x",
1948         Hd->PartitionNumber,
1949         "MBR",
1950 //      *((UINT32 *)(&(Hd->Signature[0])))
1951         le32dec(&(Hd->Signature[0]))
1952         );
1953       break;
1954 
1955     case SIGNATURE_TYPE_GUID:
1956       UefiDevicePathLibCatPrint (
1957         Str,
1958         "HD(%d,%s,%36s",
1959         Hd->PartitionNumber,
1960         "GPT",
1961         G(&(Hd->Signature[0]))
1962         );
1963       break;
1964 
1965     default:
1966       UefiDevicePathLibCatPrint (
1967         Str,
1968         "HD(%d,%d,0",
1969         Hd->PartitionNumber,
1970         Hd->SignatureType
1971         );
1972       break;
1973   }
1974 
1975   if (DisplayOnly) {
1976     UefiDevicePathLibCatPrint (Str, ")");
1977   } else {
1978     UefiDevicePathLibCatPrint (Str, ",0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
1979   }
1980 }
1981 
1982 /**
1983   Converts a CDROM device path structure to its string representative.
1984 
1985   @param Str             The string representative of input device.
1986   @param DevPath         The input device path structure.
1987   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1988                          of the display node is used, where applicable. If DisplayOnly
1989                          is FALSE, then the longer text representation of the display node
1990                          is used.
1991   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1992                          representation for a device node can be used, where applicable.
1993 
1994 **/
1995 static VOID
DevPathToTextCDROM(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)1996 DevPathToTextCDROM (
1997   IN OUT POOL_PRINT  *Str,
1998   IN VOID            *DevPath,
1999   IN BOOLEAN         DisplayOnly,
2000   IN BOOLEAN         AllowShortcuts
2001   )
2002 {
2003   CDROM_DEVICE_PATH  *Cd;
2004 
2005   Cd = DevPath;
2006   if (DisplayOnly) {
2007     UefiDevicePathLibCatPrint (Str, "CDROM(0x%x)", Cd->BootEntry);
2008     return;
2009   }
2010 
2011   UefiDevicePathLibCatPrint (Str, "CDROM(0x%x,0x%lx,0x%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
2012 }
2013 
2014 /**
2015   Converts a File device path structure to its string representative.
2016 
2017   @param Str             The string representative of input device.
2018   @param DevPath         The input device path structure.
2019   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2020                          of the display node is used, where applicable. If DisplayOnly
2021                          is FALSE, then the longer text representation of the display node
2022                          is used.
2023   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2024                          representation for a device node can be used, where applicable.
2025 
2026 **/
2027 static VOID
DevPathToTextFilePath(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2028 DevPathToTextFilePath (
2029   IN OUT POOL_PRINT  *Str,
2030   IN VOID            *DevPath,
2031   IN BOOLEAN         DisplayOnly,
2032   IN BOOLEAN         AllowShortcuts
2033   )
2034 {
2035   FILEPATH_DEVICE_PATH  *Fp;
2036   char *name = NULL;
2037 
2038   Fp = DevPath;
2039   ucs2_to_utf8(Fp->PathName, &name);
2040   UefiDevicePathLibCatPrint (Str, "File(%s)", name);
2041   free(name);
2042 }
2043 
2044 /**
2045   Converts a Media protocol device path structure to its string representative.
2046 
2047   @param Str             The string representative of input device.
2048   @param DevPath         The input device path structure.
2049   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2050                          of the display node is used, where applicable. If DisplayOnly
2051                          is FALSE, then the longer text representation of the display node
2052                          is used.
2053   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2054                          representation for a device node can be used, where applicable.
2055 
2056 **/
2057 static VOID
DevPathToTextMediaProtocol(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2058 DevPathToTextMediaProtocol (
2059   IN OUT POOL_PRINT  *Str,
2060   IN VOID            *DevPath,
2061   IN BOOLEAN         DisplayOnly,
2062   IN BOOLEAN         AllowShortcuts
2063   )
2064 {
2065   MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
2066 
2067   MediaProt = DevPath;
2068   UefiDevicePathLibCatPrint (Str, "Media(%36s)", G(&MediaProt->Protocol));
2069 }
2070 
2071 /**
2072   Converts a Firmware Volume device path structure to its string representative.
2073 
2074   @param Str             The string representative of input device.
2075   @param DevPath         The input device path structure.
2076   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2077                          of the display node is used, where applicable. If DisplayOnly
2078                          is FALSE, then the longer text representation of the display node
2079                          is used.
2080   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2081                          representation for a device node can be used, where applicable.
2082 
2083 **/
2084 static VOID
DevPathToTextFv(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2085 DevPathToTextFv (
2086   IN OUT POOL_PRINT  *Str,
2087   IN VOID            *DevPath,
2088   IN BOOLEAN         DisplayOnly,
2089   IN BOOLEAN         AllowShortcuts
2090   )
2091 {
2092   MEDIA_FW_VOL_DEVICE_PATH  *Fv;
2093 
2094   Fv = DevPath;
2095   UefiDevicePathLibCatPrint (Str, "Fv(%36s)", G(&Fv->FvName));
2096 }
2097 
2098 /**
2099   Converts a Firmware Volume File device path structure to its string representative.
2100 
2101   @param Str             The string representative of input device.
2102   @param DevPath         The input device path structure.
2103   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2104                          of the display node is used, where applicable. If DisplayOnly
2105                          is FALSE, then the longer text representation of the display node
2106                          is used.
2107   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2108                          representation for a device node can be used, where applicable.
2109 
2110 **/
2111 static VOID
DevPathToTextFvFile(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2112 DevPathToTextFvFile (
2113   IN OUT POOL_PRINT  *Str,
2114   IN VOID            *DevPath,
2115   IN BOOLEAN         DisplayOnly,
2116   IN BOOLEAN         AllowShortcuts
2117   )
2118 {
2119   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFile;
2120 
2121   FvFile = DevPath;
2122   UefiDevicePathLibCatPrint (Str, "FvFile(%36s)", G(&FvFile->FvFileName));
2123 }
2124 
2125 /**
2126   Converts a Relative Offset device path structure to its string representative.
2127 
2128   @param Str             The string representative of input device.
2129   @param DevPath         The input device path structure.
2130   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2131                          of the display node is used, where applicable. If DisplayOnly
2132                          is FALSE, then the longer text representation of the display node
2133                          is used.
2134   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2135                          representation for a device node can be used, where applicable.
2136 
2137 **/
2138 static VOID
DevPathRelativeOffsetRange(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2139 DevPathRelativeOffsetRange (
2140   IN OUT POOL_PRINT  *Str,
2141   IN VOID            *DevPath,
2142   IN BOOLEAN         DisplayOnly,
2143   IN BOOLEAN         AllowShortcuts
2144   )
2145 {
2146   MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  *Offset;
2147 
2148   Offset = DevPath;
2149   UefiDevicePathLibCatPrint (
2150     Str,
2151     "Offset(0x%lx,0x%lx)",
2152     Offset->StartingOffset,
2153     Offset->EndingOffset
2154     );
2155 }
2156 
2157 /**
2158   Converts a Ram Disk device path structure to its string representative.
2159 
2160   @param Str             The string representative of input device.
2161   @param DevPath         The input device path structure.
2162   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2163                          of the display node is used, where applicable. If DisplayOnly
2164                          is FALSE, then the longer text representation of the display node
2165                          is used.
2166   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2167                          representation for a device node can be used, where applicable.
2168 
2169 **/
2170 static VOID
DevPathToTextRamDisk(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2171 DevPathToTextRamDisk (
2172   IN OUT POOL_PRINT  *Str,
2173   IN VOID            *DevPath,
2174   IN BOOLEAN         DisplayOnly,
2175   IN BOOLEAN         AllowShortcuts
2176   )
2177 {
2178   MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
2179 
2180   RamDisk = DevPath;
2181 
2182   if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid)) {
2183     UefiDevicePathLibCatPrint (
2184       Str,
2185       "VirtualDisk(0x%lx,0x%lx,%d)",
2186       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2187       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2188       RamDisk->Instance
2189       );
2190   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid)) {
2191     UefiDevicePathLibCatPrint (
2192       Str,
2193       "VirtualCD(0x%lx,0x%lx,%d)",
2194       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2195       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2196       RamDisk->Instance
2197       );
2198   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid)) {
2199     UefiDevicePathLibCatPrint (
2200       Str,
2201       "PersistentVirtualDisk(0x%lx,0x%lx,%d)",
2202       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2203       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2204       RamDisk->Instance
2205       );
2206   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid)) {
2207     UefiDevicePathLibCatPrint (
2208       Str,
2209       "PersistentVirtualCD(0x%lx,0x%lx,%d)",
2210       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2211       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2212       RamDisk->Instance
2213       );
2214   } else {
2215     UefiDevicePathLibCatPrint (
2216       Str,
2217       "RamDisk(0x%lx,0x%lx,%d,%36s)",
2218       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2219       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2220       RamDisk->Instance,
2221       G(&RamDisk->TypeGuid)
2222       );
2223   }
2224 }
2225 
2226 /**
2227   Converts a BIOS Boot Specification device path structure to its string representative.
2228 
2229   @param Str             The string representative of input device.
2230   @param DevPath         The input device path structure.
2231   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2232                          of the display node is used, where applicable. If DisplayOnly
2233                          is FALSE, then the longer text representation of the display node
2234                          is used.
2235   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2236                          representation for a device node can be used, where applicable.
2237 
2238 **/
2239 static VOID
DevPathToTextBBS(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2240 DevPathToTextBBS (
2241   IN OUT POOL_PRINT  *Str,
2242   IN VOID            *DevPath,
2243   IN BOOLEAN         DisplayOnly,
2244   IN BOOLEAN         AllowShortcuts
2245   )
2246 {
2247   BBS_BBS_DEVICE_PATH  *Bbs;
2248   const char           *Type;
2249 
2250   Bbs = DevPath;
2251   switch (Bbs->DeviceType) {
2252     case BBS_TYPE_FLOPPY:
2253       Type = "Floppy";
2254       break;
2255 
2256     case BBS_TYPE_HARDDRIVE:
2257       Type = "HD";
2258       break;
2259 
2260     case BBS_TYPE_CDROM:
2261       Type = "CDROM";
2262       break;
2263 
2264     case BBS_TYPE_PCMCIA:
2265       Type = "PCMCIA";
2266       break;
2267 
2268     case BBS_TYPE_USB:
2269       Type = "USB";
2270       break;
2271 
2272     case BBS_TYPE_EMBEDDED_NETWORK:
2273       Type = "Network";
2274       break;
2275 
2276     default:
2277       Type = NULL;
2278       break;
2279   }
2280 
2281   if (Type != NULL) {
2282     UefiDevicePathLibCatPrint (Str, "BBS(%s,%s", Type, Bbs->String);
2283   } else {
2284     UefiDevicePathLibCatPrint (Str, "BBS(0x%x,%s", Bbs->DeviceType, Bbs->String);
2285   }
2286 
2287   if (DisplayOnly) {
2288     UefiDevicePathLibCatPrint (Str, ")");
2289     return;
2290   }
2291 
2292   UefiDevicePathLibCatPrint (Str, ",0x%x)", Bbs->StatusFlag);
2293 }
2294 
2295 /**
2296   Converts an End-of-Device-Path structure to its string representative.
2297 
2298   @param Str             The string representative of input device.
2299   @param DevPath         The input device path structure.
2300   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2301                          of the display node is used, where applicable. If DisplayOnly
2302                          is FALSE, then the longer text representation of the display node
2303                          is used.
2304   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2305                          representation for a device node can be used, where applicable.
2306 
2307 **/
2308 static VOID
DevPathToTextEndInstance(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2309 DevPathToTextEndInstance (
2310   IN OUT POOL_PRINT  *Str,
2311   IN VOID            *DevPath,
2312   IN BOOLEAN         DisplayOnly,
2313   IN BOOLEAN         AllowShortcuts
2314   )
2315 {
2316   UefiDevicePathLibCatPrint (Str, ",");
2317 }
2318 
2319 GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_GENERIC_TABLE  mUefiDevicePathLibToTextTableGeneric[] = {
2320   { HARDWARE_DEVICE_PATH,  "HardwarePath" },
2321   { ACPI_DEVICE_PATH,      "AcpiPath"     },
2322   { MESSAGING_DEVICE_PATH, "Msg"          },
2323   { MEDIA_DEVICE_PATH,     "MediaPath"    },
2324   { BBS_DEVICE_PATH,       "BbsPath"      },
2325   { 0,                     NULL            }
2326 };
2327 
2328 /**
2329   Converts an unknown device path structure to its string representative.
2330 
2331   @param Str             The string representative of input device.
2332   @param DevPath         The input device path structure.
2333   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2334                          of the display node is used, where applicable. If DisplayOnly
2335                          is FALSE, then the longer text representation of the display node
2336                          is used.
2337   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2338                          representation for a device node can be used, where applicable.
2339 
2340 **/
2341 static VOID
DevPathToTextNodeGeneric(IN OUT POOL_PRINT * Str,IN VOID * DevPath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2342 DevPathToTextNodeGeneric (
2343   IN OUT POOL_PRINT  *Str,
2344   IN VOID            *DevPath,
2345   IN BOOLEAN         DisplayOnly,
2346   IN BOOLEAN         AllowShortcuts
2347   )
2348 {
2349   EFI_DEVICE_PATH_PROTOCOL  *Node;
2350   UINTN                     Index;
2351 
2352   Node = DevPath;
2353 
2354   for (Index = 0; mUefiDevicePathLibToTextTableGeneric[Index].Text != NULL; Index++) {
2355     if (DevicePathType (Node) == mUefiDevicePathLibToTextTableGeneric[Index].Type) {
2356       break;
2357     }
2358   }
2359 
2360   if (mUefiDevicePathLibToTextTableGeneric[Index].Text == NULL) {
2361     //
2362     // It's a node whose type cannot be recognized
2363     //
2364     UefiDevicePathLibCatPrint (Str, "Path(%d,%d", DevicePathType (Node), DevicePathSubType (Node));
2365   } else {
2366     //
2367     // It's a node whose type can be recognized
2368     //
2369     UefiDevicePathLibCatPrint (Str, "%s(%d", mUefiDevicePathLibToTextTableGeneric[Index].Text, DevicePathSubType (Node));
2370   }
2371 
2372   Index = sizeof (EFI_DEVICE_PATH_PROTOCOL);
2373   if (Index < DevicePathNodeLength (Node)) {
2374     UefiDevicePathLibCatPrint (Str, ",");
2375     for ( ; Index < DevicePathNodeLength (Node); Index++) {
2376       UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *)Node)[Index]);
2377     }
2378   }
2379 
2380   UefiDevicePathLibCatPrint (Str, ")");
2381 }
2382 
2383 static const DEVICE_PATH_TO_TEXT_TABLE  mUefiDevicePathLibToTextTable[] = {
2384   { HARDWARE_DEVICE_PATH,  HW_PCI_DP,                        DevPathToTextPci           },
2385   { HARDWARE_DEVICE_PATH,  HW_PCCARD_DP,                     DevPathToTextPccard        },
2386   { HARDWARE_DEVICE_PATH,  HW_MEMMAP_DP,                     DevPathToTextMemMap        },
2387   { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP,                     DevPathToTextVendor        },
2388   { HARDWARE_DEVICE_PATH,  HW_CONTROLLER_DP,                 DevPathToTextController    },
2389   { HARDWARE_DEVICE_PATH,  HW_BMC_DP,                        DevPathToTextBmc           },
2390   { ACPI_DEVICE_PATH,      ACPI_DP,                          DevPathToTextAcpi          },
2391   { ACPI_DEVICE_PATH,      ACPI_EXTENDED_DP,                 DevPathToTextAcpiEx        },
2392   { ACPI_DEVICE_PATH,      ACPI_ADR_DP,                      DevPathToTextAcpiAdr       },
2393   { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP,                     DevPathToTextAtapi         },
2394   { MESSAGING_DEVICE_PATH, MSG_SCSI_DP,                      DevPathToTextScsi          },
2395   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP,              DevPathToTextFibre         },
2396   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP,            DevPathToTextFibreEx       },
2397   { MESSAGING_DEVICE_PATH, MSG_SASEX_DP,                     DevPathToTextSasEx         },
2398   { MESSAGING_DEVICE_PATH, MSG_NVME_NAMESPACE_DP,            DevPathToTextNVMe          },
2399   { MESSAGING_DEVICE_PATH, MSG_UFS_DP,                       DevPathToTextUfs           },
2400   { MESSAGING_DEVICE_PATH, MSG_SD_DP,                        DevPathToTextSd            },
2401   { MESSAGING_DEVICE_PATH, MSG_EMMC_DP,                      DevPathToTextEmmc          },
2402   { MESSAGING_DEVICE_PATH, MSG_1394_DP,                      DevPathToText1394          },
2403   { MESSAGING_DEVICE_PATH, MSG_USB_DP,                       DevPathToTextUsb           },
2404   { MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP,                  DevPathToTextUsbWWID       },
2405   { MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP,       DevPathToTextLogicalUnit   },
2406   { MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,                 DevPathToTextUsbClass      },
2407   { MESSAGING_DEVICE_PATH, MSG_SATA_DP,                      DevPathToTextSata          },
2408   { MESSAGING_DEVICE_PATH, MSG_I2O_DP,                       DevPathToTextI2O           },
2409   { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,                  DevPathToTextMacAddr       },
2410   { MESSAGING_DEVICE_PATH, MSG_IPv4_DP,                      DevPathToTextIPv4          },
2411   { MESSAGING_DEVICE_PATH, MSG_IPv6_DP,                      DevPathToTextIPv6          },
2412   { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP,                DevPathToTextInfiniBand    },
2413   { MESSAGING_DEVICE_PATH, MSG_UART_DP,                      DevPathToTextUart          },
2414   { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,                    DevPathToTextVendor        },
2415   { MESSAGING_DEVICE_PATH, MSG_ISCSI_DP,                     DevPathToTextiSCSI         },
2416   { MESSAGING_DEVICE_PATH, MSG_VLAN_DP,                      DevPathToTextVlan          },
2417   { MESSAGING_DEVICE_PATH, MSG_DNS_DP,                       DevPathToTextDns           },
2418   { MESSAGING_DEVICE_PATH, MSG_URI_DP,                       DevPathToTextUri           },
2419   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_DP,                 DevPathToTextBluetooth     },
2420   { MESSAGING_DEVICE_PATH, MSG_WIFI_DP,                      DevPathToTextWiFi          },
2421   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_LE_DP,              DevPathToTextBluetoothLE   },
2422   { MEDIA_DEVICE_PATH,     MEDIA_HARDDRIVE_DP,               DevPathToTextHardDrive     },
2423   { MEDIA_DEVICE_PATH,     MEDIA_CDROM_DP,                   DevPathToTextCDROM         },
2424   { MEDIA_DEVICE_PATH,     MEDIA_VENDOR_DP,                  DevPathToTextVendor        },
2425   { MEDIA_DEVICE_PATH,     MEDIA_PROTOCOL_DP,                DevPathToTextMediaProtocol },
2426   { MEDIA_DEVICE_PATH,     MEDIA_FILEPATH_DP,                DevPathToTextFilePath      },
2427   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_VOL_DP,             DevPathToTextFv            },
2428   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_FILE_DP,            DevPathToTextFvFile        },
2429   { MEDIA_DEVICE_PATH,     MEDIA_RELATIVE_OFFSET_RANGE_DP,   DevPathRelativeOffsetRange },
2430   { MEDIA_DEVICE_PATH,     MEDIA_RAM_DISK_DP,                DevPathToTextRamDisk       },
2431   { BBS_DEVICE_PATH,       BBS_BBS_DP,                       DevPathToTextBBS           },
2432   { END_DEVICE_PATH_TYPE,  END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance   },
2433   { 0,                     0,                                NULL                       }
2434 };
2435 
2436 /**
2437   Converts a device node to its string representation.
2438 
2439   @param DeviceNode        A Pointer to the device node to be converted.
2440   @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
2441                            of the display node is used, where applicable. If DisplayOnly
2442                            is FALSE, then the longer text representation of the display node
2443                            is used.
2444   @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
2445                            representation for a device node can be used, where applicable.
2446 
2447   @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
2448           is NULL or there was insufficient memory.
2449 
2450 **/
2451 static char *
2452 EFIAPI
UefiDevicePathLibConvertDeviceNodeToText(IN CONST EFI_DEVICE_PATH_PROTOCOL * DeviceNode,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2453 UefiDevicePathLibConvertDeviceNodeToText (
2454   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
2455   IN BOOLEAN                         DisplayOnly,
2456   IN BOOLEAN                         AllowShortcuts
2457   )
2458 {
2459   POOL_PRINT           Str;
2460   UINTN                Index;
2461   DEVICE_PATH_TO_TEXT  ToText;
2462   EFI_DEVICE_PATH_PROTOCOL  *Node;
2463 
2464   if (DeviceNode == NULL) {
2465     return NULL;
2466   }
2467 
2468   ZeroMem (&Str, sizeof (Str));
2469 
2470   //
2471   // Process the device path node
2472   // If not found, use a generic function
2473   //
2474   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DeviceNode);
2475   ToText = DevPathToTextNodeGeneric;
2476   for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index++) {
2477     if ((DevicePathType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].Type) &&
2478         (DevicePathSubType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].SubType)
2479         )
2480     {
2481       ToText = mUefiDevicePathLibToTextTable[Index].Function;
2482       break;
2483     }
2484   }
2485 
2486   //
2487   // Print this node
2488   //
2489   ToText (&Str, (VOID *)Node, DisplayOnly, AllowShortcuts);
2490 
2491   ASSERT (Str.Str != NULL);
2492   return Str.Str;
2493 }
2494 
2495 /**
2496   Converts a device path to its text representation.
2497 
2498   @param DevicePath      A Pointer to the device to be converted.
2499   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2500                          of the display node is used, where applicable. If DisplayOnly
2501                          is FALSE, then the longer text representation of the display node
2502                          is used.
2503   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2504                          representation for a device node can be used, where applicable.
2505 
2506   @return A pointer to the allocated text representation of the device path or
2507           NULL if DeviceNode is NULL or there was insufficient memory.
2508 
2509 **/
2510 static char *
2511 EFIAPI
UefiDevicePathLibConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN BOOLEAN DisplayOnly,IN BOOLEAN AllowShortcuts)2512 UefiDevicePathLibConvertDevicePathToText (
2513   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
2514   IN BOOLEAN                         DisplayOnly,
2515   IN BOOLEAN                         AllowShortcuts
2516   )
2517 {
2518   POOL_PRINT                Str;
2519   EFI_DEVICE_PATH_PROTOCOL  *Node;
2520   EFI_DEVICE_PATH_PROTOCOL  *AlignedNode;
2521   UINTN                     Index;
2522   DEVICE_PATH_TO_TEXT       ToText;
2523 
2524   if (DevicePath == NULL) {
2525     return NULL;
2526   }
2527 
2528   ZeroMem (&Str, sizeof (Str));
2529 
2530   //
2531   // Process each device path node
2532   //
2533   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DevicePath);
2534   while (!IsDevicePathEnd (Node)) {
2535     //
2536     // Find the handler to dump this device path node
2537     // If not found, use a generic function
2538     //
2539     ToText = DevPathToTextNodeGeneric;
2540     for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index += 1) {
2541       if ((DevicePathType (Node) == mUefiDevicePathLibToTextTable[Index].Type) &&
2542           (DevicePathSubType (Node) == mUefiDevicePathLibToTextTable[Index].SubType)
2543           )
2544       {
2545         ToText = mUefiDevicePathLibToTextTable[Index].Function;
2546         break;
2547       }
2548     }
2549 
2550     //
2551     //  Put a path separator in if needed
2552     //
2553     if ((Str.Count != 0) && (ToText != DevPathToTextEndInstance)) {
2554       if (Str.Str[Str.Count] != ',') {
2555         UefiDevicePathLibCatPrint (&Str, "/");
2556       }
2557     }
2558 
2559     AlignedNode = AllocateCopyPool (DevicePathNodeLength (Node), Node);
2560     //
2561     // Print this node of the device path
2562     //
2563     ToText (&Str, AlignedNode, DisplayOnly, AllowShortcuts);
2564     FreePool (AlignedNode);
2565 
2566     //
2567     // Next device path node
2568     //
2569     Node = NextDevicePathNode (Node);
2570   }
2571 
2572   if (Str.Str == NULL) {
2573     return AllocateZeroPool (sizeof (CHAR16));
2574   } else {
2575     return Str.Str;
2576   }
2577 }
2578 
2579 ssize_t
efidp_format_device_path(char * buf,size_t len,const_efidp dp,ssize_t max)2580 efidp_format_device_path(char *buf, size_t len, const_efidp dp, ssize_t max)
2581 {
2582 	char *str;
2583 	ssize_t retval;
2584 
2585 	/*
2586 	 * Basic sanity check on the device path.
2587 	 */
2588 	if (!IsDevicePathValid((CONST EFI_DEVICE_PATH_PROTOCOL *) dp, max)) {
2589 		*buf = '\0';
2590 		return 0;
2591 	}
2592 
2593 	str = UefiDevicePathLibConvertDevicePathToText (
2594 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2595 	if (str == NULL)
2596 		return -1;
2597 	strlcpy(buf, str, len);
2598 	retval = strlen(str);
2599 	free(str);
2600 
2601 	return retval;
2602 }
2603 
2604 ssize_t
efidp_format_device_path_node(char * buf,size_t len,const_efidp dp)2605 efidp_format_device_path_node(char *buf, size_t len, const_efidp dp)
2606 {
2607 	char *str;
2608 	ssize_t retval;
2609 
2610 	str = UefiDevicePathLibConvertDeviceNodeToText (
2611 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2612 	if (str == NULL)
2613 		return -1;
2614 	strlcpy(buf, str, len);
2615 	retval = strlen(str);
2616 	free(str);
2617 
2618 	return retval;
2619 }
2620 
2621 size_t
efidp_size(const_efidp dp)2622 efidp_size(const_efidp dp)
2623 {
2624 
2625 	return GetDevicePathSize(__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp));
2626 }
2627 
2628 char *
efidp_extract_file_path(const_efidp dp)2629 efidp_extract_file_path(const_efidp dp)
2630 {
2631 	const FILEPATH_DEVICE_PATH  *fp;
2632 	char *name = NULL;
2633 
2634 	fp = (const void *)dp;
2635 	ucs2_to_utf8(fp->PathName, &name);
2636 	return name;
2637 }
2638