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