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