public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [Patch 0/2] BaseTools: Add Flexible PCD Value support
@ 2017-12-26 16:40 Yonghong Zhu
  2017-12-26 16:40 ` [Patch 1/2] BaseTools: Support PCD flexible values format Yonghong Zhu
  2017-12-26 16:40 ` [Patch 2/2] BaseTools: Add DevicePath support for PCD values Yonghong Zhu
  0 siblings, 2 replies; 4+ messages in thread
From: Yonghong Zhu @ 2017-12-26 16:40 UTC (permalink / raw)
  To: edk2-devel; +Cc: Yunhua Feng

https://bugzilla.tianocore.org/show_bug.cgi?id=541

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>

Yonghong Zhu (2):
  BaseTools: Support PCD flexible values format
  BaseTools: Add DevicePath support for PCD values

 BaseTools/Source/BinaryFiles.txt                   |    3 +-
 BaseTools/Source/C/DevicePath/DevicePath.c         |  188 ++
 BaseTools/Source/C/DevicePath/DevicePath.h         | 1380 ++++++++
 BaseTools/Source/C/DevicePath/DevicePathFromText.c | 3503 ++++++++++++++++++++
 BaseTools/Source/C/DevicePath/DevicePathFromText.h |   72 +
 .../Source/C/DevicePath/DevicePathUtilities.c      | 2352 +++++++++++++
 .../Source/C/DevicePath/DevicePathUtilities.h      |  555 ++++
 BaseTools/Source/C/DevicePath/GNUmakefile          |   30 +
 BaseTools/Source/C/DevicePath/Makefile             |   24 +
 BaseTools/Source/C/DevicePath/UefiDevicePathLib.c  |  298 ++
 BaseTools/Source/C/DevicePath/UefiDevicePathLib.h  |  473 +++
 BaseTools/Source/C/GNUmakefile                     |    3 +-
 BaseTools/Source/C/Makefile                        |    5 +-
 BaseTools/Source/Python/AutoGen/AutoGen.py         |   39 +
 BaseTools/Source/Python/AutoGen/GenC.py            |    2 +
 BaseTools/Source/Python/Common/Expression.py       |  241 +-
 BaseTools/Source/Python/Common/Misc.py             |  236 +-
 BaseTools/Source/Python/Workspace/DscBuildData.py  |   14 +-
 BaseTools/Source/Python/Workspace/InfBuildData.py  |    7 +
 .../Source/Python/Workspace/MetaFileParser.py      |   17 +-
 .../Source/Python/Workspace/WorkspaceCommon.py     |    6 +-
 BaseTools/Source/Python/build/BuildReport.py       |    6 +
 22 files changed, 9338 insertions(+), 116 deletions(-)
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePath.c
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePath.h
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathFromText.c
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathFromText.h
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathUtilities.c
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathUtilities.h
 create mode 100644 BaseTools/Source/C/DevicePath/GNUmakefile
 create mode 100644 BaseTools/Source/C/DevicePath/Makefile
 create mode 100644 BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
 create mode 100644 BaseTools/Source/C/DevicePath/UefiDevicePathLib.h

-- 
2.6.1.windows.1



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Patch 1/2] BaseTools: Support PCD flexible values format
  2017-12-26 16:40 [Patch 0/2] BaseTools: Add Flexible PCD Value support Yonghong Zhu
@ 2017-12-26 16:40 ` Yonghong Zhu
  2017-12-26 16:40 ` [Patch 2/2] BaseTools: Add DevicePath support for PCD values Yonghong Zhu
  1 sibling, 0 replies; 4+ messages in thread
From: Yonghong Zhu @ 2017-12-26 16:40 UTC (permalink / raw)
  To: edk2-devel; +Cc: Yunhua Feng

https://bugzilla.tianocore.org/show_bug.cgi?id=541

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
---
 BaseTools/Source/Python/AutoGen/AutoGen.py         |  39 ++++
 BaseTools/Source/Python/AutoGen/GenC.py            |   2 +
 BaseTools/Source/Python/Common/Expression.py       | 246 ++++++++++++++++++++-
 BaseTools/Source/Python/Common/Misc.py             | 203 +++++++++--------
 BaseTools/Source/Python/Workspace/DscBuildData.py  |  14 +-
 BaseTools/Source/Python/Workspace/InfBuildData.py  |   7 +
 .../Source/Python/Workspace/MetaFileParser.py      |  17 +-
 .../Source/Python/Workspace/WorkspaceCommon.py     |   8 +-
 BaseTools/Source/Python/build/BuildReport.py       |   6 +
 9 files changed, 429 insertions(+), 113 deletions(-)

diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py
index cacd009..8be5bfc 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGen.py
@@ -269,10 +269,11 @@ class WorkspaceAutoGen(AutoGen):
         self.AutoGenObjectList = []
         self._BuildDir      = None
         self._FvDir         = None
         self._MakeFileDir   = None
         self._BuildCommand  = None
+        self._GuidDict = {}
 
         # there's many relative directory operations, so ...
         os.chdir(self.WorkspaceDir)
 
         #
@@ -417,24 +418,42 @@ class WorkspaceAutoGen(AutoGen):
                     TokenSpaceGuidCNameList = []
                     FoundFlag = False
                     PcdDatumType = ''
                     NewValue = ''
                     for package in PGen.PackageList:
+                        Guids = package.Guids
+                        self._GuidDict.update(Guids)
+                    for package in PGen.PackageList:
                         for key in package.Pcds:
                             PcdItem = package.Pcds[key]
                             if HasTokenSpace:
                                 if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
                                     PcdDatumType = PcdItem.DatumType
+                                    if pcdvalue.startswith('H'):
+                                        try:
+                                            pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
+                                        except BadExpression, Value:
+                                            if Value.result > 1:
+                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
+                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
+                                        pcdvalue = 'H' + pcdvalue
                                     NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
                                     FoundFlag = True
                             else:
                                 if PcdItem.TokenCName == TokenCName:
                                     if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
                                         if len (TokenSpaceGuidCNameList) < 1:
                                             TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
                                             PcdDatumType = PcdItem.DatumType
                                             TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
+                                            if pcdvalue.startswith('H'):
+                                                try:
+                                                    pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
+                                                except BadExpression, Value:
+                                                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
+                                                                    (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
+                                                pcdvalue = 'H' + pcdvalue
                                             NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
                                             FoundFlag = True
                                         else:
                                             EdkLogger.error(
                                                     'build',
@@ -2444,10 +2463,30 @@ class PlatformAutoGen(AutoGen):
                 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
             if FromPcd.DatumType not in [None, '']:
                 ToPcd.DatumType = FromPcd.DatumType
             if FromPcd.SkuInfoList not in [None, '', []]:
                 ToPcd.SkuInfoList = FromPcd.SkuInfoList
+            # Add Flexible PCD format parse
+            PcdValue = ToPcd.DefaultValue
+            if PcdValue:
+                try:
+                    ToPcd.DefaultValue = ValueExpression(PcdValue)(True)
+                except WrnExpression, Value:
+                    ToPcd.DefaultValue = Value.result
+                except BadExpression, Value:
+                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
+                                    File=self.MetaFile)
+            if ToPcd.DefaultValue:
+                _GuidDict = {}
+                for Pkg in self.PackageList:
+                    Guids = Pkg.Guids
+                    _GuidDict.update(Guids)
+                try:
+                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, _GuidDict)(True)
+                except BadExpression, Value:
+                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
+                                        File=self.MetaFile)
 
             # check the validation of datum
             IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
             if not IsValid:
                 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
diff --git a/BaseTools/Source/Python/AutoGen/GenC.py b/BaseTools/Source/Python/AutoGen/GenC.py
index 6b95cd4..3e98506 100644
--- a/BaseTools/Source/Python/AutoGen/GenC.py
+++ b/BaseTools/Source/Python/AutoGen/GenC.py
@@ -1031,10 +1031,12 @@ def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd):
             elif BoolValue == 'FALSE' or BoolValue == '0':
                 Value = '0U'
 
         if Pcd.DatumType in ['UINT64', 'UINT32', 'UINT16', 'UINT8']:
             try:
+                if Value.upper().endswith('L'):
+                    Value = Value[:-1]
                 if Value.upper().startswith('0X'):
                     ValueNumber = int (Value, 16)
                 else:
                     ValueNumber = int (Value)
             except:
diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py
index ba83e02..4d8bd14 100644
--- a/BaseTools/Source/Python/Common/Expression.py
+++ b/BaseTools/Source/Python/Common/Expression.py
@@ -13,11 +13,13 @@
 ## Import Modules
 #
 from Common.GlobalData import *
 from CommonDataClass.Exceptions import BadExpression
 from CommonDataClass.Exceptions import WrnExpression
-from Misc import GuidStringToGuidStructureString
+from Misc import GuidStringToGuidStructureString, ParseFieldValue
+import Common.EdkLogger as EdkLogger
+import copy
 
 ERR_STRING_EXPR         = 'This operator cannot be used in string expression: [%s].'
 ERR_SNYTAX              = 'Syntax error, the rest of expression cannot be evaluated: [%s].'
 ERR_MATCH               = 'No matching right parenthesis.'
 ERR_STRING_TOKEN        = 'Bad string token: [%s].'
@@ -112,10 +114,19 @@ def ReplaceExprMacro(String, Macros, ExceptionList = None):
             String = RetStr
             MacroStartPos = String.find('$(')
         StrList[i] = RetStr
     return ''.join(StrList)
 
+# transfer int to string for in/not in expression
+def IntToStr(Value):
+    StrList = []
+    while Value > 0:
+        StrList.append(chr(Value & 0xff))
+        Value = Value >> 8
+    Value = '"' + ''.join(StrList) + '"'
+    return Value
+
 SupportedInMacroList = ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH', 'FAMILY']
 
 class ValueExpression(object):
     # Logical operator mapping
     LogicalOperators = {
@@ -144,14 +155,28 @@ class ValueExpression(object):
 
     @staticmethod
     def Eval(Operator, Oprand1, Oprand2 = None):
         WrnExp = None
 
-        if Operator not in ["==", "!=", ">=", "<=", ">", "<", "in", "not in"] and \
-            (type(Oprand1) == type('') or type(Oprand2) == type('')):
-            raise BadExpression(ERR_STRING_EXPR % Operator)
-
+        if Operator not in ["in", "not in"] and (type(Oprand1) == type('') or type(Oprand2) == type('')):
+            if type(Oprand1) == type(''):
+                if Oprand1[0] in ['"', "'"] or Oprand1.startswith('L"') or Oprand1.startswith("L'")or Oprand1.startswith('UINT'):
+                    Oprand1, Size = ParseFieldValue(Oprand1)
+                else:
+                    Oprand1,Size = ParseFieldValue('"' + Oprand1 + '"')
+            if type(Oprand2) == type(''):
+                if Oprand2[0] in ['"', "'", 'L'] or Oprand2.startswith('UINT'):
+                    Oprand2, Size = ParseFieldValue(Oprand2)
+                else:
+                    Oprand2, Size = ParseFieldValue('"' + Oprand2 + '"')
+            if type(Oprand1) == type('') or type(Oprand2) == type(''):
+                raise BadExpression(ERR_STRING_EXPR % Operator)
+        if Operator in ['in', 'not in']:
+            if type(Oprand1) != type(''):
+                Oprand1 = IntToStr(Oprand1)
+            if type(Oprand2) != type(''):
+                Oprand2 = IntToStr(Oprand2)
         TypeDict = {
             type(0)  : 0,
             type(0L) : 0,
             type('') : 1,
             type(True) : 2
@@ -224,10 +249,13 @@ class ValueExpression(object):
         self._NoProcess = False
         if type(Expression) != type(''):
             self._Expr = Expression
             self._NoProcess = True
             return
+        if Expression.strip().startswith('{') and Expression.strip().endswith('}'):
+            self._Expr = Expression
+            self._NoProcess = True
 
         self._Expr = ReplaceExprMacro(Expression.strip(),
                                   SymbolTable,
                                   SupportedInMacroList)
 
@@ -235,11 +263,11 @@ class ValueExpression(object):
             raise BadExpression(ERR_EMPTY_EXPR)
 
         #
         # The symbol table including PCD and macro mapping
         #
-        self._Symb = SymbolTable
+        self._Symb = copy.deepcopy(SymbolTable)
         self._Symb.update(self.LogicalOperators)
         self._Idx = 0
         self._Len = len(self._Expr)
         self._Token = ''
         self._WarnExcept = None
@@ -282,11 +310,11 @@ class ValueExpression(object):
             if Val == 'L""':
                 Val = False
             elif not Val:
                 Val = False
                 RealVal = '""'
-            elif not Val.startswith('L"') and not Val.startswith('{'):
+            elif not Val.startswith('L"') and not Val.startswith('{') and not Val.startswith("L'"):
                 Val = True
                 RealVal = '"' + RealVal + '"'
 
         # The expression has been parsed, but the end of expression is not reached
         # It means the rest does not comply EBNF of <Expression>
@@ -424,10 +452,19 @@ class ValueExpression(object):
     # Try to convert string to number
     def __IsNumberToken(self):
         Radix = 10
         if self._Token.lower()[0:2] == '0x' and len(self._Token) > 2:
             Radix = 16
+        if self._Token.startswith('"') or self._Token.startswith("'")\
+            or self._Token.startswith("L'") or self._Token.startswith('L"'):
+            Flag = 0
+            for Index in range(len(self._Token)):
+                if self._Token[Index] in ['"', "'"]:
+                    Flag += 1
+            if Flag == 2:
+                self._Token = ParseFieldValue(self._Token)[0]
+                return True
         try:
             self._Token = int(self._Token, Radix)
             return True
         except ValueError:
             return False
@@ -471,14 +508,16 @@ class ValueExpression(object):
 
         # Replace escape \\\", \"
         Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace('\\\"', '\\\'')
         for Ch in Expr:
             self._Idx += 1
-            if Ch == '"':
+            if Ch == '"' or Ch == "'":
                 break
         self._Token = self._LiteralToken = self._Expr[Idx:self._Idx]
-        if not self._Token.endswith('"'):
+        if self._Token.startswith('"') and not self._Token.endswith('"'):
+            raise BadExpression(ERR_STRING_TOKEN % self._Token)
+        if self._Token.startswith("'") and not self._Token.endswith("'"):
             raise BadExpression(ERR_STRING_TOKEN % self._Token)
         self._Token = self._Token[1:-1]
         return self._Token
 
     # Get token that is comprised by alphanumeric, underscore or dot(used by PCD)
@@ -576,11 +615,48 @@ class ValueExpression(object):
         if Expr.startswith('L"'):
             # Skip L
             self._Idx += 1
             UStr = self.__GetString()
             self._Token = 'L"' + UStr + '"'
+            self._Token, Size = ParseFieldValue(self._Token)
+            return self._Token
+        elif Expr.startswith("L'"):
+            # Skip L
+            self._Idx += 1
+            UStr = self.__GetString()
+            self._Token = "L'" + UStr + "'"
+            self._Token, Size = ParseFieldValue(self._Token)
+            return self._Token
+        elif Expr.startswith('"'):
+            UStr = self.__GetString()
+            self._Token = '"' + UStr + '"'
+            self._Token, Size = ParseFieldValue(self._Token)
             return self._Token
+        elif Expr.startswith("'"):
+            UStr = self.__GetString()
+            self._Token = "'" + UStr + "'"
+            self._Token, Size = ParseFieldValue(self._Token)
+            return self._Token
+        elif Expr.startswith('UINT'):
+            Re = re.compile('(?:UINT8|UINT16|UINT32|UINT64)\((.+)\)')
+            try:
+                RetValue = Re.search(Expr).group(1)
+            except:
+                 raise BadExpression('Invalid Expression %s' % Expr)
+            Idx = self._Idx
+            for Ch in Expr:
+                self._Idx += 1
+                if Ch == '(':
+                    Prefix = self._Expr[Idx:self._Idx - 1]
+                    Idx = self._Idx
+                if Ch == ')':
+                    TmpValue = self._Expr[Idx :self._Idx - 1]
+                    TmpValue = ValueExpression(TmpValue)(True)
+                    TmpValue = '0x%x' % int(TmpValue) if type(TmpValue) != type('') else TmpValue
+                    break
+            self._Token, Size = ParseFieldValue(Prefix + '(' + TmpValue + ')')
+            return  self._Token
 
         self._Token = ''
         if Expr:
             Ch = Expr[0]
             Match = self.RegGuidPattern.match(Expr)
@@ -646,10 +722,162 @@ class ValueExpression(object):
                 self._Token = self.LogicalOperators[self._Token]
             return True
         self._Idx = Idx
         return False
 
+class ValueExpressionEx(ValueExpression):
+    def __init__(self, PcdValue, PcdType, SymbolTable={}):
+        ValueExpression.__init__(self, PcdValue, SymbolTable)
+        self.PcdValue = PcdValue
+        self.PcdType = PcdType
+
+    def __call__(self, RealValue=False, Depth=0):
+        PcdValue = self.PcdValue
+        try:
+            PcdValue = ValueExpression.__call__(self, RealValue, Depth)
+        except WrnExpression, Value:
+            PcdValue = Value.result
+
+        if PcdValue == 'True':
+            PcdValue = '1'
+        if PcdValue == 'False':
+            PcdValue = '0'
+        if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
+            PcdValue = PcdValue.strip()
+            if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
+                PcdValue = PcdValue[1:-1].split(',')
+            if type(PcdValue) == type([]):
+                TmpValue = 0
+                Size = 0
+                for Item in PcdValue:
+                    if Item.startswith('UINT16'):
+                        ItemSize = 2
+                    elif Item.startswith('UINT32'):
+                        ItemSize = 4
+                    elif Item.startswith('UINT64'):
+                        ItemSize = 8
+                    else:
+                        ItemSize = 0
+                    Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
+
+                    if ItemSize == 0:
+                        ItemValue, ItemSize = ParseFieldValue(Item)
+                    else:
+                        ItemValue = ParseFieldValue(Item)[0]
+
+                    if type(ItemValue) == type(''):
+                        ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)
+
+                    TmpValue = (ItemValue << (Size * 8)) | TmpValue
+                    Size = Size + ItemSize
+            else:
+                TmpValue, Size = ParseFieldValue(PcdValue)
+            if type(TmpValue) == type(''):
+                TmpValue = int(TmpValue)
+            else:
+                PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
+            if TmpValue < 0:
+                raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
+            if self.PcdType == 'UINT8' and Size > 1:
+                raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
+            if self.PcdType == 'UINT16' and Size > 2:
+                raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
+            if self.PcdType == 'UINT32' and Size > 4:
+                raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
+            if self.PcdType == 'UINT64' and Size > 8:
+                raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
+        if self.PcdType in ['VOID*']:
+            try:
+                TmpValue = long(PcdValue)
+                TmpList = []
+                if TmpValue.bit_length() == 0:
+                    PcdValue = '{0x00}'
+                else:
+                    for I in range((TmpValue.bit_length() + 7) / 8):
+                        TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
+                    PcdValue = '{' + ', '.join(TmpList) + '}'
+            except:
+                if PcdValue.strip().startswith('{'):
+                    PcdValue = PcdValue.strip()[1:-1].strip()
+                    Size = 0
+                    ValueStr = ''
+                    TokenSpaceGuidName = ''
+                    if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
+                        try:
+                            TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)
+                        except:
+                            pass
+                        if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
+                            PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
+                        elif TokenSpaceGuidName:
+                            raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
+
+                        ListItem, Size = ParseFieldValue(PcdValue)
+                    elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
+                        ListItem, Size = ParseFieldValue(PcdValue)
+                    else:
+                        ListItem = PcdValue.split(',')
+
+                    if type(ListItem) == type(0) or type(ListItem) == type(0L):
+                        for Index in range(0, Size):
+                            ValueStr += '0x%02X' % (int(ListItem) & 255)
+                            ListItem >>= 8
+                            ValueStr += ', '
+                            PcdValue = '{' + ValueStr[:-2] + '}'
+                    elif type(ListItem) == type(''):
+                        if ListItem.startswith('{') and ListItem.endswith('}'):
+                            PcdValue = ListItem
+                    else:
+                        LabelDict = {}
+                        ReLabel = re.compile('LABEL\((\w+)\)')
+                        ReOffset = re.compile('OFFSET_OF\((\w+)\)')
+                        for Index, Item in enumerate(ListItem):
+                            # for LABEL parse
+                            Item = Item.strip()
+                            try:
+                                LabelList = ReLabel.findall(Item)
+                                for Label in LabelList:
+                                    if Label not in LabelDict.keys():
+                                        LabelDict[Label] = str(Index)
+                                Item = ReLabel.sub('', Item)
+                            except:
+                                pass
+                            try:
+                                OffsetList = ReOffset.findall(Item)
+                            except:
+                                pass
+                            for Offset in OffsetList:
+                                if Offset in LabelDict.keys():
+                                    Re = re.compile('OFFSET_OF\(%s\)'% Offset)
+                                    Item = Re.sub(LabelDict[Offset], Item)
+                                else:
+                                    raise BadExpression('%s not defined before use' % Offset)
+                            if Item.startswith('UINT16'):
+                                ItemSize = 2
+                            elif Item.startswith('UINT32'):
+                                ItemSize = 4
+                            elif Item.startswith('UINT64'):
+                                ItemSize = 8
+                            else:
+                                ItemSize = 0
+                            TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
+                            Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
+                            if ItemSize == 0:
+                                ItemValue, ItemSize = ParseFieldValue(Item)
+                            else:
+                                ItemValue = ParseFieldValue(Item)[0]
+                            for I in range(0, ItemSize):
+                                ValueStr += '0x%02X' % (int(ItemValue) & 255)
+                                ItemValue >>= 8
+                                ValueStr += ', '
+                            Size += ItemSize
+
+                        if Size > 0:
+                            PcdValue = '{' + ValueStr[:-2] + '}'
+        if RealValue:
+            return PcdValue
+
 if __name__ == '__main__':
     pass
     while True:
         input = raw_input('Input expr: ')
         if input in 'qQ':
diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
index 0374be0..c51b685 100644
--- a/BaseTools/Source/Python/Common/Misc.py
+++ b/BaseTools/Source/Python/Common/Misc.py
@@ -35,10 +35,11 @@ from BuildToolError import *
 from CommonDataClass.DataClass import *
 from Parsing import GetSplitValueList
 from Common.LongFilePathSupport import OpenLongFilePath as open
 from Common.MultipleWorkspace import MultipleWorkspace as mws
 import uuid
+from CommonDataClass.Exceptions import BadExpression
 
 ## Regular expression used to find out place holders in string template
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)
 
 ## Dictionary used to store file time stamp for quick re-access
@@ -1470,103 +1471,123 @@ def AnalyzePcdExpression(Setting):
         FieldList.append(Setting[StartPos:Pos].strip())
         StartPos = Pos + 1
 
     return FieldList
 
+def ParseDevPathValue (Value):
+    pass
+
 def ParseFieldValue (Value):
-  if type(Value) == type(0):
-    return Value, (Value.bit_length() + 7) / 8
-  if type(Value) <> type(''):
-    raise ValueError
-  Value = Value.strip()
-  if Value.startswith('UINT8') and Value.endswith(')'):
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
-    if Size > 1:
-      raise ValueError
+    if type(Value) == type(0):
+        return Value, (Value.bit_length() + 7) / 8
+    if type(Value) <> type(''):
+        raise BadExpression('Type %s is %s' %(Value, type(Value)))
+    Value = Value.strip()
+    if Value.startswith('UINT8') and Value.endswith(')'):
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
+        if Size > 1:
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))
+        return Value, 1
+    if Value.startswith('UINT16') and Value.endswith(')'):
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
+        if Size > 2:
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))
+        return Value, 2
+    if Value.startswith('UINT32') and Value.endswith(')'):
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
+        if Size > 4:
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))
+        return Value, 4
+    if Value.startswith('UINT64') and Value.endswith(')'):
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
+        if Size > 8:
+            raise BadExpression('Value (%s) Size larger than %d' % (Value, Size))
+        return Value, 8
+    if Value.startswith('GUID') and Value.endswith(')'):
+        Value = Value.split('(', 1)[1][:-1].strip()
+        if Value[0] == '{' and Value[-1] == '}':
+            Value = Value[1:-1].strip()
+            Value = Value.split('{', 1)
+            Value = ['%02x' % int(Item, 16) for Item in (Value[0] + Value[1][:-1]).split(',')]
+            if len(Value[0]) != 8:
+                Value[0] = '%08X' % int(Value[0], 16)
+            if len(Value[1]) != 4:
+                Value[1] = '%04X' % int(Value[1], 16)
+            if len(Value[2]) != 4:
+                Value[2] = '%04X' % int(Value[2], 16)
+            Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11])
+        if Value[0] == '"' and Value[-1] == '"':
+            Value = Value[1:-1]
+        try:
+            Value = "'" + uuid.UUID(Value).get_bytes_le() + "'"
+        except ValueError, Message:
+            raise BadExpression('%s' % Message)
+        Value, Size = ParseFieldValue(Value)
+        return Value, 16
+    if Value.startswith('L"') and Value.endswith('"'):
+        # Unicode String
+        List = list(Value[2:-1])
+        List.reverse()
+        Value = 0
+        for Char in List:
+            Value = (Value << 16) | ord(Char)
+        return Value, (len(List) + 1) * 2
+    if Value.startswith('"') and Value.endswith('"'):
+        # ASCII String
+        List = list(Value[1:-1])
+        List.reverse()
+        Value = 0
+        for Char in List:
+            Value = (Value << 8) | ord(Char)
+        return Value, len(List) + 1
+    if Value.startswith("L'") and Value.endswith("'"):
+        # Unicode Character Constant
+        List = list(Value[2:-1])
+        List.reverse()
+        Value = 0
+        for Char in List:
+            Value = (Value << 16) | ord(Char)
+        return Value, len(List) * 2
+    if Value.startswith("'") and Value.endswith("'"):
+        # Character constant
+        List = list(Value[1:-1])
+        List.reverse()
+        Value = 0
+        for Char in List:
+            Value = (Value << 8) | ord(Char)
+        return Value, len(List)
+    if Value.startswith('{') and Value.endswith('}'):
+        # Byte array
+        Value = Value[1:-1]
+        List = [Item.strip() for Item in Value.split(',')]
+        List.reverse()
+        Value = 0
+        RetSize = 0
+        for Item in List:
+            ItemValue, Size = ParseFieldValue(Item)
+            RetSize += Size
+            for I in range(Size):
+                Value = (Value << 8) | ((ItemValue >> 8 * I) & 0xff)
+        return Value, RetSize
+    if Value.startswith('DEVICE_PATH(') and Value.endswith(')'):
+        Value = Value.split('"')[1]
+        return ParseDevPathValue(Value)
+    if Value.lower().startswith('0x'):
+        Value = int(Value, 16)
+        if Value == 0:
+            return 0, 1
+        return Value, (Value.bit_length() + 7) / 8
+    if Value[0].isdigit():
+        Value = int(Value, 10)
+        if Value == 0:
+            return 0, 1
+        return Value, (Value.bit_length() + 7) / 8
+    if Value.lower() == 'true':
+        return 1, 1
+    if Value.lower() == 'false':
+        return 0, 1
     return Value, 1
-  if Value.startswith('UINT16') and Value.endswith(')'):
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
-    if Size > 2:
-      raise ValueError
-    return Value, 2
-  if Value.startswith('UINT32') and Value.endswith(')'):
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
-    if Size > 4:
-      raise ValueError
-    return Value, 4
-  if Value.startswith('UINT64') and Value.endswith(')'):
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
-    if Size > 8:
-      raise ValueError
-    return Value, 8
-  if Value.startswith('GUID') and Value.endswith(')'):
-    Value = Value.split('(', 1)[1][:-1].strip()
-    if Value[0] == '{' and Value[-1] == '}':
-      Value = Value[1:-1].strip()
-      Value = Value.split('{', 1)
-      Value = [Item.strip()[2:] for Item in (Value[0] + Value[1][:-1]).split(',')]
-      Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11])
-    if Value[0] == '"' and Value[-1] == '"':
-      Value = Value[1:-1]
-    Value = "'" + uuid.UUID(Value).get_bytes_le() + "'"
-    Value, Size = ParseFieldValue(Value)
-    return Value, 16
-  if Value.startswith('L"') and Value.endswith('"'):
-    # Unicode String
-    List = list(Value[2:-1])
-    List.reverse()
-    Value = 0
-    for Char in List:
-      Value = (Value << 16) | ord(Char)
-    return Value, (len(List) + 1) * 2
-  if Value.startswith('"') and Value.endswith('"'):
-    # ASCII String
-    List = list(Value[1:-1])
-    List.reverse()
-    Value = 0
-    for Char in List:
-      Value = (Value << 8) | ord(Char)
-    return Value, len(List) + 1
-  if Value.startswith("L'") and Value.endswith("'"):
-    # Unicode Character Constant
-    List = list(Value[2:-1])
-    List.reverse()
-    Value = 0
-    for Char in List:
-      Value = (Value << 16) | ord(Char)
-    return Value, len(List) * 2
-  if Value.startswith("'") and Value.endswith("'"):
-    # Character constant
-    List = list(Value[1:-1])
-    List.reverse()
-    Value = 0
-    for Char in List:
-      Value = (Value << 8) | ord(Char)
-    return Value, len(List)
-  if Value.startswith('{') and Value.endswith('}'):
-    # Byte array
-    Value = Value[1:-1]
-    List = [Item.strip() for Item in Value.split(',')]
-    List.reverse()
-    Value = 0
-    for Item in List:
-      ItemValue, Size = ParseFieldValue(Item)
-      if Size > 1:
-        raise ValueError
-      Value = (Value << 8) | ItemValue
-    return Value, len(List)
-  if Value.lower().startswith('0x'):
-    Value = int(Value, 16)
-    return Value, (Value.bit_length() + 7) / 8
-  if Value[0].isdigit():
-    Value = int(Value, 10)
-    return Value, (Value.bit_length() + 7) / 8
-  if Value.lower() == 'true':
-    return 1, 1
-  if Value.lower() == 'false':
-    return 0, 1
-  return Value, 1
 
 ## AnalyzeDscPcd
 #
 #  Analyze DSC PCD value, since there is no data type info in DSC
 #  This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index e422100..05b26a3 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -798,11 +798,11 @@ class DscBuildData(PlatformBuildClassObject):
                 if ModuleFile in self._Modules:
                     continue
                 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
                 PkgSet.update(ModuleData.Packages)
 
-            self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
+            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
 
 
         if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
             EdkLogger.error('build', PARSER_ERROR,
                             "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),
@@ -819,10 +819,12 @@ class DscBuildData(PlatformBuildClassObject):
         if ValueList[Index] and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
             try:
                 ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)
             except WrnExpression, Value:
                 ValueList[Index] = Value.result
+            except BadExpression, Value:
+                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
             except EvaluationException, Excpt:
                 if hasattr(Excpt, 'Pcd'):
                     if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
                         EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
                                         " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
@@ -832,15 +834,17 @@ class DscBuildData(PlatformBuildClassObject):
                         EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
                                         File=self.MetaFile, Line=LineNo)
                 else:
                     EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
                                     File=self.MetaFile, Line=LineNo)
-            if ValueList[Index] == 'True':
-                ValueList[Index] = '1'
-            elif ValueList[Index] == 'False':
-                ValueList[Index] = '0'
         if ValueList[Index]:
+            DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
+            try:
+                ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
+            except BadExpression, Value:
+                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
+                                ExtraData="PCD [%s.%s] Value \"%s\" " % (TokenSpaceGuid, PcdCName, ValueList[Index]))
             Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
             if not Valid:
                 EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
                                 ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
             if PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
diff --git a/BaseTools/Source/Python/Workspace/InfBuildData.py b/BaseTools/Source/Python/Workspace/InfBuildData.py
index fd94067..7ea9b56 100644
--- a/BaseTools/Source/Python/Workspace/InfBuildData.py
+++ b/BaseTools/Source/Python/Workspace/InfBuildData.py
@@ -14,10 +14,11 @@
 
 from Common.String import *
 from Common.DataType import *
 from Common.Misc import *
 from types import *
+from MetaFileParser import *
 
 from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject
 ## Module build information from INF file
 #
 #  This class is used to retrieve information stored in database and convert them
@@ -1142,10 +1143,16 @@ class InfBuildData(ModuleBuildClassObject):
                     Pcd.DatumType = PcdInPackage.DatumType
                     Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
                     Pcd.InfDefaultValue = Pcd.DefaultValue
                     if Pcd.DefaultValue in [None, '']:
                         Pcd.DefaultValue = PcdInPackage.DefaultValue
+                    else:
+                        try:
+                            Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue, Pcd.DatumType, self.Guids)(True)
+                        except BadExpression, Value:
+                            EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid, PcdRealName, Pcd.DefaultValue, Value),
+                                            File=self.MetaFile, Line=LineNo)
                     break
             else:
                 EdkLogger.error(
                             'build',
                             FORMAT_INVALID,
diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py
index 3038447..b2b0e28 100644
--- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
+++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
@@ -25,11 +25,11 @@ import Common.EdkLogger as EdkLogger
 import Common.GlobalData as GlobalData
 
 from CommonDataClass.DataClass import *
 from Common.DataType import *
 from Common.String import *
-from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression
+from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue
 from Common.Expression import *
 from CommonDataClass.Exceptions import *
 from Common.LongFilePathSupport import OpenLongFilePath as open
 
 from MetaFileTable import MetaFileStorage
@@ -180,10 +180,11 @@ class MetaFileParser(object):
         self._Enabled = 0
         self._Finished = False
         self._PostProcessed = False
         # Different version of meta-file has different way to parse.
         self._Version = 0
+        self._GuidDict = {}  # for Parser PCD value {GUID(gTokeSpaceGuidName)}
 
     ## Store the parsed data in table
     def _Store(self, *Args):
         return self._Table.Insert(*Args)
 
@@ -1869,10 +1870,12 @@ class DecParser(MetaFileParser):
                             ExtraData=self._CurrentLine + \
                                       " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
                             File=self.MetaFile, Line=self._LineIndex + 1)
         self._ValueList[0] = TokenList[0]
         self._ValueList[1] = TokenList[1]
+        if self._ValueList[0] not in self._GuidDict:
+            self._GuidDict[self._ValueList[0]] = self._ValueList[1]
 
     ## PCD sections parser
     #
     #   [PcdsFixedAtBuild]
     #   [PcdsPatchableInModule]
@@ -1985,16 +1988,18 @@ class DecParser(MetaFileParser):
             if PcdValue:
                 try:
                     ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
                 except WrnExpression, Value:
                     ValueList[0] = Value.result
+                except BadExpression, Value:
+                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
 
-            if ValueList[0] == 'True':
-                ValueList[0] = '1'
-            if ValueList[0] == 'False':
-                ValueList[0] = '0'
-
+            if ValueList[0]:
+                try:
+                    ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
+                except BadExpression, Value:
+                    EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
             # check format of default value against the datum type
             IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
             if not IsValid:
                 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
                                 File=self.MetaFile, Line=self._LineIndex + 1)
diff --git a/BaseTools/Source/Python/Workspace/WorkspaceCommon.py b/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
index c289b9d..c760e57 100644
--- a/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
+++ b/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
@@ -1,9 +1,9 @@
 ## @file
 # Common routines used by workspace
 #
-# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012 - 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
 #
@@ -41,28 +41,32 @@ def GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain):
 #  @param BuildDatabase: The database saves all data for all metafiles
 #  @param Arch: Current arch
 #  @param Target: Current target
 #  @param Toolchain: Current toolchain
 #  @retval: A dictionary contains instances of PcdClassObject with key (PcdCName, TokenSpaceGuid)
+#  @retval: A dictionary contains real GUIDs of TokenSpaceGuid
 #
 def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain,additionalPkgs):
     PkgList = GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain)
     PkgList = set(PkgList)
     PkgList |= additionalPkgs
     DecPcds = {}
+    GuidDict = {}
     for Pkg in PkgList:
+        Guids = Pkg.Guids
+        GuidDict.update(Guids)
         for Pcd in Pkg.Pcds:
             PcdCName = Pcd[0]
             PcdTokenName = Pcd[1]
             if GlobalData.MixedPcd:
                 for PcdItem in GlobalData.MixedPcd.keys():
                     if (PcdCName, PcdTokenName) in GlobalData.MixedPcd[PcdItem]:
                         PcdCName = PcdItem[0]
                         break
             if (PcdCName, PcdTokenName) not in DecPcds.keys():
                 DecPcds[PcdCName, PcdTokenName] = Pkg.Pcds[Pcd]
-    return DecPcds
+    return DecPcds, GuidDict
 
 ## Get all dependent libraries for a module
 #
 #  @param Module: InfBuildData instance
 #  @param Platform: DscBuildData instance
diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py
index 75e8ec9..5da9914 100644
--- a/BaseTools/Source/Python/build/BuildReport.py
+++ b/BaseTools/Source/Python/build/BuildReport.py
@@ -43,10 +43,11 @@ import Common.GlobalData as GlobalData
 from AutoGen.AutoGen import ModuleAutoGen
 from Common.Misc import PathClass
 from Common.String import NormPath
 from Common.DataType import *
 import collections
+from Common.Expression import ValueExpressionEx
 
 ## Pattern to extract contents in EDK DXS files
 gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)
 
 ## Pattern to find total FV total size, occupied size in flash report intermediate file
@@ -847,12 +848,15 @@ class PcdReport(object):
 
         #
         # Collect PCD DEC default value.
         #
         self.DecPcdDefault = {}
+        self._GuidDict = {}
         for Pa in Wa.AutoGenObjectList:
             for Package in Pa.PackageList:
+                Guids = Package.Guids
+                self._GuidDict.update(Guids)
                 for (TokenCName, TokenSpaceGuidCName, DecType) in Package.Pcds:
                     DecDefaultValue = Package.Pcds[TokenCName, TokenSpaceGuidCName, DecType].DefaultValue
                     self.DecPcdDefault.setdefault((TokenCName, TokenSpaceGuidCName, DecType), DecDefaultValue)
         #
         # Collect PCDs defined in DSC common section
@@ -941,10 +945,12 @@ class PcdReport(object):
                     #
                     DecDefaultValue = self.DecPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType))
                     DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
                     DscDefaultValBak= DscDefaultValue
                     DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue)
+                    if DscDefaultValue:
+                        DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
                     InfDefaultValue = None
                     
                     PcdValue = DecDefaultValue
                     if DscDefaultValue:
                         PcdValue = DscDefaultValue
-- 
2.6.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Patch 2/2] BaseTools: Add DevicePath support for PCD values
  2017-12-26 16:40 [Patch 0/2] BaseTools: Add Flexible PCD Value support Yonghong Zhu
  2017-12-26 16:40 ` [Patch 1/2] BaseTools: Support PCD flexible values format Yonghong Zhu
@ 2017-12-26 16:40 ` Yonghong Zhu
  2017-12-27  2:40   ` Gao, Liming
  1 sibling, 1 reply; 4+ messages in thread
From: Yonghong Zhu @ 2017-12-26 16:40 UTC (permalink / raw)
  To: edk2-devel; +Cc: Yunhua Feng

Use C code parse device path to output hex string, and Python
run command when PCD Value need device path parse.

https://bugzilla.tianocore.org/show_bug.cgi?id=541

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
---
 BaseTools/Source/BinaryFiles.txt                   |    3 +-
 BaseTools/Source/C/DevicePath/DevicePath.c         |  188 ++
 BaseTools/Source/C/DevicePath/DevicePath.h         | 1404 ++++++++
 BaseTools/Source/C/DevicePath/DevicePathFromText.c | 3503 ++++++++++++++++++++
 BaseTools/Source/C/DevicePath/DevicePathFromText.h |   72 +
 .../Source/C/DevicePath/DevicePathUtilities.c      | 2352 +++++++++++++
 .../Source/C/DevicePath/DevicePathUtilities.h      |  555 ++++
 BaseTools/Source/C/DevicePath/GNUmakefile          |   30 +
 BaseTools/Source/C/DevicePath/Makefile             |   24 +
 BaseTools/Source/C/DevicePath/UefiDevicePathLib.c  |  298 ++
 BaseTools/Source/C/DevicePath/UefiDevicePathLib.h  |  473 +++
 BaseTools/Source/C/GNUmakefile                     |    3 +-
 BaseTools/Source/C/Makefile                        |    5 +-
 BaseTools/Source/Python/Common/Misc.py             |   35 +-
 BaseTools/Source/Python/Workspace/DscBuildData.py  |    2 +-
 15 files changed, 8940 insertions(+), 7 deletions(-)
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePath.c
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePath.h
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathFromText.c
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathFromText.h
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathUtilities.c
 create mode 100644 BaseTools/Source/C/DevicePath/DevicePathUtilities.h
 create mode 100644 BaseTools/Source/C/DevicePath/GNUmakefile
 create mode 100644 BaseTools/Source/C/DevicePath/Makefile
 create mode 100644 BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
 create mode 100644 BaseTools/Source/C/DevicePath/UefiDevicePathLib.h

diff --git a/BaseTools/Source/BinaryFiles.txt b/BaseTools/Source/BinaryFiles.txt
index 7b014a7..a5273d4 100644
--- a/BaseTools/Source/BinaryFiles.txt
+++ b/BaseTools/Source/BinaryFiles.txt
@@ -9,11 +9,11 @@
 # [ExtraFiles.Win32] section.
 # The [CxFreeze.Win32] section is maintained by the owner of the Build Server who
 # must ensure that files that are required by the cx_freeze frozen binaries are 
 # present in the Bin\Win32 directory.
 #
-# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 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
@@ -57,10 +57,11 @@ TianoCompress.exe
 Trim.exe
 UPT.exe
 VfrCompile.exe
 VolInfo.exe
 Pkcs7Sign.exe
+DevicePath.exe
 
 [ExtraFiles.Win32]
 TestSigningPrivateKey.pem
 config.ini
 exception.xml
diff --git a/BaseTools/Source/C/DevicePath/DevicePath.c b/BaseTools/Source/C/DevicePath/DevicePath.c
new file mode 100644
index 0000000..6c32ad4
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/DevicePath.c
@@ -0,0 +1,188 @@
+/** @file
+  Definition for Device Path Tool.
+
+Copyright (c) 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"
+
+//
+// Utility Name
+//
+#define UTILITY_NAME  "DevicePath"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+
+EFI_GUID gEfiDebugPortDevicePathGuid = DEVICE_PATH_MESSAGING_DEBUGPORT;
+EFI_GUID gEfiPcAnsiGuid = EFI_PC_ANSI_GUID;
+EFI_GUID gEfiVT100Guid = EFI_VT_100_GUID;
+EFI_GUID gEfiVT100PlusGuid = EFI_VT_100_PLUS_GUID;
+EFI_GUID gEfiVTUTF8Guid = EFI_VT_UTF8_GUID;
+EFI_GUID gEfiUartDevicePathGuid = EFI_UART_DEVICE_PATH_GUID;
+EFI_GUID gEfiSasDevicePathGuid = EFI_SAS_DEVICE_PATH_GUID;
+EFI_GUID gEfiVirtualDiskGuid = { 0x77AB535A, 0x45FC, 0x624B, {0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }};
+EFI_GUID gEfiVirtualCdGuid = { 0x3D5ABD30, 0x4175, 0x87CE, {0x6D, 0x64, 0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB }};
+EFI_GUID gEfiPersistentVirtualDiskGuid =  { 0x5CEA02C9, 0x4D07, 0x69D3, {0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 }};
+EFI_GUID gEfiPersistentVirtualCdGuid = { 0x08018188, 0x42CD, 0xBB48, {0x10, 0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D }};
+
+STATIC
+VOID
+Version (
+  VOID
+)
+/*++
+
+Routine Description:
+
+  Displays the standard utility information to SDTOUT
+
+Arguments:
+
+  None
+
+Returns:
+
+  None
+
+--*/
+{
+  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
+}
+
+STATIC
+VOID
+Usage (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+  None
+
+Returns:
+
+  None
+
+--*/
+{
+  //
+  // Summary usage
+  //
+  fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME);
+
+  //
+  // Copyright declaration
+  //
+  fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
+  //
+  // Details Option
+  //
+  fprintf (stdout, "Options:\n");
+  fprintf (stdout, "  DevicePathString      DevicePathString like as:\n"
+                "                        \"PciRoot(0)/Pci(0,0)\"\n"
+                "                        start with \" and end with \"\n"
+                "                        not support blank in device path string.\n");
+
+  fprintf (stdout, "  --version             Show program's version number and exit.\n");
+  fprintf (stdout, "  -h, --help            Show this help message and exit.\n");
+}
+
+
+void print_mem(void const *vp, size_t n)
+{
+    unsigned char const *p = vp;
+    for (size_t i=0; i<n; i++) {
+        printf("0x%02x ", p[i]);
+  }
+}
+
+VOID
+Ascii2UnicodeString (
+  CHAR8    *String,
+  CHAR16   *UniString
+ )
+/*++
+
+Routine Description:
+
+  Write ascii string as unicode string format to FILE
+
+Arguments:
+
+  String      - Pointer to string that is written to FILE.
+  UniString   - Pointer to unicode string
+
+Returns:
+
+  NULL
+
+--*/
+{
+  while (*String != '\0') {
+    *(UniString++) = (CHAR16) *(String++);
+  }
+  //
+  // End the UniString with a NULL.
+  //
+  *UniString = '\0';
+}
+
+int main(int argc, CHAR8 *argv[])
+{
+  CHAR8 * Str;
+  CHAR16* Str16;
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+  if (argc == 1) {
+    Error (NULL, 0, 1001, "Missing options", "No input options specified.");
+    Usage ();
+    return STATUS_ERROR;
+  }
+  if ((stricmp (argv[1], "-h") == 0) || (stricmp (argv[1], "--help") == 0)) {
+    Version ();
+    Usage ();
+    return STATUS_SUCCESS;
+  }
+
+  if (stricmp (argv[1], "--version") == 0) {
+    Version ();
+    return STATUS_SUCCESS;
+  }
+  Str = argv[1];
+  if (Str == NULL) {
+    fprintf(stderr, "Invalid option value, Device Path can't be NULL");
+    return STATUS_ERROR;
+  }
+  Str16 = (CHAR16 *)malloc(1024);
+  if (Str16 == NULL) {
+    fprintf(stderr, "Resource, memory cannot be allcoated");
+    return STATUS_ERROR;
+  }
+  Ascii2UnicodeString(Str, Str16);
+  DevicePath = UefiDevicePathLibConvertTextToDevicePath(Str16);
+  while (!((DevicePath->Type == END_DEVICE_PATH_TYPE) && (DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) )
+  {
+    print_mem(DevicePath, (DevicePath->Length[0] | DevicePath->Length[1] << 8));
+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePath + (DevicePath->Length[0] | DevicePath->Length[1] << 8));
+  }
+  print_mem(DevicePath, (DevicePath->Length[0] | DevicePath->Length[1] << 8));
+  putchar('\n');
+  return STATUS_SUCCESS;
+}
diff --git a/BaseTools/Source/C/DevicePath/DevicePath.h b/BaseTools/Source/C/DevicePath/DevicePath.h
new file mode 100644
index 0000000..389c993
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/DevicePath.h
@@ -0,0 +1,1404 @@
+/** @file
+  The device path protocol as defined in UEFI 2.0.
+
+  The device path represents a programmatic path to a device,
+  from a software point of view. The path must persist from boot to boot, so
+  it can not contain things like PCI bus numbers that change from boot to boot.
+
+Copyright (c) 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 that 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 __EFI_DEVICE_PATH_H__
+#define __EFI_DEVICE_PATH_H__
+
+#include <Guid/PcAnsi.h>
+#include <IndustryStandard/Acpi3_0.h>
+
+///
+/// Device Path protocol.
+///
+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
+  { \
+    0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+  }
+
+///
+/// Device Path guid definition for backward-compatible with EFI1.1.
+///
+#define DEVICE_PATH_PROTOCOL  EFI_DEVICE_PATH_PROTOCOL_GUID
+
+#pragma pack(1)
+
+/**
+  This protocol can be used on any device handle to obtain generic path/location
+  information concerning the physical device or logical device. If the handle does
+  not logically map to a physical device, the handle may not necessarily support
+  the device path protocol. The device path describes the location of the device
+  the handle is for. The size of the Device Path can be determined from the structures
+  that make up the Device Path.
+**/
+typedef struct {
+  UINT8 Type;       ///< 0x01 Hardware Device Path.
+                    ///< 0x02 ACPI Device Path.
+                    ///< 0x03 Messaging Device Path.
+                    ///< 0x04 Media Device Path.
+                    ///< 0x05 BIOS Boot Specification Device Path.
+                    ///< 0x7F End of Hardware Device Path.
+
+  UINT8 SubType;    ///< Varies by Type
+                    ///< 0xFF End Entire Device Path, or
+                    ///< 0x01 End This Instance of a Device Path and start a new
+                    ///< Device Path.
+
+  UINT8 Length[2];  ///< Specific Device Path data. Type and Sub-Type define
+                    ///< type of data. Size of data is included in Length.
+
+} EFI_DEVICE_PATH_PROTOCOL;
+
+///
+/// Device Path protocol definition for backward-compatible with EFI1.1.
+///
+typedef EFI_DEVICE_PATH_PROTOCOL  EFI_DEVICE_PATH;
+
+///
+/// Hardware Device Paths.
+///
+#define HARDWARE_DEVICE_PATH      0x01
+
+///
+/// PCI Device Path SubType.
+///
+#define HW_PCI_DP                 0x01
+
+///
+/// PCI Device Path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// PCI Function Number.
+  ///
+  UINT8                           Function;
+  ///
+  /// PCI Device Number.
+  ///
+  UINT8                           Device;
+} PCI_DEVICE_PATH;
+
+///
+/// PCCARD Device Path SubType.
+///
+#define HW_PCCARD_DP              0x02
+
+///
+/// PCCARD Device Path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Function Number (0 = First Function).
+  ///
+  UINT8                           FunctionNumber;
+} PCCARD_DEVICE_PATH;
+
+///
+/// Memory Mapped Device Path SubType.
+///
+#define HW_MEMMAP_DP             0x03
+
+///
+/// Memory Mapped Device Path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// EFI_MEMORY_TYPE
+  ///
+  UINT32                          MemoryType;
+  ///
+  /// Starting Memory Address.
+  ///
+  EFI_PHYSICAL_ADDRESS            StartingAddress;
+  ///
+  /// Ending Memory Address.
+  ///
+  EFI_PHYSICAL_ADDRESS            EndingAddress;
+} MEMMAP_DEVICE_PATH;
+
+///
+/// Hardware Vendor Device Path SubType.
+///
+#define HW_VENDOR_DP              0x04
+
+///
+/// The Vendor Device Path allows the creation of vendor-defined Device Paths. A vendor must
+/// allocate a Vendor GUID for a Device Path. The Vendor GUID can then be used to define the
+/// contents on the n bytes that follow in the Vendor Device Path node.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Vendor-assigned GUID that defines the data that follows.
+  ///
+  EFI_GUID                        Guid;
+  ///
+  /// Vendor-defined variable size data.
+  ///
+} VENDOR_DEVICE_PATH;
+
+///
+/// Controller Device Path SubType.
+///
+#define HW_CONTROLLER_DP          0x05
+
+///
+/// Controller Device Path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Controller number.
+  ///
+  UINT32                          ControllerNumber;
+} CONTROLLER_DEVICE_PATH;
+
+///
+/// BMC Device Path SubType.
+///
+#define HW_BMC_DP                 0x06
+
+///
+/// BMC Device Path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Interface Type.
+  ///
+  UINT8                           InterfaceType;
+  ///
+  /// Base Address.
+  ///
+  UINT8                           BaseAddress[8];
+} BMC_DEVICE_PATH;
+
+///
+/// ACPI Device Paths.
+///
+#define ACPI_DEVICE_PATH          0x02
+
+///
+/// ACPI Device Path SubType.
+///
+#define ACPI_DP                   0x01
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Device's PnP hardware ID stored in a numeric 32-bit
+  /// compressed EISA-type ID. This value must match the
+  /// corresponding _HID in the ACPI name space.
+  ///
+  UINT32                          HID;
+  ///
+  /// Unique ID that is required by ACPI if two devices have the
+  /// same _HID. This value must also match the corresponding
+  /// _UID/_HID pair in the ACPI name space. Only the 32-bit
+  /// numeric value type of _UID is supported. Thus, strings must
+  /// not be used for the _UID in the ACPI name space.
+  ///
+  UINT32                          UID;
+} ACPI_HID_DEVICE_PATH;
+
+///
+/// Expanded ACPI Device Path SubType.
+///
+#define ACPI_EXTENDED_DP          0x02
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Device's PnP hardware ID stored in a numeric 32-bit
+  /// compressed EISA-type ID. This value must match the
+  /// corresponding _HID in the ACPI name space.
+  ///
+  UINT32                          HID;
+  ///
+  /// Unique ID that is required by ACPI if two devices have the
+  /// same _HID. This value must also match the corresponding
+  /// _UID/_HID pair in the ACPI name space.
+  ///
+  UINT32                          UID;
+  ///
+  /// Device's compatible PnP hardware ID stored in a numeric
+  /// 32-bit compressed EISA-type ID. This value must match at
+  /// least one of the compatible device IDs returned by the
+  /// corresponding _CID in the ACPI name space.
+  ///
+  UINT32                          CID;
+  ///
+  /// Optional variable length _HIDSTR.
+  /// Optional variable length _UIDSTR.
+  /// Optional variable length _CIDSTR.
+  ///
+} ACPI_EXTENDED_HID_DEVICE_PATH;
+
+//
+//  EISA ID Macro
+//  EISA ID Definition 32-bits
+//   bits[15:0] - three character compressed ASCII EISA ID.
+//   bits[31:16] - binary number
+//    Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z'
+//
+#define PNP_EISA_ID_CONST         0x41d0
+#define EISA_ID(_Name, _Num)      ((UINT32)((_Name) | (_Num) << 16))
+#define EISA_PNP_ID(_PNPId)       (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
+#define EFI_PNP_ID(_PNPId)        (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
+
+#define PNP_EISA_ID_MASK          0xffff
+#define EISA_ID_TO_NUM(_Id)       ((_Id) >> 16)
+
+///
+/// ACPI _ADR Device Path SubType.
+///
+#define ACPI_ADR_DP               0x03
+
+///
+/// The _ADR device path is used to contain video output device attributes to support the Graphics
+/// Output Protocol. The device path can contain multiple _ADR entries if multiple video output
+/// devices are displaying the same output.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// _ADR value. For video output devices the value of this
+  /// field comes from Table B-2 of the ACPI 3.0 specification. At
+  /// least one _ADR value is required.
+  ///
+  UINT32                          ADR;
+  //
+  // This device path may optionally contain more than one _ADR entry.
+  //
+} ACPI_ADR_DEVICE_PATH;
+
+#define ACPI_ADR_DISPLAY_TYPE_OTHER             0
+#define ACPI_ADR_DISPLAY_TYPE_VGA               1
+#define ACPI_ADR_DISPLAY_TYPE_TV                2
+#define ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL  3
+#define ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL  4
+
+#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput, _BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \
+          ((UINT32)(  ((UINT32)((_DeviceIdScheme) & 0x1) << 31) |  \
+                      (((_HeadId)                 & 0x7) << 18) |  \
+                      (((_NonVgaOutput)           & 0x1) << 17) |  \
+                      (((_BiosCanDetect)          & 0x1) << 16) |  \
+                      (((_VendorInfo)             & 0xf) << 12) |  \
+                      (((_Type)                   & 0xf) << 8)  |  \
+                      (((_Port)                   & 0xf) << 4)  |  \
+                       ((_Index)                  & 0xf) ))
+
+///
+/// Messaging Device Paths.
+/// This Device Path is used to describe the connection of devices outside the resource domain of the
+/// system. This Device Path can describe physical messaging information like SCSI ID, or abstract
+/// information like networking protocol IP addresses.
+///
+#define MESSAGING_DEVICE_PATH     0x03
+
+///
+/// ATAPI Device Path SubType
+///
+#define MSG_ATAPI_DP              0x01
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Set to zero for primary, or one for secondary.
+  ///
+  UINT8                           PrimarySecondary;
+  ///
+  /// Set to zero for master, or one for slave mode.
+  ///
+  UINT8                           SlaveMaster;
+  ///
+  /// Logical Unit Number.
+  ///
+  UINT16                          Lun;
+} ATAPI_DEVICE_PATH;
+
+///
+/// SCSI Device Path SubType.
+///
+#define MSG_SCSI_DP               0x02
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Target ID on the SCSI bus (PUN).
+  ///
+  UINT16                          Pun;
+  ///
+  /// Logical Unit Number (LUN).
+  ///
+  UINT16                          Lun;
+} SCSI_DEVICE_PATH;
+
+///
+/// Fibre Channel SubType.
+///
+#define MSG_FIBRECHANNEL_DP       0x03
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Reserved for the future.
+  ///
+  UINT32                          Reserved;
+  ///
+  /// Fibre Channel World Wide Number.
+  ///
+  UINT64                          WWN;
+  ///
+  /// Fibre Channel Logical Unit Number.
+  ///
+  UINT64                          Lun;
+} FIBRECHANNEL_DEVICE_PATH;
+
+///
+/// Fibre Channel Ex SubType.
+///
+#define MSG_FIBRECHANNELEX_DP     0x15
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Reserved for the future.
+  ///
+  UINT32                          Reserved;
+  ///
+  /// 8 byte array containing Fibre Channel End Device Port Name.
+  ///
+  UINT8                           WWN[8];
+  ///
+  /// 8 byte array containing Fibre Channel Logical Unit Number.
+  ///
+  UINT8                           Lun[8];
+} FIBRECHANNELEX_DEVICE_PATH;
+
+///
+/// 1394 Device Path SubType
+///
+#define MSG_1394_DP               0x04
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Reserved for the future.
+  ///
+  UINT32                          Reserved;
+  ///
+  /// 1394 Global Unique ID (GUID).
+  ///
+  UINT64                          Guid;
+} F1394_DEVICE_PATH;
+
+///
+/// USB Device Path SubType.
+///
+#define MSG_USB_DP                0x05
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL      Header;
+  ///
+  /// USB Parent Port Number.
+  ///
+  UINT8                         ParentPortNumber;
+  ///
+  /// USB Interface Number.
+  ///
+  UINT8                         InterfaceNumber;
+} USB_DEVICE_PATH;
+
+///
+/// USB Class Device Path SubType.
+///
+#define MSG_USB_CLASS_DP          0x0f
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL      Header;
+  ///
+  /// Vendor ID assigned by USB-IF. A value of 0xFFFF will
+  /// match any Vendor ID.
+  ///
+  UINT16                        VendorId;
+  ///
+  /// Product ID assigned by USB-IF. A value of 0xFFFF will
+  /// match any Product ID.
+  ///
+  UINT16                        ProductId;
+  ///
+  /// The class code assigned by the USB-IF. A value of 0xFF
+  /// will match any class code.
+  ///
+  UINT8                         DeviceClass;
+  ///
+  /// The subclass code assigned by the USB-IF. A value of
+  /// 0xFF will match any subclass code.
+  ///
+  UINT8                         DeviceSubClass;
+  ///
+  /// The protocol code assigned by the USB-IF. A value of
+  /// 0xFF will match any protocol code.
+  ///
+  UINT8                         DeviceProtocol;
+} USB_CLASS_DEVICE_PATH;
+
+///
+/// USB WWID Device Path SubType.
+///
+#define MSG_USB_WWID_DP           0x10
+
+///
+/// This device path describes a USB device using its serial number.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL      Header;
+  ///
+  /// USB interface number.
+  ///
+  UINT16                        InterfaceNumber;
+  ///
+  /// USB vendor id of the device.
+  ///
+  UINT16                        VendorId;
+  ///
+  /// USB product id of the device.
+  ///
+  UINT16                        ProductId;
+  ///
+  /// Last 64-or-fewer UTF-16 characters of the USB
+  /// serial number. The length of the string is
+  /// determined by the Length field less the offset of the
+  /// Serial Number field (10)
+  ///
+  /// CHAR16                     SerialNumber[...];
+} USB_WWID_DEVICE_PATH;
+
+///
+/// Device Logical Unit SubType.
+///
+#define MSG_DEVICE_LOGICAL_UNIT_DP  0x11
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL      Header;
+  ///
+  /// Logical Unit Number for the interface.
+  ///
+  UINT8                         Lun;
+} DEVICE_LOGICAL_UNIT_DEVICE_PATH;
+
+///
+/// SATA Device Path SubType.
+///
+#define MSG_SATA_DP               0x12
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// The HBA port number that facilitates the connection to the
+  /// device or a port multiplier. The value 0xFFFF is reserved.
+  ///
+  UINT16                          HBAPortNumber;
+  ///
+  /// The Port multiplier port number that facilitates the connection
+  /// to the device. Must be set to 0xFFFF if the device is directly
+  /// connected to the HBA.
+  ///
+  UINT16                          PortMultiplierPortNumber;
+  ///
+  /// Logical Unit Number.
+  ///
+  UINT16                          Lun;
+} SATA_DEVICE_PATH;
+
+///
+/// Flag for if the device is directly connected to the HBA.
+///
+#define SATA_HBA_DIRECT_CONNECT_FLAG 0x8000
+
+///
+/// I2O Device Path SubType.
+///
+#define MSG_I2O_DP                0x06
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Target ID (TID) for a device.
+  ///
+  UINT32                          Tid;
+} I2O_DEVICE_PATH;
+
+///
+/// MAC Address Device Path SubType.
+///
+#define MSG_MAC_ADDR_DP           0x0b
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// The MAC address for a network interface padded with 0s.
+  ///
+  EFI_MAC_ADDRESS                 MacAddress;
+  ///
+  /// Network interface type(i.e. 802.3, FDDI).
+  ///
+  UINT8                           IfType;
+} MAC_ADDR_DEVICE_PATH;
+
+///
+/// IPv4 Device Path SubType
+///
+#define MSG_IPv4_DP               0x0c
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// The local IPv4 address.
+  ///
+  EFI_IPv4_ADDRESS                LocalIpAddress;
+  ///
+  /// The remote IPv4 address.
+  ///
+  EFI_IPv4_ADDRESS                RemoteIpAddress;
+  ///
+  /// The local port number.
+  ///
+  UINT16                          LocalPort;
+  ///
+  /// The remote port number.
+  ///
+  UINT16                          RemotePort;
+  ///
+  /// The network protocol(i.e. UDP, TCP).
+  ///
+  UINT16                          Protocol;
+  ///
+  /// 0x00 - The Source IP Address was assigned though DHCP.
+  /// 0x01 - The Source IP Address is statically bound.
+  ///
+  BOOLEAN                         StaticIpAddress;
+  ///
+  /// The gateway IP address
+  ///
+  EFI_IPv4_ADDRESS                GatewayIpAddress;
+  ///
+  /// The subnet mask
+  ///
+  EFI_IPv4_ADDRESS                SubnetMask;
+} IPv4_DEVICE_PATH;
+
+///
+/// IPv6 Device Path SubType.
+///
+#define MSG_IPv6_DP               0x0d
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// The local IPv6 address.
+  ///
+  EFI_IPv6_ADDRESS                LocalIpAddress;
+  ///
+  /// The remote IPv6 address.
+  ///
+  EFI_IPv6_ADDRESS                RemoteIpAddress;
+  ///
+  /// The local port number.
+  ///
+  UINT16                          LocalPort;
+  ///
+  /// The remote port number.
+  ///
+  UINT16                          RemotePort;
+  ///
+  /// The network protocol(i.e. UDP, TCP).
+  ///
+  UINT16                          Protocol;
+  ///
+  /// 0x00 - The Local IP Address was manually configured.
+  /// 0x01 - The Local IP Address is assigned through IPv6
+  /// stateless auto-configuration.
+  /// 0x02 - The Local IP Address is assigned through IPv6
+  /// stateful configuration.
+  ///
+  UINT8                           IpAddressOrigin;
+  ///
+  /// The prefix length
+  ///
+  UINT8                           PrefixLength;
+  ///
+  /// The gateway IP address
+  ///
+  EFI_IPv6_ADDRESS                GatewayIpAddress;
+} IPv6_DEVICE_PATH;
+
+///
+/// InfiniBand Device Path SubType.
+///
+#define MSG_INFINIBAND_DP         0x09
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Flags to help identify/manage InfiniBand device path elements:
+  /// Bit 0 - IOC/Service (0b = IOC, 1b = Service).
+  /// Bit 1 - Extend Boot Environment.
+  /// Bit 2 - Console Protocol.
+  /// Bit 3 - Storage Protocol.
+  /// Bit 4 - Network Protocol.
+  /// All other bits are reserved.
+  ///
+  UINT32                          ResourceFlags;
+  ///
+  /// 128-bit Global Identifier for remote fabric port.
+  ///
+  UINT8                           PortGid[16];
+  ///
+  /// 64-bit unique identifier to remote IOC or server process.
+  /// Interpretation of field specified by Resource Flags (bit 0).
+  ///
+  UINT64                          ServiceId;
+  ///
+  /// 64-bit persistent ID of remote IOC port.
+  ///
+  UINT64                          TargetPortId;
+  ///
+  /// 64-bit persistent ID of remote device.
+  ///
+  UINT64                          DeviceId;
+} INFINIBAND_DEVICE_PATH;
+
+#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE                0x01
+#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT  0x02
+#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL           0x04
+#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL           0x08
+#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL           0x10
+
+///
+/// UART Device Path SubType.
+///
+#define MSG_UART_DP               0x0e
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Reserved.
+  ///
+  UINT32                          Reserved;
+  ///
+  /// The baud rate setting for the UART style device. A value of 0
+  /// means that the device's default baud rate will be used.
+  ///
+  UINT64                          BaudRate;
+  ///
+  /// The number of data bits for the UART style device. A value
+  /// of 0 means that the device's default number of data bits will be used.
+  ///
+  UINT8                           DataBits;
+  ///
+  /// The parity setting for the UART style device.
+  /// Parity 0x00 - Default Parity.
+  /// Parity 0x01 - No Parity.
+  /// Parity 0x02 - Even Parity.
+  /// Parity 0x03 - Odd Parity.
+  /// Parity 0x04 - Mark Parity.
+  /// Parity 0x05 - Space Parity.
+  ///
+  UINT8                           Parity;
+  ///
+  /// The number of stop bits for the UART style device.
+  /// Stop Bits 0x00 - Default Stop Bits.
+  /// Stop Bits 0x01 - 1 Stop Bit.
+  /// Stop Bits 0x02 - 1.5 Stop Bits.
+  /// Stop Bits 0x03 - 2 Stop Bits.
+  ///
+  UINT8                           StopBits;
+} UART_DEVICE_PATH;
+
+//
+// Use VENDOR_DEVICE_PATH struct
+//
+#define MSG_VENDOR_DP             0x0a
+typedef VENDOR_DEVICE_PATH        VENDOR_DEFINED_DEVICE_PATH;
+
+#define DEVICE_PATH_MESSAGING_PC_ANSI     EFI_PC_ANSI_GUID
+#define DEVICE_PATH_MESSAGING_VT_100      EFI_VT_100_GUID
+#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID
+#define DEVICE_PATH_MESSAGING_VT_UTF8     EFI_VT_UTF8_GUID
+
+///
+/// A new device path node is defined to declare flow control characteristics.
+/// UART Flow Control Messaging Device Path
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL GUID.
+  ///
+  EFI_GUID                        Guid;
+  ///
+  /// Bitmap of supported flow control types.
+  /// Bit 0 set indicates hardware flow control.
+  /// Bit 1 set indicates Xon/Xoff flow control.
+  /// All other bits are reserved and are clear.
+  ///
+  UINT32                          FlowControlMap;
+} UART_FLOW_CONTROL_DEVICE_PATH;
+
+#define UART_FLOW_CONTROL_HARDWARE         0x00000001
+#define UART_FLOW_CONTROL_XON_XOFF         0x00000010
+
+#define DEVICE_PATH_MESSAGING_SAS          EFI_SAS_DEVICE_PATH_GUID
+///
+/// Serial Attached SCSI (SAS) Device Path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// DEVICE_PATH_MESSAGING_SAS GUID.
+  ///
+  EFI_GUID                        Guid;
+  ///
+  /// Reserved for future use.
+  ///
+  UINT32                          Reserved;
+  ///
+  /// SAS Address for Serial Attached SCSI Target.
+  ///
+  UINT64                          SasAddress;
+  ///
+  /// SAS Logical Unit Number.
+  ///
+  UINT64                          Lun;
+  ///
+  /// More Information about the device and its interconnect.
+  ///
+  UINT16                          DeviceTopology;
+  ///
+  /// Relative Target Port (RTP).
+  ///
+  UINT16                          RelativeTargetPort;
+} SAS_DEVICE_PATH;
+
+///
+/// Serial Attached SCSI (SAS) Ex Device Path SubType
+///
+#define MSG_SASEX_DP              0x16
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// 8-byte array of the SAS Address for Serial Attached SCSI Target Port.
+  ///
+  UINT8                           SasAddress[8];
+  ///
+  /// 8-byte array of the SAS Logical Unit Number.
+  ///
+  UINT8                           Lun[8];
+  ///
+  /// More Information about the device and its interconnect.
+  ///
+  UINT16                          DeviceTopology;
+  ///
+  /// Relative Target Port (RTP).
+  ///
+  UINT16                          RelativeTargetPort;
+} SASEX_DEVICE_PATH;
+
+///
+/// NvmExpress Namespace Device Path SubType.
+///
+#define MSG_NVME_NAMESPACE_DP     0x17
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  UINT32                          NamespaceId;
+  UINT64                          NamespaceUuid;
+} NVME_NAMESPACE_DEVICE_PATH;
+
+///
+/// DNS Device Path SubType
+///
+#define MSG_DNS_DP                0x1F
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Indicates the DNS server address is IPv4 or IPv6 address.
+  ///
+  UINT8                           IsIPv6;
+  ///
+  /// Instance of the DNS server address.
+  ///
+  EFI_IP_ADDRESS                  DnsServerIp[1024];
+} DNS_DEVICE_PATH;
+
+///
+/// Uniform Resource Identifiers (URI) Device Path SubType
+///
+#define MSG_URI_DP                0x18
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Instance of the URI pursuant to RFC 3986.
+  ///
+  CHAR8                           Uri[1024];
+} URI_DEVICE_PATH;
+
+///
+/// Universal Flash Storage (UFS) Device Path SubType.
+///
+#define MSG_UFS_DP                0x19
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Target ID on the UFS bus (PUN).
+  ///
+  UINT8                           Pun;
+  ///
+  /// Logical Unit Number (LUN).
+  ///
+  UINT8                           Lun;
+} UFS_DEVICE_PATH;
+
+///
+/// SD (Secure Digital) Device Path SubType.
+///
+#define MSG_SD_DP                 0x1A
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  UINT8                           SlotNumber;
+} SD_DEVICE_PATH;
+
+///
+/// EMMC (Embedded MMC) Device Path SubType.
+///
+#define MSG_EMMC_DP                 0x1D
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  UINT8                           SlotNumber;
+} EMMC_DEVICE_PATH;
+
+///
+/// iSCSI Device Path SubType
+///
+#define MSG_ISCSI_DP              0x13
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Network Protocol (0 = TCP, 1+ = reserved).
+  ///
+  UINT16                          NetworkProtocol;
+  ///
+  /// iSCSI Login Options.
+  ///
+  UINT16                          LoginOption;
+  ///
+  /// iSCSI Logical Unit Number.
+  ///
+  UINT64                          Lun;
+  ///
+  /// iSCSI Target Portal group tag the initiator intends
+  /// to establish a session with.
+  ///
+  UINT16                          TargetPortalGroupTag;
+  ///
+  /// iSCSI NodeTarget Name. The length of the name
+  /// is determined by subtracting the offset of this field from Length.
+  ///
+  /// CHAR8                        iSCSI Target Name.
+} ISCSI_DEVICE_PATH;
+
+#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST             0x0000
+#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C   0x0002
+#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST               0x0000
+#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C     0x0008
+#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP              0x0000
+#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON               0x1000
+#define ISCSI_LOGIN_OPTION_CHAP_BI                      0x0000
+#define ISCSI_LOGIN_OPTION_CHAP_UNI                     0x2000
+
+///
+/// VLAN Device Path SubType.
+///
+#define MSG_VLAN_DP               0x14
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// VLAN identifier (0-4094).
+  ///
+  UINT16                          VlanId;
+} VLAN_DEVICE_PATH;
+
+///
+/// BLUETOOTH_ADDRESS
+///
+typedef struct {
+  ///
+  /// 48bit Bluetooth device address.
+  ///
+  UINT8      Address[6];
+} BLUETOOTH_ADDRESS;
+
+///
+/// Bluetooth Device Path SubType.
+///
+#define MSG_BLUETOOTH_DP     0x1b
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// 48bit Bluetooth device address.
+  ///
+  BLUETOOTH_ADDRESS               BD_ADDR;
+} BLUETOOTH_DEVICE_PATH;
+
+///
+/// Wi-Fi Device Path SubType.
+///
+#define MSG_WIFI_DP               0x1C
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Service set identifier. A 32-byte octets string.
+  ///
+  UINT8                           SSId[32];
+} WIFI_DEVICE_PATH;
+
+///
+/// BLUETOOTH_LE_ADDRESS
+///
+typedef struct {
+  ///
+  /// 48-bit Bluetooth device address
+  ///
+  UINT8      Address[6];
+  ///
+  /// 0x00 - Public Device Address
+  /// 0x01 - Random Device Address
+  ///
+  UINT8      Type;
+} BLUETOOTH_LE_ADDRESS;
+
+///
+/// Bluetooth LE Device Path SubType.
+///
+#define MSG_BLUETOOTH_LE_DP       0x1E
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  BLUETOOTH_LE_ADDRESS            Address;
+} BLUETOOTH_LE_DEVICE_PATH;
+
+//
+// Media Device Path
+//
+#define MEDIA_DEVICE_PATH         0x04
+
+///
+/// Hard Drive Media Device Path SubType.
+///
+#define MEDIA_HARDDRIVE_DP        0x01
+
+///
+/// The Hard Drive Media Device Path is used to represent a partition on a hard drive.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Describes the entry in a partition table, starting with entry 1.
+  /// Partition number zero represents the entire device. Valid
+  /// partition numbers for a MBR partition are [1, 4]. Valid
+  /// partition numbers for a GPT partition are [1, NumberOfPartitionEntries].
+  ///
+  UINT32                          PartitionNumber;
+  ///
+  /// Starting LBA of the partition on the hard drive.
+  ///
+  UINT64                          PartitionStart;
+  ///
+  /// Size of the partition in units of Logical Blocks.
+  ///
+  UINT64                          PartitionSize;
+  ///
+  /// Signature unique to this partition:
+  /// If SignatureType is 0, this field has to be initialized with 16 zeros.
+  /// If SignatureType is 1, the MBR signature is stored in the first 4 bytes of this field.
+  /// The other 12 bytes are initialized with zeros.
+  /// If SignatureType is 2, this field contains a 16 byte signature.
+  ///
+  UINT8                           Signature[16];
+  ///
+  /// Partition Format: (Unused values reserved).
+  /// 0x01 - PC-AT compatible legacy MBR.
+  /// 0x02 - GUID Partition Table.
+  ///
+  UINT8                           MBRType;
+  ///
+  /// Type of Disk Signature: (Unused values reserved).
+  /// 0x00 - No Disk Signature.
+  /// 0x01 - 32-bit signature from address 0x1b8 of the type 0x01 MBR.
+  /// 0x02 - GUID signature.
+  ///
+  UINT8                           SignatureType;
+} HARDDRIVE_DEVICE_PATH;
+
+#define MBR_TYPE_PCAT             0x01
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
+
+#define NO_DISK_SIGNATURE         0x00
+#define SIGNATURE_TYPE_MBR        0x01
+#define SIGNATURE_TYPE_GUID       0x02
+
+///
+/// CD-ROM Media Device Path SubType.
+///
+#define MEDIA_CDROM_DP            0x02
+
+///
+/// The CD-ROM Media Device Path is used to define a system partition that exists on a CD-ROM.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Boot Entry number from the Boot Catalog. The Initial/Default entry is defined as zero.
+  ///
+  UINT32                          BootEntry;
+  ///
+  /// Starting RBA of the partition on the medium. CD-ROMs use Relative logical Block Addressing.
+  ///
+  UINT64                          PartitionStart;
+  ///
+  /// Size of the partition in units of Blocks, also called Sectors.
+  ///
+  UINT64                          PartitionSize;
+} CDROM_DEVICE_PATH;
+
+//
+// Use VENDOR_DEVICE_PATH struct
+//
+#define MEDIA_VENDOR_DP           0x03  ///< Media vendor device path subtype.
+
+///
+/// File Path Media Device Path SubType
+///
+#define MEDIA_FILEPATH_DP         0x04
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// A NULL-terminated Path string including directory and file names.
+  ///
+  CHAR16                          PathName[1];
+} FILEPATH_DEVICE_PATH;
+
+#define SIZE_OF_FILEPATH_DEVICE_PATH  OFFSET_OF(FILEPATH_DEVICE_PATH,PathName)
+
+///
+/// Media Protocol Device Path SubType.
+///
+#define MEDIA_PROTOCOL_DP         0x05
+
+///
+/// The Media Protocol Device Path is used to denote the protocol that is being
+/// used in a device path at the location of the path specified.
+/// Many protocols are inherent to the style of device path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// The ID of the protocol.
+  ///
+  EFI_GUID                        Protocol;
+} MEDIA_PROTOCOL_DEVICE_PATH;
+
+///
+/// PIWG Firmware File SubType.
+///
+#define MEDIA_PIWG_FW_FILE_DP     0x06
+
+///
+/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware file.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Firmware file name
+  ///
+  EFI_GUID                        FvFileName;
+} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH;
+
+///
+/// PIWG Firmware Volume Device Path SubType.
+///
+#define MEDIA_PIWG_FW_VOL_DP      0x07
+
+///
+/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware volume.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Firmware volume name.
+  ///
+  EFI_GUID                        FvName;
+} MEDIA_FW_VOL_DEVICE_PATH;
+
+///
+/// Media relative offset range device path.
+///
+#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08
+
+///
+/// Used to describe the offset range of media relative.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  UINT32                    Reserved;
+  UINT64                    StartingOffset;
+  UINT64                    EndingOffset;
+} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH;
+
+///
+/// This GUID defines a RAM Disk supporting a raw disk format in volatile memory.
+///
+#define EFI_VIRTUAL_DISK_GUID               EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_VOLATILE
+
+extern  EFI_GUID                            gEfiVirtualDiskGuid;
+
+///
+/// This GUID defines a RAM Disk supporting an ISO image in volatile memory.
+///
+#define EFI_VIRTUAL_CD_GUID                 EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_VOLATILE
+
+extern  EFI_GUID                            gEfiVirtualCdGuid;
+
+///
+/// This GUID defines a RAM Disk supporting a raw disk format in persistent memory.
+///
+#define EFI_PERSISTENT_VIRTUAL_DISK_GUID    EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_PERSISTENT
+
+extern  EFI_GUID                            gEfiPersistentVirtualDiskGuid;
+
+///
+/// This GUID defines a RAM Disk supporting an ISO image in persistent memory.
+///
+#define EFI_PERSISTENT_VIRTUAL_CD_GUID      EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_PERSISTENT
+
+extern  EFI_GUID                            gEfiPersistentVirtualCdGuid;
+
+///
+/// Media ram disk device path.
+///
+#define MEDIA_RAM_DISK_DP         0x09
+
+///
+/// Used to describe the ram disk device path.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Starting Memory Address.
+  ///
+  UINT32                          StartingAddr[2];
+  ///
+  /// Ending Memory Address.
+  ///
+  UINT32                          EndingAddr[2];
+  ///
+  /// GUID that defines the type of the RAM Disk.
+  ///
+  EFI_GUID                        TypeGuid;
+  ///
+  /// RAM Diskinstance number, if supported. The default value is zero.
+  ///
+  UINT16                          Instance;
+} MEDIA_RAM_DISK_DEVICE_PATH;
+
+///
+/// BIOS Boot Specification Device Path.
+///
+#define BBS_DEVICE_PATH           0x05
+
+///
+/// BIOS Boot Specification Device Path SubType.
+///
+#define BBS_BBS_DP                0x01
+
+///
+/// This Device Path is used to describe the booting of non-EFI-aware operating systems.
+///
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL        Header;
+  ///
+  /// Device Type as defined by the BIOS Boot Specification.
+  ///
+  UINT16                          DeviceType;
+  ///
+  /// Status Flags as defined by the BIOS Boot Specification.
+  ///
+  UINT16                          StatusFlag;
+  ///
+  /// Null-terminated ASCII string that describes the boot device to a user.
+  ///
+  CHAR8                           String[1];
+} BBS_BBS_DEVICE_PATH;
+
+//
+// DeviceType definitions - from BBS specification
+//
+#define BBS_TYPE_FLOPPY           0x01
+#define BBS_TYPE_HARDDRIVE        0x02
+#define BBS_TYPE_CDROM            0x03
+#define BBS_TYPE_PCMCIA           0x04
+#define BBS_TYPE_USB              0x05
+#define BBS_TYPE_EMBEDDED_NETWORK 0x06
+#define BBS_TYPE_BEV              0x80
+#define BBS_TYPE_UNKNOWN          0xFF
+
+
+///
+/// Union of all possible Device Paths and pointers to Device Paths.
+///
+typedef union {
+  EFI_DEVICE_PATH_PROTOCOL                   DevPath;
+  PCI_DEVICE_PATH                            Pci;
+  PCCARD_DEVICE_PATH                         PcCard;
+  MEMMAP_DEVICE_PATH                         MemMap;
+  VENDOR_DEVICE_PATH                         Vendor;
+
+  CONTROLLER_DEVICE_PATH                     Controller;
+  BMC_DEVICE_PATH                            Bmc;
+  ACPI_HID_DEVICE_PATH                       Acpi;
+  ACPI_EXTENDED_HID_DEVICE_PATH              ExtendedAcpi;
+  ACPI_ADR_DEVICE_PATH                       AcpiAdr;
+
+  ATAPI_DEVICE_PATH                          Atapi;
+  SCSI_DEVICE_PATH                           Scsi;
+  ISCSI_DEVICE_PATH                          Iscsi;
+  FIBRECHANNEL_DEVICE_PATH                   FibreChannel;
+  FIBRECHANNELEX_DEVICE_PATH                 FibreChannelEx;
+
+  F1394_DEVICE_PATH                          F1394;
+  USB_DEVICE_PATH                            Usb;
+  SATA_DEVICE_PATH                           Sata;
+  USB_CLASS_DEVICE_PATH                      UsbClass;
+  USB_WWID_DEVICE_PATH                       UsbWwid;
+  DEVICE_LOGICAL_UNIT_DEVICE_PATH            LogicUnit;
+  I2O_DEVICE_PATH                            I2O;
+  MAC_ADDR_DEVICE_PATH                       MacAddr;
+  IPv4_DEVICE_PATH                           Ipv4;
+  IPv6_DEVICE_PATH                           Ipv6;
+  VLAN_DEVICE_PATH                           Vlan;
+  INFINIBAND_DEVICE_PATH                     InfiniBand;
+  UART_DEVICE_PATH                           Uart;
+  UART_FLOW_CONTROL_DEVICE_PATH              UartFlowControl;
+  SAS_DEVICE_PATH                            Sas;
+  SASEX_DEVICE_PATH                          SasEx;
+  NVME_NAMESPACE_DEVICE_PATH                 NvmeNamespace;
+  DNS_DEVICE_PATH                            Dns;
+  URI_DEVICE_PATH                            Uri;
+  BLUETOOTH_DEVICE_PATH                      Bluetooth;
+  WIFI_DEVICE_PATH                           WiFi;
+  UFS_DEVICE_PATH                            Ufs;
+  SD_DEVICE_PATH                             Sd;
+  EMMC_DEVICE_PATH                           Emmc;
+  HARDDRIVE_DEVICE_PATH                      HardDrive;
+  CDROM_DEVICE_PATH                          CD;
+
+  FILEPATH_DEVICE_PATH                       FilePath;
+  MEDIA_PROTOCOL_DEVICE_PATH                 MediaProtocol;
+
+  MEDIA_FW_VOL_DEVICE_PATH                   FirmwareVolume;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH          FirmwareFile;
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH    Offset;
+  MEDIA_RAM_DISK_DEVICE_PATH                 RamDisk;
+  BBS_BBS_DEVICE_PATH                        Bbs;
+} EFI_DEV_PATH;
+
+
+
+typedef union {
+  EFI_DEVICE_PATH_PROTOCOL                   *DevPath;
+  PCI_DEVICE_PATH                            *Pci;
+  PCCARD_DEVICE_PATH                         *PcCard;
+  MEMMAP_DEVICE_PATH                         *MemMap;
+  VENDOR_DEVICE_PATH                         *Vendor;
+
+  CONTROLLER_DEVICE_PATH                     *Controller;
+  BMC_DEVICE_PATH                            *Bmc;
+  ACPI_HID_DEVICE_PATH                       *Acpi;
+  ACPI_EXTENDED_HID_DEVICE_PATH              *ExtendedAcpi;
+  ACPI_ADR_DEVICE_PATH                       *AcpiAdr;
+
+  ATAPI_DEVICE_PATH                          *Atapi;
+  SCSI_DEVICE_PATH                           *Scsi;
+  ISCSI_DEVICE_PATH                          *Iscsi;
+  FIBRECHANNEL_DEVICE_PATH                   *FibreChannel;
+  FIBRECHANNELEX_DEVICE_PATH                 *FibreChannelEx;
+
+  F1394_DEVICE_PATH                          *F1394;
+  USB_DEVICE_PATH                            *Usb;
+  SATA_DEVICE_PATH                           *Sata;
+  USB_CLASS_DEVICE_PATH                      *UsbClass;
+  USB_WWID_DEVICE_PATH                       *UsbWwid;
+  DEVICE_LOGICAL_UNIT_DEVICE_PATH            *LogicUnit;
+  I2O_DEVICE_PATH                            *I2O;
+  MAC_ADDR_DEVICE_PATH                       *MacAddr;
+  IPv4_DEVICE_PATH                           *Ipv4;
+  IPv6_DEVICE_PATH                           *Ipv6;
+  VLAN_DEVICE_PATH                           *Vlan;
+  INFINIBAND_DEVICE_PATH                     *InfiniBand;
+  UART_DEVICE_PATH                           *Uart;
+  UART_FLOW_CONTROL_DEVICE_PATH              *UartFlowControl;
+  SAS_DEVICE_PATH                            *Sas;
+  SASEX_DEVICE_PATH                          *SasEx;
+  NVME_NAMESPACE_DEVICE_PATH                 *NvmeNamespace;
+  DNS_DEVICE_PATH                            *Dns;
+  URI_DEVICE_PATH                            *Uri;
+  BLUETOOTH_DEVICE_PATH                      *Bluetooth;
+  WIFI_DEVICE_PATH                           *WiFi;
+  UFS_DEVICE_PATH                            *Ufs;
+  SD_DEVICE_PATH                             *Sd;
+  EMMC_DEVICE_PATH                           *Emmc;
+  HARDDRIVE_DEVICE_PATH                      *HardDrive;
+  CDROM_DEVICE_PATH                          *CD;
+
+  FILEPATH_DEVICE_PATH                       *FilePath;
+  MEDIA_PROTOCOL_DEVICE_PATH                 *MediaProtocol;
+
+  MEDIA_FW_VOL_DEVICE_PATH                   *FirmwareVolume;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH          *FirmwareFile;
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH    *Offset;
+  MEDIA_RAM_DISK_DEVICE_PATH                 *RamDisk;
+  BBS_BBS_DEVICE_PATH                        *Bbs;
+  UINT8                                      *Raw;
+} EFI_DEV_PATH_PTR;
+
+#define EFI_DEBUGPORT_PROTOCOL_GUID \
+  { \
+    0xEBA4E8D2, 0x3858, 0x41EC, {0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 } \
+  }
+//
+// DEBUGPORT variable definitions...
+//
+#define EFI_DEBUGPORT_VARIABLE_NAME L"DEBUGPORT"
+#define EFI_DEBUGPORT_VARIABLE_GUID EFI_DEBUGPORT_PROTOCOL_GUID
+extern EFI_GUID  gEfiDebugPortVariableGuid;
+
+//
+// DebugPort device path definitions...
+//
+#define DEVICE_PATH_MESSAGING_DEBUGPORT EFI_DEBUGPORT_PROTOCOL_GUID
+extern EFI_GUID  gEfiDebugPortDevicePathGuid;
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  Header;
+  EFI_GUID                  Guid;
+} DEBUGPORT_DEVICE_PATH;
+
+#pragma pack()
+
+#define END_DEVICE_PATH_TYPE                 0x7f
+#define END_ENTIRE_DEVICE_PATH_SUBTYPE       0xFF
+#define END_INSTANCE_DEVICE_PATH_SUBTYPE     0x01
+
+extern EFI_GUID gEfiDevicePathProtocolGuid;
+
+#endif
diff --git a/BaseTools/Source/C/DevicePath/DevicePathFromText.c b/BaseTools/Source/C/DevicePath/DevicePathFromText.c
new file mode 100644
index 0000000..fb5b09b
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/DevicePathFromText.c
@@ -0,0 +1,3503 @@
+/** @file
+  DevicePathFromText protocol as defined in the UEFI 2.0 specification.
+
+Copyright (c) 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.
+
+**/
+CHAR16 *
+UefiDevicePathLibStrDuplicate (
+   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.
+
+**/
+CHAR16 *
+GetParamByNodeName (
+   CHAR16 *Str,
+   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] = L'\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
+
+**/
+CHAR16 *
+SplitStr (
+    CHAR16 **List,
+       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 = L'\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
+
+**/
+CHAR16 *
+GetNextParamStr (
+    CHAR16 **List
+  )
+{
+  //
+  // The separator is comma
+  //
+  return SplitStr (List, L',');
+}
+
+/**
+  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
+
+**/
+CHAR16 *
+GetNextDeviceNodeStr (
+    CHAR16   **DevicePath,
+      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 = L'\0';
+    Str++;
+  } else {
+    *IsInstanceEnd = FALSE;
+    if (!IS_NULL (*Str)) {
+      *Str = L'\0';
+      Str++;
+    }
+  }
+
+  *DevicePath = Str;
+
+  return ReturnStr;
+}
+
+
+/**
+  Return whether the integer string is a hex string.
+
+  @param Str             The integer string
+
+  @retval TRUE   Hex string
+  @retval FALSE  Decimal string
+
+**/
+BOOLEAN
+IsHexStr (
+   CHAR16   *Str
+  )
+{
+  //
+  // skip preceeding white space
+  //
+  while ((*Str != 0) && *Str == L' ') {
+    Str ++;
+  }
+  //
+  // skip preceeding zeros
+  //
+  while ((*Str != 0) && *Str == L'0') {
+    Str ++;
+  }
+
+  return (BOOLEAN) (*Str == L'x' || *Str == L'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
+
+**/
+UINTN
+Strtoi (
+   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
+
+**/
+VOID
+Strtoi64 (
+    CHAR16  *Str,
+   UINT64  *Data
+  )
+{
+  if (IsHexStr (Str)) {
+    *Data = StrHexToUint64 (Str);
+  } else {
+    *Data = StrDecimalToUint64 (Str);
+  }
+}
+
+/**
+  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
+
+**/
+VOID
+StrToAscii (
+       CHAR16 *Str,
+    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.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextGenericPath (
+   UINT8  Type,
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPath (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextHardwarePath (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPci (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPcCard (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMemoryMapped (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextVendor (
+   CHAR16 *TextDeviceNode,
+   UINT8  Type,
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenHw (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextCtrl (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBmc (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiPath (
+   CHAR16 *TextDeviceNode
+  )
+{
+  return DevPathFromTextGenericPath (ACPI_DEVICE_PATH, TextDeviceNode);
+}
+
+/**
+  Converts a string to EisaId.
+
+  @param Text   The input string.
+
+  @return UINT32 EISA ID.
+**/
+UINT32
+EisaIdFromText (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpi (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextAcpi (
+   CHAR16 *TextDeviceNode,
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPciRoot (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPcieRoot (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFloppy (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextKeyboard (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSerial (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextParallelPort (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiEx (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiExp (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiAdr (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMsg (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAta (
+ 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, L"Primary") == 0) {
+    Atapi->PrimarySecondary = 0;
+  } else if (StrCmp (PrimarySecondaryStr, L"Secondary") == 0) {
+    Atapi->PrimarySecondary = 1;
+  } else {
+    Atapi->PrimarySecondary = (UINT8) Strtoi (PrimarySecondaryStr);
+  }
+  if (StrCmp (SlaveMasterStr, L"Master") == 0) {
+    Atapi->SlaveMaster      = 0;
+  } else if (StrCmp (SlaveMasterStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextScsi (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFibre (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFibreEx (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromText1394 (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsb (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextI2O (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextInfiniband (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenMsg (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenPcAnsi (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenVt100 (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenVt100Plus (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenUtf8 (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUartFlowCtrl (
+   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, L"XonXoff") == 0) {
+    UartFlowControl->FlowControlMap = 2;
+  } else if (StrCmp (ValueStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSAS (
+   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, L"NoTopology") == 0) {
+    Info = 0x0;
+
+  } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) {
+
+    Uint16 = (UINT16) Strtoi (DriveBayStr);
+    if (Uint16 == 0) {
+      Info = 0x1;
+    } else {
+      Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
+    }
+
+    if (StrCmp (SASSATAStr, L"SATA") == 0) {
+      Info |= BIT4;
+    }
+
+    //
+    // Location is an integer between 0 and 1 or else
+    // the keyword Internal (0) or External (1).
+    //
+    if (StrCmp (LocationStr, L"External") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (LocationStr, L"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, L"Expanded") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (ConnectStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSasEx (
+   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, L"NoTopology") == 0) {
+    Info = 0x0;
+
+  } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) {
+
+    Uint16 = (UINT16) Strtoi (DriveBayStr);
+    if (Uint16 == 0) {
+      Info = 0x1;
+    } else {
+      Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
+    }
+
+    if (StrCmp (SASSATAStr, L"SATA") == 0) {
+      Info |= BIT4;
+    }
+
+    //
+    // Location is an integer between 0 and 1 or else
+    // the keyword Internal (0) or External (1).
+    //
+    if (StrCmp (LocationStr, L"External") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (LocationStr, L"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, L"Expanded") == 0) {
+      Uint16 = 1;
+    } else if (StrCmp (ConnectStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextNVMe (
+   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, L'-'));
+  }
+
+  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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUfs (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSd (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextEmmc (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextDebugPort (
+   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, &gEfiDebugPortDevicePathGuid);
+
+  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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMAC (
+   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);
+  if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) {
+    Length = 6;
+  }
+
+  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 .
+
+**/
+UINTN
+NetworkProtocolFromText (
+   CHAR16 *Text
+  )
+{
+  if (StrCmp (Text, L"UDP") == 0) {
+    return RFC_1700_UDP_PROTOCOL;
+  }
+
+  if (StrCmp (Text, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextIPv4 (
+   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, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextIPv6 (
+   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, L"Static") == 0) {
+    IPv6->IpAddressOrigin = 0;
+  } else if (StrCmp (TypeStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUart (
+   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, L"DEFAULT") == 0) {
+    Uart->BaudRate = 115200;
+  } else {
+    Strtoi64 (BaudStr, &Uart->BaudRate);
+  }
+  Uart->DataBits  = (UINT8) ((StrCmp (DataBitsStr, L"DEFAULT") == 0) ? 8 : Strtoi (DataBitsStr));
+  switch (*ParityStr) {
+  case L'D':
+    Uart->Parity = 0;
+    break;
+
+  case L'N':
+    Uart->Parity = 1;
+    break;
+
+  case L'E':
+    Uart->Parity = 2;
+    break;
+
+  case L'O':
+    Uart->Parity = 3;
+    break;
+
+  case L'M':
+    Uart->Parity = 4;
+    break;
+
+  case L'S':
+    Uart->Parity = 5;
+    break;
+
+  default:
+    Uart->Parity = (UINT8) Strtoi (ParityStr);
+    break;
+  }
+
+  if (StrCmp (StopBitsStr, L"D") == 0) {
+    Uart->StopBits = (UINT8) 0;
+  } else if (StrCmp (StopBitsStr, L"1") == 0) {
+    Uart->StopBits = (UINT8) 1;
+  } else if (StrCmp (StopBitsStr, L"1.5") == 0) {
+    Uart->StopBits = (UINT8) 2;
+  } else if (StrCmp (StopBitsStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextUsbClass (
+   CHAR16         *TextDeviceNode,
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbClass (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbAudio (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbCDCControl (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbHID (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbImage (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbPrinter (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbMassStorage (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbHub (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbCDCData (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbSmartCard (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbVideo (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbDiagnostic (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbWireless (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbDeviceFirmwareUpdate (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbIrdaBridge (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbTestAndMeasurement (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbWwid (
+   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] == L'\"' &&
+      SerialNumberStr[SerialNumberStrLen - 1] == L'\"'
+    ) {
+    SerialNumberStr[SerialNumberStrLen - 1] = L'\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.
+  //
+  memcpy (
+    (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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUnit (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextiSCSI (
+   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, L"CRC32C") == 0) {
+    Options |= 0x0002;
+  }
+
+  if (StrCmp (DataDigestStr, L"CRC32C") == 0) {
+    Options |= 0x0008;
+  }
+
+  if (StrCmp (AuthenticationStr, L"None") == 0) {
+    Options |= 0x0800;
+  }
+
+  if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) {
+    Options |= 0x1000;
+  }
+
+  ISCSIDevPath->LoginOption      = (UINT16) Options;
+
+  if (StrCmp (ProtocolStr, L"TCP") == 0) {
+    ISCSIDevPath->NetworkProtocol = 0;
+  } else {
+    //
+    // Undefined and reserved.
+    //
+    ISCSIDevPath->NetworkProtocol = 1;
+  }
+
+  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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVlan (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBluetooth (
+   CHAR16 *TextDeviceNode
+  )
+{
+  CHAR16                  *BluetoothStr;
+  BLUETOOTH_DEVICE_PATH   *BluetoothDp;
+
+  BluetoothStr = GetNextParamStr (&TextDeviceNode);
+  BluetoothDp  = (BLUETOOTH_DEVICE_PATH *) CreateDeviceNode (
+                                             MESSAGING_DEVICE_PATH,
+                                             MSG_BLUETOOTH_DP,
+                                             (UINT16) sizeof (BLUETOOTH_DEVICE_PATH)
+                                             );
+  StrHexToBytes (
+    BluetoothStr,
+    sizeof (BLUETOOTH_ADDRESS) * 2,
+    BluetoothDp->BD_ADDR.Address,
+    sizeof (BLUETOOTH_ADDRESS)
+    );
+  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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextWiFi (
+   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] = L'\0';
+      DataLen     = 32;
+    }
+
+    UnicodeStrToAsciiStrS (SSIdStr, AsciiStr, sizeof (AsciiStr));
+    memcpy (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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUri (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMediaPath (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextHD (
+   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, L"MBR") == 0) {
+    Hd->SignatureType = SIGNATURE_TYPE_MBR;
+    Hd->MBRType       = 0x01;
+
+    Signature32       = (UINT32) Strtoi (SignatureStr);
+    memcpy (Hd->Signature, &Signature32, sizeof (UINT32));
+  } else if (StrCmp (TypeStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextCDROM (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenMedia (
+   CHAR16 *TextDeviceNode
+  )
+{
+  return ConvertFromTextVendor (
+           TextDeviceNode,
+           MEDIA_DEVICE_PATH,
+           MEDIA_VENDOR_DP
+           );
+}
+
+/**
+  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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFilePath (
+   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;
+}
+
+/**
+  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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMedia (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFv (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFvFile (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextRelativeOffsetRange (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextRamDisk (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVirtualDisk (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVirtualCd (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPersistentVirtualDisk (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPersistentVirtualCd (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBbsPath (
+   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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBBS (
+   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, L"Floppy") == 0) {
+    Bbs->DeviceType = BBS_TYPE_FLOPPY;
+  } else if (StrCmp (TypeStr, L"HD") == 0) {
+    Bbs->DeviceType = BBS_TYPE_HARDDRIVE;
+  } else if (StrCmp (TypeStr, L"CDROM") == 0) {
+    Bbs->DeviceType = BBS_TYPE_CDROM;
+  } else if (StrCmp (TypeStr, L"PCMCIA") == 0) {
+    Bbs->DeviceType = BBS_TYPE_PCMCIA;
+  } else if (StrCmp (TypeStr, L"USB") == 0) {
+    Bbs->DeviceType = BBS_TYPE_USB;
+  } else if (StrCmp (TypeStr, L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSata (
+   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;
+}
+
+DEVICE_PATH_FROM_TEXT_TABLE mUefiDevicePathLibDevPathFromTextTable[] = {
+  {L"Path",                    DevPathFromTextPath                    },
+
+  {L"HardwarePath",            DevPathFromTextHardwarePath            },
+  {L"Pci",                     DevPathFromTextPci                     },
+  {L"PcCard",                  DevPathFromTextPcCard                  },
+  {L"MemoryMapped",            DevPathFromTextMemoryMapped            },
+  {L"VenHw",                   DevPathFromTextVenHw                   },
+  {L"Ctrl",                    DevPathFromTextCtrl                    },
+  {L"BMC",                     DevPathFromTextBmc                     },
+
+  {L"AcpiPath",                DevPathFromTextAcpiPath                },
+  {L"Acpi",                    DevPathFromTextAcpi                    },
+  {L"PciRoot",                 DevPathFromTextPciRoot                 },
+  {L"PcieRoot",                DevPathFromTextPcieRoot                },
+  {L"Floppy",                  DevPathFromTextFloppy                  },
+  {L"Keyboard",                DevPathFromTextKeyboard                },
+  {L"Serial",                  DevPathFromTextSerial                  },
+  {L"ParallelPort",            DevPathFromTextParallelPort            },
+  {L"AcpiEx",                  DevPathFromTextAcpiEx                  },
+  {L"AcpiExp",                 DevPathFromTextAcpiExp                 },
+  {L"AcpiAdr",                 DevPathFromTextAcpiAdr                 },
+
+  {L"Msg",                     DevPathFromTextMsg                     },
+  {L"Ata",                     DevPathFromTextAta                     },
+  {L"Scsi",                    DevPathFromTextScsi                    },
+  {L"Fibre",                   DevPathFromTextFibre                   },
+  {L"FibreEx",                 DevPathFromTextFibreEx                 },
+  {L"I1394",                   DevPathFromText1394                    },
+  {L"USB",                     DevPathFromTextUsb                     },
+  {L"I2O",                     DevPathFromTextI2O                     },
+  {L"Infiniband",              DevPathFromTextInfiniband              },
+  {L"VenMsg",                  DevPathFromTextVenMsg                  },
+  {L"VenPcAnsi",               DevPathFromTextVenPcAnsi               },
+  {L"VenVt100",                DevPathFromTextVenVt100                },
+  {L"VenVt100Plus",            DevPathFromTextVenVt100Plus            },
+  {L"VenUtf8",                 DevPathFromTextVenUtf8                 },
+  {L"UartFlowCtrl",            DevPathFromTextUartFlowCtrl            },
+  {L"SAS",                     DevPathFromTextSAS                     },
+  {L"SasEx",                   DevPathFromTextSasEx                   },
+  {L"NVMe",                    DevPathFromTextNVMe                    },
+  {L"UFS",                     DevPathFromTextUfs                     },
+  {L"SD",                      DevPathFromTextSd                      },
+  {L"eMMC",                    DevPathFromTextEmmc                    },
+  {L"DebugPort",               DevPathFromTextDebugPort               },
+  {L"MAC",                     DevPathFromTextMAC                     },
+  {L"IPv4",                    DevPathFromTextIPv4                    },
+  {L"IPv6",                    DevPathFromTextIPv6                    },
+  {L"Uart",                    DevPathFromTextUart                    },
+  {L"UsbClass",                DevPathFromTextUsbClass                },
+  {L"UsbAudio",                DevPathFromTextUsbAudio                },
+  {L"UsbCDCControl",           DevPathFromTextUsbCDCControl           },
+  {L"UsbHID",                  DevPathFromTextUsbHID                  },
+  {L"UsbImage",                DevPathFromTextUsbImage                },
+  {L"UsbPrinter",              DevPathFromTextUsbPrinter              },
+  {L"UsbMassStorage",          DevPathFromTextUsbMassStorage          },
+  {L"UsbHub",                  DevPathFromTextUsbHub                  },
+  {L"UsbCDCData",              DevPathFromTextUsbCDCData              },
+  {L"UsbSmartCard",            DevPathFromTextUsbSmartCard            },
+  {L"UsbVideo",                DevPathFromTextUsbVideo                },
+  {L"UsbDiagnostic",           DevPathFromTextUsbDiagnostic           },
+  {L"UsbWireless",             DevPathFromTextUsbWireless             },
+  {L"UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate },
+  {L"UsbIrdaBridge",           DevPathFromTextUsbIrdaBridge           },
+  {L"UsbTestAndMeasurement",   DevPathFromTextUsbTestAndMeasurement   },
+  {L"UsbWwid",                 DevPathFromTextUsbWwid                 },
+  {L"Unit",                    DevPathFromTextUnit                    },
+  {L"iSCSI",                   DevPathFromTextiSCSI                   },
+  {L"Vlan",                    DevPathFromTextVlan                    },
+  {L"Uri",                     DevPathFromTextUri                     },
+  {L"Bluetooth",               DevPathFromTextBluetooth               },
+  {L"Wi-Fi",                   DevPathFromTextWiFi                    },
+  {L"MediaPath",               DevPathFromTextMediaPath               },
+  {L"HD",                      DevPathFromTextHD                      },
+  {L"CDROM",                   DevPathFromTextCDROM                   },
+  {L"VenMedia",                DevPathFromTextVenMedia                },
+  {L"Media",                   DevPathFromTextMedia                   },
+  {L"Fv",                      DevPathFromTextFv                      },
+  {L"FvFile",                  DevPathFromTextFvFile                  },
+  {L"Offset",                  DevPathFromTextRelativeOffsetRange     },
+  {L"RamDisk",                 DevPathFromTextRamDisk                 },
+  {L"VirtualDisk",             DevPathFromTextVirtualDisk             },
+  {L"VirtualCD",               DevPathFromTextVirtualCd               },
+  {L"PersistentVirtualDisk",   DevPathFromTextPersistentVirtualDisk   },
+  {L"PersistentVirtualCD",     DevPathFromTextPersistentVirtualCd     },
+
+  {L"BbsPath",                 DevPathFromTextBbsPath                 },
+  {L"BBS",                     DevPathFromTextBBS                     },
+  {L"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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibConvertTextToDeviceNode (
+   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;
+    }
+  }
+
+  if (FromText == NULL) {
+    //
+    // A file path
+    //
+    FromText = DevPathFromTextFilePath;
+    DeviceNode = FromText (DeviceNodeStr);
+  } else {
+    DeviceNode = FromText (ParamStr);
+    free (ParamStr);
+  }
+
+  free (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.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibConvertTextToDevicePath (
+   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);
+    free (DevicePath);
+    free (DeviceNode);
+    DevicePath = NewDevicePath;
+
+    if (IsInstanceEnd) {
+      DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
+      ASSERT (DeviceNode != NULL);
+      SetDevicePathEndNode (DeviceNode);
+      DeviceNode->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
+
+      NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode);
+      free (DevicePath);
+      free (DeviceNode);
+      DevicePath = NewDevicePath;
+    }
+  }
+
+  free (DevicePathStr);
+  return DevicePath;
+}
diff --git a/BaseTools/Source/C/DevicePath/DevicePathFromText.h b/BaseTools/Source/C/DevicePath/DevicePathFromText.h
new file mode 100644
index 0000000..4c46921
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/DevicePathFromText.h
@@ -0,0 +1,72 @@
+/** @file
+  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL as defined in UEFI 2.0.
+  This protocol provides service to convert text to device paths and device nodes.
+
+  Copyright (c) 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.
+
+**/
+
+#ifndef __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__
+#define __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__
+
+///
+/// Device Path From Text protocol
+///
+#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \
+  { \
+    0x5c99a21, 0xc70f, 0x4ad2, {0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e  } \
+  }
+
+/**
+  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.
+
+  @retval a_pointer      Pointer to the EFI device node.
+  @retval NULL           if TextDeviceNode is NULL or there was insufficient memory.
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_FROM_TEXT_NODE)(
+   CONST CHAR16                 *TextDeviceNode
+  );
+
+
+/**
+  Convert text to the binary representation of a device node.
+
+  @param  TextDeviceNode TextDevicePath points to the text representation of a device
+                         path. Conversion starts with the first character and continues
+                         until the first non-device path character.
+
+  @retval a_pointer      Pointer to the allocated device path.
+  @retval NULL           if TextDeviceNode is NULL or there was insufficient memory.
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_FROM_TEXT_PATH)(
+   CONST CHAR16                 *TextDevicePath
+  );
+
+///
+/// This protocol converts text to device paths and device nodes.
+///
+typedef struct {
+  EFI_DEVICE_PATH_FROM_TEXT_NODE  ConvertTextToDeviceNode;
+  EFI_DEVICE_PATH_FROM_TEXT_PATH  ConvertTextToDevicePath;
+} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL;
+
+extern EFI_GUID gEfiDevicePathFromTextProtocolGuid;
+
+#endif
diff --git a/BaseTools/Source/C/DevicePath/DevicePathUtilities.c b/BaseTools/Source/C/DevicePath/DevicePathUtilities.c
new file mode 100644
index 0000000..07a58ee
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/DevicePathUtilities.c
@@ -0,0 +1,2352 @@
+/** @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) 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"
+#include "DevicePathUtilities.h"
+
+#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status)  \
+  do { \
+    ASSERT (Expression); \
+    if (!(Expression)) { \
+      return Status; \
+    } \
+  } while (FALSE)
+
+
+//
+// Template for an end-of-device path node.
+//
+CONST EFI_DEVICE_PATH_PROTOCOL  mUefiDevicePathLibEndDevicePath = {
+  END_DEVICE_PATH_TYPE,
+  END_ENTIRE_DEVICE_PATH_SUBTYPE,
+  {
+    END_DEVICE_PATH_LENGTH,
+    0
+  }
+};
+
+/**
+  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
+IsDevicePathValid (
+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+   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;
+    }
+
+    Count++;
+    if (Count >= MAX_DEVICE_PATH_NODE_COUNT) {
+      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
+DevicePathType (
+   CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return ((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
+DevicePathSubType (
+   CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return ((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
+DevicePathNodeLength (
+   CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);
+}
+
+/**
+  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 *
+NextDevicePathNode (
+   CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return (EFI_DEVICE_PATH_PROTOCOL *)((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
+IsDevicePathEndType (
+   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
+IsDevicePathEnd (
+   CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
+}
+
+/**
+  Determines if a device path node is an end node of a device path instance.
+
+  Determines if a device path node specified by Node is an end node of a device
+  path instance. If Node represents the end of a device path instance, 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 a device
+                    path instance.
+  @retval FALSE     The device path node specified by Node is not the end of a
+                    device path instance.
+
+**/
+BOOLEAN
+IsDevicePathEndInstance (
+   CONST VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
+}
+
+/**
+  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
+SetDevicePathNodeLength (
+    VOID  *Node,
+   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));
+}
+
+/**
+  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
+SetDevicePathEndNode (
+   VOID  *Node
+  )
+{
+  ASSERT (Node != NULL);
+  memcpy (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));
+}
+
+/**
+  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
+UefiDevicePathLibGetDevicePathSize (
+   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);
+}
+
+/**
+  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 *
+UefiDevicePathLibDuplicateDevicePath (
+   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 *
+UefiDevicePathLibAppendDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath
+  )
+{
+  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 = memcpy (NewDevicePath, FirstDevicePath, Size1);
+    //
+    // Over write FirstDevicePath EndNode and do the copy
+    //
+    DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath +
+                  (Size1 - END_DEVICE_PATH_LENGTH));
+    memcpy (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 *
+UefiDevicePathLibAppendDevicePathNode (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode
+  )
+{
+  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 = memcpy (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);
+
+  free (TempDevicePath);
+
+  return NewDevicePath;
+}
+
+/**
+  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 *
+UefiDevicePathLibAppendDevicePathInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  UINTN                     SrcSize;
+  UINTN                     InstanceSize;
+
+  if (DevicePath == NULL) {
+    return DuplicateDevicePath (DevicePathInstance);
+  }
+
+  if (DevicePathInstance == NULL) {
+    return NULL;
+  }
+
+  if (!IsDevicePathValid (DevicePath, 0) || !IsDevicePathValid (DevicePathInstance, 0)) {
+    return NULL;
+  }
+
+  SrcSize       = GetDevicePathSize (DevicePath);
+  InstanceSize  = GetDevicePathSize (DevicePathInstance);
+
+  NewDevicePath = AllocatePool (SrcSize + InstanceSize);
+  if (NewDevicePath != NULL) {
+
+    TempDevicePath = memcpy (NewDevicePath, DevicePath, SrcSize);;
+
+    while (!IsDevicePathEnd (TempDevicePath)) {
+      TempDevicePath = NextDevicePathNode (TempDevicePath);
+    }
+
+    TempDevicePath->SubType  = END_INSTANCE_DEVICE_PATH_SUBTYPE;
+    TempDevicePath           = NextDevicePathNode (TempDevicePath);
+    memcpy (TempDevicePath, DevicePathInstance, InstanceSize);
+  }
+
+  return NewDevicePath;
+}
+
+/**
+  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 *
+UefiDevicePathLibGetNextDevicePathInstance (
+   EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
+   UINTN                          *Size
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
+  EFI_DEVICE_PATH_PROTOCOL  *ReturnValue;
+  UINT8                     Temp;
+
+  ASSERT (Size != NULL);
+
+  if (DevicePath == NULL || *DevicePath == NULL) {
+    *Size = 0;
+    return NULL;
+  }
+
+  if (!IsDevicePathValid (*DevicePath, 0)) {
+    return NULL;
+  }
+
+  //
+  // Find the end of the device path instance
+  //
+  DevPath = *DevicePath;
+  while (!IsDevicePathEndType (DevPath)) {
+    DevPath = NextDevicePathNode (DevPath);
+  }
+
+  //
+  // Compute the size of the device path instance
+  //
+  *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
+
+  //
+  // Make a copy and return the device path instance
+  //
+  Temp              = DevPath->SubType;
+  DevPath->SubType  = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+  ReturnValue       = DuplicateDevicePath (*DevicePath);
+  DevPath->SubType  = Temp;
+
+  //
+  // If DevPath is the end of an entire device path, then another instance
+  // does not follow, so *DevicePath is set to NULL.
+  //
+  if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
+    *DevicePath = NULL;
+  } else {
+    *DevicePath = NextDevicePathNode (DevPath);
+  }
+
+  return ReturnValue;
+}
+
+/**
+  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 *
+UefiDevicePathLibCreateDeviceNode (
+   UINT8                           NodeType,
+   UINT8                           NodeSubType,
+   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;
+}
+
+/**
+  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
+UefiDevicePathLibIsDevicePathMultiInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  CONST EFI_DEVICE_PATH_PROTOCOL     *Node;
+
+  if (DevicePath == NULL) {
+    return FALSE;
+  }
+
+  if (!IsDevicePathValid (DevicePath, 0)) {
+    return FALSE;
+  }
+
+  Node = DevicePath;
+  while (!IsDevicePathEnd (Node)) {
+    if (IsDevicePathEndInstance (Node)) {
+      return TRUE;
+    }
+
+    Node = NextDevicePathNode (Node);
+  }
+
+  return FALSE;
+}
+
+
+/**
+  Retrieves the device path protocol from a handle.
+
+  This function returns the device path protocol from the handle specified by Handle.
+  If Handle is NULL or Handle does not contain a device path protocol, then NULL
+  is returned.
+
+  @param  Handle                     The handle from which to retrieve the device
+                                     path protocol.
+
+  @return The device path protocol from the handle specified by Handle.
+
+**/
+/*
+EFI_DEVICE_PATH_PROTOCOL *
+DevicePathFromHandle (
+   EFI_HANDLE                      Handle
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_STATUS                Status;
+
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID *) &DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    DevicePath = NULL;
+  }
+  return DevicePath;
+}
+*/
+/**
+  Allocates a device path for a file and appends it to an existing device path.
+
+  If Device is a valid device handle that contains a device path protocol, then a device path for
+  the file specified by FileName  is allocated and appended to the device path associated with the
+  handle Device.  The allocated device path is returned.  If Device is NULL or Device is a handle
+  that does not support the device path protocol, then a device path containing a single device
+  path node for the file specified by FileName is allocated and 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.
+
+  If FileName is NULL, then ASSERT().
+  If FileName is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Device                     A pointer to a device handle.  This parameter
+                                     is optional and may be NULL.
+  @param  FileName                   A pointer to a Null-terminated Unicode string.
+
+  @return The allocated device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+FileDevicePath (
+   EFI_HANDLE                      Device,     OPTIONAL
+   CONST CHAR16                    *FileName
+  )
+{
+  UINTN                     Size;
+  FILEPATH_DEVICE_PATH      *FilePath;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *FileDevicePath;
+
+  DevicePath = NULL;
+
+  Size = StrSize (FileName);
+  FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
+  if (FileDevicePath != NULL) {
+    FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;
+    FilePath->Header.Type    = MEDIA_DEVICE_PATH;
+    FilePath->Header.SubType = MEDIA_FILEPATH_DP;
+    memcpy (&FilePath->PathName, FileName, Size);
+    SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
+    SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));
+
+    //if (Device != NULL) {
+    //  DevicePath = DevicePathFromHandle (Device);
+    //}
+
+    DevicePath = AppendDevicePath (DevicePath, FileDevicePath);
+    free (FileDevicePath);
+  }
+
+  return DevicePath;
+}
+
+CHAR16
+InternalCharToUpper (
+        CHAR16                    Char
+  )
+{
+  if (Char >= L'a' && Char <= L'z') {
+    return (CHAR16) (Char - (L'a' - L'A'));
+  }
+
+  return Char;
+}
+
+UINTN
+StrnLenS (
+   CONST CHAR16              *String,
+   UINTN                     MaxSize
+  )
+{
+  UINTN     Length;
+
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.
+  //
+  if ((String == NULL) || (MaxSize == 0)) {
+    return 0;
+  }
+
+  Length = 0;
+  while (String[Length] != 0) {
+    if (Length >= MaxSize - 1) {
+      return MaxSize;
+    }
+    Length++;
+  }
+  return Length;
+}
+
+
+VOID *
+InternalAllocatePool (
+   UINTN   AllocationSize
+  )
+{
+  VOID * Memory;
+
+  Memory = malloc(AllocationSize);
+  ASSERT(Memory != NULL);
+  return Memory;
+}
+
+
+VOID *
+InternalReallocatePool (
+   UINTN            OldSize,
+   UINTN            NewSize,
+   VOID             *OldBuffer  OPTIONAL
+  )
+{
+  VOID  *NewBuffer;
+
+  NewBuffer = AllocateZeroPool (NewSize);
+  if (NewBuffer != NULL && OldBuffer != NULL) {
+    memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
+    free(OldBuffer);
+  }
+  return NewBuffer;
+}
+
+VOID *
+ReallocatePool (
+   UINTN  OldSize,
+   UINTN  NewSize,
+   VOID   *OldBuffer  OPTIONAL
+  )
+{
+  return InternalReallocatePool (OldSize, NewSize, OldBuffer);
+}
+
+/**
+  Returns the length of a Null-terminated Unicode string.
+
+  This function returns the number of Unicode characters in the Null-terminated
+  Unicode string specified by String.
+
+  If String is NULL, then ASSERT().
+  If String is not aligned on a 16-bit boundary, then ASSERT().
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+  PcdMaximumUnicodeStringLength Unicode characters, not including the
+  Null-terminator, then ASSERT().
+
+  @param  String  A pointer to a Null-terminated Unicode string.
+
+  @return The length of String.
+
+**/
+UINTN
+StrLen (
+  CONST CHAR16              *String
+  )
+{
+  UINTN   Length;
+
+  ASSERT (String != NULL);
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  for (Length = 0; *String != L'\0'; String++, Length++) {
+    //
+    // If PcdMaximumUnicodeStringLength is not zero,
+    // length should not more than PcdMaximumUnicodeStringLength
+    //
+  }
+  return Length;
+}
+
+BOOLEAN
+InternalSafeStringIsOverlap (
+  IN VOID    *Base1,
+  IN UINTN   Size1,
+  IN VOID    *Base2,
+  IN UINTN   Size2
+  )
+{
+  if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||
+      (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+BOOLEAN
+InternalSafeStringNoStrOverlap (
+  IN CHAR16  *Str1,
+  IN UINTN   Size1,
+  IN CHAR16  *Str2,
+  IN UINTN   Size2
+  )
+{
+  return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));
+}
+
+RETURN_STATUS
+StrDecimalToUintnS (
+    CONST CHAR16             *String,
+         CHAR16             **EndPointer,  OPTIONAL
+         UINTN              *Data
+  )
+{
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. Neither String nor Data shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // 2. The length of String shall not be greater than RSIZE_MAX.
+  //
+  if (RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == L' ') || (*String == L'\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == L'0') {
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalIsDecimalDigitCharacter (*String)) {
+    //
+    // If the number represented by String overflows according to the range
+    // defined by UINTN, then MAX_UINTN is stored in *Data and
+    // RETURN_UNSUPPORTED is returned.
+    //
+    if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) {
+      *Data = MAX_UINTN;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR16 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = *Data * 10 + (*String - L'0');
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
+  Convert a Null-terminated Unicode decimal string to a value of type UINT64.
+
+  This function outputs a value of type UINT64 by interpreting the contents of
+  the Unicode string specified by String as a decimal number. The format of the
+  input Unicode string String is:
+
+                  [spaces] [decimal digits].
+
+  The valid decimal digit character is in the range [0-9]. The function will
+  ignore the pad space, which includes spaces or tab characters, before
+  [decimal digits]. The running zero in the beginning of [decimal digits] will
+  be ignored. Then, the function stops at the first character that is a not a
+  valid decimal character or a Null-terminator, whichever one comes first.
+
+  If String is NULL, then ASSERT().
+  If Data is NULL, then ASSERT().
+  If String is not aligned in a 16-bit boundary, then ASSERT().
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+  PcdMaximumUnicodeStringLength Unicode characters, not including the
+  Null-terminator, then ASSERT().
+
+  If String has no valid decimal digits in the above format, then 0 is stored
+  at the location pointed to by Data.
+  If the number represented by String exceeds the range defined by UINT64, then
+  MAX_UINT64 is stored at the location pointed to by Data.
+
+  If EndPointer is not NULL, a pointer to the character that stopped the scan
+  is stored at the location pointed to by EndPointer. If String has no valid
+  decimal digits right after the optional pad spaces, the value of String is
+  stored at the location pointed to by EndPointer.
+
+  @param  String                   Pointer to a Null-terminated Unicode string.
+  @param  EndPointer               Pointer to character that stops scan.
+  @param  Data                     Pointer to the converted value.
+
+  @retval RETURN_SUCCESS           Value is translated from String.
+  @retval RETURN_INVALID_PARAMETER If String is NULL.
+                                   If Data is NULL.
+                                   If PcdMaximumUnicodeStringLength is not
+                                   zero, and String contains more than
+                                   PcdMaximumUnicodeStringLength Unicode
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINT64.
+
+**/
+RETURN_STATUS
+StrDecimalToUint64S (
+    CONST CHAR16             *String,
+         CHAR16             **EndPointer,  OPTIONAL
+         UINT64             *Data
+  )
+{
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. Neither String nor Data shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // 2. The length of String shall not be greater than RSIZE_MAX.
+  //
+  if (RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == L' ') || (*String == L'\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == L'0') {
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalIsDecimalDigitCharacter (*String)) {
+    //
+    // If the number represented by String overflows according to the range
+    // defined by UINT64, then MAX_UINT64 is stored in *Data and
+    // RETURN_UNSUPPORTED is returned.
+    //
+    if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {
+      *Data = MAX_UINT64;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR16 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = (*Data) * 10 + (*String - L'0');
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
+  Convert a Null-terminated Unicode hexadecimal string to a value of type
+  UINTN.
+
+  This function outputs a value of type UINTN by interpreting the contents of
+  the Unicode string specified by String as a hexadecimal number. The format of
+  the input Unicode string String is:
+
+                  [spaces][zeros][x][hexadecimal digits].
+
+  The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
+  The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
+  If "x" appears in the input string, it must be prefixed with at least one 0.
+  The function will ignore the pad space, which includes spaces or tab
+  characters, before [zeros], [x] or [hexadecimal digit]. The running zero
+  before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
+  after [x] or the first valid hexadecimal digit. Then, the function stops at
+  the first character that is a not a valid hexadecimal character or NULL,
+  whichever one comes first.
+
+  If String is NULL, then ASSERT().
+  If Data is NULL, then ASSERT().
+  If String is not aligned in a 16-bit boundary, then ASSERT().
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+  PcdMaximumUnicodeStringLength Unicode characters, not including the
+  Null-terminator, then ASSERT().
+
+  If String has no valid hexadecimal digits in the above format, then 0 is
+  stored at the location pointed to by Data.
+  If the number represented by String exceeds the range defined by UINTN, then
+  MAX_UINTN is stored at the location pointed to by Data.
+
+  If EndPointer is not NULL, a pointer to the character that stopped the scan
+  is stored at the location pointed to by EndPointer. If String has no valid
+  hexadecimal digits right after the optional pad spaces, the value of String
+  is stored at the location pointed to by EndPointer.
+
+  @param  String                   Pointer to a Null-terminated Unicode string.
+  @param  EndPointer               Pointer to character that stops scan.
+  @param  Data                     Pointer to the converted value.
+
+  @retval RETURN_SUCCESS           Value is translated from String.
+  @retval RETURN_INVALID_PARAMETER If String is NULL.
+                                   If Data is NULL.
+                                   If PcdMaximumUnicodeStringLength is not
+                                   zero, and String contains more than
+                                   PcdMaximumUnicodeStringLength Unicode
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINTN.
+
+**/
+RETURN_STATUS
+StrHexToUintnS (
+    CONST CHAR16             *String,
+         CHAR16             **EndPointer,  OPTIONAL
+         UINTN              *Data
+  )
+{
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. Neither String nor Data shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // 2. The length of String shall not be greater than RSIZE_MAX.
+  //
+  if (RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == L' ') || (*String == L'\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == L'0') {
+    String++;
+  }
+
+  if (InternalCharToUpper (*String) == L'X') {
+    if (*(String - 1) != L'0') {
+      *Data = 0;
+      return RETURN_SUCCESS;
+    }
+    //
+    // Skip the 'X'
+    //
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalIsHexaDecimalDigitCharacter (*String)) {
+    //
+    // If the number represented by String overflows according to the range
+    // defined by UINTN, then MAX_UINTN is stored in *Data and
+    // RETURN_UNSUPPORTED is returned.
+    //
+    if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) {
+      *Data = MAX_UINTN;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR16 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = (*Data << 4) + InternalHexCharToUintn (*String);
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+RETURN_STATUS
+StrHexToUint64S (
+    CONST CHAR16             *String,
+         CHAR16             **EndPointer,  OPTIONAL
+         UINT64             *Data
+  )
+{
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. Neither String nor Data shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // 2. The length of String shall not be greater than RSIZE_MAX.
+  //
+  if (RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == L' ') || (*String == L'\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == L'0') {
+    String++;
+  }
+
+  if (InternalCharToUpper (*String) == L'X') {
+    if (*(String - 1) != L'0') {
+      *Data = 0;
+      return RETURN_SUCCESS;
+    }
+    //
+    // Skip the 'X'
+    //
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalIsHexaDecimalDigitCharacter (*String)) {
+    //
+    // If the number represented by String overflows according to the range
+    // defined by UINT64, then MAX_UINT64 is stored in *Data and
+    // RETURN_UNSUPPORTED is returned.
+    //
+    if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {
+      *Data = MAX_UINT64;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR16 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data =  ((*Data) << 4) + InternalHexCharToUintn (*String);
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+UINT64
+StrDecimalToUint64 (
+  CONST CHAR16              *String
+  )
+{
+  UINT64     Result;
+
+  StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);
+  return Result;
+}
+
+
+UINT64
+StrHexToUint64 (
+  CONST CHAR16             *String
+  )
+{
+  UINT64    Result;
+
+  StrHexToUint64S (String, (CHAR16 **) NULL, &Result);
+  return Result;
+}
+
+UINTN
+StrDecimalToUintn (
+  CONST CHAR16              *String
+  )
+{
+  UINTN     Result;
+
+  StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result);
+  return Result;
+}
+
+UINTN
+StrHexToUintn (
+  CONST CHAR16              *String
+  )
+{
+  UINTN     Result;
+
+  StrHexToUintnS (String, (CHAR16 **) NULL, &Result);
+  return Result;
+}
+
+UINTN
+StrSize (
+  CONST CHAR16              *String
+  )
+{
+  return (StrLen (String) + 1) * sizeof (*String);
+}
+
+
+UINT64
+ReadUnaligned64 (
+   CONST UINT64              *Buffer
+  )
+{
+  ASSERT (Buffer != NULL);
+
+  return *Buffer;
+}
+
+UINT64
+WriteUnaligned64 (
+   UINT64                    *Buffer,
+   UINT64                    Value
+  )
+{
+  ASSERT (Buffer != NULL);
+
+  return *Buffer = Value;
+}
+
+
+EFI_GUID *
+CopyGuid (
+   EFI_GUID         *DestinationGuid,
+   CONST EFI_GUID  *SourceGuid
+  )
+{
+  WriteUnaligned64 (
+    (UINT64*)DestinationGuid,
+    ReadUnaligned64 ((CONST UINT64*)SourceGuid)
+    );
+  WriteUnaligned64 (
+    (UINT64*)DestinationGuid + 1,
+    ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
+    );
+  return DestinationGuid;
+}
+
+UINT16
+SwapBytes16 (
+  UINT16                    Value
+  )
+{
+  return (UINT16) ((Value<< 8) | (Value>> 8));
+}
+
+
+UINT32
+SwapBytes32 (
+  UINT32                    Value
+  )
+{
+  UINT32  LowerBytes;
+  UINT32  HigherBytes;
+
+  LowerBytes  = (UINT32) SwapBytes16 ((UINT16) Value);
+  HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));
+  return (LowerBytes << 16 | HigherBytes);
+}
+
+BOOLEAN
+InternalIsDecimalDigitCharacter (
+  CHAR16                    Char
+  )
+{
+  return (BOOLEAN) (Char >= L'0' && Char <= L'9');
+}
+
+VOID *
+InternalAllocateCopyPool (
+   UINTN            AllocationSize,
+   CONST VOID       *Buffer
+  )
+{
+  VOID  *Memory;
+
+  ASSERT (Buffer != NULL);
+  ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
+
+  Memory = malloc (AllocationSize);
+  if (Memory != NULL) {
+     Memory = memcpy (Memory, Buffer, AllocationSize);
+  }
+  return Memory;
+}
+
+BOOLEAN
+InternalIsHexaDecimalDigitCharacter (
+  CHAR16                    Char
+  )
+{
+
+  return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||
+    (Char >= L'A' && Char <= L'F') ||
+    (Char >= L'a' && Char <= L'f'));
+}
+
+UINTN
+InternalHexCharToUintn (
+        CHAR16                    Char
+  )
+{
+  if (InternalIsDecimalDigitCharacter (Char)) {
+    return Char - L'0';
+  }
+
+  return (10 + InternalCharToUpper (Char) - L'A');
+}
+
+
+/**
+  Convert a Null-terminated Unicode hexadecimal string to a byte array.
+
+  This function outputs a byte array by interpreting the contents of
+  the Unicode string specified by String in hexadecimal format. The format of
+  the input Unicode string String is:
+
+                  [XX]*
+
+  X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
+  The function decodes every two hexadecimal digit characters as one byte. The
+  decoding stops after Length of characters and outputs Buffer containing
+  (Length / 2) bytes.
+
+  If String is not aligned in a 16-bit boundary, then ASSERT().
+
+  If String is NULL, then ASSERT().
+
+  If Buffer is NULL, then ASSERT().
+
+  If Length is not multiple of 2, then ASSERT().
+
+  If PcdMaximumUnicodeStringLength is not zero and Length is greater than
+  PcdMaximumUnicodeStringLength, then ASSERT().
+
+  If MaxBufferSize is less than (Length / 2), then ASSERT().
+
+  @param  String                   Pointer to a Null-terminated Unicode string.
+  @param  Length                   The number of Unicode characters to decode.
+  @param  Buffer                   Pointer to the converted bytes array.
+  @param  MaxBufferSize            The maximum size of Buffer.
+
+  @retval RETURN_SUCCESS           Buffer is translated from String.
+  @retval RETURN_INVALID_PARAMETER If String is NULL.
+                                   If Data is NULL.
+                                   If Length is not multiple of 2.
+                                   If PcdMaximumUnicodeStringLength is not zero,
+                                    and Length is greater than
+                                    PcdMaximumUnicodeStringLength.
+  @retval RETURN_UNSUPPORTED       If Length of characters from String contain
+                                    a character that is not valid hexadecimal
+                                    digit characters, or a Null-terminator.
+  @retval RETURN_BUFFER_TOO_SMALL  If MaxBufferSize is less than (Length / 2).
+**/
+RETURN_STATUS
+StrHexToBytes (
+   CONST CHAR16       *String,
+   UINTN              Length,
+   UINT8              *Buffer,
+   UINTN              MaxBufferSize
+  )
+{
+  UINTN                  Index;
+
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. None of String or Buffer shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // 2. Length shall not be greater than RSIZE_MAX.
+  //
+  if (RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  //
+  // 3. Length shall not be odd.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);
+
+  //
+  // 4. MaxBufferSize shall equal to or greater than Length / 2.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);
+
+  //
+  // 5. String shall not contains invalid hexadecimal digits.
+  //
+  for (Index = 0; Index < Length; Index++) {
+    if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {
+      break;
+    }
+  }
+  if (Index != Length) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  //
+  // Convert the hex string to bytes.
+  //
+  for(Index = 0; Index < Length; Index++) {
+
+    //
+    // For even characters, write the upper nibble for each buffer byte,
+    // and for even characters, the lower nibble.
+    //
+    if ((Index & BIT0) == 0) {
+      Buffer[Index / 2]  = (UINT8) InternalHexCharToUintn (String[Index]) << 4;
+    } else {
+      Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);
+    }
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
+  Convert a Null-terminated Unicode GUID string to a value of type
+  EFI_GUID.
+
+  This function outputs a GUID value by interpreting the contents of
+  the Unicode string specified by String. The format of the input
+  Unicode string String consists of 36 characters, as follows:
+
+                  aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
+
+  The pairs aa - pp are two characters in the range [0-9], [a-f] and
+  [A-F], with each pair representing a single byte hexadecimal value.
+
+  The mapping between String and the EFI_GUID structure is as follows:
+                  aa          Data1[24:31]
+                  bb          Data1[16:23]
+                  cc          Data1[8:15]
+                  dd          Data1[0:7]
+                  ee          Data2[8:15]
+                  ff          Data2[0:7]
+                  gg          Data3[8:15]
+                  hh          Data3[0:7]
+                  ii          Data4[0:7]
+                  jj          Data4[8:15]
+                  kk          Data4[16:23]
+                  ll          Data4[24:31]
+                  mm          Data4[32:39]
+                  nn          Data4[40:47]
+                  oo          Data4[48:55]
+                  pp          Data4[56:63]
+
+  If String is NULL, then ASSERT().
+  If Guid is NULL, then ASSERT().
+  If String is not aligned in a 16-bit boundary, then ASSERT().
+
+  @param  String                   Pointer to a Null-terminated Unicode string.
+  @param  Guid                     Pointer to the converted GUID.
+
+  @retval RETURN_SUCCESS           Guid is translated from String.
+  @retval RETURN_INVALID_PARAMETER If String is NULL.
+                                   If Data is NULL.
+  @retval RETURN_UNSUPPORTED       If String is not as the above format.
+
+**/
+RETURN_STATUS
+StrToGuid (
+   CONST CHAR16       *String,
+   EFI_GUID           *Guid
+  )
+{
+  RETURN_STATUS          Status;
+  EFI_GUID               LocalGuid;
+
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. None of String or Guid shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // Get aabbccdd in big-endian.
+  //
+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));
+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {
+    return RETURN_UNSUPPORTED;
+  }
+  //
+  // Convert big-endian to little-endian.
+  //
+  LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);
+  String += 2 * sizeof (LocalGuid.Data1) + 1;
+
+  //
+  // Get eeff in big-endian.
+  //
+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));
+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {
+    return RETURN_UNSUPPORTED;
+  }
+  //
+  // Convert big-endian to little-endian.
+  //
+  LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);
+  String += 2 * sizeof (LocalGuid.Data2) + 1;
+
+  //
+  // Get gghh in big-endian.
+  //
+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));
+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {
+    return RETURN_UNSUPPORTED;
+  }
+  //
+  // Convert big-endian to little-endian.
+  //
+  LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);
+  String += 2 * sizeof (LocalGuid.Data3) + 1;
+
+  //
+  // Get iijj.
+  //
+  Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);
+  if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {
+    return RETURN_UNSUPPORTED;
+  }
+  String += 2 * 2 + 1;
+
+  //
+  // Get kkllmmnnoopp.
+  //
+  Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);
+  if (RETURN_ERROR (Status)) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  CopyGuid (Guid, &LocalGuid);
+  return RETURN_SUCCESS;
+}
+
+/**
+  Compares up to a specified length the contents of two Null-terminated Unicode strings,
+  and returns the difference between the first mismatched Unicode characters.
+
+  This function compares the Null-terminated Unicode string FirstString to the
+  Null-terminated Unicode string SecondString. At most, Length Unicode
+  characters will be compared. If Length is 0, then 0 is returned. If
+  FirstString is identical to SecondString, then 0 is returned. Otherwise, the
+  value returned is the first mismatched Unicode character in SecondString
+  subtracted from the first mismatched Unicode character in FirstString.
+
+  If Length > 0 and FirstString is NULL, then ASSERT().
+  If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().
+  If Length > 0 and SecondString is NULL, then ASSERT().
+  If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().
+  If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
+  PcdMaximumUnicodeStringLength, then ASSERT().
+  If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than
+  PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
+  then ASSERT().
+  If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than
+  PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
+  then ASSERT().
+
+  @param  FirstString   A pointer to a Null-terminated Unicode string.
+  @param  SecondString  A pointer to a Null-terminated Unicode string.
+  @param  Length        The maximum number of Unicode characters to compare.
+
+  @retval 0      FirstString is identical to SecondString.
+  @return others FirstString is not identical to SecondString.
+
+**/
+INTN
+StrnCmp (
+        CONST CHAR16              *FirstString,
+        CONST CHAR16              *SecondString,
+        UINTN                     Length
+  )
+{
+  if (Length == 0) {
+    return 0;
+  }
+
+  //
+  // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
+  // Length tests are performed inside StrLen().
+  //
+  ASSERT (StrSize (FirstString) != 0);
+  ASSERT (StrSize (SecondString) != 0);
+
+  while ((*FirstString != L'\0') &&
+         (*SecondString != L'\0') &&
+         (*FirstString == *SecondString) &&
+         (Length > 1)) {
+    FirstString++;
+    SecondString++;
+    Length--;
+  }
+
+  return *FirstString - *SecondString;
+}
+
+VOID *
+AllocateCopyPool (
+   UINTN       AllocationSize,
+   CONST VOID  *Buffer
+  )
+{
+  return InternalAllocateCopyPool (AllocationSize, Buffer);
+}
+
+INTN
+StrCmp (
+  CONST CHAR16              *FirstString,
+  CONST CHAR16              *SecondString
+  )
+{
+  //
+  // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
+  //
+  ASSERT (StrSize (FirstString) != 0);
+  ASSERT (StrSize (SecondString) != 0);
+
+  while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
+    FirstString++;
+    SecondString++;
+  }
+  return *FirstString - *SecondString;
+}
+
+UINT64
+SwapBytes64 (
+  UINT64                    Value
+  )
+{
+  return InternalMathSwapBytes64 (Value);
+}
+
+UINT64
+InternalMathSwapBytes64 (
+  UINT64                    Operand
+  )
+{
+  UINT64  LowerBytes;
+  UINT64  HigherBytes;
+
+  LowerBytes  = (UINT64) SwapBytes32 ((UINT32) Operand);
+  HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
+
+  return (LowerBytes << 32 | HigherBytes);
+}
+
+RETURN_STATUS
+StrToIpv4Address (
+  CONST CHAR16       *String,
+  CHAR16             **EndPointer,
+  EFI_IPv4_ADDRESS       *Address,
+  UINT8              *PrefixLength
+  )
+{
+  RETURN_STATUS          Status;
+  UINTN                  AddressIndex;
+  UINTN                  Uintn;
+  EFI_IPv4_ADDRESS       LocalAddress;
+  UINT8                  LocalPrefixLength;
+  CHAR16                 *Pointer;
+
+  LocalPrefixLength = MAX_UINT8;
+  LocalAddress.Addr[0] = 0;
+
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. None of String or Guid shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
+
+  for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
+    if (!InternalIsDecimalDigitCharacter (*Pointer)) {
+      //
+      // D or P contains invalid characters.
+      //
+      break;
+    }
+
+    //
+    // Get D or P.
+    //
+    Status = StrDecimalToUintnS ((CONST CHAR16 *) Pointer, &Pointer, &Uintn);
+    if (RETURN_ERROR (Status)) {
+      return RETURN_UNSUPPORTED;
+    }
+    if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+      //
+      // It's P.
+      //
+      if (Uintn > 32) {
+        return RETURN_UNSUPPORTED;
+      }
+      LocalPrefixLength = (UINT8) Uintn;
+    } else {
+      //
+      // It's D.
+      //
+      if (Uintn > MAX_UINT8) {
+        return RETURN_UNSUPPORTED;
+      }
+      LocalAddress.Addr[AddressIndex] = (UINT8) Uintn;
+      AddressIndex++;
+    }
+
+    //
+    // Check the '.' or '/', depending on the AddressIndex.
+    //
+    if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+      if (*Pointer == L'/') {
+        //
+        // '/P' is in the String.
+        // Skip "/" and get P in next loop.
+        //
+        Pointer++;
+      } else {
+        //
+        // '/P' is not in the String.
+        //
+        break;
+      }
+    } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
+      if (*Pointer == L'.') {
+        //
+        // D should be followed by '.'
+        //
+        Pointer++;
+      } else {
+        return RETURN_UNSUPPORTED;
+      }
+    }
+  }
+
+  if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  memcpy (Address, &LocalAddress, sizeof (*Address));
+  if (PrefixLength != NULL) {
+    *PrefixLength = LocalPrefixLength;
+  }
+  if (EndPointer != NULL) {
+    *EndPointer = Pointer;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+StrToIpv6Address (
+  CONST CHAR16       *String,
+  CHAR16             **EndPointer,
+  EFI_IPv6_ADDRESS   *Address,
+  UINT8              *PrefixLength
+  )
+{
+  RETURN_STATUS          Status;
+  UINTN                  AddressIndex;
+  UINTN                  Uintn;
+  EFI_IPv6_ADDRESS       LocalAddress;
+  UINT8                  LocalPrefixLength;
+  CONST CHAR16           *Pointer;
+  CHAR16                 *End;
+  UINTN                  CompressStart;
+  BOOLEAN                ExpectPrefix;
+
+  LocalPrefixLength = MAX_UINT8;
+  CompressStart     = ARRAY_SIZE (Address->Addr);
+  ExpectPrefix      = FALSE;
+
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  //
+  // 1. None of String or Guid shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
+
+  for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
+    if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
+      if (*Pointer != L':') {
+        //
+        // ":" or "/" should be followed by digit characters.
+        //
+        return RETURN_UNSUPPORTED;
+      }
+
+      //
+      // Meet second ":" after previous ":" or "/"
+      // or meet first ":" in the beginning of String.
+      //
+      if (ExpectPrefix) {
+        //
+        // ":" shall not be after "/"
+        //
+        return RETURN_UNSUPPORTED;
+      }
+
+      if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {
+        //
+        // "::" can only appear once.
+        // "::" can only appear when address is not full length.
+        //
+        return RETURN_UNSUPPORTED;
+      } else {
+        //
+        // Remember the start of zero compressing.
+        //
+        CompressStart = AddressIndex;
+        Pointer++;
+
+        if (CompressStart == 0) {
+          if (*Pointer != L':') {
+            //
+            // Single ":" shall not be in the beginning of String.
+            //
+            return RETURN_UNSUPPORTED;
+          }
+          Pointer++;
+        }
+      }
+    }
+
+    if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
+      if (*Pointer == L'/') {
+        //
+        // Might be optional "/P" after "::".
+        //
+        if (CompressStart != AddressIndex) {
+          return RETURN_UNSUPPORTED;
+        }
+      } else {
+        break;
+      }
+    } else {
+      if (!ExpectPrefix) {
+        //
+        // Get X.
+        //
+        Status = StrHexToUintnS (Pointer, &End, &Uintn);
+        if (RETURN_ERROR (Status) || End - Pointer > 4) {
+          //
+          // Number of hexadecimal digit characters is no more than 4.
+          //
+          return RETURN_UNSUPPORTED;
+        }
+        Pointer = End;
+        //
+        // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.
+        //
+        ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));
+        LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uintn >> 8);
+        LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn;
+        AddressIndex += 2;
+      } else {
+        //
+        // Get P, then exit the loop.
+        //
+        Status = StrDecimalToUintnS (Pointer, &End, &Uintn);
+        if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) {
+          //
+          // Prefix length should not exceed 128.
+          //
+          return RETURN_UNSUPPORTED;
+        }
+        LocalPrefixLength = (UINT8) Uintn;
+        Pointer = End;
+        break;
+      }
+    }
+
+    //
+    // Skip ':' or "/"
+    //
+    if (*Pointer == L'/') {
+      ExpectPrefix = TRUE;
+    } else if (*Pointer == L':') {
+      if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+        //
+        // Meet additional ":" after all 8 16-bit address
+        //
+        break;
+      }
+    } else {
+      //
+      // Meet other character that is not "/" or ":" after all 8 16-bit address
+      //
+      break;
+    }
+    Pointer++;
+  }
+
+  if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||
+    (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))
+      ) {
+    //
+    // Full length of address shall not have compressing zeros.
+    // Non-full length of address shall have compressing zeros.
+    //
+    return RETURN_UNSUPPORTED;
+  }
+  memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);
+  memset (&Address->Addr[CompressStart], 0,  ARRAY_SIZE (Address->Addr) - AddressIndex);
+  if (AddressIndex > CompressStart) {
+    memcpy (
+      &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],
+      &LocalAddress.Addr[CompressStart],
+      AddressIndex - CompressStart
+      );
+  }
+
+  if (PrefixLength != NULL) {
+    *PrefixLength = LocalPrefixLength;
+  }
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) Pointer;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+
+RETURN_STATUS
+UnicodeStrToAsciiStrS (
+  CONST CHAR16              *Source,
+  CHAR8                     *Destination,
+  UINTN                     DestMax
+  )
+{
+  UINTN            SourceLen;
+
+  ASSERT (((UINTN) Source & BIT0) == 0);
+
+  //
+  // 1. Neither Destination nor Source shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
+  //
+  if (ASCII_RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+  if (RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  //
+  // 3. DestMax shall not equal zero.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
+
+  //
+  // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
+  //
+  SourceLen = StrnLenS (Source, DestMax);
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
+
+  //
+  // 5. Copying shall not take place between objects that overlap.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);
+
+  //
+  // convert string
+  //
+  while (*Source != '\0') {
+    //
+    // If any Unicode characters in Source contain
+    // non-zero value in the upper 8 bits, then ASSERT().
+    //
+    ASSERT (*Source < 0x100);
+    *(Destination++) = (CHAR8) *(Source++);
+  }
+  *Destination = '\0';
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+StrCpyS (
+  CHAR16       *Destination,
+  UINTN        DestMax,
+  CONST CHAR16 *Source
+  )
+{
+  UINTN            SourceLen;
+
+  ASSERT (((UINTN) Destination & BIT0) == 0);
+  ASSERT (((UINTN) Source & BIT0) == 0);
+
+  //
+  // 1. Neither Destination nor Source shall be a null pointer.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
+
+  //
+  // 2. DestMax shall not be greater than RSIZE_MAX.
+  //
+  if (RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  //
+  // 3. DestMax shall not equal zero.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
+
+  //
+  // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
+  //
+  SourceLen = StrnLenS (Source, DestMax);
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
+
+  //
+  // 5. Copying shall not take place between objects that overlap.
+  //
+  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
+
+  //
+  // The StrCpyS function copies the string pointed to by Source (including the terminating
+  // null character) into the array pointed to by Destination.
+  //
+  while (*Source != 0) {
+    *(Destination++) = *(Source++);
+  }
+  *Destination = 0;
+
+  return RETURN_SUCCESS;
+}
+
+VOID *
+AllocateZeroPool (
+  UINTN  AllocationSize
+  )
+{
+  VOID * Memory;
+  Memory = malloc(AllocationSize);
+  ASSERT (Memory != NULL);
+  if (Memory == NULL) {
+    fprintf(stderr, "Not memory for malloc\n");
+  }
+  memset(Memory, 0, AllocationSize);
+  return Memory;
+}
+
+VOID *
+AllocatePool (
+  UINTN  AllocationSize
+  )
+{
+  return InternalAllocatePool (AllocationSize);
+}
+
+UINT16
+WriteUnaligned16 (
+  UINT16                    *Buffer,
+  UINT16                    Value
+  )
+{
+  ASSERT (Buffer != NULL);
+
+  return *Buffer = Value;
+}
+
+UINT16
+ReadUnaligned16 (
+  CONST UINT16              *Buffer
+  )
+{
+  ASSERT (Buffer != NULL);
+
+  return *Buffer;
+}
diff --git a/BaseTools/Source/C/DevicePath/DevicePathUtilities.h b/BaseTools/Source/C/DevicePath/DevicePathUtilities.h
new file mode 100644
index 0000000..418615f
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/DevicePathUtilities.h
@@ -0,0 +1,555 @@
+/** @file
+  EFI_DEVICE_PATH_UTILITIES_PROTOCOL as defined in UEFI 2.0.
+  Use to create and manipulate device paths and device nodes.
+
+  Copyright (c) 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.
+
+**/
+
+#ifndef __DEVICE_PATH_UTILITIES_H__
+#define __DEVICE_PATH_UTILITIES_H__
+
+///
+/// Device Path Utilities protocol
+///
+#define EFI_DEVICE_PATH_UTILITIES_GUID \
+  { \
+    0x379be4e, 0xd706, 0x437d, {0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4 } \
+  }
+
+/**
+  Returns the size of the device path, in bytes.
+
+  @param  DevicePath Points to the start of the EFI device path.
+
+  @return Size  Size of the specified device path, in bytes, including the end-of-path tag.
+  @retval 0     DevicePath is NULL
+
+**/
+typedef
+UINTN
+( *EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE)(
+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+  );
+
+
+/**
+  Create a duplicate of the specified path.
+
+  @param  DevicePath Points to the source EFI device path.
+
+  @retval Pointer    A pointer to the duplicate device path.
+  @retval NULL       insufficient memory or DevicePath is NULL
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH)(
+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+  );
+
+/**
+  Create a new path by appending the second device path to the first.
+  If Src1 is NULL and Src2 is non-NULL, then a duplicate of Src2 is returned.
+  If Src1 is non-NULL and Src2 is NULL, then a duplicate of Src1 is returned.
+  If Src1 and Src2 are both NULL, then a copy of an end-of-device-path is returned.
+
+  @param  Src1 Points to the first device path.
+  @param  Src2 Points to the second device path.
+
+  @retval Pointer  A pointer to the newly created device path.
+  @retval NULL     Memory could not be allocated
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_UTILS_APPEND_PATH)(
+   CONST EFI_DEVICE_PATH_PROTOCOL *Src1,
+   CONST EFI_DEVICE_PATH_PROTOCOL *Src2
+  );
+
+/**
+  Creates a new path by appending the device node to the device path.
+  If DeviceNode is NULL then a copy of DevicePath is returned.
+  If DevicePath is NULL then a copy of DeviceNode, followed by an end-of-device path device node is returned.
+  If both DeviceNode and DevicePath are NULL then a copy of an end-of-device-path device node is returned.
+
+  @param  DevicePath Points to the device path.
+  @param  DeviceNode Points to the device node.
+
+  @retval Pointer    A pointer to the allocated device node.
+  @retval NULL       There was insufficient memory.
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_UTILS_APPEND_NODE)(
+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode
+  );
+
+/**
+  Creates a new path by appending the specified device path instance to the specified device path.
+
+  @param  DevicePath         Points to the device path. If NULL, then ignored.
+  @param  DevicePathInstance Points to the device path instance.
+
+  @retval Pointer            A pointer to the newly created device path
+  @retval NULL               Memory could not be allocated or DevicePathInstance is NULL.
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE)(
+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
+  );
+
+/**
+  Creates a copy of the current device path instance and returns a pointer to the next device path
+  instance.
+
+  @param  DevicePathInstance     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.
+  @param  DevicePathInstanceSize On output, this holds the size of the device path instance,
+                                 in bytes or zero, if DevicePathInstance is NULL.
+                                 If NULL, then the instance size is not output.
+
+  @retval Pointer                A pointer to the copy of the current device path instance.
+  @retval NULL                   DevicePathInstace was NULL on entry or there was insufficient memory.
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE)(
+     EFI_DEVICE_PATH_PROTOCOL  **DevicePathInstance,
+   UINTN                         *DevicePathInstanceSize
+  );
+
+/**
+  Creates a device node
+
+  @param  NodeType    NodeType is the device node type (EFI_DEVICE_PATH.Type) for
+                      the new device node.
+  @param  NodeSubType NodeSubType is the device node sub-type
+                      EFI_DEVICE_PATH.SubType) for the new device node.
+  @param  NodeLength  NodeLength is the length of the device node
+                      (EFI_DEVICE_PATH.Length) for the new device node.
+
+  @retval Pointer     A pointer to the newly created device node.
+  @retval NULL        NodeLength is less than
+                      the size of the header or there was insufficient memory.
+
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+( *EFI_DEVICE_PATH_UTILS_CREATE_NODE)(
+   UINT8                          NodeType,
+   UINT8                          NodeSubType,
+   UINT16                         NodeLength
+);
+
+/**
+  Returns whether a device path is multi-instance.
+
+  @param  DevicePath Points to the device path. If NULL, then ignored.
+
+  @retval TRUE       The device path has more than one instance
+  @retval FALSE      The device path is empty or contains only a single instance.
+
+**/
+typedef
+BOOLEAN
+( *EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE)(
+   CONST EFI_DEVICE_PATH_PROTOCOL         *DevicePath
+  );
+
+///
+/// This protocol is used to creates and manipulates device paths and device nodes.
+///
+typedef struct {
+  EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE GetDevicePathSize;
+  EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH      DuplicateDevicePath;
+  EFI_DEVICE_PATH_UTILS_APPEND_PATH          AppendDevicePath;
+  EFI_DEVICE_PATH_UTILS_APPEND_NODE          AppendDeviceNode;
+  EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE      AppendDevicePathInstance;
+  EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE    GetNextDevicePathInstance;
+  EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE    IsDevicePathMultiInstance;
+  EFI_DEVICE_PATH_UTILS_CREATE_NODE          CreateDeviceNode;
+} EFI_DEVICE_PATH_UTILITIES_PROTOCOL;
+
+extern EFI_GUID gEfiDevicePathUtilitiesProtocolGuid;
+
+UINTN
+StrLen (
+  CONST CHAR16   *String
+  );
+
+VOID *
+AllocateCopyPool (
+  UINTN       AllocationSize,
+  CONST VOID  *Buffer
+  );
+
+INTN
+StrnCmp (
+  CONST CHAR16              *FirstString,
+  CONST CHAR16              *SecondString,
+  UINTN                     Length
+  );
+
+RETURN_STATUS
+StrToGuid (
+  CONST CHAR16       *String,
+  EFI_GUID               *Guid
+  );
+
+RETURN_STATUS
+StrHexToBytes (
+  CONST CHAR16       *String,
+  UINTN              Length,
+  UINT8              *Buffer,
+  UINTN              MaxBufferSize
+  );
+
+UINTN
+InternalHexCharToUintn (
+  CHAR16                    Char
+  );
+
+VOID *
+InternalAllocateCopyPool (
+   UINTN            AllocationSize,
+   CONST VOID       *Buffer
+  );
+
+BOOLEAN
+InternalIsDecimalDigitCharacter (
+        CHAR16                    Char
+  );
+
+UINT32
+SwapBytes32 (
+        UINT32                    Value
+  );
+
+UINT16
+SwapBytes16 (
+        UINT16                    Value
+  );
+
+EFI_GUID *
+CopyGuid (
+   EFI_GUID       *DestinationGuid,
+   CONST EFI_GUID  *SourceGuid
+  );
+
+UINT64
+WriteUnaligned64 (
+   UINT64                    *Buffer,
+   UINT64                    Value
+  );
+
+UINT64
+ReadUnaligned64 (
+   CONST UINT64              *Buffer
+  );
+
+UINTN
+StrSize (
+  CONST CHAR16              *String
+  );
+
+UINTN
+StrHexToUintn (
+  CONST CHAR16              *String
+  );
+
+UINTN
+StrDecimalToUintn (
+  CONST CHAR16              *String
+  );
+
+UINT64
+StrHexToUint64 (
+  CONST CHAR16             *String
+  );
+
+UINT64
+StrDecimalToUint64 (
+  CONST CHAR16              *String
+  );
+
+RETURN_STATUS
+StrHexToUint64S (
+    CONST CHAR16       *String,
+    CHAR16             **EndPointer,
+    UINT64             *Data
+  );
+
+RETURN_STATUS
+StrHexToUintnS (
+    CONST CHAR16             *String,
+         CHAR16             **EndPointer,  OPTIONAL
+         UINTN              *Data
+  );
+
+RETURN_STATUS
+StrDecimalToUint64S (
+    CONST CHAR16             *String,
+         CHAR16             **EndPointer,  OPTIONAL
+         UINT64             *Data
+  );
+
+RETURN_STATUS
+StrDecimalToUintnS (
+    CONST CHAR16             *String,
+         CHAR16             **EndPointer,  OPTIONAL
+         UINTN              *Data
+  );
+
+VOID *
+ReallocatePool (
+   UINTN  OldSize,
+   UINTN  NewSize,
+   VOID   *OldBuffer  OPTIONAL
+  );
+
+VOID *
+InternalReallocatePool (
+   UINTN            OldSize,
+   UINTN            NewSize,
+   VOID             *OldBuffer  OPTIONAL
+  );
+
+VOID *
+InternalAllocateZeroPool (
+   UINTN            AllocationSize
+  ) ;
+
+VOID *
+InternalAllocatePool (
+   UINTN            AllocationSize
+  );
+
+UINTN
+StrnLenS (
+   CONST CHAR16              *String,
+   UINTN                     MaxSize
+  );
+
+CHAR16
+InternalCharToUpper (
+        CHAR16                    Char
+  );
+
+UINTN
+DevicePathNodeLength (
+  CONST VOID  *Node
+  );
+
+UINT16
+SetDevicePathNodeLength (
+  VOID  *Node,
+  UINTN     Length
+  );
+
+INTN
+StrCmp (
+  CONST CHAR16              *FirstString,
+  CONST CHAR16              *SecondString
+  );
+
+UINT64
+SwapBytes64 (
+  UINT64                    Value
+  );
+
+UINT64
+InternalMathSwapBytes64 (
+  UINT64                    Operand
+  );
+
+RETURN_STATUS
+StrToIpv4Address (
+  CONST CHAR16       *String,
+  CHAR16             **EndPointer,
+  EFI_IPv4_ADDRESS       *Address,
+  UINT8              *PrefixLength
+  );
+
+RETURN_STATUS
+StrToIpv6Address (
+  CONST CHAR16       *String,
+  CHAR16             **EndPointer,
+  EFI_IPv6_ADDRESS       *Address,
+  UINT8              *PrefixLength
+  );
+
+RETURN_STATUS
+StrCpyS (
+  CHAR16       *Destination,
+  UINTN        DestMax,
+  CONST CHAR16 *Source
+  );
+
+RETURN_STATUS
+UnicodeStrToAsciiStrS (
+  CONST CHAR16              *Source,
+  CHAR8                     *Destination,
+  UINTN                     DestMax
+  );
+VOID *
+AllocatePool (
+  UINTN  AllocationSize
+  );
+
+VOID
+SetDevicePathEndNode (
+   VOID  *Node
+  );
+
+BOOLEAN
+IsDevicePathValid (
+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+   UINTN                    MaxSize
+  );
+
+UINT8
+DevicePathType (
+   CONST VOID  *Node
+  );
+
+UINT8
+DevicePathSubType (
+   CONST VOID  *Node
+  );
+
+UINTN
+DevicePathNodeLength (
+   CONST VOID  *Node
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+NextDevicePathNode (
+   CONST VOID  *Node
+  );
+
+BOOLEAN
+IsDevicePathEndType (
+   CONST VOID  *Node
+  );
+
+BOOLEAN
+IsDevicePathEnd (
+   CONST VOID  *Node
+  );
+BOOLEAN
+IsDevicePathEndInstance (
+   CONST VOID  *Node
+  );
+
+UINT16
+SetDevicePathNodeLength (
+    VOID  *Node,
+   UINTN     Length
+  );
+
+VOID
+SetDevicePathEndNode (
+   VOID  *Node
+  );
+
+UINTN
+UefiDevicePathLibGetDevicePathSize (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibDuplicateDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibAppendDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibAppendDevicePathNode (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibAppendDevicePathInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibGetNextDevicePathInstance (
+    EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
+   UINTN                          *Size
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+UefiDevicePathLibCreateDeviceNode (
+   UINT8                           NodeType,
+   UINT8                           NodeSubType,
+   UINT16                          NodeLength
+  );
+
+BOOLEAN
+UefiDevicePathLibIsDevicePathMultiInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+UINT16
+WriteUnaligned16 (
+  UINT16                    *Buffer,
+  UINT16                    Value
+  );
+
+UINT16
+ReadUnaligned16 (
+  CONST UINT16              *Buffer
+  );
+
+VOID *
+AllocateZeroPool (
+  UINTN  AllocationSize
+  );
+
+BOOLEAN
+InternalIsHexaDecimalDigitCharacter (
+  CHAR16                    Char
+  );
+
+BOOLEAN
+InternalSafeStringIsOverlap (
+  IN VOID    *Base1,
+  IN UINTN   Size1,
+  IN VOID    *Base2,
+  IN UINTN   Size2
+  );
+
+BOOLEAN
+InternalSafeStringNoStrOverlap (
+  IN CHAR16  *Str1,
+  IN UINTN   Size1,
+  IN CHAR16  *Str2,
+  IN UINTN   Size2
+  );
+
+#endif
diff --git a/BaseTools/Source/C/DevicePath/GNUmakefile b/BaseTools/Source/C/DevicePath/GNUmakefile
new file mode 100644
index 0000000..27f6fa1
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/GNUmakefile
@@ -0,0 +1,30 @@
+## @file
+# GNU/Linux makefile for 'DevicePath' module build.
+#
+# Copyright (c) 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.
+#
+ARCH ?= IA32
+MAKEROOT ?= ..
+
+APPNAME = DevicePath
+
+OBJECTS = DevicePath.o UefiDevicePathLib.o DevicePathFromText.o  DevicePathUtilities.o
+
+include $(MAKEROOT)/Makefiles/app.makefile
+
+LIBS = -lCommon
+ifeq ($(CYGWIN), CYGWIN)
+  LIBS += -L/lib/e2fsprogs -luuid
+endif
+
+ifeq ($(LINUX), Linux)
+  LIBS += -luuid
+endif
+
diff --git a/BaseTools/Source/C/DevicePath/Makefile b/BaseTools/Source/C/DevicePath/Makefile
new file mode 100644
index 0000000..a069c22
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/Makefile
@@ -0,0 +1,24 @@
+## @file
+# Windows makefile for 'DevicePath' module build.
+#
+# Copyright (c) 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 ..\Makefiles\ms.common
+
+APPNAME = DevicePath
+
+LIBS = $(LIB_PATH)\Common.lib
+
+OBJECTS = DevicePath.obj UefiDevicePathLib.obj DevicePathFromText.obj  DevicePathUtilities.obj
+
+#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib
+
+!INCLUDE ..\Makefiles\ms.app
+
diff --git a/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
new file mode 100644
index 0000000..a2e0322
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
@@ -0,0 +1,298 @@
+/** @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) 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"
+
+/**
+  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
+GetDevicePathSize (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  return UefiDevicePathLibGetDevicePathSize (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 *
+DuplicateDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  return UefiDevicePathLibDuplicateDevicePath (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 *
+AppendDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
+  )
+{
+  return UefiDevicePathLibAppendDevicePath (FirstDevicePath, SecondDevicePath);
+}
+
+/**
+  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 *
+AppendDevicePathNode (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
+  )
+{
+  return UefiDevicePathLibAppendDevicePathNode (DevicePath, DevicePathNode);
+}
+
+/**
+  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 *
+AppendDevicePathInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance OPTIONAL
+  )
+{
+  return UefiDevicePathLibAppendDevicePathInstance (DevicePath, DevicePathInstance);
+}
+
+/**
+  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 *
+GetNextDevicePathInstance (
+    EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
+   UINTN                          *Size
+  )
+{
+  return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, 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 *
+CreateDeviceNode (
+   UINT8                           NodeType,
+   UINT8                           NodeSubType,
+   UINT16                          NodeLength
+  )
+{
+  return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType, 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
+IsDevicePathMultiInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  )
+{
+  return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath);
+}
+
+/**
+  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 *
+ConvertTextToDeviceNode (
+   CONST CHAR16 *TextDeviceNode
+  )
+{
+  return UefiDevicePathLibConvertTextToDeviceNode (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 *
+ConvertTextToDevicePath (
+   CONST CHAR16 *TextDevicePath
+ )
+{
+  return UefiDevicePathLibConvertTextToDevicePath (TextDevicePath);
+}
diff --git a/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h
new file mode 100644
index 0000000..e03fbd0
--- /dev/null
+++ b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h
@@ -0,0 +1,473 @@
+/** @file
+  Definition for Device Path library.
+
+Copyright (c) 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.
+
+**/
+#ifndef _UEFI_DEVICE_PATH_LIB_H_
+#define _UEFI_DEVICE_PATH_LIB_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#ifdef __GNUC__
+#include <unistd.h>
+#else
+#include <direct.h>
+#endif
+#include <Common/UefiBaseTypes.h>
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+#include "DevicePath.h"
+#include "DevicePathUtilities.h"
+#include "DevicePathFromText.h"
+
+
+#define IS_COMMA(a)                ((a) == L',')
+#define IS_HYPHEN(a)               ((a) == L'-')
+#define IS_DOT(a)                  ((a) == L'.')
+#define IS_LEFT_PARENTH(a)         ((a) == L'(')
+#define IS_RIGHT_PARENTH(a)        ((a) == L')')
+#define IS_SLASH(a)                ((a) == L'/')
+#define IS_NULL(a)                 ((a) == L'\0')
+
+#define MAX_UINTN MAX_ADDRESS
+#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL)
+#define MAX_UINT16  ((UINT16)0xFFFF)
+#define MAX_UINT8   ((UINT8)0xFF)
+
+#define END_DEVICE_PATH_LENGTH               (sizeof (EFI_DEVICE_PATH_PROTOCOL))
+#define MAX_DEVICE_PATH_NODE_COUNT   1024
+#define SIZE_64KB   0x00010000
+#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0]))
+#define ASCII_RSIZE_MAX 1000000
+#ifndef RSIZE_MAX
+#define RSIZE_MAX 1000000
+#endif
+
+//
+// Private Data structure
+//
+typedef
+EFI_DEVICE_PATH_PROTOCOL  *
+(*DEVICE_PATH_FROM_TEXT) (
+  IN  CHAR16 *Str
+ );
+
+typedef struct {
+  CHAR16  *Str;
+  UINTN   Count;
+  UINTN   Capacity;
+} POOL_PRINT;
+
+
+typedef struct {
+  CHAR16                    *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()
+
+/**
+  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
+UefiDevicePathLibGetDevicePathSize (
+   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 *
+UefiDevicePathLibDuplicateDevicePath (
+   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 *
+UefiDevicePathLibAppendDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
+   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 *
+UefiDevicePathLibAppendDevicePathNode (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
+   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 *
+UefiDevicePathLibAppendDevicePathInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
+   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 *
+UefiDevicePathLibGetNextDevicePathInstance (
+   EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
+   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 *
+UefiDevicePathLibCreateDeviceNode (
+   UINT8                           NodeType,
+   UINT8                           NodeSubType,
+   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
+UefiDevicePathLibIsDevicePathMultiInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+/**
+  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 *
+UefiDevicePathLibConvertTextToDeviceNode (
+   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 *
+UefiDevicePathLibConvertTextToDevicePath (
+   CONST CHAR16 *TextDevicePath
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+CreateDeviceNode (
+   UINT8                           NodeType,
+   UINT8                           NodeSubType,
+   UINT16                          NodeLength
+  );
+
+ EFI_DEVICE_PATH_PROTOCOL *
+CreateDeviceNode (
+   UINT8                           NodeType,
+   UINT8                           NodeSubType,
+   UINT16                          NodeLength
+  );
+
+BOOLEAN
+IsDevicePathMultiInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+GetNextDevicePathInstance (
+    EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
+   UINTN                          *Size
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendDevicePathInstance (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance OPTIONAL
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendDevicePathNode (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
+  );
+EFI_DEVICE_PATH_PROTOCOL *
+AppendDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+DuplicateDevicePath (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+UINTN
+GetDevicePathSize (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
+  );
+
+CHAR16 *
+ConvertDeviceNodeToText (
+   CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
+   BOOLEAN                         DisplayOnly,
+   BOOLEAN                         AllowShortcuts
+  );
+
+CHAR16 *
+ConvertDevicePathToText (
+   CONST EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
+   BOOLEAN                          DisplayOnly,
+   BOOLEAN                          AllowShortcuts
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertTextToDeviceNode (
+   CONST CHAR16 *TextDeviceNode
+  );
+
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertTextToDevicePath (
+   CONST CHAR16 *TextDevicePath
+  );
+
+
+#endif
diff --git a/BaseTools/Source/C/GNUmakefile b/BaseTools/Source/C/GNUmakefile
index 0dc7482..37421ad 100644
--- a/BaseTools/Source/C/GNUmakefile
+++ b/BaseTools/Source/C/GNUmakefile
@@ -65,11 +65,12 @@ APPLICATIONS = \
   GenCrc32 \
   GenVtf \
   LzmaCompress \
   Split \
   TianoCompress \
-  VolInfo
+  VolInfo \
+  DevicePath
 
 SUBDIRS := $(LIBRARIES) $(APPLICATIONS)
 
 $(LIBRARIES): $(MAKEROOT)/libs
 $(APPLICATIONS): $(LIBRARIES) $(MAKEROOT)/bin $(VFRAUTOGEN)
diff --git a/BaseTools/Source/C/Makefile b/BaseTools/Source/C/Makefile
index 50be773..5428180 100644
--- a/BaseTools/Source/C/Makefile
+++ b/BaseTools/Source/C/Makefile
@@ -1,9 +1,9 @@
 ## @file
 # Windows makefile for C tools build.
 #
-# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 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
 #
@@ -30,11 +30,12 @@ APPLICATIONS = \
   GenVtf \
   LzmaCompress \
   Split \
   TianoCompress \
   VolInfo \
-  VfrCompile
+  VfrCompile \
+  DevicePath
 
 all: libs apps install
 
 libs: $(LIBRARIES)
 	@echo.
diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
index c51b685..104a370 100644
--- a/BaseTools/Source/Python/Common/Misc.py
+++ b/BaseTools/Source/Python/Common/Misc.py
@@ -36,11 +36,11 @@ from CommonDataClass.DataClass import *
 from Parsing import GetSplitValueList
 from Common.LongFilePathSupport import OpenLongFilePath as open
 from Common.MultipleWorkspace import MultipleWorkspace as mws
 import uuid
 from CommonDataClass.Exceptions import BadExpression
-
+import subprocess
 ## Regular expression used to find out place holders in string template
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)
 
 ## Dictionary used to store file time stamp for quick re-access
 gFileTimeStampCache = {}    # {file path : file time stamp}
@@ -1472,11 +1472,42 @@ def AnalyzePcdExpression(Setting):
         StartPos = Pos + 1
 
     return FieldList
 
 def ParseDevPathValue (Value):
-    pass
+    DevPathList = [ "Path","HardwarePath","Pci","PcCard","MemoryMapped","VenHw","Ctrl","BMC","AcpiPath","Acpi","PciRoot",
+                    "PcieRoot","Floppy","Keyboard","Serial","ParallelPort","AcpiEx","AcpiExp","AcpiAdr","Msg","Ata","Scsi",
+                    "Fibre","FibreEx","I1394","USB","I2O","Infiniband","VenMsg","VenPcAnsi","VenVt100","VenVt100Plus",
+                    "VenUtf8","UartFlowCtrl","SAS","SasEx","NVMe","UFS","SD","eMMC","DebugPort","MAC","IPv4","IPv6","Uart",
+                    "UsbClass","UsbAudio","UsbCDCControl","UsbHID","UsbImage","UsbPrinter","UsbMassStorage","UsbHub",
+                    "UsbCDCData","UsbSmartCard","UsbVideo","UsbDiagnostic","UsbWireless","UsbDeviceFirmwareUpdate",
+                    "UsbIrdaBridge","UsbTestAndMeasurement","UsbWwid","Unit","iSCSI","Vlan","Uri","Bluetooth","Wi-Fi",
+                    "MediaPath","HD","CDROM","VenMedia","Media","Fv","FvFile","Offset","RamDisk","VirtualDisk","VirtualCD",
+                    "PersistentVirtualDisk","PersistentVirtualCD","BbsPath","BBS","Sata" ]
+    if '\\' in Value:
+        Value.replace('\\', '/').replace(' ', '')
+    for Item in Value.split('/'):
+        Key = Item.strip().split('(')[0]
+        if Key not in DevPathList:
+            pass
+
+    Cmd = 'DevicePath ' + '"' + Value + '"'
+    try:
+        p = subprocess.Popen(Cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+        out, err = p.communicate()
+    except Exception, X:
+        raise BadExpression("DevicePath: %s" % (str(X)) )
+    finally:
+        subprocess._cleanup()
+        p.stdout.close()
+        p.stderr.close()
+    if err:
+        raise BadExpression("DevicePath: %s" % str(err))
+    Size = len(out.split())
+    out = ','.join(out.split())
+    return '{' + out + '}', Size
+
 
 def ParseFieldValue (Value):
     if type(Value) == type(0):
         return Value, (Value.bit_length() + 7) / 8
     if type(Value) <> type(''):
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index 05b26a3..f9cd429 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -2060,11 +2060,11 @@ class DscBuildData(PlatformBuildClassObject):
                 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
                 if ModuleFile in self._Modules:
                     continue
                 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
                 PkgSet.update(ModuleData.Packages)
-            self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
+            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
         return self._DecPcds
     _Macros             = property(_GetMacros)
     Arch                = property(_GetArch, _SetArch)
     Platform            = property(_GetPlatformName)
     PlatformName        = property(_GetPlatformName)
-- 
2.6.1.windows.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Patch 2/2] BaseTools: Add DevicePath support for PCD values
  2017-12-26 16:40 ` [Patch 2/2] BaseTools: Add DevicePath support for PCD values Yonghong Zhu
@ 2017-12-27  2:40   ` Gao, Liming
  0 siblings, 0 replies; 4+ messages in thread
From: Gao, Liming @ 2017-12-27  2:40 UTC (permalink / raw)
  To: Zhu, Yonghong, edk2-devel@lists.01.org; +Cc: Feng, YunhuaX

Yonghong:
   For DevicePath definition, please define them in BaseTools\Source\C\Include\Protocol directory to align MdePkg layout. 

Thanks
Liming
>-----Original Message-----
>From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>Yonghong Zhu
>Sent: Wednesday, December 27, 2017 12:40 AM
>To: edk2-devel@lists.01.org
>Cc: Feng, YunhuaX <yunhuax.feng@intel.com>
>Subject: [edk2] [Patch 2/2] BaseTools: Add DevicePath support for PCD values
>
>Use C code parse device path to output hex string, and Python
>run command when PCD Value need device path parse.
>
>https://bugzilla.tianocore.org/show_bug.cgi?id=541
>
>Contributed-under: TianoCore Contribution Agreement 1.1
>Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
>Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
>---
> BaseTools/Source/BinaryFiles.txt                   |    3 +-
> BaseTools/Source/C/DevicePath/DevicePath.c         |  188 ++
> BaseTools/Source/C/DevicePath/DevicePath.h         | 1404 ++++++++
> BaseTools/Source/C/DevicePath/DevicePathFromText.c | 3503
>++++++++++++++++++++
> BaseTools/Source/C/DevicePath/DevicePathFromText.h |   72 +
> .../Source/C/DevicePath/DevicePathUtilities.c      | 2352 +++++++++++++
> .../Source/C/DevicePath/DevicePathUtilities.h      |  555 ++++
> BaseTools/Source/C/DevicePath/GNUmakefile          |   30 +
> BaseTools/Source/C/DevicePath/Makefile             |   24 +
> BaseTools/Source/C/DevicePath/UefiDevicePathLib.c  |  298 ++
> BaseTools/Source/C/DevicePath/UefiDevicePathLib.h  |  473 +++
> BaseTools/Source/C/GNUmakefile                     |    3 +-
> BaseTools/Source/C/Makefile                        |    5 +-
> BaseTools/Source/Python/Common/Misc.py             |   35 +-
> BaseTools/Source/Python/Workspace/DscBuildData.py  |    2 +-
> 15 files changed, 8940 insertions(+), 7 deletions(-)
> create mode 100644 BaseTools/Source/C/DevicePath/DevicePath.c
> create mode 100644 BaseTools/Source/C/DevicePath/DevicePath.h
> create mode 100644 BaseTools/Source/C/DevicePath/DevicePathFromText.c
> create mode 100644 BaseTools/Source/C/DevicePath/DevicePathFromText.h
> create mode 100644 BaseTools/Source/C/DevicePath/DevicePathUtilities.c
> create mode 100644 BaseTools/Source/C/DevicePath/DevicePathUtilities.h
> create mode 100644 BaseTools/Source/C/DevicePath/GNUmakefile
> create mode 100644 BaseTools/Source/C/DevicePath/Makefile
> create mode 100644 BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
> create mode 100644 BaseTools/Source/C/DevicePath/UefiDevicePathLib.h
>
>diff --git a/BaseTools/Source/BinaryFiles.txt
>b/BaseTools/Source/BinaryFiles.txt
>index 7b014a7..a5273d4 100644
>--- a/BaseTools/Source/BinaryFiles.txt
>+++ b/BaseTools/Source/BinaryFiles.txt
>@@ -9,11 +9,11 @@
> # [ExtraFiles.Win32] section.
> # The [CxFreeze.Win32] section is maintained by the owner of the Build
>Server who
> # must ensure that files that are required by the cx_freeze frozen binaries
>are
> # present in the Bin\Win32 directory.
> #
>-# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
>+# Copyright (c) 2014 - 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
>@@ -57,10 +57,11 @@ TianoCompress.exe
> Trim.exe
> UPT.exe
> VfrCompile.exe
> VolInfo.exe
> Pkcs7Sign.exe
>+DevicePath.exe
>
> [ExtraFiles.Win32]
> TestSigningPrivateKey.pem
> config.ini
> exception.xml
>diff --git a/BaseTools/Source/C/DevicePath/DevicePath.c
>b/BaseTools/Source/C/DevicePath/DevicePath.c
>new file mode 100644
>index 0000000..6c32ad4
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/DevicePath.c
>@@ -0,0 +1,188 @@
>+/** @file
>+  Definition for Device Path Tool.
>+
>+Copyright (c) 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"
>+
>+//
>+// Utility Name
>+//
>+#define UTILITY_NAME  "DevicePath"
>+
>+//
>+// Utility version information
>+//
>+#define UTILITY_MAJOR_VERSION 0
>+#define UTILITY_MINOR_VERSION 1
>+
>+EFI_GUID gEfiDebugPortDevicePathGuid =
>DEVICE_PATH_MESSAGING_DEBUGPORT;
>+EFI_GUID gEfiPcAnsiGuid = EFI_PC_ANSI_GUID;
>+EFI_GUID gEfiVT100Guid = EFI_VT_100_GUID;
>+EFI_GUID gEfiVT100PlusGuid = EFI_VT_100_PLUS_GUID;
>+EFI_GUID gEfiVTUTF8Guid = EFI_VT_UTF8_GUID;
>+EFI_GUID gEfiUartDevicePathGuid = EFI_UART_DEVICE_PATH_GUID;
>+EFI_GUID gEfiSasDevicePathGuid = EFI_SAS_DEVICE_PATH_GUID;
>+EFI_GUID gEfiVirtualDiskGuid = { 0x77AB535A, 0x45FC, 0x624B, {0x55, 0x60,
>0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }};
>+EFI_GUID gEfiVirtualCdGuid = { 0x3D5ABD30, 0x4175, 0x87CE, {0x6D, 0x64,
>0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB }};
>+EFI_GUID gEfiPersistentVirtualDiskGuid =  { 0x5CEA02C9, 0x4D07, 0x69D3,
>{0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 }};
>+EFI_GUID gEfiPersistentVirtualCdGuid = { 0x08018188, 0x42CD, 0xBB48, {0x10,
>0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D }};
>+
>+STATIC
>+VOID
>+Version (
>+  VOID
>+)
>+/*++
>+
>+Routine Description:
>+
>+  Displays the standard utility information to SDTOUT
>+
>+Arguments:
>+
>+  None
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME,
>UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
>+}
>+
>+STATIC
>+VOID
>+Usage (
>+  VOID
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Displays the utility usage syntax to STDOUT
>+
>+Arguments:
>+
>+  None
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  //
>+  // Summary usage
>+  //
>+  fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME);
>+
>+  //
>+  // Copyright declaration
>+  //
>+  fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights
>reserved.\n\n");
>+  //
>+  // Details Option
>+  //
>+  fprintf (stdout, "Options:\n");
>+  fprintf (stdout, "  DevicePathString      DevicePathString like as:\n"
>+                "                        \"PciRoot(0)/Pci(0,0)\"\n"
>+                "                        start with \" and end with \"\n"
>+                "                        not support blank in device path string.\n");
>+
>+  fprintf (stdout, "  --version             Show program's version number and
>exit.\n");
>+  fprintf (stdout, "  -h, --help            Show this help message and exit.\n");
>+}
>+
>+
>+void print_mem(void const *vp, size_t n)
>+{
>+    unsigned char const *p = vp;
>+    for (size_t i=0; i<n; i++) {
>+        printf("0x%02x ", p[i]);
>+  }
>+}
>+
>+VOID
>+Ascii2UnicodeString (
>+  CHAR8    *String,
>+  CHAR16   *UniString
>+ )
>+/*++
>+
>+Routine Description:
>+
>+  Write ascii string as unicode string format to FILE
>+
>+Arguments:
>+
>+  String      - Pointer to string that is written to FILE.
>+  UniString   - Pointer to unicode string
>+
>+Returns:
>+
>+  NULL
>+
>+--*/
>+{
>+  while (*String != '\0') {
>+    *(UniString++) = (CHAR16) *(String++);
>+  }
>+  //
>+  // End the UniString with a NULL.
>+  //
>+  *UniString = '\0';
>+}
>+
>+int main(int argc, CHAR8 *argv[])
>+{
>+  CHAR8 * Str;
>+  CHAR16* Str16;
>+  EFI_DEVICE_PATH_PROTOCOL *DevicePath;
>+
>+  if (argc == 1) {
>+    Error (NULL, 0, 1001, "Missing options", "No input options specified.");
>+    Usage ();
>+    return STATUS_ERROR;
>+  }
>+  if ((stricmp (argv[1], "-h") == 0) || (stricmp (argv[1], "--help") == 0)) {
>+    Version ();
>+    Usage ();
>+    return STATUS_SUCCESS;
>+  }
>+
>+  if (stricmp (argv[1], "--version") == 0) {
>+    Version ();
>+    return STATUS_SUCCESS;
>+  }
>+  Str = argv[1];
>+  if (Str == NULL) {
>+    fprintf(stderr, "Invalid option value, Device Path can't be NULL");
>+    return STATUS_ERROR;
>+  }
>+  Str16 = (CHAR16 *)malloc(1024);
>+  if (Str16 == NULL) {
>+    fprintf(stderr, "Resource, memory cannot be allcoated");
>+    return STATUS_ERROR;
>+  }
>+  Ascii2UnicodeString(Str, Str16);
>+  DevicePath = UefiDevicePathLibConvertTextToDevicePath(Str16);
>+  while (!((DevicePath->Type == END_DEVICE_PATH_TYPE) && (DevicePath-
>>SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) )
>+  {
>+    print_mem(DevicePath, (DevicePath->Length[0] | DevicePath->Length[1]
><< 8));
>+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePath +
>(DevicePath->Length[0] | DevicePath->Length[1] << 8));
>+  }
>+  print_mem(DevicePath, (DevicePath->Length[0] | DevicePath->Length[1]
><< 8));
>+  putchar('\n');
>+  return STATUS_SUCCESS;
>+}
>diff --git a/BaseTools/Source/C/DevicePath/DevicePath.h
>b/BaseTools/Source/C/DevicePath/DevicePath.h
>new file mode 100644
>index 0000000..389c993
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/DevicePath.h
>@@ -0,0 +1,1404 @@
>+/** @file
>+  The device path protocol as defined in UEFI 2.0.
>+
>+  The device path represents a programmatic path to a device,
>+  from a software point of view. The path must persist from boot to boot, so
>+  it can not contain things like PCI bus numbers that change from boot to boot.
>+
>+Copyright (c) 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 that 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 __EFI_DEVICE_PATH_H__
>+#define __EFI_DEVICE_PATH_H__
>+
>+#include <Guid/PcAnsi.h>
>+#include <IndustryStandard/Acpi3_0.h>
>+
>+///
>+/// Device Path protocol.
>+///
>+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
>+  { \
>+    0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b }
>\
>+  }
>+
>+///
>+/// Device Path guid definition for backward-compatible with EFI1.1.
>+///
>+#define DEVICE_PATH_PROTOCOL  EFI_DEVICE_PATH_PROTOCOL_GUID
>+
>+#pragma pack(1)
>+
>+/**
>+  This protocol can be used on any device handle to obtain generic
>path/location
>+  information concerning the physical device or logical device. If the handle
>does
>+  not logically map to a physical device, the handle may not necessarily
>support
>+  the device path protocol. The device path describes the location of the
>device
>+  the handle is for. The size of the Device Path can be determined from the
>structures
>+  that make up the Device Path.
>+**/
>+typedef struct {
>+  UINT8 Type;       ///< 0x01 Hardware Device Path.
>+                    ///< 0x02 ACPI Device Path.
>+                    ///< 0x03 Messaging Device Path.
>+                    ///< 0x04 Media Device Path.
>+                    ///< 0x05 BIOS Boot Specification Device Path.
>+                    ///< 0x7F End of Hardware Device Path.
>+
>+  UINT8 SubType;    ///< Varies by Type
>+                    ///< 0xFF End Entire Device Path, or
>+                    ///< 0x01 End This Instance of a Device Path and start a new
>+                    ///< Device Path.
>+
>+  UINT8 Length[2];  ///< Specific Device Path data. Type and Sub-Type define
>+                    ///< type of data. Size of data is included in Length.
>+
>+} EFI_DEVICE_PATH_PROTOCOL;
>+
>+///
>+/// Device Path protocol definition for backward-compatible with EFI1.1.
>+///
>+typedef EFI_DEVICE_PATH_PROTOCOL  EFI_DEVICE_PATH;
>+
>+///
>+/// Hardware Device Paths.
>+///
>+#define HARDWARE_DEVICE_PATH      0x01
>+
>+///
>+/// PCI Device Path SubType.
>+///
>+#define HW_PCI_DP                 0x01
>+
>+///
>+/// PCI Device Path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// PCI Function Number.
>+  ///
>+  UINT8                           Function;
>+  ///
>+  /// PCI Device Number.
>+  ///
>+  UINT8                           Device;
>+} PCI_DEVICE_PATH;
>+
>+///
>+/// PCCARD Device Path SubType.
>+///
>+#define HW_PCCARD_DP              0x02
>+
>+///
>+/// PCCARD Device Path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Function Number (0 = First Function).
>+  ///
>+  UINT8                           FunctionNumber;
>+} PCCARD_DEVICE_PATH;
>+
>+///
>+/// Memory Mapped Device Path SubType.
>+///
>+#define HW_MEMMAP_DP             0x03
>+
>+///
>+/// Memory Mapped Device Path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// EFI_MEMORY_TYPE
>+  ///
>+  UINT32                          MemoryType;
>+  ///
>+  /// Starting Memory Address.
>+  ///
>+  EFI_PHYSICAL_ADDRESS            StartingAddress;
>+  ///
>+  /// Ending Memory Address.
>+  ///
>+  EFI_PHYSICAL_ADDRESS            EndingAddress;
>+} MEMMAP_DEVICE_PATH;
>+
>+///
>+/// Hardware Vendor Device Path SubType.
>+///
>+#define HW_VENDOR_DP              0x04
>+
>+///
>+/// The Vendor Device Path allows the creation of vendor-defined Device
>Paths. A vendor must
>+/// allocate a Vendor GUID for a Device Path. The Vendor GUID can then be
>used to define the
>+/// contents on the n bytes that follow in the Vendor Device Path node.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Vendor-assigned GUID that defines the data that follows.
>+  ///
>+  EFI_GUID                        Guid;
>+  ///
>+  /// Vendor-defined variable size data.
>+  ///
>+} VENDOR_DEVICE_PATH;
>+
>+///
>+/// Controller Device Path SubType.
>+///
>+#define HW_CONTROLLER_DP          0x05
>+
>+///
>+/// Controller Device Path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Controller number.
>+  ///
>+  UINT32                          ControllerNumber;
>+} CONTROLLER_DEVICE_PATH;
>+
>+///
>+/// BMC Device Path SubType.
>+///
>+#define HW_BMC_DP                 0x06
>+
>+///
>+/// BMC Device Path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Interface Type.
>+  ///
>+  UINT8                           InterfaceType;
>+  ///
>+  /// Base Address.
>+  ///
>+  UINT8                           BaseAddress[8];
>+} BMC_DEVICE_PATH;
>+
>+///
>+/// ACPI Device Paths.
>+///
>+#define ACPI_DEVICE_PATH          0x02
>+
>+///
>+/// ACPI Device Path SubType.
>+///
>+#define ACPI_DP                   0x01
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Device's PnP hardware ID stored in a numeric 32-bit
>+  /// compressed EISA-type ID. This value must match the
>+  /// corresponding _HID in the ACPI name space.
>+  ///
>+  UINT32                          HID;
>+  ///
>+  /// Unique ID that is required by ACPI if two devices have the
>+  /// same _HID. This value must also match the corresponding
>+  /// _UID/_HID pair in the ACPI name space. Only the 32-bit
>+  /// numeric value type of _UID is supported. Thus, strings must
>+  /// not be used for the _UID in the ACPI name space.
>+  ///
>+  UINT32                          UID;
>+} ACPI_HID_DEVICE_PATH;
>+
>+///
>+/// Expanded ACPI Device Path SubType.
>+///
>+#define ACPI_EXTENDED_DP          0x02
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Device's PnP hardware ID stored in a numeric 32-bit
>+  /// compressed EISA-type ID. This value must match the
>+  /// corresponding _HID in the ACPI name space.
>+  ///
>+  UINT32                          HID;
>+  ///
>+  /// Unique ID that is required by ACPI if two devices have the
>+  /// same _HID. This value must also match the corresponding
>+  /// _UID/_HID pair in the ACPI name space.
>+  ///
>+  UINT32                          UID;
>+  ///
>+  /// Device's compatible PnP hardware ID stored in a numeric
>+  /// 32-bit compressed EISA-type ID. This value must match at
>+  /// least one of the compatible device IDs returned by the
>+  /// corresponding _CID in the ACPI name space.
>+  ///
>+  UINT32                          CID;
>+  ///
>+  /// Optional variable length _HIDSTR.
>+  /// Optional variable length _UIDSTR.
>+  /// Optional variable length _CIDSTR.
>+  ///
>+} ACPI_EXTENDED_HID_DEVICE_PATH;
>+
>+//
>+//  EISA ID Macro
>+//  EISA ID Definition 32-bits
>+//   bits[15:0] - three character compressed ASCII EISA ID.
>+//   bits[31:16] - binary number
>+//    Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z'
>+//
>+#define PNP_EISA_ID_CONST         0x41d0
>+#define EISA_ID(_Name, _Num)      ((UINT32)((_Name) | (_Num) << 16))
>+#define EISA_PNP_ID(_PNPId)       (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
>+#define EFI_PNP_ID(_PNPId)        (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
>+
>+#define PNP_EISA_ID_MASK          0xffff
>+#define EISA_ID_TO_NUM(_Id)       ((_Id) >> 16)
>+
>+///
>+/// ACPI _ADR Device Path SubType.
>+///
>+#define ACPI_ADR_DP               0x03
>+
>+///
>+/// The _ADR device path is used to contain video output device attributes to
>support the Graphics
>+/// Output Protocol. The device path can contain multiple _ADR entries if
>multiple video output
>+/// devices are displaying the same output.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// _ADR value. For video output devices the value of this
>+  /// field comes from Table B-2 of the ACPI 3.0 specification. At
>+  /// least one _ADR value is required.
>+  ///
>+  UINT32                          ADR;
>+  //
>+  // This device path may optionally contain more than one _ADR entry.
>+  //
>+} ACPI_ADR_DEVICE_PATH;
>+
>+#define ACPI_ADR_DISPLAY_TYPE_OTHER             0
>+#define ACPI_ADR_DISPLAY_TYPE_VGA               1
>+#define ACPI_ADR_DISPLAY_TYPE_TV                2
>+#define ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL  3
>+#define ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL  4
>+
>+#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput,
>_BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \
>+          ((UINT32)(  ((UINT32)((_DeviceIdScheme) & 0x1) << 31) |  \
>+                      (((_HeadId)                 & 0x7) << 18) |  \
>+                      (((_NonVgaOutput)           & 0x1) << 17) |  \
>+                      (((_BiosCanDetect)          & 0x1) << 16) |  \
>+                      (((_VendorInfo)             & 0xf) << 12) |  \
>+                      (((_Type)                   & 0xf) << 8)  |  \
>+                      (((_Port)                   & 0xf) << 4)  |  \
>+                       ((_Index)                  & 0xf) ))
>+
>+///
>+/// Messaging Device Paths.
>+/// This Device Path is used to describe the connection of devices outside
>the resource domain of the
>+/// system. This Device Path can describe physical messaging information like
>SCSI ID, or abstract
>+/// information like networking protocol IP addresses.
>+///
>+#define MESSAGING_DEVICE_PATH     0x03
>+
>+///
>+/// ATAPI Device Path SubType
>+///
>+#define MSG_ATAPI_DP              0x01
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Set to zero for primary, or one for secondary.
>+  ///
>+  UINT8                           PrimarySecondary;
>+  ///
>+  /// Set to zero for master, or one for slave mode.
>+  ///
>+  UINT8                           SlaveMaster;
>+  ///
>+  /// Logical Unit Number.
>+  ///
>+  UINT16                          Lun;
>+} ATAPI_DEVICE_PATH;
>+
>+///
>+/// SCSI Device Path SubType.
>+///
>+#define MSG_SCSI_DP               0x02
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Target ID on the SCSI bus (PUN).
>+  ///
>+  UINT16                          Pun;
>+  ///
>+  /// Logical Unit Number (LUN).
>+  ///
>+  UINT16                          Lun;
>+} SCSI_DEVICE_PATH;
>+
>+///
>+/// Fibre Channel SubType.
>+///
>+#define MSG_FIBRECHANNEL_DP       0x03
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Reserved for the future.
>+  ///
>+  UINT32                          Reserved;
>+  ///
>+  /// Fibre Channel World Wide Number.
>+  ///
>+  UINT64                          WWN;
>+  ///
>+  /// Fibre Channel Logical Unit Number.
>+  ///
>+  UINT64                          Lun;
>+} FIBRECHANNEL_DEVICE_PATH;
>+
>+///
>+/// Fibre Channel Ex SubType.
>+///
>+#define MSG_FIBRECHANNELEX_DP     0x15
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Reserved for the future.
>+  ///
>+  UINT32                          Reserved;
>+  ///
>+  /// 8 byte array containing Fibre Channel End Device Port Name.
>+  ///
>+  UINT8                           WWN[8];
>+  ///
>+  /// 8 byte array containing Fibre Channel Logical Unit Number.
>+  ///
>+  UINT8                           Lun[8];
>+} FIBRECHANNELEX_DEVICE_PATH;
>+
>+///
>+/// 1394 Device Path SubType
>+///
>+#define MSG_1394_DP               0x04
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Reserved for the future.
>+  ///
>+  UINT32                          Reserved;
>+  ///
>+  /// 1394 Global Unique ID (GUID).
>+  ///
>+  UINT64                          Guid;
>+} F1394_DEVICE_PATH;
>+
>+///
>+/// USB Device Path SubType.
>+///
>+#define MSG_USB_DP                0x05
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL      Header;
>+  ///
>+  /// USB Parent Port Number.
>+  ///
>+  UINT8                         ParentPortNumber;
>+  ///
>+  /// USB Interface Number.
>+  ///
>+  UINT8                         InterfaceNumber;
>+} USB_DEVICE_PATH;
>+
>+///
>+/// USB Class Device Path SubType.
>+///
>+#define MSG_USB_CLASS_DP          0x0f
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL      Header;
>+  ///
>+  /// Vendor ID assigned by USB-IF. A value of 0xFFFF will
>+  /// match any Vendor ID.
>+  ///
>+  UINT16                        VendorId;
>+  ///
>+  /// Product ID assigned by USB-IF. A value of 0xFFFF will
>+  /// match any Product ID.
>+  ///
>+  UINT16                        ProductId;
>+  ///
>+  /// The class code assigned by the USB-IF. A value of 0xFF
>+  /// will match any class code.
>+  ///
>+  UINT8                         DeviceClass;
>+  ///
>+  /// The subclass code assigned by the USB-IF. A value of
>+  /// 0xFF will match any subclass code.
>+  ///
>+  UINT8                         DeviceSubClass;
>+  ///
>+  /// The protocol code assigned by the USB-IF. A value of
>+  /// 0xFF will match any protocol code.
>+  ///
>+  UINT8                         DeviceProtocol;
>+} USB_CLASS_DEVICE_PATH;
>+
>+///
>+/// USB WWID Device Path SubType.
>+///
>+#define MSG_USB_WWID_DP           0x10
>+
>+///
>+/// This device path describes a USB device using its serial number.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL      Header;
>+  ///
>+  /// USB interface number.
>+  ///
>+  UINT16                        InterfaceNumber;
>+  ///
>+  /// USB vendor id of the device.
>+  ///
>+  UINT16                        VendorId;
>+  ///
>+  /// USB product id of the device.
>+  ///
>+  UINT16                        ProductId;
>+  ///
>+  /// Last 64-or-fewer UTF-16 characters of the USB
>+  /// serial number. The length of the string is
>+  /// determined by the Length field less the offset of the
>+  /// Serial Number field (10)
>+  ///
>+  /// CHAR16                     SerialNumber[...];
>+} USB_WWID_DEVICE_PATH;
>+
>+///
>+/// Device Logical Unit SubType.
>+///
>+#define MSG_DEVICE_LOGICAL_UNIT_DP  0x11
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL      Header;
>+  ///
>+  /// Logical Unit Number for the interface.
>+  ///
>+  UINT8                         Lun;
>+} DEVICE_LOGICAL_UNIT_DEVICE_PATH;
>+
>+///
>+/// SATA Device Path SubType.
>+///
>+#define MSG_SATA_DP               0x12
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// The HBA port number that facilitates the connection to the
>+  /// device or a port multiplier. The value 0xFFFF is reserved.
>+  ///
>+  UINT16                          HBAPortNumber;
>+  ///
>+  /// The Port multiplier port number that facilitates the connection
>+  /// to the device. Must be set to 0xFFFF if the device is directly
>+  /// connected to the HBA.
>+  ///
>+  UINT16                          PortMultiplierPortNumber;
>+  ///
>+  /// Logical Unit Number.
>+  ///
>+  UINT16                          Lun;
>+} SATA_DEVICE_PATH;
>+
>+///
>+/// Flag for if the device is directly connected to the HBA.
>+///
>+#define SATA_HBA_DIRECT_CONNECT_FLAG 0x8000
>+
>+///
>+/// I2O Device Path SubType.
>+///
>+#define MSG_I2O_DP                0x06
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Target ID (TID) for a device.
>+  ///
>+  UINT32                          Tid;
>+} I2O_DEVICE_PATH;
>+
>+///
>+/// MAC Address Device Path SubType.
>+///
>+#define MSG_MAC_ADDR_DP           0x0b
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// The MAC address for a network interface padded with 0s.
>+  ///
>+  EFI_MAC_ADDRESS                 MacAddress;
>+  ///
>+  /// Network interface type(i.e. 802.3, FDDI).
>+  ///
>+  UINT8                           IfType;
>+} MAC_ADDR_DEVICE_PATH;
>+
>+///
>+/// IPv4 Device Path SubType
>+///
>+#define MSG_IPv4_DP               0x0c
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// The local IPv4 address.
>+  ///
>+  EFI_IPv4_ADDRESS                LocalIpAddress;
>+  ///
>+  /// The remote IPv4 address.
>+  ///
>+  EFI_IPv4_ADDRESS                RemoteIpAddress;
>+  ///
>+  /// The local port number.
>+  ///
>+  UINT16                          LocalPort;
>+  ///
>+  /// The remote port number.
>+  ///
>+  UINT16                          RemotePort;
>+  ///
>+  /// The network protocol(i.e. UDP, TCP).
>+  ///
>+  UINT16                          Protocol;
>+  ///
>+  /// 0x00 - The Source IP Address was assigned though DHCP.
>+  /// 0x01 - The Source IP Address is statically bound.
>+  ///
>+  BOOLEAN                         StaticIpAddress;
>+  ///
>+  /// The gateway IP address
>+  ///
>+  EFI_IPv4_ADDRESS                GatewayIpAddress;
>+  ///
>+  /// The subnet mask
>+  ///
>+  EFI_IPv4_ADDRESS                SubnetMask;
>+} IPv4_DEVICE_PATH;
>+
>+///
>+/// IPv6 Device Path SubType.
>+///
>+#define MSG_IPv6_DP               0x0d
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// The local IPv6 address.
>+  ///
>+  EFI_IPv6_ADDRESS                LocalIpAddress;
>+  ///
>+  /// The remote IPv6 address.
>+  ///
>+  EFI_IPv6_ADDRESS                RemoteIpAddress;
>+  ///
>+  /// The local port number.
>+  ///
>+  UINT16                          LocalPort;
>+  ///
>+  /// The remote port number.
>+  ///
>+  UINT16                          RemotePort;
>+  ///
>+  /// The network protocol(i.e. UDP, TCP).
>+  ///
>+  UINT16                          Protocol;
>+  ///
>+  /// 0x00 - The Local IP Address was manually configured.
>+  /// 0x01 - The Local IP Address is assigned through IPv6
>+  /// stateless auto-configuration.
>+  /// 0x02 - The Local IP Address is assigned through IPv6
>+  /// stateful configuration.
>+  ///
>+  UINT8                           IpAddressOrigin;
>+  ///
>+  /// The prefix length
>+  ///
>+  UINT8                           PrefixLength;
>+  ///
>+  /// The gateway IP address
>+  ///
>+  EFI_IPv6_ADDRESS                GatewayIpAddress;
>+} IPv6_DEVICE_PATH;
>+
>+///
>+/// InfiniBand Device Path SubType.
>+///
>+#define MSG_INFINIBAND_DP         0x09
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Flags to help identify/manage InfiniBand device path elements:
>+  /// Bit 0 - IOC/Service (0b = IOC, 1b = Service).
>+  /// Bit 1 - Extend Boot Environment.
>+  /// Bit 2 - Console Protocol.
>+  /// Bit 3 - Storage Protocol.
>+  /// Bit 4 - Network Protocol.
>+  /// All other bits are reserved.
>+  ///
>+  UINT32                          ResourceFlags;
>+  ///
>+  /// 128-bit Global Identifier for remote fabric port.
>+  ///
>+  UINT8                           PortGid[16];
>+  ///
>+  /// 64-bit unique identifier to remote IOC or server process.
>+  /// Interpretation of field specified by Resource Flags (bit 0).
>+  ///
>+  UINT64                          ServiceId;
>+  ///
>+  /// 64-bit persistent ID of remote IOC port.
>+  ///
>+  UINT64                          TargetPortId;
>+  ///
>+  /// 64-bit persistent ID of remote device.
>+  ///
>+  UINT64                          DeviceId;
>+} INFINIBAND_DEVICE_PATH;
>+
>+#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE                0x01
>+#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT
>0x02
>+#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL           0x04
>+#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL           0x08
>+#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL           0x10
>+
>+///
>+/// UART Device Path SubType.
>+///
>+#define MSG_UART_DP               0x0e
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Reserved.
>+  ///
>+  UINT32                          Reserved;
>+  ///
>+  /// The baud rate setting for the UART style device. A value of 0
>+  /// means that the device's default baud rate will be used.
>+  ///
>+  UINT64                          BaudRate;
>+  ///
>+  /// The number of data bits for the UART style device. A value
>+  /// of 0 means that the device's default number of data bits will be used.
>+  ///
>+  UINT8                           DataBits;
>+  ///
>+  /// The parity setting for the UART style device.
>+  /// Parity 0x00 - Default Parity.
>+  /// Parity 0x01 - No Parity.
>+  /// Parity 0x02 - Even Parity.
>+  /// Parity 0x03 - Odd Parity.
>+  /// Parity 0x04 - Mark Parity.
>+  /// Parity 0x05 - Space Parity.
>+  ///
>+  UINT8                           Parity;
>+  ///
>+  /// The number of stop bits for the UART style device.
>+  /// Stop Bits 0x00 - Default Stop Bits.
>+  /// Stop Bits 0x01 - 1 Stop Bit.
>+  /// Stop Bits 0x02 - 1.5 Stop Bits.
>+  /// Stop Bits 0x03 - 2 Stop Bits.
>+  ///
>+  UINT8                           StopBits;
>+} UART_DEVICE_PATH;
>+
>+//
>+// Use VENDOR_DEVICE_PATH struct
>+//
>+#define MSG_VENDOR_DP             0x0a
>+typedef VENDOR_DEVICE_PATH        VENDOR_DEFINED_DEVICE_PATH;
>+
>+#define DEVICE_PATH_MESSAGING_PC_ANSI     EFI_PC_ANSI_GUID
>+#define DEVICE_PATH_MESSAGING_VT_100      EFI_VT_100_GUID
>+#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID
>+#define DEVICE_PATH_MESSAGING_VT_UTF8     EFI_VT_UTF8_GUID
>+
>+///
>+/// A new device path node is defined to declare flow control characteristics.
>+/// UART Flow Control Messaging Device Path
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL GUID.
>+  ///
>+  EFI_GUID                        Guid;
>+  ///
>+  /// Bitmap of supported flow control types.
>+  /// Bit 0 set indicates hardware flow control.
>+  /// Bit 1 set indicates Xon/Xoff flow control.
>+  /// All other bits are reserved and are clear.
>+  ///
>+  UINT32                          FlowControlMap;
>+} UART_FLOW_CONTROL_DEVICE_PATH;
>+
>+#define UART_FLOW_CONTROL_HARDWARE         0x00000001
>+#define UART_FLOW_CONTROL_XON_XOFF         0x00000010
>+
>+#define DEVICE_PATH_MESSAGING_SAS          EFI_SAS_DEVICE_PATH_GUID
>+///
>+/// Serial Attached SCSI (SAS) Device Path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// DEVICE_PATH_MESSAGING_SAS GUID.
>+  ///
>+  EFI_GUID                        Guid;
>+  ///
>+  /// Reserved for future use.
>+  ///
>+  UINT32                          Reserved;
>+  ///
>+  /// SAS Address for Serial Attached SCSI Target.
>+  ///
>+  UINT64                          SasAddress;
>+  ///
>+  /// SAS Logical Unit Number.
>+  ///
>+  UINT64                          Lun;
>+  ///
>+  /// More Information about the device and its interconnect.
>+  ///
>+  UINT16                          DeviceTopology;
>+  ///
>+  /// Relative Target Port (RTP).
>+  ///
>+  UINT16                          RelativeTargetPort;
>+} SAS_DEVICE_PATH;
>+
>+///
>+/// Serial Attached SCSI (SAS) Ex Device Path SubType
>+///
>+#define MSG_SASEX_DP              0x16
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// 8-byte array of the SAS Address for Serial Attached SCSI Target Port.
>+  ///
>+  UINT8                           SasAddress[8];
>+  ///
>+  /// 8-byte array of the SAS Logical Unit Number.
>+  ///
>+  UINT8                           Lun[8];
>+  ///
>+  /// More Information about the device and its interconnect.
>+  ///
>+  UINT16                          DeviceTopology;
>+  ///
>+  /// Relative Target Port (RTP).
>+  ///
>+  UINT16                          RelativeTargetPort;
>+} SASEX_DEVICE_PATH;
>+
>+///
>+/// NvmExpress Namespace Device Path SubType.
>+///
>+#define MSG_NVME_NAMESPACE_DP     0x17
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  UINT32                          NamespaceId;
>+  UINT64                          NamespaceUuid;
>+} NVME_NAMESPACE_DEVICE_PATH;
>+
>+///
>+/// DNS Device Path SubType
>+///
>+#define MSG_DNS_DP                0x1F
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Indicates the DNS server address is IPv4 or IPv6 address.
>+  ///
>+  UINT8                           IsIPv6;
>+  ///
>+  /// Instance of the DNS server address.
>+  ///
>+  EFI_IP_ADDRESS                  DnsServerIp[1024];
>+} DNS_DEVICE_PATH;
>+
>+///
>+/// Uniform Resource Identifiers (URI) Device Path SubType
>+///
>+#define MSG_URI_DP                0x18
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Instance of the URI pursuant to RFC 3986.
>+  ///
>+  CHAR8                           Uri[1024];
>+} URI_DEVICE_PATH;
>+
>+///
>+/// Universal Flash Storage (UFS) Device Path SubType.
>+///
>+#define MSG_UFS_DP                0x19
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Target ID on the UFS bus (PUN).
>+  ///
>+  UINT8                           Pun;
>+  ///
>+  /// Logical Unit Number (LUN).
>+  ///
>+  UINT8                           Lun;
>+} UFS_DEVICE_PATH;
>+
>+///
>+/// SD (Secure Digital) Device Path SubType.
>+///
>+#define MSG_SD_DP                 0x1A
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  UINT8                           SlotNumber;
>+} SD_DEVICE_PATH;
>+
>+///
>+/// EMMC (Embedded MMC) Device Path SubType.
>+///
>+#define MSG_EMMC_DP                 0x1D
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  UINT8                           SlotNumber;
>+} EMMC_DEVICE_PATH;
>+
>+///
>+/// iSCSI Device Path SubType
>+///
>+#define MSG_ISCSI_DP              0x13
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Network Protocol (0 = TCP, 1+ = reserved).
>+  ///
>+  UINT16                          NetworkProtocol;
>+  ///
>+  /// iSCSI Login Options.
>+  ///
>+  UINT16                          LoginOption;
>+  ///
>+  /// iSCSI Logical Unit Number.
>+  ///
>+  UINT64                          Lun;
>+  ///
>+  /// iSCSI Target Portal group tag the initiator intends
>+  /// to establish a session with.
>+  ///
>+  UINT16                          TargetPortalGroupTag;
>+  ///
>+  /// iSCSI NodeTarget Name. The length of the name
>+  /// is determined by subtracting the offset of this field from Length.
>+  ///
>+  /// CHAR8                        iSCSI Target Name.
>+} ISCSI_DEVICE_PATH;
>+
>+#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST             0x0000
>+#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C   0x0002
>+#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST               0x0000
>+#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C     0x0008
>+#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP              0x0000
>+#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON               0x1000
>+#define ISCSI_LOGIN_OPTION_CHAP_BI                      0x0000
>+#define ISCSI_LOGIN_OPTION_CHAP_UNI                     0x2000
>+
>+///
>+/// VLAN Device Path SubType.
>+///
>+#define MSG_VLAN_DP               0x14
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// VLAN identifier (0-4094).
>+  ///
>+  UINT16                          VlanId;
>+} VLAN_DEVICE_PATH;
>+
>+///
>+/// BLUETOOTH_ADDRESS
>+///
>+typedef struct {
>+  ///
>+  /// 48bit Bluetooth device address.
>+  ///
>+  UINT8      Address[6];
>+} BLUETOOTH_ADDRESS;
>+
>+///
>+/// Bluetooth Device Path SubType.
>+///
>+#define MSG_BLUETOOTH_DP     0x1b
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// 48bit Bluetooth device address.
>+  ///
>+  BLUETOOTH_ADDRESS               BD_ADDR;
>+} BLUETOOTH_DEVICE_PATH;
>+
>+///
>+/// Wi-Fi Device Path SubType.
>+///
>+#define MSG_WIFI_DP               0x1C
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Service set identifier. A 32-byte octets string.
>+  ///
>+  UINT8                           SSId[32];
>+} WIFI_DEVICE_PATH;
>+
>+///
>+/// BLUETOOTH_LE_ADDRESS
>+///
>+typedef struct {
>+  ///
>+  /// 48-bit Bluetooth device address
>+  ///
>+  UINT8      Address[6];
>+  ///
>+  /// 0x00 - Public Device Address
>+  /// 0x01 - Random Device Address
>+  ///
>+  UINT8      Type;
>+} BLUETOOTH_LE_ADDRESS;
>+
>+///
>+/// Bluetooth LE Device Path SubType.
>+///
>+#define MSG_BLUETOOTH_LE_DP       0x1E
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  BLUETOOTH_LE_ADDRESS            Address;
>+} BLUETOOTH_LE_DEVICE_PATH;
>+
>+//
>+// Media Device Path
>+//
>+#define MEDIA_DEVICE_PATH         0x04
>+
>+///
>+/// Hard Drive Media Device Path SubType.
>+///
>+#define MEDIA_HARDDRIVE_DP        0x01
>+
>+///
>+/// The Hard Drive Media Device Path is used to represent a partition on a
>hard drive.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Describes the entry in a partition table, starting with entry 1.
>+  /// Partition number zero represents the entire device. Valid
>+  /// partition numbers for a MBR partition are [1, 4]. Valid
>+  /// partition numbers for a GPT partition are [1, NumberOfPartitionEntries].
>+  ///
>+  UINT32                          PartitionNumber;
>+  ///
>+  /// Starting LBA of the partition on the hard drive.
>+  ///
>+  UINT64                          PartitionStart;
>+  ///
>+  /// Size of the partition in units of Logical Blocks.
>+  ///
>+  UINT64                          PartitionSize;
>+  ///
>+  /// Signature unique to this partition:
>+  /// If SignatureType is 0, this field has to be initialized with 16 zeros.
>+  /// If SignatureType is 1, the MBR signature is stored in the first 4 bytes of
>this field.
>+  /// The other 12 bytes are initialized with zeros.
>+  /// If SignatureType is 2, this field contains a 16 byte signature.
>+  ///
>+  UINT8                           Signature[16];
>+  ///
>+  /// Partition Format: (Unused values reserved).
>+  /// 0x01 - PC-AT compatible legacy MBR.
>+  /// 0x02 - GUID Partition Table.
>+  ///
>+  UINT8                           MBRType;
>+  ///
>+  /// Type of Disk Signature: (Unused values reserved).
>+  /// 0x00 - No Disk Signature.
>+  /// 0x01 - 32-bit signature from address 0x1b8 of the type 0x01 MBR.
>+  /// 0x02 - GUID signature.
>+  ///
>+  UINT8                           SignatureType;
>+} HARDDRIVE_DEVICE_PATH;
>+
>+#define MBR_TYPE_PCAT             0x01
>+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
>+
>+#define NO_DISK_SIGNATURE         0x00
>+#define SIGNATURE_TYPE_MBR        0x01
>+#define SIGNATURE_TYPE_GUID       0x02
>+
>+///
>+/// CD-ROM Media Device Path SubType.
>+///
>+#define MEDIA_CDROM_DP            0x02
>+
>+///
>+/// The CD-ROM Media Device Path is used to define a system partition that
>exists on a CD-ROM.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Boot Entry number from the Boot Catalog. The Initial/Default entry is
>defined as zero.
>+  ///
>+  UINT32                          BootEntry;
>+  ///
>+  /// Starting RBA of the partition on the medium. CD-ROMs use Relative
>logical Block Addressing.
>+  ///
>+  UINT64                          PartitionStart;
>+  ///
>+  /// Size of the partition in units of Blocks, also called Sectors.
>+  ///
>+  UINT64                          PartitionSize;
>+} CDROM_DEVICE_PATH;
>+
>+//
>+// Use VENDOR_DEVICE_PATH struct
>+//
>+#define MEDIA_VENDOR_DP           0x03  ///< Media vendor device path
>subtype.
>+
>+///
>+/// File Path Media Device Path SubType
>+///
>+#define MEDIA_FILEPATH_DP         0x04
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// A NULL-terminated Path string including directory and file names.
>+  ///
>+  CHAR16                          PathName[1];
>+} FILEPATH_DEVICE_PATH;
>+
>+#define SIZE_OF_FILEPATH_DEVICE_PATH
>OFFSET_OF(FILEPATH_DEVICE_PATH,PathName)
>+
>+///
>+/// Media Protocol Device Path SubType.
>+///
>+#define MEDIA_PROTOCOL_DP         0x05
>+
>+///
>+/// The Media Protocol Device Path is used to denote the protocol that is
>being
>+/// used in a device path at the location of the path specified.
>+/// Many protocols are inherent to the style of device path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// The ID of the protocol.
>+  ///
>+  EFI_GUID                        Protocol;
>+} MEDIA_PROTOCOL_DEVICE_PATH;
>+
>+///
>+/// PIWG Firmware File SubType.
>+///
>+#define MEDIA_PIWG_FW_FILE_DP     0x06
>+
>+///
>+/// This device path is used by systems implementing the UEFI PI
>Specification 1.0 to describe a firmware file.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Firmware file name
>+  ///
>+  EFI_GUID                        FvFileName;
>+} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH;
>+
>+///
>+/// PIWG Firmware Volume Device Path SubType.
>+///
>+#define MEDIA_PIWG_FW_VOL_DP      0x07
>+
>+///
>+/// This device path is used by systems implementing the UEFI PI
>Specification 1.0 to describe a firmware volume.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Firmware volume name.
>+  ///
>+  EFI_GUID                        FvName;
>+} MEDIA_FW_VOL_DEVICE_PATH;
>+
>+///
>+/// Media relative offset range device path.
>+///
>+#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08
>+
>+///
>+/// Used to describe the offset range of media relative.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL  Header;
>+  UINT32                    Reserved;
>+  UINT64                    StartingOffset;
>+  UINT64                    EndingOffset;
>+} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH;
>+
>+///
>+/// This GUID defines a RAM Disk supporting a raw disk format in volatile
>memory.
>+///
>+#define EFI_VIRTUAL_DISK_GUID
>EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGIO
>N_VOLATILE
>+
>+extern  EFI_GUID                            gEfiVirtualDiskGuid;
>+
>+///
>+/// This GUID defines a RAM Disk supporting an ISO image in volatile memory.
>+///
>+#define EFI_VIRTUAL_CD_GUID
>EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION
>_VOLATILE
>+
>+extern  EFI_GUID                            gEfiVirtualCdGuid;
>+
>+///
>+/// This GUID defines a RAM Disk supporting a raw disk format in persistent
>memory.
>+///
>+#define EFI_PERSISTENT_VIRTUAL_DISK_GUID
>EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGIO
>N_PERSISTENT
>+
>+extern  EFI_GUID                            gEfiPersistentVirtualDiskGuid;
>+
>+///
>+/// This GUID defines a RAM Disk supporting an ISO image in persistent
>memory.
>+///
>+#define EFI_PERSISTENT_VIRTUAL_CD_GUID
>EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION
>_PERSISTENT
>+
>+extern  EFI_GUID                            gEfiPersistentVirtualCdGuid;
>+
>+///
>+/// Media ram disk device path.
>+///
>+#define MEDIA_RAM_DISK_DP         0x09
>+
>+///
>+/// Used to describe the ram disk device path.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Starting Memory Address.
>+  ///
>+  UINT32                          StartingAddr[2];
>+  ///
>+  /// Ending Memory Address.
>+  ///
>+  UINT32                          EndingAddr[2];
>+  ///
>+  /// GUID that defines the type of the RAM Disk.
>+  ///
>+  EFI_GUID                        TypeGuid;
>+  ///
>+  /// RAM Diskinstance number, if supported. The default value is zero.
>+  ///
>+  UINT16                          Instance;
>+} MEDIA_RAM_DISK_DEVICE_PATH;
>+
>+///
>+/// BIOS Boot Specification Device Path.
>+///
>+#define BBS_DEVICE_PATH           0x05
>+
>+///
>+/// BIOS Boot Specification Device Path SubType.
>+///
>+#define BBS_BBS_DP                0x01
>+
>+///
>+/// This Device Path is used to describe the booting of non-EFI-aware
>operating systems.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL        Header;
>+  ///
>+  /// Device Type as defined by the BIOS Boot Specification.
>+  ///
>+  UINT16                          DeviceType;
>+  ///
>+  /// Status Flags as defined by the BIOS Boot Specification.
>+  ///
>+  UINT16                          StatusFlag;
>+  ///
>+  /// Null-terminated ASCII string that describes the boot device to a user.
>+  ///
>+  CHAR8                           String[1];
>+} BBS_BBS_DEVICE_PATH;
>+
>+//
>+// DeviceType definitions - from BBS specification
>+//
>+#define BBS_TYPE_FLOPPY           0x01
>+#define BBS_TYPE_HARDDRIVE        0x02
>+#define BBS_TYPE_CDROM            0x03
>+#define BBS_TYPE_PCMCIA           0x04
>+#define BBS_TYPE_USB              0x05
>+#define BBS_TYPE_EMBEDDED_NETWORK 0x06
>+#define BBS_TYPE_BEV              0x80
>+#define BBS_TYPE_UNKNOWN          0xFF
>+
>+
>+///
>+/// Union of all possible Device Paths and pointers to Device Paths.
>+///
>+typedef union {
>+  EFI_DEVICE_PATH_PROTOCOL                   DevPath;
>+  PCI_DEVICE_PATH                            Pci;
>+  PCCARD_DEVICE_PATH                         PcCard;
>+  MEMMAP_DEVICE_PATH                         MemMap;
>+  VENDOR_DEVICE_PATH                         Vendor;
>+
>+  CONTROLLER_DEVICE_PATH                     Controller;
>+  BMC_DEVICE_PATH                            Bmc;
>+  ACPI_HID_DEVICE_PATH                       Acpi;
>+  ACPI_EXTENDED_HID_DEVICE_PATH              ExtendedAcpi;
>+  ACPI_ADR_DEVICE_PATH                       AcpiAdr;
>+
>+  ATAPI_DEVICE_PATH                          Atapi;
>+  SCSI_DEVICE_PATH                           Scsi;
>+  ISCSI_DEVICE_PATH                          Iscsi;
>+  FIBRECHANNEL_DEVICE_PATH                   FibreChannel;
>+  FIBRECHANNELEX_DEVICE_PATH                 FibreChannelEx;
>+
>+  F1394_DEVICE_PATH                          F1394;
>+  USB_DEVICE_PATH                            Usb;
>+  SATA_DEVICE_PATH                           Sata;
>+  USB_CLASS_DEVICE_PATH                      UsbClass;
>+  USB_WWID_DEVICE_PATH                       UsbWwid;
>+  DEVICE_LOGICAL_UNIT_DEVICE_PATH            LogicUnit;
>+  I2O_DEVICE_PATH                            I2O;
>+  MAC_ADDR_DEVICE_PATH                       MacAddr;
>+  IPv4_DEVICE_PATH                           Ipv4;
>+  IPv6_DEVICE_PATH                           Ipv6;
>+  VLAN_DEVICE_PATH                           Vlan;
>+  INFINIBAND_DEVICE_PATH                     InfiniBand;
>+  UART_DEVICE_PATH                           Uart;
>+  UART_FLOW_CONTROL_DEVICE_PATH              UartFlowControl;
>+  SAS_DEVICE_PATH                            Sas;
>+  SASEX_DEVICE_PATH                          SasEx;
>+  NVME_NAMESPACE_DEVICE_PATH                 NvmeNamespace;
>+  DNS_DEVICE_PATH                            Dns;
>+  URI_DEVICE_PATH                            Uri;
>+  BLUETOOTH_DEVICE_PATH                      Bluetooth;
>+  WIFI_DEVICE_PATH                           WiFi;
>+  UFS_DEVICE_PATH                            Ufs;
>+  SD_DEVICE_PATH                             Sd;
>+  EMMC_DEVICE_PATH                           Emmc;
>+  HARDDRIVE_DEVICE_PATH                      HardDrive;
>+  CDROM_DEVICE_PATH                          CD;
>+
>+  FILEPATH_DEVICE_PATH                       FilePath;
>+  MEDIA_PROTOCOL_DEVICE_PATH                 MediaProtocol;
>+
>+  MEDIA_FW_VOL_DEVICE_PATH                   FirmwareVolume;
>+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH          FirmwareFile;
>+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH    Offset;
>+  MEDIA_RAM_DISK_DEVICE_PATH                 RamDisk;
>+  BBS_BBS_DEVICE_PATH                        Bbs;
>+} EFI_DEV_PATH;
>+
>+
>+
>+typedef union {
>+  EFI_DEVICE_PATH_PROTOCOL                   *DevPath;
>+  PCI_DEVICE_PATH                            *Pci;
>+  PCCARD_DEVICE_PATH                         *PcCard;
>+  MEMMAP_DEVICE_PATH                         *MemMap;
>+  VENDOR_DEVICE_PATH                         *Vendor;
>+
>+  CONTROLLER_DEVICE_PATH                     *Controller;
>+  BMC_DEVICE_PATH                            *Bmc;
>+  ACPI_HID_DEVICE_PATH                       *Acpi;
>+  ACPI_EXTENDED_HID_DEVICE_PATH              *ExtendedAcpi;
>+  ACPI_ADR_DEVICE_PATH                       *AcpiAdr;
>+
>+  ATAPI_DEVICE_PATH                          *Atapi;
>+  SCSI_DEVICE_PATH                           *Scsi;
>+  ISCSI_DEVICE_PATH                          *Iscsi;
>+  FIBRECHANNEL_DEVICE_PATH                   *FibreChannel;
>+  FIBRECHANNELEX_DEVICE_PATH                 *FibreChannelEx;
>+
>+  F1394_DEVICE_PATH                          *F1394;
>+  USB_DEVICE_PATH                            *Usb;
>+  SATA_DEVICE_PATH                           *Sata;
>+  USB_CLASS_DEVICE_PATH                      *UsbClass;
>+  USB_WWID_DEVICE_PATH                       *UsbWwid;
>+  DEVICE_LOGICAL_UNIT_DEVICE_PATH            *LogicUnit;
>+  I2O_DEVICE_PATH                            *I2O;
>+  MAC_ADDR_DEVICE_PATH                       *MacAddr;
>+  IPv4_DEVICE_PATH                           *Ipv4;
>+  IPv6_DEVICE_PATH                           *Ipv6;
>+  VLAN_DEVICE_PATH                           *Vlan;
>+  INFINIBAND_DEVICE_PATH                     *InfiniBand;
>+  UART_DEVICE_PATH                           *Uart;
>+  UART_FLOW_CONTROL_DEVICE_PATH              *UartFlowControl;
>+  SAS_DEVICE_PATH                            *Sas;
>+  SASEX_DEVICE_PATH                          *SasEx;
>+  NVME_NAMESPACE_DEVICE_PATH                 *NvmeNamespace;
>+  DNS_DEVICE_PATH                            *Dns;
>+  URI_DEVICE_PATH                            *Uri;
>+  BLUETOOTH_DEVICE_PATH                      *Bluetooth;
>+  WIFI_DEVICE_PATH                           *WiFi;
>+  UFS_DEVICE_PATH                            *Ufs;
>+  SD_DEVICE_PATH                             *Sd;
>+  EMMC_DEVICE_PATH                           *Emmc;
>+  HARDDRIVE_DEVICE_PATH                      *HardDrive;
>+  CDROM_DEVICE_PATH                          *CD;
>+
>+  FILEPATH_DEVICE_PATH                       *FilePath;
>+  MEDIA_PROTOCOL_DEVICE_PATH                 *MediaProtocol;
>+
>+  MEDIA_FW_VOL_DEVICE_PATH                   *FirmwareVolume;
>+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH          *FirmwareFile;
>+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH    *Offset;
>+  MEDIA_RAM_DISK_DEVICE_PATH                 *RamDisk;
>+  BBS_BBS_DEVICE_PATH                        *Bbs;
>+  UINT8                                      *Raw;
>+} EFI_DEV_PATH_PTR;
>+
>+#define EFI_DEBUGPORT_PROTOCOL_GUID \
>+  { \
>+    0xEBA4E8D2, 0x3858, 0x41EC, {0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60,
>0xD0 } \
>+  }
>+//
>+// DEBUGPORT variable definitions...
>+//
>+#define EFI_DEBUGPORT_VARIABLE_NAME L"DEBUGPORT"
>+#define EFI_DEBUGPORT_VARIABLE_GUID
>EFI_DEBUGPORT_PROTOCOL_GUID
>+extern EFI_GUID  gEfiDebugPortVariableGuid;
>+
>+//
>+// DebugPort device path definitions...
>+//
>+#define DEVICE_PATH_MESSAGING_DEBUGPORT
>EFI_DEBUGPORT_PROTOCOL_GUID
>+extern EFI_GUID  gEfiDebugPortDevicePathGuid;
>+
>+typedef struct {
>+  EFI_DEVICE_PATH_PROTOCOL  Header;
>+  EFI_GUID                  Guid;
>+} DEBUGPORT_DEVICE_PATH;
>+
>+#pragma pack()
>+
>+#define END_DEVICE_PATH_TYPE                 0x7f
>+#define END_ENTIRE_DEVICE_PATH_SUBTYPE       0xFF
>+#define END_INSTANCE_DEVICE_PATH_SUBTYPE     0x01
>+
>+extern EFI_GUID gEfiDevicePathProtocolGuid;
>+
>+#endif
>diff --git a/BaseTools/Source/C/DevicePath/DevicePathFromText.c
>b/BaseTools/Source/C/DevicePath/DevicePathFromText.c
>new file mode 100644
>index 0000000..fb5b09b
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/DevicePathFromText.c
>@@ -0,0 +1,3503 @@
>+/** @file
>+  DevicePathFromText protocol as defined in the UEFI 2.0 specification.
>+
>+Copyright (c) 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.
>+
>+**/
>+CHAR16 *
>+UefiDevicePathLibStrDuplicate (
>+   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.
>+
>+**/
>+CHAR16 *
>+GetParamByNodeName (
>+   CHAR16 *Str,
>+   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] = L'\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
>+
>+**/
>+CHAR16 *
>+SplitStr (
>+    CHAR16 **List,
>+       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 = L'\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
>+
>+**/
>+CHAR16 *
>+GetNextParamStr (
>+    CHAR16 **List
>+  )
>+{
>+  //
>+  // The separator is comma
>+  //
>+  return SplitStr (List, L',');
>+}
>+
>+/**
>+  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
>+
>+**/
>+CHAR16 *
>+GetNextDeviceNodeStr (
>+    CHAR16   **DevicePath,
>+      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 = L'\0';
>+    Str++;
>+  } else {
>+    *IsInstanceEnd = FALSE;
>+    if (!IS_NULL (*Str)) {
>+      *Str = L'\0';
>+      Str++;
>+    }
>+  }
>+
>+  *DevicePath = Str;
>+
>+  return ReturnStr;
>+}
>+
>+
>+/**
>+  Return whether the integer string is a hex string.
>+
>+  @param Str             The integer string
>+
>+  @retval TRUE   Hex string
>+  @retval FALSE  Decimal string
>+
>+**/
>+BOOLEAN
>+IsHexStr (
>+   CHAR16   *Str
>+  )
>+{
>+  //
>+  // skip preceeding white space
>+  //
>+  while ((*Str != 0) && *Str == L' ') {
>+    Str ++;
>+  }
>+  //
>+  // skip preceeding zeros
>+  //
>+  while ((*Str != 0) && *Str == L'0') {
>+    Str ++;
>+  }
>+
>+  return (BOOLEAN) (*Str == L'x' || *Str == L'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
>+
>+**/
>+UINTN
>+Strtoi (
>+   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
>+
>+**/
>+VOID
>+Strtoi64 (
>+    CHAR16  *Str,
>+   UINT64  *Data
>+  )
>+{
>+  if (IsHexStr (Str)) {
>+    *Data = StrHexToUint64 (Str);
>+  } else {
>+    *Data = StrDecimalToUint64 (Str);
>+  }
>+}
>+
>+/**
>+  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
>+
>+**/
>+VOID
>+StrToAscii (
>+       CHAR16 *Str,
>+    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.
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextGenericPath (
>+   UINT8  Type,
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextPath (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextHardwarePath (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextPci (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextPcCard (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextMemoryMapped (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+ConvertFromTextVendor (
>+   CHAR16 *TextDeviceNode,
>+   UINT8  Type,
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVenHw (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextCtrl (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextBmc (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextAcpiPath (
>+   CHAR16 *TextDeviceNode
>+  )
>+{
>+  return DevPathFromTextGenericPath (ACPI_DEVICE_PATH,
>TextDeviceNode);
>+}
>+
>+/**
>+  Converts a string to EisaId.
>+
>+  @param Text   The input string.
>+
>+  @return UINT32 EISA ID.
>+**/
>+UINT32
>+EisaIdFromText (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextAcpi (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+ConvertFromTextAcpi (
>+   CHAR16 *TextDeviceNode,
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextPciRoot (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextPcieRoot (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextFloppy (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextKeyboard (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextSerial (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextParallelPort (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextAcpiEx (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextAcpiExp (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextAcpiAdr (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextMsg (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextAta (
>+ 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, L"Primary") == 0) {
>+    Atapi->PrimarySecondary = 0;
>+  } else if (StrCmp (PrimarySecondaryStr, L"Secondary") == 0) {
>+    Atapi->PrimarySecondary = 1;
>+  } else {
>+    Atapi->PrimarySecondary = (UINT8) Strtoi (PrimarySecondaryStr);
>+  }
>+  if (StrCmp (SlaveMasterStr, L"Master") == 0) {
>+    Atapi->SlaveMaster      = 0;
>+  } else if (StrCmp (SlaveMasterStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextScsi (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextFibre (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextFibreEx (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromText1394 (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsb (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextI2O (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextInfiniband (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVenMsg (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVenPcAnsi (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVenVt100 (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVenVt100Plus (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVenUtf8 (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUartFlowCtrl (
>+   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, L"XonXoff") == 0) {
>+    UartFlowControl->FlowControlMap = 2;
>+  } else if (StrCmp (ValueStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextSAS (
>+   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, L"NoTopology") == 0) {
>+    Info = 0x0;
>+
>+  } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr,
>L"SAS") == 0)) {
>+
>+    Uint16 = (UINT16) Strtoi (DriveBayStr);
>+    if (Uint16 == 0) {
>+      Info = 0x1;
>+    } else {
>+      Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
>+    }
>+
>+    if (StrCmp (SASSATAStr, L"SATA") == 0) {
>+      Info |= BIT4;
>+    }
>+
>+    //
>+    // Location is an integer between 0 and 1 or else
>+    // the keyword Internal (0) or External (1).
>+    //
>+    if (StrCmp (LocationStr, L"External") == 0) {
>+      Uint16 = 1;
>+    } else if (StrCmp (LocationStr, L"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, L"Expanded") == 0) {
>+      Uint16 = 1;
>+    } else if (StrCmp (ConnectStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextSasEx (
>+   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, L"NoTopology") == 0) {
>+    Info = 0x0;
>+
>+  } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr,
>L"SAS") == 0)) {
>+
>+    Uint16 = (UINT16) Strtoi (DriveBayStr);
>+    if (Uint16 == 0) {
>+      Info = 0x1;
>+    } else {
>+      Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
>+    }
>+
>+    if (StrCmp (SASSATAStr, L"SATA") == 0) {
>+      Info |= BIT4;
>+    }
>+
>+    //
>+    // Location is an integer between 0 and 1 or else
>+    // the keyword Internal (0) or External (1).
>+    //
>+    if (StrCmp (LocationStr, L"External") == 0) {
>+      Uint16 = 1;
>+    } else if (StrCmp (LocationStr, L"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, L"Expanded") == 0) {
>+      Uint16 = 1;
>+    } else if (StrCmp (ConnectStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextNVMe (
>+   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, L'-'));
>+  }
>+
>+  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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUfs (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextSd (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextEmmc (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextDebugPort (
>+   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, &gEfiDebugPortDevicePathGuid);
>+
>+  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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextMAC (
>+   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);
>+  if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) {
>+    Length = 6;
>+  }
>+
>+  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 .
>+
>+**/
>+UINTN
>+NetworkProtocolFromText (
>+   CHAR16 *Text
>+  )
>+{
>+  if (StrCmp (Text, L"UDP") == 0) {
>+    return RFC_1700_UDP_PROTOCOL;
>+  }
>+
>+  if (StrCmp (Text, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextIPv4 (
>+   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, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextIPv6 (
>+   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, L"Static") == 0) {
>+    IPv6->IpAddressOrigin = 0;
>+  } else if (StrCmp (TypeStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUart (
>+   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, L"DEFAULT") == 0) {
>+    Uart->BaudRate = 115200;
>+  } else {
>+    Strtoi64 (BaudStr, &Uart->BaudRate);
>+  }
>+  Uart->DataBits  = (UINT8) ((StrCmp (DataBitsStr, L"DEFAULT") == 0) ? 8 :
>Strtoi (DataBitsStr));
>+  switch (*ParityStr) {
>+  case L'D':
>+    Uart->Parity = 0;
>+    break;
>+
>+  case L'N':
>+    Uart->Parity = 1;
>+    break;
>+
>+  case L'E':
>+    Uart->Parity = 2;
>+    break;
>+
>+  case L'O':
>+    Uart->Parity = 3;
>+    break;
>+
>+  case L'M':
>+    Uart->Parity = 4;
>+    break;
>+
>+  case L'S':
>+    Uart->Parity = 5;
>+    break;
>+
>+  default:
>+    Uart->Parity = (UINT8) Strtoi (ParityStr);
>+    break;
>+  }
>+
>+  if (StrCmp (StopBitsStr, L"D") == 0) {
>+    Uart->StopBits = (UINT8) 0;
>+  } else if (StrCmp (StopBitsStr, L"1") == 0) {
>+    Uart->StopBits = (UINT8) 1;
>+  } else if (StrCmp (StopBitsStr, L"1.5") == 0) {
>+    Uart->StopBits = (UINT8) 2;
>+  } else if (StrCmp (StopBitsStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+ConvertFromTextUsbClass (
>+   CHAR16         *TextDeviceNode,
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbClass (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbAudio (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbCDCControl (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbHID (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbImage (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbPrinter (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbMassStorage (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbHub (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbCDCData (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbSmartCard (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbVideo (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbDiagnostic (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbWireless (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbDeviceFirmwareUpdate (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbIrdaBridge (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbTestAndMeasurement (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUsbWwid (
>+   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] == L'\"' &&
>+      SerialNumberStr[SerialNumberStrLen - 1] == L'\"'
>+    ) {
>+    SerialNumberStr[SerialNumberStrLen - 1] = L'\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.
>+  //
>+  memcpy (
>+    (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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUnit (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextiSCSI (
>+   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, L"CRC32C") == 0) {
>+    Options |= 0x0002;
>+  }
>+
>+  if (StrCmp (DataDigestStr, L"CRC32C") == 0) {
>+    Options |= 0x0008;
>+  }
>+
>+  if (StrCmp (AuthenticationStr, L"None") == 0) {
>+    Options |= 0x0800;
>+  }
>+
>+  if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) {
>+    Options |= 0x1000;
>+  }
>+
>+  ISCSIDevPath->LoginOption      = (UINT16) Options;
>+
>+  if (StrCmp (ProtocolStr, L"TCP") == 0) {
>+    ISCSIDevPath->NetworkProtocol = 0;
>+  } else {
>+    //
>+    // Undefined and reserved.
>+    //
>+    ISCSIDevPath->NetworkProtocol = 1;
>+  }
>+
>+  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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVlan (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextBluetooth (
>+   CHAR16 *TextDeviceNode
>+  )
>+{
>+  CHAR16                  *BluetoothStr;
>+  BLUETOOTH_DEVICE_PATH   *BluetoothDp;
>+
>+  BluetoothStr = GetNextParamStr (&TextDeviceNode);
>+  BluetoothDp  = (BLUETOOTH_DEVICE_PATH *) CreateDeviceNode (
>+                                             MESSAGING_DEVICE_PATH,
>+                                             MSG_BLUETOOTH_DP,
>+                                             (UINT16) sizeof (BLUETOOTH_DEVICE_PATH)
>+                                             );
>+  StrHexToBytes (
>+    BluetoothStr,
>+    sizeof (BLUETOOTH_ADDRESS) * 2,
>+    BluetoothDp->BD_ADDR.Address,
>+    sizeof (BLUETOOTH_ADDRESS)
>+    );
>+  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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextWiFi (
>+   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] = L'\0';
>+      DataLen     = 32;
>+    }
>+
>+    UnicodeStrToAsciiStrS (SSIdStr, AsciiStr, sizeof (AsciiStr));
>+    memcpy (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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextUri (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextMediaPath (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextHD (
>+   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, L"MBR") == 0) {
>+    Hd->SignatureType = SIGNATURE_TYPE_MBR;
>+    Hd->MBRType       = 0x01;
>+
>+    Signature32       = (UINT32) Strtoi (SignatureStr);
>+    memcpy (Hd->Signature, &Signature32, sizeof (UINT32));
>+  } else if (StrCmp (TypeStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextCDROM (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVenMedia (
>+   CHAR16 *TextDeviceNode
>+  )
>+{
>+  return ConvertFromTextVendor (
>+           TextDeviceNode,
>+           MEDIA_DEVICE_PATH,
>+           MEDIA_VENDOR_DP
>+           );
>+}
>+
>+/**
>+  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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextFilePath (
>+   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;
>+}
>+
>+/**
>+  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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextMedia (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextFv (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextFvFile (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextRelativeOffsetRange (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextRamDisk (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVirtualDisk (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextVirtualCd (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextPersistentVirtualDisk (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextPersistentVirtualCd (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextBbsPath (
>+   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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextBBS (
>+   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, L"Floppy") == 0) {
>+    Bbs->DeviceType = BBS_TYPE_FLOPPY;
>+  } else if (StrCmp (TypeStr, L"HD") == 0) {
>+    Bbs->DeviceType = BBS_TYPE_HARDDRIVE;
>+  } else if (StrCmp (TypeStr, L"CDROM") == 0) {
>+    Bbs->DeviceType = BBS_TYPE_CDROM;
>+  } else if (StrCmp (TypeStr, L"PCMCIA") == 0) {
>+    Bbs->DeviceType = BBS_TYPE_PCMCIA;
>+  } else if (StrCmp (TypeStr, L"USB") == 0) {
>+    Bbs->DeviceType = BBS_TYPE_USB;
>+  } else if (StrCmp (TypeStr, L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevPathFromTextSata (
>+   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;
>+}
>+
>+DEVICE_PATH_FROM_TEXT_TABLE
>mUefiDevicePathLibDevPathFromTextTable[] = {
>+  {L"Path",                    DevPathFromTextPath                    },
>+
>+  {L"HardwarePath",            DevPathFromTextHardwarePath            },
>+  {L"Pci",                     DevPathFromTextPci                     },
>+  {L"PcCard",                  DevPathFromTextPcCard                  },
>+  {L"MemoryMapped",            DevPathFromTextMemoryMapped            },
>+  {L"VenHw",                   DevPathFromTextVenHw                   },
>+  {L"Ctrl",                    DevPathFromTextCtrl                    },
>+  {L"BMC",                     DevPathFromTextBmc                     },
>+
>+  {L"AcpiPath",                DevPathFromTextAcpiPath                },
>+  {L"Acpi",                    DevPathFromTextAcpi                    },
>+  {L"PciRoot",                 DevPathFromTextPciRoot                 },
>+  {L"PcieRoot",                DevPathFromTextPcieRoot                },
>+  {L"Floppy",                  DevPathFromTextFloppy                  },
>+  {L"Keyboard",                DevPathFromTextKeyboard                },
>+  {L"Serial",                  DevPathFromTextSerial                  },
>+  {L"ParallelPort",            DevPathFromTextParallelPort            },
>+  {L"AcpiEx",                  DevPathFromTextAcpiEx                  },
>+  {L"AcpiExp",                 DevPathFromTextAcpiExp                 },
>+  {L"AcpiAdr",                 DevPathFromTextAcpiAdr                 },
>+
>+  {L"Msg",                     DevPathFromTextMsg                     },
>+  {L"Ata",                     DevPathFromTextAta                     },
>+  {L"Scsi",                    DevPathFromTextScsi                    },
>+  {L"Fibre",                   DevPathFromTextFibre                   },
>+  {L"FibreEx",                 DevPathFromTextFibreEx                 },
>+  {L"I1394",                   DevPathFromText1394                    },
>+  {L"USB",                     DevPathFromTextUsb                     },
>+  {L"I2O",                     DevPathFromTextI2O                     },
>+  {L"Infiniband",              DevPathFromTextInfiniband              },
>+  {L"VenMsg",                  DevPathFromTextVenMsg                  },
>+  {L"VenPcAnsi",               DevPathFromTextVenPcAnsi               },
>+  {L"VenVt100",                DevPathFromTextVenVt100                },
>+  {L"VenVt100Plus",            DevPathFromTextVenVt100Plus            },
>+  {L"VenUtf8",                 DevPathFromTextVenUtf8                 },
>+  {L"UartFlowCtrl",            DevPathFromTextUartFlowCtrl            },
>+  {L"SAS",                     DevPathFromTextSAS                     },
>+  {L"SasEx",                   DevPathFromTextSasEx                   },
>+  {L"NVMe",                    DevPathFromTextNVMe                    },
>+  {L"UFS",                     DevPathFromTextUfs                     },
>+  {L"SD",                      DevPathFromTextSd                      },
>+  {L"eMMC",                    DevPathFromTextEmmc                    },
>+  {L"DebugPort",               DevPathFromTextDebugPort               },
>+  {L"MAC",                     DevPathFromTextMAC                     },
>+  {L"IPv4",                    DevPathFromTextIPv4                    },
>+  {L"IPv6",                    DevPathFromTextIPv6                    },
>+  {L"Uart",                    DevPathFromTextUart                    },
>+  {L"UsbClass",                DevPathFromTextUsbClass                },
>+  {L"UsbAudio",                DevPathFromTextUsbAudio                },
>+  {L"UsbCDCControl",           DevPathFromTextUsbCDCControl           },
>+  {L"UsbHID",                  DevPathFromTextUsbHID                  },
>+  {L"UsbImage",                DevPathFromTextUsbImage                },
>+  {L"UsbPrinter",              DevPathFromTextUsbPrinter              },
>+  {L"UsbMassStorage",          DevPathFromTextUsbMassStorage          },
>+  {L"UsbHub",                  DevPathFromTextUsbHub                  },
>+  {L"UsbCDCData",              DevPathFromTextUsbCDCData              },
>+  {L"UsbSmartCard",            DevPathFromTextUsbSmartCard            },
>+  {L"UsbVideo",                DevPathFromTextUsbVideo                },
>+  {L"UsbDiagnostic",           DevPathFromTextUsbDiagnostic           },
>+  {L"UsbWireless",             DevPathFromTextUsbWireless             },
>+  {L"UsbDeviceFirmwareUpdate",
>DevPathFromTextUsbDeviceFirmwareUpdate },
>+  {L"UsbIrdaBridge",           DevPathFromTextUsbIrdaBridge           },
>+  {L"UsbTestAndMeasurement",
>DevPathFromTextUsbTestAndMeasurement   },
>+  {L"UsbWwid",                 DevPathFromTextUsbWwid                 },
>+  {L"Unit",                    DevPathFromTextUnit                    },
>+  {L"iSCSI",                   DevPathFromTextiSCSI                   },
>+  {L"Vlan",                    DevPathFromTextVlan                    },
>+  {L"Uri",                     DevPathFromTextUri                     },
>+  {L"Bluetooth",               DevPathFromTextBluetooth               },
>+  {L"Wi-Fi",                   DevPathFromTextWiFi                    },
>+  {L"MediaPath",               DevPathFromTextMediaPath               },
>+  {L"HD",                      DevPathFromTextHD                      },
>+  {L"CDROM",                   DevPathFromTextCDROM                   },
>+  {L"VenMedia",                DevPathFromTextVenMedia                },
>+  {L"Media",                   DevPathFromTextMedia                   },
>+  {L"Fv",                      DevPathFromTextFv                      },
>+  {L"FvFile",                  DevPathFromTextFvFile                  },
>+  {L"Offset",                  DevPathFromTextRelativeOffsetRange     },
>+  {L"RamDisk",                 DevPathFromTextRamDisk                 },
>+  {L"VirtualDisk",             DevPathFromTextVirtualDisk             },
>+  {L"VirtualCD",               DevPathFromTextVirtualCd               },
>+  {L"PersistentVirtualDisk",   DevPathFromTextPersistentVirtualDisk   },
>+  {L"PersistentVirtualCD",     DevPathFromTextPersistentVirtualCd     },
>+
>+  {L"BbsPath",                 DevPathFromTextBbsPath                 },
>+  {L"BBS",                     DevPathFromTextBBS                     },
>+  {L"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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibConvertTextToDeviceNode (
>+   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;
>+    }
>+  }
>+
>+  if (FromText == NULL) {
>+    //
>+    // A file path
>+    //
>+    FromText = DevPathFromTextFilePath;
>+    DeviceNode = FromText (DeviceNodeStr);
>+  } else {
>+    DeviceNode = FromText (ParamStr);
>+    free (ParamStr);
>+  }
>+
>+  free (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.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibConvertTextToDevicePath (
>+   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);
>+    free (DevicePath);
>+    free (DeviceNode);
>+    DevicePath = NewDevicePath;
>+
>+    if (IsInstanceEnd) {
>+      DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool
>(END_DEVICE_PATH_LENGTH);
>+      ASSERT (DeviceNode != NULL);
>+      SetDevicePathEndNode (DeviceNode);
>+      DeviceNode->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
>+
>+      NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode);
>+      free (DevicePath);
>+      free (DeviceNode);
>+      DevicePath = NewDevicePath;
>+    }
>+  }
>+
>+  free (DevicePathStr);
>+  return DevicePath;
>+}
>diff --git a/BaseTools/Source/C/DevicePath/DevicePathFromText.h
>b/BaseTools/Source/C/DevicePath/DevicePathFromText.h
>new file mode 100644
>index 0000000..4c46921
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/DevicePathFromText.h
>@@ -0,0 +1,72 @@
>+/** @file
>+  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL as defined in UEFI 2.0.
>+  This protocol provides service to convert text to device paths and device
>nodes.
>+
>+  Copyright (c) 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.
>+
>+**/
>+
>+#ifndef __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__
>+#define __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__
>+
>+///
>+/// Device Path From Text protocol
>+///
>+#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \
>+  { \
>+    0x5c99a21, 0xc70f, 0x4ad2, {0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e  }
>\
>+  }
>+
>+/**
>+  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.
>+
>+  @retval a_pointer      Pointer to the EFI device node.
>+  @retval NULL           if TextDeviceNode is NULL or there was insufficient
>memory.
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_FROM_TEXT_NODE)(
>+   CONST CHAR16                 *TextDeviceNode
>+  );
>+
>+
>+/**
>+  Convert text to the binary representation of a device node.
>+
>+  @param  TextDeviceNode TextDevicePath points to the text
>representation of a device
>+                         path. Conversion starts with the first character and continues
>+                         until the first non-device path character.
>+
>+  @retval a_pointer      Pointer to the allocated device path.
>+  @retval NULL           if TextDeviceNode is NULL or there was insufficient
>memory.
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_FROM_TEXT_PATH)(
>+   CONST CHAR16                 *TextDevicePath
>+  );
>+
>+///
>+/// This protocol converts text to device paths and device nodes.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_FROM_TEXT_NODE  ConvertTextToDeviceNode;
>+  EFI_DEVICE_PATH_FROM_TEXT_PATH  ConvertTextToDevicePath;
>+} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL;
>+
>+extern EFI_GUID gEfiDevicePathFromTextProtocolGuid;
>+
>+#endif
>diff --git a/BaseTools/Source/C/DevicePath/DevicePathUtilities.c
>b/BaseTools/Source/C/DevicePath/DevicePathUtilities.c
>new file mode 100644
>index 0000000..07a58ee
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/DevicePathUtilities.c
>@@ -0,0 +1,2352 @@
>+/** @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) 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"
>+#include "DevicePathUtilities.h"
>+
>+#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status)  \
>+  do { \
>+    ASSERT (Expression); \
>+    if (!(Expression)) { \
>+      return Status; \
>+    } \
>+  } while (FALSE)
>+
>+
>+//
>+// Template for an end-of-device path node.
>+//
>+CONST EFI_DEVICE_PATH_PROTOCOL  mUefiDevicePathLibEndDevicePath =
>{
>+  END_DEVICE_PATH_TYPE,
>+  END_ENTIRE_DEVICE_PATH_SUBTYPE,
>+  {
>+    END_DEVICE_PATH_LENGTH,
>+    0
>+  }
>+};
>+
>+/**
>+  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
>+IsDevicePathValid (
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
>+   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;
>+    }
>+
>+    Count++;
>+    if (Count >= MAX_DEVICE_PATH_NODE_COUNT) {
>+      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
>+DevicePathType (
>+   CONST VOID  *Node
>+  )
>+{
>+  ASSERT (Node != NULL);
>+  return ((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
>+DevicePathSubType (
>+   CONST VOID  *Node
>+  )
>+{
>+  ASSERT (Node != NULL);
>+  return ((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
>+DevicePathNodeLength (
>+   CONST VOID  *Node
>+  )
>+{
>+  ASSERT (Node != NULL);
>+  return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL
>*)(Node))->Length[0]);
>+}
>+
>+/**
>+  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 *
>+NextDevicePathNode (
>+   CONST VOID  *Node
>+  )
>+{
>+  ASSERT (Node != NULL);
>+  return (EFI_DEVICE_PATH_PROTOCOL *)((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
>+IsDevicePathEndType (
>+   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
>+IsDevicePathEnd (
>+   CONST VOID  *Node
>+  )
>+{
>+  ASSERT (Node != NULL);
>+  return (BOOLEAN) (IsDevicePathEndType (Node) &&
>DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
>+}
>+
>+/**
>+  Determines if a device path node is an end node of a device path instance.
>+
>+  Determines if a device path node specified by Node is an end node of a
>device
>+  path instance. If Node represents the end of a device path instance, 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 a
>device
>+                    path instance.
>+  @retval FALSE     The device path node specified by Node is not the end of a
>+                    device path instance.
>+
>+**/
>+BOOLEAN
>+IsDevicePathEndInstance (
>+   CONST VOID  *Node
>+  )
>+{
>+  ASSERT (Node != NULL);
>+  return (BOOLEAN) (IsDevicePathEndType (Node) &&
>DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
>+}
>+
>+/**
>+  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
>+SetDevicePathNodeLength (
>+    VOID  *Node,
>+   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));
>+}
>+
>+/**
>+  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
>+SetDevicePathEndNode (
>+   VOID  *Node
>+  )
>+{
>+  ASSERT (Node != NULL);
>+  memcpy (Node, &mUefiDevicePathLibEndDevicePath, sizeof
>(mUefiDevicePathLibEndDevicePath));
>+}
>+
>+/**
>+  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
>+UefiDevicePathLibGetDevicePathSize (
>+   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);
>+}
>+
>+/**
>+  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 *
>+UefiDevicePathLibDuplicateDevicePath (
>+   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 *
>+UefiDevicePathLibAppendDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath
>+  )
>+{
>+  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 = memcpy (NewDevicePath, FirstDevicePath, Size1);
>+    //
>+    // Over write FirstDevicePath EndNode and do the copy
>+    //
>+    DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *)
>NewDevicePath +
>+                  (Size1 - END_DEVICE_PATH_LENGTH));
>+    memcpy (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 *
>+UefiDevicePathLibAppendDevicePathNode (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode
>+  )
>+{
>+  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 = memcpy (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);
>+
>+  free (TempDevicePath);
>+
>+  return NewDevicePath;
>+}
>+
>+/**
>+  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 *
>+UefiDevicePathLibAppendDevicePathInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance
>+  )
>+{
>+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
>+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
>+  UINTN                     SrcSize;
>+  UINTN                     InstanceSize;
>+
>+  if (DevicePath == NULL) {
>+    return DuplicateDevicePath (DevicePathInstance);
>+  }
>+
>+  if (DevicePathInstance == NULL) {
>+    return NULL;
>+  }
>+
>+  if (!IsDevicePathValid (DevicePath, 0) || !IsDevicePathValid
>(DevicePathInstance, 0)) {
>+    return NULL;
>+  }
>+
>+  SrcSize       = GetDevicePathSize (DevicePath);
>+  InstanceSize  = GetDevicePathSize (DevicePathInstance);
>+
>+  NewDevicePath = AllocatePool (SrcSize + InstanceSize);
>+  if (NewDevicePath != NULL) {
>+
>+    TempDevicePath = memcpy (NewDevicePath, DevicePath, SrcSize);;
>+
>+    while (!IsDevicePathEnd (TempDevicePath)) {
>+      TempDevicePath = NextDevicePathNode (TempDevicePath);
>+    }
>+
>+    TempDevicePath->SubType  = END_INSTANCE_DEVICE_PATH_SUBTYPE;
>+    TempDevicePath           = NextDevicePathNode (TempDevicePath);
>+    memcpy (TempDevicePath, DevicePathInstance, InstanceSize);
>+  }
>+
>+  return NewDevicePath;
>+}
>+
>+/**
>+  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 *
>+UefiDevicePathLibGetNextDevicePathInstance (
>+   EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
>+   UINTN                          *Size
>+  )
>+{
>+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
>+  EFI_DEVICE_PATH_PROTOCOL  *ReturnValue;
>+  UINT8                     Temp;
>+
>+  ASSERT (Size != NULL);
>+
>+  if (DevicePath == NULL || *DevicePath == NULL) {
>+    *Size = 0;
>+    return NULL;
>+  }
>+
>+  if (!IsDevicePathValid (*DevicePath, 0)) {
>+    return NULL;
>+  }
>+
>+  //
>+  // Find the end of the device path instance
>+  //
>+  DevPath = *DevicePath;
>+  while (!IsDevicePathEndType (DevPath)) {
>+    DevPath = NextDevicePathNode (DevPath);
>+  }
>+
>+  //
>+  // Compute the size of the device path instance
>+  //
>+  *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof
>(EFI_DEVICE_PATH_PROTOCOL);
>+
>+  //
>+  // Make a copy and return the device path instance
>+  //
>+  Temp              = DevPath->SubType;
>+  DevPath->SubType  = END_ENTIRE_DEVICE_PATH_SUBTYPE;
>+  ReturnValue       = DuplicateDevicePath (*DevicePath);
>+  DevPath->SubType  = Temp;
>+
>+  //
>+  // If DevPath is the end of an entire device path, then another instance
>+  // does not follow, so *DevicePath is set to NULL.
>+  //
>+  if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE)
>{
>+    *DevicePath = NULL;
>+  } else {
>+    *DevicePath = NextDevicePathNode (DevPath);
>+  }
>+
>+  return ReturnValue;
>+}
>+
>+/**
>+  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 *
>+UefiDevicePathLibCreateDeviceNode (
>+   UINT8                           NodeType,
>+   UINT8                           NodeSubType,
>+   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;
>+}
>+
>+/**
>+  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
>+UefiDevicePathLibIsDevicePathMultiInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  )
>+{
>+  CONST EFI_DEVICE_PATH_PROTOCOL     *Node;
>+
>+  if (DevicePath == NULL) {
>+    return FALSE;
>+  }
>+
>+  if (!IsDevicePathValid (DevicePath, 0)) {
>+    return FALSE;
>+  }
>+
>+  Node = DevicePath;
>+  while (!IsDevicePathEnd (Node)) {
>+    if (IsDevicePathEndInstance (Node)) {
>+      return TRUE;
>+    }
>+
>+    Node = NextDevicePathNode (Node);
>+  }
>+
>+  return FALSE;
>+}
>+
>+
>+/**
>+  Retrieves the device path protocol from a handle.
>+
>+  This function returns the device path protocol from the handle specified by
>Handle.
>+  If Handle is NULL or Handle does not contain a device path protocol, then
>NULL
>+  is returned.
>+
>+  @param  Handle                     The handle from which to retrieve the device
>+                                     path protocol.
>+
>+  @return The device path protocol from the handle specified by Handle.
>+
>+**/
>+/*
>+EFI_DEVICE_PATH_PROTOCOL *
>+DevicePathFromHandle (
>+   EFI_HANDLE                      Handle
>+  )
>+{
>+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>+  EFI_STATUS                Status;
>+
>+  Status = gBS->HandleProtocol (
>+                  Handle,
>+                  &gEfiDevicePathProtocolGuid,
>+                  (VOID *) &DevicePath
>+                  );
>+  if (EFI_ERROR (Status)) {
>+    DevicePath = NULL;
>+  }
>+  return DevicePath;
>+}
>+*/
>+/**
>+  Allocates a device path for a file and appends it to an existing device path.
>+
>+  If Device is a valid device handle that contains a device path protocol, then a
>device path for
>+  the file specified by FileName  is allocated and appended to the device path
>associated with the
>+  handle Device.  The allocated device path is returned.  If Device is NULL or
>Device is a handle
>+  that does not support the device path protocol, then a device path
>containing a single device
>+  path node for the file specified by FileName is allocated and 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.
>+
>+  If FileName is NULL, then ASSERT().
>+  If FileName is not aligned on a 16-bit boundary, then ASSERT().
>+
>+  @param  Device                     A pointer to a device handle.  This parameter
>+                                     is optional and may be NULL.
>+  @param  FileName                   A pointer to a Null-terminated Unicode string.
>+
>+  @return The allocated device path.
>+
>+**/
>+EFI_DEVICE_PATH_PROTOCOL *
>+FileDevicePath (
>+   EFI_HANDLE                      Device,     OPTIONAL
>+   CONST CHAR16                    *FileName
>+  )
>+{
>+  UINTN                     Size;
>+  FILEPATH_DEVICE_PATH      *FilePath;
>+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
>+  EFI_DEVICE_PATH_PROTOCOL  *FileDevicePath;
>+
>+  DevicePath = NULL;
>+
>+  Size = StrSize (FileName);
>+  FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH +
>END_DEVICE_PATH_LENGTH);
>+  if (FileDevicePath != NULL) {
>+    FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;
>+    FilePath->Header.Type    = MEDIA_DEVICE_PATH;
>+    FilePath->Header.SubType = MEDIA_FILEPATH_DP;
>+    memcpy (&FilePath->PathName, FileName, Size);
>+    SetDevicePathNodeLength (&FilePath->Header, Size +
>SIZE_OF_FILEPATH_DEVICE_PATH);
>+    SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));
>+
>+    //if (Device != NULL) {
>+    //  DevicePath = DevicePathFromHandle (Device);
>+    //}
>+
>+    DevicePath = AppendDevicePath (DevicePath, FileDevicePath);
>+    free (FileDevicePath);
>+  }
>+
>+  return DevicePath;
>+}
>+
>+CHAR16
>+InternalCharToUpper (
>+        CHAR16                    Char
>+  )
>+{
>+  if (Char >= L'a' && Char <= L'z') {
>+    return (CHAR16) (Char - (L'a' - L'A'));
>+  }
>+
>+  return Char;
>+}
>+
>+UINTN
>+StrnLenS (
>+   CONST CHAR16              *String,
>+   UINTN                     MaxSize
>+  )
>+{
>+  UINTN     Length;
>+
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // If String is a null pointer or MaxSize is 0, then the StrnLenS function
>returns zero.
>+  //
>+  if ((String == NULL) || (MaxSize == 0)) {
>+    return 0;
>+  }
>+
>+  Length = 0;
>+  while (String[Length] != 0) {
>+    if (Length >= MaxSize - 1) {
>+      return MaxSize;
>+    }
>+    Length++;
>+  }
>+  return Length;
>+}
>+
>+
>+VOID *
>+InternalAllocatePool (
>+   UINTN   AllocationSize
>+  )
>+{
>+  VOID * Memory;
>+
>+  Memory = malloc(AllocationSize);
>+  ASSERT(Memory != NULL);
>+  return Memory;
>+}
>+
>+
>+VOID *
>+InternalReallocatePool (
>+   UINTN            OldSize,
>+   UINTN            NewSize,
>+   VOID             *OldBuffer  OPTIONAL
>+  )
>+{
>+  VOID  *NewBuffer;
>+
>+  NewBuffer = AllocateZeroPool (NewSize);
>+  if (NewBuffer != NULL && OldBuffer != NULL) {
>+    memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
>+    free(OldBuffer);
>+  }
>+  return NewBuffer;
>+}
>+
>+VOID *
>+ReallocatePool (
>+   UINTN  OldSize,
>+   UINTN  NewSize,
>+   VOID   *OldBuffer  OPTIONAL
>+  )
>+{
>+  return InternalReallocatePool (OldSize, NewSize, OldBuffer);
>+}
>+
>+/**
>+  Returns the length of a Null-terminated Unicode string.
>+
>+  This function returns the number of Unicode characters in the Null-
>terminated
>+  Unicode string specified by String.
>+
>+  If String is NULL, then ASSERT().
>+  If String is not aligned on a 16-bit boundary, then ASSERT().
>+  If PcdMaximumUnicodeStringLength is not zero, and String contains more
>than
>+  PcdMaximumUnicodeStringLength Unicode characters, not including the
>+  Null-terminator, then ASSERT().
>+
>+  @param  String  A pointer to a Null-terminated Unicode string.
>+
>+  @return The length of String.
>+
>+**/
>+UINTN
>+StrLen (
>+  CONST CHAR16              *String
>+  )
>+{
>+  UINTN   Length;
>+
>+  ASSERT (String != NULL);
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  for (Length = 0; *String != L'\0'; String++, Length++) {
>+    //
>+    // If PcdMaximumUnicodeStringLength is not zero,
>+    // length should not more than PcdMaximumUnicodeStringLength
>+    //
>+  }
>+  return Length;
>+}
>+
>+BOOLEAN
>+InternalSafeStringIsOverlap (
>+  IN VOID    *Base1,
>+  IN UINTN   Size1,
>+  IN VOID    *Base2,
>+  IN UINTN   Size2
>+  )
>+{
>+  if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 +
>Size2)) ||
>+      (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 +
>Size1))) {
>+    return TRUE;
>+  }
>+  return FALSE;
>+}
>+
>+BOOLEAN
>+InternalSafeStringNoStrOverlap (
>+  IN CHAR16  *Str1,
>+  IN UINTN   Size1,
>+  IN CHAR16  *Str2,
>+  IN UINTN   Size2
>+  )
>+{
>+  return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2
>* sizeof(CHAR16));
>+}
>+
>+RETURN_STATUS
>+StrDecimalToUintnS (
>+    CONST CHAR16             *String,
>+         CHAR16             **EndPointer,  OPTIONAL
>+         UINTN              *Data
>+  )
>+{
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. Neither String nor Data shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 2. The length of String shall not be greater than RSIZE_MAX.
>+  //
>+  if (RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <=
>RSIZE_MAX), RETURN_INVALID_PARAMETER);
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+
>+  //
>+  // Ignore the pad spaces (space or tab)
>+  //
>+  while ((*String == L' ') || (*String == L'\t')) {
>+    String++;
>+  }
>+
>+  //
>+  // Ignore leading Zeros after the spaces
>+  //
>+  while (*String == L'0') {
>+    String++;
>+  }
>+
>+  *Data = 0;
>+
>+  while (InternalIsDecimalDigitCharacter (*String)) {
>+    //
>+    // If the number represented by String overflows according to the range
>+    // defined by UINTN, then MAX_UINTN is stored in *Data and
>+    // RETURN_UNSUPPORTED is returned.
>+    //
>+    if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) {
>+      *Data = MAX_UINTN;
>+      if (EndPointer != NULL) {
>+        *EndPointer = (CHAR16 *) String;
>+      }
>+      return RETURN_UNSUPPORTED;
>+    }
>+
>+    *Data = *Data * 10 + (*String - L'0');
>+    String++;
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+  return RETURN_SUCCESS;
>+}
>+
>+/**
>+  Convert a Null-terminated Unicode decimal string to a value of type UINT64.
>+
>+  This function outputs a value of type UINT64 by interpreting the contents of
>+  the Unicode string specified by String as a decimal number. The format of
>the
>+  input Unicode string String is:
>+
>+                  [spaces] [decimal digits].
>+
>+  The valid decimal digit character is in the range [0-9]. The function will
>+  ignore the pad space, which includes spaces or tab characters, before
>+  [decimal digits]. The running zero in the beginning of [decimal digits] will
>+  be ignored. Then, the function stops at the first character that is a not a
>+  valid decimal character or a Null-terminator, whichever one comes first.
>+
>+  If String is NULL, then ASSERT().
>+  If Data is NULL, then ASSERT().
>+  If String is not aligned in a 16-bit boundary, then ASSERT().
>+  If PcdMaximumUnicodeStringLength is not zero, and String contains more
>than
>+  PcdMaximumUnicodeStringLength Unicode characters, not including the
>+  Null-terminator, then ASSERT().
>+
>+  If String has no valid decimal digits in the above format, then 0 is stored
>+  at the location pointed to by Data.
>+  If the number represented by String exceeds the range defined by UINT64,
>then
>+  MAX_UINT64 is stored at the location pointed to by Data.
>+
>+  If EndPointer is not NULL, a pointer to the character that stopped the scan
>+  is stored at the location pointed to by EndPointer. If String has no valid
>+  decimal digits right after the optional pad spaces, the value of String is
>+  stored at the location pointed to by EndPointer.
>+
>+  @param  String                   Pointer to a Null-terminated Unicode string.
>+  @param  EndPointer               Pointer to character that stops scan.
>+  @param  Data                     Pointer to the converted value.
>+
>+  @retval RETURN_SUCCESS           Value is translated from String.
>+  @retval RETURN_INVALID_PARAMETER If String is NULL.
>+                                   If Data is NULL.
>+                                   If PcdMaximumUnicodeStringLength is not
>+                                   zero, and String contains more than
>+                                   PcdMaximumUnicodeStringLength Unicode
>+                                   characters, not including the
>+                                   Null-terminator.
>+  @retval RETURN_UNSUPPORTED       If the number represented by String
>exceeds
>+                                   the range defined by UINT64.
>+
>+**/
>+RETURN_STATUS
>+StrDecimalToUint64S (
>+    CONST CHAR16             *String,
>+         CHAR16             **EndPointer,  OPTIONAL
>+         UINT64             *Data
>+  )
>+{
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. Neither String nor Data shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 2. The length of String shall not be greater than RSIZE_MAX.
>+  //
>+  if (RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <=
>RSIZE_MAX), RETURN_INVALID_PARAMETER);
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+
>+  //
>+  // Ignore the pad spaces (space or tab)
>+  //
>+  while ((*String == L' ') || (*String == L'\t')) {
>+    String++;
>+  }
>+
>+  //
>+  // Ignore leading Zeros after the spaces
>+  //
>+  while (*String == L'0') {
>+    String++;
>+  }
>+
>+  *Data = 0;
>+
>+  while (InternalIsDecimalDigitCharacter (*String)) {
>+    //
>+    // If the number represented by String overflows according to the range
>+    // defined by UINT64, then MAX_UINT64 is stored in *Data and
>+    // RETURN_UNSUPPORTED is returned.
>+    //
>+    if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {
>+      *Data = MAX_UINT64;
>+      if (EndPointer != NULL) {
>+        *EndPointer = (CHAR16 *) String;
>+      }
>+      return RETURN_UNSUPPORTED;
>+    }
>+
>+    *Data = (*Data) * 10 + (*String - L'0');
>+    String++;
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+  return RETURN_SUCCESS;
>+}
>+
>+/**
>+  Convert a Null-terminated Unicode hexadecimal string to a value of type
>+  UINTN.
>+
>+  This function outputs a value of type UINTN by interpreting the contents of
>+  the Unicode string specified by String as a hexadecimal number. The format
>of
>+  the input Unicode string String is:
>+
>+                  [spaces][zeros][x][hexadecimal digits].
>+
>+  The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
>+  The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
>+  If "x" appears in the input string, it must be prefixed with at least one 0.
>+  The function will ignore the pad space, which includes spaces or tab
>+  characters, before [zeros], [x] or [hexadecimal digit]. The running zero
>+  before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
>+  after [x] or the first valid hexadecimal digit. Then, the function stops at
>+  the first character that is a not a valid hexadecimal character or NULL,
>+  whichever one comes first.
>+
>+  If String is NULL, then ASSERT().
>+  If Data is NULL, then ASSERT().
>+  If String is not aligned in a 16-bit boundary, then ASSERT().
>+  If PcdMaximumUnicodeStringLength is not zero, and String contains more
>than
>+  PcdMaximumUnicodeStringLength Unicode characters, not including the
>+  Null-terminator, then ASSERT().
>+
>+  If String has no valid hexadecimal digits in the above format, then 0 is
>+  stored at the location pointed to by Data.
>+  If the number represented by String exceeds the range defined by UINTN,
>then
>+  MAX_UINTN is stored at the location pointed to by Data.
>+
>+  If EndPointer is not NULL, a pointer to the character that stopped the scan
>+  is stored at the location pointed to by EndPointer. If String has no valid
>+  hexadecimal digits right after the optional pad spaces, the value of String
>+  is stored at the location pointed to by EndPointer.
>+
>+  @param  String                   Pointer to a Null-terminated Unicode string.
>+  @param  EndPointer               Pointer to character that stops scan.
>+  @param  Data                     Pointer to the converted value.
>+
>+  @retval RETURN_SUCCESS           Value is translated from String.
>+  @retval RETURN_INVALID_PARAMETER If String is NULL.
>+                                   If Data is NULL.
>+                                   If PcdMaximumUnicodeStringLength is not
>+                                   zero, and String contains more than
>+                                   PcdMaximumUnicodeStringLength Unicode
>+                                   characters, not including the
>+                                   Null-terminator.
>+  @retval RETURN_UNSUPPORTED       If the number represented by String
>exceeds
>+                                   the range defined by UINTN.
>+
>+**/
>+RETURN_STATUS
>+StrHexToUintnS (
>+    CONST CHAR16             *String,
>+         CHAR16             **EndPointer,  OPTIONAL
>+         UINTN              *Data
>+  )
>+{
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. Neither String nor Data shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 2. The length of String shall not be greater than RSIZE_MAX.
>+  //
>+  if (RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <=
>RSIZE_MAX), RETURN_INVALID_PARAMETER);
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+
>+  //
>+  // Ignore the pad spaces (space or tab)
>+  //
>+  while ((*String == L' ') || (*String == L'\t')) {
>+    String++;
>+  }
>+
>+  //
>+  // Ignore leading Zeros after the spaces
>+  //
>+  while (*String == L'0') {
>+    String++;
>+  }
>+
>+  if (InternalCharToUpper (*String) == L'X') {
>+    if (*(String - 1) != L'0') {
>+      *Data = 0;
>+      return RETURN_SUCCESS;
>+    }
>+    //
>+    // Skip the 'X'
>+    //
>+    String++;
>+  }
>+
>+  *Data = 0;
>+
>+  while (InternalIsHexaDecimalDigitCharacter (*String)) {
>+    //
>+    // If the number represented by String overflows according to the range
>+    // defined by UINTN, then MAX_UINTN is stored in *Data and
>+    // RETURN_UNSUPPORTED is returned.
>+    //
>+    if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) {
>+      *Data = MAX_UINTN;
>+      if (EndPointer != NULL) {
>+        *EndPointer = (CHAR16 *) String;
>+      }
>+      return RETURN_UNSUPPORTED;
>+    }
>+
>+    *Data = (*Data << 4) + InternalHexCharToUintn (*String);
>+    String++;
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+  return RETURN_SUCCESS;
>+}
>+RETURN_STATUS
>+StrHexToUint64S (
>+    CONST CHAR16             *String,
>+         CHAR16             **EndPointer,  OPTIONAL
>+         UINT64             *Data
>+  )
>+{
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. Neither String nor Data shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 2. The length of String shall not be greater than RSIZE_MAX.
>+  //
>+  if (RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <=
>RSIZE_MAX), RETURN_INVALID_PARAMETER);
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+
>+  //
>+  // Ignore the pad spaces (space or tab)
>+  //
>+  while ((*String == L' ') || (*String == L'\t')) {
>+    String++;
>+  }
>+
>+  //
>+  // Ignore leading Zeros after the spaces
>+  //
>+  while (*String == L'0') {
>+    String++;
>+  }
>+
>+  if (InternalCharToUpper (*String) == L'X') {
>+    if (*(String - 1) != L'0') {
>+      *Data = 0;
>+      return RETURN_SUCCESS;
>+    }
>+    //
>+    // Skip the 'X'
>+    //
>+    String++;
>+  }
>+
>+  *Data = 0;
>+
>+  while (InternalIsHexaDecimalDigitCharacter (*String)) {
>+    //
>+    // If the number represented by String overflows according to the range
>+    // defined by UINT64, then MAX_UINT64 is stored in *Data and
>+    // RETURN_UNSUPPORTED is returned.
>+    //
>+    if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {
>+      *Data = MAX_UINT64;
>+      if (EndPointer != NULL) {
>+        *EndPointer = (CHAR16 *) String;
>+      }
>+      return RETURN_UNSUPPORTED;
>+    }
>+
>+    *Data =  ((*Data) << 4) + InternalHexCharToUintn (*String);
>+    String++;
>+  }
>+
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) String;
>+  }
>+  return RETURN_SUCCESS;
>+}
>+
>+UINT64
>+StrDecimalToUint64 (
>+  CONST CHAR16              *String
>+  )
>+{
>+  UINT64     Result;
>+
>+  StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);
>+  return Result;
>+}
>+
>+
>+UINT64
>+StrHexToUint64 (
>+  CONST CHAR16             *String
>+  )
>+{
>+  UINT64    Result;
>+
>+  StrHexToUint64S (String, (CHAR16 **) NULL, &Result);
>+  return Result;
>+}
>+
>+UINTN
>+StrDecimalToUintn (
>+  CONST CHAR16              *String
>+  )
>+{
>+  UINTN     Result;
>+
>+  StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result);
>+  return Result;
>+}
>+
>+UINTN
>+StrHexToUintn (
>+  CONST CHAR16              *String
>+  )
>+{
>+  UINTN     Result;
>+
>+  StrHexToUintnS (String, (CHAR16 **) NULL, &Result);
>+  return Result;
>+}
>+
>+UINTN
>+StrSize (
>+  CONST CHAR16              *String
>+  )
>+{
>+  return (StrLen (String) + 1) * sizeof (*String);
>+}
>+
>+
>+UINT64
>+ReadUnaligned64 (
>+   CONST UINT64              *Buffer
>+  )
>+{
>+  ASSERT (Buffer != NULL);
>+
>+  return *Buffer;
>+}
>+
>+UINT64
>+WriteUnaligned64 (
>+   UINT64                    *Buffer,
>+   UINT64                    Value
>+  )
>+{
>+  ASSERT (Buffer != NULL);
>+
>+  return *Buffer = Value;
>+}
>+
>+
>+EFI_GUID *
>+CopyGuid (
>+   EFI_GUID         *DestinationGuid,
>+   CONST EFI_GUID  *SourceGuid
>+  )
>+{
>+  WriteUnaligned64 (
>+    (UINT64*)DestinationGuid,
>+    ReadUnaligned64 ((CONST UINT64*)SourceGuid)
>+    );
>+  WriteUnaligned64 (
>+    (UINT64*)DestinationGuid + 1,
>+    ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
>+    );
>+  return DestinationGuid;
>+}
>+
>+UINT16
>+SwapBytes16 (
>+  UINT16                    Value
>+  )
>+{
>+  return (UINT16) ((Value<< 8) | (Value>> 8));
>+}
>+
>+
>+UINT32
>+SwapBytes32 (
>+  UINT32                    Value
>+  )
>+{
>+  UINT32  LowerBytes;
>+  UINT32  HigherBytes;
>+
>+  LowerBytes  = (UINT32) SwapBytes16 ((UINT16) Value);
>+  HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));
>+  return (LowerBytes << 16 | HigherBytes);
>+}
>+
>+BOOLEAN
>+InternalIsDecimalDigitCharacter (
>+  CHAR16                    Char
>+  )
>+{
>+  return (BOOLEAN) (Char >= L'0' && Char <= L'9');
>+}
>+
>+VOID *
>+InternalAllocateCopyPool (
>+   UINTN            AllocationSize,
>+   CONST VOID       *Buffer
>+  )
>+{
>+  VOID  *Memory;
>+
>+  ASSERT (Buffer != NULL);
>+  ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
>+
>+  Memory = malloc (AllocationSize);
>+  if (Memory != NULL) {
>+     Memory = memcpy (Memory, Buffer, AllocationSize);
>+  }
>+  return Memory;
>+}
>+
>+BOOLEAN
>+InternalIsHexaDecimalDigitCharacter (
>+  CHAR16                    Char
>+  )
>+{
>+
>+  return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||
>+    (Char >= L'A' && Char <= L'F') ||
>+    (Char >= L'a' && Char <= L'f'));
>+}
>+
>+UINTN
>+InternalHexCharToUintn (
>+        CHAR16                    Char
>+  )
>+{
>+  if (InternalIsDecimalDigitCharacter (Char)) {
>+    return Char - L'0';
>+  }
>+
>+  return (10 + InternalCharToUpper (Char) - L'A');
>+}
>+
>+
>+/**
>+  Convert a Null-terminated Unicode hexadecimal string to a byte array.
>+
>+  This function outputs a byte array by interpreting the contents of
>+  the Unicode string specified by String in hexadecimal format. The format of
>+  the input Unicode string String is:
>+
>+                  [XX]*
>+
>+  X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
>+  The function decodes every two hexadecimal digit characters as one byte.
>The
>+  decoding stops after Length of characters and outputs Buffer containing
>+  (Length / 2) bytes.
>+
>+  If String is not aligned in a 16-bit boundary, then ASSERT().
>+
>+  If String is NULL, then ASSERT().
>+
>+  If Buffer is NULL, then ASSERT().
>+
>+  If Length is not multiple of 2, then ASSERT().
>+
>+  If PcdMaximumUnicodeStringLength is not zero and Length is greater than
>+  PcdMaximumUnicodeStringLength, then ASSERT().
>+
>+  If MaxBufferSize is less than (Length / 2), then ASSERT().
>+
>+  @param  String                   Pointer to a Null-terminated Unicode string.
>+  @param  Length                   The number of Unicode characters to decode.
>+  @param  Buffer                   Pointer to the converted bytes array.
>+  @param  MaxBufferSize            The maximum size of Buffer.
>+
>+  @retval RETURN_SUCCESS           Buffer is translated from String.
>+  @retval RETURN_INVALID_PARAMETER If String is NULL.
>+                                   If Data is NULL.
>+                                   If Length is not multiple of 2.
>+                                   If PcdMaximumUnicodeStringLength is not zero,
>+                                    and Length is greater than
>+                                    PcdMaximumUnicodeStringLength.
>+  @retval RETURN_UNSUPPORTED       If Length of characters from String
>contain
>+                                    a character that is not valid hexadecimal
>+                                    digit characters, or a Null-terminator.
>+  @retval RETURN_BUFFER_TOO_SMALL  If MaxBufferSize is less than
>(Length / 2).
>+**/
>+RETURN_STATUS
>+StrHexToBytes (
>+   CONST CHAR16       *String,
>+   UINTN              Length,
>+   UINT8              *Buffer,
>+   UINTN              MaxBufferSize
>+  )
>+{
>+  UINTN                  Index;
>+
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. None of String or Buffer shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 2. Length shall not be greater than RSIZE_MAX.
>+  //
>+  if (RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX),
>RETURN_INVALID_PARAMETER);
>+  }
>+
>+  //
>+  // 3. Length shall not be odd.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 4. MaxBufferSize shall equal to or greater than Length / 2.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2),
>RETURN_BUFFER_TOO_SMALL);
>+
>+  //
>+  // 5. String shall not contains invalid hexadecimal digits.
>+  //
>+  for (Index = 0; Index < Length; Index++) {
>+    if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {
>+      break;
>+    }
>+  }
>+  if (Index != Length) {
>+    return RETURN_UNSUPPORTED;
>+  }
>+
>+  //
>+  // Convert the hex string to bytes.
>+  //
>+  for(Index = 0; Index < Length; Index++) {
>+
>+    //
>+    // For even characters, write the upper nibble for each buffer byte,
>+    // and for even characters, the lower nibble.
>+    //
>+    if ((Index & BIT0) == 0) {
>+      Buffer[Index / 2]  = (UINT8) InternalHexCharToUintn (String[Index]) << 4;
>+    } else {
>+      Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);
>+    }
>+  }
>+  return RETURN_SUCCESS;
>+}
>+
>+/**
>+  Convert a Null-terminated Unicode GUID string to a value of type
>+  EFI_GUID.
>+
>+  This function outputs a GUID value by interpreting the contents of
>+  the Unicode string specified by String. The format of the input
>+  Unicode string String consists of 36 characters, as follows:
>+
>+                  aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>+
>+  The pairs aa - pp are two characters in the range [0-9], [a-f] and
>+  [A-F], with each pair representing a single byte hexadecimal value.
>+
>+  The mapping between String and the EFI_GUID structure is as follows:
>+                  aa          Data1[24:31]
>+                  bb          Data1[16:23]
>+                  cc          Data1[8:15]
>+                  dd          Data1[0:7]
>+                  ee          Data2[8:15]
>+                  ff          Data2[0:7]
>+                  gg          Data3[8:15]
>+                  hh          Data3[0:7]
>+                  ii          Data4[0:7]
>+                  jj          Data4[8:15]
>+                  kk          Data4[16:23]
>+                  ll          Data4[24:31]
>+                  mm          Data4[32:39]
>+                  nn          Data4[40:47]
>+                  oo          Data4[48:55]
>+                  pp          Data4[56:63]
>+
>+  If String is NULL, then ASSERT().
>+  If Guid is NULL, then ASSERT().
>+  If String is not aligned in a 16-bit boundary, then ASSERT().
>+
>+  @param  String                   Pointer to a Null-terminated Unicode string.
>+  @param  Guid                     Pointer to the converted GUID.
>+
>+  @retval RETURN_SUCCESS           Guid is translated from String.
>+  @retval RETURN_INVALID_PARAMETER If String is NULL.
>+                                   If Data is NULL.
>+  @retval RETURN_UNSUPPORTED       If String is not as the above format.
>+
>+**/
>+RETURN_STATUS
>+StrToGuid (
>+   CONST CHAR16       *String,
>+   EFI_GUID           *Guid
>+  )
>+{
>+  RETURN_STATUS          Status;
>+  EFI_GUID               LocalGuid;
>+
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. None of String or Guid shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // Get aabbccdd in big-endian.
>+  //
>+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *)
>&LocalGuid.Data1, sizeof (LocalGuid.Data1));
>+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {
>+    return RETURN_UNSUPPORTED;
>+  }
>+  //
>+  // Convert big-endian to little-endian.
>+  //
>+  LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);
>+  String += 2 * sizeof (LocalGuid.Data1) + 1;
>+
>+  //
>+  // Get eeff in big-endian.
>+  //
>+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *)
>&LocalGuid.Data2, sizeof (LocalGuid.Data2));
>+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {
>+    return RETURN_UNSUPPORTED;
>+  }
>+  //
>+  // Convert big-endian to little-endian.
>+  //
>+  LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);
>+  String += 2 * sizeof (LocalGuid.Data2) + 1;
>+
>+  //
>+  // Get gghh in big-endian.
>+  //
>+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *)
>&LocalGuid.Data3, sizeof (LocalGuid.Data3));
>+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {
>+    return RETURN_UNSUPPORTED;
>+  }
>+  //
>+  // Convert big-endian to little-endian.
>+  //
>+  LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);
>+  String += 2 * sizeof (LocalGuid.Data3) + 1;
>+
>+  //
>+  // Get iijj.
>+  //
>+  Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);
>+  if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {
>+    return RETURN_UNSUPPORTED;
>+  }
>+  String += 2 * 2 + 1;
>+
>+  //
>+  // Get kkllmmnnoopp.
>+  //
>+  Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);
>+  if (RETURN_ERROR (Status)) {
>+    return RETURN_UNSUPPORTED;
>+  }
>+
>+  CopyGuid (Guid, &LocalGuid);
>+  return RETURN_SUCCESS;
>+}
>+
>+/**
>+  Compares up to a specified length the contents of two Null-terminated
>Unicode strings,
>+  and returns the difference between the first mismatched Unicode
>characters.
>+
>+  This function compares the Null-terminated Unicode string FirstString to the
>+  Null-terminated Unicode string SecondString. At most, Length Unicode
>+  characters will be compared. If Length is 0, then 0 is returned. If
>+  FirstString is identical to SecondString, then 0 is returned. Otherwise, the
>+  value returned is the first mismatched Unicode character in SecondString
>+  subtracted from the first mismatched Unicode character in FirstString.
>+
>+  If Length > 0 and FirstString is NULL, then ASSERT().
>+  If Length > 0 and FirstString is not aligned on a 16-bit boundary, then
>ASSERT().
>+  If Length > 0 and SecondString is NULL, then ASSERT().
>+  If Length > 0 and SecondString is not aligned on a 16-bit boundary, then
>ASSERT().
>+  If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
>+  PcdMaximumUnicodeStringLength, then ASSERT().
>+  If PcdMaximumUnicodeStringLength is not zero, and FirstString contains
>more than
>+  PcdMaximumUnicodeStringLength Unicode characters, not including the
>Null-terminator,
>+  then ASSERT().
>+  If PcdMaximumUnicodeStringLength is not zero, and SecondString contains
>more than
>+  PcdMaximumUnicodeStringLength Unicode characters, not including the
>Null-terminator,
>+  then ASSERT().
>+
>+  @param  FirstString   A pointer to a Null-terminated Unicode string.
>+  @param  SecondString  A pointer to a Null-terminated Unicode string.
>+  @param  Length        The maximum number of Unicode characters to
>compare.
>+
>+  @retval 0      FirstString is identical to SecondString.
>+  @return others FirstString is not identical to SecondString.
>+
>+**/
>+INTN
>+StrnCmp (
>+        CONST CHAR16              *FirstString,
>+        CONST CHAR16              *SecondString,
>+        UINTN                     Length
>+  )
>+{
>+  if (Length == 0) {
>+    return 0;
>+  }
>+
>+  //
>+  // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
>+  // Length tests are performed inside StrLen().
>+  //
>+  ASSERT (StrSize (FirstString) != 0);
>+  ASSERT (StrSize (SecondString) != 0);
>+
>+  while ((*FirstString != L'\0') &&
>+         (*SecondString != L'\0') &&
>+         (*FirstString == *SecondString) &&
>+         (Length > 1)) {
>+    FirstString++;
>+    SecondString++;
>+    Length--;
>+  }
>+
>+  return *FirstString - *SecondString;
>+}
>+
>+VOID *
>+AllocateCopyPool (
>+   UINTN       AllocationSize,
>+   CONST VOID  *Buffer
>+  )
>+{
>+  return InternalAllocateCopyPool (AllocationSize, Buffer);
>+}
>+
>+INTN
>+StrCmp (
>+  CONST CHAR16              *FirstString,
>+  CONST CHAR16              *SecondString
>+  )
>+{
>+  //
>+  // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
>+  //
>+  ASSERT (StrSize (FirstString) != 0);
>+  ASSERT (StrSize (SecondString) != 0);
>+
>+  while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
>+    FirstString++;
>+    SecondString++;
>+  }
>+  return *FirstString - *SecondString;
>+}
>+
>+UINT64
>+SwapBytes64 (
>+  UINT64                    Value
>+  )
>+{
>+  return InternalMathSwapBytes64 (Value);
>+}
>+
>+UINT64
>+InternalMathSwapBytes64 (
>+  UINT64                    Operand
>+  )
>+{
>+  UINT64  LowerBytes;
>+  UINT64  HigherBytes;
>+
>+  LowerBytes  = (UINT64) SwapBytes32 ((UINT32) Operand);
>+  HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
>+
>+  return (LowerBytes << 32 | HigherBytes);
>+}
>+
>+RETURN_STATUS
>+StrToIpv4Address (
>+  CONST CHAR16       *String,
>+  CHAR16             **EndPointer,
>+  EFI_IPv4_ADDRESS       *Address,
>+  UINT8              *PrefixLength
>+  )
>+{
>+  RETURN_STATUS          Status;
>+  UINTN                  AddressIndex;
>+  UINTN                  Uintn;
>+  EFI_IPv4_ADDRESS       LocalAddress;
>+  UINT8                  LocalPrefixLength;
>+  CHAR16                 *Pointer;
>+
>+  LocalPrefixLength = MAX_UINT8;
>+  LocalAddress.Addr[0] = 0;
>+
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. None of String or Guid shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex <
>ARRAY_SIZE (Address->Addr) + 1;) {
>+    if (!InternalIsDecimalDigitCharacter (*Pointer)) {
>+      //
>+      // D or P contains invalid characters.
>+      //
>+      break;
>+    }
>+
>+    //
>+    // Get D or P.
>+    //
>+    Status = StrDecimalToUintnS ((CONST CHAR16 *) Pointer, &Pointer,
>&Uintn);
>+    if (RETURN_ERROR (Status)) {
>+      return RETURN_UNSUPPORTED;
>+    }
>+    if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
>+      //
>+      // It's P.
>+      //
>+      if (Uintn > 32) {
>+        return RETURN_UNSUPPORTED;
>+      }
>+      LocalPrefixLength = (UINT8) Uintn;
>+    } else {
>+      //
>+      // It's D.
>+      //
>+      if (Uintn > MAX_UINT8) {
>+        return RETURN_UNSUPPORTED;
>+      }
>+      LocalAddress.Addr[AddressIndex] = (UINT8) Uintn;
>+      AddressIndex++;
>+    }
>+
>+    //
>+    // Check the '.' or '/', depending on the AddressIndex.
>+    //
>+    if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
>+      if (*Pointer == L'/') {
>+        //
>+        // '/P' is in the String.
>+        // Skip "/" and get P in next loop.
>+        //
>+        Pointer++;
>+      } else {
>+        //
>+        // '/P' is not in the String.
>+        //
>+        break;
>+      }
>+    } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
>+      if (*Pointer == L'.') {
>+        //
>+        // D should be followed by '.'
>+        //
>+        Pointer++;
>+      } else {
>+        return RETURN_UNSUPPORTED;
>+      }
>+    }
>+  }
>+
>+  if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
>+    return RETURN_UNSUPPORTED;
>+  }
>+
>+  memcpy (Address, &LocalAddress, sizeof (*Address));
>+  if (PrefixLength != NULL) {
>+    *PrefixLength = LocalPrefixLength;
>+  }
>+  if (EndPointer != NULL) {
>+    *EndPointer = Pointer;
>+  }
>+
>+  return RETURN_SUCCESS;
>+}
>+
>+RETURN_STATUS
>+StrToIpv6Address (
>+  CONST CHAR16       *String,
>+  CHAR16             **EndPointer,
>+  EFI_IPv6_ADDRESS   *Address,
>+  UINT8              *PrefixLength
>+  )
>+{
>+  RETURN_STATUS          Status;
>+  UINTN                  AddressIndex;
>+  UINTN                  Uintn;
>+  EFI_IPv6_ADDRESS       LocalAddress;
>+  UINT8                  LocalPrefixLength;
>+  CONST CHAR16           *Pointer;
>+  CHAR16                 *End;
>+  UINTN                  CompressStart;
>+  BOOLEAN                ExpectPrefix;
>+
>+  LocalPrefixLength = MAX_UINT8;
>+  CompressStart     = ARRAY_SIZE (Address->Addr);
>+  ExpectPrefix      = FALSE;
>+
>+  ASSERT (((UINTN) String & BIT0) == 0);
>+
>+  //
>+  // 1. None of String or Guid shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE
>(Address->Addr) + 1;) {
>+    if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
>+      if (*Pointer != L':') {
>+        //
>+        // ":" or "/" should be followed by digit characters.
>+        //
>+        return RETURN_UNSUPPORTED;
>+      }
>+
>+      //
>+      // Meet second ":" after previous ":" or "/"
>+      // or meet first ":" in the beginning of String.
>+      //
>+      if (ExpectPrefix) {
>+        //
>+        // ":" shall not be after "/"
>+        //
>+        return RETURN_UNSUPPORTED;
>+      }
>+
>+      if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex ==
>ARRAY_SIZE (Address->Addr)) {
>+        //
>+        // "::" can only appear once.
>+        // "::" can only appear when address is not full length.
>+        //
>+        return RETURN_UNSUPPORTED;
>+      } else {
>+        //
>+        // Remember the start of zero compressing.
>+        //
>+        CompressStart = AddressIndex;
>+        Pointer++;
>+
>+        if (CompressStart == 0) {
>+          if (*Pointer != L':') {
>+            //
>+            // Single ":" shall not be in the beginning of String.
>+            //
>+            return RETURN_UNSUPPORTED;
>+          }
>+          Pointer++;
>+        }
>+      }
>+    }
>+
>+    if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
>+      if (*Pointer == L'/') {
>+        //
>+        // Might be optional "/P" after "::".
>+        //
>+        if (CompressStart != AddressIndex) {
>+          return RETURN_UNSUPPORTED;
>+        }
>+      } else {
>+        break;
>+      }
>+    } else {
>+      if (!ExpectPrefix) {
>+        //
>+        // Get X.
>+        //
>+        Status = StrHexToUintnS (Pointer, &End, &Uintn);
>+        if (RETURN_ERROR (Status) || End - Pointer > 4) {
>+          //
>+          // Number of hexadecimal digit characters is no more than 4.
>+          //
>+          return RETURN_UNSUPPORTED;
>+        }
>+        Pointer = End;
>+        //
>+        // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit
>characters is no more than 4.
>+        //
>+        ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));
>+        LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uintn >> 8);
>+        LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn;
>+        AddressIndex += 2;
>+      } else {
>+        //
>+        // Get P, then exit the loop.
>+        //
>+        Status = StrDecimalToUintnS (Pointer, &End, &Uintn);
>+        if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) {
>+          //
>+          // Prefix length should not exceed 128.
>+          //
>+          return RETURN_UNSUPPORTED;
>+        }
>+        LocalPrefixLength = (UINT8) Uintn;
>+        Pointer = End;
>+        break;
>+      }
>+    }
>+
>+    //
>+    // Skip ':' or "/"
>+    //
>+    if (*Pointer == L'/') {
>+      ExpectPrefix = TRUE;
>+    } else if (*Pointer == L':') {
>+      if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
>+        //
>+        // Meet additional ":" after all 8 16-bit address
>+        //
>+        break;
>+      }
>+    } else {
>+      //
>+      // Meet other character that is not "/" or ":" after all 8 16-bit address
>+      //
>+      break;
>+    }
>+    Pointer++;
>+  }
>+
>+  if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart !=
>ARRAY_SIZE (Address->Addr)) ||
>+    (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart ==
>ARRAY_SIZE (Address->Addr))
>+      ) {
>+    //
>+    // Full length of address shall not have compressing zeros.
>+    // Non-full length of address shall have compressing zeros.
>+    //
>+    return RETURN_UNSUPPORTED;
>+  }
>+  memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);
>+  memset (&Address->Addr[CompressStart], 0,  ARRAY_SIZE (Address->Addr)
>- AddressIndex);
>+  if (AddressIndex > CompressStart) {
>+    memcpy (
>+      &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) -
>AddressIndex],
>+      &LocalAddress.Addr[CompressStart],
>+      AddressIndex - CompressStart
>+      );
>+  }
>+
>+  if (PrefixLength != NULL) {
>+    *PrefixLength = LocalPrefixLength;
>+  }
>+  if (EndPointer != NULL) {
>+    *EndPointer = (CHAR16 *) Pointer;
>+  }
>+
>+  return RETURN_SUCCESS;
>+}
>+
>+
>+RETURN_STATUS
>+UnicodeStrToAsciiStrS (
>+  CONST CHAR16              *Source,
>+  CHAR8                     *Destination,
>+  UINTN                     DestMax
>+  )
>+{
>+  UINTN            SourceLen;
>+
>+  ASSERT (((UINTN) Source & BIT0) == 0);
>+
>+  //
>+  // 1. Neither Destination nor Source shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
>+  //
>+  if (ASCII_RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX),
>RETURN_INVALID_PARAMETER);
>+  }
>+  if (RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX),
>RETURN_INVALID_PARAMETER);
>+  }
>+
>+  //
>+  // 3. DestMax shall not equal zero.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
>+  //
>+  SourceLen = StrnLenS (Source, DestMax);
>+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen),
>RETURN_BUFFER_TOO_SMALL);
>+
>+  //
>+  // 5. Copying shall not take place between objects that overlap.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap
>(Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)),
>RETURN_ACCESS_DENIED);
>+
>+  //
>+  // convert string
>+  //
>+  while (*Source != '\0') {
>+    //
>+    // If any Unicode characters in Source contain
>+    // non-zero value in the upper 8 bits, then ASSERT().
>+    //
>+    ASSERT (*Source < 0x100);
>+    *(Destination++) = (CHAR8) *(Source++);
>+  }
>+  *Destination = '\0';
>+
>+  return RETURN_SUCCESS;
>+}
>+
>+RETURN_STATUS
>+StrCpyS (
>+  CHAR16       *Destination,
>+  UINTN        DestMax,
>+  CONST CHAR16 *Source
>+  )
>+{
>+  UINTN            SourceLen;
>+
>+  ASSERT (((UINTN) Destination & BIT0) == 0);
>+  ASSERT (((UINTN) Source & BIT0) == 0);
>+
>+  //
>+  // 1. Neither Destination nor Source shall be a null pointer.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL),
>RETURN_INVALID_PARAMETER);
>+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 2. DestMax shall not be greater than RSIZE_MAX.
>+  //
>+  if (RSIZE_MAX != 0) {
>+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX),
>RETURN_INVALID_PARAMETER);
>+  }
>+
>+  //
>+  // 3. DestMax shall not equal zero.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0),
>RETURN_INVALID_PARAMETER);
>+
>+  //
>+  // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
>+  //
>+  SourceLen = StrnLenS (Source, DestMax);
>+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen),
>RETURN_BUFFER_TOO_SMALL);
>+
>+  //
>+  // 5. Copying shall not take place between objects that overlap.
>+  //
>+  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap
>(Destination, DestMax, (CHAR16 *)Source, SourceLen + 1),
>RETURN_ACCESS_DENIED);
>+
>+  //
>+  // The StrCpyS function copies the string pointed to by Source (including the
>terminating
>+  // null character) into the array pointed to by Destination.
>+  //
>+  while (*Source != 0) {
>+    *(Destination++) = *(Source++);
>+  }
>+  *Destination = 0;
>+
>+  return RETURN_SUCCESS;
>+}
>+
>+VOID *
>+AllocateZeroPool (
>+  UINTN  AllocationSize
>+  )
>+{
>+  VOID * Memory;
>+  Memory = malloc(AllocationSize);
>+  ASSERT (Memory != NULL);
>+  if (Memory == NULL) {
>+    fprintf(stderr, "Not memory for malloc\n");
>+  }
>+  memset(Memory, 0, AllocationSize);
>+  return Memory;
>+}
>+
>+VOID *
>+AllocatePool (
>+  UINTN  AllocationSize
>+  )
>+{
>+  return InternalAllocatePool (AllocationSize);
>+}
>+
>+UINT16
>+WriteUnaligned16 (
>+  UINT16                    *Buffer,
>+  UINT16                    Value
>+  )
>+{
>+  ASSERT (Buffer != NULL);
>+
>+  return *Buffer = Value;
>+}
>+
>+UINT16
>+ReadUnaligned16 (
>+  CONST UINT16              *Buffer
>+  )
>+{
>+  ASSERT (Buffer != NULL);
>+
>+  return *Buffer;
>+}
>diff --git a/BaseTools/Source/C/DevicePath/DevicePathUtilities.h
>b/BaseTools/Source/C/DevicePath/DevicePathUtilities.h
>new file mode 100644
>index 0000000..418615f
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/DevicePathUtilities.h
>@@ -0,0 +1,555 @@
>+/** @file
>+  EFI_DEVICE_PATH_UTILITIES_PROTOCOL as defined in UEFI 2.0.
>+  Use to create and manipulate device paths and device nodes.
>+
>+  Copyright (c) 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.
>+
>+**/
>+
>+#ifndef __DEVICE_PATH_UTILITIES_H__
>+#define __DEVICE_PATH_UTILITIES_H__
>+
>+///
>+/// Device Path Utilities protocol
>+///
>+#define EFI_DEVICE_PATH_UTILITIES_GUID \
>+  { \
>+    0x379be4e, 0xd706, 0x437d, {0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72,
>0xa4 } \
>+  }
>+
>+/**
>+  Returns the size of the device path, in bytes.
>+
>+  @param  DevicePath Points to the start of the EFI device path.
>+
>+  @return Size  Size of the specified device path, in bytes, including the end-
>of-path tag.
>+  @retval 0     DevicePath is NULL
>+
>+**/
>+typedef
>+UINTN
>+( *EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE)(
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
>+  );
>+
>+
>+/**
>+  Create a duplicate of the specified path.
>+
>+  @param  DevicePath Points to the source EFI device path.
>+
>+  @retval Pointer    A pointer to the duplicate device path.
>+  @retval NULL       insufficient memory or DevicePath is NULL
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH)(
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
>+  );
>+
>+/**
>+  Create a new path by appending the second device path to the first.
>+  If Src1 is NULL and Src2 is non-NULL, then a duplicate of Src2 is returned.
>+  If Src1 is non-NULL and Src2 is NULL, then a duplicate of Src1 is returned.
>+  If Src1 and Src2 are both NULL, then a copy of an end-of-device-path is
>returned.
>+
>+  @param  Src1 Points to the first device path.
>+  @param  Src2 Points to the second device path.
>+
>+  @retval Pointer  A pointer to the newly created device path.
>+  @retval NULL     Memory could not be allocated
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_UTILS_APPEND_PATH)(
>+   CONST EFI_DEVICE_PATH_PROTOCOL *Src1,
>+   CONST EFI_DEVICE_PATH_PROTOCOL *Src2
>+  );
>+
>+/**
>+  Creates a new path by appending the device node to the device path.
>+  If DeviceNode is NULL then a copy of DevicePath is returned.
>+  If DevicePath is NULL then a copy of DeviceNode, followed by an end-of-
>device path device node is returned.
>+  If both DeviceNode and DevicePath are NULL then a copy of an end-of-
>device-path device node is returned.
>+
>+  @param  DevicePath Points to the device path.
>+  @param  DeviceNode Points to the device node.
>+
>+  @retval Pointer    A pointer to the allocated device node.
>+  @retval NULL       There was insufficient memory.
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_UTILS_APPEND_NODE)(
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode
>+  );
>+
>+/**
>+  Creates a new path by appending the specified device path instance to the
>specified device path.
>+
>+  @param  DevicePath         Points to the device path. If NULL, then ignored.
>+  @param  DevicePathInstance Points to the device path instance.
>+
>+  @retval Pointer            A pointer to the newly created device path
>+  @retval NULL               Memory could not be allocated or DevicePathInstance
>is NULL.
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE)(
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
>+  );
>+
>+/**
>+  Creates a copy of the current device path instance and returns a pointer to
>the next device path
>+  instance.
>+
>+  @param  DevicePathInstance     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.
>+  @param  DevicePathInstanceSize On output, this holds the size of the
>device path instance,
>+                                 in bytes or zero, if DevicePathInstance is NULL.
>+                                 If NULL, then the instance size is not output.
>+
>+  @retval Pointer                A pointer to the copy of the current device path
>instance.
>+  @retval NULL                   DevicePathInstace was NULL on entry or there was
>insufficient memory.
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE)(
>+     EFI_DEVICE_PATH_PROTOCOL  **DevicePathInstance,
>+   UINTN                         *DevicePathInstanceSize
>+  );
>+
>+/**
>+  Creates a device node
>+
>+  @param  NodeType    NodeType is the device node type
>(EFI_DEVICE_PATH.Type) for
>+                      the new device node.
>+  @param  NodeSubType NodeSubType is the device node sub-type
>+                      EFI_DEVICE_PATH.SubType) for the new device node.
>+  @param  NodeLength  NodeLength is the length of the device node
>+                      (EFI_DEVICE_PATH.Length) for the new device node.
>+
>+  @retval Pointer     A pointer to the newly created device node.
>+  @retval NULL        NodeLength is less than
>+                      the size of the header or there was insufficient memory.
>+
>+**/
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL*
>+( *EFI_DEVICE_PATH_UTILS_CREATE_NODE)(
>+   UINT8                          NodeType,
>+   UINT8                          NodeSubType,
>+   UINT16                         NodeLength
>+);
>+
>+/**
>+  Returns whether a device path is multi-instance.
>+
>+  @param  DevicePath Points to the device path. If NULL, then ignored.
>+
>+  @retval TRUE       The device path has more than one instance
>+  @retval FALSE      The device path is empty or contains only a single instance.
>+
>+**/
>+typedef
>+BOOLEAN
>+( *EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE)(
>+   CONST EFI_DEVICE_PATH_PROTOCOL         *DevicePath
>+  );
>+
>+///
>+/// This protocol is used to creates and manipulates device paths and device
>nodes.
>+///
>+typedef struct {
>+  EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE GetDevicePathSize;
>+  EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH      DuplicateDevicePath;
>+  EFI_DEVICE_PATH_UTILS_APPEND_PATH          AppendDevicePath;
>+  EFI_DEVICE_PATH_UTILS_APPEND_NODE          AppendDeviceNode;
>+  EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE
>AppendDevicePathInstance;
>+  EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE
>GetNextDevicePathInstance;
>+  EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE
>IsDevicePathMultiInstance;
>+  EFI_DEVICE_PATH_UTILS_CREATE_NODE          CreateDeviceNode;
>+} EFI_DEVICE_PATH_UTILITIES_PROTOCOL;
>+
>+extern EFI_GUID gEfiDevicePathUtilitiesProtocolGuid;
>+
>+UINTN
>+StrLen (
>+  CONST CHAR16   *String
>+  );
>+
>+VOID *
>+AllocateCopyPool (
>+  UINTN       AllocationSize,
>+  CONST VOID  *Buffer
>+  );
>+
>+INTN
>+StrnCmp (
>+  CONST CHAR16              *FirstString,
>+  CONST CHAR16              *SecondString,
>+  UINTN                     Length
>+  );
>+
>+RETURN_STATUS
>+StrToGuid (
>+  CONST CHAR16       *String,
>+  EFI_GUID               *Guid
>+  );
>+
>+RETURN_STATUS
>+StrHexToBytes (
>+  CONST CHAR16       *String,
>+  UINTN              Length,
>+  UINT8              *Buffer,
>+  UINTN              MaxBufferSize
>+  );
>+
>+UINTN
>+InternalHexCharToUintn (
>+  CHAR16                    Char
>+  );
>+
>+VOID *
>+InternalAllocateCopyPool (
>+   UINTN            AllocationSize,
>+   CONST VOID       *Buffer
>+  );
>+
>+BOOLEAN
>+InternalIsDecimalDigitCharacter (
>+        CHAR16                    Char
>+  );
>+
>+UINT32
>+SwapBytes32 (
>+        UINT32                    Value
>+  );
>+
>+UINT16
>+SwapBytes16 (
>+        UINT16                    Value
>+  );
>+
>+EFI_GUID *
>+CopyGuid (
>+   EFI_GUID       *DestinationGuid,
>+   CONST EFI_GUID  *SourceGuid
>+  );
>+
>+UINT64
>+WriteUnaligned64 (
>+   UINT64                    *Buffer,
>+   UINT64                    Value
>+  );
>+
>+UINT64
>+ReadUnaligned64 (
>+   CONST UINT64              *Buffer
>+  );
>+
>+UINTN
>+StrSize (
>+  CONST CHAR16              *String
>+  );
>+
>+UINTN
>+StrHexToUintn (
>+  CONST CHAR16              *String
>+  );
>+
>+UINTN
>+StrDecimalToUintn (
>+  CONST CHAR16              *String
>+  );
>+
>+UINT64
>+StrHexToUint64 (
>+  CONST CHAR16             *String
>+  );
>+
>+UINT64
>+StrDecimalToUint64 (
>+  CONST CHAR16              *String
>+  );
>+
>+RETURN_STATUS
>+StrHexToUint64S (
>+    CONST CHAR16       *String,
>+    CHAR16             **EndPointer,
>+    UINT64             *Data
>+  );
>+
>+RETURN_STATUS
>+StrHexToUintnS (
>+    CONST CHAR16             *String,
>+         CHAR16             **EndPointer,  OPTIONAL
>+         UINTN              *Data
>+  );
>+
>+RETURN_STATUS
>+StrDecimalToUint64S (
>+    CONST CHAR16             *String,
>+         CHAR16             **EndPointer,  OPTIONAL
>+         UINT64             *Data
>+  );
>+
>+RETURN_STATUS
>+StrDecimalToUintnS (
>+    CONST CHAR16             *String,
>+         CHAR16             **EndPointer,  OPTIONAL
>+         UINTN              *Data
>+  );
>+
>+VOID *
>+ReallocatePool (
>+   UINTN  OldSize,
>+   UINTN  NewSize,
>+   VOID   *OldBuffer  OPTIONAL
>+  );
>+
>+VOID *
>+InternalReallocatePool (
>+   UINTN            OldSize,
>+   UINTN            NewSize,
>+   VOID             *OldBuffer  OPTIONAL
>+  );
>+
>+VOID *
>+InternalAllocateZeroPool (
>+   UINTN            AllocationSize
>+  ) ;
>+
>+VOID *
>+InternalAllocatePool (
>+   UINTN            AllocationSize
>+  );
>+
>+UINTN
>+StrnLenS (
>+   CONST CHAR16              *String,
>+   UINTN                     MaxSize
>+  );
>+
>+CHAR16
>+InternalCharToUpper (
>+        CHAR16                    Char
>+  );
>+
>+UINTN
>+DevicePathNodeLength (
>+  CONST VOID  *Node
>+  );
>+
>+UINT16
>+SetDevicePathNodeLength (
>+  VOID  *Node,
>+  UINTN     Length
>+  );
>+
>+INTN
>+StrCmp (
>+  CONST CHAR16              *FirstString,
>+  CONST CHAR16              *SecondString
>+  );
>+
>+UINT64
>+SwapBytes64 (
>+  UINT64                    Value
>+  );
>+
>+UINT64
>+InternalMathSwapBytes64 (
>+  UINT64                    Operand
>+  );
>+
>+RETURN_STATUS
>+StrToIpv4Address (
>+  CONST CHAR16       *String,
>+  CHAR16             **EndPointer,
>+  EFI_IPv4_ADDRESS       *Address,
>+  UINT8              *PrefixLength
>+  );
>+
>+RETURN_STATUS
>+StrToIpv6Address (
>+  CONST CHAR16       *String,
>+  CHAR16             **EndPointer,
>+  EFI_IPv6_ADDRESS       *Address,
>+  UINT8              *PrefixLength
>+  );
>+
>+RETURN_STATUS
>+StrCpyS (
>+  CHAR16       *Destination,
>+  UINTN        DestMax,
>+  CONST CHAR16 *Source
>+  );
>+
>+RETURN_STATUS
>+UnicodeStrToAsciiStrS (
>+  CONST CHAR16              *Source,
>+  CHAR8                     *Destination,
>+  UINTN                     DestMax
>+  );
>+VOID *
>+AllocatePool (
>+  UINTN  AllocationSize
>+  );
>+
>+VOID
>+SetDevicePathEndNode (
>+   VOID  *Node
>+  );
>+
>+BOOLEAN
>+IsDevicePathValid (
>+   CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
>+   UINTN                    MaxSize
>+  );
>+
>+UINT8
>+DevicePathType (
>+   CONST VOID  *Node
>+  );
>+
>+UINT8
>+DevicePathSubType (
>+   CONST VOID  *Node
>+  );
>+
>+UINTN
>+DevicePathNodeLength (
>+   CONST VOID  *Node
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+NextDevicePathNode (
>+   CONST VOID  *Node
>+  );
>+
>+BOOLEAN
>+IsDevicePathEndType (
>+   CONST VOID  *Node
>+  );
>+
>+BOOLEAN
>+IsDevicePathEnd (
>+   CONST VOID  *Node
>+  );
>+BOOLEAN
>+IsDevicePathEndInstance (
>+   CONST VOID  *Node
>+  );
>+
>+UINT16
>+SetDevicePathNodeLength (
>+    VOID  *Node,
>+   UINTN     Length
>+  );
>+
>+VOID
>+SetDevicePathEndNode (
>+   VOID  *Node
>+  );
>+
>+UINTN
>+UefiDevicePathLibGetDevicePathSize (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibDuplicateDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibAppendDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibAppendDevicePathNode (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibAppendDevicePathInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibGetNextDevicePathInstance (
>+    EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
>+   UINTN                          *Size
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+UefiDevicePathLibCreateDeviceNode (
>+   UINT8                           NodeType,
>+   UINT8                           NodeSubType,
>+   UINT16                          NodeLength
>+  );
>+
>+BOOLEAN
>+UefiDevicePathLibIsDevicePathMultiInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  );
>+
>+UINT16
>+WriteUnaligned16 (
>+  UINT16                    *Buffer,
>+  UINT16                    Value
>+  );
>+
>+UINT16
>+ReadUnaligned16 (
>+  CONST UINT16              *Buffer
>+  );
>+
>+VOID *
>+AllocateZeroPool (
>+  UINTN  AllocationSize
>+  );
>+
>+BOOLEAN
>+InternalIsHexaDecimalDigitCharacter (
>+  CHAR16                    Char
>+  );
>+
>+BOOLEAN
>+InternalSafeStringIsOverlap (
>+  IN VOID    *Base1,
>+  IN UINTN   Size1,
>+  IN VOID    *Base2,
>+  IN UINTN   Size2
>+  );
>+
>+BOOLEAN
>+InternalSafeStringNoStrOverlap (
>+  IN CHAR16  *Str1,
>+  IN UINTN   Size1,
>+  IN CHAR16  *Str2,
>+  IN UINTN   Size2
>+  );
>+
>+#endif
>diff --git a/BaseTools/Source/C/DevicePath/GNUmakefile
>b/BaseTools/Source/C/DevicePath/GNUmakefile
>new file mode 100644
>index 0000000..27f6fa1
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/GNUmakefile
>@@ -0,0 +1,30 @@
>+## @file
>+# GNU/Linux makefile for 'DevicePath' module build.
>+#
>+# Copyright (c) 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.
>+#
>+ARCH ?= IA32
>+MAKEROOT ?= ..
>+
>+APPNAME = DevicePath
>+
>+OBJECTS = DevicePath.o UefiDevicePathLib.o DevicePathFromText.o
>DevicePathUtilities.o
>+
>+include $(MAKEROOT)/Makefiles/app.makefile
>+
>+LIBS = -lCommon
>+ifeq ($(CYGWIN), CYGWIN)
>+  LIBS += -L/lib/e2fsprogs -luuid
>+endif
>+
>+ifeq ($(LINUX), Linux)
>+  LIBS += -luuid
>+endif
>+
>diff --git a/BaseTools/Source/C/DevicePath/Makefile
>b/BaseTools/Source/C/DevicePath/Makefile
>new file mode 100644
>index 0000000..a069c22
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/Makefile
>@@ -0,0 +1,24 @@
>+## @file
>+# Windows makefile for 'DevicePath' module build.
>+#
>+# Copyright (c) 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 ..\Makefiles\ms.common
>+
>+APPNAME = DevicePath
>+
>+LIBS = $(LIB_PATH)\Common.lib
>+
>+OBJECTS = DevicePath.obj UefiDevicePathLib.obj DevicePathFromText.obj
>DevicePathUtilities.obj
>+
>+#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib
>+
>+!INCLUDE ..\Makefiles\ms.app
>+
>diff --git a/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
>b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
>new file mode 100644
>index 0000000..a2e0322
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c
>@@ -0,0 +1,298 @@
>+/** @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) 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"
>+
>+/**
>+  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
>+GetDevicePathSize (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  )
>+{
>+  return UefiDevicePathLibGetDevicePathSize (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 *
>+DuplicateDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  )
>+{
>+  return UefiDevicePathLibDuplicateDevicePath (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 *
>+AppendDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
>+  )
>+{
>+  return UefiDevicePathLibAppendDevicePath (FirstDevicePath,
>SecondDevicePath);
>+}
>+
>+/**
>+  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 *
>+AppendDevicePathNode (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
>+  )
>+{
>+  return UefiDevicePathLibAppendDevicePathNode (DevicePath,
>DevicePathNode);
>+}
>+
>+/**
>+  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 *
>+AppendDevicePathInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance OPTIONAL
>+  )
>+{
>+  return UefiDevicePathLibAppendDevicePathInstance (DevicePath,
>DevicePathInstance);
>+}
>+
>+/**
>+  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 *
>+GetNextDevicePathInstance (
>+    EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
>+   UINTN                          *Size
>+  )
>+{
>+  return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, 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 *
>+CreateDeviceNode (
>+   UINT8                           NodeType,
>+   UINT8                           NodeSubType,
>+   UINT16                          NodeLength
>+  )
>+{
>+  return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType,
>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
>+IsDevicePathMultiInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  )
>+{
>+  return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath);
>+}
>+
>+/**
>+  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 *
>+ConvertTextToDeviceNode (
>+   CONST CHAR16 *TextDeviceNode
>+  )
>+{
>+  return UefiDevicePathLibConvertTextToDeviceNode (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 *
>+ConvertTextToDevicePath (
>+   CONST CHAR16 *TextDevicePath
>+ )
>+{
>+  return UefiDevicePathLibConvertTextToDevicePath (TextDevicePath);
>+}
>diff --git a/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h
>b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h
>new file mode 100644
>index 0000000..e03fbd0
>--- /dev/null
>+++ b/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h
>@@ -0,0 +1,473 @@
>+/** @file
>+  Definition for Device Path library.
>+
>+Copyright (c) 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.
>+
>+**/
>+#ifndef _UEFI_DEVICE_PATH_LIB_H_
>+#define _UEFI_DEVICE_PATH_LIB_H_
>+
>+#include <stdio.h>
>+#include <stdlib.h>
>+#include <string.h>
>+#include <ctype.h>
>+#include <assert.h>
>+#ifdef __GNUC__
>+#include <unistd.h>
>+#else
>+#include <direct.h>
>+#endif
>+#include <Common/UefiBaseTypes.h>
>+#include "CommonLib.h"
>+#include "EfiUtilityMsgs.h"
>+#include "DevicePath.h"
>+#include "DevicePathUtilities.h"
>+#include "DevicePathFromText.h"
>+
>+
>+#define IS_COMMA(a)                ((a) == L',')
>+#define IS_HYPHEN(a)               ((a) == L'-')
>+#define IS_DOT(a)                  ((a) == L'.')
>+#define IS_LEFT_PARENTH(a)         ((a) == L'(')
>+#define IS_RIGHT_PARENTH(a)        ((a) == L')')
>+#define IS_SLASH(a)                ((a) == L'/')
>+#define IS_NULL(a)                 ((a) == L'\0')
>+
>+#define MAX_UINTN MAX_ADDRESS
>+#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL)
>+#define MAX_UINT16  ((UINT16)0xFFFF)
>+#define MAX_UINT8   ((UINT8)0xFF)
>+
>+#define END_DEVICE_PATH_LENGTH               (sizeof
>(EFI_DEVICE_PATH_PROTOCOL))
>+#define MAX_DEVICE_PATH_NODE_COUNT   1024
>+#define SIZE_64KB   0x00010000
>+#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0]))
>+#define ASCII_RSIZE_MAX 1000000
>+#ifndef RSIZE_MAX
>+#define RSIZE_MAX 1000000
>+#endif
>+
>+//
>+// Private Data structure
>+//
>+typedef
>+EFI_DEVICE_PATH_PROTOCOL  *
>+(*DEVICE_PATH_FROM_TEXT) (
>+  IN  CHAR16 *Str
>+ );
>+
>+typedef struct {
>+  CHAR16  *Str;
>+  UINTN   Count;
>+  UINTN   Capacity;
>+} POOL_PRINT;
>+
>+
>+typedef struct {
>+  CHAR16                    *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()
>+
>+/**
>+  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
>+UefiDevicePathLibGetDevicePathSize (
>+   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 *
>+UefiDevicePathLibDuplicateDevicePath (
>+   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 *
>+UefiDevicePathLibAppendDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
>+   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 *
>+UefiDevicePathLibAppendDevicePathNode (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
>+   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 *
>+UefiDevicePathLibAppendDevicePathInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
>+   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 *
>+UefiDevicePathLibGetNextDevicePathInstance (
>+   EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
>+   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 *
>+UefiDevicePathLibCreateDeviceNode (
>+   UINT8                           NodeType,
>+   UINT8                           NodeSubType,
>+   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
>+UefiDevicePathLibIsDevicePathMultiInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  );
>+
>+/**
>+  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 *
>+UefiDevicePathLibConvertTextToDeviceNode (
>+   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 *
>+UefiDevicePathLibConvertTextToDevicePath (
>+   CONST CHAR16 *TextDevicePath
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+CreateDeviceNode (
>+   UINT8                           NodeType,
>+   UINT8                           NodeSubType,
>+   UINT16                          NodeLength
>+  );
>+
>+ EFI_DEVICE_PATH_PROTOCOL *
>+CreateDeviceNode (
>+   UINT8                           NodeType,
>+   UINT8                           NodeSubType,
>+   UINT16                          NodeLength
>+  );
>+
>+BOOLEAN
>+IsDevicePathMultiInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+GetNextDevicePathInstance (
>+    EFI_DEVICE_PATH_PROTOCOL    **DevicePath,
>+   UINTN                          *Size
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+AppendDevicePathInstance (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,        OPTIONAL
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathInstance OPTIONAL
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+AppendDevicePathNode (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
>+  );
>+EFI_DEVICE_PATH_PROTOCOL *
>+AppendDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+DuplicateDevicePath (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  );
>+
>+UINTN
>+GetDevicePathSize (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
>+  );
>+
>+CHAR16 *
>+ConvertDeviceNodeToText (
>+   CONST EFI_DEVICE_PATH_PROTOCOL  *DeviceNode,
>+   BOOLEAN                         DisplayOnly,
>+   BOOLEAN                         AllowShortcuts
>+  );
>+
>+CHAR16 *
>+ConvertDevicePathToText (
>+   CONST EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
>+   BOOLEAN                          DisplayOnly,
>+   BOOLEAN                          AllowShortcuts
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+ConvertTextToDeviceNode (
>+   CONST CHAR16 *TextDeviceNode
>+  );
>+
>+EFI_DEVICE_PATH_PROTOCOL *
>+ConvertTextToDevicePath (
>+   CONST CHAR16 *TextDevicePath
>+  );
>+
>+
>+#endif
>diff --git a/BaseTools/Source/C/GNUmakefile
>b/BaseTools/Source/C/GNUmakefile
>index 0dc7482..37421ad 100644
>--- a/BaseTools/Source/C/GNUmakefile
>+++ b/BaseTools/Source/C/GNUmakefile
>@@ -65,11 +65,12 @@ APPLICATIONS = \
>   GenCrc32 \
>   GenVtf \
>   LzmaCompress \
>   Split \
>   TianoCompress \
>-  VolInfo
>+  VolInfo \
>+  DevicePath
>
> SUBDIRS := $(LIBRARIES) $(APPLICATIONS)
>
> $(LIBRARIES): $(MAKEROOT)/libs
> $(APPLICATIONS): $(LIBRARIES) $(MAKEROOT)/bin $(VFRAUTOGEN)
>diff --git a/BaseTools/Source/C/Makefile b/BaseTools/Source/C/Makefile
>index 50be773..5428180 100644
>--- a/BaseTools/Source/C/Makefile
>+++ b/BaseTools/Source/C/Makefile
>@@ -1,9 +1,9 @@
> ## @file
> # Windows makefile for C tools build.
> #
>-# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
>+# Copyright (c) 2009 - 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
> #
>@@ -30,11 +30,12 @@ APPLICATIONS = \
>   GenVtf \
>   LzmaCompress \
>   Split \
>   TianoCompress \
>   VolInfo \
>-  VfrCompile
>+  VfrCompile \
>+  DevicePath
>
> all: libs apps install
>
> libs: $(LIBRARIES)
> 	@echo.
>diff --git a/BaseTools/Source/Python/Common/Misc.py
>b/BaseTools/Source/Python/Common/Misc.py
>index c51b685..104a370 100644
>--- a/BaseTools/Source/Python/Common/Misc.py
>+++ b/BaseTools/Source/Python/Common/Misc.py
>@@ -36,11 +36,11 @@ from CommonDataClass.DataClass import *
> from Parsing import GetSplitValueList
> from Common.LongFilePathSupport import OpenLongFilePath as open
> from Common.MultipleWorkspace import MultipleWorkspace as mws
> import uuid
> from CommonDataClass.Exceptions import BadExpression
>-
>+import subprocess
> ## Regular expression used to find out place holders in string template
> gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE |
>re.UNICODE)
>
> ## Dictionary used to store file time stamp for quick re-access
> gFileTimeStampCache = {}    # {file path : file time stamp}
>@@ -1472,11 +1472,42 @@ def AnalyzePcdExpression(Setting):
>         StartPos = Pos + 1
>
>     return FieldList
>
> def ParseDevPathValue (Value):
>-    pass
>+    DevPathList =
>[ "Path","HardwarePath","Pci","PcCard","MemoryMapped","VenHw","Ctrl","
>BMC","AcpiPath","Acpi","PciRoot",
>+
>"PcieRoot","Floppy","Keyboard","Serial","ParallelPort","AcpiEx","AcpiExp","A
>cpiAdr","Msg","Ata","Scsi",
>+
>"Fibre","FibreEx","I1394","USB","I2O","Infiniband","VenMsg","VenPcAnsi","V
>enVt100","VenVt100Plus",
>+
>"VenUtf8","UartFlowCtrl","SAS","SasEx","NVMe","UFS","SD","eMMC","Debu
>gPort","MAC","IPv4","IPv6","Uart",
>+
>"UsbClass","UsbAudio","UsbCDCControl","UsbHID","UsbImage","UsbPrinter"
>,"UsbMassStorage","UsbHub",
>+
>"UsbCDCData","UsbSmartCard","UsbVideo","UsbDiagnostic","UsbWireless","
>UsbDeviceFirmwareUpdate",
>+
>"UsbIrdaBridge","UsbTestAndMeasurement","UsbWwid","Unit","iSCSI","Vla
>n","Uri","Bluetooth","Wi-Fi",
>+
>"MediaPath","HD","CDROM","VenMedia","Media","Fv","FvFile","Offset","Ra
>mDisk","VirtualDisk","VirtualCD",
>+
>"PersistentVirtualDisk","PersistentVirtualCD","BbsPath","BBS","Sata" ]
>+    if '\\' in Value:
>+        Value.replace('\\', '/').replace(' ', '')
>+    for Item in Value.split('/'):
>+        Key = Item.strip().split('(')[0]
>+        if Key not in DevPathList:
>+            pass
>+
>+    Cmd = 'DevicePath ' + '"' + Value + '"'
>+    try:
>+        p = subprocess.Popen(Cmd, stdout=subprocess.PIPE,
>stderr=subprocess.PIPE, shell=True)
>+        out, err = p.communicate()
>+    except Exception, X:
>+        raise BadExpression("DevicePath: %s" % (str(X)) )
>+    finally:
>+        subprocess._cleanup()
>+        p.stdout.close()
>+        p.stderr.close()
>+    if err:
>+        raise BadExpression("DevicePath: %s" % str(err))
>+    Size = len(out.split())
>+    out = ','.join(out.split())
>+    return '{' + out + '}', Size
>+
>
> def ParseFieldValue (Value):
>     if type(Value) == type(0):
>         return Value, (Value.bit_length() + 7) / 8
>     if type(Value) <> type(''):
>diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py
>b/BaseTools/Source/Python/Workspace/DscBuildData.py
>index 05b26a3..f9cd429 100644
>--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
>+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
>@@ -2060,11 +2060,11 @@ class DscBuildData(PlatformBuildClassObject):
>                 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace,
>Arch=self._Arch)
>                 if ModuleFile in self._Modules:
>                     continue
>                 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target,
>self._Toolchain]
>                 PkgSet.update(ModuleData.Packages)
>-            self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch,
>self._Target, self._Toolchain,PkgSet)
>+            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb,
>self._Arch, self._Target, self._Toolchain,PkgSet)
>         return self._DecPcds
>     _Macros             = property(_GetMacros)
>     Arch                = property(_GetArch, _SetArch)
>     Platform            = property(_GetPlatformName)
>     PlatformName        = property(_GetPlatformName)
>--
>2.6.1.windows.1
>
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-12-27  2:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-26 16:40 [Patch 0/2] BaseTools: Add Flexible PCD Value support Yonghong Zhu
2017-12-26 16:40 ` [Patch 1/2] BaseTools: Support PCD flexible values format Yonghong Zhu
2017-12-26 16:40 ` [Patch 2/2] BaseTools: Add DevicePath support for PCD values Yonghong Zhu
2017-12-27  2:40   ` Gao, Liming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox