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