xref: /freebsd/lib/libefivar/efivar-dp-format.c (revision 924226fba12cc9a228c73b956e1b7fa24c60b055)
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 = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), SerialNumberStr);
1053     ASSERT (NewStr != NULL);
1054     NewStr[Length]  = 0;
1055     SerialNumberStr = NewStr;
1056   }
1057 
1058   UefiDevicePathLibCatPrint (
1059     Str,
1060     "UsbWwid(0x%x,0x%x,0x%x,\"%S\")",
1061     UsbWWId->VendorId,
1062     UsbWWId->ProductId,
1063     UsbWWId->InterfaceNumber,
1064     SerialNumberStr
1065     );
1066 }
1067 
1068 /**
1069   Converts a Logic Unit device path structure to its string representative.
1070 
1071   @param Str             The string representative of input device.
1072   @param DevPath         The input device path structure.
1073   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1074                          of the display node is used, where applicable. If DisplayOnly
1075                          is FALSE, then the longer text representation of the display node
1076                          is used.
1077   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1078                          representation for a device node can be used, where applicable.
1079 
1080 **/
1081 static VOID
1082 DevPathToTextLogicalUnit (
1083   IN OUT POOL_PRINT  *Str,
1084   IN VOID            *DevPath,
1085   IN BOOLEAN         DisplayOnly,
1086   IN BOOLEAN         AllowShortcuts
1087   )
1088 {
1089   DEVICE_LOGICAL_UNIT_DEVICE_PATH  *LogicalUnit;
1090 
1091   LogicalUnit = DevPath;
1092   UefiDevicePathLibCatPrint (Str, "Unit(0x%x)", LogicalUnit->Lun);
1093 }
1094 
1095 /**
1096   Converts a USB class device path structure to its string representative.
1097 
1098   @param Str             The string representative of input device.
1099   @param DevPath         The input device path structure.
1100   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1101                          of the display node is used, where applicable. If DisplayOnly
1102                          is FALSE, then the longer text representation of the display node
1103                          is used.
1104   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1105                          representation for a device node can be used, where applicable.
1106 
1107 **/
1108 static VOID
1109 DevPathToTextUsbClass (
1110   IN OUT POOL_PRINT  *Str,
1111   IN VOID            *DevPath,
1112   IN BOOLEAN         DisplayOnly,
1113   IN BOOLEAN         AllowShortcuts
1114   )
1115 {
1116   USB_CLASS_DEVICE_PATH  *UsbClass;
1117   BOOLEAN                IsKnownSubClass;
1118 
1119   UsbClass = DevPath;
1120 
1121   IsKnownSubClass = TRUE;
1122   switch (UsbClass->DeviceClass) {
1123     case USB_CLASS_AUDIO:
1124       UefiDevicePathLibCatPrint (Str, "UsbAudio");
1125       break;
1126 
1127     case USB_CLASS_CDCCONTROL:
1128       UefiDevicePathLibCatPrint (Str, "UsbCDCControl");
1129       break;
1130 
1131     case USB_CLASS_HID:
1132       UefiDevicePathLibCatPrint (Str, "UsbHID");
1133       break;
1134 
1135     case USB_CLASS_IMAGE:
1136       UefiDevicePathLibCatPrint (Str, "UsbImage");
1137       break;
1138 
1139     case USB_CLASS_PRINTER:
1140       UefiDevicePathLibCatPrint (Str, "UsbPrinter");
1141       break;
1142 
1143     case USB_CLASS_MASS_STORAGE:
1144       UefiDevicePathLibCatPrint (Str, "UsbMassStorage");
1145       break;
1146 
1147     case USB_CLASS_HUB:
1148       UefiDevicePathLibCatPrint (Str, "UsbHub");
1149       break;
1150 
1151     case USB_CLASS_CDCDATA:
1152       UefiDevicePathLibCatPrint (Str, "UsbCDCData");
1153       break;
1154 
1155     case USB_CLASS_SMART_CARD:
1156       UefiDevicePathLibCatPrint (Str, "UsbSmartCard");
1157       break;
1158 
1159     case USB_CLASS_VIDEO:
1160       UefiDevicePathLibCatPrint (Str, "UsbVideo");
1161       break;
1162 
1163     case USB_CLASS_DIAGNOSTIC:
1164       UefiDevicePathLibCatPrint (Str, "UsbDiagnostic");
1165       break;
1166 
1167     case USB_CLASS_WIRELESS:
1168       UefiDevicePathLibCatPrint (Str, "UsbWireless");
1169       break;
1170 
1171     default:
1172       IsKnownSubClass = FALSE;
1173       break;
1174   }
1175 
1176   if (IsKnownSubClass) {
1177     UefiDevicePathLibCatPrint (
1178       Str,
1179       "(0x%x,0x%x,0x%x,0x%x)",
1180       UsbClass->VendorId,
1181       UsbClass->ProductId,
1182       UsbClass->DeviceSubClass,
1183       UsbClass->DeviceProtocol
1184       );
1185     return;
1186   }
1187 
1188   if (UsbClass->DeviceClass == USB_CLASS_RESERVE) {
1189     if (UsbClass->DeviceSubClass == USB_SUBCLASS_FW_UPDATE) {
1190       UefiDevicePathLibCatPrint (
1191         Str,
1192         "UsbDeviceFirmwareUpdate(0x%x,0x%x,0x%x)",
1193         UsbClass->VendorId,
1194         UsbClass->ProductId,
1195         UsbClass->DeviceProtocol
1196         );
1197       return;
1198     } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_IRDA_BRIDGE) {
1199       UefiDevicePathLibCatPrint (
1200         Str,
1201         "UsbIrdaBridge(0x%x,0x%x,0x%x)",
1202         UsbClass->VendorId,
1203         UsbClass->ProductId,
1204         UsbClass->DeviceProtocol
1205         );
1206       return;
1207     } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_TEST) {
1208       UefiDevicePathLibCatPrint (
1209         Str,
1210         "UsbTestAndMeasurement(0x%x,0x%x,0x%x)",
1211         UsbClass->VendorId,
1212         UsbClass->ProductId,
1213         UsbClass->DeviceProtocol
1214         );
1215       return;
1216     }
1217   }
1218 
1219   UefiDevicePathLibCatPrint (
1220     Str,
1221     "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
1222     UsbClass->VendorId,
1223     UsbClass->ProductId,
1224     UsbClass->DeviceClass,
1225     UsbClass->DeviceSubClass,
1226     UsbClass->DeviceProtocol
1227     );
1228 }
1229 
1230 /**
1231   Converts a SATA device path structure to its string representative.
1232 
1233   @param Str             The string representative of input device.
1234   @param DevPath         The input device path structure.
1235   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1236                          of the display node is used, where applicable. If DisplayOnly
1237                          is FALSE, then the longer text representation of the display node
1238                          is used.
1239   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1240                          representation for a device node can be used, where applicable.
1241 
1242 **/
1243 static VOID
1244 DevPathToTextSata (
1245   IN OUT POOL_PRINT  *Str,
1246   IN VOID            *DevPath,
1247   IN BOOLEAN         DisplayOnly,
1248   IN BOOLEAN         AllowShortcuts
1249   )
1250 {
1251   SATA_DEVICE_PATH  *Sata;
1252 
1253   Sata = DevPath;
1254   UefiDevicePathLibCatPrint (
1255     Str,
1256     "Sata(0x%x,0x%x,0x%x)",
1257     Sata->HBAPortNumber,
1258     Sata->PortMultiplierPortNumber,
1259     Sata->Lun
1260     );
1261 }
1262 
1263 /**
1264   Converts a I20 device path structure to its string representative.
1265 
1266   @param Str             The string representative of input device.
1267   @param DevPath         The input device path structure.
1268   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1269                          of the display node is used, where applicable. If DisplayOnly
1270                          is FALSE, then the longer text representation of the display node
1271                          is used.
1272   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1273                          representation for a device node can be used, where applicable.
1274 
1275 **/
1276 static VOID
1277 DevPathToTextI2O (
1278   IN OUT POOL_PRINT  *Str,
1279   IN VOID            *DevPath,
1280   IN BOOLEAN         DisplayOnly,
1281   IN BOOLEAN         AllowShortcuts
1282   )
1283 {
1284   I2O_DEVICE_PATH  *I2ODevPath;
1285 
1286   I2ODevPath = DevPath;
1287   UefiDevicePathLibCatPrint (Str, "I2O(0x%x)", I2ODevPath->Tid);
1288 }
1289 
1290 /**
1291   Converts a MAC address device path structure to its string representative.
1292 
1293   @param Str             The string representative of input device.
1294   @param DevPath         The input device path structure.
1295   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1296                          of the display node is used, where applicable. If DisplayOnly
1297                          is FALSE, then the longer text representation of the display node
1298                          is used.
1299   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1300                          representation for a device node can be used, where applicable.
1301 
1302 **/
1303 static VOID
1304 DevPathToTextMacAddr (
1305   IN OUT POOL_PRINT  *Str,
1306   IN VOID            *DevPath,
1307   IN BOOLEAN         DisplayOnly,
1308   IN BOOLEAN         AllowShortcuts
1309   )
1310 {
1311   MAC_ADDR_DEVICE_PATH  *MacDevPath;
1312   UINTN                 HwAddressSize;
1313   UINTN                 Index;
1314 
1315   MacDevPath = DevPath;
1316 
1317   HwAddressSize = sizeof (EFI_MAC_ADDRESS);
1318   if ((MacDevPath->IfType == 0x01) || (MacDevPath->IfType == 0x00)) {
1319     HwAddressSize = 6;
1320   }
1321 
1322   UefiDevicePathLibCatPrint (Str, "MAC(");
1323 
1324   for (Index = 0; Index < HwAddressSize; Index++) {
1325     UefiDevicePathLibCatPrint (Str, "%02x", MacDevPath->MacAddress.Addr[Index]);
1326   }
1327 
1328   UefiDevicePathLibCatPrint (Str, ",0x%x)", MacDevPath->IfType);
1329 }
1330 
1331 /**
1332   Converts network protocol string to its text representation.
1333 
1334   @param Str             The string representative of input device.
1335   @param Protocol        The network protocol ID.
1336 
1337 **/
1338 static VOID
1339 CatNetworkProtocol (
1340   IN OUT POOL_PRINT  *Str,
1341   IN UINT16          Protocol
1342   )
1343 {
1344   if (Protocol == RFC_1700_TCP_PROTOCOL) {
1345     UefiDevicePathLibCatPrint (Str, "TCP");
1346   } else if (Protocol == RFC_1700_UDP_PROTOCOL) {
1347     UefiDevicePathLibCatPrint (Str, "UDP");
1348   } else {
1349     UefiDevicePathLibCatPrint (Str, "0x%x", Protocol);
1350   }
1351 }
1352 
1353 /**
1354   Converts IP v4 address to its text representation.
1355 
1356   @param Str             The string representative of input device.
1357   @param Address         The IP v4 address.
1358 **/
1359 static VOID
1360 CatIPv4Address (
1361   IN OUT POOL_PRINT    *Str,
1362   IN EFI_IPv4_ADDRESS  *Address
1363   )
1364 {
1365   UefiDevicePathLibCatPrint (Str, "%d.%d.%d.%d", Address->Addr[0], Address->Addr[1], Address->Addr[2], Address->Addr[3]);
1366 }
1367 
1368 /**
1369   Converts IP v6 address to its text representation.
1370 
1371   @param Str             The string representative of input device.
1372   @param Address         The IP v6 address.
1373 **/
1374 static VOID
1375 CatIPv6Address (
1376   IN OUT POOL_PRINT    *Str,
1377   IN EFI_IPv6_ADDRESS  *Address
1378   )
1379 {
1380   UefiDevicePathLibCatPrint (
1381     Str,
1382     "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
1383     Address->Addr[0],
1384     Address->Addr[1],
1385     Address->Addr[2],
1386     Address->Addr[3],
1387     Address->Addr[4],
1388     Address->Addr[5],
1389     Address->Addr[6],
1390     Address->Addr[7],
1391     Address->Addr[8],
1392     Address->Addr[9],
1393     Address->Addr[10],
1394     Address->Addr[11],
1395     Address->Addr[12],
1396     Address->Addr[13],
1397     Address->Addr[14],
1398     Address->Addr[15]
1399     );
1400 }
1401 
1402 /**
1403   Converts a IPv4 device path structure to its string representative.
1404 
1405   @param Str             The string representative of input device.
1406   @param DevPath         The input device path structure.
1407   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1408                          of the display node is used, where applicable. If DisplayOnly
1409                          is FALSE, then the longer text representation of the display node
1410                          is used.
1411   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1412                          representation for a device node can be used, where applicable.
1413 
1414 **/
1415 static VOID
1416 DevPathToTextIPv4 (
1417   IN OUT POOL_PRINT  *Str,
1418   IN VOID            *DevPath,
1419   IN BOOLEAN         DisplayOnly,
1420   IN BOOLEAN         AllowShortcuts
1421   )
1422 {
1423   IPv4_DEVICE_PATH  *IPDevPath;
1424 
1425   IPDevPath = DevPath;
1426   UefiDevicePathLibCatPrint (Str, "IPv4(");
1427   CatIPv4Address (Str, &IPDevPath->RemoteIpAddress);
1428 
1429   if (DisplayOnly) {
1430     UefiDevicePathLibCatPrint (Str, ")");
1431     return;
1432   }
1433 
1434   UefiDevicePathLibCatPrint (Str, ",");
1435   CatNetworkProtocol (Str, IPDevPath->Protocol);
1436 
1437   UefiDevicePathLibCatPrint (Str, ",%s,", IPDevPath->StaticIpAddress ? "Static" : "DHCP");
1438   CatIPv4Address (Str, &IPDevPath->LocalIpAddress);
1439   if (DevicePathNodeLength (IPDevPath) == sizeof (IPv4_DEVICE_PATH)) {
1440     UefiDevicePathLibCatPrint (Str, ",");
1441     CatIPv4Address (Str, &IPDevPath->GatewayIpAddress);
1442     UefiDevicePathLibCatPrint (Str, ",");
1443     CatIPv4Address (Str, &IPDevPath->SubnetMask);
1444   }
1445 
1446   UefiDevicePathLibCatPrint (Str, ")");
1447 }
1448 
1449 /**
1450   Converts a IPv6 device path structure to its string representative.
1451 
1452   @param Str             The string representative of input device.
1453   @param DevPath         The input device path structure.
1454   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1455                          of the display node is used, where applicable. If DisplayOnly
1456                          is FALSE, then the longer text representation of the display node
1457                          is used.
1458   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1459                          representation for a device node can be used, where applicable.
1460 
1461 **/
1462 static VOID
1463 DevPathToTextIPv6 (
1464   IN OUT POOL_PRINT  *Str,
1465   IN VOID            *DevPath,
1466   IN BOOLEAN         DisplayOnly,
1467   IN BOOLEAN         AllowShortcuts
1468   )
1469 {
1470   IPv6_DEVICE_PATH  *IPDevPath;
1471 
1472   IPDevPath = DevPath;
1473   UefiDevicePathLibCatPrint (Str, "IPv6(");
1474   CatIPv6Address (Str, &IPDevPath->RemoteIpAddress);
1475   if (DisplayOnly) {
1476     UefiDevicePathLibCatPrint (Str, ")");
1477     return;
1478   }
1479 
1480   UefiDevicePathLibCatPrint (Str, ",");
1481   CatNetworkProtocol (Str, IPDevPath->Protocol);
1482 
1483   switch (IPDevPath->IpAddressOrigin) {
1484     case 0:
1485       UefiDevicePathLibCatPrint (Str, ",Static,");
1486       break;
1487     case 1:
1488       UefiDevicePathLibCatPrint (Str, ",StatelessAutoConfigure,");
1489       break;
1490     default:
1491       UefiDevicePathLibCatPrint (Str, ",StatefulAutoConfigure,");
1492       break;
1493   }
1494 
1495   CatIPv6Address (Str, &IPDevPath->LocalIpAddress);
1496 
1497   if (DevicePathNodeLength (IPDevPath) == sizeof (IPv6_DEVICE_PATH)) {
1498     UefiDevicePathLibCatPrint (Str, ",0x%x,", IPDevPath->PrefixLength);
1499     CatIPv6Address (Str, &IPDevPath->GatewayIpAddress);
1500   }
1501 
1502   UefiDevicePathLibCatPrint (Str, ")");
1503 }
1504 
1505 /**
1506   Converts an Infini Band device path structure to its string representative.
1507 
1508   @param Str             The string representative of input device.
1509   @param DevPath         The input device path structure.
1510   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1511                          of the display node is used, where applicable. If DisplayOnly
1512                          is FALSE, then the longer text representation of the display node
1513                          is used.
1514   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1515                          representation for a device node can be used, where applicable.
1516 
1517 **/
1518 static VOID
1519 DevPathToTextInfiniBand (
1520   IN OUT POOL_PRINT  *Str,
1521   IN VOID            *DevPath,
1522   IN BOOLEAN         DisplayOnly,
1523   IN BOOLEAN         AllowShortcuts
1524   )
1525 {
1526   INFINIBAND_DEVICE_PATH  *InfiniBand;
1527 
1528   InfiniBand = DevPath;
1529   UefiDevicePathLibCatPrint (
1530     Str,
1531     "Infiniband(0x%x,%36s,0x%lx,0x%lx,0x%lx)",
1532     InfiniBand->ResourceFlags,
1533     G(InfiniBand->PortGid),
1534     InfiniBand->ServiceId,
1535     InfiniBand->TargetPortId,
1536     InfiniBand->DeviceId
1537     );
1538 }
1539 
1540 /**
1541   Converts a UART device path structure to its string representative.
1542 
1543   @param Str             The string representative of input device.
1544   @param DevPath         The input device path structure.
1545   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1546                          of the display node is used, where applicable. If DisplayOnly
1547                          is FALSE, then the longer text representation of the display node
1548                          is used.
1549   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1550                          representation for a device node can be used, where applicable.
1551 
1552 **/
1553 static VOID
1554 DevPathToTextUart (
1555   IN OUT POOL_PRINT  *Str,
1556   IN VOID            *DevPath,
1557   IN BOOLEAN         DisplayOnly,
1558   IN BOOLEAN         AllowShortcuts
1559   )
1560 {
1561   UART_DEVICE_PATH  *Uart;
1562   CHAR8             Parity;
1563 
1564   Uart = DevPath;
1565   switch (Uart->Parity) {
1566     case 0:
1567       Parity = 'D';
1568       break;
1569 
1570     case 1:
1571       Parity = 'N';
1572       break;
1573 
1574     case 2:
1575       Parity = 'E';
1576       break;
1577 
1578     case 3:
1579       Parity = 'O';
1580       break;
1581 
1582     case 4:
1583       Parity = 'M';
1584       break;
1585 
1586     case 5:
1587       Parity = 'S';
1588       break;
1589 
1590     default:
1591       Parity = 'x';
1592       break;
1593   }
1594 
1595   if (Uart->BaudRate == 0) {
1596     UefiDevicePathLibCatPrint (Str, "Uart(DEFAULT,");
1597   } else {
1598     UefiDevicePathLibCatPrint (Str, "Uart(%ld,", Uart->BaudRate);
1599   }
1600 
1601   if (Uart->DataBits == 0) {
1602     UefiDevicePathLibCatPrint (Str, "DEFAULT,");
1603   } else {
1604     UefiDevicePathLibCatPrint (Str, "%d,", Uart->DataBits);
1605   }
1606 
1607   UefiDevicePathLibCatPrint (Str, "%c,", Parity);
1608 
1609   switch (Uart->StopBits) {
1610     case 0:
1611       UefiDevicePathLibCatPrint (Str, "D)");
1612       break;
1613 
1614     case 1:
1615       UefiDevicePathLibCatPrint (Str, "1)");
1616       break;
1617 
1618     case 2:
1619       UefiDevicePathLibCatPrint (Str, "1.5)");
1620       break;
1621 
1622     case 3:
1623       UefiDevicePathLibCatPrint (Str, "2)");
1624       break;
1625 
1626     default:
1627       UefiDevicePathLibCatPrint (Str, "x)");
1628       break;
1629   }
1630 }
1631 
1632 /**
1633   Converts an iSCSI device path structure to its string representative.
1634 
1635   @param Str             The string representative of input device.
1636   @param DevPath         The input device path structure.
1637   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1638                          of the display node is used, where applicable. If DisplayOnly
1639                          is FALSE, then the longer text representation of the display node
1640                          is used.
1641   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1642                          representation for a device node can be used, where applicable.
1643 
1644 **/
1645 static VOID
1646 DevPathToTextiSCSI (
1647   IN OUT POOL_PRINT  *Str,
1648   IN VOID            *DevPath,
1649   IN BOOLEAN         DisplayOnly,
1650   IN BOOLEAN         AllowShortcuts
1651   )
1652 {
1653   ISCSI_DEVICE_PATH_WITH_NAME  *ISCSIDevPath;
1654   UINT16                       Options;
1655   UINTN                        Index;
1656 
1657   ISCSIDevPath = DevPath;
1658   UefiDevicePathLibCatPrint (
1659     Str,
1660     "iSCSI(%s,0x%x,0x",
1661     ISCSIDevPath->TargetName,
1662     ISCSIDevPath->TargetPortalGroupTag
1663     );
1664   for (Index = 0; Index < sizeof (ISCSIDevPath->Lun) / sizeof (UINT8); Index++) {
1665     UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *)&ISCSIDevPath->Lun)[Index]);
1666   }
1667 
1668   Options = ISCSIDevPath->LoginOption;
1669   UefiDevicePathLibCatPrint (Str, ",%s,", (((Options >> 1) & 0x0001) != 0) ? "CRC32C" : "None");
1670   UefiDevicePathLibCatPrint (Str, "%s,", (((Options >> 3) & 0x0001) != 0) ? "CRC32C" : "None");
1671   if (((Options >> 11) & 0x0001) != 0) {
1672     UefiDevicePathLibCatPrint (Str, "%s,", "None");
1673   } else if (((Options >> 12) & 0x0001) != 0) {
1674     UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_UNI");
1675   } else {
1676     UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_BI");
1677   }
1678 
1679   UefiDevicePathLibCatPrint (Str, "%s)", (ISCSIDevPath->NetworkProtocol == 0) ? "TCP" : "reserved");
1680 }
1681 
1682 /**
1683   Converts a VLAN device path structure to its string representative.
1684 
1685   @param Str             The string representative of input device.
1686   @param DevPath         The input device path structure.
1687   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1688                          of the display node is used, where applicable. If DisplayOnly
1689                          is FALSE, then the longer text representation of the display node
1690                          is used.
1691   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1692                          representation for a device node can be used, where applicable.
1693 
1694 **/
1695 static VOID
1696 DevPathToTextVlan (
1697   IN OUT POOL_PRINT  *Str,
1698   IN VOID            *DevPath,
1699   IN BOOLEAN         DisplayOnly,
1700   IN BOOLEAN         AllowShortcuts
1701   )
1702 {
1703   VLAN_DEVICE_PATH  *Vlan;
1704 
1705   Vlan = DevPath;
1706   UefiDevicePathLibCatPrint (Str, "Vlan(%d)", Vlan->VlanId);
1707 }
1708 
1709 /**
1710   Converts a Bluetooth device path structure to its string representative.
1711 
1712   @param Str             The string representative of input device.
1713   @param DevPath         The input device path structure.
1714   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1715                          of the display node is used, where applicable. If DisplayOnly
1716                          is FALSE, then the longer text representation of the display node
1717                          is used.
1718   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1719                          representation for a device node can be used, where applicable.
1720 
1721 **/
1722 static VOID
1723 DevPathToTextBluetooth (
1724   IN OUT POOL_PRINT  *Str,
1725   IN VOID            *DevPath,
1726   IN BOOLEAN         DisplayOnly,
1727   IN BOOLEAN         AllowShortcuts
1728   )
1729 {
1730   BLUETOOTH_DEVICE_PATH  *Bluetooth;
1731 
1732   Bluetooth = DevPath;
1733   UefiDevicePathLibCatPrint (
1734     Str,
1735     "Bluetooth(%02x%02x%02x%02x%02x%02x)",
1736     Bluetooth->BD_ADDR.Address[0],
1737     Bluetooth->BD_ADDR.Address[1],
1738     Bluetooth->BD_ADDR.Address[2],
1739     Bluetooth->BD_ADDR.Address[3],
1740     Bluetooth->BD_ADDR.Address[4],
1741     Bluetooth->BD_ADDR.Address[5]
1742     );
1743 }
1744 
1745 /**
1746   Converts a Wi-Fi device path structure to its string representative.
1747 
1748   @param Str             The string representative of input device.
1749   @param DevPath         The input device path structure.
1750   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1751                          of the display node is used, where applicable. If DisplayOnly
1752                          is FALSE, then the longer text representation of the display node
1753                          is used.
1754   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1755                          representation for a device node can be used, where applicable.
1756 
1757 **/
1758 static VOID
1759 DevPathToTextWiFi (
1760   IN OUT POOL_PRINT  *Str,
1761   IN VOID            *DevPath,
1762   IN BOOLEAN         DisplayOnly,
1763   IN BOOLEAN         AllowShortcuts
1764   )
1765 {
1766   WIFI_DEVICE_PATH  *WiFi;
1767   UINT8             SSId[33];
1768 
1769   WiFi = DevPath;
1770 
1771   SSId[32] = '\0';
1772   CopyMem (SSId, WiFi->SSId, 32);
1773 
1774   UefiDevicePathLibCatPrint (Str, "Wi-Fi(%s)", SSId);
1775 }
1776 
1777 /**
1778   Converts a Bluetooth device path structure to its string representative.
1779 
1780   @param Str             The string representative of input device.
1781   @param DevPath         The input device path structure.
1782   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1783                          of the display node is used, where applicable. If DisplayOnly
1784                          is FALSE, then the longer text representation of the display node
1785                          is used.
1786   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1787                          representation for a device node can be used, where applicable.
1788 
1789 **/
1790 static VOID
1791 DevPathToTextBluetoothLE (
1792   IN OUT POOL_PRINT  *Str,
1793   IN VOID            *DevPath,
1794   IN BOOLEAN         DisplayOnly,
1795   IN BOOLEAN         AllowShortcuts
1796   )
1797 {
1798   BLUETOOTH_LE_DEVICE_PATH  *BluetoothLE;
1799 
1800   BluetoothLE = DevPath;
1801   UefiDevicePathLibCatPrint (
1802     Str,
1803     "BluetoothLE(%02x%02x%02x%02x%02x%02x,0x%02x)",
1804     BluetoothLE->Address.Address[0],
1805     BluetoothLE->Address.Address[1],
1806     BluetoothLE->Address.Address[2],
1807     BluetoothLE->Address.Address[3],
1808     BluetoothLE->Address.Address[4],
1809     BluetoothLE->Address.Address[5],
1810     BluetoothLE->Address.Type
1811     );
1812 }
1813 
1814 /**
1815   Converts a DNS device path structure to its string representative.
1816 
1817   @param Str             The string representative of input device.
1818   @param DevPath         The input device path structure.
1819   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1820                          of the display node is used, where applicable. If DisplayOnly
1821                          is FALSE, then the longer text representation of the display node
1822                          is used.
1823   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1824                          representation for a device node can be used, where applicable.
1825 
1826 **/
1827 static VOID
1828 DevPathToTextDns (
1829   IN OUT POOL_PRINT  *Str,
1830   IN VOID            *DevPath,
1831   IN BOOLEAN         DisplayOnly,
1832   IN BOOLEAN         AllowShortcuts
1833   )
1834 {
1835   DNS_DEVICE_PATH  *DnsDevPath;
1836   UINT32           DnsServerIpCount;
1837   UINT32           DnsServerIpIndex;
1838 
1839   DnsDevPath       = DevPath;
1840   DnsServerIpCount = (UINT32)(DevicePathNodeLength (DnsDevPath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof (DnsDevPath->IsIPv6)) / sizeof (EFI_IP_ADDRESS);
1841 
1842   UefiDevicePathLibCatPrint (Str, "Dns(");
1843 
1844   for (DnsServerIpIndex = 0; DnsServerIpIndex < DnsServerIpCount; DnsServerIpIndex++) {
1845     if (DnsDevPath->IsIPv6 == 0x00) {
1846       CatIPv4Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v4));
1847     } else {
1848       CatIPv6Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v6));
1849     }
1850 
1851     if (DnsServerIpIndex < DnsServerIpCount - 1) {
1852       UefiDevicePathLibCatPrint (Str, ",");
1853     }
1854   }
1855 
1856   UefiDevicePathLibCatPrint (Str, ")");
1857 }
1858 
1859 /**
1860   Converts a URI device path structure to its string representative.
1861 
1862   @param Str             The string representative of input device.
1863   @param DevPath         The input device path structure.
1864   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1865                          of the display node is used, where applicable. If DisplayOnly
1866                          is FALSE, then the longer text representation of the display node
1867                          is used.
1868   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1869                          representation for a device node can be used, where applicable.
1870 
1871 **/
1872 static VOID
1873 DevPathToTextUri (
1874   IN OUT POOL_PRINT  *Str,
1875   IN VOID            *DevPath,
1876   IN BOOLEAN         DisplayOnly,
1877   IN BOOLEAN         AllowShortcuts
1878   )
1879 {
1880   URI_DEVICE_PATH  *Uri;
1881   UINTN            UriLength;
1882   CHAR8            *UriStr;
1883 
1884   //
1885   // Uri in the device path may not be null terminated.
1886   //
1887   Uri       = DevPath;
1888   UriLength = DevicePathNodeLength (Uri) - sizeof (URI_DEVICE_PATH);
1889   UriStr    = AllocatePool (UriLength + 1);
1890   ASSERT (UriStr != NULL);
1891 
1892   CopyMem (UriStr, Uri->Uri, UriLength);
1893   UriStr[UriLength] = '\0';
1894   UefiDevicePathLibCatPrint (Str, "Uri(%s)", UriStr);
1895   FreePool (UriStr);
1896 }
1897 
1898 /**
1899   Converts a Hard drive device path structure to its string representative.
1900 
1901   @param Str             The string representative of input device.
1902   @param DevPath         The input device path structure.
1903   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1904                          of the display node is used, where applicable. If DisplayOnly
1905                          is FALSE, then the longer text representation of the display node
1906                          is used.
1907   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1908                          representation for a device node can be used, where applicable.
1909 
1910 **/
1911 static VOID
1912 DevPathToTextHardDrive (
1913   IN OUT POOL_PRINT  *Str,
1914   IN VOID            *DevPath,
1915   IN BOOLEAN         DisplayOnly,
1916   IN BOOLEAN         AllowShortcuts
1917   )
1918 {
1919   HARDDRIVE_DEVICE_PATH  *Hd;
1920 
1921   Hd = DevPath;
1922   switch (Hd->SignatureType) {
1923     case SIGNATURE_TYPE_MBR:
1924       UefiDevicePathLibCatPrint (
1925         Str,
1926         "HD(%d,%s,0x%08x,",
1927         Hd->PartitionNumber,
1928         "MBR",
1929 //      *((UINT32 *)(&(Hd->Signature[0])))
1930         le32dec(&(Hd->Signature[0]))
1931         );
1932       break;
1933 
1934     case SIGNATURE_TYPE_GUID:
1935       UefiDevicePathLibCatPrint (
1936         Str,
1937         "HD(%d,%s,%36s,",
1938         Hd->PartitionNumber,
1939         "GPT",
1940         G(&(Hd->Signature[0]))
1941         );
1942       break;
1943 
1944     default:
1945       UefiDevicePathLibCatPrint (
1946         Str,
1947         "HD(%d,%d,0,",
1948         Hd->PartitionNumber,
1949         Hd->SignatureType
1950         );
1951       break;
1952   }
1953 
1954   UefiDevicePathLibCatPrint (Str, "0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
1955 }
1956 
1957 /**
1958   Converts a CDROM device path structure to its string representative.
1959 
1960   @param Str             The string representative of input device.
1961   @param DevPath         The input device path structure.
1962   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1963                          of the display node is used, where applicable. If DisplayOnly
1964                          is FALSE, then the longer text representation of the display node
1965                          is used.
1966   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1967                          representation for a device node can be used, where applicable.
1968 
1969 **/
1970 static VOID
1971 DevPathToTextCDROM (
1972   IN OUT POOL_PRINT  *Str,
1973   IN VOID            *DevPath,
1974   IN BOOLEAN         DisplayOnly,
1975   IN BOOLEAN         AllowShortcuts
1976   )
1977 {
1978   CDROM_DEVICE_PATH  *Cd;
1979 
1980   Cd = DevPath;
1981   if (DisplayOnly) {
1982     UefiDevicePathLibCatPrint (Str, "CDROM(0x%x)", Cd->BootEntry);
1983     return;
1984   }
1985 
1986   UefiDevicePathLibCatPrint (Str, "CDROM(0x%x,0x%lx,0x%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
1987 }
1988 
1989 /**
1990   Converts a File device path structure to its string representative.
1991 
1992   @param Str             The string representative of input device.
1993   @param DevPath         The input device path structure.
1994   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
1995                          of the display node is used, where applicable. If DisplayOnly
1996                          is FALSE, then the longer text representation of the display node
1997                          is used.
1998   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
1999                          representation for a device node can be used, where applicable.
2000 
2001 **/
2002 static VOID
2003 DevPathToTextFilePath (
2004   IN OUT POOL_PRINT  *Str,
2005   IN VOID            *DevPath,
2006   IN BOOLEAN         DisplayOnly,
2007   IN BOOLEAN         AllowShortcuts
2008   )
2009 {
2010   FILEPATH_DEVICE_PATH  *Fp;
2011   char *name = NULL;
2012 
2013   Fp = DevPath;
2014   ucs2_to_utf8(Fp->PathName, &name);
2015   UefiDevicePathLibCatPrint (Str, "File(%s)", name);
2016   free(name);
2017 }
2018 
2019 /**
2020   Converts a Media protocol device path structure to its string representative.
2021 
2022   @param Str             The string representative of input device.
2023   @param DevPath         The input device path structure.
2024   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2025                          of the display node is used, where applicable. If DisplayOnly
2026                          is FALSE, then the longer text representation of the display node
2027                          is used.
2028   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2029                          representation for a device node can be used, where applicable.
2030 
2031 **/
2032 static VOID
2033 DevPathToTextMediaProtocol (
2034   IN OUT POOL_PRINT  *Str,
2035   IN VOID            *DevPath,
2036   IN BOOLEAN         DisplayOnly,
2037   IN BOOLEAN         AllowShortcuts
2038   )
2039 {
2040   MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
2041 
2042   MediaProt = DevPath;
2043   UefiDevicePathLibCatPrint (Str, "Media(%36s)", G(&MediaProt->Protocol));
2044 }
2045 
2046 /**
2047   Converts a Firmware Volume device path structure to its string representative.
2048 
2049   @param Str             The string representative of input device.
2050   @param DevPath         The input device path structure.
2051   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2052                          of the display node is used, where applicable. If DisplayOnly
2053                          is FALSE, then the longer text representation of the display node
2054                          is used.
2055   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2056                          representation for a device node can be used, where applicable.
2057 
2058 **/
2059 static VOID
2060 DevPathToTextFv (
2061   IN OUT POOL_PRINT  *Str,
2062   IN VOID            *DevPath,
2063   IN BOOLEAN         DisplayOnly,
2064   IN BOOLEAN         AllowShortcuts
2065   )
2066 {
2067   MEDIA_FW_VOL_DEVICE_PATH  *Fv;
2068 
2069   Fv = DevPath;
2070   UefiDevicePathLibCatPrint (Str, "Fv(%36s)", G(&Fv->FvName));
2071 }
2072 
2073 /**
2074   Converts a Firmware Volume File device path structure to its string representative.
2075 
2076   @param Str             The string representative of input device.
2077   @param DevPath         The input device path structure.
2078   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2079                          of the display node is used, where applicable. If DisplayOnly
2080                          is FALSE, then the longer text representation of the display node
2081                          is used.
2082   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2083                          representation for a device node can be used, where applicable.
2084 
2085 **/
2086 static VOID
2087 DevPathToTextFvFile (
2088   IN OUT POOL_PRINT  *Str,
2089   IN VOID            *DevPath,
2090   IN BOOLEAN         DisplayOnly,
2091   IN BOOLEAN         AllowShortcuts
2092   )
2093 {
2094   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFile;
2095 
2096   FvFile = DevPath;
2097   UefiDevicePathLibCatPrint (Str, "FvFile(%36s)", G(&FvFile->FvFileName));
2098 }
2099 
2100 /**
2101   Converts a Relative Offset device path structure to its string representative.
2102 
2103   @param Str             The string representative of input device.
2104   @param DevPath         The input device path structure.
2105   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2106                          of the display node is used, where applicable. If DisplayOnly
2107                          is FALSE, then the longer text representation of the display node
2108                          is used.
2109   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2110                          representation for a device node can be used, where applicable.
2111 
2112 **/
2113 static VOID
2114 DevPathRelativeOffsetRange (
2115   IN OUT POOL_PRINT  *Str,
2116   IN VOID            *DevPath,
2117   IN BOOLEAN         DisplayOnly,
2118   IN BOOLEAN         AllowShortcuts
2119   )
2120 {
2121   MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  *Offset;
2122 
2123   Offset = DevPath;
2124   UefiDevicePathLibCatPrint (
2125     Str,
2126     "Offset(0x%lx,0x%lx)",
2127     Offset->StartingOffset,
2128     Offset->EndingOffset
2129     );
2130 }
2131 
2132 /**
2133   Converts a Ram Disk device path structure to its string representative.
2134 
2135   @param Str             The string representative of input device.
2136   @param DevPath         The input device path structure.
2137   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2138                          of the display node is used, where applicable. If DisplayOnly
2139                          is FALSE, then the longer text representation of the display node
2140                          is used.
2141   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2142                          representation for a device node can be used, where applicable.
2143 
2144 **/
2145 static VOID
2146 DevPathToTextRamDisk (
2147   IN OUT POOL_PRINT  *Str,
2148   IN VOID            *DevPath,
2149   IN BOOLEAN         DisplayOnly,
2150   IN BOOLEAN         AllowShortcuts
2151   )
2152 {
2153   MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
2154 
2155   RamDisk = DevPath;
2156 
2157   if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid)) {
2158     UefiDevicePathLibCatPrint (
2159       Str,
2160       "VirtualDisk(0x%lx,0x%lx,%d)",
2161       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2162       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2163       RamDisk->Instance
2164       );
2165   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid)) {
2166     UefiDevicePathLibCatPrint (
2167       Str,
2168       "VirtualCD(0x%lx,0x%lx,%d)",
2169       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2170       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2171       RamDisk->Instance
2172       );
2173   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid)) {
2174     UefiDevicePathLibCatPrint (
2175       Str,
2176       "PersistentVirtualDisk(0x%lx,0x%lx,%d)",
2177       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2178       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2179       RamDisk->Instance
2180       );
2181   } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid)) {
2182     UefiDevicePathLibCatPrint (
2183       Str,
2184       "PersistentVirtualCD(0x%lx,0x%lx,%d)",
2185       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2186       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2187       RamDisk->Instance
2188       );
2189   } else {
2190     UefiDevicePathLibCatPrint (
2191       Str,
2192       "RamDisk(0x%lx,0x%lx,%d,%36s)",
2193       LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
2194       LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
2195       RamDisk->Instance,
2196       G(&RamDisk->TypeGuid)
2197       );
2198   }
2199 }
2200 
2201 /**
2202   Converts a BIOS Boot Specification device path structure to its string representative.
2203 
2204   @param Str             The string representative of input device.
2205   @param DevPath         The input device path structure.
2206   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2207                          of the display node is used, where applicable. If DisplayOnly
2208                          is FALSE, then the longer text representation of the display node
2209                          is used.
2210   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2211                          representation for a device node can be used, where applicable.
2212 
2213 **/
2214 static VOID
2215 DevPathToTextBBS (
2216   IN OUT POOL_PRINT  *Str,
2217   IN VOID            *DevPath,
2218   IN BOOLEAN         DisplayOnly,
2219   IN BOOLEAN         AllowShortcuts
2220   )
2221 {
2222   BBS_BBS_DEVICE_PATH  *Bbs;
2223   const char           *Type;
2224 
2225   Bbs = DevPath;
2226   switch (Bbs->DeviceType) {
2227     case BBS_TYPE_FLOPPY:
2228       Type = "Floppy";
2229       break;
2230 
2231     case BBS_TYPE_HARDDRIVE:
2232       Type = "HD";
2233       break;
2234 
2235     case BBS_TYPE_CDROM:
2236       Type = "CDROM";
2237       break;
2238 
2239     case BBS_TYPE_PCMCIA:
2240       Type = "PCMCIA";
2241       break;
2242 
2243     case BBS_TYPE_USB:
2244       Type = "USB";
2245       break;
2246 
2247     case BBS_TYPE_EMBEDDED_NETWORK:
2248       Type = "Network";
2249       break;
2250 
2251     default:
2252       Type = NULL;
2253       break;
2254   }
2255 
2256   if (Type != NULL) {
2257     UefiDevicePathLibCatPrint (Str, "BBS(%s,%s", Type, Bbs->String);
2258   } else {
2259     UefiDevicePathLibCatPrint (Str, "BBS(0x%x,%s", Bbs->DeviceType, Bbs->String);
2260   }
2261 
2262   if (DisplayOnly) {
2263     UefiDevicePathLibCatPrint (Str, ")");
2264     return;
2265   }
2266 
2267   UefiDevicePathLibCatPrint (Str, ",0x%x)", Bbs->StatusFlag);
2268 }
2269 
2270 /**
2271   Converts an End-of-Device-Path structure to its string representative.
2272 
2273   @param Str             The string representative of input device.
2274   @param DevPath         The input device path structure.
2275   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2276                          of the display node is used, where applicable. If DisplayOnly
2277                          is FALSE, then the longer text representation of the display node
2278                          is used.
2279   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2280                          representation for a device node can be used, where applicable.
2281 
2282 **/
2283 static VOID
2284 DevPathToTextEndInstance (
2285   IN OUT POOL_PRINT  *Str,
2286   IN VOID            *DevPath,
2287   IN BOOLEAN         DisplayOnly,
2288   IN BOOLEAN         AllowShortcuts
2289   )
2290 {
2291   UefiDevicePathLibCatPrint (Str, ",");
2292 }
2293 
2294 GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_GENERIC_TABLE  mUefiDevicePathLibToTextTableGeneric[] = {
2295   { HARDWARE_DEVICE_PATH,  "HardwarePath" },
2296   { ACPI_DEVICE_PATH,      "AcpiPath"     },
2297   { MESSAGING_DEVICE_PATH, "Msg"          },
2298   { MEDIA_DEVICE_PATH,     "MediaPath"    },
2299   { BBS_DEVICE_PATH,       "BbsPath"      },
2300   { 0,                     NULL            }
2301 };
2302 
2303 /**
2304   Converts an unknown device path structure to its string representative.
2305 
2306   @param Str             The string representative of input device.
2307   @param DevPath         The input device path structure.
2308   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2309                          of the display node is used, where applicable. If DisplayOnly
2310                          is FALSE, then the longer text representation of the display node
2311                          is used.
2312   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2313                          representation for a device node can be used, where applicable.
2314 
2315 **/
2316 static VOID
2317 DevPathToTextNodeGeneric (
2318   IN OUT POOL_PRINT  *Str,
2319   IN VOID            *DevPath,
2320   IN BOOLEAN         DisplayOnly,
2321   IN BOOLEAN         AllowShortcuts
2322   )
2323 {
2324   EFI_DEVICE_PATH_PROTOCOL  *Node;
2325   UINTN                     Index;
2326 
2327   Node = DevPath;
2328 
2329   for (Index = 0; mUefiDevicePathLibToTextTableGeneric[Index].Text != NULL; Index++) {
2330     if (DevicePathType (Node) == mUefiDevicePathLibToTextTableGeneric[Index].Type) {
2331       break;
2332     }
2333   }
2334 
2335   if (mUefiDevicePathLibToTextTableGeneric[Index].Text == NULL) {
2336     //
2337     // It's a node whose type cannot be recognized
2338     //
2339     UefiDevicePathLibCatPrint (Str, "Path(%d,%d", DevicePathType (Node), DevicePathSubType (Node));
2340   } else {
2341     //
2342     // It's a node whose type can be recognized
2343     //
2344     UefiDevicePathLibCatPrint (Str, "%s(%d", mUefiDevicePathLibToTextTableGeneric[Index].Text, DevicePathSubType (Node));
2345   }
2346 
2347   Index = sizeof (EFI_DEVICE_PATH_PROTOCOL);
2348   if (Index < DevicePathNodeLength (Node)) {
2349     UefiDevicePathLibCatPrint (Str, ",");
2350     for ( ; Index < DevicePathNodeLength (Node); Index++) {
2351       UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *)Node)[Index]);
2352     }
2353   }
2354 
2355   UefiDevicePathLibCatPrint (Str, ")");
2356 }
2357 
2358 static const DEVICE_PATH_TO_TEXT_TABLE  mUefiDevicePathLibToTextTable[] = {
2359   { HARDWARE_DEVICE_PATH,  HW_PCI_DP,                        DevPathToTextPci           },
2360   { HARDWARE_DEVICE_PATH,  HW_PCCARD_DP,                     DevPathToTextPccard        },
2361   { HARDWARE_DEVICE_PATH,  HW_MEMMAP_DP,                     DevPathToTextMemMap        },
2362   { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP,                     DevPathToTextVendor        },
2363   { HARDWARE_DEVICE_PATH,  HW_CONTROLLER_DP,                 DevPathToTextController    },
2364   { HARDWARE_DEVICE_PATH,  HW_BMC_DP,                        DevPathToTextBmc           },
2365   { ACPI_DEVICE_PATH,      ACPI_DP,                          DevPathToTextAcpi          },
2366   { ACPI_DEVICE_PATH,      ACPI_EXTENDED_DP,                 DevPathToTextAcpiEx        },
2367   { ACPI_DEVICE_PATH,      ACPI_ADR_DP,                      DevPathToTextAcpiAdr       },
2368   { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP,                     DevPathToTextAtapi         },
2369   { MESSAGING_DEVICE_PATH, MSG_SCSI_DP,                      DevPathToTextScsi          },
2370   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP,              DevPathToTextFibre         },
2371   { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP,            DevPathToTextFibreEx       },
2372   { MESSAGING_DEVICE_PATH, MSG_SASEX_DP,                     DevPathToTextSasEx         },
2373   { MESSAGING_DEVICE_PATH, MSG_NVME_NAMESPACE_DP,            DevPathToTextNVMe          },
2374   { MESSAGING_DEVICE_PATH, MSG_UFS_DP,                       DevPathToTextUfs           },
2375   { MESSAGING_DEVICE_PATH, MSG_SD_DP,                        DevPathToTextSd            },
2376   { MESSAGING_DEVICE_PATH, MSG_EMMC_DP,                      DevPathToTextEmmc          },
2377   { MESSAGING_DEVICE_PATH, MSG_1394_DP,                      DevPathToText1394          },
2378   { MESSAGING_DEVICE_PATH, MSG_USB_DP,                       DevPathToTextUsb           },
2379   { MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP,                  DevPathToTextUsbWWID       },
2380   { MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP,       DevPathToTextLogicalUnit   },
2381   { MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,                 DevPathToTextUsbClass      },
2382   { MESSAGING_DEVICE_PATH, MSG_SATA_DP,                      DevPathToTextSata          },
2383   { MESSAGING_DEVICE_PATH, MSG_I2O_DP,                       DevPathToTextI2O           },
2384   { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,                  DevPathToTextMacAddr       },
2385   { MESSAGING_DEVICE_PATH, MSG_IPv4_DP,                      DevPathToTextIPv4          },
2386   { MESSAGING_DEVICE_PATH, MSG_IPv6_DP,                      DevPathToTextIPv6          },
2387   { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP,                DevPathToTextInfiniBand    },
2388   { MESSAGING_DEVICE_PATH, MSG_UART_DP,                      DevPathToTextUart          },
2389   { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,                    DevPathToTextVendor        },
2390   { MESSAGING_DEVICE_PATH, MSG_ISCSI_DP,                     DevPathToTextiSCSI         },
2391   { MESSAGING_DEVICE_PATH, MSG_VLAN_DP,                      DevPathToTextVlan          },
2392   { MESSAGING_DEVICE_PATH, MSG_DNS_DP,                       DevPathToTextDns           },
2393   { MESSAGING_DEVICE_PATH, MSG_URI_DP,                       DevPathToTextUri           },
2394   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_DP,                 DevPathToTextBluetooth     },
2395   { MESSAGING_DEVICE_PATH, MSG_WIFI_DP,                      DevPathToTextWiFi          },
2396   { MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_LE_DP,              DevPathToTextBluetoothLE   },
2397   { MEDIA_DEVICE_PATH,     MEDIA_HARDDRIVE_DP,               DevPathToTextHardDrive     },
2398   { MEDIA_DEVICE_PATH,     MEDIA_CDROM_DP,                   DevPathToTextCDROM         },
2399   { MEDIA_DEVICE_PATH,     MEDIA_VENDOR_DP,                  DevPathToTextVendor        },
2400   { MEDIA_DEVICE_PATH,     MEDIA_PROTOCOL_DP,                DevPathToTextMediaProtocol },
2401   { MEDIA_DEVICE_PATH,     MEDIA_FILEPATH_DP,                DevPathToTextFilePath      },
2402   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_VOL_DP,             DevPathToTextFv            },
2403   { MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_FILE_DP,            DevPathToTextFvFile        },
2404   { MEDIA_DEVICE_PATH,     MEDIA_RELATIVE_OFFSET_RANGE_DP,   DevPathRelativeOffsetRange },
2405   { MEDIA_DEVICE_PATH,     MEDIA_RAM_DISK_DP,                DevPathToTextRamDisk       },
2406   { BBS_DEVICE_PATH,       BBS_BBS_DP,                       DevPathToTextBBS           },
2407   { END_DEVICE_PATH_TYPE,  END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance   },
2408   { 0,                     0,                                NULL                       }
2409 };
2410 
2411 /**
2412   Converts a device node to its string representation.
2413 
2414   @param DeviceNode        A Pointer to the device node to be converted.
2415   @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
2416                            of the display node is used, where applicable. If DisplayOnly
2417                            is FALSE, then the longer text representation of the display node
2418                            is used.
2419   @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
2420                            representation for a device node can be used, where applicable.
2421 
2422   @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
2423           is NULL or there was insufficient memory.
2424 
2425 **/
2426 static char *
2427 EFIAPI
2428 UefiDevicePathLibConvertDeviceNodeToText (
2429   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
2430   IN BOOLEAN                         DisplayOnly,
2431   IN BOOLEAN                         AllowShortcuts
2432   )
2433 {
2434   POOL_PRINT           Str;
2435   UINTN                Index;
2436   DEVICE_PATH_TO_TEXT  ToText;
2437   EFI_DEVICE_PATH_PROTOCOL  *Node;
2438 
2439   if (DeviceNode == NULL) {
2440     return NULL;
2441   }
2442 
2443   ZeroMem (&Str, sizeof (Str));
2444 
2445   //
2446   // Process the device path node
2447   // If not found, use a generic function
2448   //
2449   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DeviceNode);
2450   ToText = DevPathToTextNodeGeneric;
2451   for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index++) {
2452     if ((DevicePathType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].Type) &&
2453         (DevicePathSubType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].SubType)
2454         )
2455     {
2456       ToText = mUefiDevicePathLibToTextTable[Index].Function;
2457       break;
2458     }
2459   }
2460 
2461   //
2462   // Print this node
2463   //
2464   ToText (&Str, (VOID *)Node, DisplayOnly, AllowShortcuts);
2465 
2466   ASSERT (Str.Str != NULL);
2467   return Str.Str;
2468 }
2469 
2470 /**
2471   Converts a device path to its text representation.
2472 
2473   @param DevicePath      A Pointer to the device to be converted.
2474   @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
2475                          of the display node is used, where applicable. If DisplayOnly
2476                          is FALSE, then the longer text representation of the display node
2477                          is used.
2478   @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
2479                          representation for a device node can be used, where applicable.
2480 
2481   @return A pointer to the allocated text representation of the device path or
2482           NULL if DeviceNode is NULL or there was insufficient memory.
2483 
2484 **/
2485 static char *
2486 EFIAPI
2487 UefiDevicePathLibConvertDevicePathToText (
2488   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
2489   IN BOOLEAN                         DisplayOnly,
2490   IN BOOLEAN                         AllowShortcuts
2491   )
2492 {
2493   POOL_PRINT                Str;
2494   EFI_DEVICE_PATH_PROTOCOL  *Node;
2495   EFI_DEVICE_PATH_PROTOCOL  *AlignedNode;
2496   UINTN                     Index;
2497   DEVICE_PATH_TO_TEXT       ToText;
2498 
2499   if (DevicePath == NULL) {
2500     return NULL;
2501   }
2502 
2503   ZeroMem (&Str, sizeof (Str));
2504 
2505   //
2506   // Process each device path node
2507   //
2508   Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DevicePath);
2509   while (!IsDevicePathEnd (Node)) {
2510     //
2511     // Find the handler to dump this device path node
2512     // If not found, use a generic function
2513     //
2514     ToText = DevPathToTextNodeGeneric;
2515     for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index += 1) {
2516       if ((DevicePathType (Node) == mUefiDevicePathLibToTextTable[Index].Type) &&
2517           (DevicePathSubType (Node) == mUefiDevicePathLibToTextTable[Index].SubType)
2518           )
2519       {
2520         ToText = mUefiDevicePathLibToTextTable[Index].Function;
2521         break;
2522       }
2523     }
2524 
2525     //
2526     //  Put a path separator in if needed
2527     //
2528     if ((Str.Count != 0) && (ToText != DevPathToTextEndInstance)) {
2529       if (Str.Str[Str.Count] != ',') {
2530         UefiDevicePathLibCatPrint (&Str, "/");
2531       }
2532     }
2533 
2534     AlignedNode = AllocateCopyPool (DevicePathNodeLength (Node), Node);
2535     //
2536     // Print this node of the device path
2537     //
2538     ToText (&Str, AlignedNode, DisplayOnly, AllowShortcuts);
2539     FreePool (AlignedNode);
2540 
2541     //
2542     // Next device path node
2543     //
2544     Node = NextDevicePathNode (Node);
2545   }
2546 
2547   if (Str.Str == NULL) {
2548     return AllocateZeroPool (sizeof (CHAR16));
2549   } else {
2550     return Str.Str;
2551   }
2552 }
2553 
2554 ssize_t
2555 efidp_format_device_path(char *buf, size_t len, const_efidp dp, ssize_t max)
2556 {
2557 	char *str;
2558 	ssize_t retval;
2559 
2560 	/*
2561 	 * Basic sanity check on the device path.
2562 	 */
2563 	if (!IsDevicePathValid((CONST EFI_DEVICE_PATH_PROTOCOL *) dp, max)) {
2564 		*buf = '\0';
2565 		return 0;
2566 	}
2567 
2568 	str = UefiDevicePathLibConvertDevicePathToText (
2569 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2570 	if (str == NULL)
2571 		return -1;
2572 	strlcpy(buf, str, len);
2573 	retval = strlen(str);
2574 	free(str);
2575 
2576 	return retval;
2577 }
2578 
2579 ssize_t
2580 efidp_format_device_path_node(char *buf, size_t len, const_efidp dp)
2581 {
2582 	char *str;
2583 	ssize_t retval;
2584 
2585 	str = UefiDevicePathLibConvertDeviceNodeToText (
2586 		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
2587 	if (str == NULL)
2588 		return -1;
2589 	strlcpy(buf, str, len);
2590 	retval = strlen(str);
2591 	free(str);
2592 
2593 	return retval;
2594 }
2595 
2596 size_t
2597 efidp_size(const_efidp dp)
2598 {
2599 
2600 	return GetDevicePathSize(__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp));
2601 }
2602 
2603 char *
2604 efidp_extract_file_path(const_efidp dp)
2605 {
2606 	const FILEPATH_DEVICE_PATH  *fp;
2607 	char *name = NULL;
2608 
2609 	fp = (const void *)dp;
2610 	ucs2_to_utf8(fp->PathName, &name);
2611 	return name;
2612 }
2613