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