From 9039c7357001469aebd0b4af881edb50ac2add29 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Tue, 21 Mar 2017 19:54:45 +0100
Subject: [PATCH 2/5] WIP update libefivar

---
 lib/libefivar/FreeBSD-update                 |   40 +
 lib/libefivar/Makefile                       |   16 +-
 lib/libefivar/ProcessorBind.h                |    4 +
 lib/libefivar/efi-osdep.h                    |  111 +
 lib/libefivar/{libefivar.c => efichar.c}     |   10 +-
 lib/libefivar/{libefivar_int.h => efichar.h} |   12 +-
 lib/libefivar/efivar-dp-format.c             | 2427 +++++++++++++++++
 lib/libefivar/efivar-dp-parse.c              | 3703 ++++++++++++++++++++++++++
 lib/libefivar/efivar-dp.h                    |   65 +
 lib/libefivar/efivar.3                       |    3 +-
 lib/libefivar/efivar.c                       |   44 +-
 lib/libefivar/efivar.h                       |   16 +-
 lib/libefivar/uefi-dplib.h                   |  626 +++++
 lib/libefivar/uefi-dputil.c                  |  636 +++++
 lib/libefivar/uefi-guid.c                    |   36 +
 lib/libefivar/uefi-guid.dat                  |   11 +
 16 files changed, 7726 insertions(+), 34 deletions(-)
 create mode 100644 lib/libefivar/FreeBSD-update
 create mode 100644 lib/libefivar/ProcessorBind.h
 create mode 100644 lib/libefivar/efi-osdep.h
 rename lib/libefivar/{libefivar.c => efichar.c} (93%)
 rename lib/libefivar/{libefivar_int.h => efichar.h} (83%)
 create mode 100644 lib/libefivar/efivar-dp-format.c
 create mode 100644 lib/libefivar/efivar-dp-parse.c
 create mode 100644 lib/libefivar/efivar-dp.h
 create mode 100644 lib/libefivar/uefi-dplib.h
 create mode 100644 lib/libefivar/uefi-dputil.c
 create mode 100644 lib/libefivar/uefi-guid.c
 create mode 100644 lib/libefivar/uefi-guid.dat

diff --git a/lib/libefivar/FreeBSD-update b/lib/libefivar/FreeBSD-update
new file mode 100644
index 0000000000..113a6fc393
--- /dev/null
+++ b/lib/libefivar/FreeBSD-update
@@ -0,0 +1,40 @@
+$FreeBSD: head/lib/libefivar/FreeBSD-update 314926 2017-03-09 00:31:31Z imp $
+
+For the printing and parsing functionality, we use the Tianocore routines
+directly.
+
+efivar-dp-format.c is a copy of MdePkg/Library/UefiDevicePathLib/DevicePathToText.c
+efivar-dp-parse.c is a copy of MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c
+
+These files are first mechnaically processed with
+
+sed -e "s/L'/'/;"'s/L"/"/g;s/%g/%36s/g;s/%a/%s/g;s/^VOID/static VOID/g;s/ *$//g'
+
+for several reasons. We're moving from wide routines to narrow
+routines. The UTC-2 this code is written for is a bad match for
+wchar_t which is an int. It's a much better match for plain narrow
+characters on FreeBSD. So we pretend that CHAR16 for these files is
+really char * (ASCII).
+
+Next, we have have to convert the Unicode printf that this code
+expects to FreeBSD's printf. %g means "Print the GUID" and %a means
+"print the ASCII string." so we mechanically convert them. Once we've
+done that we can compare efivar-dp-*.c to its source to see what's
+changed. Because we go through this indirection, I've done that
+outside of svn. To upgrade you have to do these files by hand. You
+have to go through and make routines static.
+
+uefi-*.[ch] are internal routines to support this. They've been copied
+from EDK2 as well, but in a more haphazard manner. This was a trade
+off between ease of implementation / upgrade vs pulling in too much
+since less than half of any file was needed.
+
+efi-osdep.h shims the EDK2 types to FreeBSD's types. It's included by
+ProcessorBind.h which EDK2 uses to define the CPU. We keep it separate
+from uefi-dplib.h to allow better sharing.
+
+uefi-dplib.h shims the EDK2 routines that are needed to FreeBSD's
+routines. This is relatively easy since we map all the UCS-2 routines
+to simple char * routines.
+
+RESIST THE URGE TO CLEAN UP THESE FILES.
diff --git a/lib/libefivar/Makefile b/lib/libefivar/Makefile
index d4df2e5ba2..77d4184f35 100644
--- a/lib/libefivar/Makefile
+++ b/lib/libefivar/Makefile
@@ -22,15 +22,23 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/lib/libefivar/Makefile 307071 2016-10-11 22:30:41Z imp $
+# $FreeBSD: head/lib/libefivar/Makefile 314926 2017-03-09 00:31:31Z imp $
+
+EDK2INC=${.CURDIR}/../../sys/contrib/edk2/Include
+
+.PATH:	${EFIBOOT}/libefi
 
 PACKAGE=lib${LIB}
 LIB=		efivar
-SRCS=		efivar.c libefivar.c
-INCS=		efivar.h
+SRCS=		efivar.c efichar.c efivar-dp-format.c \
+		efivar-dp-parse.c \
+		uefi-guid.c uefi-dputil.c
+INCS=		efivar.h efivar-dp.h
 SHLIB_MAJOR=	1
 MAN=		efivar.3
 
+CFLAGS+=	-I${.CURDIR} -I${EDK2INC}
+
 MLINKS+=efivar.3 efi_variables_supported.3 \
 	efivar.3 efi_del_variable.3 \
 	efivar.3 efi_get_variable.3 \
@@ -46,4 +54,6 @@ MLINKS+=efivar.3 efi_variables_supported.3 \
 	efivar.3 efi_guid_to_symbol.3 \
 	efivar.3 libefivar.3
 
+WARNS?=		3
+
 .include <bsd.lib.mk>
diff --git a/lib/libefivar/ProcessorBind.h b/lib/libefivar/ProcessorBind.h
new file mode 100644
index 0000000000..9576ae2cf1
--- /dev/null
+++ b/lib/libefivar/ProcessorBind.h
@@ -0,0 +1,4 @@
+/* File in public domain */
+/* Brings in the glue for UEFI/EDK2 Tianocore code to run on this OS */
+/* $FreeBSD: head/lib/libefivar/ProcessorBind.h 314926 2017-03-09 00:31:31Z imp $ */
+#include "efi-osdep.h"
diff --git a/lib/libefivar/efi-osdep.h b/lib/libefivar/efi-osdep.h
new file mode 100644
index 0000000000..8f8d807d59
--- /dev/null
+++ b/lib/libefivar/efi-osdep.h
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: head/lib/libefivar/efi-osdep.h 314926 2017-03-09 00:31:31Z imp $
+ */
+
+#ifndef	_EFI_OSDEP_H_
+#define	_EFI_OSDEP_H_
+
+/*
+ * Defines to adjust the types that EDK2 uses for FreeBSD so we can
+ * use the code and headers mostly unchanged. The headers are imported
+ * all into one directory to avoid case issues with filenames and
+ * included. The actual code is heavily modified since it has too many
+ * annoying dependencies that are difficult to satisfy.
+ */
+
+#include <sys/cdefs.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <uuid.h>
+
+typedef int8_t INT8;
+typedef int16_t INT16;
+typedef int32_t INT32;
+typedef int64_t INT64;
+typedef intptr_t INTN;
+typedef uint8_t UINT8;
+typedef uint16_t UINT16;
+typedef uint32_t UINT32;
+typedef uint64_t UINT64;
+typedef uintptr_t UINTN;
+//typedef uintptr_t EFI_PHYSICAL_ADDRESS;
+//typedef uint32_t EFI_IPv4_ADDRESS;
+//typedef uint8_t EFI_MAC_ADDRESS[6];
+//typedef uint8_t EFI_IPv6_ADDRESS[16];
+typedef uint8_t CHAR8;
+typedef uint16_t CHAR16;
+typedef UINT8 BOOLEAN;
+typedef void VOID;
+//typedef uuid_t GUID;
+//typedef uuid_t EFI_GUID;
+
+/* We can't actually call this stuff, so snip out API syntactic sugar */
+#define INTERFACE_DECL(x)
+#define EFIAPI
+#define IN
+#define OUT
+#define CONST const
+#define OPTIONAL
+//#define TRUE 1
+//#define FALSE 0
+
+/*
+ * EDK2 has fine definitions for these, so let it define them.
+ */
+#undef NULL
+#undef EFI_PAGE_SIZE
+#undef EFI_PAGE_MASK
+
+/*
+ * Note: the EDK2 code assumed #pragma packed works and PACKED is a
+ * workaround for some old toolchain issues for EDK2 that aren't
+ * relevent to FreeBSD.
+ */
+#define PACKED
+
+/*
+ * Since we're not compiling for the UEFI boot time (which use ms abi
+ * conventions), tell EDK2 to define VA_START correctly. For the boot
+ * loader, this likely needs to be different.
+ */
+#define NO_MSABI_VA_FUNCS 1
+
+/*
+ * Finally, we need to define the processor we are in EDK2 terms.
+ */
+#if defined(__i386__)
+#define MDE_CPU_IA32
+#elif defined(__amd64__)
+#define MDE_CPU_X64
+#elif defined(__arm__)
+#define MDE_CPU_ARM
+#elif defined(__aarch64__)
+#define MDE_CPU_AARCH64
+#endif
+/* FreeBSD doesn't have/use MDE_CPU_EBC or MDE_CPU_IPF (ia64) */
+
+#endif /* _EFI_OSDEP_H_ */
diff --git a/lib/libefivar/libefivar.c b/lib/libefivar/efichar.c
similarity index 93%
rename from lib/libefivar/libefivar.c
rename to lib/libefivar/efichar.c
index e8d167b5f7..79b9e0508e 100644
--- a/lib/libefivar/libefivar.c
+++ b/lib/libefivar/efichar.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/libefivar/libefivar.c 307071 2016-10-11 22:30:41Z imp $");
+__FBSDID("$FreeBSD: head/sys/boot/efi/libefi/efichar.c 314925 2017-03-09 00:24:01Z imp $");
 
 #include <sys/types.h>
 #include <errno.h>
