xref: /freebsd/lib/libefivar/efivar-dp-format.c (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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   ASSERT (UriStr != NULL);
1908 
1909   CopyMem (UriStr, Uri->Uri, UriLength);
1910   UriStr[UriLength] = '\0';
1911   UefiDevicePathLibCatPrint (Str, "Uri(%s)", UriStr);
1912   FreePool (UriStr);
1913 }
1914 
1915 /**
1916   Converts a Hard drive device path structure to its string representative.
1917 
1918   @param Str             The string representative of input device.
1919   @param DevPath         The input device path structure.
1920   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1921                          of the display node is used, where applicable. If DisplayOnly
1922                          is FALSE, then the longer text representation of the display node
1923                          is used.
1924   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1925                          representation for a device node can be used, where applicable.
1926 
1927 **/
1928 static VOID
1929 DevPathToTextHardDrive (
1930   IN OUT POOL_PRINT  *Str,
1931   IN VOID            *DevPath,
1932   IN BOOLEAN         DisplayOnly,
1933   IN BOOLEAN         AllowShortcuts
1934   )
1935 {
1936   HARDDRIVE_DEVICE_PATH  *Hd;
1937 
1938   Hd = DevPath;
1939   switch (Hd->SignatureType) {
1940     case SIGNATURE_TYPE_MBR:
1941       UefiDevicePathLibCatPrint (
1942         Str,
1943         "HD(%d,%s,0x%08x,",
1944         Hd->PartitionNumber,
1945         "MBR",
1946 //      *((UINT32 *)(&(Hd->Signature[0])))
1947         le32dec(&(Hd->Signature[0]))
1948         );
1949       break;
1950 
1951     case SIGNATURE_TYPE_GUID:
1952       UefiDevicePathLibCatPrint (
1953         Str,
1954         "HD(%d,%s,%36s,",
1955         Hd->PartitionNumber,
1956         "GPT",
1957         G(&(Hd->Signature[0]))
1958         );
1959       break;
1960 
1961     default:
1962       UefiDevicePathLibCatPrint (
1963         Str,
1964         "HD(%d,%d,0,",
1965         Hd->PartitionNumber,
1966         Hd->SignatureType
1967         );
1968       break;
1969   }
1970 
1971   UefiDevicePathLibCatPrint (Str, "0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
1972 }
1973 
1974 /**
1975   Converts a CDROM device path structure to its string representative.
1976 
1977   @param Str             The string representative of input device.
1978   @param DevPath         The input device path structure.
1979   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1980                          of the display node is used, where applicable. If DisplayOnly
1981                          is FALSE, then the longer text representation of the display node
1982                          is used.
1983   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1984                          representation for a device node can be used, where applicable.
1985 
1986 **/
1987 static VOID
1988 DevPathToTextCDROM (
1989   IN OUT POOL_PRINT  *Str,
1990   IN VOID            *DevPath,
1991   IN BOOLEAN         DisplayOnly,
1992   IN BOOLEAN         AllowShortcuts
1993   )
1994 {
1995   CDROM_DEVICE_PATH  *Cd;
1996 
1997   Cd = DevPath;
1998   if (DisplayOnly) {
1999     UefiDevicePathLibCatPrint (Str, "CDROM(0x%x)", Cd->BootEntry);
2000     return;
2001   }
2002 
2003   UefiDevicePathLibCatPrint (Str, "CDROM(0x%x,0x%lx,0x%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
2004 }
2005 
2006 /**
2007   Converts a File device path structure to its string representative.
2008 
2009   @param Str             The string representative of input device.
2010   @param DevPath         The input device path structure.
2011   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2012                          of the display node is used, where applicable. If DisplayOnly
2013                          is FALSE, then the longer text representation of the display node
2014                          is used.
2015   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2016                          representation for a device node can be used, where applicable.
2017 
2018 **/
2019 static VOID
2020 DevPathToTextFilePath (
2021   IN OUT POOL_PRINT  *Str,
2022   IN VOID            *DevPath,
2023   IN BOOLEAN         DisplayOnly,
2024   IN BOOLEAN         AllowShortcuts
2025   )
2026 {
2027   FILEPATH_DEVICE_PATH  *Fp;
2028   char *name = NULL;
2029 
2030   Fp = DevPath;
2031   ucs2_to_utf8(Fp->PathName, &name);
2032   UefiDevicePathLibCatPrint (Str, "File(%s)", name);
2033   free(name);
2034 }
2035 
2036 /**
2037   Converts a Media protocol device path structure to its string representative.
2038 
2039   @param Str             The string representative of input device.
2040   @param DevPath         The input device path structure.
2041   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2042                          of the display node is used, where applicable. If DisplayOnly
2043                          is FALSE, then the longer text representation of the display node
2044                          is used.
2045   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2046                          representation for a device node can be used, where applicable.
2047 
2048 **/
2049 static VOID
2050 DevPathToTextMediaProtocol (
2051   IN OUT POOL_PRINT  *Str,
2052   IN VOID            *DevPath,
2053   IN BOOLEAN         DisplayOnly,
2054   IN BOOLEAN         AllowShortcuts
2055   )
2056 {
2057   MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
2058 
2059   MediaProt = DevPath;
2060   UefiDevicePathLibCatPrint (Str, "Media(%36s)", G(&MediaProt->Protocol));
2061 }
2062 
2063 /**
2064   Converts a Firmware Volume device path structure to its string representative.
2065 
2066   @param Str             The string representative of input device.
2067   @param DevPath         The input device path structure.
2068   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2069                          of the display node is used, where applicable. If DisplayOnly
2070                          is FALSE, then the longer text representation of the display node
2071                          is used.
2072   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2073                          representation for a device node can be used, where applicable.
2074 
2075 **/
2076 static VOID
2077 DevPathToTextFv (
2078   IN OUT POOL_PRINT  *Str,
2079   IN VOID            *DevPath,
2080   IN BOOLEAN         DisplayOnly,
2081   IN BOOLEAN         AllowShortcuts
2082   )
2083 {
2084   MEDIA_FW_VOL_DEVICE_PATH  *Fv;
2085 
2086   Fv = DevPath;
2087   UefiDevicePathLibCatPrint (Str, "Fv(%36s)", G(&Fv->FvName));
2088 }
2089 
2090 /**
2091   Converts a Firmware Volume File device path structure to its string representative.
2092 
2093   @param Str             The string representative of input device.
2094   @param DevPath         The input device path structure.
2095   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2096                          of the display node is used, where applicable. If DisplayOnly
2097                          is FALSE, then the longer text representation of the display node
2098                          is used.
2099   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2100                          representation for a device node can be used, where applicable.
2101 
2102 **/
2103 static VOID
2104 DevPathToTextFvFile (
2105   IN OUT POOL_PRINT  *Str,
2106   IN VOID            *DevPath,
2107   IN BOOLEAN         DisplayOnly,
2108   IN BOOLEAN         AllowShortcuts
2109   )
2110 {
2111   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFile;
2112 
2113   FvFile = DevPath;
2114   UefiDevicePathLibCatPrint (Str, "FvFile(%36s)", G(&FvFile->FvFileName));
2115 }
2116 
2117 /**
2118   Converts a Relative Offset device path structure to its string representative.
2119 
2120   @param Str             The string representative of input device.
2121   @param DevPath         The input device path structure.
2122   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2123                          of the display node is used, where applicable. If DisplayOnly
2124                          is FALSE, then the longer text representation of the display node
2125                          is used.
2126   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2127                          representation for a device node can be used, where applicable.
2128 
2129 **/
2130 static VOID
2131 DevPathRelativeOffsetRange (
2132   IN OUT POOL_PRINT  *Str,
2133   IN VOID            *DevPath,
2134   IN BOOLEAN         DisplayOnly,
2135   IN BOOLEAN         AllowShortcuts
2136   )
2137 {
2138   MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  *Offset;
2139 
2140   Offset = DevPath;
2141   UefiDevicePathLibCatPrint (
2142     Str,
2143     "Offset(0x%lx,0x%lx)",
2144     Offset->StartingOffset,
2145     Offset->EndingOffset
2146     );
2147 }
2148 
2149 /**
2150   Converts a Ram Disk device path structure to its string representative.
2151 
2152   @param Str             The string representative of input device.
2153   @param DevPath         The input device path structure.
2154   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2155                          of the display node is used, where applicable. If DisplayOnly
2156                          is FALSE, then the longer text representation of the display node
2157                          is used.
2158   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2159                          representation for a device node can be used, where applicable.
2160 
2161 **/
2162 static VOID
2163 DevPathToTextRamDisk (
2164   IN OUT POOL_PRINT  *Str,
2165   IN VOID            *DevPath,
2166   IN BOOLEAN         DisplayOnly,
2167   IN BOOLEAN         AllowShortcuts
2168   )
2169 {
2170   MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
2171 
2172   RamDisk = DevPath;
2173 
2174   if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid)) {
2175     UefiDevicePathLibCatPrint (
2176       Str,
2177       "VirtualDisk(0x%lx,0x%lx,%d)",
2178       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2179       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2180       RamDisk->Instance
2181       );
2182   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid)) {
2183     UefiDevicePathLibCatPrint (
2184       Str,
2185       "VirtualCD(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, &gEfiPersistentVirtualDiskGuid)) {
2191     UefiDevicePathLibCatPrint (
2192       Str,
2193       "PersistentVirtualDisk(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, &gEfiPersistentVirtualCdGuid)) {
2199     UefiDevicePathLibCatPrint (
2200       Str,
2201       "PersistentVirtualCD(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 {
2207     UefiDevicePathLibCatPrint (
2208       Str,
2209       "RamDisk(0x%lx,0x%lx,%d,%36s)",
2210       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2211       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2212       RamDisk->Instance,
2213       G(&RamDisk->TypeGuid)
2214       );
2215   }
2216 }
2217 
2218 /**
2219   Converts a BIOS Boot Specification device path structure to its string representative.
2220 
2221   @param Str             The string representative of input device.
2222   @param DevPath         The input device path structure.
2223   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2224                          of the display node is used, where applicable. If DisplayOnly
2225                          is FALSE, then the longer text representation of the display node
2226                          is used.
2227   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2228                          representation for a device node can be used, where applicable.
2229 
2230 **/
2231 static VOID
2232 DevPathToTextBBS (
2233   IN OUT POOL_PRINT  *Str,
2234   IN VOID            *DevPath,
2235   IN BOOLEAN         DisplayOnly,
2236   IN BOOLEAN         AllowShortcuts
2237   )
2238 {
2239   BBS_BBS_DEVICE_PATH  *Bbs;
2240   const char           *Type;
2241 
2242   Bbs = DevPath;
2243   switch (Bbs->DeviceType) {
2244     case BBS_TYPE_FLOPPY:
2245       Type = "Floppy";
2246       break;
2247 
2248     case BBS_TYPE_HARDDRIVE:
2249       Type = "HD";
2250       break;
2251 
2252     case BBS_TYPE_CDROM:
2253       Type = "CDROM";
2254       break;
2255 
2256     case BBS_TYPE_PCMCIA:
2257       Type = "PCMCIA";
2258       break;
2259 
2260     case BBS_TYPE_USB:
2261       Type = "USB";
2262       break;
2263 
2264     case BBS_TYPE_EMBEDDED_NETWORK:
2265       Type = "Network";
2266       break;
2267 
2268     default:
2269       Type = NULL;
2270       break;
2271   }
2272 
2273   if (Type != NULL) {
2274     UefiDevicePathLibCatPrint (Str, "BBS(%s,%s", Type, Bbs->String);
2275   } else {
2276     UefiDevicePathLibCatPrint (Str, "BBS(0x%x,%s", Bbs->DeviceType, Bbs->String);
2277   }
2278 
2279   if (DisplayOnly) {
2280     UefiDevicePathLibCatPrint (Str, ")");
2281     return;
2282   }
2283 
2284   UefiDevicePathLibCatPrint (Str, ",0x%x)", Bbs->StatusFlag);
2285 }
2286 
2287 /**
2288   Converts an End-of-Device-Path structure to its string representative.
2289 
2290   @param Str             The string representative of input device.
2291   @param DevPath         The input device path structure.
2292   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2293                          of the display node is used, where applicable. If DisplayOnly
2294                          is FALSE, then the longer text representation of the display node
2295                          is used.
2296   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2297                          representation for a device node can be used, where applicable.
2298 
2299 **/
2300 static VOID
2301 DevPathToTextEndInstance (
2302   IN OUT POOL_PRINT  *Str,
2303   IN VOID            *DevPath,
2304   IN BOOLEAN         DisplayOnly,
2305   IN BOOLEAN         AllowShortcuts
2306   )
2307 {
2308   UefiDevicePathLibCatPrint (Str, ",");
2309 }
2310 
2311 GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_GENERIC_TABLE  mUefiDevicePathLibToTextTableGeneric[] = {
2312   { HARDWARE_DEVICE_PATH,  "HardwarePath" },
2313   { ACPI_DEVICE_PATH,      "AcpiPath"     },
2314   { MESSAGING_DEVICE_PATH, "Msg"          },
2315   { MEDIA_DEVICE_PATH,     "MediaPath"    },
2316   { BBS_DEVICE_PATH,       "BbsPath"      },
2317   { 0,                     NULL            }
2318 };
2319 
2320 /**
2321   Converts an unknown device path structure to its string representative.
2322 
2323   @param Str             The string representative of input device.
2324   @param DevPath         The input device path structure.
2325   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2326                          of the display node is used, where applicable. If DisplayOnly
2327                          is FALSE, then the longer text representation of the display node
2328                          is used.
2329   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2330                          representation for a device node can be used, where applicable.
2331 
2332 **/
2333 static VOID
2334 DevPathToTextNodeGeneric (
2335   IN OUT POOL_PRINT  *Str,
2336   IN VOID            *DevPath,
2337   IN BOOLEAN         DisplayOnly,
2338   IN BOOLEAN         AllowShortcuts
2339   )
2340 {
2341   EFI_DEVICE_PATH_PROTOCOL  *Node;
2342   UINTN                     Index;
2343 
2344   Node = DevPath;
2345 
2346   for (Index = 0; mUefiDevicePathLibToTextTableGeneric[Index].Text != NULL; Index++) {
2347     if (DevicePathType (Node) == mUefiDevicePathLibToTextTableGeneric[Index].Type) {
2348       break;
2349     }
2350   }
2351 
2352   if (mUefiDevicePathLibToTextTableGeneric[Index].Text == NULL) {
2353     //
2354     // It's a node whose type cannot be recognized
2355     //
2356     UefiDevicePathLibCatPrint (Str, "Path(%d,%d", DevicePathType (Node), DevicePathSubType (Node));
2357   } else {
2358     //
2359     // It's a node whose type can be recognized
2360     //
2361     UefiDevicePathLibCatPrint (Str, "%s(%d", mUefiDevicePathLibToTextTableGeneric[Index].Text, DevicePathSubType (Node));
2362   }
2363 
2364   Index = sizeof (EFI_DEVICE_PATH_PROTOCOL);
2365   if (Index < DevicePathNodeLength (Node)) {
2366     UefiDevicePathLibCatPrint (Str, ",");
2367     for ( ; Index < DevicePathNodeLength (Node); Index++) {
2368       UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *)Node)[Index]);
2369     }
2370   }
2371 
2372   UefiDevicePathLibCatPrint (Str, ")");
2373 }
2374 
2375 static const DEVICE_PATH_TO_TEXT_TABLE  mUefiDevicePathLibToTextTable[] = {
2376   { HARDWARE_DEVICE_PATH,  HW_PCI_DP,                        DevPathToTextPci           },
2377   { HARDWARE_DEVICE_PATH,  HW_PCCARD_DP,                     DevPathToTextPccard        },
2378   { HARDWARE_DEVICE_PATH,  HW_MEMMAP_DP,                     DevPathToTextMemMap        },
2379   { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP,                     DevPathToTextVendor        },
2380   { HARDWARE_DEVICE_PATH,  HW_CONTROLLER_DP,                 DevPathToTextController    },
2381   { HARDWARE_DEVICE_PATH,  HW_BMC_DP,                        DevPathToTextBmc           },
2382   { ACPI_DEVICE_PATH,      ACPI_DP,                          DevPathToTextAcpi          },
2383   { ACPI_DEVICE_PATH,      ACPI_EXTENDED_DP,                 DevPathToTextAcpiEx        },
2384   { ACPI_DEVICE_PATH,      ACPI_ADR_DP,                      DevPathToTextAcpiAdr       },
2385   { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP,                     DevPathToTextAtapi         },
2386   { MESSAGING_DEVICE_PATH, MSG_SCSI_DP,                      DevPathToTextScsi          },
2387   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP,              DevPathToTextFibre         },
2388   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP,            DevPathToTextFibreEx       },
2389   { MESSAGING_DEVICE_PATH, MSG_SASEX_DP,                     DevPathToTextSasEx         },
2390   { MESSAGING_DEVICE_PATH, MSG_NVME_NAMESPACE_DP,            DevPathToTextNVMe          },
2391   { MESSAGING_DEVICE_PATH, MSG_UFS_DP,                       DevPathToTextUfs           },
2392   { MESSAGING_DEVICE_PATH, MSG_SD_DP,                        DevPathToTextSd            },
2393   { MESSAGING_DEVICE_PATH, MSG_EMMC_DP,                      DevPathToTextEmmc          },
2394   { MESSAGING_DEVICE_PATH, MSG_1394_DP,                      DevPathToText1394          },
2395   { MESSAGING_DEVICE_PATH, MSG_USB_DP,                       DevPathToTextUsb           },
2396   { MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP,                  DevPathToTextUsbWWID       },
2397   { MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP,       DevPathToTextLogicalUnit   },
2398   { MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,                 DevPathToTextUsbClass      },
2399   { MESSAGING_DEVICE_PATH, MSG_SATA_DP,                      DevPathToTextSata          },
2400   { MESSAGING_DEVICE_PATH, MSG_I2O_DP,                       DevPathToTextI2O           },
2401   { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,                  DevPathToTextMacAddr       },
2402   { MESSAGING_DEVICE_PATH, MSG_IPv4_DP,                      DevPathToTextIPv4          },
2403   { MESSAGING_DEVICE_PATH, MSG_IPv6_DP,                      DevPathToTextIPv6          },
2404   { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP,                DevPathToTextInfiniBand    },
2405   { MESSAGING_DEVICE_PATH, MSG_UART_DP,                      DevPathToTextUart          },
2406   { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,                    DevPathToTextVendor        },
2407   { MESSAGING_DEVICE_PATH, MSG_ISCSI_DP,                     DevPathToTextiSCSI         },
2408   { MESSAGING_DEVICE_PATH, MSG_VLAN_DP,                      DevPathToTextVlan          },
2409   { MESSAGING_DEVICE_PATH, MSG_DNS_DP,                       DevPathToTextDns           },
2410   { MESSAGING_DEVICE_PATH, MSG_URI_DP,                       DevPathToTextUri           },
2411   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_DP,                 DevPathToTextBluetooth     },
2412   { MESSAGING_DEVICE_PATH, MSG_WIFI_DP,                      DevPathToTextWiFi          },
2413   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_LE_DP,              DevPathToTextBluetoothLE   },
2414   { MEDIA_DEVICE_PATH,     MEDIA_HARDDRIVE_DP,               DevPathToTextHardDrive     },
2415   { MEDIA_DEVICE_PATH,     MEDIA_CDROM_DP,                   DevPathToTextCDROM         },
2416   { MEDIA_DEVICE_PATH,     MEDIA_VENDOR_DP,                  DevPathToTextVendor        },
2417   { MEDIA_DEVICE_PATH,     MEDIA_PROTOCOL_DP,                DevPathToTextMediaProtocol },
2418   { MEDIA_DEVICE_PATH,     MEDIA_FILEPATH_DP,                DevPathToTextFilePath      },
2419   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_VOL_DP,             DevPathToTextFv            },
2420   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_FILE_DP,            DevPathToTextFvFile        },
2421   { MEDIA_DEVICE_PATH,     MEDIA_RELATIVE_OFFSET_RANGE_DP,   DevPathRelativeOffsetRange },
2422   { MEDIA_DEVICE_PATH,     MEDIA_RAM_DISK_DP,                DevPathToTextRamDisk       },
2423   { BBS_DEVICE_PATH,       BBS_BBS_DP,                       DevPathToTextBBS           },
2424   { END_DEVICE_PATH_TYPE,  END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance   },
2425   { 0,                     0,                                NULL                       }
2426 };
2427 
2428 /**
2429   Converts a device node to its string representation.
2430 
2431   @param DeviceNode        A Pointer to the device node to be converted.
2432   @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
2433                            of the display node is used, where applicable. If DisplayOnly
2434                            is FALSE, then the longer text representation of the display node
2435                            is used.
2436   @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
2437                            representation for a device node can be used, where applicable.
2438 
2439   @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
2440           is NULL or there was insufficient memory.
2441 
2442 **/
2443 static char *
2444 EFIAPI
2445 UefiDevicePathLibConvertDeviceNodeToText (
2446   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
2447   IN BOOLEAN                         DisplayOnly,
2448   IN BOOLEAN                         AllowShortcuts
2449   )
2450 {
2451   POOL_PRINT           Str;
2452   UINTN                Index;
2453   DEVICE_PATH_TO_TEXT  ToText;
2454   EFI_DEVICE_PATH_PROTOCOL  *Node;
2455 
2456   if (DeviceNode == NULL) {
2457     return NULL;
2458   }
2459 
2460   ZeroMem (&Str, sizeof (Str));
2461 
2462   //
2463   // Process the device path node
2464   // If not found, use a generic function
2465   //
2466   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DeviceNode);
2467   ToText = DevPathToTextNodeGeneric;
2468   for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index++) {
2469     if ((DevicePathType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].Type) &&
2470         (DevicePathSubType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].SubType)
2471         )
2472     {
2473       ToText = mUefiDevicePathLibToTextTable[Index].Function;
2474       break;
2475     }
2476   }
2477 
2478   //
2479   // Print this node
2480   //
2481   ToText (&Str, (VOID *)Node, DisplayOnly, AllowShortcuts);
2482 
2483   ASSERT (Str.Str != NULL);
2484   return Str.Str;
2485 }
2486 
2487 /**
2488   Converts a device path to its text representation.
2489 
2490   @param DevicePath      A Pointer to the device to be converted.
2491   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2492                          of the display node is used, where applicable. If DisplayOnly
2493                          is FALSE, then the longer text representation of the display node
2494                          is used.
2495   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2496                          representation for a device node can be used, where applicable.
2497 
2498   @return A pointer to the allocated text representation of the device path or
2499           NULL if DeviceNode is NULL or there was insufficient memory.
2500 
2501 **/
2502 static char *
2503 EFIAPI
2504 UefiDevicePathLibConvertDevicePathToText (
2505   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
2506   IN BOOLEAN                         DisplayOnly,
2507   IN BOOLEAN                         AllowShortcuts
2508   )
2509 {
2510   POOL_PRINT                Str;
2511   EFI_DEVICE_PATH_PROTOCOL  *Node;
2512   EFI_DEVICE_PATH_PROTOCOL  *AlignedNode;
2513   UINTN                     Index;
2514   DEVICE_PATH_TO_TEXT       ToText;
2515 
2516   if (DevicePath == NULL) {
2517     return NULL;
2518   }
2519 
2520   ZeroMem (&Str, sizeof (Str));
2521 
2522   //
2523   // Process each device path node
2524   //
2525   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DevicePath);
2526   while (!IsDevicePathEnd (Node)) {
2527     //
2528     // Find the handler to dump this device path node
2529     // If not found, use a generic function
2530     //
2531     ToText = DevPathToTextNodeGeneric;
2532     for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index += 1) {
2533       if ((DevicePathType (Node) == mUefiDevicePathLibToTextTable[Index].Type) &&
2534           (DevicePathSubType (Node) == mUefiDevicePathLibToTextTable[Index].SubType)
2535           )
2536       {
2537         ToText = mUefiDevicePathLibToTextTable[Index].Function;
2538         break;
2539       }
2540     }
2541 
2542     //
2543     //  Put a path separator in if needed
2544     //
2545     if ((Str.Count != 0) && (ToText != DevPathToTextEndInstance)) {
2546       if (Str.Str[Str.Count] != ',') {
2547         UefiDevicePathLibCatPrint (&Str, "/");
2548       }
2549     }
2550 
2551     AlignedNode = AllocateCopyPool (DevicePathNodeLength (Node), Node);
2552     //
2553     // Print this node of the device path
2554     //
2555     ToText (&Str, AlignedNode, DisplayOnly, AllowShortcuts);
2556     FreePool (AlignedNode);
2557 
2558     //
2559     // Next device path node
2560     //
2561     Node = NextDevicePathNode (Node);
2562   }
2563 
2564   if (Str.Str == NULL) {
2565     return AllocateZeroPool (sizeof (CHAR16));
2566   } else {
2567     return Str.Str;
2568   }
2569 }
2570 
2571 ssize_t
2572 efidp_format_device_path(char *buf, size_t len, const_efidp dp, ssize_t max)
2573 {
2574 	char *str;
2575 	ssize_t retval;
2576 
2577 	/*
2578 	 * Basic sanity check on the device path.
2579 	 */
2580 	if (!IsDevicePathValid((CONST EFI_DEVICE_PATH_PROTOCOL *) dp, max)) {
2581 		*buf = '\0';
2582 		return 0;
2583 	}
2584 
2585 	str = UefiDevicePathLibConvertDevicePathToText (
2586 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2587 	if (str == NULL)
2588 		return -1;
2589 	strlcpy(buf, str, len);
2590 	retval = strlen(str);
2591 	free(str);
2592 
2593 	return retval;
2594 }
2595 
2596 ssize_t
2597 efidp_format_device_path_node(char *buf, size_t len, const_efidp dp)
2598 {
2599 	char *str;
2600 	ssize_t retval;
2601 
2602 	str = UefiDevicePathLibConvertDeviceNodeToText (
2603 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2604 	if (str == NULL)
2605 		return -1;
2606 	strlcpy(buf, str, len);
2607 	retval = strlen(str);
2608 	free(str);
2609 
2610 	return retval;
2611 }
2612 
2613 size_t
2614 efidp_size(const_efidp dp)
2615 {
2616 
2617 	return GetDevicePathSize(__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp));
2618 }
2619 
2620 char *
2621 efidp_extract_file_path(const_efidp dp)
2622 {
2623 	const FILEPATH_DEVICE_PATH  *fp;
2624 	char *name = NULL;
2625 
2626 	fp = (const void *)dp;
2627 	ucs2_to_utf8(fp->PathName, &name);
2628 	return name;
2629 }
2630