xref: /freebsd/lib/libefivar/efivar-dp-format.c (revision 02e9120893770924227138ba49df1edb3896112a)
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   CHAR8                          *HIDStr;
482   CHAR8                          *UIDStr;
483   CHAR8                          *CIDStr;
484   char                           HIDText[11];
485   char                           CIDText[11];
486 
487   AcpiEx = DevPath;
488   HIDStr = (CHAR8 *)(((UINT8 *)AcpiEx) + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
489   UIDStr = HIDStr + AsciiStrLen (HIDStr) + 1;
490   CIDStr = UIDStr + AsciiStrLen (UIDStr) + 1;
491 
492   if (DisplayOnly) {
493     if ((EISA_ID_TO_NUM (AcpiEx->HID) == 0x0A03) ||
494         ((EISA_ID_TO_NUM (AcpiEx->CID) == 0x0A03) && (EISA_ID_TO_NUM (AcpiEx->HID) != 0x0A08)))
495     {
496       if (AcpiEx->UID == 0) {
497         UefiDevicePathLibCatPrint (Str, "PciRoot(%s)", UIDStr);
498       } else {
499         UefiDevicePathLibCatPrint (Str, "PciRoot(0x%x)", AcpiEx->UID);
500       }
501 
502       return;
503     }
504 
505     if ((EISA_ID_TO_NUM (AcpiEx->HID) == 0x0A08) || (EISA_ID_TO_NUM (AcpiEx->CID) == 0x0A08)) {
506       if (AcpiEx->UID == 0) {
507         UefiDevicePathLibCatPrint (Str, "PcieRoot(%s)", UIDStr);
508       } else {
509         UefiDevicePathLibCatPrint (Str, "PcieRoot(0x%x)", AcpiEx->UID);
510       }
511 
512       return;
513     }
514   }
515 
516   //
517   // Converts EISA identification to string.
518   //
519   UnicodeSPrint (
520     HIDText,
521     sizeof (HIDText),
522     "%c%c%c%04X",
523     ((AcpiEx->HID >> 10) & 0x1f) + 'A' - 1,
524     ((AcpiEx->HID >>  5) & 0x1f) + 'A' - 1,
525     ((AcpiEx->HID >>  0) & 0x1f) + 'A' - 1,
526     (AcpiEx->HID >> 16) & 0xFFFF
527     );
528   UnicodeSPrint (
529     CIDText,
530     sizeof (CIDText),
531     "%c%c%c%04X",
532     ((AcpiEx->CID >> 10) & 0x1f) + 'A' - 1,
533     ((AcpiEx->CID >>  5) & 0x1f) + 'A' - 1,
534     ((AcpiEx->CID >>  0) & 0x1f) + 'A' - 1,
535     (AcpiEx->CID >> 16) & 0xFFFF
536     );
537 
538   if ((*HIDStr == '\0') && (*CIDStr == '\0') && (*UIDStr != '\0')) {
539     //
540     // use AcpiExp()
541     //
542     if (AcpiEx->CID == 0) {
543       UefiDevicePathLibCatPrint (
544         Str,
545         "AcpiExp(%s,0,%s)",
546         HIDText,
547         UIDStr
548         );
549     } else {
550       UefiDevicePathLibCatPrint (
551         Str,
552         "AcpiExp(%s,%s,%s)",
553         HIDText,
554         CIDText,
555         UIDStr
556         );
557     }
558   } else {
559     if (DisplayOnly) {
560       //
561       // display only
562       //
563       if (AcpiEx->HID == 0) {
564         UefiDevicePathLibCatPrint (Str, "AcpiEx(%s,", HIDStr);
565       } else {
566         UefiDevicePathLibCatPrint (Str, "AcpiEx(%s,", HIDText);
567       }
568 
569       if (AcpiEx->CID == 0) {
570         UefiDevicePathLibCatPrint (Str, "%s,", CIDStr);
571       } else {
572         UefiDevicePathLibCatPrint (Str, "%s,", CIDText);
573       }
574 
575       if (AcpiEx->UID == 0) {
576         UefiDevicePathLibCatPrint (Str, "%s)", UIDStr);
577       } else {
578         UefiDevicePathLibCatPrint (Str, "0x%x)", AcpiEx->UID);
579       }
580     } else {
581       UefiDevicePathLibCatPrint (
582         Str,
583         "AcpiEx(%s,%s,0x%x,%s,%s,%s)",
584         HIDText,
585         CIDText,
586         AcpiEx->UID,
587         HIDStr,
588         CIDStr,
589         UIDStr
590         );
591     }
592   }
593 }
594 
595 /**
596   Converts a ACPI address device path structure to its string representative.
597 
598   @param Str             The string representative of input device.
599   @param DevPath         The input device path structure.
600   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
601                          of the display node is used, where applicable. If DisplayOnly
602                          is FALSE, then the longer text representation of the display node
603                          is used.
604   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
605                          representation for a device node can be used, where applicable.
606 
607 **/
608 static VOID
609 DevPathToTextAcpiAdr (
610   IN OUT POOL_PRINT  *Str,
611   IN VOID            *DevPath,
612   IN BOOLEAN         DisplayOnly,
613   IN BOOLEAN         AllowShortcuts
614   )
615 {
616   ACPI_ADR_DEVICE_PATH  *AcpiAdr;
617   UINT32                *Addr;
618   UINT16                Index;
619   UINT16                Length;
620   UINT16                AdditionalAdrCount;
621 
622   AcpiAdr            = DevPath;
623   Length             = (UINT16)DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)AcpiAdr);
624   AdditionalAdrCount = (UINT16)((Length - 8) / 4);
625 
626   UefiDevicePathLibCatPrint (Str, "AcpiAdr(0x%x", AcpiAdr->ADR);
627   Addr = &AcpiAdr->ADR + 1;
628   for (Index = 0; Index < AdditionalAdrCount; Index++) {
629     UefiDevicePathLibCatPrint (Str, ",0x%x", Addr[Index]);
630   }
631 
632   UefiDevicePathLibCatPrint (Str, ")");
633 }
634 
635 /**
636   Converts a ATAPI device path structure to its string representative.
637 
638   @param Str             The string representative of input device.
639   @param DevPath         The input device path structure.
640   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
641                          of the display node is used, where applicable. If DisplayOnly
642                          is FALSE, then the longer text representation of the display node
643                          is used.
644   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
645                          representation for a device node can be used, where applicable.
646 
647 **/
648 static VOID
649 DevPathToTextAtapi (
650   IN OUT POOL_PRINT  *Str,
651   IN VOID            *DevPath,
652   IN BOOLEAN         DisplayOnly,
653   IN BOOLEAN         AllowShortcuts
654   )
655 {
656   ATAPI_DEVICE_PATH  *Atapi;
657 
658   Atapi = DevPath;
659 
660   if (DisplayOnly) {
661     UefiDevicePathLibCatPrint (Str, "Ata(0x%x)", Atapi->Lun);
662   } else {
663     UefiDevicePathLibCatPrint (
664       Str,
665       "Ata(%s,%s,0x%x)",
666       (Atapi->PrimarySecondary == 1) ? "Secondary" : "Primary",
667       (Atapi->SlaveMaster == 1) ? "Slave" : "Master",
668       Atapi->Lun
669       );
670   }
671 }
672 
673 /**
674   Converts a SCSI device path structure to its string representative.
675 
676   @param Str             The string representative of input device.
677   @param DevPath         The input device path structure.
678   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
679                          of the display node is used, where applicable. If DisplayOnly
680                          is FALSE, then the longer text representation of the display node
681                          is used.
682   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
683                          representation for a device node can be used, where applicable.
684 
685 **/
686 static VOID
687 DevPathToTextScsi (
688   IN OUT POOL_PRINT  *Str,
689   IN VOID            *DevPath,
690   IN BOOLEAN         DisplayOnly,
691   IN BOOLEAN         AllowShortcuts
692   )
693 {
694   SCSI_DEVICE_PATH  *Scsi;
695 
696   Scsi = DevPath;
697   UefiDevicePathLibCatPrint (Str, "Scsi(0x%x,0x%x)", Scsi->Pun, Scsi->Lun);
698 }
699 
700 /**
701   Converts a Fibre device path structure to its string representative.
702 
703   @param Str             The string representative of input device.
704   @param DevPath         The input device path structure.
705   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
706                          of the display node is used, where applicable. If DisplayOnly
707                          is FALSE, then the longer text representation of the display node
708                          is used.
709   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
710                          representation for a device node can be used, where applicable.
711 
712 **/
713 static VOID
714 DevPathToTextFibre (
715   IN OUT POOL_PRINT  *Str,
716   IN VOID            *DevPath,
717   IN BOOLEAN         DisplayOnly,
718   IN BOOLEAN         AllowShortcuts
719   )
720 {
721   FIBRECHANNEL_DEVICE_PATH  *Fibre;
722 
723   Fibre = DevPath;
724   UefiDevicePathLibCatPrint (Str, "Fibre(0x%lx,0x%lx)", Fibre->WWN, Fibre->Lun);
725 }
726 
727 /**
728   Converts a FibreEx device path structure to its string representative.
729 
730   @param Str             The string representative of input device.
731   @param DevPath         The input device path structure.
732   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
733                          of the display node is used, where applicable. If DisplayOnly
734                          is FALSE, then the longer text representation of the display node
735                          is used.
736   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
737                          representation for a device node can be used, where applicable.
738 
739 **/
740 static VOID
741 DevPathToTextFibreEx (
742   IN OUT POOL_PRINT  *Str,
743   IN VOID            *DevPath,
744   IN BOOLEAN         DisplayOnly,
745   IN BOOLEAN         AllowShortcuts
746   )
747 {
748   FIBRECHANNELEX_DEVICE_PATH  *FibreEx;
749   UINTN                       Index;
750 
751   FibreEx = DevPath;
752   UefiDevicePathLibCatPrint (Str, "FibreEx(0x");
753   for (Index = 0; Index < sizeof (FibreEx->WWN) / sizeof (FibreEx->WWN[0]); Index++) {
754     UefiDevicePathLibCatPrint (Str, "%02x", FibreEx->WWN[Index]);
755   }
756 
757   UefiDevicePathLibCatPrint (Str, ",0x");
758   for (Index = 0; Index < sizeof (FibreEx->Lun) / sizeof (FibreEx->Lun[0]); Index++) {
759     UefiDevicePathLibCatPrint (Str, "%02x", FibreEx->Lun[Index]);
760   }
761 
762   UefiDevicePathLibCatPrint (Str, ")");
763 }
764 
765 /**
766   Converts a Sas Ex device path structure to its string representative.
767 
768   @param Str             The string representative of input device.
769   @param DevPath         The input device path structure.
770   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
771                          of the display node is used, where applicable. If DisplayOnly
772                          is FALSE, then the longer text representation of the display node
773                          is used.
774   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
775                          representation for a device node can be used, where applicable.
776 
777 **/
778 static VOID
779 DevPathToTextSasEx (
780   IN OUT POOL_PRINT  *Str,
781   IN VOID            *DevPath,
782   IN BOOLEAN         DisplayOnly,
783   IN BOOLEAN         AllowShortcuts
784   )
785 {
786   SASEX_DEVICE_PATH  *SasEx;
787   UINTN              Index;
788 
789   SasEx = DevPath;
790   UefiDevicePathLibCatPrint (Str, "SasEx(0x");
791 
792   for (Index = 0; Index < sizeof (SasEx->SasAddress) / sizeof (SasEx->SasAddress[0]); Index++) {
793     UefiDevicePathLibCatPrint (Str, "%02x", SasEx->SasAddress[Index]);
794   }
795 
796   UefiDevicePathLibCatPrint (Str, ",0x");
797   for (Index = 0; Index < sizeof (SasEx->Lun) / sizeof (SasEx->Lun[0]); Index++) {
798     UefiDevicePathLibCatPrint (Str, "%02x", SasEx->Lun[Index]);
799   }
800 
801   UefiDevicePathLibCatPrint (Str, ",0x%x,", SasEx->RelativeTargetPort);
802 
803   if (((SasEx->DeviceTopology & 0x0f) == 0) && ((SasEx->DeviceTopology & BIT7) == 0)) {
804     UefiDevicePathLibCatPrint (Str, "NoTopology,0,0,0");
805   } else if (((SasEx->DeviceTopology & 0x0f) <= 2) && ((SasEx->DeviceTopology & BIT7) == 0)) {
806     UefiDevicePathLibCatPrint (
807       Str,
808       "%s,%s,%s,",
809       ((SasEx->DeviceTopology & BIT4) != 0) ? "SATA" : "SAS",
810       ((SasEx->DeviceTopology & BIT5) != 0) ? "External" : "Internal",
811       ((SasEx->DeviceTopology & BIT6) != 0) ? "Expanded" : "Direct"
812       );
813     if ((SasEx->DeviceTopology & 0x0f) == 1) {
814       UefiDevicePathLibCatPrint (Str, "0");
815     } else {
816       //
817       // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
818       //
819       UefiDevicePathLibCatPrint (Str, "0x%x", ((SasEx->DeviceTopology >> 8) & 0xff) + 1);
820     }
821   } else {
822     UefiDevicePathLibCatPrint (Str, "0x%x,0,0,0", SasEx->DeviceTopology);
823   }
824 
825   UefiDevicePathLibCatPrint (Str, ")");
826   return;
827 }
828 
829 /**
830   Converts a NVM Express Namespace device path structure to its string representative.
831 
832   @param Str             The string representative of input device.
833   @param DevPath         The input device path structure.
834   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
835                          of the display node is used, where applicable. If DisplayOnly
836                          is FALSE, then the longer text representation of the display node
837                          is used.
838   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
839                          representation for a device node can be used, where applicable.
840 
841 **/
842 static VOID
843 DevPathToTextNVMe (
844   IN OUT POOL_PRINT  *Str,
845   IN VOID            *DevPath,
846   IN BOOLEAN         DisplayOnly,
847   IN BOOLEAN         AllowShortcuts
848   )
849 {
850   NVME_NAMESPACE_DEVICE_PATH  *Nvme;
851   UINT8                       *Uuid;
852 
853   Nvme = DevPath;
854   Uuid = (UINT8 *)&Nvme->NamespaceUuid;
855   UefiDevicePathLibCatPrint (
856     Str,
857     "NVMe(0x%x,%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)",
858     Nvme->NamespaceId,
859     Uuid[7],
860     Uuid[6],
861     Uuid[5],
862     Uuid[4],
863     Uuid[3],
864     Uuid[2],
865     Uuid[1],
866     Uuid[0]
867     );
868 }
869 
870 /**
871   Converts a UFS device path structure to its string representative.
872 
873   @param Str             The string representative of input device.
874   @param DevPath         The input device path structure.
875   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
876                          of the display node is used, where applicable. If DisplayOnly
877                          is FALSE, then the longer text representation of the display node
878                          is used.
879   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
880                          representation for a device node can be used, where applicable.
881 
882 **/
883 static VOID
884 DevPathToTextUfs (
885   IN OUT POOL_PRINT  *Str,
886   IN VOID            *DevPath,
887   IN BOOLEAN         DisplayOnly,
888   IN BOOLEAN         AllowShortcuts
889   )
890 {
891   UFS_DEVICE_PATH  *Ufs;
892 
893   Ufs = DevPath;
894   UefiDevicePathLibCatPrint (Str, "UFS(0x%x,0x%x)", Ufs->Pun, Ufs->Lun);
895 }
896 
897 /**
898   Converts a SD (Secure Digital) device path structure to its string representative.
899 
900   @param Str             The string representative of input device.
901   @param DevPath         The input device path structure.
902   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
903                          of the display node is used, where applicable. If DisplayOnly
904                          is FALSE, then the longer text representation of the display node
905                          is used.
906   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
907                          representation for a device node can be used, where applicable.
908 
909 **/
910 static VOID
911 DevPathToTextSd (
912   IN OUT POOL_PRINT  *Str,
913   IN VOID            *DevPath,
914   IN BOOLEAN         DisplayOnly,
915   IN BOOLEAN         AllowShortcuts
916   )
917 {
918   SD_DEVICE_PATH  *Sd;
919 
920   Sd = DevPath;
921   UefiDevicePathLibCatPrint (
922     Str,
923     "SD(0x%x)",
924     Sd->SlotNumber
925     );
926 }
927 
928 /**
929   Converts a EMMC (Embedded MMC) device path structure to its string representative.
930 
931   @param Str             The string representative of input device.
932   @param DevPath         The input device path structure.
933   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
934                          of the display node is used, where applicable. If DisplayOnly
935                          is FALSE, then the longer text representation of the display node
936                          is used.
937   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
938                          representation for a device node can be used, where applicable.
939 
940 **/
941 static VOID
942 DevPathToTextEmmc (
943   IN OUT POOL_PRINT  *Str,
944   IN VOID            *DevPath,
945   IN BOOLEAN         DisplayOnly,
946   IN BOOLEAN         AllowShortcuts
947   )
948 {
949   EMMC_DEVICE_PATH  *Emmc;
950 
951   Emmc = DevPath;
952   UefiDevicePathLibCatPrint (
953     Str,
954     "eMMC(0x%x)",
955     Emmc->SlotNumber
956     );
957 }
958 
959 /**
960   Converts a 1394 device path structure to its string representative.
961 
962   @param Str             The string representative of input device.
963   @param DevPath         The input device path structure.
964   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
965                          of the display node is used, where applicable. If DisplayOnly
966                          is FALSE, then the longer text representation of the display node
967                          is used.
968   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
969                          representation for a device node can be used, where applicable.
970 
971 **/
972 static VOID
973 DevPathToText1394 (
974   IN OUT POOL_PRINT  *Str,
975   IN VOID            *DevPath,
976   IN BOOLEAN         DisplayOnly,
977   IN BOOLEAN         AllowShortcuts
978   )
979 {
980   F1394_DEVICE_PATH  *F1394DevPath;
981 
982   F1394DevPath = DevPath;
983   //
984   // Guid has format of IEEE-EUI64
985   //
986   UefiDevicePathLibCatPrint (Str, "I1394(%016lx)", F1394DevPath->Guid);
987 }
988 
989 /**
990   Converts a USB device path structure to its string representative.
991 
992   @param Str             The string representative of input device.
993   @param DevPath         The input device path structure.
994   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
995                          of the display node is used, where applicable. If DisplayOnly
996                          is FALSE, then the longer text representation of the display node
997                          is used.
998   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
999                          representation for a device node can be used, where applicable.
1000 
1001 **/
1002 static VOID
1003 DevPathToTextUsb (
1004   IN OUT POOL_PRINT  *Str,
1005   IN VOID            *DevPath,
1006   IN BOOLEAN         DisplayOnly,
1007   IN BOOLEAN         AllowShortcuts
1008   )
1009 {
1010   USB_DEVICE_PATH  *Usb;
1011 
1012   Usb = DevPath;
1013   UefiDevicePathLibCatPrint (Str, "USB(0x%x,0x%x)", Usb->ParentPortNumber, Usb->InterfaceNumber);
1014 }
1015 
1016 /**
1017   Converts a USB WWID device path structure to its string representative.
1018 
1019   @param Str             The string representative of input device.
1020   @param DevPath         The input device path structure.
1021   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1022                          of the display node is used, where applicable. If DisplayOnly
1023                          is FALSE, then the longer text representation of the display node
1024                          is used.
1025   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1026                          representation for a device node can be used, where applicable.
1027 
1028 **/
1029 static VOID
1030 DevPathToTextUsbWWID (
1031   IN OUT POOL_PRINT  *Str,
1032   IN VOID            *DevPath,
1033   IN BOOLEAN         DisplayOnly,
1034   IN BOOLEAN         AllowShortcuts
1035   )
1036 {
1037   USB_WWID_DEVICE_PATH  *UsbWWId;
1038   CHAR16                *SerialNumberStr;
1039   CHAR16                *NewStr;
1040   UINT16                Length;
1041 
1042   UsbWWId = DevPath;
1043 
1044   SerialNumberStr = (CHAR16 *)(&UsbWWId + 1);
1045   Length          = (UINT16)((DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)UsbWWId) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16));
1046   if ((Length >= 1) && (SerialNumberStr[Length - 1] != 0)) {
1047     //
1048     // In case no NULL terminator in SerialNumber, create a new one with NULL terminator
1049     //
1050     NewStr = AllocatePool ((Length + 1) * sizeof (CHAR16));
1051     ASSERT (NewStr != NULL);
1052     CopyMem (NewStr, SerialNumberStr, Length * sizeof (CHAR16));
1053     NewStr[Length]  = 0;
1054     SerialNumberStr = NewStr;
1055   }
1056 
1057   UefiDevicePathLibCatPrint (
1058     Str,
1059     "UsbWwid(0x%x,0x%x,0x%x,\"%S\")",
1060     UsbWWId->VendorId,
1061     UsbWWId->ProductId,
1062     UsbWWId->InterfaceNumber,
1063     SerialNumberStr
1064     );
1065 }
1066 
1067 /**
1068   Converts a Logic Unit device path structure to its string representative.
1069 
1070   @param Str             The string representative of input device.
1071   @param DevPath         The input device path structure.
1072   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1073                          of the display node is used, where applicable. If DisplayOnly
1074                          is FALSE, then the longer text representation of the display node
1075                          is used.
1076   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1077                          representation for a device node can be used, where applicable.
1078 
1079 **/
1080 static VOID
1081 DevPathToTextLogicalUnit (
1082   IN OUT POOL_PRINT  *Str,
1083   IN VOID            *DevPath,
1084   IN BOOLEAN         DisplayOnly,
1085   IN BOOLEAN         AllowShortcuts
1086   )
1087 {
1088   DEVICE_LOGICAL_UNIT_DEVICE_PATH  *LogicalUnit;
1089 
1090   LogicalUnit = DevPath;
1091   UefiDevicePathLibCatPrint (Str, "Unit(0x%x)", LogicalUnit->Lun);
1092 }
1093 
1094 /**
1095   Converts a USB class device path structure to its string representative.
1096 
1097   @param Str             The string representative of input device.
1098   @param DevPath         The input device path structure.
1099   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1100                          of the display node is used, where applicable. If DisplayOnly
1101                          is FALSE, then the longer text representation of the display node
1102                          is used.
1103   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1104                          representation for a device node can be used, where applicable.
1105 
1106 **/
1107 static VOID
1108 DevPathToTextUsbClass (
1109   IN OUT POOL_PRINT  *Str,
1110   IN VOID            *DevPath,
1111   IN BOOLEAN         DisplayOnly,
1112   IN BOOLEAN         AllowShortcuts
1113   )
1114 {
1115   USB_CLASS_DEVICE_PATH  *UsbClass;
1116   BOOLEAN                IsKnownSubClass;
1117 
1118   UsbClass = DevPath;
1119 
1120   IsKnownSubClass = TRUE;
1121   switch (UsbClass->DeviceClass) {
1122     case USB_CLASS_AUDIO:
1123       UefiDevicePathLibCatPrint (Str, "UsbAudio");
1124       break;
1125 
1126     case USB_CLASS_CDCCONTROL:
1127       UefiDevicePathLibCatPrint (Str, "UsbCDCControl");
1128       break;
1129 
1130     case USB_CLASS_HID:
1131       UefiDevicePathLibCatPrint (Str, "UsbHID");
1132       break;
1133 
1134     case USB_CLASS_IMAGE:
1135       UefiDevicePathLibCatPrint (Str, "UsbImage");
1136       break;
1137 
1138     case USB_CLASS_PRINTER:
1139       UefiDevicePathLibCatPrint (Str, "UsbPrinter");
1140       break;
1141 
1142     case USB_CLASS_MASS_STORAGE:
1143       UefiDevicePathLibCatPrint (Str, "UsbMassStorage");
1144       break;
1145 
1146     case USB_CLASS_HUB:
1147       UefiDevicePathLibCatPrint (Str, "UsbHub");
1148       break;
1149 
1150     case USB_CLASS_CDCDATA:
1151       UefiDevicePathLibCatPrint (Str, "UsbCDCData");
1152       break;
1153 
1154     case USB_CLASS_SMART_CARD:
1155       UefiDevicePathLibCatPrint (Str, "UsbSmartCard");
1156       break;
1157 
1158     case USB_CLASS_VIDEO:
1159       UefiDevicePathLibCatPrint (Str, "UsbVideo");
1160       break;
1161 
1162     case USB_CLASS_DIAGNOSTIC:
1163       UefiDevicePathLibCatPrint (Str, "UsbDiagnostic");
1164       break;
1165 
1166     case USB_CLASS_WIRELESS:
1167       UefiDevicePathLibCatPrint (Str, "UsbWireless");
1168       break;
1169 
1170     default:
1171       IsKnownSubClass = FALSE;
1172       break;
1173   }
1174 
1175   if (IsKnownSubClass) {
1176     UefiDevicePathLibCatPrint (
1177       Str,
1178       "(0x%x,0x%x,0x%x,0x%x)",
1179       UsbClass->VendorId,
1180       UsbClass->ProductId,
1181       UsbClass->DeviceSubClass,
1182       UsbClass->DeviceProtocol
1183       );
1184     return;
1185   }
1186 
1187   if (UsbClass->DeviceClass == USB_CLASS_RESERVE) {
1188     if (UsbClass->DeviceSubClass == USB_SUBCLASS_FW_UPDATE) {
1189       UefiDevicePathLibCatPrint (
1190         Str,
1191         "UsbDeviceFirmwareUpdate(0x%x,0x%x,0x%x)",
1192         UsbClass->VendorId,
1193         UsbClass->ProductId,
1194         UsbClass->DeviceProtocol
1195         );
1196       return;
1197     } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_IRDA_BRIDGE) {
1198       UefiDevicePathLibCatPrint (
1199         Str,
1200         "UsbIrdaBridge(0x%x,0x%x,0x%x)",
1201         UsbClass->VendorId,
1202         UsbClass->ProductId,
1203         UsbClass->DeviceProtocol
1204         );
1205       return;
1206     } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_TEST) {
1207       UefiDevicePathLibCatPrint (
1208         Str,
1209         "UsbTestAndMeasurement(0x%x,0x%x,0x%x)",
1210         UsbClass->VendorId,
1211         UsbClass->ProductId,
1212         UsbClass->DeviceProtocol
1213         );
1214       return;
1215     }
1216   }
1217 
1218   UefiDevicePathLibCatPrint (
1219     Str,
1220     "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
1221     UsbClass->VendorId,
1222     UsbClass->ProductId,
1223     UsbClass->DeviceClass,
1224     UsbClass->DeviceSubClass,
1225     UsbClass->DeviceProtocol
1226     );
1227 }
1228 
1229 /**
1230   Converts a SATA device path structure to its string representative.
1231 
1232   @param Str             The string representative of input device.
1233   @param DevPath         The input device path structure.
1234   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1235                          of the display node is used, where applicable. If DisplayOnly
1236                          is FALSE, then the longer text representation of the display node
1237                          is used.
1238   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1239                          representation for a device node can be used, where applicable.
1240 
1241 **/
1242 static VOID
1243 DevPathToTextSata (
1244   IN OUT POOL_PRINT  *Str,
1245   IN VOID            *DevPath,
1246   IN BOOLEAN         DisplayOnly,
1247   IN BOOLEAN         AllowShortcuts
1248   )
1249 {
1250   SATA_DEVICE_PATH  *Sata;
1251 
1252   Sata = DevPath;
1253   UefiDevicePathLibCatPrint (
1254     Str,
1255     "Sata(0x%x,0x%x,0x%x)",
1256     Sata->HBAPortNumber,
1257     Sata->PortMultiplierPortNumber,
1258     Sata->Lun
1259     );
1260 }
1261 
1262 /**
1263   Converts a I20 device path structure to its string representative.
1264 
1265   @param Str             The string representative of input device.
1266   @param DevPath         The input device path structure.
1267   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1268                          of the display node is used, where applicable. If DisplayOnly
1269                          is FALSE, then the longer text representation of the display node
1270                          is used.
1271   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1272                          representation for a device node can be used, where applicable.
1273 
1274 **/
1275 static VOID
1276 DevPathToTextI2O (
1277   IN OUT POOL_PRINT  *Str,
1278   IN VOID            *DevPath,
1279   IN BOOLEAN         DisplayOnly,
1280   IN BOOLEAN         AllowShortcuts
1281   )
1282 {
1283   I2O_DEVICE_PATH  *I2ODevPath;
1284 
1285   I2ODevPath = DevPath;
1286   UefiDevicePathLibCatPrint (Str, "I2O(0x%x)", I2ODevPath->Tid);
1287 }
1288 
1289 /**
1290   Converts a MAC address device path structure to its string representative.
1291 
1292   @param Str             The string representative of input device.
1293   @param DevPath         The input device path structure.
1294   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1295                          of the display node is used, where applicable. If DisplayOnly
1296                          is FALSE, then the longer text representation of the display node
1297                          is used.
1298   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1299                          representation for a device node can be used, where applicable.
1300 
1301 **/
1302 static VOID
1303 DevPathToTextMacAddr (
1304   IN OUT POOL_PRINT  *Str,
1305   IN VOID            *DevPath,
1306   IN BOOLEAN         DisplayOnly,
1307   IN BOOLEAN         AllowShortcuts
1308   )
1309 {
1310   MAC_ADDR_DEVICE_PATH  *MacDevPath;
1311   UINTN                 HwAddressSize;
1312   UINTN                 Index;
1313 
1314   MacDevPath = DevPath;
1315 
1316   HwAddressSize = sizeof (EFI_MAC_ADDRESS);
1317   if ((MacDevPath->IfType == 0x01) || (MacDevPath->IfType == 0x00)) {
1318     HwAddressSize = 6;
1319   }
1320 
1321   UefiDevicePathLibCatPrint (Str, "MAC(");
1322 
1323   for (Index = 0; Index < HwAddressSize; Index++) {
1324     UefiDevicePathLibCatPrint (Str, "%02x", MacDevPath->MacAddress.Addr[Index]);
1325   }
1326 
1327   UefiDevicePathLibCatPrint (Str, ",0x%x)", MacDevPath->IfType);
1328 }
1329 
1330 /**
1331   Converts network protocol string to its text representation.
1332 
1333   @param Str             The string representative of input device.
1334   @param Protocol        The network protocol ID.
1335 
1336 **/
1337 static VOID
1338 CatNetworkProtocol (
1339   IN OUT POOL_PRINT  *Str,
1340   IN UINT16          Protocol
1341   )
1342 {
1343   if (Protocol == RFC_1700_TCP_PROTOCOL) {
1344     UefiDevicePathLibCatPrint (Str, "TCP");
1345   } else if (Protocol == RFC_1700_UDP_PROTOCOL) {
1346     UefiDevicePathLibCatPrint (Str, "UDP");
1347   } else {
1348     UefiDevicePathLibCatPrint (Str, "0x%x", Protocol);
1349   }
1350 }
1351 
1352 /**
1353   Converts IP v4 address to its text representation.
1354 
1355   @param Str             The string representative of input device.
1356   @param Address         The IP v4 address.
1357 **/
1358 static VOID
1359 CatIPv4Address (
1360   IN OUT POOL_PRINT    *Str,
1361   IN EFI_IPv4_ADDRESS  *Address
1362   )
1363 {
1364   UefiDevicePathLibCatPrint (Str, "%d.%d.%d.%d", Address->Addr[0], Address->Addr[1], Address->Addr[2], Address->Addr[3]);
1365 }
1366 
1367 /**
1368   Converts IP v6 address to its text representation.
1369 
1370   @param Str             The string representative of input device.
1371   @param Address         The IP v6 address.
1372 **/
1373 static VOID
1374 CatIPv6Address (
1375   IN OUT POOL_PRINT    *Str,
1376   IN EFI_IPv6_ADDRESS  *Address
1377   )
1378 {
1379   UefiDevicePathLibCatPrint (
1380     Str,
1381     "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
1382     Address->Addr[0],
1383     Address->Addr[1],
1384     Address->Addr[2],
1385     Address->Addr[3],
1386     Address->Addr[4],
1387     Address->Addr[5],
1388     Address->Addr[6],
1389     Address->Addr[7],
1390     Address->Addr[8],
1391     Address->Addr[9],
1392     Address->Addr[10],
1393     Address->Addr[11],
1394     Address->Addr[12],
1395     Address->Addr[13],
1396     Address->Addr[14],
1397     Address->Addr[15]
1398     );
1399 }
1400 
1401 /**
1402   Converts a IPv4 device path structure to its string representative.
1403 
1404   @param Str             The string representative of input device.
1405   @param DevPath         The input device path structure.
1406   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1407                          of the display node is used, where applicable. If DisplayOnly
1408                          is FALSE, then the longer text representation of the display node
1409                          is used.
1410   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1411                          representation for a device node can be used, where applicable.
1412 
1413 **/
1414 static VOID
1415 DevPathToTextIPv4 (
1416   IN OUT POOL_PRINT  *Str,
1417   IN VOID            *DevPath,
1418   IN BOOLEAN         DisplayOnly,
1419   IN BOOLEAN         AllowShortcuts
1420   )
1421 {
1422   IPv4_DEVICE_PATH  *IPDevPath;
1423 
1424   IPDevPath = DevPath;
1425   UefiDevicePathLibCatPrint (Str, "IPv4(");
1426   CatIPv4Address (Str, &IPDevPath->RemoteIpAddress);
1427 
1428   if (DisplayOnly) {
1429     UefiDevicePathLibCatPrint (Str, ")");
1430     return;
1431   }
1432 
1433   UefiDevicePathLibCatPrint (Str, ",");
1434   CatNetworkProtocol (Str, IPDevPath->Protocol);
1435 
1436   UefiDevicePathLibCatPrint (Str, ",%s,", IPDevPath->StaticIpAddress ? "Static" : "DHCP");
1437   CatIPv4Address (Str, &IPDevPath->LocalIpAddress);
1438   if (DevicePathNodeLength (IPDevPath) == sizeof (IPv4_DEVICE_PATH)) {
1439     UefiDevicePathLibCatPrint (Str, ",");
1440     CatIPv4Address (Str, &IPDevPath->GatewayIpAddress);
1441     UefiDevicePathLibCatPrint (Str, ",");
1442     CatIPv4Address (Str, &IPDevPath->SubnetMask);
1443   }
1444 
1445   UefiDevicePathLibCatPrint (Str, ")");
1446 }
1447 
1448 /**
1449   Converts a IPv6 device path structure to its string representative.
1450 
1451   @param Str             The string representative of input device.
1452   @param DevPath         The input device path structure.
1453   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1454                          of the display node is used, where applicable. If DisplayOnly
1455                          is FALSE, then the longer text representation of the display node
1456                          is used.
1457   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1458                          representation for a device node can be used, where applicable.
1459 
1460 **/
1461 static VOID
1462 DevPathToTextIPv6 (
1463   IN OUT POOL_PRINT  *Str,
1464   IN VOID            *DevPath,
1465   IN BOOLEAN         DisplayOnly,
1466   IN BOOLEAN         AllowShortcuts
1467   )
1468 {
1469   IPv6_DEVICE_PATH  *IPDevPath;
1470 
1471   IPDevPath = DevPath;
1472   UefiDevicePathLibCatPrint (Str, "IPv6(");
1473   CatIPv6Address (Str, &IPDevPath->RemoteIpAddress);
1474   if (DisplayOnly) {
1475     UefiDevicePathLibCatPrint (Str, ")");
1476     return;
1477   }
1478 
1479   UefiDevicePathLibCatPrint (Str, ",");
1480   CatNetworkProtocol (Str, IPDevPath->Protocol);
1481 
1482   switch (IPDevPath->IpAddressOrigin) {
1483     case 0:
1484       UefiDevicePathLibCatPrint (Str, ",Static,");
1485       break;
1486     case 1:
1487       UefiDevicePathLibCatPrint (Str, ",StatelessAutoConfigure,");
1488       break;
1489     default:
1490       UefiDevicePathLibCatPrint (Str, ",StatefulAutoConfigure,");
1491       break;
1492   }
1493 
1494   CatIPv6Address (Str, &IPDevPath->LocalIpAddress);
1495 
1496   if (DevicePathNodeLength (IPDevPath) == sizeof (IPv6_DEVICE_PATH)) {
1497     UefiDevicePathLibCatPrint (Str, ",0x%x,", IPDevPath->PrefixLength);
1498     CatIPv6Address (Str, &IPDevPath->GatewayIpAddress);
1499   }
1500 
1501   UefiDevicePathLibCatPrint (Str, ")");
1502 }
1503 
1504 /**
1505   Converts an Infini Band device path structure to its string representative.
1506 
1507   @param Str             The string representative of input device.
1508   @param DevPath         The input device path structure.
1509   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1510                          of the display node is used, where applicable. If DisplayOnly
1511                          is FALSE, then the longer text representation of the display node
1512                          is used.
1513   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1514                          representation for a device node can be used, where applicable.
1515 
1516 **/
1517 static VOID
1518 DevPathToTextInfiniBand (
1519   IN OUT POOL_PRINT  *Str,
1520   IN VOID            *DevPath,
1521   IN BOOLEAN         DisplayOnly,
1522   IN BOOLEAN         AllowShortcuts
1523   )
1524 {
1525   INFINIBAND_DEVICE_PATH  *InfiniBand;
1526 
1527   InfiniBand = DevPath;
1528   UefiDevicePathLibCatPrint (
1529     Str,
1530     "Infiniband(0x%x,%36s,0x%lx,0x%lx,0x%lx)",
1531     InfiniBand->ResourceFlags,
1532     G(InfiniBand->PortGid),
1533     InfiniBand->ServiceId,
1534     InfiniBand->TargetPortId,
1535     InfiniBand->DeviceId
1536     );
1537 }
1538 
1539 /**
1540   Converts a UART device path structure to its string representative.
1541 
1542   @param Str             The string representative of input device.
1543   @param DevPath         The input device path structure.
1544   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1545                          of the display node is used, where applicable. If DisplayOnly
1546                          is FALSE, then the longer text representation of the display node
1547                          is used.
1548   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1549                          representation for a device node can be used, where applicable.
1550 
1551 **/
1552 static VOID
1553 DevPathToTextUart (
1554   IN OUT POOL_PRINT  *Str,
1555   IN VOID            *DevPath,
1556   IN BOOLEAN         DisplayOnly,
1557   IN BOOLEAN         AllowShortcuts
1558   )
1559 {
1560   UART_DEVICE_PATH  *Uart;
1561   CHAR8             Parity;
1562 
1563   Uart = DevPath;
1564   switch (Uart->Parity) {
1565     case 0:
1566       Parity = 'D';
1567       break;
1568 
1569     case 1:
1570       Parity = 'N';
1571       break;
1572 
1573     case 2:
1574       Parity = 'E';
1575       break;
1576 
1577     case 3:
1578       Parity = 'O';
1579       break;
1580 
1581     case 4:
1582       Parity = 'M';
1583       break;
1584 
1585     case 5:
1586       Parity = 'S';
1587       break;
1588 
1589     default:
1590       Parity = 'x';
1591       break;
1592   }
1593 
1594   if (Uart->BaudRate == 0) {
1595     UefiDevicePathLibCatPrint (Str, "Uart(DEFAULT,");
1596   } else {
1597     UefiDevicePathLibCatPrint (Str, "Uart(%ld,", Uart->BaudRate);
1598   }
1599 
1600   if (Uart->DataBits == 0) {
1601     UefiDevicePathLibCatPrint (Str, "DEFAULT,");
1602   } else {
1603     UefiDevicePathLibCatPrint (Str, "%d,", Uart->DataBits);
1604   }
1605 
1606   UefiDevicePathLibCatPrint (Str, "%c,", Parity);
1607 
1608   switch (Uart->StopBits) {
1609     case 0:
1610       UefiDevicePathLibCatPrint (Str, "D)");
1611       break;
1612 
1613     case 1:
1614       UefiDevicePathLibCatPrint (Str, "1)");
1615       break;
1616 
1617     case 2:
1618       UefiDevicePathLibCatPrint (Str, "1.5)");
1619       break;
1620 
1621     case 3:
1622       UefiDevicePathLibCatPrint (Str, "2)");
1623       break;
1624 
1625     default:
1626       UefiDevicePathLibCatPrint (Str, "x)");
1627       break;
1628   }
1629 }
1630 
1631 /**
1632   Converts an iSCSI device path structure to its string representative.
1633 
1634   @param Str             The string representative of input device.
1635   @param DevPath         The input device path structure.
1636   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1637                          of the display node is used, where applicable. If DisplayOnly
1638                          is FALSE, then the longer text representation of the display node
1639                          is used.
1640   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1641                          representation for a device node can be used, where applicable.
1642 
1643 **/
1644 static VOID
1645 DevPathToTextiSCSI (
1646   IN OUT POOL_PRINT  *Str,
1647   IN VOID            *DevPath,
1648   IN BOOLEAN         DisplayOnly,
1649   IN BOOLEAN         AllowShortcuts
1650   )
1651 {
1652   ISCSI_DEVICE_PATH_WITH_NAME  *ISCSIDevPath;
1653   UINT16                       Options;
1654   UINTN                        Index;
1655 
1656   ISCSIDevPath = DevPath;
1657   UefiDevicePathLibCatPrint (
1658     Str,
1659     "iSCSI(%s,0x%x,0x",
1660     ISCSIDevPath->TargetName,
1661     ISCSIDevPath->TargetPortalGroupTag
1662     );
1663   for (Index = 0; Index < sizeof (ISCSIDevPath->Lun) / sizeof (UINT8); Index++) {
1664     UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *)&ISCSIDevPath->Lun)[Index]);
1665   }
1666 
1667   Options = ISCSIDevPath->LoginOption;
1668   UefiDevicePathLibCatPrint (Str, ",%s,", (((Options >> 1) & 0x0001) != 0) ? "CRC32C" : "None");
1669   UefiDevicePathLibCatPrint (Str, "%s,", (((Options >> 3) & 0x0001) != 0) ? "CRC32C" : "None");
1670   if (((Options >> 11) & 0x0001) != 0) {
1671     UefiDevicePathLibCatPrint (Str, "%s,", "None");
1672   } else if (((Options >> 12) & 0x0001) != 0) {
1673     UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_UNI");
1674   } else {
1675     UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_BI");
1676   }
1677 
1678   UefiDevicePathLibCatPrint (Str, "%s)", (ISCSIDevPath->NetworkProtocol == 0) ? "TCP" : "reserved");
1679 }
1680 
1681 /**
1682   Converts a VLAN device path structure to its string representative.
1683 
1684   @param Str             The string representative of input device.
1685   @param DevPath         The input device path structure.
1686   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1687                          of the display node is used, where applicable. If DisplayOnly
1688                          is FALSE, then the longer text representation of the display node
1689                          is used.
1690   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1691                          representation for a device node can be used, where applicable.
1692 
1693 **/
1694 static VOID
1695 DevPathToTextVlan (
1696   IN OUT POOL_PRINT  *Str,
1697   IN VOID            *DevPath,
1698   IN BOOLEAN         DisplayOnly,
1699   IN BOOLEAN         AllowShortcuts
1700   )
1701 {
1702   VLAN_DEVICE_PATH  *Vlan;
1703 
1704   Vlan = DevPath;
1705   UefiDevicePathLibCatPrint (Str, "Vlan(%d)", Vlan->VlanId);
1706 }
1707 
1708 /**
1709   Converts a Bluetooth device path structure to its string representative.
1710 
1711   @param Str             The string representative of input device.
1712   @param DevPath         The input device path structure.
1713   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1714                          of the display node is used, where applicable. If DisplayOnly
1715                          is FALSE, then the longer text representation of the display node
1716                          is used.
1717   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1718                          representation for a device node can be used, where applicable.
1719 
1720 **/
1721 static VOID
1722 DevPathToTextBluetooth (
1723   IN OUT POOL_PRINT  *Str,
1724   IN VOID            *DevPath,
1725   IN BOOLEAN         DisplayOnly,
1726   IN BOOLEAN         AllowShortcuts
1727   )
1728 {
1729   BLUETOOTH_DEVICE_PATH  *Bluetooth;
1730 
1731   Bluetooth = DevPath;
1732   UefiDevicePathLibCatPrint (
1733     Str,
1734     "Bluetooth(%02x%02x%02x%02x%02x%02x)",
1735     Bluetooth->BD_ADDR.Address[0],
1736     Bluetooth->BD_ADDR.Address[1],
1737     Bluetooth->BD_ADDR.Address[2],
1738     Bluetooth->BD_ADDR.Address[3],
1739     Bluetooth->BD_ADDR.Address[4],
1740     Bluetooth->BD_ADDR.Address[5]
1741     );
1742 }
1743 
1744 /**
1745   Converts a Wi-Fi device path structure to its string representative.
1746 
1747   @param Str             The string representative of input device.
1748   @param DevPath         The input device path structure.
1749   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1750                          of the display node is used, where applicable. If DisplayOnly
1751                          is FALSE, then the longer text representation of the display node
1752                          is used.
1753   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1754                          representation for a device node can be used, where applicable.
1755 
1756 **/
1757 static VOID
1758 DevPathToTextWiFi (
1759   IN OUT POOL_PRINT  *Str,
1760   IN VOID            *DevPath,
1761   IN BOOLEAN         DisplayOnly,
1762   IN BOOLEAN         AllowShortcuts
1763   )
1764 {
1765   WIFI_DEVICE_PATH  *WiFi;
1766   UINT8             SSId[33];
1767 
1768   WiFi = DevPath;
1769 
1770   SSId[32] = '\0';
1771   CopyMem (SSId, WiFi->SSId, 32);
1772 
1773   UefiDevicePathLibCatPrint (Str, "Wi-Fi(%s)", SSId);
1774 }
1775 
1776 /**
1777   Converts a Bluetooth device path structure to its string representative.
1778 
1779   @param Str             The string representative of input device.
1780   @param DevPath         The input device path structure.
1781   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1782                          of the display node is used, where applicable. If DisplayOnly
1783                          is FALSE, then the longer text representation of the display node
1784                          is used.
1785   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1786                          representation for a device node can be used, where applicable.
1787 
1788 **/
1789 static VOID
1790 DevPathToTextBluetoothLE (
1791   IN OUT POOL_PRINT  *Str,
1792   IN VOID            *DevPath,
1793   IN BOOLEAN         DisplayOnly,
1794   IN BOOLEAN         AllowShortcuts
1795   )
1796 {
1797   BLUETOOTH_LE_DEVICE_PATH  *BluetoothLE;
1798 
1799   BluetoothLE = DevPath;
1800   UefiDevicePathLibCatPrint (
1801     Str,
1802     "BluetoothLE(%02x%02x%02x%02x%02x%02x,0x%02x)",
1803     BluetoothLE->Address.Address[0],
1804     BluetoothLE->Address.Address[1],
1805     BluetoothLE->Address.Address[2],
1806     BluetoothLE->Address.Address[3],
1807     BluetoothLE->Address.Address[4],
1808     BluetoothLE->Address.Address[5],
1809     BluetoothLE->Address.Type
1810     );
1811 }
1812 
1813 /**
1814   Converts a DNS device path structure to its string representative.
1815 
1816   @param Str             The string representative of input device.
1817   @param DevPath         The input device path structure.
1818   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1819                          of the display node is used, where applicable. If DisplayOnly
1820                          is FALSE, then the longer text representation of the display node
1821                          is used.
1822   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1823                          representation for a device node can be used, where applicable.
1824 
1825 **/
1826 static VOID
1827 DevPathToTextDns (
1828   IN OUT POOL_PRINT  *Str,
1829   IN VOID            *DevPath,
1830   IN BOOLEAN         DisplayOnly,
1831   IN BOOLEAN         AllowShortcuts
1832   )
1833 {
1834   DNS_DEVICE_PATH  *DnsDevPath;
1835   UINT32           DnsServerIpCount;
1836   UINT32           DnsServerIpIndex;
1837 
1838   DnsDevPath       = DevPath;
1839   DnsServerIpCount = (UINT32)(DevicePathNodeLength (DnsDevPath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof (DnsDevPath->IsIPv6)) / sizeof (EFI_IP_ADDRESS);
1840 
1841   UefiDevicePathLibCatPrint (Str, "Dns(");
1842 
1843   for (DnsServerIpIndex = 0; DnsServerIpIndex < DnsServerIpCount; DnsServerIpIndex++) {
1844     if (DnsDevPath->IsIPv6 == 0x00) {
1845       CatIPv4Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v4));
1846     } else {
1847       CatIPv6Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v6));
1848     }
1849 
1850     if (DnsServerIpIndex < DnsServerIpCount - 1) {
1851       UefiDevicePathLibCatPrint (Str, ",");
1852     }
1853   }
1854 
1855   UefiDevicePathLibCatPrint (Str, ")");
1856 }
1857 
1858 /**
1859   Converts a URI device path structure to its string representative.
1860 
1861   @param Str             The string representative of input device.
1862   @param DevPath         The input device path structure.
1863   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1864                          of the display node is used, where applicable. If DisplayOnly
1865                          is FALSE, then the longer text representation of the display node
1866                          is used.
1867   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1868                          representation for a device node can be used, where applicable.
1869 
1870 **/
1871 static VOID
1872 DevPathToTextUri (
1873   IN OUT POOL_PRINT  *Str,
1874   IN VOID            *DevPath,
1875   IN BOOLEAN         DisplayOnly,
1876   IN BOOLEAN         AllowShortcuts
1877   )
1878 {
1879   URI_DEVICE_PATH  *Uri;
1880   UINTN            UriLength;
1881   CHAR8            *UriStr;
1882 
1883   //
1884   // Uri in the device path may not be null terminated.
1885   //
1886   Uri       = DevPath;
1887   UriLength = DevicePathNodeLength (Uri) - sizeof (URI_DEVICE_PATH);
1888   UriStr    = AllocatePool (UriLength + 1);
1889   ASSERT (UriStr != NULL);
1890 
1891   CopyMem (UriStr, Uri->Uri, UriLength);
1892   UriStr[UriLength] = '\0';
1893   UefiDevicePathLibCatPrint (Str, "Uri(%s)", UriStr);
1894   FreePool (UriStr);
1895 }
1896 
1897 /**
1898   Converts a Hard drive device path structure to its string representative.
1899 
1900   @param Str             The string representative of input device.
1901   @param DevPath         The input device path structure.
1902   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1903                          of the display node is used, where applicable. If DisplayOnly
1904                          is FALSE, then the longer text representation of the display node
1905                          is used.
1906   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1907                          representation for a device node can be used, where applicable.
1908 
1909 **/
1910 static VOID
1911 DevPathToTextHardDrive (
1912   IN OUT POOL_PRINT  *Str,
1913   IN VOID            *DevPath,
1914   IN BOOLEAN         DisplayOnly,
1915   IN BOOLEAN         AllowShortcuts
1916   )
1917 {
1918   HARDDRIVE_DEVICE_PATH  *Hd;
1919 
1920   Hd = DevPath;
1921   switch (Hd->SignatureType) {
1922     case SIGNATURE_TYPE_MBR:
1923       UefiDevicePathLibCatPrint (
1924         Str,
1925         "HD(%d,%s,0x%08x,",
1926         Hd->PartitionNumber,
1927         "MBR",
1928 //      *((UINT32 *)(&(Hd->Signature[0])))
1929         le32dec(&(Hd->Signature[0]))
1930         );
1931       break;
1932 
1933     case SIGNATURE_TYPE_GUID:
1934       UefiDevicePathLibCatPrint (
1935         Str,
1936         "HD(%d,%s,%36s,",
1937         Hd->PartitionNumber,
1938         "GPT",
1939         G(&(Hd->Signature[0]))
1940         );
1941       break;
1942 
1943     default:
1944       UefiDevicePathLibCatPrint (
1945         Str,
1946         "HD(%d,%d,0,",
1947         Hd->PartitionNumber,
1948         Hd->SignatureType
1949         );
1950       break;
1951   }
1952 
1953   UefiDevicePathLibCatPrint (Str, "0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
1954 }
1955 
1956 /**
1957   Converts a CDROM device path structure to its string representative.
1958 
1959   @param Str             The string representative of input device.
1960   @param DevPath         The input device path structure.
1961   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1962                          of the display node is used, where applicable. If DisplayOnly
1963                          is FALSE, then the longer text representation of the display node
1964                          is used.
1965   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1966                          representation for a device node can be used, where applicable.
1967 
1968 **/
1969 static VOID
1970 DevPathToTextCDROM (
1971   IN OUT POOL_PRINT  *Str,
1972   IN VOID            *DevPath,
1973   IN BOOLEAN         DisplayOnly,
1974   IN BOOLEAN         AllowShortcuts
1975   )
1976 {
1977   CDROM_DEVICE_PATH  *Cd;
1978 
1979   Cd = DevPath;
1980   if (DisplayOnly) {
1981     UefiDevicePathLibCatPrint (Str, "CDROM(0x%x)", Cd->BootEntry);
1982     return;
1983   }
1984 
1985   UefiDevicePathLibCatPrint (Str, "CDROM(0x%x,0x%lx,0x%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
1986 }
1987 
1988 /**
1989   Converts a File device path structure to its string representative.
1990 
1991   @param Str             The string representative of input device.
1992   @param DevPath         The input device path structure.
1993   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1994                          of the display node is used, where applicable. If DisplayOnly
1995                          is FALSE, then the longer text representation of the display node
1996                          is used.
1997   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1998                          representation for a device node can be used, where applicable.
1999 
2000 **/
2001 static VOID
2002 DevPathToTextFilePath (
2003   IN OUT POOL_PRINT  *Str,
2004   IN VOID            *DevPath,
2005   IN BOOLEAN         DisplayOnly,
2006   IN BOOLEAN         AllowShortcuts
2007   )
2008 {
2009   FILEPATH_DEVICE_PATH  *Fp;
2010   char *name = NULL;
2011 
2012   Fp = DevPath;
2013   ucs2_to_utf8(Fp->PathName, &name);
2014   UefiDevicePathLibCatPrint (Str, "File(%s)", name);
2015   free(name);
2016 }
2017 
2018 /**
2019   Converts a Media protocol device path structure to its string representative.
2020 
2021   @param Str             The string representative of input device.
2022   @param DevPath         The input device path structure.
2023   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2024                          of the display node is used, where applicable. If DisplayOnly
2025                          is FALSE, then the longer text representation of the display node
2026                          is used.
2027   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2028                          representation for a device node can be used, where applicable.
2029 
2030 **/
2031 static VOID
2032 DevPathToTextMediaProtocol (
2033   IN OUT POOL_PRINT  *Str,
2034   IN VOID            *DevPath,
2035   IN BOOLEAN         DisplayOnly,
2036   IN BOOLEAN         AllowShortcuts
2037   )
2038 {
2039   MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
2040 
2041   MediaProt = DevPath;
2042   UefiDevicePathLibCatPrint (Str, "Media(%36s)", G(&MediaProt->Protocol));
2043 }
2044 
2045 /**
2046   Converts a Firmware Volume device path structure to its string representative.
2047 
2048   @param Str             The string representative of input device.
2049   @param DevPath         The input device path structure.
2050   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2051                          of the display node is used, where applicable. If DisplayOnly
2052                          is FALSE, then the longer text representation of the display node
2053                          is used.
2054   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2055                          representation for a device node can be used, where applicable.
2056 
2057 **/
2058 static VOID
2059 DevPathToTextFv (
2060   IN OUT POOL_PRINT  *Str,
2061   IN VOID            *DevPath,
2062   IN BOOLEAN         DisplayOnly,
2063   IN BOOLEAN         AllowShortcuts
2064   )
2065 {
2066   MEDIA_FW_VOL_DEVICE_PATH  *Fv;
2067 
2068   Fv = DevPath;
2069   UefiDevicePathLibCatPrint (Str, "Fv(%36s)", G(&Fv->FvName));
2070 }
2071 
2072 /**
2073   Converts a Firmware Volume File device path structure to its string representative.
2074 
2075   @param Str             The string representative of input device.
2076   @param DevPath         The input device path structure.
2077   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2078                          of the display node is used, where applicable. If DisplayOnly
2079                          is FALSE, then the longer text representation of the display node
2080                          is used.
2081   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2082                          representation for a device node can be used, where applicable.
2083 
2084 **/
2085 static VOID
2086 DevPathToTextFvFile (
2087   IN OUT POOL_PRINT  *Str,
2088   IN VOID            *DevPath,
2089   IN BOOLEAN         DisplayOnly,
2090   IN BOOLEAN         AllowShortcuts
2091   )
2092 {
2093   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFile;
2094 
2095   FvFile = DevPath;
2096   UefiDevicePathLibCatPrint (Str, "FvFile(%36s)", G(&FvFile->FvFileName));
2097 }
2098 
2099 /**
2100   Converts a Relative Offset device path structure to its string representative.
2101 
2102   @param Str             The string representative of input device.
2103   @param DevPath         The input device path structure.
2104   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2105                          of the display node is used, where applicable. If DisplayOnly
2106                          is FALSE, then the longer text representation of the display node
2107                          is used.
2108   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2109                          representation for a device node can be used, where applicable.
2110 
2111 **/
2112 static VOID
2113 DevPathRelativeOffsetRange (
2114   IN OUT POOL_PRINT  *Str,
2115   IN VOID            *DevPath,
2116   IN BOOLEAN         DisplayOnly,
2117   IN BOOLEAN         AllowShortcuts
2118   )
2119 {
2120   MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  *Offset;
2121 
2122   Offset = DevPath;
2123   UefiDevicePathLibCatPrint (
2124     Str,
2125     "Offset(0x%lx,0x%lx)",
2126     Offset->StartingOffset,
2127     Offset->EndingOffset
2128     );
2129 }
2130 
2131 /**
2132   Converts a Ram Disk device path structure to its string representative.
2133 
2134   @param Str             The string representative of input device.
2135   @param DevPath         The input device path structure.
2136   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2137                          of the display node is used, where applicable. If DisplayOnly
2138                          is FALSE, then the longer text representation of the display node
2139                          is used.
2140   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2141                          representation for a device node can be used, where applicable.
2142 
2143 **/
2144 static VOID
2145 DevPathToTextRamDisk (
2146   IN OUT POOL_PRINT  *Str,
2147   IN VOID            *DevPath,
2148   IN BOOLEAN         DisplayOnly,
2149   IN BOOLEAN         AllowShortcuts
2150   )
2151 {
2152   MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
2153 
2154   RamDisk = DevPath;
2155 
2156   if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid)) {
2157     UefiDevicePathLibCatPrint (
2158       Str,
2159       "VirtualDisk(0x%lx,0x%lx,%d)",
2160       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2161       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2162       RamDisk->Instance
2163       );
2164   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid)) {
2165     UefiDevicePathLibCatPrint (
2166       Str,
2167       "VirtualCD(0x%lx,0x%lx,%d)",
2168       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2169       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2170       RamDisk->Instance
2171       );
2172   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid)) {
2173     UefiDevicePathLibCatPrint (
2174       Str,
2175       "PersistentVirtualDisk(0x%lx,0x%lx,%d)",
2176       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2177       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2178       RamDisk->Instance
2179       );
2180   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid)) {
2181     UefiDevicePathLibCatPrint (
2182       Str,
2183       "PersistentVirtualCD(0x%lx,0x%lx,%d)",
2184       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2185       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2186       RamDisk->Instance
2187       );
2188   } else {
2189     UefiDevicePathLibCatPrint (
2190       Str,
2191       "RamDisk(0x%lx,0x%lx,%d,%36s)",
2192       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2193       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2194       RamDisk->Instance,
2195       G(&RamDisk->TypeGuid)
2196       );
2197   }
2198 }
2199 
2200 /**
2201   Converts a BIOS Boot Specification device path structure to its string representative.
2202 
2203   @param Str             The string representative of input device.
2204   @param DevPath         The input device path structure.
2205   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2206                          of the display node is used, where applicable. If DisplayOnly
2207                          is FALSE, then the longer text representation of the display node
2208                          is used.
2209   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2210                          representation for a device node can be used, where applicable.
2211 
2212 **/
2213 static VOID
2214 DevPathToTextBBS (
2215   IN OUT POOL_PRINT  *Str,
2216   IN VOID            *DevPath,
2217   IN BOOLEAN         DisplayOnly,
2218   IN BOOLEAN         AllowShortcuts
2219   )
2220 {
2221   BBS_BBS_DEVICE_PATH  *Bbs;
2222   const char           *Type;
2223 
2224   Bbs = DevPath;
2225   switch (Bbs->DeviceType) {
2226     case BBS_TYPE_FLOPPY:
2227       Type = "Floppy";
2228       break;
2229 
2230     case BBS_TYPE_HARDDRIVE:
2231       Type = "HD";
2232       break;
2233 
2234     case BBS_TYPE_CDROM:
2235       Type = "CDROM";
2236       break;
2237 
2238     case BBS_TYPE_PCMCIA:
2239       Type = "PCMCIA";
2240       break;
2241 
2242     case BBS_TYPE_USB:
2243       Type = "USB";
2244       break;
2245 
2246     case BBS_TYPE_EMBEDDED_NETWORK:
2247       Type = "Network";
2248       break;
2249 
2250     default:
2251       Type = NULL;
2252       break;
2253   }
2254 
2255   if (Type != NULL) {
2256     UefiDevicePathLibCatPrint (Str, "BBS(%s,%s", Type, Bbs->String);
2257   } else {
2258     UefiDevicePathLibCatPrint (Str, "BBS(0x%x,%s", Bbs->DeviceType, Bbs->String);
2259   }
2260 
2261   if (DisplayOnly) {
2262     UefiDevicePathLibCatPrint (Str, ")");
2263     return;
2264   }
2265 
2266   UefiDevicePathLibCatPrint (Str, ",0x%x)", Bbs->StatusFlag);
2267 }
2268 
2269 /**
2270   Converts an End-of-Device-Path structure to its string representative.
2271 
2272   @param Str             The string representative of input device.
2273   @param DevPath         The input device path structure.
2274   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2275                          of the display node is used, where applicable. If DisplayOnly
2276                          is FALSE, then the longer text representation of the display node
2277                          is used.
2278   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2279                          representation for a device node can be used, where applicable.
2280 
2281 **/
2282 static VOID
2283 DevPathToTextEndInstance (
2284   IN OUT POOL_PRINT  *Str,
2285   IN VOID            *DevPath,
2286   IN BOOLEAN         DisplayOnly,
2287   IN BOOLEAN         AllowShortcuts
2288   )
2289 {
2290   UefiDevicePathLibCatPrint (Str, ",");
2291 }
2292 
2293 GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_GENERIC_TABLE  mUefiDevicePathLibToTextTableGeneric[] = {
2294   { HARDWARE_DEVICE_PATH,  "HardwarePath" },
2295   { ACPI_DEVICE_PATH,      "AcpiPath"     },
2296   { MESSAGING_DEVICE_PATH, "Msg"          },
2297   { MEDIA_DEVICE_PATH,     "MediaPath"    },
2298   { BBS_DEVICE_PATH,       "BbsPath"      },
2299   { 0,                     NULL            }
2300 };
2301 
2302 /**
2303   Converts an unknown device path structure to its string representative.
2304 
2305   @param Str             The string representative of input device.
2306   @param DevPath         The input device path structure.
2307   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2308                          of the display node is used, where applicable. If DisplayOnly
2309                          is FALSE, then the longer text representation of the display node
2310                          is used.
2311   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2312                          representation for a device node can be used, where applicable.
2313 
2314 **/
2315 static VOID
2316 DevPathToTextNodeGeneric (
2317   IN OUT POOL_PRINT  *Str,
2318   IN VOID            *DevPath,
2319   IN BOOLEAN         DisplayOnly,
2320   IN BOOLEAN         AllowShortcuts
2321   )
2322 {
2323   EFI_DEVICE_PATH_PROTOCOL  *Node;
2324   UINTN                     Index;
2325 
2326   Node = DevPath;
2327 
2328   for (Index = 0; mUefiDevicePathLibToTextTableGeneric[Index].Text != NULL; Index++) {
2329     if (DevicePathType (Node) == mUefiDevicePathLibToTextTableGeneric[Index].Type) {
2330       break;
2331     }
2332   }
2333 
2334   if (mUefiDevicePathLibToTextTableGeneric[Index].Text == NULL) {
2335     //
2336     // It's a node whose type cannot be recognized
2337     //
2338     UefiDevicePathLibCatPrint (Str, "Path(%d,%d", DevicePathType (Node), DevicePathSubType (Node));
2339   } else {
2340     //
2341     // It's a node whose type can be recognized
2342     //
2343     UefiDevicePathLibCatPrint (Str, "%s(%d", mUefiDevicePathLibToTextTableGeneric[Index].Text, DevicePathSubType (Node));
2344   }
2345 
2346   Index = sizeof (EFI_DEVICE_PATH_PROTOCOL);
2347   if (Index < DevicePathNodeLength (Node)) {
2348     UefiDevicePathLibCatPrint (Str, ",");
2349     for ( ; Index < DevicePathNodeLength (Node); Index++) {
2350       UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *)Node)[Index]);
2351     }
2352   }
2353 
2354   UefiDevicePathLibCatPrint (Str, ")");
2355 }
2356 
2357 static const DEVICE_PATH_TO_TEXT_TABLE  mUefiDevicePathLibToTextTable[] = {
2358   { HARDWARE_DEVICE_PATH,  HW_PCI_DP,                        DevPathToTextPci           },
2359   { HARDWARE_DEVICE_PATH,  HW_PCCARD_DP,                     DevPathToTextPccard        },
2360   { HARDWARE_DEVICE_PATH,  HW_MEMMAP_DP,                     DevPathToTextMemMap        },
2361   { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP,                     DevPathToTextVendor        },
2362   { HARDWARE_DEVICE_PATH,  HW_CONTROLLER_DP,                 DevPathToTextController    },
2363   { HARDWARE_DEVICE_PATH,  HW_BMC_DP,                        DevPathToTextBmc           },
2364   { ACPI_DEVICE_PATH,      ACPI_DP,                          DevPathToTextAcpi          },
2365   { ACPI_DEVICE_PATH,      ACPI_EXTENDED_DP,                 DevPathToTextAcpiEx        },
2366   { ACPI_DEVICE_PATH,      ACPI_ADR_DP,                      DevPathToTextAcpiAdr       },
2367   { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP,                     DevPathToTextAtapi         },
2368   { MESSAGING_DEVICE_PATH, MSG_SCSI_DP,                      DevPathToTextScsi          },
2369   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP,              DevPathToTextFibre         },
2370   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP,            DevPathToTextFibreEx       },
2371   { MESSAGING_DEVICE_PATH, MSG_SASEX_DP,                     DevPathToTextSasEx         },
2372   { MESSAGING_DEVICE_PATH, MSG_NVME_NAMESPACE_DP,            DevPathToTextNVMe          },
2373   { MESSAGING_DEVICE_PATH, MSG_UFS_DP,                       DevPathToTextUfs           },
2374   { MESSAGING_DEVICE_PATH, MSG_SD_DP,                        DevPathToTextSd            },
2375   { MESSAGING_DEVICE_PATH, MSG_EMMC_DP,                      DevPathToTextEmmc          },
2376   { MESSAGING_DEVICE_PATH, MSG_1394_DP,                      DevPathToText1394          },
2377   { MESSAGING_DEVICE_PATH, MSG_USB_DP,                       DevPathToTextUsb           },
2378   { MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP,                  DevPathToTextUsbWWID       },
2379   { MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP,       DevPathToTextLogicalUnit   },
2380   { MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,                 DevPathToTextUsbClass      },
2381   { MESSAGING_DEVICE_PATH, MSG_SATA_DP,                      DevPathToTextSata          },
2382   { MESSAGING_DEVICE_PATH, MSG_I2O_DP,                       DevPathToTextI2O           },
2383   { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,                  DevPathToTextMacAddr       },
2384   { MESSAGING_DEVICE_PATH, MSG_IPv4_DP,                      DevPathToTextIPv4          },
2385   { MESSAGING_DEVICE_PATH, MSG_IPv6_DP,                      DevPathToTextIPv6          },
2386   { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP,                DevPathToTextInfiniBand    },
2387   { MESSAGING_DEVICE_PATH, MSG_UART_DP,                      DevPathToTextUart          },
2388   { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,                    DevPathToTextVendor        },
2389   { MESSAGING_DEVICE_PATH, MSG_ISCSI_DP,                     DevPathToTextiSCSI         },
2390   { MESSAGING_DEVICE_PATH, MSG_VLAN_DP,                      DevPathToTextVlan          },
2391   { MESSAGING_DEVICE_PATH, MSG_DNS_DP,                       DevPathToTextDns           },
2392   { MESSAGING_DEVICE_PATH, MSG_URI_DP,                       DevPathToTextUri           },
2393   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_DP,                 DevPathToTextBluetooth     },
2394   { MESSAGING_DEVICE_PATH, MSG_WIFI_DP,                      DevPathToTextWiFi          },
2395   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_LE_DP,              DevPathToTextBluetoothLE   },
2396   { MEDIA_DEVICE_PATH,     MEDIA_HARDDRIVE_DP,               DevPathToTextHardDrive     },
2397   { MEDIA_DEVICE_PATH,     MEDIA_CDROM_DP,                   DevPathToTextCDROM         },
2398   { MEDIA_DEVICE_PATH,     MEDIA_VENDOR_DP,                  DevPathToTextVendor        },
2399   { MEDIA_DEVICE_PATH,     MEDIA_PROTOCOL_DP,                DevPathToTextMediaProtocol },
2400   { MEDIA_DEVICE_PATH,     MEDIA_FILEPATH_DP,                DevPathToTextFilePath      },
2401   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_VOL_DP,             DevPathToTextFv            },
2402   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_FILE_DP,            DevPathToTextFvFile        },
2403   { MEDIA_DEVICE_PATH,     MEDIA_RELATIVE_OFFSET_RANGE_DP,   DevPathRelativeOffsetRange },
2404   { MEDIA_DEVICE_PATH,     MEDIA_RAM_DISK_DP,                DevPathToTextRamDisk       },
2405   { BBS_DEVICE_PATH,       BBS_BBS_DP,                       DevPathToTextBBS           },
2406   { END_DEVICE_PATH_TYPE,  END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance   },
2407   { 0,                     0,                                NULL                       }
2408 };
2409 
2410 /**
2411   Converts a device node to its string representation.
2412 
2413   @param DeviceNode        A Pointer to the device node to be converted.
2414   @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
2415                            of the display node is used, where applicable. If DisplayOnly
2416                            is FALSE, then the longer text representation of the display node
2417                            is used.
2418   @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
2419                            representation for a device node can be used, where applicable.
2420 
2421   @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
2422           is NULL or there was insufficient memory.
2423 
2424 **/
2425 static char *
2426 EFIAPI
2427 UefiDevicePathLibConvertDeviceNodeToText (
2428   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
2429   IN BOOLEAN                         DisplayOnly,
2430   IN BOOLEAN                         AllowShortcuts
2431   )
2432 {
2433   POOL_PRINT           Str;
2434   UINTN                Index;
2435   DEVICE_PATH_TO_TEXT  ToText;
2436   EFI_DEVICE_PATH_PROTOCOL  *Node;
2437 
2438   if (DeviceNode == NULL) {
2439     return NULL;
2440   }
2441 
2442   ZeroMem (&Str, sizeof (Str));
2443 
2444   //
2445   // Process the device path node
2446   // If not found, use a generic function
2447   //
2448   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DeviceNode);
2449   ToText = DevPathToTextNodeGeneric;
2450   for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index++) {
2451     if ((DevicePathType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].Type) &&
2452         (DevicePathSubType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].SubType)
2453         )
2454     {
2455       ToText = mUefiDevicePathLibToTextTable[Index].Function;
2456       break;
2457     }
2458   }
2459 
2460   //
2461   // Print this node
2462   //
2463   ToText (&Str, (VOID *)Node, DisplayOnly, AllowShortcuts);
2464 
2465   ASSERT (Str.Str != NULL);
2466   return Str.Str;
2467 }
2468 
2469 /**
2470   Converts a device path to its text representation.
2471 
2472   @param DevicePath      A Pointer to the device to be converted.
2473   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2474                          of the display node is used, where applicable. If DisplayOnly
2475                          is FALSE, then the longer text representation of the display node
2476                          is used.
2477   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2478                          representation for a device node can be used, where applicable.
2479 
2480   @return A pointer to the allocated text representation of the device path or
2481           NULL if DeviceNode is NULL or there was insufficient memory.
2482 
2483 **/
2484 static char *
2485 EFIAPI
2486 UefiDevicePathLibConvertDevicePathToText (
2487   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
2488   IN BOOLEAN                         DisplayOnly,
2489   IN BOOLEAN                         AllowShortcuts
2490   )
2491 {
2492   POOL_PRINT                Str;
2493   EFI_DEVICE_PATH_PROTOCOL  *Node;
2494   EFI_DEVICE_PATH_PROTOCOL  *AlignedNode;
2495   UINTN                     Index;
2496   DEVICE_PATH_TO_TEXT       ToText;
2497 
2498   if (DevicePath == NULL) {
2499     return NULL;
2500   }
2501 
2502   ZeroMem (&Str, sizeof (Str));
2503 
2504   //
2505   // Process each device path node
2506   //
2507   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DevicePath);
2508   while (!IsDevicePathEnd (Node)) {
2509     //
2510     // Find the handler to dump this device path node
2511     // If not found, use a generic function
2512     //
2513     ToText = DevPathToTextNodeGeneric;
2514     for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index += 1) {
2515       if ((DevicePathType (Node) == mUefiDevicePathLibToTextTable[Index].Type) &&
2516           (DevicePathSubType (Node) == mUefiDevicePathLibToTextTable[Index].SubType)
2517           )
2518       {
2519         ToText = mUefiDevicePathLibToTextTable[Index].Function;
2520         break;
2521       }
2522     }
2523 
2524     //
2525     //  Put a path separator in if needed
2526     //
2527     if ((Str.Count != 0) && (ToText != DevPathToTextEndInstance)) {
2528       if (Str.Str[Str.Count] != ',') {
2529         UefiDevicePathLibCatPrint (&Str, "/");
2530       }
2531     }
2532 
2533     AlignedNode = AllocateCopyPool (DevicePathNodeLength (Node), Node);
2534     //
2535     // Print this node of the device path
2536     //
2537     ToText (&Str, AlignedNode, DisplayOnly, AllowShortcuts);
2538     FreePool (AlignedNode);
2539 
2540     //
2541     // Next device path node
2542     //
2543     Node = NextDevicePathNode (Node);
2544   }
2545 
2546   if (Str.Str == NULL) {
2547     return AllocateZeroPool (sizeof (CHAR16));
2548   } else {
2549     return Str.Str;
2550   }
2551 }
2552 
2553 ssize_t
2554 efidp_format_device_path(char *buf, size_t len, const_efidp dp, ssize_t max)
2555 {
2556 	char *str;
2557 	ssize_t retval;
2558 
2559 	/*
2560 	 * Basic sanity check on the device path.
2561 	 */
2562 	if (!IsDevicePathValid((CONST EFI_DEVICE_PATH_PROTOCOL *) dp, max)) {
2563 		*buf = '\0';
2564 		return 0;
2565 	}
2566 
2567 	str = UefiDevicePathLibConvertDevicePathToText (
2568 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2569 	if (str == NULL)
2570 		return -1;
2571 	strlcpy(buf, str, len);
2572 	retval = strlen(str);
2573 	free(str);
2574 
2575 	return retval;
2576 }
2577 
2578 ssize_t
2579 efidp_format_device_path_node(char *buf, size_t len, const_efidp dp)
2580 {
2581 	char *str;
2582 	ssize_t retval;
2583 
2584 	str = UefiDevicePathLibConvertDeviceNodeToText (
2585 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2586 	if (str == NULL)
2587 		return -1;
2588 	strlcpy(buf, str, len);
2589 	retval = strlen(str);
2590 	free(str);
2591 
2592 	return retval;
2593 }
2594 
2595 size_t
2596 efidp_size(const_efidp dp)
2597 {
2598 
2599 	return GetDevicePathSize(__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp));
2600 }
2601 
2602 char *
2603 efidp_extract_file_path(const_efidp dp)
2604 {
2605 	const FILEPATH_DEVICE_PATH  *fp;
2606 	char *name = NULL;
2607 
2608 	fp = (const void *)dp;
2609 	ucs2_to_utf8(fp->PathName, &name);
2610 	return name;
2611 }
2612