@@ -36,9 +36,7 @@ __FBSDID("$FreeBSD: head/lib/libefivar/libefivar.c 307071 2016-10-11 22:30:41Z i
 #include <sys/efi.h>
 #include <machine/efi.h>
 
-#include "libefivar_int.h"
-
-#include <stdio.h>
+#include "efichar.h"
 
 /*
  * If nm were converted to utf8, what what would strlen
@@ -65,7 +63,7 @@ utf8_len_of_ucs2(const efi_char *nm)
 }
 
 int
-libefi_ucs2_to_utf8(const efi_char *nm, char **name)
+ucs2_to_utf8(const efi_char *nm, char **name)
 {
 	size_t len, sz;
 	efi_char c;
@@ -113,7 +111,7 @@ libefi_ucs2_to_utf8(const efi_char *nm, char **name)
 }
 
 int
-libefi_utf8_to_ucs2(const char *name, efi_char **nmp, size_t *len)
+utf8_to_ucs2(const char *name, efi_char **nmp, size_t *len)
 {
 	efi_char *nm;
 	size_t sz;
diff --git a/lib/libefivar/libefivar_int.h b/lib/libefivar/efichar.h
similarity index 83%
rename from lib/libefivar/libefivar_int.h
rename to lib/libefivar/efichar.h
index 2bebd41841..35393e0aef 100644
--- a/lib/libefivar/libefivar_int.h
+++ b/lib/libefivar/efichar.h
@@ -23,13 +23,13 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/libefivar/libefivar_int.h 307071 2016-10-11 22:30:41Z imp $
+ * $FreeBSD: head/sys/boot/efi/include/efichar.h 314925 2017-03-09 00:24:01Z imp $
  */
 
-#ifndef _LIBEFI_INT_H_
-#define	_LIBEFI_INT_H_
+#ifndef _BOOT_EFI_EFICHAR_H_
+#define	_BOOT_EFI_EFICHAR_H_
 
-int libefi_ucs2_to_utf8(const efi_char *, char **);
-int libefi_utf8_to_ucs2(const char *, efi_char **, size_t *);
+int ucs2_to_utf8(const efi_char *, char **);
+int utf8_to_ucs2(const char *, efi_char **, size_t *);
 
-#endif /* _LIBEFI_INT_H_ */
+#endif /* _BOOT_EFI_EFICHAR_H_ */
diff --git a/lib/libefivar/efivar-dp-format.c b/lib/libefivar/efivar-dp-format.c
new file mode 100644
index 0000000000..32e406564f
--- /dev/null
+++ b/lib/libefivar/efivar-dp-format.c
@@ -0,0 +1,2427 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Routines to format EFI_DEVICE_PATHs from the UEFI standard. Much of
+ * this file is taken from EDK2 and rototilled.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libefivar/efivar-dp-format.c 314926 2017-03-09 00:31:31Z imp $");
+
+#include <efivar.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "efi-osdep.h"
+#include "efivar-dp.h"
+
+#include "uefi-dplib.h"
+
+/*
+ * This is a lie, but since we have converted everything
+ * from wide to narrow, it's the right lie now.
+ */
+#define UnicodeSPrint snprintf
+
+/*
+ * Taken from MdePkg/Library/UefiDevicePathLib/DevicePathToText.c
+ * hash a11928f3310518ab1c6fd34e8d0fdbb72de9602c 2017-Mar-01
+ * heavily modified:
+ *	wide strings converted to narrow
+ *	Low level printing code redone for narrow strings
+ *	Routines made static
+ *	%s -> %S in spots (where it is still UCS-2)
+ *	%a (ascii) -> %s
+ *	%g -> %36s hack to print guid (see above for caveat)
+ *	some tidying up of const and deconsting. It's evil, but const
+ *	  poisoning the whole file was too much.
+ */
+
+/** @file
+  DevicePathToText protocol as defined in the UEFI 2.0 specification.
+
+  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+// #include "UefiDevicePathLib.h"
+
+/**
+  Concatenates a formatted unicode string to allocated pool. The caller must
+  free the resulting buffer.
+
+  @param Str             Tracks the allocated pool, size in use, and
+                         amount of pool allocated.
+  @param Fmt             The format string
+  @param ...             Variable arguments based on the format string.
+
+  @return Allocated buffer with the formatted string printed in it.
+          The caller must free the allocated buffer. The buffer
+          allocation is not packed.
+
+**/
+static char *
+EFIAPI
+UefiDevicePathLibCatPrint (
+  IN OUT POOL_PRINT   *Str,
+  IN const char       *Fmt,
+  ...
+  )
+{
+  UINTN   Count;
+  VA_LIST Args;
+
+  VA_START (Args, Fmt);
+  Count = vsnprintf(NULL, 0, Fmt, Args);
+  VA_END(Args);
+
+  if ((Str->Count + (Count + 1)) > Str->Capacity) {
+    Str->Capacity = (Str->Count + (Count + 1) * 2);
+    Str->Str = reallocf(Str->Str, Str->Capacity);
+    ASSERT (Str->Str != NULL);
+  }
+  VA_START (Args, Fmt);
+  vsnprintf(Str->Str + Str->Count, Str->Capacity - Str->Count, Fmt, Args);
+  Str->Count += Count;
+
+  VA_END (Args);
+  return Str->Str;
+}
+
+/**
+  Converts a PCI device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextPci (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  PCI_DEVICE_PATH *Pci;
+
+  Pci = DevPath;
+  UefiDevicePathLibCatPrint (Str, "Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
+}
+
+/**
+  Converts a PC Card device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextPccard (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  PCCARD_DEVICE_PATH  *Pccard;
+
+  Pccard = DevPath;
+  UefiDevicePathLibCatPrint (Str, "PcCard(0x%x)", Pccard->FunctionNumber);
+}
+
+/**
+  Converts a Memory Map device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextMemMap (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  MEMMAP_DEVICE_PATH  *MemMap;
+
+  MemMap = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "MemoryMapped(0x%x,0x%lx,0x%lx)",
+    MemMap->MemoryType,
+    MemMap->StartingAddress,
+    MemMap->EndingAddress
+    );
+}
+
+/**
+  Converts a Vendor device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextVendor (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  VENDOR_DEVICE_PATH  *Vendor;
+  const char          *Type;
+  UINTN               Index;
+  UINTN               DataLength;
+  UINT32              FlowControlMap;
+  UINT16              Info;
+
+  Vendor = (VENDOR_DEVICE_PATH *) DevPath;
+  switch (DevicePathType (&Vendor->Header)) {
+  case HARDWARE_DEVICE_PATH:
+    Type = "Hw";
+    break;
+
+  case MESSAGING_DEVICE_PATH:
+    Type = "Msg";
+    if (AllowShortcuts) {
+      if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
+        UefiDevicePathLibCatPrint (Str, "VenPcAnsi()");
+        return ;
+      } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
+        UefiDevicePathLibCatPrint (Str, "VenVt100()");
+        return ;
+      } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
+        UefiDevicePathLibCatPrint (Str, "VenVt100Plus()");
+        return ;
+      } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
+        UefiDevicePathLibCatPrint (Str, "VenUft8()");
+        return ;
+      } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid)) {
+        FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
+        switch (FlowControlMap & 0x00000003) {
+        case 0:
+          UefiDevicePathLibCatPrint (Str, "UartFlowCtrl(%s)", "None");
+          break;
+
+        case 1:
+          UefiDevicePathLibCatPrint (Str, "UartFlowCtrl(%s)", "Hardware");
+          break;
+
+        case 2:
+          UefiDevicePathLibCatPrint (Str, "UartFlowCtrl(%s)", "XonXoff");
+          break;
+
+        default:
+          break;
+        }
+
+        return ;
+      } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {
+        UefiDevicePathLibCatPrint (
+          Str,
+          "SAS(0x%lx,0x%lx,0x%x,",
+          ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
+          ((SAS_DEVICE_PATH *) Vendor)->Lun,
+          ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
+          );
+        Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
+        if (((Info & 0x0f) == 0) && ((Info & BIT7) == 0)) {
+          UefiDevicePathLibCatPrint (Str, "NoTopology,0,0,0,");
+        } else if (((Info & 0x0f) <= 2) && ((Info & BIT7) == 0)) {
+          UefiDevicePathLibCatPrint (
+            Str,
+            "%s,%s,%s,",
+            ((Info & BIT4) != 0) ? "SATA" : "SAS",
+            ((Info & BIT5) != 0) ? "External" : "Internal",
+            ((Info & BIT6) != 0) ? "Expanded" : "Direct"
+            );
+          if ((Info & 0x0f) == 1) {
+            UefiDevicePathLibCatPrint (Str, "0,");
+          } else {
+            //
+            // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
+            //
+            UefiDevicePathLibCatPrint (Str, "0x%x,", ((Info >> 8) & 0xff) + 1);
+          }
+        } else {
+          UefiDevicePathLibCatPrint (Str, "0x%x,0,0,0,", Info);
+        }
+
+        UefiDevicePathLibCatPrint (Str, "0x%x)", ((SAS_DEVICE_PATH *) Vendor)->Reserved);
+        return ;
+      } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
+        UefiDevicePathLibCatPrint (Str, "DebugPort()");
+        return ;
+      }
+    }
+    break;
+
+  case MEDIA_DEVICE_PATH:
+    Type = "Media";
+    break;
+
+  default:
+    Type = "?";
+    break;
+  }
+
+  DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
+  UefiDevicePathLibCatPrint (Str, "Ven%s(%36s", Type, G(&Vendor->Guid));
+  if (DataLength != 0) {
+    UefiDevicePathLibCatPrint (Str, ",");
+    for (Index = 0; Index < DataLength; Index++) {
+      UefiDevicePathLibCatPrint (Str, "%02x", ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
+    }
+  }
+
+  UefiDevicePathLibCatPrint (Str, ")");
+}
+
+/**
+  Converts a Controller device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextController (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  CONTROLLER_DEVICE_PATH  *Controller;
+
+  Controller = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "Ctrl(0x%x)",
+    Controller->ControllerNumber
+    );
+}
+
+/**
+  Converts a BMC device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextBmc (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  BMC_DEVICE_PATH    *Bmc;
+
+  Bmc = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "BMC(0x%x,0x%lx)",
+    Bmc->InterfaceType,
+    ReadUnaligned64 ((&Bmc->BaseAddress))
+    );
+}
+
+/**
+  Converts a ACPI device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextAcpi (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  ACPI_HID_DEVICE_PATH  *Acpi;
+
+  Acpi = DevPath;
+  if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+    switch (EISA_ID_TO_NUM (Acpi->HID)) {
+    case 0x0a03:
+      UefiDevicePathLibCatPrint (Str, "PciRoot(0x%x)", Acpi->UID);
+      break;
+
+    case 0x0a08:
+      UefiDevicePathLibCatPrint (Str, "PcieRoot(0x%x)", Acpi->UID);
+      break;
+
+    case 0x0604:
+      UefiDevicePathLibCatPrint (Str, "Floppy(0x%x)", Acpi->UID);
+      break;
+
+    case 0x0301:
+      UefiDevicePathLibCatPrint (Str, "Keyboard(0x%x)", Acpi->UID);
+      break;
+
+    case 0x0501:
+      UefiDevicePathLibCatPrint (Str, "Serial(0x%x)", Acpi->UID);
+      break;
+
+    case 0x0401:
+      UefiDevicePathLibCatPrint (Str, "ParallelPort(0x%x)", Acpi->UID);
+      break;
+
+    default:
+      UefiDevicePathLibCatPrint (Str, "Acpi(PNP%04x,0x%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
+      break;
+    }
+  } else {
+    UefiDevicePathLibCatPrint (Str, "Acpi(0x%08x,0x%x)", Acpi->HID, Acpi->UID);
+  }
+}
+
+/**
+  Converts a ACPI extended HID device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextAcpiEx (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  ACPI_EXTENDED_HID_DEVICE_PATH  *AcpiEx;
+  CHAR8                          *HIDStr;
+  CHAR8                          *UIDStr;
+  CHAR8                          *CIDStr;
+  char                           HIDText[11];
+  char                           CIDText[11];
+
+  AcpiEx = DevPath;
+  HIDStr = (CHAR8 *) (((UINT8 *) AcpiEx) + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
+  UIDStr = HIDStr + AsciiStrLen (HIDStr) + 1;
+  CIDStr = UIDStr + AsciiStrLen (UIDStr) + 1;
+
+  //
+  // Converts EISA identification to string.
+  //
+  UnicodeSPrint (
+    HIDText,
+    sizeof (HIDText),
+    "%c%c%c%04X",
+    ((AcpiEx->HID >> 10) & 0x1f) + 'A' - 1,
+    ((AcpiEx->HID >>  5) & 0x1f) + 'A' - 1,
+    ((AcpiEx->HID >>  0) & 0x1f) + 'A' - 1,
+    (AcpiEx->HID >> 16) & 0xFFFF
+    );
+  UnicodeSPrint (
+    CIDText,
+    sizeof (CIDText),
+    "%c%c%c%04X",
+    ((AcpiEx->CID >> 10) & 0x1f) + 'A' - 1,
+    ((AcpiEx->CID >>  5) & 0x1f) + 'A' - 1,
+    ((AcpiEx->CID >>  0) & 0x1f) + 'A' - 1,
+    (AcpiEx->CID >> 16) & 0xFFFF
+    );
+
+  if ((*HIDStr == '\0') && (*CIDStr == '\0') && (AcpiEx->UID == 0)) {
+    //
+    // use AcpiExp()
+    //
+    UefiDevicePathLibCatPrint (
+      Str,
+      "AcpiExp(%s,%s,%s)",
+      HIDText,
+      CIDText,
+      UIDStr
+      );
+  } else {
+    if (AllowShortcuts) {
+      //
+      // display only
+      //
+      if (AcpiEx->HID == 0) {
+        UefiDevicePathLibCatPrint (Str, "AcpiEx(%s,", HIDStr);
+      } else {
+        UefiDevicePathLibCatPrint (Str, "AcpiEx(%s,", HIDText);
+      }
+
+      if (AcpiEx->UID == 0) {
+        UefiDevicePathLibCatPrint (Str, "%s,", UIDStr);
+      } else {
+        UefiDevicePathLibCatPrint (Str, "0x%x,", AcpiEx->UID);
+      }
+
+      if (AcpiEx->CID == 0) {
+        UefiDevicePathLibCatPrint (Str, "%s)", CIDStr);
+      } else {
+        UefiDevicePathLibCatPrint (Str, "%s)", CIDText);
+      }
+    } else {
+      UefiDevicePathLibCatPrint (
+        Str,
+        "AcpiEx(%s,%s,0x%x,%s,%s,%s)",
+        HIDText,
+        CIDText,
+        AcpiEx->UID,
+        HIDStr,
+        CIDStr,
+        UIDStr
+        );
+    }
+  }
+}
+
+/**
+  Converts a ACPI address device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextAcpiAdr (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  ACPI_ADR_DEVICE_PATH    *AcpiAdr;
+  UINT32                  *Addr;
+  UINT16                  Index;
+  UINT16                  Length;
+  UINT16                  AdditionalAdrCount;
+
+  AcpiAdr            = DevPath;
+  Length             = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);
+  AdditionalAdrCount = (UINT16) ((Length - 8) / 4);
+
+  UefiDevicePathLibCatPrint (Str, "AcpiAdr(0x%x", AcpiAdr->ADR);
+  Addr = &AcpiAdr->ADR + 1;
+  for (Index = 0; Index < AdditionalAdrCount; Index++) {
+    UefiDevicePathLibCatPrint (Str, ",0x%x", Addr[Index]);
+  }
+  UefiDevicePathLibCatPrint (Str, ")");
+}
+
+/**
+  Converts a ATAPI device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextAtapi (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  ATAPI_DEVICE_PATH *Atapi;
+
+  Atapi = DevPath;
+
+  if (DisplayOnly) {
+    UefiDevicePathLibCatPrint (Str, "Ata(0x%x)", Atapi->Lun);
+  } else {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "Ata(%s,%s,0x%x)",
+      (Atapi->PrimarySecondary == 1) ? "Secondary" : "Primary",
+      (Atapi->SlaveMaster == 1) ? "Slave" : "Master",
+      Atapi->Lun
+      );
+  }
+}
+
+/**
+  Converts a SCSI device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextScsi (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  SCSI_DEVICE_PATH  *Scsi;
+
+  Scsi = DevPath;
+  UefiDevicePathLibCatPrint (Str, "Scsi(0x%x,0x%x)", Scsi->Pun, Scsi->Lun);
+}
+
+/**
+  Converts a Fibre device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextFibre (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  FIBRECHANNEL_DEVICE_PATH  *Fibre;
+
+  Fibre = DevPath;
+  UefiDevicePathLibCatPrint (Str, "Fibre(0x%lx,0x%lx)", Fibre->WWN, Fibre->Lun);
+}
+
+/**
+  Converts a FibreEx device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextFibreEx (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  FIBRECHANNELEX_DEVICE_PATH  *FibreEx;
+  UINTN                       Index;
+
+  FibreEx = DevPath;
+  UefiDevicePathLibCatPrint (Str, "FibreEx(0x");
+  for (Index = 0; Index < sizeof (FibreEx->WWN) / sizeof (FibreEx->WWN[0]); Index++) {
+    UefiDevicePathLibCatPrint (Str, "%02x", FibreEx->WWN[Index]);
+  }
+  UefiDevicePathLibCatPrint (Str, ",0x");
+  for (Index = 0; Index < sizeof (FibreEx->Lun) / sizeof (FibreEx->Lun[0]); Index++) {
+    UefiDevicePathLibCatPrint (Str, "%02x", FibreEx->Lun[Index]);
+  }
+  UefiDevicePathLibCatPrint (Str, ")");
+}
+
+/**
+  Converts a Sas Ex device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextSasEx (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  SASEX_DEVICE_PATH  *SasEx;
+  UINTN              Index;
+
+  SasEx = DevPath;
+  UefiDevicePathLibCatPrint (Str, "SasEx(0x");
+
+  for (Index = 0; Index < sizeof (SasEx->SasAddress) / sizeof (SasEx->SasAddress[0]); Index++) {
+    UefiDevicePathLibCatPrint (Str, "%02x", SasEx->SasAddress[Index]);
+  }
+  UefiDevicePathLibCatPrint (Str, ",0x");
+  for (Index = 0; Index < sizeof (SasEx->Lun) / sizeof (SasEx->Lun[0]); Index++) {
+    UefiDevicePathLibCatPrint (Str, "%02x", SasEx->Lun[Index]);
+  }
+  UefiDevicePathLibCatPrint (Str, ",0x%x,", SasEx->RelativeTargetPort);
+
+  if (((SasEx->DeviceTopology & 0x0f) == 0) && ((SasEx->DeviceTopology & BIT7) == 0)) {
+    UefiDevicePathLibCatPrint (Str, "NoTopology,0,0,0");
+  } else if (((SasEx->DeviceTopology & 0x0f) <= 2) && ((SasEx->DeviceTopology & BIT7) == 0)) {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "%s,%s,%s,",
+      ((SasEx->DeviceTopology & BIT4) != 0) ? "SATA" : "SAS",
+      ((SasEx->DeviceTopology & BIT5) != 0) ? "External" : "Internal",
+      ((SasEx->DeviceTopology & BIT6) != 0) ? "Expanded" : "Direct"
+      );
+    if ((SasEx->DeviceTopology & 0x0f) == 1) {
+      UefiDevicePathLibCatPrint (Str, "0");
+    } else {
+      //
+      // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
+      //
+      UefiDevicePathLibCatPrint (Str, "0x%x", ((SasEx->DeviceTopology >> 8) & 0xff) + 1);
+    }
+  } else {
+    UefiDevicePathLibCatPrint (Str, "0x%x,0,0,0", SasEx->DeviceTopology);
+  }
+
+  UefiDevicePathLibCatPrint (Str, ")");
+  return ;
+
+}
+
+/**
+  Converts a NVM Express Namespace device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextNVMe (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  NVME_NAMESPACE_DEVICE_PATH *Nvme;
+  UINT8                      *Uuid;
+
+  Nvme = DevPath;
+  Uuid = (UINT8 *) &Nvme->NamespaceUuid;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "NVMe(0x%x,%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)",
+    Nvme->NamespaceId,
+    Uuid[7], Uuid[6], Uuid[5], Uuid[4],
+    Uuid[3], Uuid[2], Uuid[1], Uuid[0]
+    );
+}
+
+/**
+  Converts a UFS device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextUfs (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  UFS_DEVICE_PATH  *Ufs;
+
+  Ufs = DevPath;
+  UefiDevicePathLibCatPrint (Str, "UFS(0x%x,0x%x)", Ufs->Pun, Ufs->Lun);
+}
+
+/**
+  Converts a SD (Secure Digital) device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextSd (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  SD_DEVICE_PATH             *Sd;
+
+  Sd = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "SD(0x%x)",
+    Sd->SlotNumber
+    );
+}
+
+/**
+  Converts a EMMC (Embedded MMC) device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextEmmc (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  EMMC_DEVICE_PATH             *Emmc;
+
+  Emmc = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "eMMC(0x%x)",
+    Emmc->SlotNumber
+    );
+}
+
+/**
+  Converts a 1394 device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToText1394 (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  F1394_DEVICE_PATH *F1394DevPath;
+
+  F1394DevPath = DevPath;
+  //
+  // Guid has format of IEEE-EUI64
+  //
+  UefiDevicePathLibCatPrint (Str, "I1394(%016lx)", F1394DevPath->Guid);
+}
+
+/**
+  Converts a USB device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextUsb (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  USB_DEVICE_PATH *Usb;
+
+  Usb = DevPath;
+  UefiDevicePathLibCatPrint (Str, "USB(0x%x,0x%x)", Usb->ParentPortNumber, Usb->InterfaceNumber);
+}
+
+/**
+  Converts a USB WWID device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextUsbWWID (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  USB_WWID_DEVICE_PATH  *UsbWWId;
+  CHAR16                *SerialNumberStr;
+  CHAR16                *NewStr;
+  UINT16                Length;
+
+  UsbWWId = DevPath;
+
+  SerialNumberStr = (CHAR16 *) (&UsbWWId + 1);
+  Length = (UINT16) ((DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UsbWWId) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16));
+  if (SerialNumberStr [Length - 1] != 0) {
+    //
+    // In case no NULL terminator in SerialNumber, create a new one with NULL terminator
+    //
+    NewStr = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), SerialNumberStr);
+    ASSERT (NewStr != NULL);
+    NewStr [Length] = 0;
+    SerialNumberStr = NewStr;
+  }
+
+  UefiDevicePathLibCatPrint (
+    Str,
+    "UsbWwid(0x%x,0x%x,0x%x,\"%S\")",
+    UsbWWId->VendorId,
+    UsbWWId->ProductId,
+    UsbWWId->InterfaceNumber,
+    SerialNumberStr
+    );
+}
+
+/**
+  Converts a Logic Unit device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextLogicalUnit (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
+
+  LogicalUnit = DevPath;
+  UefiDevicePathLibCatPrint (Str, "Unit(0x%x)", LogicalUnit->Lun);
+}
+
+/**
+  Converts a USB class device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextUsbClass (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  USB_CLASS_DEVICE_PATH *UsbClass;
+  BOOLEAN               IsKnownSubClass;
+
+
+  UsbClass = DevPath;
+
+  IsKnownSubClass = TRUE;
+  switch (UsbClass->DeviceClass) {
+  case USB_CLASS_AUDIO:
+    UefiDevicePathLibCatPrint (Str, "UsbAudio");
+    break;
+
+  case USB_CLASS_CDCCONTROL:
+    UefiDevicePathLibCatPrint (Str, "UsbCDCControl");
+    break;
+
+  case USB_CLASS_HID:
+    UefiDevicePathLibCatPrint (Str, "UsbHID");
+    break;
+
+  case USB_CLASS_IMAGE:
+    UefiDevicePathLibCatPrint (Str, "UsbImage");
+    break;
+
+  case USB_CLASS_PRINTER:
+    UefiDevicePathLibCatPrint (Str, "UsbPrinter");
+    break;
+
+  case USB_CLASS_MASS_STORAGE:
+    UefiDevicePathLibCatPrint (Str, "UsbMassStorage");
+    break;
+
+  case USB_CLASS_HUB:
+    UefiDevicePathLibCatPrint (Str, "UsbHub");
+    break;
+
+  case USB_CLASS_CDCDATA:
+    UefiDevicePathLibCatPrint (Str, "UsbCDCData");
+    break;
+
+  case USB_CLASS_SMART_CARD:
+    UefiDevicePathLibCatPrint (Str, "UsbSmartCard");
+    break;
+
+  case USB_CLASS_VIDEO:
+    UefiDevicePathLibCatPrint (Str, "UsbVideo");
+    break;
+
+  case USB_CLASS_DIAGNOSTIC:
+    UefiDevicePathLibCatPrint (Str, "UsbDiagnostic");
+    break;
+
+  case USB_CLASS_WIRELESS:
+    UefiDevicePathLibCatPrint (Str, "UsbWireless");
+    break;
+
+  default:
+    IsKnownSubClass = FALSE;
+    break;
+  }
+
+  if (IsKnownSubClass) {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "(0x%x,0x%x,0x%x,0x%x)",
+      UsbClass->VendorId,
+      UsbClass->ProductId,
+      UsbClass->DeviceSubClass,
+      UsbClass->DeviceProtocol
+      );
+    return;
+  }
+
+  if (UsbClass->DeviceClass == USB_CLASS_RESERVE) {
+    if (UsbClass->DeviceSubClass == USB_SUBCLASS_FW_UPDATE) {
+      UefiDevicePathLibCatPrint (
+        Str,
+        "UsbDeviceFirmwareUpdate(0x%x,0x%x,0x%x)",
+        UsbClass->VendorId,
+        UsbClass->ProductId,
+        UsbClass->DeviceProtocol
+        );
+      return;
+    } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_IRDA_BRIDGE) {
+      UefiDevicePathLibCatPrint (
+        Str,
+        "UsbIrdaBridge(0x%x,0x%x,0x%x)",
+        UsbClass->VendorId,
+        UsbClass->ProductId,
+        UsbClass->DeviceProtocol
+        );
+      return;
+    } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_TEST) {
+      UefiDevicePathLibCatPrint (
+        Str,
+        "UsbTestAndMeasurement(0x%x,0x%x,0x%x)",
+        UsbClass->VendorId,
+        UsbClass->ProductId,
+        UsbClass->DeviceProtocol
+        );
+      return;
+    }
+  }
+
+  UefiDevicePathLibCatPrint (
+    Str,
+    "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
+    UsbClass->VendorId,
+    UsbClass->ProductId,
+    UsbClass->DeviceClass,
+    UsbClass->DeviceSubClass,
+    UsbClass->DeviceProtocol
+    );
+}
+
+/**
+  Converts a SATA device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextSata (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  SATA_DEVICE_PATH *Sata;
+
+  Sata = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "Sata(0x%x,0x%x,0x%x)",
+    Sata->HBAPortNumber,
+    Sata->PortMultiplierPortNumber,
+    Sata->Lun
+    );
+}
+
+/**
+  Converts a I20 device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextI2O (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  I2O_DEVICE_PATH *I2ODevPath;
+
+  I2ODevPath = DevPath;
+  UefiDevicePathLibCatPrint (Str, "I2O(0x%x)", I2ODevPath->Tid);
+}
+
+/**
+  Converts a MAC address device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextMacAddr (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  MAC_ADDR_DEVICE_PATH  *MacDevPath;
+  UINTN                 HwAddressSize;
+  UINTN                 Index;
+
+  MacDevPath = DevPath;
+
+  HwAddressSize = sizeof (EFI_MAC_ADDRESS);
+  if (MacDevPath->IfType == 0x01 || MacDevPath->IfType == 0x00) {
+    HwAddressSize = 6;
+  }
+
+  UefiDevicePathLibCatPrint (Str, "MAC(");
+
+  for (Index = 0; Index < HwAddressSize; Index++) {
+    UefiDevicePathLibCatPrint (Str, "%02x", MacDevPath->MacAddress.Addr[Index]);
+  }
+
+  UefiDevicePathLibCatPrint (Str, ",0x%x)", MacDevPath->IfType);
+}
+
+/**
+  Converts network protocol string to its text representation.
+
+  @param Str             The string representative of input device.
+  @param Protocol        The network protocol ID.
+
+**/
+static VOID
+CatNetworkProtocol (
+  IN OUT POOL_PRINT  *Str,
+  IN UINT16          Protocol
+  )
+{
+  if (Protocol == RFC_1700_TCP_PROTOCOL) {
+    UefiDevicePathLibCatPrint (Str, "TCP");
+  } else if (Protocol == RFC_1700_UDP_PROTOCOL) {
+    UefiDevicePathLibCatPrint (Str, "UDP");
+  } else {
+    UefiDevicePathLibCatPrint (Str, "0x%x", Protocol);
+  }
+}
+
+/**
+  Converts IP v4 address to its text representation.
+
+  @param Str             The string representative of input device.
+  @param Address         The IP v4 address.
+**/
+static VOID
+CatIPv4Address (
+  IN OUT POOL_PRINT   *Str,
+  IN EFI_IPv4_ADDRESS *Address
+  )
+{
+  UefiDevicePathLibCatPrint (Str, "%d.%d.%d.%d", Address->Addr[0], Address->Addr[1], Address->Addr[2], Address->Addr[3]);
+}
+
+/**
+  Converts IP v6 address to its text representation.
+
+  @param Str             The string representative of input device.
+  @param Address         The IP v6 address.
+**/
+static VOID
+CatIPv6Address (
+  IN OUT POOL_PRINT   *Str,
+  IN EFI_IPv6_ADDRESS *Address
+  )
+{
+  UefiDevicePathLibCatPrint (
+    Str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+    Address->Addr[0],  Address->Addr[1],
+    Address->Addr[2],  Address->Addr[3],
+    Address->Addr[4],  Address->Addr[5],
+    Address->Addr[6],  Address->Addr[7],
+    Address->Addr[8],  Address->Addr[9],
+    Address->Addr[10], Address->Addr[11],
+    Address->Addr[12], Address->Addr[13],
+    Address->Addr[14], Address->Addr[15]
+  );
+}
+
+/**
+  Converts a IPv4 device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextIPv4 (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  IPv4_DEVICE_PATH  *IPDevPath;
+
+  IPDevPath = DevPath;
+  UefiDevicePathLibCatPrint (Str, "IPv4(");
+  CatIPv4Address (Str, &IPDevPath->RemoteIpAddress);
+
+  if (DisplayOnly) {
+    UefiDevicePathLibCatPrint (Str, ")");
+    return ;
+  }
+
+  UefiDevicePathLibCatPrint (Str, ",");
+  CatNetworkProtocol (Str, IPDevPath->Protocol);
+
+  UefiDevicePathLibCatPrint (Str, ",%s,", IPDevPath->StaticIpAddress ? "Static" : "DHCP");
+  CatIPv4Address (Str, &IPDevPath->LocalIpAddress);
+  if (DevicePathNodeLength (IPDevPath) == sizeof (IPv4_DEVICE_PATH)) {
+    UefiDevicePathLibCatPrint (Str, ",");
+    CatIPv4Address (Str, &IPDevPath->GatewayIpAddress);
+    UefiDevicePathLibCatPrint (Str, ",");
+    CatIPv4Address (Str, &IPDevPath->SubnetMask);
+  }
+  UefiDevicePathLibCatPrint (Str, ")");
+}
+
+/**
+  Converts a IPv6 device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextIPv6 (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  IPv6_DEVICE_PATH  *IPDevPath;
+
+  IPDevPath = DevPath;
+  UefiDevicePathLibCatPrint (Str, "IPv6(");
+  CatIPv6Address (Str, &IPDevPath->RemoteIpAddress);
+  if (DisplayOnly) {
+    UefiDevicePathLibCatPrint (Str, ")");
+    return ;
+  }
+
+  UefiDevicePathLibCatPrint (Str, ",");
+  CatNetworkProtocol (Str, IPDevPath->Protocol);
+
+  switch (IPDevPath->IpAddressOrigin) {
+    case 0:
+      UefiDevicePathLibCatPrint (Str, ",Static,");
+      break;
+    case 1:
+      UefiDevicePathLibCatPrint (Str, ",StatelessAutoConfigure,");
+      break;
+    default:
+      UefiDevicePathLibCatPrint (Str, ",StatefulAutoConfigure,");
+      break;
+  }
+
+  CatIPv6Address (Str, &IPDevPath->LocalIpAddress);
+
+  if (DevicePathNodeLength (IPDevPath) == sizeof (IPv6_DEVICE_PATH)) {
+    UefiDevicePathLibCatPrint (Str, ",0x%x,", IPDevPath->PrefixLength);
+    CatIPv6Address (Str, &IPDevPath->GatewayIpAddress);
+  }
+  UefiDevicePathLibCatPrint (Str, ")");
+}
+
+/**
+  Converts an Infini Band device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextInfiniBand (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  INFINIBAND_DEVICE_PATH  *InfiniBand;
+
+  InfiniBand = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "Infiniband(0x%x,%36s,0x%lx,0x%lx,0x%lx)",
+    InfiniBand->ResourceFlags,
+    G(InfiniBand->PortGid),
+    InfiniBand->ServiceId,
+    InfiniBand->TargetPortId,
+    InfiniBand->DeviceId
+    );
+}
+
+/**
+  Converts a UART device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextUart (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  UART_DEVICE_PATH  *Uart;
+  CHAR8             Parity;
+
+  Uart = DevPath;
+  switch (Uart->Parity) {
+  case 0:
+    Parity = 'D';
+    break;
+
+  case 1:
+    Parity = 'N';
+    break;
+
+  case 2:
+    Parity = 'E';
+    break;
+
+  case 3:
+    Parity = 'O';
+    break;
+
+  case 4:
+    Parity = 'M';
+    break;
+
+  case 5:
+    Parity = 'S';
+    break;
+
+  default:
+    Parity = 'x';
+    break;
+  }
+
+  if (Uart->BaudRate == 0) {
+    UefiDevicePathLibCatPrint (Str, "Uart(DEFAULT,");
+  } else {
+    UefiDevicePathLibCatPrint (Str, "Uart(%ld,", Uart->BaudRate);
+  }
+
+  if (Uart->DataBits == 0) {
+    UefiDevicePathLibCatPrint (Str, "DEFAULT,");
+  } else {
+    UefiDevicePathLibCatPrint (Str, "%d,", Uart->DataBits);
+  }
+
+  UefiDevicePathLibCatPrint (Str, "%c,", Parity);
+
+  switch (Uart->StopBits) {
+  case 0:
+    UefiDevicePathLibCatPrint (Str, "D)");
+    break;
+
+  case 1:
+    UefiDevicePathLibCatPrint (Str, "1)");
+    break;
+
+  case 2:
+    UefiDevicePathLibCatPrint (Str, "1.5)");
+    break;
+
+  case 3:
+    UefiDevicePathLibCatPrint (Str, "2)");
+    break;
+
+  default:
+    UefiDevicePathLibCatPrint (Str, "x)");
+    break;
+  }
+}
+
+/**
+  Converts an iSCSI device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextiSCSI (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath;
+  UINT16                      Options;
+
+  ISCSIDevPath = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "iSCSI(%s,0x%x,0x%lx,",
+    ISCSIDevPath->TargetName,
+    ISCSIDevPath->TargetPortalGroupTag,
+    ISCSIDevPath->Lun
+    );
+
+  Options = ISCSIDevPath->LoginOption;
+  UefiDevicePathLibCatPrint (Str, "%s,", (((Options >> 1) & 0x0001) != 0) ? "CRC32C" : "None");
+  UefiDevicePathLibCatPrint (Str, "%s,", (((Options >> 3) & 0x0001) != 0) ? "CRC32C" : "None");
+  if (((Options >> 11) & 0x0001) != 0) {
+    UefiDevicePathLibCatPrint (Str, "%s,", "None");
+  } else if (((Options >> 12) & 0x0001) != 0) {
+    UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_UNI");
+  } else {
+    UefiDevicePathLibCatPrint (Str, "%s,", "CHAP_BI");
+
+  }
+
+  UefiDevicePathLibCatPrint (Str, "%s)", (ISCSIDevPath->NetworkProtocol == 0) ? "TCP" : "reserved");
+}
+
+/**
+  Converts a VLAN device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextVlan (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  VLAN_DEVICE_PATH  *Vlan;
+
+  Vlan = DevPath;
+  UefiDevicePathLibCatPrint (Str, "Vlan(%d)", Vlan->VlanId);
+}
+
+/**
+  Converts a Bluetooth device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextBluetooth (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  BLUETOOTH_DEVICE_PATH  *Bluetooth;
+
+  Bluetooth = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "Bluetooth(%02x%02x%02x%02x%02x%02x)",
+    Bluetooth->BD_ADDR.Address[5],
+    Bluetooth->BD_ADDR.Address[4],
+    Bluetooth->BD_ADDR.Address[3],
+    Bluetooth->BD_ADDR.Address[2],
+    Bluetooth->BD_ADDR.Address[1],
+    Bluetooth->BD_ADDR.Address[0]
+    );
+}
+
+/**
+  Converts a Wi-Fi device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextWiFi (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  WIFI_DEVICE_PATH      *WiFi;
+  UINT8                 SSId[33];
+
+  WiFi = DevPath;
+
+  SSId[32] = '\0';
+  CopyMem (SSId, WiFi->SSId, 32);
+
+  UefiDevicePathLibCatPrint (Str, "Wi-Fi(%s)", SSId);
+}
+
+/**
+  Converts a URI device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextUri (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  URI_DEVICE_PATH    *Uri;
+  UINTN              UriLength;
+  CHAR8              *UriStr;
+
+  //
+  // Uri in the device path may not be null terminated.
+  //
+  Uri       = DevPath;
+  UriLength = DevicePathNodeLength (Uri) - sizeof (URI_DEVICE_PATH);
+  UriStr = AllocatePool (UriLength + 1);
+  ASSERT (UriStr != NULL);
+
+  CopyMem (UriStr, Uri->Uri, UriLength);
+  UriStr[UriLength] = '\0';
+  UefiDevicePathLibCatPrint (Str, "Uri(%s)", UriStr);
+  FreePool (UriStr);
+}
+
+/**
+  Converts a Hard drive device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextHardDrive (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  HARDDRIVE_DEVICE_PATH *Hd;
+
+  Hd = DevPath;
+  switch (Hd->SignatureType) {
+  case SIGNATURE_TYPE_MBR:
+    UefiDevicePathLibCatPrint (
+      Str,
+      "HD(%d,%s,0x%08x,",
+      Hd->PartitionNumber,
+      "MBR",
+//      *((UINT32 *) (&(Hd->Signature[0])))
+      le32dec(&(Hd->Signature[0]))
+      );
+    break;
+
+  case SIGNATURE_TYPE_GUID:
+    UefiDevicePathLibCatPrint (
+      Str,
+      "HD(%d,%s,%36s,",
+      Hd->PartitionNumber,
+      "GPT",
+      G(&(Hd->Signature[0]))
+      );
+    break;
+
+  default:
+    UefiDevicePathLibCatPrint (
+      Str,
+      "HD(%d,%d,0,",
+      Hd->PartitionNumber,
+      Hd->SignatureType
+      );
+    break;
+  }
+
+  UefiDevicePathLibCatPrint (Str, "0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
+}
+
+/**
+  Converts a CDROM device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextCDROM (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  CDROM_DEVICE_PATH *Cd;
+
+  Cd = DevPath;
+  if (DisplayOnly) {
+    UefiDevicePathLibCatPrint (Str, "CDROM(0x%x)", Cd->BootEntry);
+    return ;
+  }
+
+  UefiDevicePathLibCatPrint (Str, "CDROM(0x%x,0x%lx,0x%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
+}
+
+/**
+  Converts a File device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextFilePath (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  FILEPATH_DEVICE_PATH  *Fp;
+
+  Fp = DevPath;
+  UefiDevicePathLibCatPrint (Str, "%s", Fp->PathName);
+}
+
+/**
+  Converts a Media protocol device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextMediaProtocol (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
+
+  MediaProt = DevPath;
+  UefiDevicePathLibCatPrint (Str, "Media(%36s)", G(&MediaProt->Protocol));
+}
+
+/**
+  Converts a Firmware Volume device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextFv (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  MEDIA_FW_VOL_DEVICE_PATH  *Fv;
+
+  Fv = DevPath;
+  UefiDevicePathLibCatPrint (Str, "Fv(%36s)", G(&Fv->FvName));
+}
+
+/**
+  Converts a Firmware Volume File device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextFvFile (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFile;
+
+  FvFile = DevPath;
+  UefiDevicePathLibCatPrint (Str, "FvFile(%36s)", G(&FvFile->FvFileName));
+}
+
+/**
+  Converts a Relative Offset device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathRelativeOffsetRange (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath,
+  IN BOOLEAN              DisplayOnly,
+  IN BOOLEAN              AllowShortcuts
+  )
+{
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
+
+  Offset = DevPath;
+  UefiDevicePathLibCatPrint (
+    Str,
+    "Offset(0x%lx,0x%lx)",
+    Offset->StartingOffset,
+    Offset->EndingOffset
+    );
+}
+
+/**
+  Converts a Ram Disk device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextRamDisk (
+  IN OUT POOL_PRINT       *Str,
+  IN VOID                 *DevPath,
+  IN BOOLEAN              DisplayOnly,
+  IN BOOLEAN              AllowShortcuts
+  )
+{
+  MEDIA_RAM_DISK_DEVICE_PATH *RamDisk;
+
+  RamDisk = DevPath;
+
+  if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid)) {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "VirtualDisk(0x%lx,0x%lx,%d)",
+      LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
+      LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
+      RamDisk->Instance
+      );
+  } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid)) {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "VirtualCD(0x%lx,0x%lx,%d)",
+      LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
+      LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
+      RamDisk->Instance
+      );
+  } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid)) {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "PersistentVirtualDisk(0x%lx,0x%lx,%d)",
+      LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
+      LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
+      RamDisk->Instance
+      );
+  } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid)) {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "PersistentVirtualCD(0x%lx,0x%lx,%d)",
+      LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
+      LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
+      RamDisk->Instance
+      );
+  } else {
+    UefiDevicePathLibCatPrint (
+      Str,
+      "RamDisk(0x%lx,0x%lx,%d,%36s)",
+      LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0],
+      LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0],
+      RamDisk->Instance,
+      G(&RamDisk->TypeGuid)
+      );
+  }
+}
+
+/**
+  Converts a BIOS Boot Specification device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextBBS (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  BBS_BBS_DEVICE_PATH *Bbs;
+  const char          *Type;
+
+  Bbs = DevPath;
+  switch (Bbs->DeviceType) {
+  case BBS_TYPE_FLOPPY:
+    Type = "Floppy";
+    break;
+
+  case BBS_TYPE_HARDDRIVE:
+    Type = "HD";
+    break;
+
+  case BBS_TYPE_CDROM:
+    Type = "CDROM";
+    break;
+
+  case BBS_TYPE_PCMCIA:
+    Type = "PCMCIA";
+    break;
+
+  case BBS_TYPE_USB:
+    Type = "USB";
+    break;
+
+  case BBS_TYPE_EMBEDDED_NETWORK:
+    Type = "Network";
+    break;
+
+  default:
+    Type = NULL;
+    break;
+  }
+
+  if (Type != NULL) {
+    UefiDevicePathLibCatPrint (Str, "BBS(%s,%s", Type, Bbs->String);
+  } else {
+    UefiDevicePathLibCatPrint (Str, "BBS(0x%x,%s", Bbs->DeviceType, Bbs->String);
+  }
+
+  if (DisplayOnly) {
+    UefiDevicePathLibCatPrint (Str, ")");
+    return ;
+  }
+
+  UefiDevicePathLibCatPrint (Str, ",0x%x)", Bbs->StatusFlag);
+}
+
+/**
+  Converts an End-of-Device-Path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextEndInstance (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  UefiDevicePathLibCatPrint (Str, ",");
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_GENERIC_TABLE mUefiDevicePathLibToTextTableGeneric[] = {
+  {HARDWARE_DEVICE_PATH,  "HardwarePath"   },
+  {ACPI_DEVICE_PATH,      "AcpiPath"       },
+  {MESSAGING_DEVICE_PATH, "Msg"            },
+  {MEDIA_DEVICE_PATH,     "MediaPath"      },
+  {BBS_DEVICE_PATH,       "BbsPath"        },
+  {0, NULL}
+};
+
+/**
+  Converts an unknown device path structure to its string representative.
+
+  @param Str             The string representative of input device.
+  @param DevPath         The input device path structure.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+**/
+static VOID
+DevPathToTextNodeGeneric (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevPath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL *Node;
+  UINTN                    Index;
+
+  Node = DevPath;
+
+  for (Index = 0; mUefiDevicePathLibToTextTableGeneric[Index].Text != NULL; Index++) {
+    if (DevicePathType (Node) == mUefiDevicePathLibToTextTableGeneric[Index].Type) {
+      break;
+    }
+  }
+
+  if (mUefiDevicePathLibToTextTableGeneric[Index].Text == NULL) {
+    //
+    // It's a node whose type cannot be recognized
+    //
+    UefiDevicePathLibCatPrint (Str, "Path(%d,%d", DevicePathType (Node), DevicePathSubType (Node));
+  } else {
+    //
+    // It's a node whose type can be recognized
+    //
+    UefiDevicePathLibCatPrint (Str, "%s(%d", mUefiDevicePathLibToTextTableGeneric[Index].Text, DevicePathSubType (Node));
+  }
+
+  Index = sizeof (EFI_DEVICE_PATH_PROTOCOL);
+  if (Index < DevicePathNodeLength (Node)) {
+    UefiDevicePathLibCatPrint (Str, ",");
+    for (; Index < DevicePathNodeLength (Node); Index++) {
+      UefiDevicePathLibCatPrint (Str, "%02x", ((UINT8 *) Node)[Index]);
+    }
+  }
+
+  UefiDevicePathLibCatPrint (Str, ")");
+}
+
+static const DEVICE_PATH_TO_TEXT_TABLE mUefiDevicePathLibToTextTable[] = {
+  {HARDWARE_DEVICE_PATH,  HW_PCI_DP,                        DevPathToTextPci            },
+  {HARDWARE_DEVICE_PATH,  HW_PCCARD_DP,                     DevPathToTextPccard         },
+  {HARDWARE_DEVICE_PATH,  HW_MEMMAP_DP,                     DevPathToTextMemMap         },
+  {HARDWARE_DEVICE_PATH,  HW_VENDOR_DP,                     DevPathToTextVendor         },
+  {HARDWARE_DEVICE_PATH,  HW_CONTROLLER_DP,                 DevPathToTextController     },
+  {HARDWARE_DEVICE_PATH,  HW_BMC_DP,                        DevPathToTextBmc            },
+  {ACPI_DEVICE_PATH,      ACPI_DP,                          DevPathToTextAcpi           },
+  {ACPI_DEVICE_PATH,      ACPI_EXTENDED_DP,                 DevPathToTextAcpiEx         },
+  {ACPI_DEVICE_PATH,      ACPI_ADR_DP,                      DevPathToTextAcpiAdr        },
+  {MESSAGING_DEVICE_PATH, MSG_ATAPI_DP,                     DevPathToTextAtapi          },
+  {MESSAGING_DEVICE_PATH, MSG_SCSI_DP,                      DevPathToTextScsi           },
+  {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP,              DevPathToTextFibre          },
+  {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP,            DevPathToTextFibreEx        },
+  {MESSAGING_DEVICE_PATH, MSG_SASEX_DP,                     DevPathToTextSasEx          },
+  {MESSAGING_DEVICE_PATH, MSG_NVME_NAMESPACE_DP,            DevPathToTextNVMe           },
+  {MESSAGING_DEVICE_PATH, MSG_UFS_DP,                       DevPathToTextUfs            },
+  {MESSAGING_DEVICE_PATH, MSG_SD_DP,                        DevPathToTextSd             },
+  {MESSAGING_DEVICE_PATH, MSG_EMMC_DP,                      DevPathToTextEmmc           },
+  {MESSAGING_DEVICE_PATH, MSG_1394_DP,                      DevPathToText1394           },
+  {MESSAGING_DEVICE_PATH, MSG_USB_DP,                       DevPathToTextUsb            },
+  {MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP,                  DevPathToTextUsbWWID        },
+  {MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP,       DevPathToTextLogicalUnit    },
+  {MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,                 DevPathToTextUsbClass       },
+  {MESSAGING_DEVICE_PATH, MSG_SATA_DP,                      DevPathToTextSata           },
+  {MESSAGING_DEVICE_PATH, MSG_I2O_DP,                       DevPathToTextI2O            },
+  {MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,                  DevPathToTextMacAddr        },
+  {MESSAGING_DEVICE_PATH, MSG_IPv4_DP,                      DevPathToTextIPv4           },
+  {MESSAGING_DEVICE_PATH, MSG_IPv6_DP,                      DevPathToTextIPv6           },
+  {MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP,                DevPathToTextInfiniBand     },
+  {MESSAGING_DEVICE_PATH, MSG_UART_DP,                      DevPathToTextUart           },
+  {MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,                    DevPathToTextVendor         },
+  {MESSAGING_DEVICE_PATH, MSG_ISCSI_DP,                     DevPathToTextiSCSI          },
+  {MESSAGING_DEVICE_PATH, MSG_VLAN_DP,                      DevPathToTextVlan           },
+  {MESSAGING_DEVICE_PATH, MSG_URI_DP,                       DevPathToTextUri            },
+  {MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_DP,                 DevPathToTextBluetooth      },
+  {MESSAGING_DEVICE_PATH, MSG_WIFI_DP,                      DevPathToTextWiFi           },
+  {MEDIA_DEVICE_PATH,     MEDIA_HARDDRIVE_DP,               DevPathToTextHardDrive      },
+  {MEDIA_DEVICE_PATH,     MEDIA_CDROM_DP,                   DevPathToTextCDROM          },
+  {MEDIA_DEVICE_PATH,     MEDIA_VENDOR_DP,                  DevPathToTextVendor         },
+  {MEDIA_DEVICE_PATH,     MEDIA_PROTOCOL_DP,                DevPathToTextMediaProtocol  },
+  {MEDIA_DEVICE_PATH,     MEDIA_FILEPATH_DP,                DevPathToTextFilePath       },
+  {MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_VOL_DP,             DevPathToTextFv             },
+  {MEDIA_DEVICE_PATH,     MEDIA_PIWG_FW_FILE_DP,            DevPathToTextFvFile         },
+  {MEDIA_DEVICE_PATH,     MEDIA_RELATIVE_OFFSET_RANGE_DP,   DevPathRelativeOffsetRange  },
+  {MEDIA_DEVICE_PATH,     MEDIA_RAM_DISK_DP,                DevPathToTextRamDisk        },
+  {BBS_DEVICE_PATH,       BBS_BBS_DP,                       DevPathToTextBBS            },
+  {END_DEVICE_PATH_TYPE,  END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance    },
+  {0, 0, NULL}
+};
+
+#ifndef __DragonFly__
+/**
+  Converts a device node to its string representation.
+
+  @param DeviceNode        A Pointer to the device node to be converted.
+  @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
+                           of the display node is used, where applicable. If DisplayOnly
+                           is FALSE, then the longer text representation of the display node
+                           is used.
+  @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
+                           representation for a device node can be used, where applicable.
+
+  @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
+          is NULL or there was insufficient memory.
+
+**/
+CHAR16 *
+EFIAPI
+UefiDevicePathLibConvertDeviceNodeToText (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
+  IN BOOLEAN                         DisplayOnly,
+  IN BOOLEAN                         AllowShortcuts
+  )
+{
+  POOL_PRINT          Str;
+  UINTN               Index;
+  DEVICE_PATH_TO_TEXT ToText;
+
+  if (DeviceNode == NULL) {
+    return NULL;
+  }
+
+  ZeroMem (&Str, sizeof (Str));
+
+  //
+  // Process the device path node
+  // If not found, use a generic function
+  //
+  ToText = DevPathToTextNodeGeneric;
+  for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index++) {
+    if (DevicePathType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].Type &&
+        DevicePathSubType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].SubType
+        ) {
+      ToText = mUefiDevicePathLibToTextTable[Index].Function;
+      break;
+    }
+  }
+
+  //
+  // Print this node
+  //
+  ToText (&Str, (VOID *) DeviceNode, DisplayOnly, AllowShortcuts);
+
+  ASSERT (Str.Str != NULL);
+  return Str.Str;
+}
+#endif
+
+/**
+  Converts a device path to its text representation.
+
+  @param DevicePath      A Pointer to the device to be converted.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+  @return A pointer to the allocated text representation of the device path or
+          NULL if DeviceNode is NULL or there was insufficient memory.
+
+**/
+static char *
+EFIAPI
+UefiDevicePathLibConvertDevicePathToText (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
+  IN BOOLEAN                          DisplayOnly,
+  IN BOOLEAN                          AllowShortcuts
+  )
+{
+  POOL_PRINT               Str;
+  EFI_DEVICE_PATH_PROTOCOL *Node;
+  EFI_DEVICE_PATH_PROTOCOL *AlignedNode;
+  UINTN                    Index;
+  DEVICE_PATH_TO_TEXT      ToText;
+
+  if (DevicePath == NULL) {
+    return NULL;
+  }
+
+  ZeroMem (&Str, sizeof (Str));
+
+  //
+  // Process each device path node
+  //
+  Node = __DECONST(EFI_DEVICE_PATH_PROTOCOL *, DevicePath);
+  while (!IsDevicePathEnd (Node)) {
+    //
+    // Find the handler to dump this device path node
+    // If not found, use a generic function
+    //
+    ToText = DevPathToTextNodeGeneric;
+    for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index += 1) {
+
+      if (DevicePathType (Node) == mUefiDevicePathLibToTextTable[Index].Type &&
+          DevicePathSubType (Node) == mUefiDevicePathLibToTextTable[Index].SubType
+          ) {
+        ToText = mUefiDevicePathLibToTextTable[Index].Function;
+        break;
+      }
+    }
+    //
+    //  Put a path separator in if needed
+    //
+    if ((Str.Count != 0) && (ToText != DevPathToTextEndInstance)) {
+      if (Str.Str[Str.Count] != ',') {
+        UefiDevicePathLibCatPrint (&Str, "/");
+      }
+    }
+
+    AlignedNode = AllocateCopyPool (DevicePathNodeLength (Node), Node);
+    //
+    // Print this node of the device path
+    //
+    ToText (&Str, AlignedNode, DisplayOnly, AllowShortcuts);
+    FreePool (AlignedNode);
+
+    //
+    // Next device path node
+    //
+    Node = NextDevicePathNode (Node);
+  }
+
+  if (Str.Str == NULL) {
+    return AllocateZeroPool (sizeof (CHAR16));
+  } else {
+    return Str.Str;
+  }
+}
+
+
+ssize_t
+efidp_format_device_path(char *buf, size_t len, const_efidp dp, ssize_t max)
+{
+	char *str;
+	ssize_t retval;
+
+	str = UefiDevicePathLibConvertDevicePathToText (
+		__DECONST(EFI_DEVICE_PATH_PROTOCOL *, dp), FALSE, TRUE);
+	if (str == NULL)
+		return -1;
+	strlcpy(buf, str, len);
+	retval = strlen(str);
+	free(str);
+
+	return retval;
+}
diff --git a/lib/libefivar/efivar-dp-parse.c b/lib/libefivar/efivar-dp-parse.c
new file mode 100644
index 0000000000..2a42e1b06b
--- /dev/null
+++ b/lib/libefivar/efivar-dp-parse.c
@@ -0,0 +1,3703 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Routines to format EFI_DEVICE_PATHs from the UEFI standard. Much of
+ * this file is taken from EDK2 and rototilled.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libefivar/efivar-dp-parse.c 314926 2017-03-09 00:31:31Z imp $");
+
+#include <ctype.h>
+#include <efivar.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "efi-osdep.h"
+#include "efivar-dp.h"
+
+#include "uefi-dplib.h"
+
+/* XXX STUBS -- this stuff doesn't work yet */
+#define StrToIpv4Address(str, unk, ipv4ptr, unk2)
+#define StrToIpv6Address(str, unk, ipv6ptr, unk2)
+
+/*
+ * OK. Now this is evil. Can't typedef it again. Sure beats changing them all.
+ * Since we're doing it all as narrow characters since wchar_t can't be used on
+ * FreeBSD and CHAR16 strings generally aren't a good fit. Since this parsing
+ * doesn't need Unicode for anything, this works out well.
+ */
+#define CHAR16 char
+
+/*
+ * Taken from MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c
+ * hash a11928f3310518ab1c6fd34e8d0fdbb72de9602c 2017-Mar-01
+ */
+
+/** @file
+  DevicePathFromText protocol as defined in the UEFI 2.0 specification.
+
+Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+// #include "UefiDevicePathLib.h"
+
+/**
+
+  Duplicates a string.
+
+  @param  Src  Source string.
+
+  @return The duplicated string.
+
+**/
+static
+CHAR16 *
+UefiDevicePathLibStrDuplicate (
+  IN CONST CHAR16  *Src
+  )
+{
+  return AllocateCopyPool (StrSize (Src), Src);
+}
+
+/**
+
+  Get parameter in a pair of parentheses follow the given node name.
+  For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1".
+
+  @param  Str      Device Path Text.
+  @param  NodeName Name of the node.
+
+  @return Parameter text for the node.
+
+**/
+static
+CHAR16 *
+GetParamByNodeName (
+  IN CHAR16 *Str,
+  IN const CHAR16 *NodeName
+  )
+{
+  CHAR16  *ParamStr;
+  CHAR16  *StrPointer;
+  UINTN   NodeNameLength;
+  UINTN   ParameterLength;
+
+  //
+  // Check whether the node name matchs
+  //
+  NodeNameLength = StrLen (NodeName);
+  if (StrnCmp (Str, NodeName, NodeNameLength) != 0) {
+    return NULL;
+  }
+
+  ParamStr = Str + NodeNameLength;
+  if (!IS_LEFT_PARENTH (*ParamStr)) {
+    return NULL;
+  }
+
+  //
+  // Skip the found '(' and find first occurrence of ')'
+  //
+  ParamStr++;
+  ParameterLength = 0;
+  StrPointer = ParamStr;
+  while (!IS_NULL (*StrPointer)) {
+    if (IS_RIGHT_PARENTH (*StrPointer)) {
+      break;
+    }
+    StrPointer++;
+    ParameterLength++;
+  }
+  if (IS_NULL (*StrPointer)) {
+    //
+    // ')' not found
+    //
+    return NULL;
+  }
+
+  ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr);
+  if (ParamStr == NULL) {
+    return NULL;
+  }
+  //
+  // Terminate the parameter string
+  //
+  ParamStr[ParameterLength] = '\0';
+
+  return ParamStr;
+}
+
+/**
+  Gets current sub-string from a string list, before return
+  the list header is moved to next sub-string. The sub-string is separated
+  by the specified character. For example, the separator is ',', the string
+  list is "2,0,3", it returns "2", the remain list move to "0,3"
+
+  @param  List        A string list separated by the specified separator
+  @param  Separator   The separator character
+
+  @return A pointer to the current sub-string
+
+**/
+static
+CHAR16 *
+SplitStr (
+  IN OUT CHAR16 **List,
+  IN     CHAR16 Separator
+  )
+{
+  CHAR16  *Str;
+  CHAR16  *ReturnStr;
+
+  Str = *List;
+  ReturnStr = Str;
+
+  if (IS_NULL (*Str)) {
+    return ReturnStr;
+  }
+
+  //
+  // Find first occurrence of the separator
+  //
+  while (!IS_NULL (*Str)) {
+    if (*Str == Separator) {
+      break;
+    }
+    Str++;
+  }
+
+  if (*Str == Separator) {
+    //
+    // Find a sub-string, terminate it
+    //
+    *Str = '\0';
+    Str++;
+  }
+
+  //
+  // Move to next sub-string
+  //
+  *List = Str;
+
+  return ReturnStr;
+}
+
+/**
+  Gets the next parameter string from the list.
+
+  @param List            A string list separated by the specified separator
+
+  @return A pointer to the current sub-string
+
+**/
+static
+CHAR16 *
+GetNextParamStr (
+  IN OUT CHAR16 **List
+  )
+{
+  //
+  // The separator is comma
+  //
+  return SplitStr (List, ',');
+}
+
+/**
+  Get one device node from entire device path text.
+
+  @param DevicePath      On input, the current Device Path node; on output, the next device path node
+  @param IsInstanceEnd   This node is the end of a device path instance
+
+  @return A device node text or NULL if no more device node available
+
+**/
+static
+CHAR16 *
+GetNextDeviceNodeStr (
+  IN OUT CHAR16   **DevicePath,
+  OUT    BOOLEAN  *IsInstanceEnd
+  )
+{
+  CHAR16  *Str;
+  CHAR16  *ReturnStr;
+  UINTN   ParenthesesStack;
+
+  Str = *DevicePath;
+  if (IS_NULL (*Str)) {
+    return NULL;
+  }
+
+  //
+  // Skip the leading '/', '(', ')' and ','
+  //
+  while (!IS_NULL (*Str)) {
+    if (!IS_SLASH (*Str) &&
+        !IS_COMMA (*Str) &&
+        !IS_LEFT_PARENTH (*Str) &&
+        !IS_RIGHT_PARENTH (*Str)) {
+      break;
+    }
+    Str++;
+  }
+
+  ReturnStr = Str;
+
+  //
+  // Scan for the separator of this device node, '/' or ','
+  //
+  ParenthesesStack = 0;
+  while (!IS_NULL (*Str)) {
+    if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) {
+      break;
+    }
+
+    if (IS_LEFT_PARENTH (*Str)) {
+      ParenthesesStack++;
+    } else if (IS_RIGHT_PARENTH (*Str)) {
+      ParenthesesStack--;
+    }
+
+    Str++;
+  }
+
+  if (ParenthesesStack != 0) {
+    //
+    // The '(' doesn't pair with ')', invalid device path text
+    //
+    return NULL;
+  }
+
+  if (IS_COMMA (*Str)) {
+    *IsInstanceEnd = TRUE;
+    *Str = '\0';
+    Str++;
+  } else {
+    *IsInstanceEnd = FALSE;
+    if (!IS_NULL (*Str)) {
+      *Str = '\0';
+      Str++;
+    }
+  }
+
+  *DevicePath = Str;
+
+  return ReturnStr;
+}
+
+
+#ifndef __DragonFly__
+/**
+  Return whether the integer string is a hex string.
+
+  @param Str             The integer string
+
+  @retval TRUE   Hex string
+  @retval FALSE  Decimal string
+
+**/
+static
+BOOLEAN
+IsHexStr (
+  IN CHAR16   *Str
+  )
+{
+  //
+  // skip preceeding white space
+  //
+  while ((*Str != 0) && *Str == ' ') {
+    Str ++;
+  }
+  //
+  // skip preceeding zeros
+  //
+  while ((*Str != 0) && *Str == '0') {
+    Str ++;
+  }
+
+  return (BOOLEAN) (*Str == 'x' || *Str == 'X');
+}
+
+/**
+
+  Convert integer string to uint.
+
+  @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.
+
+  @return A UINTN value represented by Str
+
+**/
+static
+UINTN
+Strtoi (
+  IN CHAR16  *Str
+  )
+{
+  if (IsHexStr (Str)) {
+    return StrHexToUintn (Str);
+  } else {
+    return StrDecimalToUintn (Str);
+  }
+}
+
+/**
+
+  Convert integer string to 64 bit data.
+
+  @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.
+  @param Data            A pointer to the UINT64 value represented by Str
+
+**/
+static
+VOID
+Strtoi64 (
+  IN  CHAR16  *Str,
+  OUT UINT64  *Data
+  )
+{
+  if (IsHexStr (Str)) {
+    *Data = StrHexToUint64 (Str);
+  } else {
+    *Data = StrDecimalToUint64 (Str);
+  }
+}
+#endif
+
+/**
+  Converts a Unicode string to ASCII string.
+
+  @param Str             The equivalent Unicode string
+  @param AsciiStr        On input, it points to destination ASCII string buffer; on output, it points
+                         to the next ASCII string next to it
+
+**/
+static
+VOID
+StrToAscii (
+  IN     CHAR16 *Str,
+  IN OUT CHAR8  **AsciiStr
+  )
+{
+  CHAR8 *Dest;
+
+  Dest = *AsciiStr;
+  while (!IS_NULL (*Str)) {
+    *(Dest++) = (CHAR8) *(Str++);
+  }
+  *Dest = 0;
+
+  //
+  // Return the string next to it
+  //
+  *AsciiStr = Dest + 1;
+}
+
+/**
+  Converts a generic text device path node to device path structure.
+
+  @param Type            The type of the device path node.
+  @param TextDeviceNode  The input text device path node.
+
+  @return A pointer to device path structure.
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextGenericPath (
+  IN UINT8  Type,
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL *Node;
+  CHAR16                   *SubtypeStr;
+  CHAR16                   *DataStr;
+  UINTN                    DataLength;
+
+  SubtypeStr = GetNextParamStr (&TextDeviceNode);
+  DataStr    = GetNextParamStr (&TextDeviceNode);
+
+  if (DataStr == NULL) {
+    DataLength = 0;
+  } else {
+    DataLength = StrLen (DataStr) / 2;
+  }
+  Node = CreateDeviceNode (
+           Type,
+           (UINT8) Strtoi (SubtypeStr),
+           (UINT16) (sizeof (EFI_DEVICE_PATH_PROTOCOL) + DataLength)
+           );
+
+  StrHexToBytes (DataStr, DataLength * 2, (UINT8 *) (Node + 1), DataLength);
+  return Node;
+}
+
+/**
+  Converts a generic text device path node to device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPath (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                   *TypeStr;
+
+  TypeStr    = GetNextParamStr (&TextDeviceNode);
+
+  return DevPathFromTextGenericPath ((UINT8) Strtoi (TypeStr), TextDeviceNode);
+}
+
+/**
+  Converts a generic hardware text device path node to Hardware device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to Hardware device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextHardwarePath (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return DevPathFromTextGenericPath (HARDWARE_DEVICE_PATH, TextDeviceNode);
+}
+
+/**
+  Converts a text device path node to Hardware PCI device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to Hardware PCI device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPci (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16          *FunctionStr;
+  CHAR16          *DeviceStr;
+  PCI_DEVICE_PATH *Pci;
+
+  DeviceStr   = GetNextParamStr (&TextDeviceNode);
+  FunctionStr = GetNextParamStr (&TextDeviceNode);
+  Pci         = (PCI_DEVICE_PATH *) CreateDeviceNode (
+                                      HARDWARE_DEVICE_PATH,
+                                      HW_PCI_DP,
+                                      (UINT16) sizeof (PCI_DEVICE_PATH)
+                                      );
+
+  Pci->Function = (UINT8) Strtoi (FunctionStr);
+  Pci->Device   = (UINT8) Strtoi (DeviceStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Pci;
+}
+
+/**
+  Converts a text device path node to Hardware PC card device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to Hardware PC card device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPcCard (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16              *FunctionNumberStr;
+  PCCARD_DEVICE_PATH  *Pccard;
+
+  FunctionNumberStr = GetNextParamStr (&TextDeviceNode);
+  Pccard            = (PCCARD_DEVICE_PATH *) CreateDeviceNode (
+                                               HARDWARE_DEVICE_PATH,
+                                               HW_PCCARD_DP,
+                                               (UINT16) sizeof (PCCARD_DEVICE_PATH)
+                                               );
+
+  Pccard->FunctionNumber  = (UINT8) Strtoi (FunctionNumberStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Pccard;
+}
+
+/**
+  Converts a text device path node to Hardware memory map device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to Hardware memory map device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMemoryMapped (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16              *MemoryTypeStr;
+  CHAR16              *StartingAddressStr;
+  CHAR16              *EndingAddressStr;
+  MEMMAP_DEVICE_PATH  *MemMap;
+
+  MemoryTypeStr      = GetNextParamStr (&TextDeviceNode);
+  StartingAddressStr = GetNextParamStr (&TextDeviceNode);
+  EndingAddressStr   = GetNextParamStr (&TextDeviceNode);
+  MemMap             = (MEMMAP_DEVICE_PATH *) CreateDeviceNode (
+                                               HARDWARE_DEVICE_PATH,
+                                               HW_MEMMAP_DP,
+                                               (UINT16) sizeof (MEMMAP_DEVICE_PATH)
+                                               );
+
+  MemMap->MemoryType = (UINT32) Strtoi (MemoryTypeStr);
+  Strtoi64 (StartingAddressStr, &MemMap->StartingAddress);
+  Strtoi64 (EndingAddressStr, &MemMap->EndingAddress);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) MemMap;
+}
+
+/**
+  Converts a text device path node to Vendor device path structure based on the input Type
+  and SubType.
+
+  @param TextDeviceNode  The input Text device path node.
+  @param Type            The type of device path node.
+  @param SubType         The subtype of device path node.
+
+  @return A pointer to the newly-created Vendor device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextVendor (
+  IN CHAR16 *TextDeviceNode,
+  IN UINT8  Type,
+  IN UINT8  SubType
+  )
+{
+  CHAR16              *GuidStr;
+  CHAR16              *DataStr;
+  UINTN               Length;
+  VENDOR_DEVICE_PATH  *Vendor;
+
+  GuidStr = GetNextParamStr (&TextDeviceNode);
+
+  DataStr = GetNextParamStr (&TextDeviceNode);
+  Length  = StrLen (DataStr);
+  //
+  // Two hex characters make up 1 buffer byte
+  //
+  Length  = (Length + 1) / 2;
+
+  Vendor  = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+                                     Type,
+                                     SubType,
+                                     (UINT16) (sizeof (VENDOR_DEVICE_PATH) + Length)
+                                     );
+
+  StrToGuid (GuidStr, &Vendor->Guid);
+  StrHexToBytes (DataStr, Length * 2, (UINT8 *) (Vendor + 1), Length);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+  Converts a text device path node to Vendor Hardware device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Vendor Hardware device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenHw (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextVendor (
+           TextDeviceNode,
+           HARDWARE_DEVICE_PATH,
+           HW_VENDOR_DP
+           );
+}
+
+/**
+  Converts a text device path node to Hardware Controller device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Hardware Controller device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextCtrl (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                  *ControllerStr;
+  CONTROLLER_DEVICE_PATH  *Controller;
+
+  ControllerStr = GetNextParamStr (&TextDeviceNode);
+  Controller    = (CONTROLLER_DEVICE_PATH *) CreateDeviceNode (
+                                               HARDWARE_DEVICE_PATH,
+                                               HW_CONTROLLER_DP,
+                                               (UINT16) sizeof (CONTROLLER_DEVICE_PATH)
+                                               );
+  Controller->ControllerNumber = (UINT32) Strtoi (ControllerStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Controller;
+}
+
+/**
+  Converts a text device path node to BMC device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created BMC device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBmc (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                *InterfaceTypeStr;
+  CHAR16                *BaseAddressStr;
+  BMC_DEVICE_PATH       *BmcDp;
+
+  InterfaceTypeStr = GetNextParamStr (&TextDeviceNode);
+  BaseAddressStr   = GetNextParamStr (&TextDeviceNode);
+  BmcDp            = (BMC_DEVICE_PATH *) CreateDeviceNode (
+                                           HARDWARE_DEVICE_PATH,
+                                           HW_BMC_DP,
+                                           (UINT16) sizeof (BMC_DEVICE_PATH)
+                                           );
+
+  BmcDp->InterfaceType = (UINT8) Strtoi (InterfaceTypeStr);
+  WriteUnaligned64 (
+    (UINT64 *) (&BmcDp->BaseAddress),
+    StrHexToUint64 (BaseAddressStr)
+    );
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) BmcDp;
+}
+
+/**
+  Converts a generic ACPI text device path node to ACPI device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to ACPI device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiPath (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return DevPathFromTextGenericPath (ACPI_DEVICE_PATH, TextDeviceNode);
+}
+
+/**
+  Converts a string to EisaId.
+
+  @param Text   The input string.
+
+  @return UINT32 EISA ID.
+**/
+static
+UINT32
+EisaIdFromText (
+  IN CHAR16 *Text
+  )
+{
+  return (((Text[0] - 'A' + 1) & 0x1f) << 10)
+       + (((Text[1] - 'A' + 1) & 0x1f) <<  5)
+       + (((Text[2] - 'A' + 1) & 0x1f) <<  0)
+       + (UINT32) (StrHexToUintn (&Text[3]) << 16)
+       ;
+}
+
+/**
+  Converts a text device path node to ACPI HID device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created ACPI HID device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpi (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                *HIDStr;
+  CHAR16                *UIDStr;
+  ACPI_HID_DEVICE_PATH  *Acpi;
+
+  HIDStr = GetNextParamStr (&TextDeviceNode);
+  UIDStr = GetNextParamStr (&TextDeviceNode);
+  Acpi   = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode (
+                                      ACPI_DEVICE_PATH,
+                                      ACPI_DP,
+                                      (UINT16) sizeof (ACPI_HID_DEVICE_PATH)
+                                      );
+
+  Acpi->HID = EisaIdFromText (HIDStr);
+  Acpi->UID = (UINT32) Strtoi (UIDStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Acpi;
+}
+
+/**
+  Converts a text device path node to ACPI HID device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+  @param PnPId           The input plug and play identification.
+
+  @return A pointer to the newly-created ACPI HID device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextAcpi (
+  IN CHAR16 *TextDeviceNode,
+  IN UINT32  PnPId
+  )
+{
+  CHAR16                *UIDStr;
+  ACPI_HID_DEVICE_PATH  *Acpi;
+
+  UIDStr = GetNextParamStr (&TextDeviceNode);
+  Acpi   = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode (
+                                      ACPI_DEVICE_PATH,
+                                      ACPI_DP,
+                                      (UINT16) sizeof (ACPI_HID_DEVICE_PATH)
+                                      );
+
+  Acpi->HID = EFI_PNP_ID (PnPId);
+  Acpi->UID = (UINT32) Strtoi (UIDStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Acpi;
+}
+
+/**
+  Converts a text device path node to PCI root device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created PCI root device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPciRoot (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextAcpi (TextDeviceNode, 0x0a03);
+}
+
+/**
+  Converts a text device path node to PCIE root device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created PCIE root device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPcieRoot (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextAcpi (TextDeviceNode, 0x0a08);
+}
+
+/**
+  Converts a text device path node to Floppy device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Floppy device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFloppy (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextAcpi (TextDeviceNode, 0x0604);
+}
+
+/**
+  Converts a text device path node to Keyboard device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created  Keyboard device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextKeyboard (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextAcpi (TextDeviceNode, 0x0301);
+}
+
+/**
+  Converts a text device path node to Serial device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Serial device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSerial (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextAcpi (TextDeviceNode, 0x0501);
+}
+
+/**
+  Converts a text device path node to Parallel Port device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Parallel Port device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextParallelPort (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextAcpi (TextDeviceNode, 0x0401);
+}
+
+/**
+  Converts a text device path node to ACPI extension device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created ACPI extension device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiEx (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                         *HIDStr;
+  CHAR16                         *CIDStr;
+  CHAR16                         *UIDStr;
+  CHAR16                         *HIDSTRStr;
+  CHAR16                         *CIDSTRStr;
+  CHAR16                         *UIDSTRStr;
+  CHAR8                          *AsciiStr;
+  UINT16                         Length;
+  ACPI_EXTENDED_HID_DEVICE_PATH  *AcpiEx;
+
+  HIDStr    = GetNextParamStr (&TextDeviceNode);
+  CIDStr    = GetNextParamStr (&TextDeviceNode);
+  UIDStr    = GetNextParamStr (&TextDeviceNode);
+  HIDSTRStr = GetNextParamStr (&TextDeviceNode);
+  CIDSTRStr = GetNextParamStr (&TextDeviceNode);
+  UIDSTRStr = GetNextParamStr (&TextDeviceNode);
+
+  Length    = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (HIDSTRStr) + 1);
+  Length    = (UINT16) (Length + StrLen (UIDSTRStr) + 1);
+  Length    = (UINT16) (Length + StrLen (CIDSTRStr) + 1);
+  AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode (
+                                               ACPI_DEVICE_PATH,
+                                               ACPI_EXTENDED_DP,
+                                               Length
+                                               );
+
+  AcpiEx->HID = EisaIdFromText (HIDStr);
+  AcpiEx->CID = EisaIdFromText (CIDStr);
+  AcpiEx->UID = (UINT32) Strtoi (UIDStr);
+
+  AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
+  StrToAscii (HIDSTRStr, &AsciiStr);
+  StrToAscii (UIDSTRStr, &AsciiStr);
+  StrToAscii (CIDSTRStr, &AsciiStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx;
+}
+
+/**
+  Converts a text device path node to ACPI extension device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created ACPI extension device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiExp (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                         *HIDStr;
+  CHAR16                         *CIDStr;
+  CHAR16                         *UIDSTRStr;
+  CHAR8                          *AsciiStr;
+  UINT16                         Length;
+  ACPI_EXTENDED_HID_DEVICE_PATH  *AcpiEx;
+
+  HIDStr    = GetNextParamStr (&TextDeviceNode);
+  CIDStr    = GetNextParamStr (&TextDeviceNode);
+  UIDSTRStr = GetNextParamStr (&TextDeviceNode);
+  Length    = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (UIDSTRStr) + 3);
+  AcpiEx    = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode (
+                                                  ACPI_DEVICE_PATH,
+                                                  ACPI_EXTENDED_DP,
+                                                  Length
+                                                  );
+
+  AcpiEx->HID = EisaIdFromText (HIDStr);
+  AcpiEx->CID = EisaIdFromText (CIDStr);
+  AcpiEx->UID = 0;
+
+  AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
+  //
+  // HID string is NULL
+  //
+  *AsciiStr = '\0';
+  //
+  // Convert UID string
+  //
+  AsciiStr++;
+  StrToAscii (UIDSTRStr, &AsciiStr);
+  //
+  // CID string is NULL
+  //
+  *AsciiStr = '\0';
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx;
+}
+
+/**
+  Converts a text device path node to ACPI _ADR device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created ACPI _ADR device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiAdr (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                *DisplayDeviceStr;
+  ACPI_ADR_DEVICE_PATH  *AcpiAdr;
+  UINTN                 Index;
+  UINTN                 Length;
+
+  AcpiAdr = (ACPI_ADR_DEVICE_PATH *) CreateDeviceNode (
+                                       ACPI_DEVICE_PATH,
+                                       ACPI_ADR_DP,
+                                       (UINT16) sizeof (ACPI_ADR_DEVICE_PATH)
+                                       );
+  ASSERT (AcpiAdr != NULL);
+
+  for (Index = 0; ; Index++) {
+    DisplayDeviceStr = GetNextParamStr (&TextDeviceNode);
+    if (IS_NULL (*DisplayDeviceStr)) {
+      break;
+    }
+    if (Index > 0) {
+      Length  = DevicePathNodeLength (AcpiAdr);
+      AcpiAdr = ReallocatePool (
+                  Length,
+                  Length + sizeof (UINT32),
+                  AcpiAdr
+                  );
+      ASSERT (AcpiAdr != NULL);
+      SetDevicePathNodeLength (AcpiAdr, Length + sizeof (UINT32));
+    }
+
+    (&AcpiAdr->ADR)[Index] = (UINT32) Strtoi (DisplayDeviceStr);
+  }
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr;
+}
+
+/**
+  Converts a generic messaging text device path node to messaging device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to messaging device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMsg (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return DevPathFromTextGenericPath (MESSAGING_DEVICE_PATH, TextDeviceNode);
+}
+
+/**
+  Converts a text device path node to Parallel Port device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Parallel Port device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAta (
+IN CHAR16 *TextDeviceNode
+)
+{
+  CHAR16            *PrimarySecondaryStr;
+  CHAR16            *SlaveMasterStr;
+  CHAR16            *LunStr;
+  ATAPI_DEVICE_PATH *Atapi;
+
+  Atapi = (ATAPI_DEVICE_PATH *) CreateDeviceNode (
+    MESSAGING_DEVICE_PATH,
+    MSG_ATAPI_DP,
+    (UINT16) sizeof (ATAPI_DEVICE_PATH)
+    );
+
+  PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode);
+  SlaveMasterStr      = GetNextParamStr (&TextDeviceNode);
+  LunStr              = GetNextParamStr (&TextDeviceNode);
+
+  if (StrCmp (PrimarySecondaryStr, "Primary") == 0) {
+    Atapi->PrimarySecondary = 0;
+  } else if (StrCmp (PrimarySecondaryStr, "Secondary") == 0) {
+    Atapi->PrimarySecondary = 1;
+  } else {
+    Atapi->PrimarySecondary = (UINT8) Strtoi (PrimarySecondaryStr);
+  }
+  if (StrCmp (SlaveMasterStr, "Master") == 0) {
+    Atapi->SlaveMaster      = 0;
+  } else if (StrCmp (SlaveMasterStr, "Slave") == 0) {
+    Atapi->SlaveMaster      = 1;
+  } else {
+    Atapi->SlaveMaster      = (UINT8) Strtoi (SlaveMasterStr);
+  }
+
+  Atapi->Lun                = (UINT16) Strtoi (LunStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Atapi;
+}
+
+/**
+  Converts a text device path node to SCSI device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created SCSI device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextScsi (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *PunStr;
+  CHAR16            *LunStr;
+  SCSI_DEVICE_PATH  *Scsi;
+
+  PunStr = GetNextParamStr (&TextDeviceNode);
+  LunStr = GetNextParamStr (&TextDeviceNode);
+  Scsi   = (SCSI_DEVICE_PATH *) CreateDeviceNode (
+                                   MESSAGING_DEVICE_PATH,
+                                   MSG_SCSI_DP,
+                                   (UINT16) sizeof (SCSI_DEVICE_PATH)
+                                   );
+
+  Scsi->Pun = (UINT16) Strtoi (PunStr);
+  Scsi->Lun = (UINT16) Strtoi (LunStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Scsi;
+}
+
+/**
+  Converts a text device path node to Fibre device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Fibre device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFibre (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                    *WWNStr;
+  CHAR16                    *LunStr;
+  FIBRECHANNEL_DEVICE_PATH  *Fibre;
+
+  WWNStr = GetNextParamStr (&TextDeviceNode);
+  LunStr = GetNextParamStr (&TextDeviceNode);
+  Fibre  = (FIBRECHANNEL_DEVICE_PATH *) CreateDeviceNode (
+                                          MESSAGING_DEVICE_PATH,
+                                          MSG_FIBRECHANNEL_DP,
+                                          (UINT16) sizeof (FIBRECHANNEL_DEVICE_PATH)
+                                          );
+
+  Fibre->Reserved = 0;
+  Strtoi64 (WWNStr, &Fibre->WWN);
+  Strtoi64 (LunStr, &Fibre->Lun);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Fibre;
+}
+
+/**
+  Converts a text device path node to FibreEx device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created FibreEx device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFibreEx (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                      *WWNStr;
+  CHAR16                      *LunStr;
+  FIBRECHANNELEX_DEVICE_PATH  *FibreEx;
+
+  WWNStr  = GetNextParamStr (&TextDeviceNode);
+  LunStr  = GetNextParamStr (&TextDeviceNode);
+  FibreEx = (FIBRECHANNELEX_DEVICE_PATH *) CreateDeviceNode (
+                                             MESSAGING_DEVICE_PATH,
+                                             MSG_FIBRECHANNELEX_DP,
+                                             (UINT16) sizeof (FIBRECHANNELEX_DEVICE_PATH)
+                                             );
+
+  FibreEx->Reserved = 0;
+  Strtoi64 (WWNStr, (UINT64 *) (&FibreEx->WWN));
+  Strtoi64 (LunStr, (UINT64 *) (&FibreEx->Lun));
+
+  *(UINT64 *) (&FibreEx->WWN) = SwapBytes64 (*(UINT64 *) (&FibreEx->WWN));
+  *(UINT64 *) (&FibreEx->Lun) = SwapBytes64 (*(UINT64 *) (&FibreEx->Lun));
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) FibreEx;
+}
+
+/**
+  Converts a text device path node to 1394 device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created 1394 device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromText1394 (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *GuidStr;
+  F1394_DEVICE_PATH *F1394DevPath;
+
+  GuidStr = GetNextParamStr (&TextDeviceNode);
+  F1394DevPath  = (F1394_DEVICE_PATH *) CreateDeviceNode (
+                                          MESSAGING_DEVICE_PATH,
+                                          MSG_1394_DP,
+                                          (UINT16) sizeof (F1394_DEVICE_PATH)
+                                          );
+
+  F1394DevPath->Reserved = 0;
+  F1394DevPath->Guid     = StrHexToUint64 (GuidStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) F1394DevPath;
+}
+
+/**
+  Converts a text device path node to USB device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsb (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16          *PortStr;
+  CHAR16          *InterfaceStr;
+  USB_DEVICE_PATH *Usb;
+
+  PortStr               = GetNextParamStr (&TextDeviceNode);
+  InterfaceStr          = GetNextParamStr (&TextDeviceNode);
+  Usb                   = (USB_DEVICE_PATH *) CreateDeviceNode (
+                                                MESSAGING_DEVICE_PATH,
+                                                MSG_USB_DP,
+                                                (UINT16) sizeof (USB_DEVICE_PATH)
+                                                );
+
+  Usb->ParentPortNumber = (UINT8) Strtoi (PortStr);
+  Usb->InterfaceNumber  = (UINT8) Strtoi (InterfaceStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Usb;
+}
+
+/**
+  Converts a text device path node to I20 device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created I20 device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextI2O (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16          *TIDStr;
+  I2O_DEVICE_PATH *I2ODevPath;
+
+  TIDStr     = GetNextParamStr (&TextDeviceNode);
+  I2ODevPath = (I2O_DEVICE_PATH *) CreateDeviceNode (
+                                    MESSAGING_DEVICE_PATH,
+                                    MSG_I2O_DP,
+                                    (UINT16) sizeof (I2O_DEVICE_PATH)
+                                    );
+
+  I2ODevPath->Tid  = (UINT32) Strtoi (TIDStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) I2ODevPath;
+}
+
+/**
+  Converts a text device path node to Infini Band device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Infini Band device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextInfiniband (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                  *FlagsStr;
+  CHAR16                  *GuidStr;
+  CHAR16                  *SidStr;
+  CHAR16                  *TidStr;
+  CHAR16                  *DidStr;
+  INFINIBAND_DEVICE_PATH  *InfiniBand;
+
+  FlagsStr   = GetNextParamStr (&TextDeviceNode);
+  GuidStr    = GetNextParamStr (&TextDeviceNode);
+  SidStr     = GetNextParamStr (&TextDeviceNode);
+  TidStr     = GetNextParamStr (&TextDeviceNode);
+  DidStr     = GetNextParamStr (&TextDeviceNode);
+  InfiniBand = (INFINIBAND_DEVICE_PATH *) CreateDeviceNode (
+                                            MESSAGING_DEVICE_PATH,
+                                            MSG_INFINIBAND_DP,
+                                            (UINT16) sizeof (INFINIBAND_DEVICE_PATH)
+                                            );
+
+  InfiniBand->ResourceFlags = (UINT32) Strtoi (FlagsStr);
+  StrToGuid (GuidStr, (EFI_GUID *) InfiniBand->PortGid);
+  Strtoi64 (SidStr, &InfiniBand->ServiceId);
+  Strtoi64 (TidStr, &InfiniBand->TargetPortId);
+  Strtoi64 (DidStr, &InfiniBand->DeviceId);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) InfiniBand;
+}
+
+/**
+  Converts a text device path node to Vendor-Defined Messaging device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Vendor-Defined Messaging device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenMsg (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextVendor (
+            TextDeviceNode,
+            MESSAGING_DEVICE_PATH,
+            MSG_VENDOR_DP
+            );
+}
+
+/**
+  Converts a text device path node to Vendor defined PC-ANSI device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Vendor defined PC-ANSI device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenPcAnsi (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  VENDOR_DEVICE_PATH  *Vendor;
+
+  Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+                                    MESSAGING_DEVICE_PATH,
+                                    MSG_VENDOR_DP,
+                                    (UINT16) sizeof (VENDOR_DEVICE_PATH));
+  CopyGuid (&Vendor->Guid, &gEfiPcAnsiGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+  Converts a text device path node to Vendor defined VT100 device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Vendor defined VT100 device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenVt100 (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  VENDOR_DEVICE_PATH  *Vendor;
+
+  Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+                                    MESSAGING_DEVICE_PATH,
+                                    MSG_VENDOR_DP,
+                                    (UINT16) sizeof (VENDOR_DEVICE_PATH));
+  CopyGuid (&Vendor->Guid, &gEfiVT100Guid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+  Converts a text device path node to Vendor defined VT100 Plus device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Vendor defined VT100 Plus device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenVt100Plus (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  VENDOR_DEVICE_PATH  *Vendor;
+
+  Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+                                    MESSAGING_DEVICE_PATH,
+                                    MSG_VENDOR_DP,
+                                    (UINT16) sizeof (VENDOR_DEVICE_PATH));
+  CopyGuid (&Vendor->Guid, &gEfiVT100PlusGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+  Converts a text device path node to Vendor defined UTF8 device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Vendor defined UTF8 device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenUtf8 (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  VENDOR_DEVICE_PATH  *Vendor;
+
+  Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+                                    MESSAGING_DEVICE_PATH,
+                                    MSG_VENDOR_DP,
+                                    (UINT16) sizeof (VENDOR_DEVICE_PATH));
+  CopyGuid (&Vendor->Guid, &gEfiVTUTF8Guid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+  Converts a text device path node to UART Flow Control device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created UART Flow Control device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUartFlowCtrl (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                        *ValueStr;
+  UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl;
+
+  ValueStr        = GetNextParamStr (&TextDeviceNode);
+  UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) CreateDeviceNode (
+                                                        MESSAGING_DEVICE_PATH,
+                                                        MSG_VENDOR_DP,
+                                                        (UINT16) sizeof (UART_FLOW_CONTROL_DEVICE_PATH)
+                                                        );
+
+  CopyGuid (&UartFlowControl->Guid, &gEfiUartDevicePathGuid);
+  if (StrCmp (ValueStr, "XonXoff") == 0) {
+    UartFlowControl->FlowControlMap = 2;
+  } else if (StrCmp (ValueStr, "Hardware") == 0) {
+    UartFlowControl->FlowControlMap = 1;
+  } else {
+    UartFlowControl->FlowControlMap = 0;
+  }
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) UartFlowControl;
+}
+
+/**
+  Converts a text device path node to Serial Attached SCSI device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Serial Attached SCSI device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSAS (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16          *AddressStr;
+  CHAR16          *LunStr;
+  CHAR16          *RTPStr;
+  CHAR16          *SASSATAStr;
+  CHAR16          *LocationStr;
+  CHAR16          *ConnectStr;
+  CHAR16          *DriveBayStr;
+  CHAR16          *ReservedStr;
+  UINT16          Info;
+  UINT16          Uint16;
+  SAS_DEVICE_PATH *Sas;
+
+  AddressStr  = GetNextParamStr (&TextDeviceNode);
+  LunStr      = GetNextParamStr (&TextDeviceNode);
+  RTPStr      = GetNextParamStr (&TextDeviceNode);
+  SASSATAStr  = GetNextParamStr (&TextDeviceNode);
+  LocationStr = GetNextParamStr (&TextDeviceNode);
+  ConnectStr  = GetNextParamStr (&TextDeviceNode);
+  DriveBayStr = GetNextParamStr (&TextDeviceNode);
+  ReservedStr = GetNextParamStr (&TextDeviceNode);
+  Sas         = (SAS_DEVICE_PATH *) CreateDeviceNode (
+                                       MESSAGING_DEVICE_PATH,
+                                       MSG_VENDOR_DP,
+                                       (UINT16) sizeof (SAS_DEVICE_PATH)
+                                       );
+
+  CopyGuid (&Sas->Guid, &gEfiSasDevicePathGuid);
+  Strtoi64 (AddressStr, &Sas->SasAddress);
+  Strtoi64 (LunStr, &Sas->Lun);
+  Sas->RelativeTargetPort = (UINT16) Strtoi (RTPStr);
+
+  if (StrCmp (SASSATAStr, "NoTopology") == 0) {
+    Info = 0x0;
+
+  } else if ((StrCmp (SASSATAStr, "SATA") == 0) || (StrCmp (SASSATAStr, "SAS") == 0)) {
+
+    Uint16 = (UINT16) Strtoi (DriveBayStr);
+    if (Uint16 == 0) {
+      Info = 0x1;
+    } else {
+      Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
+    }
+
+    if (StrCmp (SASSATAStr, "SATA") == 0) {
+      Info |= BIT4;
+    }
+
+    //
+    // Location is an integer between 0 and 1 or else
+    // the keyword Internal (0) or External (1).
+    //
+    if (StrCmp (LocationStr, "External") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (LocationStr, "Internal") == 0) {
+      Uint16 = 0;
+    } else {
+      Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0);
+    }
+    Info |= (Uint16 << 5);
+
+    //
+    // Connect is an integer between 0 and 3 or else
+    // the keyword Direct (0) or Expanded (1).
+    //
+    if (StrCmp (ConnectStr, "Expanded") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (ConnectStr, "Direct") == 0) {
+      Uint16 = 0;
+    } else {
+      Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1));
+    }
+    Info |= (Uint16 << 6);
+
+  } else {
+    Info = (UINT16) Strtoi (SASSATAStr);
+  }
+
+  Sas->DeviceTopology = Info;
+  Sas->Reserved       = (UINT32) Strtoi (ReservedStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Sas;
+}
+
+/**
+  Converts a text device path node to Serial Attached SCSI Ex device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Serial Attached SCSI Ex device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSasEx (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *AddressStr;
+  CHAR16            *LunStr;
+  CHAR16            *RTPStr;
+  CHAR16            *SASSATAStr;
+  CHAR16            *LocationStr;
+  CHAR16            *ConnectStr;
+  CHAR16            *DriveBayStr;
+  UINT16            Info;
+  UINT16            Uint16;
+  UINT64            SasAddress;
+  UINT64            Lun;
+  SASEX_DEVICE_PATH *SasEx;
+
+  AddressStr  = GetNextParamStr (&TextDeviceNode);
+  LunStr      = GetNextParamStr (&TextDeviceNode);
+  RTPStr      = GetNextParamStr (&TextDeviceNode);
+  SASSATAStr  = GetNextParamStr (&TextDeviceNode);
+  LocationStr = GetNextParamStr (&TextDeviceNode);
+  ConnectStr  = GetNextParamStr (&TextDeviceNode);
+  DriveBayStr = GetNextParamStr (&TextDeviceNode);
+  SasEx       = (SASEX_DEVICE_PATH *) CreateDeviceNode (
+                                        MESSAGING_DEVICE_PATH,
+                                        MSG_SASEX_DP,
+                                        (UINT16) sizeof (SASEX_DEVICE_PATH)
+                                        );
+
+  Strtoi64 (AddressStr, &SasAddress);
+  Strtoi64 (LunStr,     &Lun);
+  WriteUnaligned64 ((UINT64 *) &SasEx->SasAddress, SwapBytes64 (SasAddress));
+  WriteUnaligned64 ((UINT64 *) &SasEx->Lun,        SwapBytes64 (Lun));
+  SasEx->RelativeTargetPort      = (UINT16) Strtoi (RTPStr);
+
+  if (StrCmp (SASSATAStr, "NoTopology") == 0) {
+    Info = 0x0;
+
+  } else if ((StrCmp (SASSATAStr, "SATA") == 0) || (StrCmp (SASSATAStr, "SAS") == 0)) {
+
+    Uint16 = (UINT16) Strtoi (DriveBayStr);
+    if (Uint16 == 0) {
+      Info = 0x1;
+    } else {
+      Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
+    }
+
+    if (StrCmp (SASSATAStr, "SATA") == 0) {
+      Info |= BIT4;
+    }
+
+    //
+    // Location is an integer between 0 and 1 or else
+    // the keyword Internal (0) or External (1).
+    //
+    if (StrCmp (LocationStr, "External") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (LocationStr, "Internal") == 0) {
+      Uint16 = 0;
+    } else {
+      Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0);
+    }
+    Info |= (Uint16 << 5);
+
+    //
+    // Connect is an integer between 0 and 3 or else
+    // the keyword Direct (0) or Expanded (1).
+    //
+    if (StrCmp (ConnectStr, "Expanded") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (ConnectStr, "Direct") == 0) {
+      Uint16 = 0;
+    } else {
+      Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1));
+    }
+    Info |= (Uint16 << 6);
+
+  } else {
+    Info = (UINT16) Strtoi (SASSATAStr);
+  }
+
+  SasEx->DeviceTopology = Info;
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) SasEx;
+}
+
+/**
+  Converts a text device path node to NVM Express Namespace device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created NVM Express Namespace device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextNVMe (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                     *NamespaceIdStr;
+  CHAR16                     *NamespaceUuidStr;
+  NVME_NAMESPACE_DEVICE_PATH *Nvme;
+  UINT8                      *Uuid;
+  UINTN                      Index;
+
+  NamespaceIdStr   = GetNextParamStr (&TextDeviceNode);
+  NamespaceUuidStr = GetNextParamStr (&TextDeviceNode);
+  Nvme = (NVME_NAMESPACE_DEVICE_PATH *) CreateDeviceNode (
+    MESSAGING_DEVICE_PATH,
+    MSG_NVME_NAMESPACE_DP,
+    (UINT16) sizeof (NVME_NAMESPACE_DEVICE_PATH)
+    );
+
+  Nvme->NamespaceId = (UINT32) Strtoi (NamespaceIdStr);
+  Uuid = (UINT8 *) &Nvme->NamespaceUuid;
+
+  Index = sizeof (Nvme->NamespaceUuid) / sizeof (UINT8);
+  while (Index-- != 0) {
+    Uuid[Index] = (UINT8) StrHexToUintn (SplitStr (&NamespaceUuidStr, '-'));
+  }
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Nvme;
+}
+
+/**
+  Converts a text device path node to UFS device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created UFS device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUfs (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *PunStr;
+  CHAR16            *LunStr;
+  UFS_DEVICE_PATH   *Ufs;
+
+  PunStr = GetNextParamStr (&TextDeviceNode);
+  LunStr = GetNextParamStr (&TextDeviceNode);
+  Ufs    = (UFS_DEVICE_PATH *) CreateDeviceNode (
+                                 MESSAGING_DEVICE_PATH,
+                                 MSG_UFS_DP,
+                                 (UINT16) sizeof (UFS_DEVICE_PATH)
+                                 );
+
+  Ufs->Pun = (UINT8) Strtoi (PunStr);
+  Ufs->Lun = (UINT8) Strtoi (LunStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Ufs;
+}
+
+/**
+  Converts a text device path node to SD (Secure Digital) device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created SD device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSd (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *SlotNumberStr;
+  SD_DEVICE_PATH    *Sd;
+
+  SlotNumberStr = GetNextParamStr (&TextDeviceNode);
+  Sd            = (SD_DEVICE_PATH *) CreateDeviceNode (
+                                       MESSAGING_DEVICE_PATH,
+                                       MSG_SD_DP,
+                                       (UINT16) sizeof (SD_DEVICE_PATH)
+                                       );
+
+  Sd->SlotNumber = (UINT8) Strtoi (SlotNumberStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Sd;
+}
+
+/**
+  Converts a text device path node to EMMC (Embedded MMC) device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created EMMC device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextEmmc (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *SlotNumberStr;
+  EMMC_DEVICE_PATH  *Emmc;
+
+  SlotNumberStr = GetNextParamStr (&TextDeviceNode);
+  Emmc          = (EMMC_DEVICE_PATH *) CreateDeviceNode (
+                                       MESSAGING_DEVICE_PATH,
+                                       MSG_EMMC_DP,
+                                       (UINT16) sizeof (EMMC_DEVICE_PATH)
+                                       );
+
+  Emmc->SlotNumber = (UINT8) Strtoi (SlotNumberStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Emmc;
+}
+
+/**
+  Converts a text device path node to Debug Port device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Debug Port device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextDebugPort (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  VENDOR_DEFINED_MESSAGING_DEVICE_PATH  *Vend;
+
+  Vend = (VENDOR_DEFINED_MESSAGING_DEVICE_PATH *) CreateDeviceNode (
+                                                    MESSAGING_DEVICE_PATH,
+                                                    MSG_VENDOR_DP,
+                                                    (UINT16) sizeof (VENDOR_DEFINED_MESSAGING_DEVICE_PATH)
+                                                    );
+
+  CopyGuid (&Vend->Guid, &gEfiDebugPortProtocolGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Vend;
+}
+
+/**
+  Converts a text device path node to MAC device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created MAC device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMAC (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                *AddressStr;
+  CHAR16                *IfTypeStr;
+  UINTN                 Length;
+  MAC_ADDR_DEVICE_PATH  *MACDevPath;
+
+  AddressStr    = GetNextParamStr (&TextDeviceNode);
+  IfTypeStr     = GetNextParamStr (&TextDeviceNode);
+  MACDevPath    = (MAC_ADDR_DEVICE_PATH *) CreateDeviceNode (
+                                              MESSAGING_DEVICE_PATH,
+                                              MSG_MAC_ADDR_DP,
+                                              (UINT16) sizeof (MAC_ADDR_DEVICE_PATH)
+                                              );
+
+  MACDevPath->IfType   = (UINT8) Strtoi (IfTypeStr);
+
+  Length = sizeof (EFI_MAC_ADDRESS);
+  StrHexToBytes (AddressStr, Length * 2, MACDevPath->MacAddress.Addr, Length);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) MACDevPath;
+}
+
+
+/**
+  Converts a text format to the network protocol ID.
+
+  @param Text  String of protocol field.
+
+  @return Network protocol ID .
+
+**/
+static
+UINTN
+NetworkProtocolFromText (
+  IN CHAR16 *Text
+  )
+{
+  if (StrCmp (Text, "UDP") == 0) {
+    return RFC_1700_UDP_PROTOCOL;
+  }
+
+  if (StrCmp (Text, "TCP") == 0) {
+    return RFC_1700_TCP_PROTOCOL;
+  }
+
+  return Strtoi (Text);
+}
+
+
+/**
+  Converts a text device path node to IPV4 device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created IPV4 device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextIPv4 (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *RemoteIPStr;
+  CHAR16            *ProtocolStr;
+  CHAR16            *TypeStr;
+  CHAR16            *LocalIPStr;
+  CHAR16            *GatewayIPStr;
+  CHAR16            *SubnetMaskStr;
+  IPv4_DEVICE_PATH  *IPv4;
+
+  RemoteIPStr           = GetNextParamStr (&TextDeviceNode);
+  ProtocolStr           = GetNextParamStr (&TextDeviceNode);
+  TypeStr               = GetNextParamStr (&TextDeviceNode);
+  LocalIPStr            = GetNextParamStr (&TextDeviceNode);
+  GatewayIPStr          = GetNextParamStr (&TextDeviceNode);
+  SubnetMaskStr         = GetNextParamStr (&TextDeviceNode);
+  IPv4                  = (IPv4_DEVICE_PATH *) CreateDeviceNode (
+                                                 MESSAGING_DEVICE_PATH,
+                                                 MSG_IPv4_DP,
+                                                 (UINT16) sizeof (IPv4_DEVICE_PATH)
+                                                 );
+
+  StrToIpv4Address (RemoteIPStr, NULL, &IPv4->RemoteIpAddress, NULL);
+  IPv4->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr);
+  if (StrCmp (TypeStr, "Static") == 0) {
+    IPv4->StaticIpAddress = TRUE;
+  } else {
+    IPv4->StaticIpAddress = FALSE;
+  }
+
+  StrToIpv4Address (LocalIPStr, NULL, &IPv4->LocalIpAddress, NULL);
+  if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*SubnetMaskStr)) {
+    StrToIpv4Address (GatewayIPStr,  NULL, &IPv4->GatewayIpAddress, NULL);
+    StrToIpv4Address (SubnetMaskStr, NULL, &IPv4->SubnetMask,       NULL);
+  } else {
+    ZeroMem (&IPv4->GatewayIpAddress, sizeof (IPv4->GatewayIpAddress));
+    ZeroMem (&IPv4->SubnetMask,    sizeof (IPv4->SubnetMask));
+  }
+
+  IPv4->LocalPort       = 0;
+  IPv4->RemotePort      = 0;
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) IPv4;
+}
+
+/**
+  Converts a text device path node to IPV6 device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created IPV6 device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextIPv6 (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *RemoteIPStr;
+  CHAR16            *ProtocolStr;
+  CHAR16            *TypeStr;
+  CHAR16            *LocalIPStr;
+  CHAR16            *GatewayIPStr;
+  CHAR16            *PrefixLengthStr;
+  IPv6_DEVICE_PATH  *IPv6;
+
+  RemoteIPStr           = GetNextParamStr (&TextDeviceNode);
+  ProtocolStr           = GetNextParamStr (&TextDeviceNode);
+  TypeStr               = GetNextParamStr (&TextDeviceNode);
+  LocalIPStr            = GetNextParamStr (&TextDeviceNode);
+  PrefixLengthStr       = GetNextParamStr (&TextDeviceNode);
+  GatewayIPStr          = GetNextParamStr (&TextDeviceNode);
+  IPv6                  = (IPv6_DEVICE_PATH *) CreateDeviceNode (
+                                                 MESSAGING_DEVICE_PATH,
+                                                 MSG_IPv6_DP,
+                                                 (UINT16) sizeof (IPv6_DEVICE_PATH)
+                                                 );
+
+  StrToIpv6Address (RemoteIPStr, NULL, &IPv6->RemoteIpAddress, NULL);
+  IPv6->Protocol        = (UINT16) NetworkProtocolFromText (ProtocolStr);
+  if (StrCmp (TypeStr, "Static") == 0) {
+    IPv6->IpAddressOrigin = 0;
+  } else if (StrCmp (TypeStr, "StatelessAutoConfigure") == 0) {
+    IPv6->IpAddressOrigin = 1;
+  } else {
+    IPv6->IpAddressOrigin = 2;
+  }
+
+  StrToIpv6Address (LocalIPStr, NULL, &IPv6->LocalIpAddress, NULL);
+  if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*PrefixLengthStr)) {
+    StrToIpv6Address (GatewayIPStr, NULL, &IPv6->GatewayIpAddress, NULL);
+    IPv6->PrefixLength = (UINT8) Strtoi (PrefixLengthStr);
+  } else {
+    ZeroMem (&IPv6->GatewayIpAddress, sizeof (IPv6->GatewayIpAddress));
+    IPv6->PrefixLength = 0;
+  }
+
+  IPv6->LocalPort       = 0;
+  IPv6->RemotePort      = 0;
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) IPv6;
+}
+
+/**
+  Converts a text device path node to UART device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created UART device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUart (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *BaudStr;
+  CHAR16            *DataBitsStr;
+  CHAR16            *ParityStr;
+  CHAR16            *StopBitsStr;
+  UART_DEVICE_PATH  *Uart;
+
+  BaudStr         = GetNextParamStr (&TextDeviceNode);
+  DataBitsStr     = GetNextParamStr (&TextDeviceNode);
+  ParityStr       = GetNextParamStr (&TextDeviceNode);
+  StopBitsStr     = GetNextParamStr (&TextDeviceNode);
+  Uart            = (UART_DEVICE_PATH *) CreateDeviceNode (
+                                           MESSAGING_DEVICE_PATH,
+                                           MSG_UART_DP,
+                                           (UINT16) sizeof (UART_DEVICE_PATH)
+                                           );
+
+  if (StrCmp (BaudStr, "DEFAULT") == 0) {
+    Uart->BaudRate = 115200;
+  } else {
+    Strtoi64 (BaudStr, &Uart->BaudRate);
+  }
+  Uart->DataBits  = (UINT8) ((StrCmp (DataBitsStr, "DEFAULT") == 0) ? 8 : Strtoi (DataBitsStr));
+  switch (*ParityStr) {
+  case 'D':
+    Uart->Parity = 0;
+    break;
+
+  case 'N':
+    Uart->Parity = 1;
+    break;
+
+  case 'E':
+    Uart->Parity = 2;
+    break;
+
+  case 'O':
+    Uart->Parity = 3;
+    break;
+
+  case 'M':
+    Uart->Parity = 4;
+    break;
+
+  case 'S':
+    Uart->Parity = 5;
+    break;
+
+  default:
+    Uart->Parity = (UINT8) Strtoi (ParityStr);
+    break;
+  }
+
+  if (StrCmp (StopBitsStr, "D") == 0) {
+    Uart->StopBits = (UINT8) 0;
+  } else if (StrCmp (StopBitsStr, "1") == 0) {
+    Uart->StopBits = (UINT8) 1;
+  } else if (StrCmp (StopBitsStr, "1.5") == 0) {
+    Uart->StopBits = (UINT8) 2;
+  } else if (StrCmp (StopBitsStr, "2") == 0) {
+    Uart->StopBits = (UINT8) 3;
+  } else {
+    Uart->StopBits = (UINT8) Strtoi (StopBitsStr);
+  }
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Uart;
+}
+
+/**
+  Converts a text device path node to USB class device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+  @param UsbClassText    A pointer to USB_CLASS_TEXT structure to be integrated to USB Class Text.
+
+  @return A pointer to the newly-created USB class device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextUsbClass (
+  IN CHAR16         *TextDeviceNode,
+  IN USB_CLASS_TEXT *UsbClassText
+  )
+{
+  CHAR16                *VIDStr;
+  CHAR16                *PIDStr;
+  CHAR16                *ClassStr;
+  CHAR16                *SubClassStr;
+  CHAR16                *ProtocolStr;
+  USB_CLASS_DEVICE_PATH *UsbClass;
+
+  UsbClass    = (USB_CLASS_DEVICE_PATH *) CreateDeviceNode (
+                                            MESSAGING_DEVICE_PATH,
+                                            MSG_USB_CLASS_DP,
+                                            (UINT16) sizeof (USB_CLASS_DEVICE_PATH)
+                                            );
+
+  VIDStr      = GetNextParamStr (&TextDeviceNode);
+  PIDStr      = GetNextParamStr (&TextDeviceNode);
+  if (UsbClassText->ClassExist) {
+    ClassStr = GetNextParamStr (&TextDeviceNode);
+    UsbClass->DeviceClass = (UINT8) Strtoi (ClassStr);
+  } else {
+    UsbClass->DeviceClass = UsbClassText->Class;
+  }
+  if (UsbClassText->SubClassExist) {
+    SubClassStr = GetNextParamStr (&TextDeviceNode);
+    UsbClass->DeviceSubClass = (UINT8) Strtoi (SubClassStr);
+  } else {
+    UsbClass->DeviceSubClass = UsbClassText->SubClass;
+  }
+
+  ProtocolStr = GetNextParamStr (&TextDeviceNode);
+
+  UsbClass->VendorId        = (UINT16) Strtoi (VIDStr);
+  UsbClass->ProductId       = (UINT16) Strtoi (PIDStr);
+  UsbClass->DeviceProtocol  = (UINT8) Strtoi (ProtocolStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) UsbClass;
+}
+
+
+/**
+  Converts a text device path node to USB class device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB class device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbClass (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = TRUE;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB audio device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB audio device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbAudio (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_AUDIO;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB CDC Control device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB CDC Control device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbCDCControl (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_CDCCONTROL;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB HID device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB HID device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbHID (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_HID;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB Image device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB Image device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbImage (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_IMAGE;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB Print device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB Print device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbPrinter (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_PRINTER;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB mass storage device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB mass storage device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbMassStorage (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_MASS_STORAGE;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB HUB device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB HUB device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbHub (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_HUB;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB CDC data device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB CDC data device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbCDCData (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_CDCDATA;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB smart card device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB smart card device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbSmartCard (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_SMART_CARD;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB video device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB video device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbVideo (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_VIDEO;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB diagnostic device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB diagnostic device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbDiagnostic (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_DIAGNOSTIC;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB wireless device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB wireless device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbWireless (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_WIRELESS;
+  UsbClassText.SubClassExist = TRUE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB device firmware update device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB device firmware update device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbDeviceFirmwareUpdate (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_RESERVE;
+  UsbClassText.SubClassExist = FALSE;
+  UsbClassText.SubClass      = USB_SUBCLASS_FW_UPDATE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB IRDA bridge device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB IRDA bridge device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbIrdaBridge (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_RESERVE;
+  UsbClassText.SubClassExist = FALSE;
+  UsbClassText.SubClass      = USB_SUBCLASS_IRDA_BRIDGE;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB text and measurement device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB text and measurement device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbTestAndMeasurement (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  USB_CLASS_TEXT  UsbClassText;
+
+  UsbClassText.ClassExist    = FALSE;
+  UsbClassText.Class         = USB_CLASS_RESERVE;
+  UsbClassText.SubClassExist = FALSE;
+  UsbClassText.SubClass      = USB_SUBCLASS_TEST;
+
+  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+  Converts a text device path node to USB WWID device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created USB WWID device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbWwid (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                *VIDStr;
+  CHAR16                *PIDStr;
+  CHAR16                *InterfaceNumStr;
+  CHAR16                *SerialNumberStr;
+  USB_WWID_DEVICE_PATH  *UsbWwid;
+  UINTN                 SerialNumberStrLen;
+
+  VIDStr                   = GetNextParamStr (&TextDeviceNode);
+  PIDStr                   = GetNextParamStr (&TextDeviceNode);
+  InterfaceNumStr          = GetNextParamStr (&TextDeviceNode);
+  SerialNumberStr          = GetNextParamStr (&TextDeviceNode);
+  SerialNumberStrLen       = StrLen (SerialNumberStr);
+  if (SerialNumberStrLen >= 2 &&
+      SerialNumberStr[0] == '\"' &&
+      SerialNumberStr[SerialNumberStrLen - 1] == '\"'
+    ) {
+    SerialNumberStr[SerialNumberStrLen - 1] = '\0';
+    SerialNumberStr++;
+    SerialNumberStrLen -= 2;
+  }
+  UsbWwid                  = (USB_WWID_DEVICE_PATH *) CreateDeviceNode (
+                                                         MESSAGING_DEVICE_PATH,
+                                                         MSG_USB_WWID_DP,
+                                                         (UINT16) (sizeof (USB_WWID_DEVICE_PATH) + SerialNumberStrLen * sizeof (CHAR16))
+                                                         );
+  UsbWwid->VendorId        = (UINT16) Strtoi (VIDStr);
+  UsbWwid->ProductId       = (UINT16) Strtoi (PIDStr);
+  UsbWwid->InterfaceNumber = (UINT16) Strtoi (InterfaceNumStr);
+
+  //
+  // There is no memory allocated in UsbWwid for the '\0' in SerialNumberStr.
+  // Therefore, the '\0' will not be copied.
+  //
+  CopyMem (
+    (UINT8 *) UsbWwid + sizeof (USB_WWID_DEVICE_PATH),
+    SerialNumberStr,
+    SerialNumberStrLen * sizeof (CHAR16)
+    );
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) UsbWwid;
+}
+
+/**
+  Converts a text device path node to Logic Unit device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Logic Unit device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUnit (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                          *LunStr;
+  DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
+
+  LunStr      = GetNextParamStr (&TextDeviceNode);
+  LogicalUnit = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) CreateDeviceNode (
+                                                      MESSAGING_DEVICE_PATH,
+                                                      MSG_DEVICE_LOGICAL_UNIT_DP,
+                                                      (UINT16) sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH)
+                                                      );
+
+  LogicalUnit->Lun  = (UINT8) Strtoi (LunStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) LogicalUnit;
+}
+
+/**
+  Converts a text device path node to iSCSI device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created iSCSI device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextiSCSI (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  UINT16                      Options;
+  CHAR16                      *NameStr;
+  CHAR16                      *PortalGroupStr;
+  CHAR16                      *LunStr;
+  CHAR16                      *HeaderDigestStr;
+  CHAR16                      *DataDigestStr;
+  CHAR16                      *AuthenticationStr;
+  CHAR16                      *ProtocolStr;
+  CHAR8                       *AsciiStr;
+  ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath;
+
+  NameStr           = GetNextParamStr (&TextDeviceNode);
+  PortalGroupStr    = GetNextParamStr (&TextDeviceNode);
+  LunStr            = GetNextParamStr (&TextDeviceNode);
+  HeaderDigestStr   = GetNextParamStr (&TextDeviceNode);
+  DataDigestStr     = GetNextParamStr (&TextDeviceNode);
+  AuthenticationStr = GetNextParamStr (&TextDeviceNode);
+  ProtocolStr       = GetNextParamStr (&TextDeviceNode);
+  ISCSIDevPath      = (ISCSI_DEVICE_PATH_WITH_NAME *) CreateDeviceNode (
+                                                        MESSAGING_DEVICE_PATH,
+                                                        MSG_ISCSI_DP,
+                                                        (UINT16) (sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + StrLen (NameStr))
+                                                        );
+
+  AsciiStr = ISCSIDevPath->TargetName;
+  StrToAscii (NameStr, &AsciiStr);
+
+  ISCSIDevPath->TargetPortalGroupTag = (UINT16) Strtoi (PortalGroupStr);
+  Strtoi64 (LunStr, &ISCSIDevPath->Lun);
+
+  Options = 0x0000;
+  if (StrCmp (HeaderDigestStr, "CRC32C") == 0) {
+    Options |= 0x0002;
+  }
+
+  if (StrCmp (DataDigestStr, "CRC32C") == 0) {
+    Options |= 0x0008;
+  }
+
+  if (StrCmp (AuthenticationStr, "None") == 0) {
+    Options |= 0x0800;
+  }
+
+  if (StrCmp (AuthenticationStr, "CHAP_UNI") == 0) {
+    Options |= 0x1000;
+  }
+
+  ISCSIDevPath->LoginOption      = (UINT16) Options;
+
+  ISCSIDevPath->NetworkProtocol  = (UINT16) StrCmp (ProtocolStr, "TCP");
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) ISCSIDevPath;
+}
+
+/**
+  Converts a text device path node to VLAN device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created VLAN device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVlan (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *VlanStr;
+  VLAN_DEVICE_PATH  *Vlan;
+
+  VlanStr = GetNextParamStr (&TextDeviceNode);
+  Vlan    = (VLAN_DEVICE_PATH *) CreateDeviceNode (
+                                   MESSAGING_DEVICE_PATH,
+                                   MSG_VLAN_DP,
+                                   (UINT16) sizeof (VLAN_DEVICE_PATH)
+                                   );
+
+  Vlan->VlanId = (UINT16) Strtoi (VlanStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Vlan;
+}
+
+/**
+  Converts a text device path node to Bluetooth device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Bluetooth device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBluetooth (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                  *BluetoothStr;
+  CHAR16                  *Walker;
+  CHAR16                  *TempNumBuffer;
+  UINTN                   TempBufferSize;
+  INT32                   Index;
+  BLUETOOTH_DEVICE_PATH   *BluetoothDp;
+
+  BluetoothStr = GetNextParamStr (&TextDeviceNode);
+  BluetoothDp = (BLUETOOTH_DEVICE_PATH *) CreateDeviceNode (
+                                   MESSAGING_DEVICE_PATH,
+                                   MSG_BLUETOOTH_DP,
+                                   (UINT16) sizeof (BLUETOOTH_DEVICE_PATH)
+                                   );
+
+  Index = sizeof (BLUETOOTH_ADDRESS) - 1;
+  Walker = BluetoothStr;
+  while (!IS_NULL(*Walker) && Index >= 0) {
+    TempBufferSize = 2 * sizeof(CHAR16) + StrSize("0x");
+    TempNumBuffer = AllocateZeroPool (TempBufferSize);
+    if (TempNumBuffer == NULL) {
+      break;
+    }
+    StrCpyS (TempNumBuffer, TempBufferSize / sizeof (CHAR16), "0x");
+    StrnCatS (TempNumBuffer, TempBufferSize / sizeof (CHAR16), Walker, 2);
+    BluetoothDp->BD_ADDR.Address[Index] = (UINT8)Strtoi (TempNumBuffer);
+    FreePool (TempNumBuffer);
+    Walker += 2;
+    Index--;
+  }
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) BluetoothDp;
+}
+
+/**
+  Converts a text device path node to Wi-Fi device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Wi-Fi device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextWiFi (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                *SSIdStr;
+  CHAR8                 AsciiStr[33];
+  UINTN                 DataLen;
+  WIFI_DEVICE_PATH      *WiFiDp;
+
+  SSIdStr = GetNextParamStr (&TextDeviceNode);
+  WiFiDp  = (WIFI_DEVICE_PATH *) CreateDeviceNode (
+                                   MESSAGING_DEVICE_PATH,
+                                   MSG_WIFI_DP,
+                                   (UINT16) sizeof (WIFI_DEVICE_PATH)
+                                   );
+
+  if (NULL != SSIdStr) {
+    DataLen = StrLen (SSIdStr);
+    if (StrLen (SSIdStr) > 32) {
+      SSIdStr[32] = '\0';
+      DataLen     = 32;
+    }
+
+    UnicodeStrToAsciiStrS (SSIdStr, AsciiStr, sizeof (AsciiStr));
+    CopyMem (WiFiDp->SSId, AsciiStr, DataLen);
+  }
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) WiFiDp;
+}
+
+/**
+  Converts a text device path node to URI device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created URI device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUri (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16           *UriStr;
+  UINTN            UriLength;
+  URI_DEVICE_PATH  *Uri;
+
+  UriStr = GetNextParamStr (&TextDeviceNode);
+  UriLength = StrnLenS (UriStr, MAX_UINT16 - sizeof (URI_DEVICE_PATH));
+  Uri    = (URI_DEVICE_PATH *) CreateDeviceNode (
+                                 MESSAGING_DEVICE_PATH,
+                                 MSG_URI_DP,
+                                 (UINT16) (sizeof (URI_DEVICE_PATH) + UriLength)
+                                 );
+
+  while (UriLength-- != 0) {
+    Uri->Uri[UriLength] = (CHAR8) UriStr[UriLength];
+  }
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Uri;
+}
+
+/**
+  Converts a media text device path node to media device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to media device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMediaPath (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return DevPathFromTextGenericPath (MEDIA_DEVICE_PATH, TextDeviceNode);
+}
+
+/**
+  Converts a text device path node to HD device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created HD device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextHD (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                *PartitionStr;
+  CHAR16                *TypeStr;
+  CHAR16                *SignatureStr;
+  CHAR16                *StartStr;
+  CHAR16                *SizeStr;
+  UINT32                Signature32;
+  HARDDRIVE_DEVICE_PATH *Hd;
+
+  PartitionStr        = GetNextParamStr (&TextDeviceNode);
+  TypeStr             = GetNextParamStr (&TextDeviceNode);
+  SignatureStr        = GetNextParamStr (&TextDeviceNode);
+  StartStr            = GetNextParamStr (&TextDeviceNode);
+  SizeStr             = GetNextParamStr (&TextDeviceNode);
+  Hd                  = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode (
+                                                    MEDIA_DEVICE_PATH,
+                                                    MEDIA_HARDDRIVE_DP,
+                                                    (UINT16) sizeof (HARDDRIVE_DEVICE_PATH)
+                                                    );
+
+  Hd->PartitionNumber = (UINT32) Strtoi (PartitionStr);
+
+  ZeroMem (Hd->Signature, 16);
+  Hd->MBRType = (UINT8) 0;
+
+  if (StrCmp (TypeStr, "MBR") == 0) {
+    Hd->SignatureType = SIGNATURE_TYPE_MBR;
+    Hd->MBRType       = 0x01;
+
+    Signature32       = (UINT32) Strtoi (SignatureStr);
+    CopyMem (Hd->Signature, &Signature32, sizeof (UINT32));
+  } else if (StrCmp (TypeStr, "GPT") == 0) {
+    Hd->SignatureType = SIGNATURE_TYPE_GUID;
+    Hd->MBRType       = 0x02;
+
+    StrToGuid (SignatureStr, (EFI_GUID *) Hd->Signature);
+  } else {
+    Hd->SignatureType = (UINT8) Strtoi (TypeStr);
+  }
+
+  Strtoi64 (StartStr, &Hd->PartitionStart);
+  Strtoi64 (SizeStr, &Hd->PartitionSize);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Hd;
+}
+
+/**
+  Converts a text device path node to CDROM device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created CDROM device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextCDROM (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16            *EntryStr;
+  CHAR16            *StartStr;
+  CHAR16            *SizeStr;
+  CDROM_DEVICE_PATH *CDROMDevPath;
+
+  EntryStr              = GetNextParamStr (&TextDeviceNode);
+  StartStr              = GetNextParamStr (&TextDeviceNode);
+  SizeStr               = GetNextParamStr (&TextDeviceNode);
+  CDROMDevPath          = (CDROM_DEVICE_PATH *) CreateDeviceNode (
+                                                  MEDIA_DEVICE_PATH,
+                                                  MEDIA_CDROM_DP,
+                                                  (UINT16) sizeof (CDROM_DEVICE_PATH)
+                                                  );
+
+  CDROMDevPath->BootEntry = (UINT32) Strtoi (EntryStr);
+  Strtoi64 (StartStr, &CDROMDevPath->PartitionStart);
+  Strtoi64 (SizeStr, &CDROMDevPath->PartitionSize);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) CDROMDevPath;
+}
+
+/**
+  Converts a text device path node to Vendor-defined media device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Vendor-defined media device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenMedia (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextVendor (
+           TextDeviceNode,
+           MEDIA_DEVICE_PATH,
+           MEDIA_VENDOR_DP
+           );
+}
+
+#ifndef __DragonFly__
+/**
+  Converts a text device path node to File device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created File device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFilePath (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  FILEPATH_DEVICE_PATH  *File;
+
+  File = (FILEPATH_DEVICE_PATH *) CreateDeviceNode (
+                                    MEDIA_DEVICE_PATH,
+                                    MEDIA_FILEPATH_DP,
+                                    (UINT16) (sizeof (FILEPATH_DEVICE_PATH) + StrLen (TextDeviceNode) * 2)
+                                    );
+
+  StrCpyS (File->PathName, StrLen (TextDeviceNode) + 1, TextDeviceNode);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) File;
+}
+#endif
+
+/**
+  Converts a text device path node to Media protocol device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Media protocol device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMedia (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                      *GuidStr;
+  MEDIA_PROTOCOL_DEVICE_PATH  *Media;
+
+  GuidStr = GetNextParamStr (&TextDeviceNode);
+  Media   = (MEDIA_PROTOCOL_DEVICE_PATH *) CreateDeviceNode (
+                                             MEDIA_DEVICE_PATH,
+                                             MEDIA_PROTOCOL_DP,
+                                             (UINT16) sizeof (MEDIA_PROTOCOL_DEVICE_PATH)
+                                             );
+
+  StrToGuid (GuidStr, &Media->Protocol);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Media;
+}
+
+/**
+  Converts a text device path node to firmware volume device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created firmware volume device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFv (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                    *GuidStr;
+  MEDIA_FW_VOL_DEVICE_PATH  *Fv;
+
+  GuidStr = GetNextParamStr (&TextDeviceNode);
+  Fv      = (MEDIA_FW_VOL_DEVICE_PATH *) CreateDeviceNode (
+                                           MEDIA_DEVICE_PATH,
+                                           MEDIA_PIWG_FW_VOL_DP,
+                                           (UINT16) sizeof (MEDIA_FW_VOL_DEVICE_PATH)
+                                           );
+
+  StrToGuid (GuidStr, &Fv->FvName);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Fv;
+}
+
+/**
+  Converts a text device path node to firmware file device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created firmware file device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFvFile (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                             *GuidStr;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFile;
+
+  GuidStr = GetNextParamStr (&TextDeviceNode);
+  FvFile  = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) CreateDeviceNode (
+                                                    MEDIA_DEVICE_PATH,
+                                                    MEDIA_PIWG_FW_FILE_DP,
+                                                    (UINT16) sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)
+                                                    );
+
+  StrToGuid (GuidStr, &FvFile->FvFileName);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) FvFile;
+}
+
+/**
+  Converts a text device path node to text relative offset device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Text device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextRelativeOffsetRange (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                                  *StartingOffsetStr;
+  CHAR16                                  *EndingOffsetStr;
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
+
+  StartingOffsetStr = GetNextParamStr (&TextDeviceNode);
+  EndingOffsetStr   = GetNextParamStr (&TextDeviceNode);
+  Offset            = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) CreateDeviceNode (
+                                                                    MEDIA_DEVICE_PATH,
+                                                                    MEDIA_RELATIVE_OFFSET_RANGE_DP,
+                                                                    (UINT16) sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)
+                                                                    );
+
+  Strtoi64 (StartingOffsetStr, &Offset->StartingOffset);
+  Strtoi64 (EndingOffsetStr, &Offset->EndingOffset);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Offset;
+}
+
+/**
+  Converts a text device path node to text ram disk device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Text device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextRamDisk (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                                  *StartingAddrStr;
+  CHAR16                                  *EndingAddrStr;
+  CHAR16                                  *TypeGuidStr;
+  CHAR16                                  *InstanceStr;
+  MEDIA_RAM_DISK_DEVICE_PATH              *RamDisk;
+  UINT64                                  StartingAddr;
+  UINT64                                  EndingAddr;
+
+  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
+  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
+  InstanceStr     = GetNextParamStr (&TextDeviceNode);
+  TypeGuidStr     = GetNextParamStr (&TextDeviceNode);
+  RamDisk         = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode (
+                                                     MEDIA_DEVICE_PATH,
+                                                     MEDIA_RAM_DISK_DP,
+                                                     (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
+                                                     );
+
+  Strtoi64 (StartingAddrStr, &StartingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr);
+  Strtoi64 (EndingAddrStr, &EndingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr);
+  RamDisk->Instance = (UINT16) Strtoi (InstanceStr);
+  StrToGuid (TypeGuidStr, &RamDisk->TypeGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk;
+}
+
+/**
+  Converts a text device path node to text virtual disk device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Text device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVirtualDisk (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                                  *StartingAddrStr;
+  CHAR16                                  *EndingAddrStr;
+  CHAR16                                  *InstanceStr;
+  MEDIA_RAM_DISK_DEVICE_PATH              *RamDisk;
+  UINT64                                  StartingAddr;
+  UINT64                                  EndingAddr;
+
+  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
+  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
+  InstanceStr     = GetNextParamStr (&TextDeviceNode);
+
+  RamDisk         = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode (
+                                                     MEDIA_DEVICE_PATH,
+                                                     MEDIA_RAM_DISK_DP,
+                                                     (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
+                                                     );
+
+  Strtoi64 (StartingAddrStr, &StartingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr);
+  Strtoi64 (EndingAddrStr, &EndingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr);
+  RamDisk->Instance = (UINT16) Strtoi (InstanceStr);
+  CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk;
+}
+
+/**
+  Converts a text device path node to text virtual cd device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Text device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVirtualCd (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                                  *StartingAddrStr;
+  CHAR16                                  *EndingAddrStr;
+  CHAR16                                  *InstanceStr;
+  MEDIA_RAM_DISK_DEVICE_PATH              *RamDisk;
+  UINT64                                  StartingAddr;
+  UINT64                                  EndingAddr;
+
+  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
+  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
+  InstanceStr     = GetNextParamStr (&TextDeviceNode);
+
+  RamDisk         = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode (
+                                                     MEDIA_DEVICE_PATH,
+                                                     MEDIA_RAM_DISK_DP,
+                                                     (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
+                                                     );
+
+  Strtoi64 (StartingAddrStr, &StartingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr);
+  Strtoi64 (EndingAddrStr, &EndingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr);
+  RamDisk->Instance = (UINT16) Strtoi (InstanceStr);
+  CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk;
+}
+
+/**
+  Converts a text device path node to text persistent virtual disk device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Text device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPersistentVirtualDisk (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                                  *StartingAddrStr;
+  CHAR16                                  *EndingAddrStr;
+  CHAR16                                  *InstanceStr;
+  MEDIA_RAM_DISK_DEVICE_PATH              *RamDisk;
+  UINT64                                  StartingAddr;
+  UINT64                                  EndingAddr;
+
+  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
+  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
+  InstanceStr     = GetNextParamStr (&TextDeviceNode);
+
+  RamDisk         = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode (
+                                                     MEDIA_DEVICE_PATH,
+                                                     MEDIA_RAM_DISK_DP,
+                                                     (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
+                                                     );
+
+  Strtoi64 (StartingAddrStr, &StartingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr);
+  Strtoi64 (EndingAddrStr, &EndingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr);
+  RamDisk->Instance = (UINT16) Strtoi (InstanceStr);
+  CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk;
+}
+
+/**
+  Converts a text device path node to text persistent virtual cd device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created Text device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPersistentVirtualCd (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                                  *StartingAddrStr;
+  CHAR16                                  *EndingAddrStr;
+  CHAR16                                  *InstanceStr;
+  MEDIA_RAM_DISK_DEVICE_PATH              *RamDisk;
+  UINT64                                  StartingAddr;
+  UINT64                                  EndingAddr;
+
+  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
+  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
+  InstanceStr     = GetNextParamStr (&TextDeviceNode);
+
+  RamDisk         = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode (
+                                                     MEDIA_DEVICE_PATH,
+                                                     MEDIA_RAM_DISK_DP,
+                                                     (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
+                                                     );
+
+  Strtoi64 (StartingAddrStr, &StartingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr);
+  Strtoi64 (EndingAddrStr, &EndingAddr);
+  WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr);
+  RamDisk->Instance = (UINT16) Strtoi (InstanceStr);
+  CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk;
+}
+
+/**
+  Converts a BBS text device path node to BBS device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to BBS device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBbsPath (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  return DevPathFromTextGenericPath (BBS_DEVICE_PATH, TextDeviceNode);
+}
+
+/**
+  Converts a text device path node to BIOS Boot Specification device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created BIOS Boot Specification device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBBS (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16              *TypeStr;
+  CHAR16              *IdStr;
+  CHAR16              *FlagsStr;
+  CHAR8               *AsciiStr;
+  BBS_BBS_DEVICE_PATH *Bbs;
+
+  TypeStr   = GetNextParamStr (&TextDeviceNode);
+  IdStr     = GetNextParamStr (&TextDeviceNode);
+  FlagsStr  = GetNextParamStr (&TextDeviceNode);
+  Bbs       = (BBS_BBS_DEVICE_PATH *) CreateDeviceNode (
+                                        BBS_DEVICE_PATH,
+                                        BBS_BBS_DP,
+                                        (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) + StrLen (IdStr))
+                                        );
+
+  if (StrCmp (TypeStr, "Floppy") == 0) {
+    Bbs->DeviceType = BBS_TYPE_FLOPPY;
+  } else if (StrCmp (TypeStr, "HD") == 0) {
+    Bbs->DeviceType = BBS_TYPE_HARDDRIVE;
+  } else if (StrCmp (TypeStr, "CDROM") == 0) {
+    Bbs->DeviceType = BBS_TYPE_CDROM;
+  } else if (StrCmp (TypeStr, "PCMCIA") == 0) {
+    Bbs->DeviceType = BBS_TYPE_PCMCIA;
+  } else if (StrCmp (TypeStr, "USB") == 0) {
+    Bbs->DeviceType = BBS_TYPE_USB;
+  } else if (StrCmp (TypeStr, "Network") == 0) {
+    Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK;
+  } else {
+    Bbs->DeviceType = (UINT16) Strtoi (TypeStr);
+  }
+
+  AsciiStr = Bbs->String;
+  StrToAscii (IdStr, &AsciiStr);
+
+  Bbs->StatusFlag = (UINT16) Strtoi (FlagsStr);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Bbs;
+}
+
+/**
+  Converts a text device path node to SATA device path structure.
+
+  @param TextDeviceNode  The input Text device path node.
+
+  @return A pointer to the newly-created SATA device path structure.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSata (
+  IN CHAR16 *TextDeviceNode
+  )
+{
+  SATA_DEVICE_PATH *Sata;
+  CHAR16           *Param1;
+  CHAR16           *Param2;
+  CHAR16           *Param3;
+
+  Param1 = GetNextParamStr (&TextDeviceNode);
+  Param2 = GetNextParamStr (&TextDeviceNode);
+  Param3 = GetNextParamStr (&TextDeviceNode);
+
+  Sata = (SATA_DEVICE_PATH *) CreateDeviceNode (
+                                MESSAGING_DEVICE_PATH,
+                                MSG_SATA_DP,
+                                (UINT16) sizeof (SATA_DEVICE_PATH)
+                                );
+  Sata->HBAPortNumber            = (UINT16) Strtoi (Param1);
+  Sata->PortMultiplierPortNumber = (UINT16) Strtoi (Param2);
+  Sata->Lun                      = (UINT16) Strtoi (Param3);
+
+  return (EFI_DEVICE_PATH_PROTOCOL *) Sata;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_FROM_TEXT_TABLE mUefiDevicePathLibDevPathFromTextTable[] = {
+  {"Path",                    DevPathFromTextPath                    },
+
+  {"HardwarePath",            DevPathFromTextHardwarePath            },
+  {"Pci",                     DevPathFromTextPci                     },
+  {"PcCard",                  DevPathFromTextPcCard                  },
+  {"MemoryMapped",            DevPathFromTextMemoryMapped            },
+  {"VenHw",                   DevPathFromTextVenHw                   },
+  {"Ctrl",                    DevPathFromTextCtrl                    },
+  {"BMC",                     DevPathFromTextBmc                     },
+
+  {"AcpiPath",                DevPathFromTextAcpiPath                },
+  {"Acpi",                    DevPathFromTextAcpi                    },
+  {"PciRoot",                 DevPathFromTextPciRoot                 },
+  {"PcieRoot",                DevPathFromTextPcieRoot                },
+  {"Floppy",                  DevPathFromTextFloppy                  },
+  {"Keyboard",                DevPathFromTextKeyboard                },
+  {"Serial",                  DevPathFromTextSerial                  },
+  {"ParallelPort",            DevPathFromTextParallelPort            },
+  {"AcpiEx",                  DevPathFromTextAcpiEx                  },
+  {"AcpiExp",                 DevPathFromTextAcpiExp                 },
+  {"AcpiAdr",                 DevPathFromTextAcpiAdr                 },
+
+  {"Msg",                     DevPathFromTextMsg                     },
+  {"Ata",                     DevPathFromTextAta                     },
+  {"Scsi",                    DevPathFromTextScsi                    },
+  {"Fibre",                   DevPathFromTextFibre                   },
+  {"FibreEx",                 DevPathFromTextFibreEx                 },
+  {"I1394",                   DevPathFromText1394                    },
+  {"USB",                     DevPathFromTextUsb                     },
+  {"I2O",                     DevPathFromTextI2O                     },
+  {"Infiniband",              DevPathFromTextInfiniband              },
+  {"VenMsg",                  DevPathFromTextVenMsg                  },
+  {"VenPcAnsi",               DevPathFromTextVenPcAnsi               },
+  {"VenVt100",                DevPathFromTextVenVt100                },
+  {"VenVt100Plus",            DevPathFromTextVenVt100Plus            },
+  {"VenUtf8",                 DevPathFromTextVenUtf8                 },
+  {"UartFlowCtrl",            DevPathFromTextUartFlowCtrl            },
+  {"SAS",                     DevPathFromTextSAS                     },
+  {"SasEx",                   DevPathFromTextSasEx                   },
+  {"NVMe",                    DevPathFromTextNVMe                    },
+  {"UFS",                     DevPathFromTextUfs                     },
+  {"SD",                      DevPathFromTextSd                      },
+  {"eMMC",                    DevPathFromTextEmmc                    },
+  {"DebugPort",               DevPathFromTextDebugPort               },
+  {"MAC",                     DevPathFromTextMAC                     },
+  {"IPv4",                    DevPathFromTextIPv4                    },
+  {"IPv6",                    DevPathFromTextIPv6                    },
+  {"Uart",                    DevPathFromTextUart                    },
+  {"UsbClass",                DevPathFromTextUsbClass                },
+  {"UsbAudio",                DevPathFromTextUsbAudio                },
+  {"UsbCDCControl",           DevPathFromTextUsbCDCControl           },
+  {"UsbHID",                  DevPathFromTextUsbHID                  },
+  {"UsbImage",                DevPathFromTextUsbImage                },
+  {"UsbPrinter",              DevPathFromTextUsbPrinter              },
+  {"UsbMassStorage",          DevPathFromTextUsbMassStorage          },
+  {"UsbHub",                  DevPathFromTextUsbHub                  },
+  {"UsbCDCData",              DevPathFromTextUsbCDCData              },
+  {"UsbSmartCard",            DevPathFromTextUsbSmartCard            },
+  {"UsbVideo",                DevPathFromTextUsbVideo                },
+  {"UsbDiagnostic",           DevPathFromTextUsbDiagnostic           },
+  {"UsbWireless",             DevPathFromTextUsbWireless             },
+  {"UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate },
+  {"UsbIrdaBridge",           DevPathFromTextUsbIrdaBridge           },
+  {"UsbTestAndMeasurement",   DevPathFromTextUsbTestAndMeasurement   },
+  {"UsbWwid",                 DevPathFromTextUsbWwid                 },
+  {"Unit",                    DevPathFromTextUnit                    },
+  {"iSCSI",                   DevPathFromTextiSCSI                   },
+  {"Vlan",                    DevPathFromTextVlan                    },
+  {"Uri",                     DevPathFromTextUri                     },
+  {"Bluetooth",               DevPathFromTextBluetooth               },
+  {"Wi-Fi",                   DevPathFromTextWiFi                    },
+  {"MediaPath",               DevPathFromTextMediaPath               },
+  {"HD",                      DevPathFromTextHD                      },
+  {"CDROM",                   DevPathFromTextCDROM                   },
+  {"VenMedia",                DevPathFromTextVenMedia                },
+  {"Media",                   DevPathFromTextMedia                   },
+  {"Fv",                      DevPathFromTextFv                      },
+  {"FvFile",                  DevPathFromTextFvFile                  },
+  {"Offset",                  DevPathFromTextRelativeOffsetRange     },
+  {"RamDisk",                 DevPathFromTextRamDisk                 },
+  {"VirtualDisk",             DevPathFromTextVirtualDisk             },
+  {"VirtualCD",               DevPathFromTextVirtualCd               },
+  {"PersistentVirtualDisk",   DevPathFromTextPersistentVirtualDisk   },
+  {"PersistentVirtualCD",     DevPathFromTextPersistentVirtualCd     },
+
+  {"BbsPath",                 DevPathFromTextBbsPath                 },
+  {"BBS",                     DevPathFromTextBBS                     },
+  {"Sata",                    DevPathFromTextSata                    },
+  {NULL, NULL}
+};
+
+/**
+  Convert text to the binary representation of a device node.
+
+  @param TextDeviceNode  TextDeviceNode points to the text representation of a device
+                         node. Conversion starts with the first character and continues
+                         until the first non-device node character.
+
+  @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
+          insufficient memory or text unsupported.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibConvertTextToDeviceNode (
+  IN CONST CHAR16 *TextDeviceNode
+  )
+{
+  DEVICE_PATH_FROM_TEXT    FromText;
+  CHAR16                   *ParamStr;
+  EFI_DEVICE_PATH_PROTOCOL *DeviceNode;
+  CHAR16                   *DeviceNodeStr;
+  UINTN                    Index;
+
+  if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) {
+    return NULL;
+  }
+
+  ParamStr      = NULL;
+  FromText      = NULL;
+  DeviceNodeStr = UefiDevicePathLibStrDuplicate (TextDeviceNode);
+  ASSERT (DeviceNodeStr != NULL);
+
+  for (Index = 0; mUefiDevicePathLibDevPathFromTextTable[Index].Function != NULL; Index++) {
+    ParamStr = GetParamByNodeName (DeviceNodeStr, mUefiDevicePathLibDevPathFromTextTable[Index].DevicePathNodeText);
+    if (ParamStr != NULL) {
+      FromText = mUefiDevicePathLibDevPathFromTextTable[Index].Function;
+      break;
+    }
+  }
+
+#ifndef __DragonFly__
+  if (FromText == NULL) {
+    //
+    // A file path
+    //
+    FromText = DevPathFromTextFilePath;
+    DeviceNode = FromText (DeviceNodeStr);
+  } else {
+#else
+  {
+#endif
+    DeviceNode = FromText (ParamStr);
+    FreePool (ParamStr);
+  }
+
+  FreePool (DeviceNodeStr);
+
+  return DeviceNode;
+}
+
+/**
+  Convert text to the binary representation of a device path.
+
+
+  @param TextDevicePath  TextDevicePath points to the text representation of a device
+                         path. Conversion starts with the first character and continues
+                         until the first non-device node character.
+
+  @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
+          there was insufficient memory.
+
+**/
+static
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibConvertTextToDevicePath (
+  IN CONST CHAR16 *TextDevicePath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL *DeviceNode;
+  EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+  CHAR16                   *DevicePathStr;
+  CHAR16                   *Str;
+  CHAR16                   *DeviceNodeStr;
+  BOOLEAN                  IsInstanceEnd;
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+  if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) {
+    return NULL;
+  }
+
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
+  ASSERT (DevicePath != NULL);
+  SetDevicePathEndNode (DevicePath);
+
+  DevicePathStr = UefiDevicePathLibStrDuplicate (TextDevicePath);
+
+  Str           = DevicePathStr;
+  while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) {
+    DeviceNode = UefiDevicePathLibConvertTextToDeviceNode (DeviceNodeStr);
+
+    NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode);
+    FreePool (DevicePath);
+    FreePool (DeviceNode);
+    DevicePath = NewDevicePath;
+
+    if (IsInstanceEnd) {
+      DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
+      ASSERT (DeviceNode != NULL);
+      SetDevicePathEndNode (DeviceNode);
+      // Fix from https://bugzilla.tianocore.org/show_bug.cgi?id=419
+      DeviceNode->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
+
+      NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode);
+      FreePool (DevicePath);
+      FreePool (DeviceNode);
+      DevicePath = NewDevicePath;
+    }
+  }
+
+  FreePool (DevicePathStr);
+  return DevicePath;
+}
+
+ssize_t
+efidp_parse_device_path(char *path, efidp out, size_t max)
+{
+	EFI_DEVICE_PATH_PROTOCOL *dp;
+	UINTN len;
+
+	dp = UefiDevicePathLibConvertTextToDevicePath (path);
+	if (dp == NULL)
+		return -1;
+	len = GetDevicePathSize(dp);
+	if (len > max) {
+		free(dp);
+		return -1;
+	}
+	memcpy(out, dp, len);
+	free(dp);
+
+	return len;
+}
diff --git a/lib/libefivar/efivar-dp.h b/lib/libefivar/efivar-dp.h
new file mode 100644
index 0000000000..5f60e1d07f
--- /dev/null
+++ b/lib/libefivar/efivar-dp.h
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: head/lib/libefivar/efivar-dp.h 314926 2017-03-09 00:31:31Z imp $
+ */
+
+#ifndef	_EFIVAR_DP_H_
+#define	_EFIVAR_DP_H_
+
+/*
+ * "Linux compatible" efivar-dp.h header. At the moment, it's really a
+ * very thin, minimal interface.
+ */
+
+/*
+ * Generic EFI_DEVICE_PATH, spelled the Linux way. We use this
+ * interface to the outside world and type-pun to the EFI EDK2 code
+ * we use to implement it.
+ */
+typedef struct {
+	uint8_t type;
+	uint8_t subtype;
+	uint16_t length;
+} __packed efidp_header;
+
+/* NB: Linux has shadow types for all dp type */
+
+typedef union {
+        efidp_header header;
+} efidp_data;
+typedef efidp_data *efidp;
+typedef const efidp_data *const_efidp;
+
+/** format a device path into UEFI standard conforming output.
+ *
+ * NB: FreeBSD's implementation is taken from EDK2, while Linux's
+ * was hand-rolled. There may be differences as a result.
+ */
+ssize_t efidp_format_device_path(char *buf, size_t len, const_efidp dp,
+    ssize_t max);
+ssize_t efidp_parse_device_path(char *path, efidp out, size_t max);
+
+#endif /* _EFIVAR_DP_H_ */
diff --git a/lib/libefivar/efivar.3 b/lib/libefivar/efivar.3
index a017981164..fe976d2c22 100644
--- a/lib/libefivar/efivar.3
+++ b/lib/libefivar/efivar.3
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD: head/lib/libefivar/efivar.3 307071 2016-10-11 22:30:41Z imp $
 .\"
