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