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