-.Dd September 14, 2016
+.Dd March 20, 2017
 .Dt LIBEFIVAR 3
 .Os
 .Sh NAME
@@ -92,6 +92,7 @@ and
 .Fn efi_guid_to_symbol
 This function is not actually implemented.
 .Sh SEE ALSO
+.Xr efidp 8 ,
 .Xr efivar 8
 .Sh AUTHORS
 .An -nosplit
diff --git a/lib/libefivar/efivar.c b/lib/libefivar/efivar.c
index 6936e738ed..0f182fe1d2 100644
--- a/lib/libefivar/efivar.c
+++ b/lib/libefivar/efivar.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/libefivar/efivar.c 307189 2016-10-13 06:56:23Z imp $");
+__FBSDID("$FreeBSD: head/lib/libefivar/efivar.c 314925 2017-03-09 00:24:01Z imp $");
 
 #include <efivar.h>
 #include <sys/efiio.h>
@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD: head/lib/libefivar/efivar.c 307189 2016-10-13 06:56:23Z imp
 #include <stdlib.h>
 #include <string.h>
 
-#include "libefivar_int.h"
+#include "efichar.h"
 
 static int efi_fd = -2;
 
@@ -44,12 +44,7 @@ static int efi_fd = -2;
 
 const efi_guid_t efi_guid_empty = Z;
 
