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