-static struct uuid_table
-{
-	const char *uuid_str;
-	const char *name;
-	efi_guid_t guid;
-} guid_tbl [] =
+static struct uuid_table guid_tbl [] =
 {
 	{ "00000000-0000-0000-0000-000000000000", "zero", Z },
 	{ "093e0fae-a6c4-4f50-9f1b-d41e2b89c19a", "sha512", Z },
@@ -92,7 +87,10 @@ efi_guid_tbl_compile(void)
 {
 	size_t i;
 	uint32_t status;
+	static int done = 0;
 
+	if (done)
+		return;
 	for (i = 0; i < nitems(guid_tbl); i++) {
 		uuid_from_string(guid_tbl[i].uuid_str, &guid_tbl[i].guid,
 		    &status);
@@ -101,6 +99,15 @@ efi_guid_tbl_compile(void)
 			fprintf(stderr, "Can't convert %s to a uuid for %s: %d\n",
 			    guid_tbl[i].uuid_str, guid_tbl[i].name, (int)status);
 	}
+	done = 1;
+}
+
+int
+efi_known_guid(struct uuid_table **tbl)
+{
+
+	*tbl = guid_tbl;
+	return (nitems(guid_tbl));
 }
 
 static int
@@ -132,10 +139,7 @@ rv_to_linux_rv(int rv)
 {
 	if (rv == 0)
 		rv = 1;
-	else if (errno == ENOENT) {
-		rv = 0;
-		errno = 0;
-	} else
+	else
 		rv = -errno;
 	return (rv);
 }
@@ -169,7 +173,7 @@ efi_get_variable(efi_guid_t guid, const char *name,
 		return -1;
 
 	efi_var_reset(&var);
-	rv = libefi_utf8_to_ucs2(name, &var.name, &var.namesize);
+	rv = utf8_to_ucs2(name, &var.name, &var.namesize);
 	if (rv != 0)
 		goto errout;
 	var.vendor = guid;
@@ -221,7 +225,6 @@ efi_get_next_variable_name(efi_guid_t **guid, char **name)
 	if (efi_open_dev() == -1)
 		return -1;
 
-
 	if (buf == NULL)
 		buf = malloc(buflen);
 
@@ -233,7 +236,7 @@ again:
 		*buf = 0;
 		/* GUID zeroed in var_reset */
 	} else {
-		rv = libefi_utf8_to_ucs2(*name, &var.name, &size);
+		rv = utf8_to_ucs2(*name, &var.name, &size);
 		if (rv != 0)
 			goto errout;
 		var.vendor = **guid;
@@ -257,7 +260,7 @@ again:
 	if (rv == 0) {
 		*name = NULL; /* XXX */
 		var.name[var.namesize / sizeof(efi_char)] = 0;	/* EFI doesn't NUL terminate */
-		rv = libefi_ucs2_to_utf8(var.name, name);
+		rv = ucs2_to_utf8(var.name, name);
 		if (rv != 0)
 			goto errout;
 		retguid = var.vendor;
@@ -267,6 +270,11 @@ errout:
 
 	/* XXX The linux interface expects name to be a static buffer -- fix or leak memory? */
 done:
+	if (errno == ENOENT) {
+		errno = 0;
+		return 0;
+	}
+
 	return (rv_to_linux_rv(rv));
 }
 
@@ -292,6 +300,7 @@ efi_guid_to_name(efi_guid_t *guid, char **name)
 	size_t i;
 	uint32_t status;
 
+	efi_guid_tbl_compile();
 	for (i = 0; i < nitems(guid_tbl); i++) {
 		if (uuid_equal(guid, &guid_tbl[i].guid, &status)) {
 			*name = strdup(guid_tbl[i].name);
@@ -328,6 +337,7 @@ efi_name_to_guid(const char *name, efi_guid_t *guid)
 {
 	size_t i;
 
+	efi_guid_tbl_compile();
 	for (i = 0; i < nitems(guid_tbl); i++) {
 		if (strcmp(name, guid_tbl[i].name) == 0) {
 			*guid = guid_tbl[i].guid;
@@ -348,7 +358,7 @@ efi_set_variable(efi_guid_t guid, const char *name,
 		return -1;
 
 	efi_var_reset(&var);
-	rv = libefi_utf8_to_ucs2(name, &var.name, &var.namesize);
+	rv = utf8_to_ucs2(name, &var.name, &var.namesize);
 	if (rv != 0)
 		goto errout;
 	var.vendor = guid;
diff --git a/lib/libefivar/efivar.h b/lib/libefivar/efivar.h
index 822cd3c125..c97b9702cd 100644
--- a/lib/libefivar/efivar.h
+++ b/lib/libefivar/efivar.h
@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/libefivar/efivar.h 307071 2016-10-11 22:30:41Z imp $
+ * $FreeBSD: head/lib/libefivar/efivar.h 314926 2017-03-09 00:31:31Z imp $
  */
 
 #ifndef	_EFIVAR_H_
@@ -49,7 +49,11 @@
 #endif
 
 
+#ifndef _EFIVAR_EFI_GUID_T_DEF
+#define _EFIVAR_EFI_GUID_T_DEF
 typedef uuid_t efi_guid_t;
+#endif
+
 #if BYTE_ORDER == LITTLE_ENDIAN
 #define	EFI_GUID(a, b, c, d, e0, e1, e2, e3, e4, e5)			\
 	((efi_guid_t) {(a), (b), (c), (d) >> 8, (d) & 0xff,		\
@@ -83,6 +87,16 @@ int efi_set_variable(efi_guid_t guid, const char *name,
 int efi_str_to_guid(const char *s, efi_guid_t *guid);
 int efi_variables_supported(void);
 
+/* FreeBSD extensions */
+struct uuid_table
+{
+	const char *uuid_str;
+	const char *name;
+	efi_guid_t guid;
+};
+
+int efi_known_guid(struct uuid_table **);
+
 extern const efi_guid_t efi_guid_empty;
 
 /* Stubs that are expected, but aren't really used */
diff --git a/lib/libefivar/uefi-dplib.h b/lib/libefivar/uefi-dplib.h
new file mode 100644
index 0000000000..2f2c1e0798
--- /dev/null
+++ b/lib/libefivar/uefi-dplib.h
@@ -0,0 +1,626 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: head/lib/libefivar/uefi-dplib.h 314926 2017-03-09 00:31:31Z imp $
+ */
+
+/*
+ * Taken from MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h
+ * hash a11928f3310518ab1c6fd34e8d0fdbb72de9602c 2017-Mar-01
+ */
+
+/** @file
+  Definition for Device Path library.
+
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_DEVICE_PATH_LIB_H_
+#define _UEFI_DEVICE_PATH_LIB_H_
+#include <Uefi.h>
+#include <Protocol/DevicePathUtilities.h>
+#include <Protocol/DebugPort.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Guid/PcAnsi.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Bluetooth.h>
+
+#define IS_COMMA(a)                ((a) == ',')
+#define IS_HYPHEN(a)               ((a) == '-')
+#define IS_DOT(a)                  ((a) == '.')
+#define IS_LEFT_PARENTH(a)         ((a) == '(')
+#define IS_RIGHT_PARENTH(a)        ((a) == ')')
+#define IS_SLASH(a)                ((a) == '/')
+#define IS_NULL(a)                 ((a) == '\0')
+
+
+//
+// Private Data structure
+//
+typedef struct {
+  char  *Str;
+  UINTN   Count;
+  UINTN   Capacity;
+} POOL_PRINT;
+
+typedef
+EFI_DEVICE_PATH_PROTOCOL  *
+(*DEVICE_PATH_FROM_TEXT) (
+  IN char *Str
+  );
+
+typedef
+VOID
+(*DEVICE_PATH_TO_TEXT) (
+  IN OUT POOL_PRINT  *Str,
+  IN VOID            *DevicePath,
+  IN BOOLEAN         DisplayOnly,
+  IN BOOLEAN         AllowShortcuts
+  );
+
+typedef struct {
+  UINT8                Type;
+  UINT8                SubType;
+  DEVICE_PATH_TO_TEXT  Function;
+} DEVICE_PATH_TO_TEXT_TABLE;
+
+typedef struct {
+  UINT8                Type;
+  const char          *Text;
+} DEVICE_PATH_TO_TEXT_GENERIC_TABLE;
+
+typedef struct {
+  const char                *DevicePathNodeText;
+  DEVICE_PATH_FROM_TEXT     Function;
+} DEVICE_PATH_FROM_TEXT_TABLE;
+
+typedef struct {
+  BOOLEAN ClassExist;
+  UINT8   Class;
+  BOOLEAN SubClassExist;
+  UINT8   SubClass;
+} USB_CLASS_TEXT;
+
+#define USB_CLASS_AUDIO            1
+#define USB_CLASS_CDCCONTROL       2
+#define USB_CLASS_HID              3
+#define USB_CLASS_IMAGE            6
+#define USB_CLASS_PRINTER          7
+#define USB_CLASS_MASS_STORAGE     8
+#define USB_CLASS_HUB              9
+#define USB_CLASS_CDCDATA          10
+#define USB_CLASS_SMART_CARD       11
+#define USB_CLASS_VIDEO            14
+#define USB_CLASS_DIAGNOSTIC       220
+#define USB_CLASS_WIRELESS         224
+
+#define USB_CLASS_RESERVE          254
+#define USB_SUBCLASS_FW_UPDATE     1
+#define USB_SUBCLASS_IRDA_BRIDGE   2
+#define USB_SUBCLASS_TEST          3
+
+#define RFC_1700_UDP_PROTOCOL      17
+#define RFC_1700_TCP_PROTOCOL      6
+
+#pragma pack(1)
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  EFI_GUID                  Guid;
+  UINT8                     VendorDefinedData[1];
+} VENDOR_DEFINED_HARDWARE_DEVICE_PATH;
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  EFI_GUID                  Guid;
+  UINT8                     VendorDefinedData[1];
+} VENDOR_DEFINED_MESSAGING_DEVICE_PATH;
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  EFI_GUID                  Guid;
+  UINT8                     VendorDefinedData[1];
+} VENDOR_DEFINED_MEDIA_DEVICE_PATH;
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  UINT32                    Hid;
+  UINT32                    Uid;
+  UINT32                    Cid;
+  CHAR8                     HidUidCidStr[3];
+} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR;
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  UINT16                    NetworkProtocol;
+  UINT16                    LoginOption;
+  UINT64                    Lun;
+  UINT16                    TargetPortalGroupTag;
+  CHAR8                     TargetName[1];
+} ISCSI_DEVICE_PATH_WITH_NAME;
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  EFI_GUID                  Guid;
+  UINT8                     VendorDefinedData[1];
+} VENDOR_DEVICE_PATH_WITH_DATA;
+
+#pragma pack()
+
+#ifdef FreeBSD		/* Remove these on FreeBSD */
+
+/**
+  Returns the size of a device path in bytes.
+
+  This function returns the size, in bytes, of the device path data structure
+  specified by DevicePath including the end of device path node.
+  If DevicePath is NULL or invalid, then 0 is returned.
+
+  @param  DevicePath  A pointer to a device path data structure.
+
+  @retval 0           If DevicePath is NULL or invalid.
+  @retval Others      The size of a device path in bytes.
+
+**/
+UINTN
+EFIAPI
+UefiDevicePathLibGetDevicePathSize (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+/**
+  Creates a new copy of an existing device path.
+
+  This function allocates space for a new copy of the device path specified by DevicePath.
+  If DevicePath is NULL, then NULL is returned.  If the memory is successfully
+  allocated, then the contents of DevicePath are copied to the newly allocated
+  buffer, and a pointer to that buffer is returned.  Otherwise, NULL is returned.
+  The memory for the new device path is allocated from EFI boot services memory.
+  It is the responsibility of the caller to free the memory allocated.
+
+  @param  DevicePath    A pointer to a device path data structure.
+
+  @retval NULL          DevicePath is NULL or invalid.
+  @retval Others        A pointer to the duplicated device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibDuplicateDevicePath (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+/**
+  Creates a new device path by appending a second device path to a first device path.
+
+  This function creates a new device path by appending a copy of SecondDevicePath
+  to a copy of FirstDevicePath in a newly allocated buffer.  Only the end-of-device-path
+  device node from SecondDevicePath is retained. The newly created device path is
+  returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of
+  SecondDevicePath is returned.  If SecondDevicePath is NULL, then it is ignored,
+  and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and
+  SecondDevicePath are NULL, then a copy of an end-of-device-path is returned.
+
+  If there is not enough memory for the newly allocated buffer, then NULL is returned.
+  The memory for the new device path is allocated from EFI boot services memory.
+  It is the responsibility of the caller to free the memory allocated.
+
+  @param  FirstDevicePath            A pointer to a device path data structure.
+  @param  SecondDevicePath           A pointer to a device path data structure.
+
+  @retval NULL      If there is not enough memory for the newly allocated buffer.
+  @retval NULL      If FirstDevicePath or SecondDevicePath is invalid.
+  @retval Others    A pointer to the new device path if success.
+                    Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibAppendDevicePath (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
+  );
+
+/**
+  Creates a new path by appending the device node to the device path.
+
+  This function creates a new device path by appending a copy of the device node
+  specified by DevicePathNode to a copy of the device path specified by DevicePath
+  in an allocated buffer. The end-of-device-path device node is moved after the
+  end of the appended device node.
+  If DevicePathNode is NULL then a copy of DevicePath is returned.
+  If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device
+  path device node is returned.
+  If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path
+  device node is returned.
+  If there is not enough memory to allocate space for the new device path, then
+  NULL is returned.
+  The memory is allocated from EFI boot services memory. It is the responsibility
+  of the caller to free the memory allocated.
+
+  @param  DevicePath                 A pointer to a device path data structure.
+  @param  DevicePathNode             A pointer to a single device path node.
+
+  @retval NULL      If there is not enough memory for the new device path.
+  @retval Others    A pointer to the new device path if success.
+                    A copy of DevicePathNode followed by an end-of-device-path node
+                    if both FirstDevicePath and SecondDevicePath are NULL.
+                    A copy of an end-of-device-path node if both FirstDevicePath
+                    and SecondDevicePath are NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibAppendDevicePathNode (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
+  );
+
+/**
+  Creates a new device path by appending the specified device path instance to the specified device
+  path.
+
+  This function creates a new device path by appending a copy of the device path
+  instance specified by DevicePathInstance to a copy of the device path specified
+  by DevicePath in a allocated buffer.
+  The end-of-device-path device node is moved after the end of the appended device
+  path instance and a new end-of-device-path-instance node is inserted between.
+  If DevicePath is NULL, then a copy if DevicePathInstance is returned.
+  If DevicePathInstance is NULL, then NULL is returned.
+  If DevicePath or DevicePathInstance is invalid, then NULL is returned.
+  If there is not enough memory to allocate space for the new device path, then
+  NULL is returned.
+  The memory is allocated from EFI boot services memory. It is the responsibility
+  of the caller to free the memory allocated.
+
+  @param  DevicePath                 A pointer to a device path data structure.
+  @param  DevicePathInstance         A pointer to a device path instance.
+
+  @return A pointer to the new device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibAppendDevicePathInstance (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance OPTIONAL
+  );
+
+/**
+  Creates a copy of the current device path instance and returns a pointer to the next device path
+  instance.
+
+  This function creates a copy of the current device path instance. It also updates
+  DevicePath to point to the next device path instance in the device path (or NULL
+  if no more) and updates Size to hold the size of the device path instance copy.
+  If DevicePath is NULL, then NULL is returned.
+  If DevicePath points to a invalid device path, then NULL is returned.
+  If there is not enough memory to allocate space for the new device path, then
+  NULL is returned.
+  The memory is allocated from EFI boot services memory. It is the responsibility
+  of the caller to free the memory allocated.
+  If Size is NULL, then ASSERT().
+
+  @param  DevicePath                 On input, this holds the pointer to the current
+                                     device path instance. On output, this holds
+                                     the pointer to the next device path instance
+                                     or NULL if there are no more device path
+                                     instances in the device path pointer to a
+                                     device path data structure.
+  @param  Size                       On output, this holds the size of the device
+                                     path instance, in bytes or zero, if DevicePath
+                                     is NULL.
+
+  @return A pointer to the current device path instance.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibGetNextDevicePathInstance (
+  IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
+  OUT UINTN                          *Size
+  );
+
+/**
+  Creates a device node.
+
+  This function creates a new device node in a newly allocated buffer of size
+  NodeLength and initializes the device path node header with NodeType and NodeSubType.
+  The new device path node is returned.
+  If NodeLength is smaller than a device path header, then NULL is returned.
+  If there is not enough memory to allocate space for the new device path, then
+  NULL is returned.
+  The memory is allocated from EFI boot services memory. It is the responsibility
+  of the caller to free the memory allocated.
+
+  @param  NodeType                   The device node type for the new device node.
+  @param  NodeSubType                The device node sub-type for the new device node.
+  @param  NodeLength                 The length of the new device node.
+
+  @return The new device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibCreateDeviceNode (
+  IN UINT8                           NodeType,
+  IN UINT8                           NodeSubType,
+  IN UINT16                          NodeLength
+  );
+
+/**
+  Determines if a device path is single or multi-instance.
+
+  This function returns TRUE if the device path specified by DevicePath is
+  multi-instance.
+  Otherwise, FALSE is returned.
+  If DevicePath is NULL or invalid, then FALSE is returned.
+
+  @param  DevicePath                 A pointer to a device path data structure.
+
+  @retval  TRUE                      DevicePath is multi-instance.
+  @retval  FALSE                     DevicePath is not multi-instance, or DevicePath
+                                     is NULL or invalid.
+
+**/
+BOOLEAN
+EFIAPI
+UefiDevicePathLibIsDevicePathMultiInstance (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+
+/**
+  Converts a device path to its text representation.
+
+  @param DevicePath      A Pointer to the device to be converted.
+  @param DisplayOnly     If DisplayOnly is TRUE, then the shorter text representation
+                         of the display node is used, where applicable. If DisplayOnly
+                         is FALSE, then the longer text representation of the display node
+                         is used.
+  @param AllowShortcuts  If AllowShortcuts is TRUE, then the shortcut forms of text
+                         representation for a device node can be used, where applicable.
+
+  @return A pointer to the allocated text representation of the device path or
+          NULL if DeviceNode is NULL or there was insufficient memory.
+
+**/
+CHAR16 *
+EFIAPI
+UefiDevicePathLibConvertDevicePathToText (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
+  IN BOOLEAN                          DisplayOnly,
+  IN BOOLEAN                          AllowShortcuts
+  );
+
+/**
+  Converts a device node to its string representation.
+
+  @param DeviceNode        A Pointer to the device node to be converted.
+  @param DisplayOnly       If DisplayOnly is TRUE, then the shorter text representation
+                           of the display node is used, where applicable. If DisplayOnly
+                           is FALSE, then the longer text representation of the display node
+                           is used.
+  @param AllowShortcuts    If AllowShortcuts is TRUE, then the shortcut forms of text
+                           representation for a device node can be used, where applicable.
+
+  @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
+          is NULL or there was insufficient memory.
+
+**/
+CHAR16 *
+EFIAPI
+UefiDevicePathLibConvertDeviceNodeToText (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
+  IN BOOLEAN                         DisplayOnly,
+  IN BOOLEAN                         AllowShortcuts
+  );
+
+/**
+  Convert text to the binary representation of a device node.
+
+  @param TextDeviceNode  TextDeviceNode points to the text representation of a device
+                         node. Conversion starts with the first character and continues
+                         until the first non-device node character.
+
+  @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
+          insufficient memory or text unsupported.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibConvertTextToDeviceNode (
+  IN CONST CHAR16 *TextDeviceNode
+  );
+
+/**
+  Convert text to the binary representation of a device path.
+
+
+  @param TextDevicePath  TextDevicePath points to the text representation of a device
+                         path. Conversion starts with the first character and continues
+                         until the first non-device node character.
+
+  @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
+          there was insufficient memory.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+UefiDevicePathLibConvertTextToDevicePath (
+  IN CONST CHAR16 *TextDevicePath
+  );
+#else
+
+/*
+ * Small FreeBSD shim layer. Fast and lose hacks to make this code work with FreeBSD.
+ */
+
+#include <ctype.h>
+
+#define _PCD_GET_MODE_32_PcdMaximumDevicePathNodeCount 1000
+#define MAX_UINTN UINTPTR_MAX
+
+#define AllocatePool(x) malloc(x)
+#define AllocateZeroPool(x) calloc(1,x)
+#define AsciiStrLen(s) strlen(s)
+#define CopyGuid(dst, src) memcpy(dst, src, sizeof(uuid_t))
+#define CopyMem(d, s, l) memcpy(d, s, l)
+#define FreePool(x) free(x)
+#define LShiftU64(x, s) ((x) << s)
+#define ReadUnaligned64(x)    le64dec(x)
+#define ReallocatePool(old, new, ptr) realloc(ptr, new)
+#define StrCmp(a, b) strcmp(a, b)
+#define StrCpyS(d, l, s) strcpy(d, s)
+#define StrHexToUint64(x) strtoll(x, NULL, 16)
+#define StrHexToUintn(x) strtoll(x, NULL, 16)
+#define StrLen(x) strlen(x)
+#define StrSize(x) (strlen(x) + 1)
+#define StrnCatS(d, l, s, len) strncat(d, s, len)
+#define StrnCmp(a, b, n) strncmp(a, b, n)
+#define StrnLenS(str, max) strlen(str)
+#define Strtoi(x) strtol(x, NULL, 0)
+#define Strtoi64(x, y) *(long long *)y = strtoll(x, NULL, 0)
+#define SwapBytes64(u64) bswap64(u64)
+#define UnicodeStrToAsciiStrS(src, dest, len) strlcpy(dest, src, len)
+#define ZeroMem(p,l) memset(p, 0, l)
+
+#undef ASSERT
+#define ASSERT(x)
+
+/*
+ * Define AllocateCopyPool and others so that we "forget" about the
+ * previous non-static deifnition since we want these to be static
+ * inlines.
+ */
+#define AllocateCopyPool AllocateCopyPoolFreeBSD
+#define CompareGuid CompareGuidFreeBSD
+#define StrHexToBytes StrHexToBytesFreeBSD
+#define StrToGuid StrToGuidFreeBSD
+#define WriteUnaligned64 WriteUnaligned64FreeBSD
+
+static inline void *
+AllocateCopyPool(size_t l, const void *p)
+{
+	void *rv;
+		
+	rv = malloc(l);
+	if (rv == NULL)
+		return NULL;
+	memcpy(rv, p, l);
+	return (rv);
+}
+
+static inline BOOLEAN
+CompareGuid (const GUID *g1, const GUID *g2)
+{
+	uint32_t ignored_status;
+
+	return (uuid_compare((const uuid_t *)g1, (const uuid_t *)g2,
+	    &ignored_status) == 0);
+}
+
+static inline int
+StrHexToBytes(const char *str, size_t len, uint8_t *buf, size_t buflen)
+{
+	size_t i;
+	char hex[3];
+
+	/*
+	 * Sanity check preconditions.
+	 */
+	if (buflen != len / 2 || (len % 1) == 1)
+		return 1;
+	for (i = 0; i < len; i += 2) {
+		if (!isxdigit(str[i]) || !isxdigit(str[i + 1]))
+			return 1;
+		hex[0] = str[i];
+		hex[1] = str[i + 1];
+		hex[2] = '\0';
+		buf[i / 2] = strtol(hex, NULL, 16);
+	}
+	return 0;
+}
+
+static inline void
+StrToGuid(const char *str, GUID *guid)
+{
+	uint32_t status;
+
+	uuid_from_string(str, (uuid_t *)guid, &status);
+}
+
+static inline void
+WriteUnaligned64(void *ptr, uint64_t val)
+{
+	memcpy(ptr, &val, sizeof(val));
+}
+
+/*
+ * Hack to allow converting %g to %s in printfs. Hack because
+ * it's single entry, uses a static buffer, etc. Sufficient for
+ * the day for this file though. IF you ever have to convert
+ * two %g's in one format, punt. Did I mention this was super lame.
+ * Not to mention it's name.... Also, the error GUID is horrific.
+ */
+static inline const char *
+guid_str(const GUID *g)
+{
+	static char buf[36 + 1];
+	char *str = NULL;
+	int32_t ignored_status;
+
+	uuid_to_string((const uuid_t *)g, &str, &ignored_status);
+	if (str != NULL)
+		strlcpy(buf, str, sizeof(buf));
+	else
+		strlcpy(buf, "groot-cannot-decode-guid-groot-smash",
+		    sizeof(buf)); /* ^^^^^^^ 36 characters ^^^^^^^ */
+	free(str);
+	return buf;
+}
+#define G(x) guid_str((const GUID *)(const void *)x)
+#endif
+
+#undef GLOBAL_REMOVE_IF_UNREFERENCED
+#define GLOBAL_REMOVE_IF_UNREFERENCED static
+
+#endif
diff --git a/lib/libefivar/uefi-dputil.c b/lib/libefivar/uefi-dputil.c
new file mode 100644
index 0000000000..76c613569a
--- /dev/null
+++ b/lib/libefivar/uefi-dputil.c
@@ -0,0 +1,636 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Routines to format EFI_DEVICE_PATHs from the UEFI standard. Much of
+ * this file is taken from EDK2 and rototilled.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libefivar/uefi-dputil.c 314926 2017-03-09 00:31:31Z imp $");
+
+#include <efivar.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/endian.h>
+
+#include "efi-osdep.h"
+
+#include "uefi-dplib.h"
+
+/* XXX maybe I sould include the entire DevicePathUtiltiies.c and ifdef out what we don't use */
+
+/*
+ * Taken from MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c
+ * hash a11928f3310518ab1c6fd34e8d0fdbb72de9602c 2017-Mar-01
+ */
+
+/** @file
+  Device Path services. The thing to remember is device paths are built out of
+  nodes. The device path is terminated by an end node that is length
+  sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
+  all over this file.
+
+  The only place where multi-instance device paths are supported is in
+  environment varibles. Multi-instance device paths should never be placed
+  on a Handle.
+
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Template for an end-of-device path node.
+//
+static CONST EFI_DEVICE_PATH_PROTOCOL  mUefiDevicePathLibEndDevicePath = {
+  END_DEVICE_PATH_TYPE,
+  END_ENTIRE_DEVICE_PATH_SUBTYPE,
+  {
+    END_DEVICE_PATH_LENGTH,
+    0
+  }
+};
+
+
+/**
+  Returns the size of a device path in bytes.
+
+  This function returns the size, in bytes, of the device path data structure
+  specified by DevicePath including the end of device path node.
+  If DevicePath is NULL or invalid, then 0 is returned.
+
+  @param  DevicePath  A pointer to a device path data structure.
+
+  @retval 0           If DevicePath is NULL or invalid.
+  @retval Others      The size of a device path in bytes.
+
+**/
+UINTN
+EFIAPI
+GetDevicePathSize (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  CONST EFI_DEVICE_PATH_PROTOCOL  *Start;
+
+  if (DevicePath == NULL) {
+    return 0;
+  }
+
+  if (!IsDevicePathValid (DevicePath, 0)) {
+    return 0;
+  }
+
+  //
+  // Search for the end of the device path structure
+  //
+  Start = DevicePath;
+  while (!IsDevicePathEnd (DevicePath)) {
+    DevicePath = NextDevicePathNode (DevicePath);
+  }
+
+  //
+  // Compute the size and add back in the size of the end device path structure
+  //
+  return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath);
+}
+
+/**
+  Determine whether a given device path is valid.
+  If DevicePath is NULL, then ASSERT().
+
+  @param  DevicePath  A pointer to a device path data structure.
+  @param  MaxSize     The maximum size of the device path data structure.
+
+  @retval TRUE        DevicePath is valid.
+  @retval FALSE       The length of any node node in the DevicePath is less
+                      than sizeof (EFI_DEVICE_PATH_PROTOCOL).
+  @retval FALSE       If MaxSize is not zero, the size of the DevicePath
+                      exceeds MaxSize.
+  @retval FALSE       If PcdMaximumDevicePathNodeCount is not zero, the node
+                      count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
+**/
+BOOLEAN
+EFIAPI
+IsDevicePathValid (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+  IN       UINTN                    MaxSize
+  )
+{
+  UINTN Count;
+  UINTN Size;
+  UINTN NodeLength;
+
+  ASSERT (DevicePath != NULL);
+
+  if (MaxSize == 0) {
+    MaxSize = MAX_UINTN;
+  }
+
+  //
+  // Validate the input size big enough to touch the first node.
+  //
+  if (MaxSize < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
+    return FALSE;
+  }
+
+  for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
+    NodeLength = DevicePathNodeLength (DevicePath);
+    if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
+      return FALSE;
+    }
+
+    if (NodeLength > MAX_UINTN - Size) {
+      return FALSE;
+    }
+    Size += NodeLength;
+
+    //
+    // Validate next node before touch it.
+    //
+    if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) {
+      return FALSE;
+    }
+
+    if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
+      Count++;
+      if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
+        return FALSE;
+      }
+    }
+  }
+
+  //
+  // Only return TRUE when the End Device Path node is valid.
+  //
+  return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
+}
+
+/**
+  Returns the Type field of a device path node.
+
+  Returns the Type field of the device path node specified by Node.
+
+  If Node is NULL, then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+
+  @return The Type field of the device path node specified by Node.
+
+**/
+UINT8
+EFIAPI
+DevicePathType (
+  IN CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return ((const EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type;
+}
+
+
+/**
+  Returns the SubType field of a device path node.
+
+  Returns the SubType field of the device path node specified by Node.
+
+  If Node is NULL, then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+
+  @return The SubType field of the device path node specified by Node.
+
+**/
+UINT8
+EFIAPI
+DevicePathSubType (
+  IN CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return ((const EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType;
+}
+
+/**
+  Returns the 16-bit Length field of a device path node.
+
+  Returns the 16-bit Length field of the device path node specified by Node.
+  Node is not required to be aligned on a 16-bit boundary, so it is recommended
+  that a function such as ReadUnaligned16() be used to extract the contents of
+  the Length field.
+
+  If Node is NULL, then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+
+  @return The 16-bit Length field of the device path node specified by Node.
+
+**/
+UINTN
+EFIAPI
+DevicePathNodeLength (
+  IN CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return ((const EFI_DEVICE_PATH_PROTOCOL *)Node)->Length[0] |
+      (((const EFI_DEVICE_PATH_PROTOCOL *)Node)->Length[1] << 8);
+}
+
+/**
+  Returns a pointer to the next node in a device path.
+
+  Returns a pointer to the device path node that follows the device path node
+  specified by Node.
+
+  If Node is NULL, then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+
+  @return a pointer to the device path node that follows the device path node
+  specified by Node.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+NextDevicePathNode (
+  IN CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return ((EFI_DEVICE_PATH_PROTOCOL *)(__DECONST(UINT8 *, Node) + DevicePathNodeLength(Node)));
+}
+
+/**
+  Determines if a device path node is an end node of a device path.
+  This includes nodes that are the end of a device path instance and nodes that
+  are the end of an entire device path.
+
+  Determines if the device path node specified by Node is an end node of a device path.
+  This includes nodes that are the end of a device path instance and nodes that are the
+  end of an entire device path.  If Node represents an end node of a device path,
+  then TRUE is returned.  Otherwise, FALSE is returned.
+
+  If Node is NULL, then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+
+  @retval TRUE      The device path node specified by Node is an end node of a
+                    device path.
+  @retval FALSE     The device path node specified by Node is not an end node of
+                    a device path.
+
+**/
+BOOLEAN
+EFIAPI
+IsDevicePathEndType (
+  IN CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE);
+}
+
+/**
+  Determines if a device path node is an end node of an entire device path.
+
+  Determines if a device path node specified by Node is an end node of an entire
+  device path. If Node represents the end of an entire device path, then TRUE is
+  returned.  Otherwise, FALSE is returned.
+
+  If Node is NULL, then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+
+  @retval TRUE      The device path node specified by Node is the end of an entire
+                    device path.
+  @retval FALSE     The device path node specified by Node is not the end of an
+                    entire device path.
+
+**/
+BOOLEAN
+EFIAPI
+IsDevicePathEnd (
+  IN CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
+}
+
+/**
+  Fills in all the fields of a device path node that is the end of an entire device path.
+
+  Fills in all the fields of a device path node specified by Node so Node represents
+  the end of an entire device path.  The Type field of Node is set to
+  END_DEVICE_PATH_TYPE, the SubType field of Node is set to
+  END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to
+  END_DEVICE_PATH_LENGTH.  Node is not required to be aligned on a 16-bit boundary,
+  so it is recommended that a function such as WriteUnaligned16() be used to set
+  the contents of the Length field.
+
+  If Node is NULL, then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+
+**/
+VOID
+EFIAPI
+SetDevicePathEndNode (
+  OUT VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  memcpy (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));
+}
+
+/**
+  Sets the length, in bytes, of a device path node.
+
+  Sets the length of the device path node specified by Node to the value specified
+  by NodeLength.  NodeLength is returned.  Node is not required to be aligned on
+  a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16()
+  be used to set the contents of the Length field.
+
+  If Node is NULL, then ASSERT().
+  If NodeLength >= SIZE_64KB, then ASSERT().
+  If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT().
+
+  @param  Node      A pointer to a device path node data structure.
+  @param  Length    The length, in bytes, of the device path node.
+
+  @return Length
+
+**/
+UINT16
+EFIAPI
+SetDevicePathNodeLength (
+  IN OUT VOID  *Node,
+  IN UINTN     Length
+  )
+{
+  ASSERT (Node != NULL);
+  ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB));
+//  return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));
+  le16enc(&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));
+  return Length;
+}
+
+/**
+  Creates a device node.
+
+  This function creates a new device node in a newly allocated buffer of size
+  NodeLength and initializes the device path node header with NodeType and NodeSubType.
+  The new device path node is returned.
+  If NodeLength is smaller than a device path header, then NULL is returned.
+  If there is not enough memory to allocate space for the new device path, then
+  NULL is returned.
+  The memory is allocated from EFI boot services memory. It is the responsibility
+  of the caller to free the memory allocated.
+
+  @param  NodeType                   The device node type for the new device node.
+  @param  NodeSubType                The device node sub-type for the new device node.
+  @param  NodeLength                 The length of the new device node.
+
+  @return The new device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+CreateDeviceNode (
+  IN UINT8                           NodeType,
+  IN UINT8                           NodeSubType,
+  IN UINT16                          NodeLength
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
+
+  if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
+    //
+    // NodeLength is less than the size of the header.
+    //
+    return NULL;
+  }
+
+  DevicePath = AllocateZeroPool (NodeLength);
+  if (DevicePath != NULL) {
+     DevicePath->Type    = NodeType;
+     DevicePath->SubType = NodeSubType;
+     SetDevicePathNodeLength (DevicePath, NodeLength);
+  }
+
+  return DevicePath;
+}
+
+/**
+  Creates a new copy of an existing device path.
+
+  This function allocates space for a new copy of the device path specified by DevicePath.
+  If DevicePath is NULL, then NULL is returned.  If the memory is successfully
+  allocated, then the contents of DevicePath are copied to the newly allocated
+  buffer, and a pointer to that buffer is returned.  Otherwise, NULL is returned.
+  The memory for the new device path is allocated from EFI boot services memory.
+  It is the responsibility of the caller to free the memory allocated.
+
+  @param  DevicePath    A pointer to a device path data structure.
+
+  @retval NULL          DevicePath is NULL or invalid.
+  @retval Others        A pointer to the duplicated device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+DuplicateDevicePath (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  UINTN                     Size;
+
+  //
+  // Compute the size
+  //
+  Size = GetDevicePathSize (DevicePath);
+  if (Size == 0) {
+    return NULL;
+  }
+
+  //
+  // Allocate space for duplicate device path
+  //
+
+  return AllocateCopyPool (Size, DevicePath);
+}
+
+/**
+  Creates a new device path by appending a second device path to a first device path.
+
+  This function creates a new device path by appending a copy of SecondDevicePath
+  to a copy of FirstDevicePath in a newly allocated buffer.  Only the end-of-device-path
+  device node from SecondDevicePath is retained. The newly created device path is
+  returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of
+  SecondDevicePath is returned.  If SecondDevicePath is NULL, then it is ignored,
+  and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and
+  SecondDevicePath are NULL, then a copy of an end-of-device-path is returned.
+
+  If there is not enough memory for the newly allocated buffer, then NULL is returned.
+  The memory for the new device path is allocated from EFI boot services memory.
+  It is the responsibility of the caller to free the memory allocated.
+
+  @param  FirstDevicePath            A pointer to a device path data structure.
+  @param  SecondDevicePath           A pointer to a device path data structure.
+
+  @retval NULL      If there is not enough memory for the newly allocated buffer.
+  @retval NULL      If FirstDevicePath or SecondDevicePath is invalid.
+  @retval Others    A pointer to the new device path if success.
+                    Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+AppendDevicePath (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
+  )
+{
+  UINTN                     Size;
+  UINTN                     Size1;
+  UINTN                     Size2;
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath2;
+
+  //
+  // If there's only 1 path, just duplicate it.
+  //
+  if (FirstDevicePath == NULL) {
+    return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath);
+  }
+
+  if (SecondDevicePath == NULL) {
+    return DuplicateDevicePath (FirstDevicePath);
+  }
+
+  if (!IsDevicePathValid (FirstDevicePath, 0) || !IsDevicePathValid (SecondDevicePath, 0)) {
+    return NULL;
+  }
+
+  //
+  // Allocate space for the combined device path. It only has one end node of
+  // length EFI_DEVICE_PATH_PROTOCOL.
+  //
+  Size1         = GetDevicePathSize (FirstDevicePath);
+  Size2         = GetDevicePathSize (SecondDevicePath);
+  Size          = Size1 + Size2 - END_DEVICE_PATH_LENGTH;
+
+  NewDevicePath = AllocatePool (Size);
+
+  if (NewDevicePath != NULL) {
+    NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1);
+    //
+    // Over write FirstDevicePath EndNode and do the copy
+    //
+    DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath +
+                  (Size1 - END_DEVICE_PATH_LENGTH));
+    CopyMem (DevicePath2, SecondDevicePath, Size2);
+  }
+
+  return NewDevicePath;
+}
+
+/**
+  Creates a new path by appending the device node to the device path.
+
+  This function creates a new device path by appending a copy of the device node
+  specified by DevicePathNode to a copy of the device path specified by DevicePath
+  in an allocated buffer. The end-of-device-path device node is moved after the
+  end of the appended device node.
+  If DevicePathNode is NULL then a copy of DevicePath is returned.
+  If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device
+  path device node is returned.
+  If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path
+  device node is returned.
+  If there is not enough memory to allocate space for the new device path, then
+  NULL is returned.
+  The memory is allocated from EFI boot services memory. It is the responsibility
+  of the caller to free the memory allocated.
+
+  @param  DevicePath                 A pointer to a device path data structure.
+  @param  DevicePathNode             A pointer to a single device path node.
+
+  @retval NULL      If there is not enough memory for the new device path.
+  @retval Others    A pointer to the new device path if success.
+                    A copy of DevicePathNode followed by an end-of-device-path node
+                    if both FirstDevicePath and SecondDevicePath are NULL.
+                    A copy of an end-of-device-path node if both FirstDevicePath
+                    and SecondDevicePath are NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+AppendDevicePathNode (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *NextNode;
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
+  UINTN                     NodeLength;
+
+  if (DevicePathNode == NULL) {
+    return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath);
+  }
+  //
+  // Build a Node that has a terminator on it
+  //
+  NodeLength = DevicePathNodeLength (DevicePathNode);
+
+  TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH);
+  if (TempDevicePath == NULL) {
+    return NULL;
+  }
+  TempDevicePath = CopyMem (TempDevicePath, DevicePathNode, NodeLength);
+  //
+  // Add and end device path node to convert Node to device path
+  //
+  NextNode = NextDevicePathNode (TempDevicePath);
+  SetDevicePathEndNode (NextNode);
+  //
+  // Append device paths
+  //
+  NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath);
+
+  FreePool (TempDevicePath);
+
+  return NewDevicePath;
+}
diff --git a/lib/libefivar/uefi-guid.c b/lib/libefivar/uefi-guid.c
new file mode 100644
index 0000000000..532aa4240f
--- /dev/null
+++ b/lib/libefivar/uefi-guid.c
@@ -0,0 +1,36 @@
+/* This generated file is in the public domain */
+/* $FreeBSD: head/lib/libefivar/uefi-guid.c 314926 2017-03-09 00:31:31Z imp $ */
+
+#include <uuid.h>
+#include <stdint.h>
+
+typedef struct {          
+    uint32_t  Data1;
+    uint16_t  Data2;
+    uint16_t  Data3;
+    uint8_t   Data4[8]; 
+} EFI_GUID;
+
+extern EFI_GUID    gEfiDebugPortProtocolGuid;
+extern EFI_GUID    gEfiPcAnsiGuid;
+extern EFI_GUID    gEfiPersistentVirtualCdGuid;
+extern EFI_GUID    gEfiPersistentVirtualDiskGuid;
+extern EFI_GUID    gEfiSasDevicePathGuid;
+extern EFI_GUID    gEfiUartDevicePathGuid;
+extern EFI_GUID    gEfiVT100Guid;
+extern EFI_GUID    gEfiVT100PlusGuid;
+extern EFI_GUID    gEfiVTUTF8Guid;
+extern EFI_GUID    gEfiVirtualCdGuid;
+extern EFI_GUID    gEfiVirtualDiskGuid;
+
+EFI_GUID    gEfiDebugPortProtocolGuid      = { 0xEBA4E8D2, 0x3858, 0x41EC, { 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 }} ;
+EFI_GUID    gEfiPcAnsiGuid                 = { 0xE0C14753, 0xF9BE, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} ;
+EFI_GUID    gEfiPersistentVirtualCdGuid    = { 0x08018188, 0x42CD, 0xBB48, {0x10, 0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D }} ;
+EFI_GUID    gEfiPersistentVirtualDiskGuid  = { 0x5CEA02C9, 0x4D07, 0x69D3, {0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 }} ;
+EFI_GUID    gEfiSasDevicePathGuid          = { 0xd487ddb4, 0x008b, 0x11d9, { 0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d }} ;
+EFI_GUID    gEfiUartDevicePathGuid         = { 0x37499a9d, 0x542f, 0x4c89, { 0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 }} ;
+EFI_GUID    gEfiVT100Guid                  = { 0xDFA66065, 0xB419, 0x11D3, { 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} ;
+EFI_GUID    gEfiVT100PlusGuid              = { 0x7BAEC70B, 0x57E0, 0x4C76, { 0x8E, 0x87, 0x2F, 0x9E, 0x28, 0x08, 0x83, 0x43 }} ;
+EFI_GUID    gEfiVTUTF8Guid                 = { 0xAD15A0D6, 0x8BEC, 0x4ACF, { 0xA0, 0x73, 0xD0, 0x1D, 0xE7, 0x7E, 0x2D, 0x88 }} ;
+EFI_GUID    gEfiVirtualCdGuid              = { 0x3D5ABD30, 0x4175, 0x87CE, {0x6D, 0x64, 0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB }} ;
+EFI_GUID    gEfiVirtualDiskGuid            = { 0x77AB535A, 0x45FC, 0x624B, {0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }} ;
diff --git a/lib/libefivar/uefi-guid.dat b/lib/libefivar/uefi-guid.dat
new file mode 100644
index 0000000000..921b179ae3
--- /dev/null
+++ b/lib/libefivar/uefi-guid.dat
@@ -0,0 +1,11 @@
+gEfiDebugPortProtocolGuid
+gEfiPcAnsiGuid
+gEfiPersistentVirtualCdGuid
+gEfiPersistentVirtualDiskGuid
+gEfiSasDevicePathGuid
+gEfiUartDevicePathGuid
+gEfiVT100Guid
+gEfiVT100PlusGuid
+gEfiVTUTF8Guid
+gEfiVirtualCdGuid
+gEfiVirtualDiskGuid
-- 
2.11.0

