1/*-
2 * Copyright (c) 2017 Netflix, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26/*
27 * Routines to format EFI_DEVICE_PATHs from the UEFI standard. Much of
28 * this file is taken from EDK2 and rototilled.
29 */
30
31#include <sys/cdefs.h>
32#include <ctype.h>
33#include <efivar.h>
34#include <stdio.h>
35#include <string.h>
36#include <wchar.h>
37
38#include "efichar.h"
39
40#include "efi-osdep.h"
41#include "efivar-dp.h"
42
43#include "uefi-dplib.h"
44
45/* XXX STUBS -- this stuff doesn't work yet */
46#define StrToIpv4Address(str, unk, ipv4ptr, unk2)	(void)(str)
47#define StrToIpv6Address(str, unk, ipv6ptr, unk2)	(void)(str)
48
49/*
50 * OK. Now this is evil. Can't typedef it again. Sure beats changing them all.
51 * Since we're doing it all as narrow characters since wchar_t can't be used on
52 * FreeBSD and CHAR16 strings generally aren't a good fit. Since this parsing
53 * doesn't need Unicode for anything, this works out well.
54 */
55#define CHAR16 char
56
57/*
58 * Taken from MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c
59 */
60
61/** @file
62  DevicePathFromText protocol as defined in the UEFI 2.0 specification.
63
64Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
65SPDX-License-Identifier: BSD-2-Clause-Patent
66
67**/
68
69// #include "UefiDevicePathLib.h"
70
71/**
72
73  Duplicates a string.
74
75  @param  Src  Source string.
76
77  @return The duplicated string.
78
79**/
80static
81CHAR16 *
82UefiDevicePathLibStrDuplicate (
83  IN CONST CHAR16  *Src
84  )
85{
86  return AllocateCopyPool (StrSize (Src), Src);
87}
88
89/**
90
91  Get parameter in a pair of parentheses follow the given node name.
92  For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1".
93
94  @param  Str      Device Path Text.
95  @param  NodeName Name of the node.
96
97  @return Parameter text for the node.
98
99**/
100static
101CHAR16 *
102GetParamByNodeName (
103  IN CHAR16  *Str,
104  IN const CHAR16  *NodeName
105  )
106{
107  CHAR16  *ParamStr;
108  CHAR16  *StrPointer;
109  UINTN   NodeNameLength;
110  UINTN   ParameterLength;
111
112  //
113  // Check whether the node name matchs
114  //
115  NodeNameLength = StrLen (NodeName);
116  if (StrnCmp (Str, NodeName, NodeNameLength) != 0) {
117    return NULL;
118  }
119
120  ParamStr = Str + NodeNameLength;
121  if (!IS_LEFT_PARENTH (*ParamStr)) {
122    return NULL;
123  }
124
125  //
126  // Skip the found '(' and find first occurrence of ')'
127  //
128  ParamStr++;
129  ParameterLength = 0;
130  StrPointer      = ParamStr;
131  while (!IS_NULL (*StrPointer)) {
132    if (IS_RIGHT_PARENTH (*StrPointer)) {
133      break;
134    }
135
136    StrPointer++;
137    ParameterLength++;
138  }
139
140  if (IS_NULL (*StrPointer)) {
141    //
142    // ')' not found
143    //
144    return NULL;
145  }
146
147  ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr);
148  if (ParamStr == NULL) {
149    return NULL;
150  }
151
152  //
153  // Terminate the parameter string
154  //
155  ParamStr[ParameterLength] = '\0';
156
157  return ParamStr;
158}
159
160/**
161  Gets current sub-string from a string list, before return
162  the list header is moved to next sub-string. The sub-string is separated
163  by the specified character. For example, the separator is ',', the string
164  list is "2,0,3", it returns "2", the remain list move to "0,3"
165
166  @param  List        A string list separated by the specified separator
167  @param  Separator   The separator character
168
169  @return A pointer to the current sub-string
170
171**/
172static
173CHAR16 *
174SplitStr (
175  IN OUT CHAR16  **List,
176  IN     CHAR16  Separator
177  )
178{
179  CHAR16  *Str;
180  CHAR16  *ReturnStr;
181
182  Str       = *List;
183  ReturnStr = Str;
184
185  if (IS_NULL (*Str)) {
186    return ReturnStr;
187  }
188
189  //
190  // Find first occurrence of the separator
191  //
192  while (!IS_NULL (*Str)) {
193    if (*Str == Separator) {
194      break;
195    }
196
197    Str++;
198  }
199
200  if (*Str == Separator) {
201    //
202    // Find a sub-string, terminate it
203    //
204    *Str = '\0';
205    Str++;
206  }
207
208  //
209  // Move to next sub-string
210  //
211  *List = Str;
212
213  return ReturnStr;
214}
215
216/**
217  Gets the next parameter string from the list.
218
219  @param List            A string list separated by the specified separator
220
221  @return A pointer to the current sub-string
222
223**/
224static
225CHAR16 *
226GetNextParamStr (
227  IN OUT CHAR16  **List
228  )
229{
230  //
231  // The separator is comma
232  //
233  return SplitStr (List, ',');
234}
235
236/**
237  Get one device node from entire device path text.
238
239  @param DevicePath      On input, the current Device Path node; on output, the next device path node
240  @param IsInstanceEnd   This node is the end of a device path instance
241
242  @return A device node text or NULL if no more device node available
243
244**/
245static
246CHAR16 *
247GetNextDeviceNodeStr (
248  IN OUT CHAR16   **DevicePath,
249  OUT    BOOLEAN  *IsInstanceEnd
250  )
251{
252  CHAR16  *Str;
253  CHAR16  *ReturnStr;
254  UINTN   ParenthesesStack;
255
256  Str = *DevicePath;
257  if (IS_NULL (*Str)) {
258    return NULL;
259  }
260
261  //
262  // Skip the leading '/', '(', ')' and ','
263  //
264  while (!IS_NULL (*Str)) {
265    if (!IS_SLASH (*Str) &&
266        !IS_COMMA (*Str) &&
267        !IS_LEFT_PARENTH (*Str) &&
268        !IS_RIGHT_PARENTH (*Str))
269    {
270      break;
271    }
272
273    Str++;
274  }
275
276  ReturnStr = Str;
277
278  //
279  // Scan for the separator of this device node, '/' or ','
280  //
281  ParenthesesStack = 0;
282  while (!IS_NULL (*Str)) {
283    if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) {
284      break;
285    }
286
287    if (IS_LEFT_PARENTH (*Str)) {
288      ParenthesesStack++;
289    } else if (IS_RIGHT_PARENTH (*Str)) {
290      ParenthesesStack--;
291    }
292
293    Str++;
294  }
295
296  if (ParenthesesStack != 0) {
297    //
298    // The '(' doesn't pair with ')', invalid device path text
299    //
300    return NULL;
301  }
302
303  if (IS_COMMA (*Str)) {
304    *IsInstanceEnd = TRUE;
305    *Str           = '\0';
306    Str++;
307  } else {
308    *IsInstanceEnd = FALSE;
309    if (!IS_NULL (*Str)) {
310      *Str = '\0';
311      Str++;
312    }
313  }
314
315  *DevicePath = Str;
316
317  return ReturnStr;
318}
319
320
321#ifndef __FreeBSD__
322/**
323  Return whether the integer string is a hex string.
324
325  @param Str             The integer string
326
327  @retval TRUE   Hex string
328  @retval FALSE  Decimal string
329
330**/
331static
332BOOLEAN
333IsHexStr (
334  IN CHAR16  *Str
335  )
336{
337  //
338  // skip preceeding white space
339  //
340  while ((*Str != 0) && *Str == ' ') {
341    Str++;
342  }
343
344  //
345  // skip preceeding zeros
346  //
347  while ((*Str != 0) && *Str == '0') {
348    Str++;
349  }
350
351  return (BOOLEAN)(*Str == 'x' || *Str == 'X');
352}
353
354/**
355
356  Convert integer string to uint.
357
358  @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.
359
360  @return A UINTN value represented by Str
361
362**/
363static
364UINTN
365Strtoi (
366  IN CHAR16  *Str
367  )
368{
369  if (IsHexStr (Str)) {
370    return StrHexToUintn (Str);
371  } else {
372    return StrDecimalToUintn (Str);
373  }
374}
375
376/**
377
378  Convert integer string to 64 bit data.
379
380  @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.
381  @param Data            A pointer to the UINT64 value represented by Str
382
383**/
384static
385VOID
386Strtoi64 (
387  IN  CHAR16  *Str,
388  OUT UINT64  *Data
389  )
390{
391  if (IsHexStr (Str)) {
392    *Data = StrHexToUint64 (Str);
393  } else {
394    *Data = StrDecimalToUint64 (Str);
395  }
396}
397#endif
398
399/**
400  Converts a Unicode string to ASCII string.
401
402  @param Str             The equivalent Unicode string
403  @param AsciiStr        On input, it points to destination ASCII string buffer; on output, it points
404                         to the next ASCII string next to it
405
406**/
407static
408VOID
409StrToAscii (
410  IN     CHAR16  *Str,
411  IN OUT CHAR8   **AsciiStr
412  )
413{
414  CHAR8  *Dest;
415
416  Dest = *AsciiStr;
417  while (!IS_NULL (*Str)) {
418    *(Dest++) = (CHAR8)*(Str++);
419  }
420
421  *Dest = 0;
422
423  //
424  // Return the string next to it
425  //
426  *AsciiStr = Dest + 1;
427}
428
429/**
430  Converts a generic text device path node to device path structure.
431
432  @param Type            The type of the device path node.
433  @param TextDeviceNode  The input text device path node.
434
435  @return A pointer to device path structure.
436**/
437static
438EFI_DEVICE_PATH_PROTOCOL *
439DevPathFromTextGenericPath (
440  IN UINT8   Type,
441  IN CHAR16  *TextDeviceNode
442  )
443{
444  EFI_DEVICE_PATH_PROTOCOL  *Node;
445  CHAR16                    *SubtypeStr;
446  CHAR16                    *DataStr;
447  UINTN                     DataLength;
448
449  SubtypeStr = GetNextParamStr (&TextDeviceNode);
450  DataStr    = GetNextParamStr (&TextDeviceNode);
451
452  if (DataStr == NULL) {
453    DataLength = 0;
454  } else {
455    DataLength = StrLen (DataStr) / 2;
456  }
457
458  Node = CreateDeviceNode (
459           Type,
460           (UINT8)Strtoi (SubtypeStr),
461           (UINT16)(sizeof (EFI_DEVICE_PATH_PROTOCOL) + DataLength)
462           );
463
464  StrHexToBytes (DataStr, DataLength * 2, (UINT8 *)(Node + 1), DataLength);
465  return Node;
466}
467
468/**
469  Converts a generic text device path node to device path structure.
470
471  @param TextDeviceNode  The input Text device path node.
472
473  @return A pointer to device path structure.
474
475**/
476static
477EFI_DEVICE_PATH_PROTOCOL *
478DevPathFromTextPath (
479  IN CHAR16  *TextDeviceNode
480  )
481{
482  CHAR16  *TypeStr;
483
484  TypeStr = GetNextParamStr (&TextDeviceNode);
485
486  return DevPathFromTextGenericPath ((UINT8)Strtoi (TypeStr), TextDeviceNode);
487}
488
489/**
490  Converts a generic hardware text device path node to Hardware device path structure.
491
492  @param TextDeviceNode  The input Text device path node.
493
494  @return A pointer to Hardware device path structure.
495
496**/
497static
498EFI_DEVICE_PATH_PROTOCOL *
499DevPathFromTextHardwarePath (
500  IN CHAR16  *TextDeviceNode
501  )
502{
503  return DevPathFromTextGenericPath (HARDWARE_DEVICE_PATH, TextDeviceNode);
504}
505
506/**
507  Converts a text device path node to Hardware PCI device path structure.
508
509  @param TextDeviceNode  The input Text device path node.
510
511  @return A pointer to Hardware PCI device path structure.
512
513**/
514static
515EFI_DEVICE_PATH_PROTOCOL *
516DevPathFromTextPci (
517  IN CHAR16  *TextDeviceNode
518  )
519{
520  CHAR16           *FunctionStr;
521  CHAR16           *DeviceStr;
522  PCI_DEVICE_PATH  *Pci;
523
524  DeviceStr   = GetNextParamStr (&TextDeviceNode);
525  FunctionStr = GetNextParamStr (&TextDeviceNode);
526  Pci         = (PCI_DEVICE_PATH *)CreateDeviceNode (
527                                     HARDWARE_DEVICE_PATH,
528                                     HW_PCI_DP,
529                                     (UINT16)sizeof (PCI_DEVICE_PATH)
530                                     );
531
532  Pci->Function = (UINT8)Strtoi (FunctionStr);
533  Pci->Device   = (UINT8)Strtoi (DeviceStr);
534
535  return (EFI_DEVICE_PATH_PROTOCOL *)Pci;
536}
537
538/**
539  Converts a text device path node to Hardware PC card device path structure.
540
541  @param TextDeviceNode  The input Text device path node.
542
543  @return A pointer to Hardware PC card device path structure.
544
545**/
546static
547EFI_DEVICE_PATH_PROTOCOL *
548DevPathFromTextPcCard (
549  IN CHAR16  *TextDeviceNode
550  )
551{
552  CHAR16              *FunctionNumberStr;
553  PCCARD_DEVICE_PATH  *Pccard;
554
555  FunctionNumberStr = GetNextParamStr (&TextDeviceNode);
556  Pccard            = (PCCARD_DEVICE_PATH *)CreateDeviceNode (
557                                              HARDWARE_DEVICE_PATH,
558                                              HW_PCCARD_DP,
559                                              (UINT16)sizeof (PCCARD_DEVICE_PATH)
560                                              );
561
562  Pccard->FunctionNumber = (UINT8)Strtoi (FunctionNumberStr);
563
564  return (EFI_DEVICE_PATH_PROTOCOL *)Pccard;
565}
566
567/**
568  Converts a text device path node to Hardware memory map device path structure.
569
570  @param TextDeviceNode  The input Text device path node.
571
572  @return A pointer to Hardware memory map device path structure.
573
574**/
575static
576EFI_DEVICE_PATH_PROTOCOL *
577DevPathFromTextMemoryMapped (
578  IN CHAR16  *TextDeviceNode
579  )
580{
581  CHAR16              *MemoryTypeStr;
582  CHAR16              *StartingAddressStr;
583  CHAR16              *EndingAddressStr;
584  MEMMAP_DEVICE_PATH  *MemMap;
585
586  MemoryTypeStr      = GetNextParamStr (&TextDeviceNode);
587  StartingAddressStr = GetNextParamStr (&TextDeviceNode);
588  EndingAddressStr   = GetNextParamStr (&TextDeviceNode);
589  MemMap             = (MEMMAP_DEVICE_PATH *)CreateDeviceNode (
590                                               HARDWARE_DEVICE_PATH,
591                                               HW_MEMMAP_DP,
592                                               (UINT16)sizeof (MEMMAP_DEVICE_PATH)
593                                               );
594
595  MemMap->MemoryType = (UINT32)Strtoi (MemoryTypeStr);
596  Strtoi64 (StartingAddressStr, &MemMap->StartingAddress);
597  Strtoi64 (EndingAddressStr, &MemMap->EndingAddress);
598
599  return (EFI_DEVICE_PATH_PROTOCOL *)MemMap;
600}
601
602/**
603  Converts a text device path node to Vendor device path structure based on the input Type
604  and SubType.
605
606  @param TextDeviceNode  The input Text device path node.
607  @param Type            The type of device path node.
608  @param SubType         The subtype of device path node.
609
610  @return A pointer to the newly-created Vendor device path structure.
611
612**/
613static
614EFI_DEVICE_PATH_PROTOCOL *
615ConvertFromTextVendor (
616  IN CHAR16  *TextDeviceNode,
617  IN UINT8   Type,
618  IN UINT8   SubType
619  )
620{
621  CHAR16              *GuidStr;
622  CHAR16              *DataStr;
623  UINTN               Length;
624  VENDOR_DEVICE_PATH  *Vendor;
625
626  GuidStr = GetNextParamStr (&TextDeviceNode);
627
628  DataStr = GetNextParamStr (&TextDeviceNode);
629  Length  = StrLen (DataStr);
630  //
631  // Two hex characters make up 1 buffer byte
632  //
633  Length = (Length + 1) / 2;
634
635  Vendor = (VENDOR_DEVICE_PATH *)CreateDeviceNode (
636                                   Type,
637                                   SubType,
638                                   (UINT16)(sizeof (VENDOR_DEVICE_PATH) + Length)
639                                   );
640
641  StrToGuid (GuidStr, &Vendor->Guid);
642  StrHexToBytes (DataStr, Length * 2, (UINT8 *)(Vendor + 1), Length);
643
644  return (EFI_DEVICE_PATH_PROTOCOL *)Vendor;
645}
646
647/**
648  Converts a text device path node to Vendor Hardware device path structure.
649
650  @param TextDeviceNode  The input Text device path node.
651
652  @return A pointer to the newly-created Vendor Hardware device path structure.
653
654**/
655static
656EFI_DEVICE_PATH_PROTOCOL *
657DevPathFromTextVenHw (
658  IN CHAR16  *TextDeviceNode
659  )
660{
661  return ConvertFromTextVendor (
662           TextDeviceNode,
663           HARDWARE_DEVICE_PATH,
664           HW_VENDOR_DP
665           );
666}
667
668/**
669  Converts a text device path node to Hardware Controller device path structure.
670
671  @param TextDeviceNode  The input Text device path node.
672
673  @return A pointer to the newly-created Hardware Controller device path structure.
674
675**/
676static
677EFI_DEVICE_PATH_PROTOCOL *
678DevPathFromTextCtrl (
679  IN CHAR16  *TextDeviceNode
680  )
681{
682  CHAR16                  *ControllerStr;
683  CONTROLLER_DEVICE_PATH  *Controller;
684
685  ControllerStr = GetNextParamStr (&TextDeviceNode);
686  Controller    = (CONTROLLER_DEVICE_PATH *)CreateDeviceNode (
687                                              HARDWARE_DEVICE_PATH,
688                                              HW_CONTROLLER_DP,
689                                              (UINT16)sizeof (CONTROLLER_DEVICE_PATH)
690                                              );
691  Controller->ControllerNumber = (UINT32)Strtoi (ControllerStr);
692
693  return (EFI_DEVICE_PATH_PROTOCOL *)Controller;
694}
695
696/**
697  Converts a text device path node to BMC device path structure.
698
699  @param TextDeviceNode  The input Text device path node.
700
701  @return A pointer to the newly-created BMC device path structure.
702
703**/
704static
705EFI_DEVICE_PATH_PROTOCOL *
706DevPathFromTextBmc (
707  IN CHAR16  *TextDeviceNode
708  )
709{
710  CHAR16           *InterfaceTypeStr;
711  CHAR16           *BaseAddressStr;
712  BMC_DEVICE_PATH  *BmcDp;
713
714  InterfaceTypeStr = GetNextParamStr (&TextDeviceNode);
715  BaseAddressStr   = GetNextParamStr (&TextDeviceNode);
716  BmcDp            = (BMC_DEVICE_PATH *)CreateDeviceNode (
717                                          HARDWARE_DEVICE_PATH,
718                                          HW_BMC_DP,
719                                          (UINT16)sizeof (BMC_DEVICE_PATH)
720                                          );
721
722  BmcDp->InterfaceType = (UINT8)Strtoi (InterfaceTypeStr);
723  WriteUnaligned64 (
724    (UINT64 *)(&BmcDp->BaseAddress),
725    StrHexToUint64 (BaseAddressStr)
726    );
727
728  return (EFI_DEVICE_PATH_PROTOCOL *)BmcDp;
729}
730
731/**
732  Converts a generic ACPI text device path node to ACPI device path structure.
733
734  @param TextDeviceNode  The input Text device path node.
735
736  @return A pointer to ACPI device path structure.
737
738**/
739static
740EFI_DEVICE_PATH_PROTOCOL *
741DevPathFromTextAcpiPath (
742  IN CHAR16  *TextDeviceNode
743  )
744{
745  return DevPathFromTextGenericPath (ACPI_DEVICE_PATH, TextDeviceNode);
746}
747
748/**
749  Converts a string to EisaId.
750
751  @param Text   The input string.
752
753  @return UINT32 EISA ID.
754**/
755static
756UINT32
757EisaIdFromText (
758  IN CHAR16  *Text
759  )
760{
761  return (((Text[0] - 'A' + 1) & 0x1f) << 10)
762         + (((Text[1] - 'A' + 1) & 0x1f) <<  5)
763         + (((Text[2] - 'A' + 1) & 0x1f) <<  0)
764         + (UINT32)(StrHexToUintn (&Text[3]) << 16)
765  ;
766}
767
768/**
769  Converts a text device path node to ACPI HID device path structure.
770
771  @param TextDeviceNode  The input Text device path node.
772
773  @return A pointer to the newly-created ACPI HID device path structure.
774
775**/
776static
777EFI_DEVICE_PATH_PROTOCOL *
778DevPathFromTextAcpi (
779  IN CHAR16  *TextDeviceNode
780  )
781{
782  CHAR16                *HIDStr;
783  CHAR16                *UIDStr;
784  ACPI_HID_DEVICE_PATH  *Acpi;
785
786  HIDStr = GetNextParamStr (&TextDeviceNode);
787  UIDStr = GetNextParamStr (&TextDeviceNode);
788  Acpi   = (ACPI_HID_DEVICE_PATH *)CreateDeviceNode (
789                                     ACPI_DEVICE_PATH,
790                                     ACPI_DP,
791                                     (UINT16)sizeof (ACPI_HID_DEVICE_PATH)
792                                     );
793
794  Acpi->HID = EisaIdFromText (HIDStr);
795  Acpi->UID = (UINT32)Strtoi (UIDStr);
796
797  return (EFI_DEVICE_PATH_PROTOCOL *)Acpi;
798}
799
800/**
801  Converts a text device path node to ACPI HID device path structure.
802
803  @param TextDeviceNode  The input Text device path node.
804  @param PnPId           The input plug and play identification.
805
806  @return A pointer to the newly-created ACPI HID device path structure.
807
808**/
809static
810EFI_DEVICE_PATH_PROTOCOL *
811ConvertFromTextAcpi (
812  IN CHAR16  *TextDeviceNode,
813  IN UINT32  PnPId
814  )
815{
816  CHAR16                *UIDStr;
817  ACPI_HID_DEVICE_PATH  *Acpi;
818
819  UIDStr = GetNextParamStr (&TextDeviceNode);
820  Acpi   = (ACPI_HID_DEVICE_PATH *)CreateDeviceNode (
821                                     ACPI_DEVICE_PATH,
822                                     ACPI_DP,
823                                     (UINT16)sizeof (ACPI_HID_DEVICE_PATH)
824                                     );
825
826  Acpi->HID = EFI_PNP_ID (PnPId);
827  Acpi->UID = (UINT32)Strtoi (UIDStr);
828
829  return (EFI_DEVICE_PATH_PROTOCOL *)Acpi;
830}
831
832/**
833  Converts a text device path node to PCI root device path structure.
834
835  @param TextDeviceNode  The input Text device path node.
836
837  @return A pointer to the newly-created PCI root device path structure.
838
839**/
840static
841EFI_DEVICE_PATH_PROTOCOL *
842DevPathFromTextPciRoot (
843  IN CHAR16  *TextDeviceNode
844  )
845{
846  return ConvertFromTextAcpi (TextDeviceNode, 0x0a03);
847}
848
849/**
850  Converts a text device path node to PCIE root device path structure.
851
852  @param TextDeviceNode  The input Text device path node.
853
854  @return A pointer to the newly-created PCIE root device path structure.
855
856**/
857static
858EFI_DEVICE_PATH_PROTOCOL *
859DevPathFromTextPcieRoot (
860  IN CHAR16  *TextDeviceNode
861  )
862{
863  return ConvertFromTextAcpi (TextDeviceNode, 0x0a08);
864}
865
866/**
867  Converts a text device path node to Floppy device path structure.
868
869  @param TextDeviceNode  The input Text device path node.
870
871  @return A pointer to the newly-created Floppy device path structure.
872
873**/
874static
875EFI_DEVICE_PATH_PROTOCOL *
876DevPathFromTextFloppy (
877  IN CHAR16  *TextDeviceNode
878  )
879{
880  return ConvertFromTextAcpi (TextDeviceNode, 0x0604);
881}
882
883/**
884  Converts a text device path node to Keyboard device path structure.
885
886  @param TextDeviceNode  The input Text device path node.
887
888  @return A pointer to the newly-created  Keyboard device path structure.
889
890**/
891static
892EFI_DEVICE_PATH_PROTOCOL *
893DevPathFromTextKeyboard (
894  IN CHAR16  *TextDeviceNode
895  )
896{
897  return ConvertFromTextAcpi (TextDeviceNode, 0x0301);
898}
899
900/**
901  Converts a text device path node to Serial device path structure.
902
903  @param TextDeviceNode  The input Text device path node.
904
905  @return A pointer to the newly-created Serial device path structure.
906
907**/
908static
909EFI_DEVICE_PATH_PROTOCOL *
910DevPathFromTextSerial (
911  IN CHAR16  *TextDeviceNode
912  )
913{
914  return ConvertFromTextAcpi (TextDeviceNode, 0x0501);
915}
916
917/**
918  Converts a text device path node to Parallel Port device path structure.
919
920  @param TextDeviceNode  The input Text device path node.
921
922  @return A pointer to the newly-created Parallel Port device path structure.
923
924**/
925static
926EFI_DEVICE_PATH_PROTOCOL *
927DevPathFromTextParallelPort (
928  IN CHAR16  *TextDeviceNode
929  )
930{
931  return ConvertFromTextAcpi (TextDeviceNode, 0x0401);
932}
933
934/**
935  Converts a text device path node to ACPI extension device path structure.
936
937  @param TextDeviceNode  The input Text device path node.
938
939  @return A pointer to the newly-created ACPI extension device path structure.
940
941**/
942static
943EFI_DEVICE_PATH_PROTOCOL *
944DevPathFromTextAcpiEx (
945  IN CHAR16  *TextDeviceNode
946  )
947{
948  CHAR16                         *HIDStr;
949  CHAR16                         *CIDStr;
950  CHAR16                         *UIDStr;
951  CHAR16                         *HIDSTRStr;
952  CHAR16                         *CIDSTRStr;
953  CHAR16                         *UIDSTRStr;
954  CHAR8                          *AsciiStr;
955  UINT16                         Length;
956  ACPI_EXTENDED_HID_DEVICE_PATH  *AcpiEx;
957
958  HIDStr    = GetNextParamStr (&TextDeviceNode);
959  CIDStr    = GetNextParamStr (&TextDeviceNode);
960  UIDStr    = GetNextParamStr (&TextDeviceNode);
961  HIDSTRStr = GetNextParamStr (&TextDeviceNode);
962  CIDSTRStr = GetNextParamStr (&TextDeviceNode);
963  UIDSTRStr = GetNextParamStr (&TextDeviceNode);
964
965  Length = (UINT16)(sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (HIDSTRStr) + 1);
966  Length = (UINT16)(Length + StrLen (UIDSTRStr) + 1);
967  Length = (UINT16)(Length + StrLen (CIDSTRStr) + 1);
968  AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *)CreateDeviceNode (
969                                              ACPI_DEVICE_PATH,
970                                              ACPI_EXTENDED_DP,
971                                              Length
972                                              );
973
974  AcpiEx->HID = EisaIdFromText (HIDStr);
975  AcpiEx->CID = EisaIdFromText (CIDStr);
976  AcpiEx->UID = (UINT32)Strtoi (UIDStr);
977
978  AsciiStr = (CHAR8 *)((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
979  StrToAscii (HIDSTRStr, &AsciiStr);
980  StrToAscii (UIDSTRStr, &AsciiStr);
981  StrToAscii (CIDSTRStr, &AsciiStr);
982
983  return (EFI_DEVICE_PATH_PROTOCOL *)AcpiEx;
984}
985
986/**
987  Converts a text device path node to ACPI extension device path structure.
988
989  @param TextDeviceNode  The input Text device path node.
990
991  @return A pointer to the newly-created ACPI extension device path structure.
992
993**/
994static
995EFI_DEVICE_PATH_PROTOCOL *
996DevPathFromTextAcpiExp (
997  IN CHAR16  *TextDeviceNode
998  )
999{
1000  CHAR16                         *HIDStr;
1001  CHAR16                         *CIDStr;
1002  CHAR16                         *UIDSTRStr;
1003  CHAR8                          *AsciiStr;
1004  UINT16                         Length;
1005  ACPI_EXTENDED_HID_DEVICE_PATH  *AcpiEx;
1006
1007  HIDStr    = GetNextParamStr (&TextDeviceNode);
1008  CIDStr    = GetNextParamStr (&TextDeviceNode);
1009  UIDSTRStr = GetNextParamStr (&TextDeviceNode);
1010  Length    = (UINT16)(sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (UIDSTRStr) + 3);
1011  AcpiEx    = (ACPI_EXTENDED_HID_DEVICE_PATH *)CreateDeviceNode (
1012                                                 ACPI_DEVICE_PATH,
1013                                                 ACPI_EXTENDED_DP,
1014                                                 Length
1015                                                 );
1016
1017  AcpiEx->HID = EisaIdFromText (HIDStr);
1018  //
1019  // According to UEFI spec, the CID parameter is optional and has a default value of 0.
1020  // So when the CID parameter is not specified or specified as 0 in the text device node.
1021  // Set the CID to 0 in the ACPI extension device path structure.
1022  //
1023  if ((*CIDStr == '\0') || (*CIDStr == '0')) {
1024    AcpiEx->CID = 0;
1025  } else {
1026    AcpiEx->CID = EisaIdFromText (CIDStr);
1027  }
1028
1029  AcpiEx->UID = 0;
1030
1031  AsciiStr = (CHAR8 *)((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
1032  //
1033  // HID string is NULL
1034  //
1035  *AsciiStr = '\0';
1036  //
1037  // Convert UID string
1038  //
1039  AsciiStr++;
1040  StrToAscii (UIDSTRStr, &AsciiStr);
1041  //
1042  // CID string is NULL
1043  //
1044  *AsciiStr = '\0';
1045
1046  return (EFI_DEVICE_PATH_PROTOCOL *)AcpiEx;
1047}
1048
1049/**
1050  Converts a text device path node to ACPI _ADR device path structure.
1051
1052  @param TextDeviceNode  The input Text device path node.
1053
1054  @return A pointer to the newly-created ACPI _ADR device path structure.
1055
1056**/
1057static
1058EFI_DEVICE_PATH_PROTOCOL *
1059DevPathFromTextAcpiAdr (
1060  IN CHAR16  *TextDeviceNode
1061  )
1062{
1063  CHAR16                *DisplayDeviceStr;
1064  ACPI_ADR_DEVICE_PATH  *AcpiAdr;
1065  UINTN                 Index;
1066  UINTN                 Length;
1067
1068  AcpiAdr = (ACPI_ADR_DEVICE_PATH *)CreateDeviceNode (
1069                                      ACPI_DEVICE_PATH,
1070                                      ACPI_ADR_DP,
1071                                      (UINT16)sizeof (ACPI_ADR_DEVICE_PATH)
1072                                      );
1073  ASSERT (AcpiAdr != NULL);
1074
1075  for (Index = 0; ; Index++) {
1076    DisplayDeviceStr = GetNextParamStr (&TextDeviceNode);
1077    if (IS_NULL (*DisplayDeviceStr)) {
1078      break;
1079    }
1080
1081    if (Index > 0) {
1082      Length  = DevicePathNodeLength (AcpiAdr);
1083      AcpiAdr = ReallocatePool (
1084                  Length,
1085                  Length + sizeof (UINT32),
1086                  AcpiAdr
1087                  );
1088      ASSERT (AcpiAdr != NULL);
1089      SetDevicePathNodeLength (AcpiAdr, Length + sizeof (UINT32));
1090    }
1091
1092    (&AcpiAdr->ADR)[Index] = (UINT32)Strtoi (DisplayDeviceStr);
1093  }
1094
1095  return (EFI_DEVICE_PATH_PROTOCOL *)AcpiAdr;
1096}
1097
1098/**
1099  Converts a generic messaging text device path node to messaging device path structure.
1100
1101  @param TextDeviceNode  The input Text device path node.
1102
1103  @return A pointer to messaging device path structure.
1104
1105**/
1106static
1107EFI_DEVICE_PATH_PROTOCOL *
1108DevPathFromTextMsg (
1109  IN CHAR16  *TextDeviceNode
1110  )
1111{
1112  return DevPathFromTextGenericPath (MESSAGING_DEVICE_PATH, TextDeviceNode);
1113}
1114
1115/**
1116  Converts a text device path node to Parallel Port device path structure.
1117
1118  @param TextDeviceNode  The input Text device path node.
1119
1120  @return A pointer to the newly-created Parallel Port device path structure.
1121
1122**/
1123static
1124EFI_DEVICE_PATH_PROTOCOL *
1125DevPathFromTextAta (
1126  IN CHAR16  *TextDeviceNode
1127  )
1128{
1129  CHAR16             *PrimarySecondaryStr;
1130  CHAR16             *SlaveMasterStr;
1131  CHAR16             *LunStr;
1132  ATAPI_DEVICE_PATH  *Atapi;
1133
1134  Atapi = (ATAPI_DEVICE_PATH *)CreateDeviceNode (
1135                                 MESSAGING_DEVICE_PATH,
1136                                 MSG_ATAPI_DP,
1137                                 (UINT16)sizeof (ATAPI_DEVICE_PATH)
1138                                 );
1139
1140  PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode);
1141  SlaveMasterStr      = GetNextParamStr (&TextDeviceNode);
1142  LunStr              = GetNextParamStr (&TextDeviceNode);
1143
1144  if (StrCmp (PrimarySecondaryStr, "Primary") == 0) {
1145    Atapi->PrimarySecondary = 0;
1146  } else if (StrCmp (PrimarySecondaryStr, "Secondary") == 0) {
1147    Atapi->PrimarySecondary = 1;
1148  } else {
1149    Atapi->PrimarySecondary = (UINT8)Strtoi (PrimarySecondaryStr);
1150  }
1151
1152  if (StrCmp (SlaveMasterStr, "Master") == 0) {
1153    Atapi->SlaveMaster = 0;
1154  } else if (StrCmp (SlaveMasterStr, "Slave") == 0) {
1155    Atapi->SlaveMaster = 1;
1156  } else {
1157    Atapi->SlaveMaster = (UINT8)Strtoi (SlaveMasterStr);
1158  }
1159
1160  Atapi->Lun = (UINT16)Strtoi (LunStr);
1161
1162  return (EFI_DEVICE_PATH_PROTOCOL *)Atapi;
1163}
1164
1165/**
1166  Converts a text device path node to SCSI device path structure.
1167
1168  @param TextDeviceNode  The input Text device path node.
1169
1170  @return A pointer to the newly-created SCSI device path structure.
1171
1172**/
1173static
1174EFI_DEVICE_PATH_PROTOCOL *
1175DevPathFromTextScsi (
1176  IN CHAR16  *TextDeviceNode
1177  )
1178{
1179  CHAR16            *PunStr;
1180  CHAR16            *LunStr;
1181  SCSI_DEVICE_PATH  *Scsi;
1182
1183  PunStr = GetNextParamStr (&TextDeviceNode);
1184  LunStr = GetNextParamStr (&TextDeviceNode);
1185  Scsi   = (SCSI_DEVICE_PATH *)CreateDeviceNode (
1186                                 MESSAGING_DEVICE_PATH,
1187                                 MSG_SCSI_DP,
1188                                 (UINT16)sizeof (SCSI_DEVICE_PATH)
1189                                 );
1190
1191  Scsi->Pun = (UINT16)Strtoi (PunStr);
1192  Scsi->Lun = (UINT16)Strtoi (LunStr);
1193
1194  return (EFI_DEVICE_PATH_PROTOCOL *)Scsi;
1195}
1196
1197/**
1198  Converts a text device path node to Fibre device path structure.
1199
1200  @param TextDeviceNode  The input Text device path node.
1201
1202  @return A pointer to the newly-created Fibre device path structure.
1203
1204**/
1205static
1206EFI_DEVICE_PATH_PROTOCOL *
1207DevPathFromTextFibre (
1208  IN CHAR16  *TextDeviceNode
1209  )
1210{
1211  CHAR16                    *WWNStr;
1212  CHAR16                    *LunStr;
1213  FIBRECHANNEL_DEVICE_PATH  *Fibre;
1214
1215  WWNStr = GetNextParamStr (&TextDeviceNode);
1216  LunStr = GetNextParamStr (&TextDeviceNode);
1217  Fibre  = (FIBRECHANNEL_DEVICE_PATH *)CreateDeviceNode (
1218                                         MESSAGING_DEVICE_PATH,
1219                                         MSG_FIBRECHANNEL_DP,
1220                                         (UINT16)sizeof (FIBRECHANNEL_DEVICE_PATH)
1221                                         );
1222
1223  Fibre->Reserved = 0;
1224  Strtoi64 (WWNStr, &Fibre->WWN);
1225  Strtoi64 (LunStr, &Fibre->Lun);
1226
1227  return (EFI_DEVICE_PATH_PROTOCOL *)Fibre;
1228}
1229
1230/**
1231  Converts a text device path node to FibreEx device path structure.
1232
1233  @param TextDeviceNode  The input Text device path node.
1234
1235  @return A pointer to the newly-created FibreEx device path structure.
1236
1237**/
1238static
1239EFI_DEVICE_PATH_PROTOCOL *
1240DevPathFromTextFibreEx (
1241  IN CHAR16  *TextDeviceNode
1242  )
1243{
1244  CHAR16                      *WWNStr;
1245  CHAR16                      *LunStr;
1246  FIBRECHANNELEX_DEVICE_PATH  *FibreEx;
1247
1248  WWNStr  = GetNextParamStr (&TextDeviceNode);
1249  LunStr  = GetNextParamStr (&TextDeviceNode);
1250  FibreEx = (FIBRECHANNELEX_DEVICE_PATH *)CreateDeviceNode (
1251                                            MESSAGING_DEVICE_PATH,
1252                                            MSG_FIBRECHANNELEX_DP,
1253                                            (UINT16)sizeof (FIBRECHANNELEX_DEVICE_PATH)
1254                                            );
1255
1256  FibreEx->Reserved = 0;
1257  Strtoi64 (WWNStr, (UINT64 *)(&FibreEx->WWN));
1258  Strtoi64 (LunStr, (UINT64 *)(&FibreEx->Lun));
1259
1260  *(UINT64 *)(&FibreEx->WWN) = SwapBytes64 (*(UINT64 *)(&FibreEx->WWN));
1261  *(UINT64 *)(&FibreEx->Lun) = SwapBytes64 (*(UINT64 *)(&FibreEx->Lun));
1262
1263  return (EFI_DEVICE_PATH_PROTOCOL *)FibreEx;
1264}
1265
1266/**
1267  Converts a text device path node to 1394 device path structure.
1268
1269  @param TextDeviceNode  The input Text device path node.
1270
1271  @return A pointer to the newly-created 1394 device path structure.
1272
1273**/
1274static
1275EFI_DEVICE_PATH_PROTOCOL *
1276DevPathFromText1394 (
1277  IN CHAR16  *TextDeviceNode
1278  )
1279{
1280  CHAR16             *GuidStr;
1281  F1394_DEVICE_PATH  *F1394DevPath;
1282
1283  GuidStr      = GetNextParamStr (&TextDeviceNode);
1284  F1394DevPath = (F1394_DEVICE_PATH *)CreateDeviceNode (
1285                                        MESSAGING_DEVICE_PATH,
1286                                        MSG_1394_DP,
1287                                        (UINT16)sizeof (F1394_DEVICE_PATH)
1288                                        );
1289
1290  F1394DevPath->Reserved = 0;
1291  F1394DevPath->Guid     = StrHexToUint64 (GuidStr);
1292
1293  return (EFI_DEVICE_PATH_PROTOCOL *)F1394DevPath;
1294}
1295
1296/**
1297  Converts a text device path node to USB device path structure.
1298
1299  @param TextDeviceNode  The input Text device path node.
1300
1301  @return A pointer to the newly-created USB device path structure.
1302
1303**/
1304static
1305EFI_DEVICE_PATH_PROTOCOL *
1306DevPathFromTextUsb (
1307  IN CHAR16  *TextDeviceNode
1308  )
1309{
1310  CHAR16           *PortStr;
1311  CHAR16           *InterfaceStr;
1312  USB_DEVICE_PATH  *Usb;
1313
1314  PortStr      = GetNextParamStr (&TextDeviceNode);
1315  InterfaceStr = GetNextParamStr (&TextDeviceNode);
1316  Usb          = (USB_DEVICE_PATH *)CreateDeviceNode (
1317                                      MESSAGING_DEVICE_PATH,
1318                                      MSG_USB_DP,
1319                                      (UINT16)sizeof (USB_DEVICE_PATH)
1320                                      );
1321
1322  Usb->ParentPortNumber = (UINT8)Strtoi (PortStr);
1323  Usb->InterfaceNumber  = (UINT8)Strtoi (InterfaceStr);
1324
1325  return (EFI_DEVICE_PATH_PROTOCOL *)Usb;
1326}
1327
1328/**
1329  Converts a text device path node to I20 device path structure.
1330
1331  @param TextDeviceNode  The input Text device path node.
1332
1333  @return A pointer to the newly-created I20 device path structure.
1334
1335**/
1336static
1337EFI_DEVICE_PATH_PROTOCOL *
1338DevPathFromTextI2O (
1339  IN CHAR16  *TextDeviceNode
1340  )
1341{
1342  CHAR16           *TIDStr;
1343  I2O_DEVICE_PATH  *I2ODevPath;
1344
1345  TIDStr     = GetNextParamStr (&TextDeviceNode);
1346  I2ODevPath = (I2O_DEVICE_PATH *)CreateDeviceNode (
1347                                    MESSAGING_DEVICE_PATH,
1348                                    MSG_I2O_DP,
1349                                    (UINT16)sizeof (I2O_DEVICE_PATH)
1350                                    );
1351
1352  I2ODevPath->Tid = (UINT32)Strtoi (TIDStr);
1353
1354  return (EFI_DEVICE_PATH_PROTOCOL *)I2ODevPath;
1355}
1356
1357/**
1358  Converts a text device path node to Infini Band device path structure.
1359
1360  @param TextDeviceNode  The input Text device path node.
1361
1362  @return A pointer to the newly-created Infini Band device path structure.
1363
1364**/
1365static
1366EFI_DEVICE_PATH_PROTOCOL *
1367DevPathFromTextInfiniband (
1368  IN CHAR16  *TextDeviceNode
1369  )
1370{
1371  CHAR16                  *FlagsStr;
1372  CHAR16                  *GuidStr;
1373  CHAR16                  *SidStr;
1374  CHAR16                  *TidStr;
1375  CHAR16                  *DidStr;
1376  INFINIBAND_DEVICE_PATH  *InfiniBand;
1377
1378  FlagsStr   = GetNextParamStr (&TextDeviceNode);
1379  GuidStr    = GetNextParamStr (&TextDeviceNode);
1380  SidStr     = GetNextParamStr (&TextDeviceNode);
1381  TidStr     = GetNextParamStr (&TextDeviceNode);
1382  DidStr     = GetNextParamStr (&TextDeviceNode);
1383  InfiniBand = (INFINIBAND_DEVICE_PATH *)CreateDeviceNode (
1384                                           MESSAGING_DEVICE_PATH,
1385                                           MSG_INFINIBAND_DP,
1386                                           (UINT16)sizeof (INFINIBAND_DEVICE_PATH)
1387                                           );
1388
1389  InfiniBand->ResourceFlags = (UINT32)Strtoi (FlagsStr);
1390  StrToGuid (GuidStr, (EFI_GUID *)InfiniBand->PortGid);
1391  Strtoi64 (SidStr, &InfiniBand->ServiceId);
1392  Strtoi64 (TidStr, &InfiniBand->TargetPortId);
1393  Strtoi64 (DidStr, &InfiniBand->DeviceId);
1394
1395  return (EFI_DEVICE_PATH_PROTOCOL *)InfiniBand;
1396}
1397
1398/**
1399  Converts a text device path node to Vendor-Defined Messaging device path structure.
1400
1401  @param TextDeviceNode  The input Text device path node.
1402
1403  @return A pointer to the newly-created Vendor-Defined Messaging device path structure.
1404
1405**/
1406static
1407EFI_DEVICE_PATH_PROTOCOL *
1408DevPathFromTextVenMsg (
1409  IN CHAR16  *TextDeviceNode
1410  )
1411{
1412  return ConvertFromTextVendor (
1413           TextDeviceNode,
1414           MESSAGING_DEVICE_PATH,
1415           MSG_VENDOR_DP
1416           );
1417}
1418
1419/**
1420  Converts a text device path node to Vendor defined PC-ANSI device path structure.
1421
1422  @param TextDeviceNode  The input Text device path node.
1423
1424  @return A pointer to the newly-created Vendor defined PC-ANSI device path structure.
1425
1426**/
1427static
1428EFI_DEVICE_PATH_PROTOCOL *
1429DevPathFromTextVenPcAnsi (
1430  IN CHAR16  *TextDeviceNode
1431  )
1432{
1433  VENDOR_DEVICE_PATH  *Vendor;
1434
1435  Vendor = (VENDOR_DEVICE_PATH *)CreateDeviceNode (
1436                                   MESSAGING_DEVICE_PATH,
1437                                   MSG_VENDOR_DP,
1438                                   (UINT16)sizeof (VENDOR_DEVICE_PATH)
1439                                   );
1440  CopyGuid (&Vendor->Guid, &gEfiPcAnsiGuid);
1441
1442  return (EFI_DEVICE_PATH_PROTOCOL *)Vendor;
1443}
1444
1445/**
1446  Converts a text device path node to Vendor defined VT100 device path structure.
1447
1448  @param TextDeviceNode  The input Text device path node.
1449
1450  @return A pointer to the newly-created Vendor defined VT100 device path structure.
1451
1452**/
1453static
1454EFI_DEVICE_PATH_PROTOCOL *
1455DevPathFromTextVenVt100 (
1456  IN CHAR16  *TextDeviceNode
1457  )
1458{
1459  VENDOR_DEVICE_PATH  *Vendor;
1460
1461  Vendor = (VENDOR_DEVICE_PATH *)CreateDeviceNode (
1462                                   MESSAGING_DEVICE_PATH,
1463                                   MSG_VENDOR_DP,
1464                                   (UINT16)sizeof (VENDOR_DEVICE_PATH)
1465                                   );
1466  CopyGuid (&Vendor->Guid, &gEfiVT100Guid);
1467
1468  return (EFI_DEVICE_PATH_PROTOCOL *)Vendor;
1469}
1470
1471/**
1472  Converts a text device path node to Vendor defined VT100 Plus device path structure.
1473
1474  @param TextDeviceNode  The input Text device path node.
1475
1476  @return A pointer to the newly-created Vendor defined VT100 Plus device path structure.
1477
1478**/
1479static
1480EFI_DEVICE_PATH_PROTOCOL *
1481DevPathFromTextVenVt100Plus (
1482  IN CHAR16  *TextDeviceNode
1483  )
1484{
1485  VENDOR_DEVICE_PATH  *Vendor;
1486
1487  Vendor = (VENDOR_DEVICE_PATH *)CreateDeviceNode (
1488                                   MESSAGING_DEVICE_PATH,
1489                                   MSG_VENDOR_DP,
1490                                   (UINT16)sizeof (VENDOR_DEVICE_PATH)
1491                                   );
1492  CopyGuid (&Vendor->Guid, &gEfiVT100PlusGuid);
1493
1494  return (EFI_DEVICE_PATH_PROTOCOL *)Vendor;
1495}
1496
1497/**
1498  Converts a text device path node to Vendor defined UTF8 device path structure.
1499
1500  @param TextDeviceNode  The input Text device path node.
1501
1502  @return A pointer to the newly-created Vendor defined UTF8 device path structure.
1503
1504**/
1505static
1506EFI_DEVICE_PATH_PROTOCOL *
1507DevPathFromTextVenUtf8 (
1508  IN CHAR16  *TextDeviceNode
1509  )
1510{
1511  VENDOR_DEVICE_PATH  *Vendor;
1512
1513  Vendor = (VENDOR_DEVICE_PATH *)CreateDeviceNode (
1514                                   MESSAGING_DEVICE_PATH,
1515                                   MSG_VENDOR_DP,
1516                                   (UINT16)sizeof (VENDOR_DEVICE_PATH)
1517                                   );
1518  CopyGuid (&Vendor->Guid, &gEfiVTUTF8Guid);
1519
1520  return (EFI_DEVICE_PATH_PROTOCOL *)Vendor;
1521}
1522
1523/**
1524  Converts a text device path node to UART Flow Control device path structure.
1525
1526  @param TextDeviceNode  The input Text device path node.
1527
1528  @return A pointer to the newly-created UART Flow Control device path structure.
1529
1530**/
1531static
1532EFI_DEVICE_PATH_PROTOCOL *
1533DevPathFromTextUartFlowCtrl (
1534  IN CHAR16  *TextDeviceNode
1535  )
1536{
1537  CHAR16                         *ValueStr;
1538  UART_FLOW_CONTROL_DEVICE_PATH  *UartFlowControl;
1539
1540  ValueStr        = GetNextParamStr (&TextDeviceNode);
1541  UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *)CreateDeviceNode (
1542                                                       MESSAGING_DEVICE_PATH,
1543                                                       MSG_VENDOR_DP,
1544                                                       (UINT16)sizeof (UART_FLOW_CONTROL_DEVICE_PATH)
1545                                                       );
1546
1547  CopyGuid (&UartFlowControl->Guid, &gEfiUartDevicePathGuid);
1548  if (StrCmp (ValueStr, "XonXoff") == 0) {
1549    UartFlowControl->FlowControlMap = 2;
1550  } else if (StrCmp (ValueStr, "Hardware") == 0) {
1551    UartFlowControl->FlowControlMap = 1;
1552  } else {
1553    UartFlowControl->FlowControlMap = 0;
1554  }
1555
1556  return (EFI_DEVICE_PATH_PROTOCOL *)UartFlowControl;
1557}
1558
1559/**
1560  Converts a text device path node to Serial Attached SCSI device path structure.
1561
1562  @param TextDeviceNode  The input Text device path node.
1563
1564  @return A pointer to the newly-created Serial Attached SCSI device path structure.
1565
1566**/
1567static
1568EFI_DEVICE_PATH_PROTOCOL *
1569DevPathFromTextSAS (
1570  IN CHAR16  *TextDeviceNode
1571  )
1572{
1573  CHAR16           *AddressStr;
1574  CHAR16           *LunStr;
1575  CHAR16           *RTPStr;
1576  CHAR16           *SASSATAStr;
1577  CHAR16           *LocationStr;
1578  CHAR16           *ConnectStr;
1579  CHAR16           *DriveBayStr;
1580  CHAR16           *ReservedStr;
1581  UINT16           Info;
1582  UINT16           Uint16;
1583  SAS_DEVICE_PATH  *Sas;
1584
1585  AddressStr  = GetNextParamStr (&TextDeviceNode);
1586  LunStr      = GetNextParamStr (&TextDeviceNode);
1587  RTPStr      = GetNextParamStr (&TextDeviceNode);
1588  SASSATAStr  = GetNextParamStr (&TextDeviceNode);
1589  LocationStr = GetNextParamStr (&TextDeviceNode);
1590  ConnectStr  = GetNextParamStr (&TextDeviceNode);
1591  DriveBayStr = GetNextParamStr (&TextDeviceNode);
1592  ReservedStr = GetNextParamStr (&TextDeviceNode);
1593  Sas         = (SAS_DEVICE_PATH *)CreateDeviceNode (
1594                                     MESSAGING_DEVICE_PATH,
1595                                     MSG_VENDOR_DP,
1596                                     (UINT16)sizeof (SAS_DEVICE_PATH)
1597                                     );
1598
1599  CopyGuid (&Sas->Guid, &gEfiSasDevicePathGuid);
1600  Strtoi64 (AddressStr, &Sas->SasAddress);
1601  Strtoi64 (LunStr, &Sas->Lun);
1602  Sas->RelativeTargetPort = (UINT16)Strtoi (RTPStr);
1603
1604  if (StrCmp (SASSATAStr, "NoTopology") == 0) {
1605    Info = 0x0;
1606  } else if ((StrCmp (SASSATAStr, "SATA") == 0) || (StrCmp (SASSATAStr, "SAS") == 0)) {
1607    Uint16 = (UINT16)Strtoi (DriveBayStr);
1608    if (Uint16 == 0) {
1609      Info = 0x1;
1610    } else {
1611      Info = (UINT16)(0x2 | ((Uint16 - 1) << 8));
1612    }
1613
1614    if (StrCmp (SASSATAStr, "SATA") == 0) {
1615      Info |= BIT4;
1616    }
1617
1618    //
1619    // Location is an integer between 0 and 1 or else
1620    // the keyword Internal (0) or External (1).
1621    //
1622    if (StrCmp (LocationStr, "External") == 0) {
1623      Uint16 = 1;
1624    } else if (StrCmp (LocationStr, "Internal") == 0) {
1625      Uint16 = 0;
1626    } else {
1627      Uint16 = ((UINT16)Strtoi (LocationStr) & BIT0);
1628    }
1629
1630    Info |= (Uint16 << 5);
1631
1632    //
1633    // Connect is an integer between 0 and 3 or else
1634    // the keyword Direct (0) or Expanded (1).
1635    //
1636    if (StrCmp (ConnectStr, "Expanded") == 0) {
1637      Uint16 = 1;
1638    } else if (StrCmp (ConnectStr, "Direct") == 0) {
1639      Uint16 = 0;
1640    } else {
1641      Uint16 = ((UINT16)Strtoi (ConnectStr) & (BIT0 | BIT1));
1642    }
1643
1644    Info |= (Uint16 << 6);
1645  } else {
1646    Info = (UINT16)Strtoi (SASSATAStr);
1647  }
1648
1649  Sas->DeviceTopology = Info;
1650  Sas->Reserved       = (UINT32)Strtoi (ReservedStr);
1651
1652  return (EFI_DEVICE_PATH_PROTOCOL *)Sas;
1653}
1654
1655/**
1656  Converts a text device path node to Serial Attached SCSI Ex device path structure.
1657
1658  @param TextDeviceNode  The input Text device path node.
1659
1660  @return A pointer to the newly-created Serial Attached SCSI Ex device path structure.
1661
1662**/
1663static
1664EFI_DEVICE_PATH_PROTOCOL *
1665DevPathFromTextSasEx (
1666  IN CHAR16  *TextDeviceNode
1667  )
1668{
1669  CHAR16             *AddressStr;
1670  CHAR16             *LunStr;
1671  CHAR16             *RTPStr;
1672  CHAR16             *SASSATAStr;
1673  CHAR16             *LocationStr;
1674  CHAR16             *ConnectStr;
1675  CHAR16             *DriveBayStr;
1676  UINT16             Info;
1677  UINT16             Uint16;
1678  UINT64             SasAddress;
1679  UINT64             Lun;
1680  SASEX_DEVICE_PATH  *SasEx;
1681
1682  AddressStr  = GetNextParamStr (&TextDeviceNode);
1683  LunStr      = GetNextParamStr (&TextDeviceNode);
1684  RTPStr      = GetNextParamStr (&TextDeviceNode);
1685  SASSATAStr  = GetNextParamStr (&TextDeviceNode);
1686  LocationStr = GetNextParamStr (&TextDeviceNode);
1687  ConnectStr  = GetNextParamStr (&TextDeviceNode);
1688  DriveBayStr = GetNextParamStr (&TextDeviceNode);
1689  SasEx       = (SASEX_DEVICE_PATH *)CreateDeviceNode (
1690                                       MESSAGING_DEVICE_PATH,
1691                                       MSG_SASEX_DP,
1692                                       (UINT16)sizeof (SASEX_DEVICE_PATH)
1693                                       );
1694
1695  Strtoi64 (AddressStr, &SasAddress);
1696  Strtoi64 (LunStr, &Lun);
1697  WriteUnaligned64 ((UINT64 *)&SasEx->SasAddress, SwapBytes64 (SasAddress));
1698  WriteUnaligned64 ((UINT64 *)&SasEx->Lun, SwapBytes64 (Lun));
1699  SasEx->RelativeTargetPort = (UINT16)Strtoi (RTPStr);
1700
1701  if (StrCmp (SASSATAStr, "NoTopology") == 0) {
1702    Info = 0x0;
1703  } else if ((StrCmp (SASSATAStr, "SATA") == 0) || (StrCmp (SASSATAStr, "SAS") == 0)) {
1704    Uint16 = (UINT16)Strtoi (DriveBayStr);
1705    if (Uint16 == 0) {
1706      Info = 0x1;
1707    } else {
1708      Info = (UINT16)(0x2 | ((Uint16 - 1) << 8));
1709    }
1710
1711    if (StrCmp (SASSATAStr, "SATA") == 0) {
1712      Info |= BIT4;
1713    }
1714
1715    //
1716    // Location is an integer between 0 and 1 or else
1717    // the keyword Internal (0) or External (1).
1718    //
1719    if (StrCmp (LocationStr, "External") == 0) {
1720      Uint16 = 1;
1721    } else if (StrCmp (LocationStr, "Internal") == 0) {
1722      Uint16 = 0;
1723    } else {
1724      Uint16 = ((UINT16)Strtoi (LocationStr) & BIT0);
1725    }
1726
1727    Info |= (Uint16 << 5);
1728
1729    //
1730    // Connect is an integer between 0 and 3 or else
1731    // the keyword Direct (0) or Expanded (1).
1732    //
1733    if (StrCmp (ConnectStr, "Expanded") == 0) {
1734      Uint16 = 1;
1735    } else if (StrCmp (ConnectStr, "Direct") == 0) {
1736      Uint16 = 0;
1737    } else {
1738      Uint16 = ((UINT16)Strtoi (ConnectStr) & (BIT0 | BIT1));
1739    }
1740
1741    Info |= (Uint16 << 6);
1742  } else {
1743    Info = (UINT16)Strtoi (SASSATAStr);
1744  }
1745
1746  SasEx->DeviceTopology = Info;
1747
1748  return (EFI_DEVICE_PATH_PROTOCOL *)SasEx;
1749}
1750
1751/**
1752  Converts a text device path node to NVM Express Namespace device path structure.
1753
1754  @param TextDeviceNode  The input Text device path node.
1755
1756  @return A pointer to the newly-created NVM Express Namespace device path structure.
1757
1758**/
1759static
1760EFI_DEVICE_PATH_PROTOCOL *
1761DevPathFromTextNVMe (
1762  IN CHAR16  *TextDeviceNode
1763  )
1764{
1765  CHAR16                      *NamespaceIdStr;
1766  CHAR16                      *NamespaceUuidStr;
1767  NVME_NAMESPACE_DEVICE_PATH  *Nvme;
1768  UINT8                       *Uuid;
1769  UINTN                       Index;
1770
1771  NamespaceIdStr   = GetNextParamStr (&TextDeviceNode);
1772  NamespaceUuidStr = GetNextParamStr (&TextDeviceNode);
1773  Nvme             = (NVME_NAMESPACE_DEVICE_PATH *)CreateDeviceNode (
1774                                                     MESSAGING_DEVICE_PATH,
1775                                                     MSG_NVME_NAMESPACE_DP,
1776                                                     (UINT16)sizeof (NVME_NAMESPACE_DEVICE_PATH)
1777                                                     );
1778
1779  Nvme->NamespaceId = (UINT32)Strtoi (NamespaceIdStr);
1780  Uuid              = (UINT8 *)&Nvme->NamespaceUuid;
1781
1782  Index = sizeof (Nvme->NamespaceUuid) / sizeof (UINT8);
1783  while (Index-- != 0) {
1784    Uuid[Index] = (UINT8)StrHexToUintn (SplitStr (&NamespaceUuidStr, '-'));
1785  }
1786
1787  return (EFI_DEVICE_PATH_PROTOCOL *)Nvme;
1788}
1789
1790/**
1791  Converts a text device path node to UFS device path structure.
1792
1793  @param TextDeviceNode  The input Text device path node.
1794
1795  @return A pointer to the newly-created UFS device path structure.
1796
1797**/
1798static
1799EFI_DEVICE_PATH_PROTOCOL *
1800DevPathFromTextUfs (
1801  IN CHAR16  *TextDeviceNode
1802  )
1803{
1804  CHAR16           *PunStr;
1805  CHAR16           *LunStr;
1806  UFS_DEVICE_PATH  *Ufs;
1807
1808  PunStr = GetNextParamStr (&TextDeviceNode);
1809  LunStr = GetNextParamStr (&TextDeviceNode);
1810  Ufs    = (UFS_DEVICE_PATH *)CreateDeviceNode (
1811                                MESSAGING_DEVICE_PATH,
1812                                MSG_UFS_DP,
1813                                (UINT16)sizeof (UFS_DEVICE_PATH)
1814                                );
1815
1816  Ufs->Pun = (UINT8)Strtoi (PunStr);
1817  Ufs->Lun = (UINT8)Strtoi (LunStr);
1818
1819  return (EFI_DEVICE_PATH_PROTOCOL *)Ufs;
1820}
1821
1822/**
1823  Converts a text device path node to SD (Secure Digital) device path structure.
1824
1825  @param TextDeviceNode  The input Text device path node.
1826
1827  @return A pointer to the newly-created SD device path structure.
1828
1829**/
1830static
1831EFI_DEVICE_PATH_PROTOCOL *
1832DevPathFromTextSd (
1833  IN CHAR16  *TextDeviceNode
1834  )
1835{
1836  CHAR16          *SlotNumberStr;
1837  SD_DEVICE_PATH  *Sd;
1838
1839  SlotNumberStr = GetNextParamStr (&TextDeviceNode);
1840  Sd            = (SD_DEVICE_PATH *)CreateDeviceNode (
1841                                      MESSAGING_DEVICE_PATH,
1842                                      MSG_SD_DP,
1843                                      (UINT16)sizeof (SD_DEVICE_PATH)
1844                                      );
1845
1846  Sd->SlotNumber = (UINT8)Strtoi (SlotNumberStr);
1847
1848  return (EFI_DEVICE_PATH_PROTOCOL *)Sd;
1849}
1850
1851/**
1852  Converts a text device path node to EMMC (Embedded MMC) device path structure.
1853
1854  @param TextDeviceNode  The input Text device path node.
1855
1856  @return A pointer to the newly-created EMMC device path structure.
1857
1858**/
1859static
1860EFI_DEVICE_PATH_PROTOCOL *
1861DevPathFromTextEmmc (
1862  IN CHAR16  *TextDeviceNode
1863  )
1864{
1865  CHAR16            *SlotNumberStr;
1866  EMMC_DEVICE_PATH  *Emmc;
1867
1868  SlotNumberStr = GetNextParamStr (&TextDeviceNode);
1869  Emmc          = (EMMC_DEVICE_PATH *)CreateDeviceNode (
1870                                        MESSAGING_DEVICE_PATH,
1871                                        MSG_EMMC_DP,
1872                                        (UINT16)sizeof (EMMC_DEVICE_PATH)
1873                                        );
1874
1875  Emmc->SlotNumber = (UINT8)Strtoi (SlotNumberStr);
1876
1877  return (EFI_DEVICE_PATH_PROTOCOL *)Emmc;
1878}
1879
1880/**
1881  Converts a text device path node to Debug Port device path structure.
1882
1883  @param TextDeviceNode  The input Text device path node.
1884
1885  @return A pointer to the newly-created Debug Port device path structure.
1886
1887**/
1888static
1889EFI_DEVICE_PATH_PROTOCOL *
1890DevPathFromTextDebugPort (
1891  IN CHAR16  *TextDeviceNode
1892  )
1893{
1894  VENDOR_DEVICE_PATH  *Vend;
1895
1896  Vend = (VENDOR_DEVICE_PATH *)CreateDeviceNode (
1897                                 MESSAGING_DEVICE_PATH,
1898                                 MSG_VENDOR_DP,
1899                                 (UINT16)sizeof (VENDOR_DEVICE_PATH)
1900                                 );
1901
1902  CopyGuid (&Vend->Guid, &gEfiDebugPortProtocolGuid);
1903
1904  return (EFI_DEVICE_PATH_PROTOCOL *)Vend;
1905}
1906
1907/**
1908  Converts a text device path node to MAC device path structure.
1909
1910  @param TextDeviceNode  The input Text device path node.
1911
1912  @return A pointer to the newly-created MAC device path structure.
1913
1914**/
1915static
1916EFI_DEVICE_PATH_PROTOCOL *
1917DevPathFromTextMAC (
1918  IN CHAR16  *TextDeviceNode
1919  )
1920{
1921  CHAR16                *AddressStr;
1922  CHAR16                *IfTypeStr;
1923  UINTN                 Length;
1924  MAC_ADDR_DEVICE_PATH  *MACDevPath;
1925
1926  AddressStr = GetNextParamStr (&TextDeviceNode);
1927  IfTypeStr  = GetNextParamStr (&TextDeviceNode);
1928  MACDevPath = (MAC_ADDR_DEVICE_PATH *)CreateDeviceNode (
1929                                         MESSAGING_DEVICE_PATH,
1930                                         MSG_MAC_ADDR_DP,
1931                                         (UINT16)sizeof (MAC_ADDR_DEVICE_PATH)
1932                                         );
1933
1934  MACDevPath->IfType = (UINT8)Strtoi (IfTypeStr);
1935
1936  Length = sizeof (EFI_MAC_ADDRESS);
1937  if ((MACDevPath->IfType == 0x01) || (MACDevPath->IfType == 0x00)) {
1938    Length = 6;
1939  }
1940
1941  StrHexToBytes (AddressStr, Length * 2, MACDevPath->MacAddress.Addr, Length);
1942
1943  return (EFI_DEVICE_PATH_PROTOCOL *)MACDevPath;
1944}
1945
1946/**
1947  Converts a text format to the network protocol ID.
1948
1949  @param Text  String of protocol field.
1950
1951  @return Network protocol ID .
1952
1953**/
1954static
1955UINTN
1956NetworkProtocolFromText (
1957  IN CHAR16  *Text
1958  )
1959{
1960  if (StrCmp (Text, "UDP") == 0) {
1961    return RFC_1700_UDP_PROTOCOL;
1962  }
1963
1964  if (StrCmp (Text, "TCP") == 0) {
1965    return RFC_1700_TCP_PROTOCOL;
1966  }
1967
1968  return Strtoi (Text);
1969}
1970
1971/**
1972  Converts a text device path node to IPV4 device path structure.
1973
1974  @param TextDeviceNode  The input Text device path node.
1975
1976  @return A pointer to the newly-created IPV4 device path structure.
1977
1978**/
1979static
1980EFI_DEVICE_PATH_PROTOCOL *
1981DevPathFromTextIPv4 (
1982  IN CHAR16  *TextDeviceNode
1983  )
1984{
1985  CHAR16            *RemoteIPStr;
1986  CHAR16            *ProtocolStr;
1987  CHAR16            *TypeStr;
1988  CHAR16            *LocalIPStr;
1989  CHAR16            *GatewayIPStr;
1990  CHAR16            *SubnetMaskStr;
1991  IPv4_DEVICE_PATH  *IPv4;
1992
1993  RemoteIPStr   = GetNextParamStr (&TextDeviceNode);
1994  ProtocolStr   = GetNextParamStr (&TextDeviceNode);
1995  TypeStr       = GetNextParamStr (&TextDeviceNode);
1996  LocalIPStr    = GetNextParamStr (&TextDeviceNode);
1997  GatewayIPStr  = GetNextParamStr (&TextDeviceNode);
1998  SubnetMaskStr = GetNextParamStr (&TextDeviceNode);
1999  IPv4          = (IPv4_DEVICE_PATH *)CreateDeviceNode (
2000                                        MESSAGING_DEVICE_PATH,
2001                                        MSG_IPv4_DP,
2002                                        (UINT16)sizeof (IPv4_DEVICE_PATH)
2003                                        );
2004
2005  StrToIpv4Address (RemoteIPStr, NULL, &IPv4->RemoteIpAddress, NULL);
2006  IPv4->Protocol = (UINT16)NetworkProtocolFromText (ProtocolStr);
2007  if (StrCmp (TypeStr, "Static") == 0) {
2008    IPv4->StaticIpAddress = TRUE;
2009  } else {
2010    IPv4->StaticIpAddress = FALSE;
2011  }
2012
2013  StrToIpv4Address (LocalIPStr, NULL, &IPv4->LocalIpAddress, NULL);
2014  if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*SubnetMaskStr)) {
2015    StrToIpv4Address (GatewayIPStr, NULL, &IPv4->GatewayIpAddress, NULL);
2016    StrToIpv4Address (SubnetMaskStr, NULL, &IPv4->SubnetMask, NULL);
2017  } else {
2018    ZeroMem (&IPv4->GatewayIpAddress, sizeof (IPv4->GatewayIpAddress));
2019    ZeroMem (&IPv4->SubnetMask, sizeof (IPv4->SubnetMask));
2020  }
2021
2022  IPv4->LocalPort  = 0;
2023  IPv4->RemotePort = 0;
2024
2025  return (EFI_DEVICE_PATH_PROTOCOL *)IPv4;
2026}
2027
2028/**
2029  Converts a text device path node to IPV6 device path structure.
2030
2031  @param TextDeviceNode  The input Text device path node.
2032
2033  @return A pointer to the newly-created IPV6 device path structure.
2034
2035**/
2036static
2037EFI_DEVICE_PATH_PROTOCOL *
2038DevPathFromTextIPv6 (
2039  IN CHAR16  *TextDeviceNode
2040  )
2041{
2042  CHAR16            *RemoteIPStr;
2043  CHAR16            *ProtocolStr;
2044  CHAR16            *TypeStr;
2045  CHAR16            *LocalIPStr;
2046  CHAR16            *GatewayIPStr;
2047  CHAR16            *PrefixLengthStr;
2048  IPv6_DEVICE_PATH  *IPv6;
2049
2050  RemoteIPStr     = GetNextParamStr (&TextDeviceNode);
2051  ProtocolStr     = GetNextParamStr (&TextDeviceNode);
2052  TypeStr         = GetNextParamStr (&TextDeviceNode);
2053  LocalIPStr      = GetNextParamStr (&TextDeviceNode);
2054  PrefixLengthStr = GetNextParamStr (&TextDeviceNode);
2055  GatewayIPStr    = GetNextParamStr (&TextDeviceNode);
2056  IPv6            = (IPv6_DEVICE_PATH *)CreateDeviceNode (
2057                                          MESSAGING_DEVICE_PATH,
2058                                          MSG_IPv6_DP,
2059                                          (UINT16)sizeof (IPv6_DEVICE_PATH)
2060                                          );
2061
2062  StrToIpv6Address (RemoteIPStr, NULL, &IPv6->RemoteIpAddress, NULL);
2063  IPv6->Protocol = (UINT16)NetworkProtocolFromText (ProtocolStr);
2064  if (StrCmp (TypeStr, "Static") == 0) {
2065    IPv6->IpAddressOrigin = 0;
2066  } else if (StrCmp (TypeStr, "StatelessAutoConfigure") == 0) {
2067    IPv6->IpAddressOrigin = 1;
2068  } else {
2069    IPv6->IpAddressOrigin = 2;
2070  }
2071
2072  StrToIpv6Address (LocalIPStr, NULL, &IPv6->LocalIpAddress, NULL);
2073  if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*PrefixLengthStr)) {
2074    StrToIpv6Address (GatewayIPStr, NULL, &IPv6->GatewayIpAddress, NULL);
2075    IPv6->PrefixLength = (UINT8)Strtoi (PrefixLengthStr);
2076  } else {
2077    ZeroMem (&IPv6->GatewayIpAddress, sizeof (IPv6->GatewayIpAddress));
2078    IPv6->PrefixLength = 0;
2079  }
2080
2081  IPv6->LocalPort  = 0;
2082  IPv6->RemotePort = 0;
2083
2084  return (EFI_DEVICE_PATH_PROTOCOL *)IPv6;
2085}
2086
2087/**
2088  Converts a text device path node to UART device path structure.
2089
2090  @param TextDeviceNode  The input Text device path node.
2091
2092  @return A pointer to the newly-created UART device path structure.
2093
2094**/
2095static
2096EFI_DEVICE_PATH_PROTOCOL *
2097DevPathFromTextUart (
2098  IN CHAR16  *TextDeviceNode
2099  )
2100{
2101  CHAR16            *BaudStr;
2102  CHAR16            *DataBitsStr;
2103  CHAR16            *ParityStr;
2104  CHAR16            *StopBitsStr;
2105  UART_DEVICE_PATH  *Uart;
2106
2107  BaudStr     = GetNextParamStr (&TextDeviceNode);
2108  DataBitsStr = GetNextParamStr (&TextDeviceNode);
2109  ParityStr   = GetNextParamStr (&TextDeviceNode);
2110  StopBitsStr = GetNextParamStr (&TextDeviceNode);
2111  Uart        = (UART_DEVICE_PATH *)CreateDeviceNode (
2112                                      MESSAGING_DEVICE_PATH,
2113                                      MSG_UART_DP,
2114                                      (UINT16)sizeof (UART_DEVICE_PATH)
2115                                      );
2116
2117  if (StrCmp (BaudStr, "DEFAULT") == 0) {
2118    Uart->BaudRate = 115200;
2119  } else {
2120    Strtoi64 (BaudStr, &Uart->BaudRate);
2121  }
2122
2123  Uart->DataBits = (UINT8)((StrCmp (DataBitsStr, "DEFAULT") == 0) ? 8 : Strtoi (DataBitsStr));
2124  switch (*ParityStr) {
2125    case 'D':
2126      Uart->Parity = 0;
2127      break;
2128
2129    case 'N':
2130      Uart->Parity = 1;
2131      break;
2132
2133    case 'E':
2134      Uart->Parity = 2;
2135      break;
2136
2137    case 'O':
2138      Uart->Parity = 3;
2139      break;
2140
2141    case 'M':
2142      Uart->Parity = 4;
2143      break;
2144
2145    case 'S':
2146      Uart->Parity = 5;
2147      break;
2148
2149    default:
2150      Uart->Parity = (UINT8)Strtoi (ParityStr);
2151      break;
2152  }
2153
2154  if (StrCmp (StopBitsStr, "D") == 0) {
2155    Uart->StopBits = (UINT8)0;
2156  } else if (StrCmp (StopBitsStr, "1") == 0) {
2157    Uart->StopBits = (UINT8)1;
2158  } else if (StrCmp (StopBitsStr, "1.5") == 0) {
2159    Uart->StopBits = (UINT8)2;
2160  } else if (StrCmp (StopBitsStr, "2") == 0) {
2161    Uart->StopBits = (UINT8)3;
2162  } else {
2163    Uart->StopBits = (UINT8)Strtoi (StopBitsStr);
2164  }
2165
2166  return (EFI_DEVICE_PATH_PROTOCOL *)Uart;
2167}
2168
2169/**
2170  Converts a text device path node to USB class device path structure.
2171
2172  @param TextDeviceNode  The input Text device path node.
2173  @param UsbClassText    A pointer to USB_CLASS_TEXT structure to be integrated to USB Class Text.
2174
2175  @return A pointer to the newly-created USB class device path structure.
2176
2177**/
2178static
2179EFI_DEVICE_PATH_PROTOCOL *
2180ConvertFromTextUsbClass (
2181  IN CHAR16          *TextDeviceNode,
2182  IN USB_CLASS_TEXT  *UsbClassText
2183  )
2184{
2185  CHAR16                 *VIDStr;
2186  CHAR16                 *PIDStr;
2187  CHAR16                 *ClassStr;
2188  CHAR16                 *SubClassStr;
2189  CHAR16                 *ProtocolStr;
2190  USB_CLASS_DEVICE_PATH  *UsbClass;
2191
2192  UsbClass = (USB_CLASS_DEVICE_PATH *)CreateDeviceNode (
2193                                        MESSAGING_DEVICE_PATH,
2194                                        MSG_USB_CLASS_DP,
2195                                        (UINT16)sizeof (USB_CLASS_DEVICE_PATH)
2196                                        );
2197
2198  VIDStr = GetNextParamStr (&TextDeviceNode);
2199  PIDStr = GetNextParamStr (&TextDeviceNode);
2200  if (UsbClassText->ClassExist) {
2201    ClassStr = GetNextParamStr (&TextDeviceNode);
2202    if (*ClassStr == '\0') {
2203      UsbClass->DeviceClass = 0xFF;
2204    } else {
2205      UsbClass->DeviceClass = (UINT8)Strtoi (ClassStr);
2206    }
2207  } else {
2208    UsbClass->DeviceClass = UsbClassText->Class;
2209  }
2210
2211  if (UsbClassText->SubClassExist) {
2212    SubClassStr = GetNextParamStr (&TextDeviceNode);
2213    if (*SubClassStr == '\0') {
2214      UsbClass->DeviceSubClass = 0xFF;
2215    } else {
2216      UsbClass->DeviceSubClass = (UINT8)Strtoi (SubClassStr);
2217    }
2218  } else {
2219    UsbClass->DeviceSubClass = UsbClassText->SubClass;
2220  }
2221
2222  ProtocolStr = GetNextParamStr (&TextDeviceNode);
2223
2224  if (*VIDStr == '\0') {
2225    UsbClass->VendorId = 0xFFFF;
2226  } else {
2227    UsbClass->VendorId = (UINT16)Strtoi (VIDStr);
2228  }
2229
2230  if (*PIDStr == '\0') {
2231    UsbClass->ProductId = 0xFFFF;
2232  } else {
2233    UsbClass->ProductId = (UINT16)Strtoi (PIDStr);
2234  }
2235
2236  if (*ProtocolStr == '\0') {
2237    UsbClass->DeviceProtocol = 0xFF;
2238  } else {
2239    UsbClass->DeviceProtocol = (UINT8)Strtoi (ProtocolStr);
2240  }
2241
2242  return (EFI_DEVICE_PATH_PROTOCOL *)UsbClass;
2243}
2244
2245/**
2246  Converts a text device path node to USB class device path structure.
2247
2248  @param TextDeviceNode  The input Text device path node.
2249
2250  @return A pointer to the newly-created USB class device path structure.
2251
2252**/
2253static
2254EFI_DEVICE_PATH_PROTOCOL *
2255DevPathFromTextUsbClass (
2256  IN CHAR16  *TextDeviceNode
2257  )
2258{
2259  USB_CLASS_TEXT  UsbClassText;
2260
2261  UsbClassText.ClassExist    = TRUE;
2262  UsbClassText.SubClassExist = TRUE;
2263
2264  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2265}
2266
2267/**
2268  Converts a text device path node to USB audio device path structure.
2269
2270  @param TextDeviceNode  The input Text device path node.
2271
2272  @return A pointer to the newly-created USB audio device path structure.
2273
2274**/
2275static
2276EFI_DEVICE_PATH_PROTOCOL *
2277DevPathFromTextUsbAudio (
2278  IN CHAR16  *TextDeviceNode
2279  )
2280{
2281  USB_CLASS_TEXT  UsbClassText;
2282
2283  UsbClassText.ClassExist    = FALSE;
2284  UsbClassText.Class         = USB_CLASS_AUDIO;
2285  UsbClassText.SubClassExist = TRUE;
2286
2287  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2288}
2289
2290/**
2291  Converts a text device path node to USB CDC Control device path structure.
2292
2293  @param TextDeviceNode  The input Text device path node.
2294
2295  @return A pointer to the newly-created USB CDC Control device path structure.
2296
2297**/
2298static
2299EFI_DEVICE_PATH_PROTOCOL *
2300DevPathFromTextUsbCDCControl (
2301  IN CHAR16  *TextDeviceNode
2302  )
2303{
2304  USB_CLASS_TEXT  UsbClassText;
2305
2306  UsbClassText.ClassExist    = FALSE;
2307  UsbClassText.Class         = USB_CLASS_CDCCONTROL;
2308  UsbClassText.SubClassExist = TRUE;
2309
2310  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2311}
2312
2313/**
2314  Converts a text device path node to USB HID device path structure.
2315
2316  @param TextDeviceNode  The input Text device path node.
2317
2318  @return A pointer to the newly-created USB HID device path structure.
2319
2320**/
2321static
2322EFI_DEVICE_PATH_PROTOCOL *
2323DevPathFromTextUsbHID (
2324  IN CHAR16  *TextDeviceNode
2325  )
2326{
2327  USB_CLASS_TEXT  UsbClassText;
2328
2329  UsbClassText.ClassExist    = FALSE;
2330  UsbClassText.Class         = USB_CLASS_HID;
2331  UsbClassText.SubClassExist = TRUE;
2332
2333  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2334}
2335
2336/**
2337  Converts a text device path node to USB Image device path structure.
2338
2339  @param TextDeviceNode  The input Text device path node.
2340
2341  @return A pointer to the newly-created USB Image device path structure.
2342
2343**/
2344static
2345EFI_DEVICE_PATH_PROTOCOL *
2346DevPathFromTextUsbImage (
2347  IN CHAR16  *TextDeviceNode
2348  )
2349{
2350  USB_CLASS_TEXT  UsbClassText;
2351
2352  UsbClassText.ClassExist    = FALSE;
2353  UsbClassText.Class         = USB_CLASS_IMAGE;
2354  UsbClassText.SubClassExist = TRUE;
2355
2356  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2357}
2358
2359/**
2360  Converts a text device path node to USB Print device path structure.
2361
2362  @param TextDeviceNode  The input Text device path node.
2363
2364  @return A pointer to the newly-created USB Print device path structure.
2365
2366**/
2367static
2368EFI_DEVICE_PATH_PROTOCOL *
2369DevPathFromTextUsbPrinter (
2370  IN CHAR16  *TextDeviceNode
2371  )
2372{
2373  USB_CLASS_TEXT  UsbClassText;
2374
2375  UsbClassText.ClassExist    = FALSE;
2376  UsbClassText.Class         = USB_CLASS_PRINTER;
2377  UsbClassText.SubClassExist = TRUE;
2378
2379  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2380}
2381
2382/**
2383  Converts a text device path node to USB mass storage device path structure.
2384
2385  @param TextDeviceNode  The input Text device path node.
2386
2387  @return A pointer to the newly-created USB mass storage device path structure.
2388
2389**/
2390static
2391EFI_DEVICE_PATH_PROTOCOL *
2392DevPathFromTextUsbMassStorage (
2393  IN CHAR16  *TextDeviceNode
2394  )
2395{
2396  USB_CLASS_TEXT  UsbClassText;
2397
2398  UsbClassText.ClassExist    = FALSE;
2399  UsbClassText.Class         = USB_CLASS_MASS_STORAGE;
2400  UsbClassText.SubClassExist = TRUE;
2401
2402  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2403}
2404
2405/**
2406  Converts a text device path node to USB HUB device path structure.
2407
2408  @param TextDeviceNode  The input Text device path node.
2409
2410  @return A pointer to the newly-created USB HUB device path structure.
2411
2412**/
2413static
2414EFI_DEVICE_PATH_PROTOCOL *
2415DevPathFromTextUsbHub (
2416  IN CHAR16  *TextDeviceNode
2417  )
2418{
2419  USB_CLASS_TEXT  UsbClassText;
2420
2421  UsbClassText.ClassExist    = FALSE;
2422  UsbClassText.Class         = USB_CLASS_HUB;
2423  UsbClassText.SubClassExist = TRUE;
2424
2425  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2426}
2427
2428/**
2429  Converts a text device path node to USB CDC data device path structure.
2430
2431  @param TextDeviceNode  The input Text device path node.
2432
2433  @return A pointer to the newly-created USB CDC data device path structure.
2434
2435**/
2436static
2437EFI_DEVICE_PATH_PROTOCOL *
2438DevPathFromTextUsbCDCData (
2439  IN CHAR16  *TextDeviceNode
2440  )
2441{
2442  USB_CLASS_TEXT  UsbClassText;
2443
2444  UsbClassText.ClassExist    = FALSE;
2445  UsbClassText.Class         = USB_CLASS_CDCDATA;
2446  UsbClassText.SubClassExist = TRUE;
2447
2448  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2449}
2450
2451/**
2452  Converts a text device path node to USB smart card device path structure.
2453
2454  @param TextDeviceNode  The input Text device path node.
2455
2456  @return A pointer to the newly-created USB smart card device path structure.
2457
2458**/
2459static
2460EFI_DEVICE_PATH_PROTOCOL *
2461DevPathFromTextUsbSmartCard (
2462  IN CHAR16  *TextDeviceNode
2463  )
2464{
2465  USB_CLASS_TEXT  UsbClassText;
2466
2467  UsbClassText.ClassExist    = FALSE;
2468  UsbClassText.Class         = USB_CLASS_SMART_CARD;
2469  UsbClassText.SubClassExist = TRUE;
2470
2471  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2472}
2473
2474/**
2475  Converts a text device path node to USB video device path structure.
2476
2477  @param TextDeviceNode  The input Text device path node.
2478
2479  @return A pointer to the newly-created USB video device path structure.
2480
2481**/
2482static
2483EFI_DEVICE_PATH_PROTOCOL *
2484DevPathFromTextUsbVideo (
2485  IN CHAR16  *TextDeviceNode
2486  )
2487{
2488  USB_CLASS_TEXT  UsbClassText;
2489
2490  UsbClassText.ClassExist    = FALSE;
2491  UsbClassText.Class         = USB_CLASS_VIDEO;
2492  UsbClassText.SubClassExist = TRUE;
2493
2494  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2495}
2496
2497/**
2498  Converts a text device path node to USB diagnostic device path structure.
2499
2500  @param TextDeviceNode  The input Text device path node.
2501
2502  @return A pointer to the newly-created USB diagnostic device path structure.
2503
2504**/
2505static
2506EFI_DEVICE_PATH_PROTOCOL *
2507DevPathFromTextUsbDiagnostic (
2508  IN CHAR16  *TextDeviceNode
2509  )
2510{
2511  USB_CLASS_TEXT  UsbClassText;
2512
2513  UsbClassText.ClassExist    = FALSE;
2514  UsbClassText.Class         = USB_CLASS_DIAGNOSTIC;
2515  UsbClassText.SubClassExist = TRUE;
2516
2517  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2518}
2519
2520/**
2521  Converts a text device path node to USB wireless device path structure.
2522
2523  @param TextDeviceNode  The input Text device path node.
2524
2525  @return A pointer to the newly-created USB wireless device path structure.
2526
2527**/
2528static
2529EFI_DEVICE_PATH_PROTOCOL *
2530DevPathFromTextUsbWireless (
2531  IN CHAR16  *TextDeviceNode
2532  )
2533{
2534  USB_CLASS_TEXT  UsbClassText;
2535
2536  UsbClassText.ClassExist    = FALSE;
2537  UsbClassText.Class         = USB_CLASS_WIRELESS;
2538  UsbClassText.SubClassExist = TRUE;
2539
2540  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2541}
2542
2543/**
2544  Converts a text device path node to USB device firmware update device path structure.
2545
2546  @param TextDeviceNode  The input Text device path node.
2547
2548  @return A pointer to the newly-created USB device firmware update device path structure.
2549
2550**/
2551static
2552EFI_DEVICE_PATH_PROTOCOL *
2553DevPathFromTextUsbDeviceFirmwareUpdate (
2554  IN CHAR16  *TextDeviceNode
2555  )
2556{
2557  USB_CLASS_TEXT  UsbClassText;
2558
2559  UsbClassText.ClassExist    = FALSE;
2560  UsbClassText.Class         = USB_CLASS_RESERVE;
2561  UsbClassText.SubClassExist = FALSE;
2562  UsbClassText.SubClass      = USB_SUBCLASS_FW_UPDATE;
2563
2564  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2565}
2566
2567/**
2568  Converts a text device path node to USB IRDA bridge device path structure.
2569
2570  @param TextDeviceNode  The input Text device path node.
2571
2572  @return A pointer to the newly-created USB IRDA bridge device path structure.
2573
2574**/
2575static
2576EFI_DEVICE_PATH_PROTOCOL *
2577DevPathFromTextUsbIrdaBridge (
2578  IN CHAR16  *TextDeviceNode
2579  )
2580{
2581  USB_CLASS_TEXT  UsbClassText;
2582
2583  UsbClassText.ClassExist    = FALSE;
2584  UsbClassText.Class         = USB_CLASS_RESERVE;
2585  UsbClassText.SubClassExist = FALSE;
2586  UsbClassText.SubClass      = USB_SUBCLASS_IRDA_BRIDGE;
2587
2588  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2589}
2590
2591/**
2592  Converts a text device path node to USB text and measurement device path structure.
2593
2594  @param TextDeviceNode  The input Text device path node.
2595
2596  @return A pointer to the newly-created USB text and measurement device path structure.
2597
2598**/
2599static
2600EFI_DEVICE_PATH_PROTOCOL *
2601DevPathFromTextUsbTestAndMeasurement (
2602  IN CHAR16  *TextDeviceNode
2603  )
2604{
2605  USB_CLASS_TEXT  UsbClassText;
2606
2607  UsbClassText.ClassExist    = FALSE;
2608  UsbClassText.Class         = USB_CLASS_RESERVE;
2609  UsbClassText.SubClassExist = FALSE;
2610  UsbClassText.SubClass      = USB_SUBCLASS_TEST;
2611
2612  return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
2613}
2614
2615/**
2616  Converts a text device path node to USB WWID device path structure.
2617
2618  @param TextDeviceNode  The input Text device path node.
2619
2620  @return A pointer to the newly-created USB WWID device path structure.
2621
2622**/
2623static
2624EFI_DEVICE_PATH_PROTOCOL *
2625DevPathFromTextUsbWwid (
2626  IN CHAR16  *TextDeviceNode
2627  )
2628{
2629  CHAR16                *VIDStr;
2630  CHAR16                *PIDStr;
2631  CHAR16                *InterfaceNumStr;
2632  CHAR16                *SerialNumberStr;
2633  USB_WWID_DEVICE_PATH  *UsbWwid;
2634  UINTN                 SerialNumberStrLen;
2635
2636  VIDStr             = GetNextParamStr (&TextDeviceNode);
2637  PIDStr             = GetNextParamStr (&TextDeviceNode);
2638  InterfaceNumStr    = GetNextParamStr (&TextDeviceNode);
2639  SerialNumberStr    = GetNextParamStr (&TextDeviceNode);
2640  SerialNumberStrLen = StrLen (SerialNumberStr);
2641  if ((SerialNumberStrLen >= 2) &&
2642      (SerialNumberStr[0] == '\"') &&
2643      (SerialNumberStr[SerialNumberStrLen - 1] == '\"')
2644      )
2645  {
2646    SerialNumberStr[SerialNumberStrLen - 1] = '\0';
2647    SerialNumberStr++;
2648    SerialNumberStrLen -= 2;
2649  }
2650
2651  UsbWwid = (USB_WWID_DEVICE_PATH *)CreateDeviceNode (
2652                                      MESSAGING_DEVICE_PATH,
2653                                      MSG_USB_WWID_DP,
2654                                      (UINT16)(sizeof (USB_WWID_DEVICE_PATH) + SerialNumberStrLen * sizeof (CHAR16))
2655                                      );
2656  UsbWwid->VendorId        = (UINT16)Strtoi (VIDStr);
2657  UsbWwid->ProductId       = (UINT16)Strtoi (PIDStr);
2658  UsbWwid->InterfaceNumber = (UINT16)Strtoi (InterfaceNumStr);
2659
2660  //
2661  // There is no memory allocated in UsbWwid for the '\0' in SerialNumberStr.
2662  // Therefore, the '\0' will not be copied.
2663  //
2664  CopyMem (
2665    (UINT8 *)UsbWwid + sizeof (USB_WWID_DEVICE_PATH),
2666    SerialNumberStr,
2667    SerialNumberStrLen * sizeof (CHAR16)
2668    );
2669
2670  return (EFI_DEVICE_PATH_PROTOCOL *)UsbWwid;
2671}
2672
2673/**
2674  Converts a text device path node to Logic Unit device path structure.
2675
2676  @param TextDeviceNode  The input Text device path node.
2677
2678  @return A pointer to the newly-created Logic Unit device path structure.
2679
2680**/
2681static
2682EFI_DEVICE_PATH_PROTOCOL *
2683DevPathFromTextUnit (
2684  IN CHAR16  *TextDeviceNode
2685  )
2686{
2687  CHAR16                           *LunStr;
2688  DEVICE_LOGICAL_UNIT_DEVICE_PATH  *LogicalUnit;
2689
2690  LunStr      = GetNextParamStr (&TextDeviceNode);
2691  LogicalUnit = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *)CreateDeviceNode (
2692                                                     MESSAGING_DEVICE_PATH,
2693                                                     MSG_DEVICE_LOGICAL_UNIT_DP,
2694                                                     (UINT16)sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH)
2695                                                     );
2696
2697  LogicalUnit->Lun = (UINT8)Strtoi (LunStr);
2698
2699  return (EFI_DEVICE_PATH_PROTOCOL *)LogicalUnit;
2700}
2701
2702/**
2703  Converts a text device path node to iSCSI device path structure.
2704
2705  @param TextDeviceNode  The input Text device path node.
2706
2707  @return A pointer to the newly-created iSCSI device path structure.
2708
2709**/
2710static
2711EFI_DEVICE_PATH_PROTOCOL *
2712DevPathFromTextiSCSI (
2713  IN CHAR16  *TextDeviceNode
2714  )
2715{
2716  UINT16                       Options;
2717  CHAR16                       *NameStr;
2718  CHAR16                       *PortalGroupStr;
2719  CHAR16                       *LunStr;
2720  CHAR16                       *HeaderDigestStr;
2721  CHAR16                       *DataDigestStr;
2722  CHAR16                       *AuthenticationStr;
2723  CHAR16                       *ProtocolStr;
2724  CHAR8                        *AsciiStr;
2725  ISCSI_DEVICE_PATH_WITH_NAME  *ISCSIDevPath;
2726  UINT64                       Lun;
2727
2728  NameStr           = GetNextParamStr (&TextDeviceNode);
2729  PortalGroupStr    = GetNextParamStr (&TextDeviceNode);
2730  LunStr            = GetNextParamStr (&TextDeviceNode);
2731  HeaderDigestStr   = GetNextParamStr (&TextDeviceNode);
2732  DataDigestStr     = GetNextParamStr (&TextDeviceNode);
2733  AuthenticationStr = GetNextParamStr (&TextDeviceNode);
2734  ProtocolStr       = GetNextParamStr (&TextDeviceNode);
2735  ISCSIDevPath      = (ISCSI_DEVICE_PATH_WITH_NAME *)CreateDeviceNode (
2736                                                       MESSAGING_DEVICE_PATH,
2737                                                       MSG_ISCSI_DP,
2738                                                       (UINT16)(sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + StrLen (NameStr))
2739                                                       );
2740
2741  AsciiStr = ISCSIDevPath->TargetName;
2742  StrToAscii (NameStr, &AsciiStr);
2743
2744  ISCSIDevPath->TargetPortalGroupTag = (UINT16)Strtoi (PortalGroupStr);
2745  Strtoi64 (LunStr, &Lun);
2746  WriteUnaligned64 ((UINT64 *)&ISCSIDevPath->Lun, SwapBytes64 (Lun));
2747
2748  Options = 0x0000;
2749  if (StrCmp (HeaderDigestStr, "CRC32C") == 0) {
2750    Options |= 0x0002;
2751  }
2752
2753  if (StrCmp (DataDigestStr, "CRC32C") == 0) {
2754    Options |= 0x0008;
2755  }
2756
2757  if (StrCmp (AuthenticationStr, "None") == 0) {
2758    Options |= 0x0800;
2759  }
2760
2761  if (StrCmp (AuthenticationStr, "CHAP_UNI") == 0) {
2762    Options |= 0x1000;
2763  }
2764
2765  ISCSIDevPath->LoginOption = (UINT16)Options;
2766
2767  if (IS_NULL (*ProtocolStr) || (StrCmp (ProtocolStr, "TCP") == 0)) {
2768    ISCSIDevPath->NetworkProtocol = 0;
2769  } else {
2770    //
2771    // Undefined and reserved.
2772    //
2773    ISCSIDevPath->NetworkProtocol = 1;
2774  }
2775
2776  return (EFI_DEVICE_PATH_PROTOCOL *)ISCSIDevPath;
2777}
2778
2779/**
2780  Converts a text device path node to VLAN device path structure.
2781
2782  @param TextDeviceNode  The input Text device path node.
2783
2784  @return A pointer to the newly-created VLAN device path structure.
2785
2786**/
2787static
2788EFI_DEVICE_PATH_PROTOCOL *
2789DevPathFromTextVlan (
2790  IN CHAR16  *TextDeviceNode
2791  )
2792{
2793  CHAR16            *VlanStr;
2794  VLAN_DEVICE_PATH  *Vlan;
2795
2796  VlanStr = GetNextParamStr (&TextDeviceNode);
2797  Vlan    = (VLAN_DEVICE_PATH *)CreateDeviceNode (
2798                                  MESSAGING_DEVICE_PATH,
2799                                  MSG_VLAN_DP,
2800                                  (UINT16)sizeof (VLAN_DEVICE_PATH)
2801                                  );
2802
2803  Vlan->VlanId = (UINT16)Strtoi (VlanStr);
2804
2805  return (EFI_DEVICE_PATH_PROTOCOL *)Vlan;
2806}
2807
2808/**
2809  Converts a text device path node to Bluetooth device path structure.
2810
2811  @param TextDeviceNode  The input Text device path node.
2812
2813  @return A pointer to the newly-created Bluetooth device path structure.
2814
2815**/
2816static
2817EFI_DEVICE_PATH_PROTOCOL *
2818DevPathFromTextBluetooth (
2819  IN CHAR16  *TextDeviceNode
2820  )
2821{
2822  CHAR16                 *BluetoothStr;
2823  BLUETOOTH_DEVICE_PATH  *BluetoothDp;
2824
2825  BluetoothStr = GetNextParamStr (&TextDeviceNode);
2826  BluetoothDp  = (BLUETOOTH_DEVICE_PATH *)CreateDeviceNode (
2827                                            MESSAGING_DEVICE_PATH,
2828                                            MSG_BLUETOOTH_DP,
2829                                            (UINT16)sizeof (BLUETOOTH_DEVICE_PATH)
2830                                            );
2831  StrHexToBytes (
2832    BluetoothStr,
2833    sizeof (BLUETOOTH_ADDRESS) * 2,
2834    BluetoothDp->BD_ADDR.Address,
2835    sizeof (BLUETOOTH_ADDRESS)
2836    );
2837  return (EFI_DEVICE_PATH_PROTOCOL *)BluetoothDp;
2838}
2839
2840/**
2841  Converts a text device path node to Wi-Fi device path structure.
2842
2843  @param TextDeviceNode  The input Text device path node.
2844
2845  @return A pointer to the newly-created Wi-Fi device path structure.
2846
2847**/
2848static
2849EFI_DEVICE_PATH_PROTOCOL *
2850DevPathFromTextWiFi (
2851  IN CHAR16  *TextDeviceNode
2852  )
2853{
2854  CHAR16            *SSIdStr;
2855  CHAR8             AsciiStr[33];
2856  UINTN             DataLen;
2857  WIFI_DEVICE_PATH  *WiFiDp;
2858
2859  SSIdStr = GetNextParamStr (&TextDeviceNode);
2860  WiFiDp  = (WIFI_DEVICE_PATH *)CreateDeviceNode (
2861                                  MESSAGING_DEVICE_PATH,
2862                                  MSG_WIFI_DP,
2863                                  (UINT16)sizeof (WIFI_DEVICE_PATH)
2864                                  );
2865
2866  if (NULL != SSIdStr) {
2867    DataLen = StrLen (SSIdStr);
2868    if (StrLen (SSIdStr) > 32) {
2869      SSIdStr[32] = '\0';
2870      DataLen     = 32;
2871    }
2872
2873    UnicodeStrToAsciiStrS (SSIdStr, AsciiStr, sizeof (AsciiStr));
2874    CopyMem (WiFiDp->SSId, AsciiStr, DataLen);
2875  }
2876
2877  return (EFI_DEVICE_PATH_PROTOCOL *)WiFiDp;
2878}
2879
2880/**
2881  Converts a text device path node to Bluetooth LE device path structure.
2882
2883  @param TextDeviceNode  The input Text device path node.
2884
2885  @return A pointer to the newly-created Bluetooth LE device path structure.
2886
2887**/
2888static
2889EFI_DEVICE_PATH_PROTOCOL *
2890DevPathFromTextBluetoothLE (
2891  IN CHAR16  *TextDeviceNode
2892  )
2893{
2894  CHAR16                    *BluetoothLeAddrStr;
2895  CHAR16                    *BluetoothLeAddrTypeStr;
2896  BLUETOOTH_LE_DEVICE_PATH  *BluetoothLeDp;
2897
2898  BluetoothLeAddrStr     = GetNextParamStr (&TextDeviceNode);
2899  BluetoothLeAddrTypeStr = GetNextParamStr (&TextDeviceNode);
2900  BluetoothLeDp          = (BLUETOOTH_LE_DEVICE_PATH *)CreateDeviceNode (
2901                                                         MESSAGING_DEVICE_PATH,
2902                                                         MSG_BLUETOOTH_LE_DP,
2903                                                         (UINT16)sizeof (BLUETOOTH_LE_DEVICE_PATH)
2904                                                         );
2905
2906  BluetoothLeDp->Address.Type = (UINT8)Strtoi (BluetoothLeAddrTypeStr);
2907  StrHexToBytes (
2908    BluetoothLeAddrStr,
2909    sizeof (BluetoothLeDp->Address.Address) * 2,
2910    BluetoothLeDp->Address.Address,
2911    sizeof (BluetoothLeDp->Address.Address)
2912    );
2913  return (EFI_DEVICE_PATH_PROTOCOL *)BluetoothLeDp;
2914}
2915
2916/**
2917  Converts a text device path node to DNS device path structure.
2918
2919  @param TextDeviceNode  The input Text device path node.
2920
2921  @return A pointer to the newly-created DNS device path structure.
2922
2923**/
2924static
2925EFI_DEVICE_PATH_PROTOCOL *
2926DevPathFromTextDns (
2927  IN CHAR16  *TextDeviceNode
2928  )
2929{
2930  CHAR16           *DeviceNodeStr;
2931  CHAR16           *DeviceNodeStrPtr;
2932  UINT32           DnsServerIpCount;
2933  UINT16           DnsDeviceNodeLength;
2934  DNS_DEVICE_PATH  *DnsDeviceNode;
2935  UINT32           DnsServerIpIndex;
2936  CHAR16           *DnsServerIp;
2937
2938  //
2939  // Count the DNS server address number.
2940  //
2941  DeviceNodeStr = UefiDevicePathLibStrDuplicate (TextDeviceNode);
2942  if (DeviceNodeStr == NULL) {
2943    return NULL;
2944  }
2945
2946  DeviceNodeStrPtr = DeviceNodeStr;
2947
2948  DnsServerIpCount = 0;
2949  while (DeviceNodeStrPtr != NULL && *DeviceNodeStrPtr != '\0') {
2950    GetNextParamStr (&DeviceNodeStrPtr);
2951    DnsServerIpCount++;
2952  }
2953
2954  FreePool (DeviceNodeStr);
2955  DeviceNodeStr = NULL;
2956
2957  //
2958  // One or more instances of the DNS server address in EFI_IP_ADDRESS,
2959  // otherwise, NULL will be returned.
2960  //
2961  if (DnsServerIpCount == 0) {
2962    return NULL;
2963  }
2964
2965  //
2966  // Create the DNS DeviceNode.
2967  //
2968  DnsDeviceNodeLength = (UINT16)(sizeof (EFI_DEVICE_PATH_PROTOCOL) + sizeof (UINT8) + DnsServerIpCount * sizeof (EFI_IP_ADDRESS));
2969  DnsDeviceNode       = (DNS_DEVICE_PATH *)CreateDeviceNode (
2970                                             MESSAGING_DEVICE_PATH,
2971                                             MSG_DNS_DP,
2972                                             DnsDeviceNodeLength
2973                                             );
2974  if (DnsDeviceNode == NULL) {
2975    return NULL;
2976  }
2977
2978  //
2979  // Confirm the DNS server address is IPv4 or IPv6 type.
2980  //
2981  DeviceNodeStrPtr = TextDeviceNode;
2982  while (!IS_NULL (*DeviceNodeStrPtr)) {
2983    if (*DeviceNodeStrPtr == '.') {
2984      DnsDeviceNode->IsIPv6 = 0x00;
2985      break;
2986    }
2987
2988    if (*DeviceNodeStrPtr == ':') {
2989      DnsDeviceNode->IsIPv6 = 0x01;
2990      break;
2991    }
2992
2993    DeviceNodeStrPtr++;
2994  }
2995
2996  for (DnsServerIpIndex = 0; DnsServerIpIndex < DnsServerIpCount; DnsServerIpIndex++) {
2997    DnsServerIp = GetNextParamStr (&TextDeviceNode);
2998    if (DnsDeviceNode->IsIPv6 == 0x00) {
2999      StrToIpv4Address (DnsServerIp, NULL, &(DnsDeviceNode->DnsServerIp[DnsServerIpIndex].v4), NULL);
3000    } else {
3001      StrToIpv6Address (DnsServerIp, NULL, &(DnsDeviceNode->DnsServerIp[DnsServerIpIndex].v6), NULL);
3002    }
3003  }
3004
3005  return (EFI_DEVICE_PATH_PROTOCOL *)DnsDeviceNode;
3006}
3007
3008/**
3009  Converts a text device path node to URI device path structure.
3010
3011  @param TextDeviceNode  The input Text device path node.
3012
3013  @return A pointer to the newly-created URI device path structure.
3014
3015**/
3016static
3017EFI_DEVICE_PATH_PROTOCOL *
3018DevPathFromTextUri (
3019  IN CHAR16  *TextDeviceNode
3020  )
3021{
3022  CHAR16           *UriStr;
3023  UINTN            UriLength;
3024  URI_DEVICE_PATH  *Uri;
3025
3026  UriStr    = GetNextParamStr (&TextDeviceNode);
3027  UriLength = StrnLenS (UriStr, MAX_UINT16 - sizeof (URI_DEVICE_PATH));
3028  Uri       = (URI_DEVICE_PATH *)CreateDeviceNode (
3029                                   MESSAGING_DEVICE_PATH,
3030                                   MSG_URI_DP,
3031                                   (UINT16)(sizeof (URI_DEVICE_PATH) + UriLength)
3032                                   );
3033
3034  while (UriLength-- != 0) {
3035    Uri->Uri[UriLength] = (CHAR8)UriStr[UriLength];
3036  }
3037
3038  return (EFI_DEVICE_PATH_PROTOCOL *)Uri;
3039}
3040
3041/**
3042  Converts a media text device path node to media device path structure.
3043
3044  @param TextDeviceNode  The input Text device path node.
3045
3046  @return A pointer to media device path structure.
3047
3048**/
3049static
3050EFI_DEVICE_PATH_PROTOCOL *
3051DevPathFromTextMediaPath (
3052  IN CHAR16  *TextDeviceNode
3053  )
3054{
3055  return DevPathFromTextGenericPath (MEDIA_DEVICE_PATH, TextDeviceNode);
3056}
3057
3058/**
3059  Converts a text device path node to HD device path structure.
3060
3061  @param TextDeviceNode  The input Text device path node.
3062
3063  @return A pointer to the newly-created HD device path structure.
3064
3065**/
3066static
3067EFI_DEVICE_PATH_PROTOCOL *
3068DevPathFromTextHD (
3069  IN CHAR16  *TextDeviceNode
3070  )
3071{
3072  CHAR16                 *PartitionStr;
3073  CHAR16                 *TypeStr;
3074  CHAR16                 *SignatureStr;
3075  CHAR16                 *StartStr;
3076  CHAR16                 *SizeStr;
3077  UINT32                 Signature32;
3078  HARDDRIVE_DEVICE_PATH  *Hd;
3079
3080  PartitionStr = GetNextParamStr (&TextDeviceNode);
3081  TypeStr      = GetNextParamStr (&TextDeviceNode);
3082  SignatureStr = GetNextParamStr (&TextDeviceNode);
3083  StartStr     = GetNextParamStr (&TextDeviceNode);
3084  SizeStr      = GetNextParamStr (&TextDeviceNode);
3085  Hd           = (HARDDRIVE_DEVICE_PATH *)CreateDeviceNode (
3086                                            MEDIA_DEVICE_PATH,
3087                                            MEDIA_HARDDRIVE_DP,
3088                                            (UINT16)sizeof (HARDDRIVE_DEVICE_PATH)
3089                                            );
3090
3091  Hd->PartitionNumber = (UINT32)Strtoi (PartitionStr);
3092
3093  ZeroMem (Hd->Signature, 16);
3094  Hd->MBRType = (UINT8)0;
3095
3096  if (StrCmp (TypeStr, "MBR") == 0) {
3097    Hd->SignatureType = SIGNATURE_TYPE_MBR;
3098    Hd->MBRType       = 0x01;
3099
3100    Signature32 = (UINT32)Strtoi (SignatureStr);
3101    CopyMem (Hd->Signature, &Signature32, sizeof (UINT32));
3102  } else if (StrCmp (TypeStr, "GPT") == 0) {
3103    Hd->SignatureType = SIGNATURE_TYPE_GUID;
3104    Hd->MBRType       = 0x02;
3105
3106    StrToGuid (SignatureStr, (EFI_GUID *)Hd->Signature);
3107  } else {
3108    Hd->SignatureType = (UINT8)Strtoi (TypeStr);
3109  }
3110
3111  Strtoi64 (StartStr, &Hd->PartitionStart);
3112  Strtoi64 (SizeStr, &Hd->PartitionSize);
3113
3114  return (EFI_DEVICE_PATH_PROTOCOL *)Hd;
3115}
3116
3117/**
3118  Converts a text device path node to CDROM device path structure.
3119
3120  @param TextDeviceNode  The input Text device path node.
3121
3122  @return A pointer to the newly-created CDROM device path structure.
3123
3124**/
3125static
3126EFI_DEVICE_PATH_PROTOCOL *
3127DevPathFromTextCDROM (
3128  IN CHAR16  *TextDeviceNode
3129  )
3130{
3131  CHAR16             *EntryStr;
3132  CHAR16             *StartStr;
3133  CHAR16             *SizeStr;
3134  CDROM_DEVICE_PATH  *CDROMDevPath;
3135
3136  EntryStr     = GetNextParamStr (&TextDeviceNode);
3137  StartStr     = GetNextParamStr (&TextDeviceNode);
3138  SizeStr      = GetNextParamStr (&TextDeviceNode);
3139  CDROMDevPath = (CDROM_DEVICE_PATH *)CreateDeviceNode (
3140                                        MEDIA_DEVICE_PATH,
3141                                        MEDIA_CDROM_DP,
3142                                        (UINT16)sizeof (CDROM_DEVICE_PATH)
3143                                        );
3144
3145  CDROMDevPath->BootEntry = (UINT32)Strtoi (EntryStr);
3146  Strtoi64 (StartStr, &CDROMDevPath->PartitionStart);
3147  Strtoi64 (SizeStr, &CDROMDevPath->PartitionSize);
3148
3149  return (EFI_DEVICE_PATH_PROTOCOL *)CDROMDevPath;
3150}
3151
3152/**
3153  Converts a text device path node to Vendor-defined media device path structure.
3154
3155  @param TextDeviceNode  The input Text device path node.
3156
3157  @return A pointer to the newly-created Vendor-defined media device path structure.
3158
3159**/
3160static
3161EFI_DEVICE_PATH_PROTOCOL *
3162DevPathFromTextVenMedia (
3163  IN CHAR16  *TextDeviceNode
3164  )
3165{
3166  return ConvertFromTextVendor (
3167           TextDeviceNode,
3168           MEDIA_DEVICE_PATH,
3169           MEDIA_VENDOR_DP
3170           );
3171}
3172
3173/**
3174  Converts a text device path node to File device path structure.
3175
3176  @param TextDeviceNode  The input Text device path node.
3177
3178  @return A pointer to the newly-created File device path structure.
3179
3180**/
3181static
3182EFI_DEVICE_PATH_PROTOCOL *
3183DevPathFromTextFilePath (
3184  IN CHAR16  *TextDeviceNode
3185  )
3186{
3187  FILEPATH_DEVICE_PATH  *File;
3188
3189#ifndef __FreeBSD__
3190  File = (FILEPATH_DEVICE_PATH *)CreateDeviceNode (
3191                                   MEDIA_DEVICE_PATH,
3192                                   MEDIA_FILEPATH_DP,
3193                                   (UINT16)(sizeof (FILEPATH_DEVICE_PATH) + StrLen (TextDeviceNode) * 2)
3194                                   );
3195
3196  StrCpyS (File->PathName, StrLen (TextDeviceNode) + 1, TextDeviceNode);
3197#else
3198  size_t len = (sizeof (FILEPATH_DEVICE_PATH) + StrLen (TextDeviceNode) * 2);
3199  efi_char *v;
3200  File = (FILEPATH_DEVICE_PATH *)CreateDeviceNode (
3201                                   MEDIA_DEVICE_PATH,
3202                                   MEDIA_FILEPATH_DP,
3203                                   (UINT16)len
3204                                   );
3205  v = File->PathName;
3206  utf8_to_ucs2(TextDeviceNode, &v, &len);
3207#endif
3208
3209  return (EFI_DEVICE_PATH_PROTOCOL *)File;
3210}
3211
3212/**
3213  Converts a text device path node to Media protocol device path structure.
3214
3215  @param TextDeviceNode  The input Text device path node.
3216
3217  @return A pointer to the newly-created Media protocol device path structure.
3218
3219**/
3220static
3221EFI_DEVICE_PATH_PROTOCOL *
3222DevPathFromTextMedia (
3223  IN CHAR16  *TextDeviceNode
3224  )
3225{
3226  CHAR16                      *GuidStr;
3227  MEDIA_PROTOCOL_DEVICE_PATH  *Media;
3228
3229  GuidStr = GetNextParamStr (&TextDeviceNode);
3230  Media   = (MEDIA_PROTOCOL_DEVICE_PATH *)CreateDeviceNode (
3231                                            MEDIA_DEVICE_PATH,
3232                                            MEDIA_PROTOCOL_DP,
3233                                            (UINT16)sizeof (MEDIA_PROTOCOL_DEVICE_PATH)
3234                                            );
3235
3236  StrToGuid (GuidStr, &Media->Protocol);
3237
3238  return (EFI_DEVICE_PATH_PROTOCOL *)Media;
3239}
3240
3241/**
3242  Converts a text device path node to firmware volume device path structure.
3243
3244  @param TextDeviceNode  The input Text device path node.
3245
3246  @return A pointer to the newly-created firmware volume device path structure.
3247
3248**/
3249static
3250EFI_DEVICE_PATH_PROTOCOL *
3251DevPathFromTextFv (
3252  IN CHAR16  *TextDeviceNode
3253  )
3254{
3255  CHAR16                    *GuidStr;
3256  MEDIA_FW_VOL_DEVICE_PATH  *Fv;
3257
3258  GuidStr = GetNextParamStr (&TextDeviceNode);
3259  Fv      = (MEDIA_FW_VOL_DEVICE_PATH *)CreateDeviceNode (
3260                                          MEDIA_DEVICE_PATH,
3261                                          MEDIA_PIWG_FW_VOL_DP,
3262                                          (UINT16)sizeof (MEDIA_FW_VOL_DEVICE_PATH)
3263                                          );
3264
3265  StrToGuid (GuidStr, &Fv->FvName);
3266
3267  return (EFI_DEVICE_PATH_PROTOCOL *)Fv;
3268}
3269
3270/**
3271  Converts a text device path node to firmware file device path structure.
3272
3273  @param TextDeviceNode  The input Text device path node.
3274
3275  @return A pointer to the newly-created firmware file device path structure.
3276
3277**/
3278static
3279EFI_DEVICE_PATH_PROTOCOL *
3280DevPathFromTextFvFile (
3281  IN CHAR16  *TextDeviceNode
3282  )
3283{
3284  CHAR16                             *GuidStr;
3285  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FvFile;
3286
3287  GuidStr = GetNextParamStr (&TextDeviceNode);
3288  FvFile  = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)CreateDeviceNode (
3289                                                   MEDIA_DEVICE_PATH,
3290                                                   MEDIA_PIWG_FW_FILE_DP,
3291                                                   (UINT16)sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)
3292                                                   );
3293
3294  StrToGuid (GuidStr, &FvFile->FvFileName);
3295
3296  return (EFI_DEVICE_PATH_PROTOCOL *)FvFile;
3297}
3298
3299/**
3300  Converts a text device path node to text relative offset device path structure.
3301
3302  @param TextDeviceNode  The input Text device path node.
3303
3304  @return A pointer to the newly-created Text device path structure.
3305
3306**/
3307static
3308EFI_DEVICE_PATH_PROTOCOL *
3309DevPathFromTextRelativeOffsetRange (
3310  IN CHAR16  *TextDeviceNode
3311  )
3312{
3313  CHAR16                                   *StartingOffsetStr;
3314  CHAR16                                   *EndingOffsetStr;
3315  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  *Offset;
3316
3317  StartingOffsetStr = GetNextParamStr (&TextDeviceNode);
3318  EndingOffsetStr   = GetNextParamStr (&TextDeviceNode);
3319  Offset            = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *)CreateDeviceNode (
3320                                                                   MEDIA_DEVICE_PATH,
3321                                                                   MEDIA_RELATIVE_OFFSET_RANGE_DP,
3322                                                                   (UINT16)sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)
3323                                                                   );
3324
3325  Strtoi64 (StartingOffsetStr, &Offset->StartingOffset);
3326  Strtoi64 (EndingOffsetStr, &Offset->EndingOffset);
3327
3328  return (EFI_DEVICE_PATH_PROTOCOL *)Offset;
3329}
3330
3331/**
3332  Converts a text device path node to text ram disk device path structure.
3333
3334  @param TextDeviceNode  The input Text device path node.
3335
3336  @return A pointer to the newly-created Text device path structure.
3337
3338**/
3339static
3340EFI_DEVICE_PATH_PROTOCOL *
3341DevPathFromTextRamDisk (
3342  IN CHAR16  *TextDeviceNode
3343  )
3344{
3345  CHAR16                      *StartingAddrStr;
3346  CHAR16                      *EndingAddrStr;
3347  CHAR16                      *TypeGuidStr;
3348  CHAR16                      *InstanceStr;
3349  MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
3350  UINT64                      StartingAddr;
3351  UINT64                      EndingAddr;
3352
3353  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
3354  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
3355  InstanceStr     = GetNextParamStr (&TextDeviceNode);
3356  TypeGuidStr     = GetNextParamStr (&TextDeviceNode);
3357  RamDisk         = (MEDIA_RAM_DISK_DEVICE_PATH *)CreateDeviceNode (
3358                                                    MEDIA_DEVICE_PATH,
3359                                                    MEDIA_RAM_DISK_DP,
3360                                                    (UINT16)sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
3361                                                    );
3362
3363  Strtoi64 (StartingAddrStr, &StartingAddr);
3364  WriteUnaligned64 ((UINT64 *)&(RamDisk->StartingAddr[0]), StartingAddr);
3365  Strtoi64 (EndingAddrStr, &EndingAddr);
3366  WriteUnaligned64 ((UINT64 *)&(RamDisk->EndingAddr[0]), EndingAddr);
3367  RamDisk->Instance = (UINT16)Strtoi (InstanceStr);
3368  StrToGuid (TypeGuidStr, &RamDisk->TypeGuid);
3369
3370  return (EFI_DEVICE_PATH_PROTOCOL *)RamDisk;
3371}
3372
3373/**
3374  Converts a text device path node to text virtual disk device path structure.
3375
3376  @param TextDeviceNode  The input Text device path node.
3377
3378  @return A pointer to the newly-created Text device path structure.
3379
3380**/
3381static
3382EFI_DEVICE_PATH_PROTOCOL *
3383DevPathFromTextVirtualDisk (
3384  IN CHAR16  *TextDeviceNode
3385  )
3386{
3387  CHAR16                      *StartingAddrStr;
3388  CHAR16                      *EndingAddrStr;
3389  CHAR16                      *InstanceStr;
3390  MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
3391  UINT64                      StartingAddr;
3392  UINT64                      EndingAddr;
3393
3394  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
3395  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
3396  InstanceStr     = GetNextParamStr (&TextDeviceNode);
3397
3398  RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *)CreateDeviceNode (
3399                                            MEDIA_DEVICE_PATH,
3400                                            MEDIA_RAM_DISK_DP,
3401                                            (UINT16)sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
3402                                            );
3403
3404  Strtoi64 (StartingAddrStr, &StartingAddr);
3405  WriteUnaligned64 ((UINT64 *)&(RamDisk->StartingAddr[0]), StartingAddr);
3406  Strtoi64 (EndingAddrStr, &EndingAddr);
3407  WriteUnaligned64 ((UINT64 *)&(RamDisk->EndingAddr[0]), EndingAddr);
3408  RamDisk->Instance = (UINT16)Strtoi (InstanceStr);
3409  CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid);
3410
3411  return (EFI_DEVICE_PATH_PROTOCOL *)RamDisk;
3412}
3413
3414/**
3415  Converts a text device path node to text virtual cd device path structure.
3416
3417  @param TextDeviceNode  The input Text device path node.
3418
3419  @return A pointer to the newly-created Text device path structure.
3420
3421**/
3422static
3423EFI_DEVICE_PATH_PROTOCOL *
3424DevPathFromTextVirtualCd (
3425  IN CHAR16  *TextDeviceNode
3426  )
3427{
3428  CHAR16                      *StartingAddrStr;
3429  CHAR16                      *EndingAddrStr;
3430  CHAR16                      *InstanceStr;
3431  MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
3432  UINT64                      StartingAddr;
3433  UINT64                      EndingAddr;
3434
3435  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
3436  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
3437  InstanceStr     = GetNextParamStr (&TextDeviceNode);
3438
3439  RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *)CreateDeviceNode (
3440                                            MEDIA_DEVICE_PATH,
3441                                            MEDIA_RAM_DISK_DP,
3442                                            (UINT16)sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
3443                                            );
3444
3445  Strtoi64 (StartingAddrStr, &StartingAddr);
3446  WriteUnaligned64 ((UINT64 *)&(RamDisk->StartingAddr[0]), StartingAddr);
3447  Strtoi64 (EndingAddrStr, &EndingAddr);
3448  WriteUnaligned64 ((UINT64 *)&(RamDisk->EndingAddr[0]), EndingAddr);
3449  RamDisk->Instance = (UINT16)Strtoi (InstanceStr);
3450  CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid);
3451
3452  return (EFI_DEVICE_PATH_PROTOCOL *)RamDisk;
3453}
3454
3455/**
3456  Converts a text device path node to text persistent virtual disk device path structure.
3457
3458  @param TextDeviceNode  The input Text device path node.
3459
3460  @return A pointer to the newly-created Text device path structure.
3461
3462**/
3463static
3464EFI_DEVICE_PATH_PROTOCOL *
3465DevPathFromTextPersistentVirtualDisk (
3466  IN CHAR16  *TextDeviceNode
3467  )
3468{
3469  CHAR16                      *StartingAddrStr;
3470  CHAR16                      *EndingAddrStr;
3471  CHAR16                      *InstanceStr;
3472  MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
3473  UINT64                      StartingAddr;
3474  UINT64                      EndingAddr;
3475
3476  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
3477  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
3478  InstanceStr     = GetNextParamStr (&TextDeviceNode);
3479
3480  RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *)CreateDeviceNode (
3481                                            MEDIA_DEVICE_PATH,
3482                                            MEDIA_RAM_DISK_DP,
3483                                            (UINT16)sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
3484                                            );
3485
3486  Strtoi64 (StartingAddrStr, &StartingAddr);
3487  WriteUnaligned64 ((UINT64 *)&(RamDisk->StartingAddr[0]), StartingAddr);
3488  Strtoi64 (EndingAddrStr, &EndingAddr);
3489  WriteUnaligned64 ((UINT64 *)&(RamDisk->EndingAddr[0]), EndingAddr);
3490  RamDisk->Instance = (UINT16)Strtoi (InstanceStr);
3491  CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid);
3492
3493  return (EFI_DEVICE_PATH_PROTOCOL *)RamDisk;
3494}
3495
3496/**
3497  Converts a text device path node to text persistent virtual cd device path structure.
3498
3499  @param TextDeviceNode  The input Text device path node.
3500
3501  @return A pointer to the newly-created Text device path structure.
3502
3503**/
3504static
3505EFI_DEVICE_PATH_PROTOCOL *
3506DevPathFromTextPersistentVirtualCd (
3507  IN CHAR16  *TextDeviceNode
3508  )
3509{
3510  CHAR16                      *StartingAddrStr;
3511  CHAR16                      *EndingAddrStr;
3512  CHAR16                      *InstanceStr;
3513  MEDIA_RAM_DISK_DEVICE_PATH  *RamDisk;
3514  UINT64                      StartingAddr;
3515  UINT64                      EndingAddr;
3516
3517  StartingAddrStr = GetNextParamStr (&TextDeviceNode);
3518  EndingAddrStr   = GetNextParamStr (&TextDeviceNode);
3519  InstanceStr     = GetNextParamStr (&TextDeviceNode);
3520
3521  RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *)CreateDeviceNode (
3522                                            MEDIA_DEVICE_PATH,
3523                                            MEDIA_RAM_DISK_DP,
3524                                            (UINT16)sizeof (MEDIA_RAM_DISK_DEVICE_PATH)
3525                                            );
3526
3527  Strtoi64 (StartingAddrStr, &StartingAddr);
3528  WriteUnaligned64 ((UINT64 *)&(RamDisk->StartingAddr[0]), StartingAddr);
3529  Strtoi64 (EndingAddrStr, &EndingAddr);
3530  WriteUnaligned64 ((UINT64 *)&(RamDisk->EndingAddr[0]), EndingAddr);
3531  RamDisk->Instance = (UINT16)Strtoi (InstanceStr);
3532  CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid);
3533
3534  return (EFI_DEVICE_PATH_PROTOCOL *)RamDisk;
3535}
3536
3537/**
3538  Converts a BBS text device path node to BBS device path structure.
3539
3540  @param TextDeviceNode  The input Text device path node.
3541
3542  @return A pointer to BBS device path structure.
3543
3544**/
3545static
3546EFI_DEVICE_PATH_PROTOCOL *
3547DevPathFromTextBbsPath (
3548  IN CHAR16  *TextDeviceNode
3549  )
3550{
3551  return DevPathFromTextGenericPath (BBS_DEVICE_PATH, TextDeviceNode);
3552}
3553
3554/**
3555  Converts a text device path node to BIOS Boot Specification device path structure.
3556
3557  @param TextDeviceNode  The input Text device path node.
3558
3559  @return A pointer to the newly-created BIOS Boot Specification device path structure.
3560
3561**/
3562static
3563EFI_DEVICE_PATH_PROTOCOL *
3564DevPathFromTextBBS (
3565  IN CHAR16  *TextDeviceNode
3566  )
3567{
3568  CHAR16               *TypeStr;
3569  CHAR16               *IdStr;
3570  CHAR16               *FlagsStr;
3571  CHAR8                *AsciiStr;
3572  BBS_BBS_DEVICE_PATH  *Bbs;
3573
3574  TypeStr  = GetNextParamStr (&TextDeviceNode);
3575  IdStr    = GetNextParamStr (&TextDeviceNode);
3576  FlagsStr = GetNextParamStr (&TextDeviceNode);
3577  Bbs      = (BBS_BBS_DEVICE_PATH *)CreateDeviceNode (
3578                                      BBS_DEVICE_PATH,
3579                                      BBS_BBS_DP,
3580                                      (UINT16)(sizeof (BBS_BBS_DEVICE_PATH) + StrLen (IdStr))
3581                                      );
3582
3583  if (StrCmp (TypeStr, "Floppy") == 0) {
3584    Bbs->DeviceType = BBS_TYPE_FLOPPY;
3585  } else if (StrCmp (TypeStr, "HD") == 0) {
3586    Bbs->DeviceType = BBS_TYPE_HARDDRIVE;
3587  } else if (StrCmp (TypeStr, "CDROM") == 0) {
3588    Bbs->DeviceType = BBS_TYPE_CDROM;
3589  } else if (StrCmp (TypeStr, "PCMCIA") == 0) {
3590    Bbs->DeviceType = BBS_TYPE_PCMCIA;
3591  } else if (StrCmp (TypeStr, "USB") == 0) {
3592    Bbs->DeviceType = BBS_TYPE_USB;
3593  } else if (StrCmp (TypeStr, "Network") == 0) {
3594    Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK;
3595  } else {
3596    Bbs->DeviceType = (UINT16)Strtoi (TypeStr);
3597  }
3598
3599  AsciiStr = Bbs->String;
3600  StrToAscii (IdStr, &AsciiStr);
3601
3602  Bbs->StatusFlag = (UINT16)Strtoi (FlagsStr);
3603
3604  return (EFI_DEVICE_PATH_PROTOCOL *)Bbs;
3605}
3606
3607/**
3608  Converts a text device path node to SATA device path structure.
3609
3610  @param TextDeviceNode  The input Text device path node.
3611
3612  @return A pointer to the newly-created SATA device path structure.
3613
3614**/
3615static
3616EFI_DEVICE_PATH_PROTOCOL *
3617DevPathFromTextSata (
3618  IN CHAR16  *TextDeviceNode
3619  )
3620{
3621  SATA_DEVICE_PATH  *Sata;
3622  CHAR16            *Param1;
3623  CHAR16            *Param2;
3624  CHAR16            *Param3;
3625
3626  Param1 = GetNextParamStr (&TextDeviceNode);
3627  Param2 = GetNextParamStr (&TextDeviceNode);
3628  Param3 = GetNextParamStr (&TextDeviceNode);
3629
3630  Sata = (SATA_DEVICE_PATH *)CreateDeviceNode (
3631                               MESSAGING_DEVICE_PATH,
3632                               MSG_SATA_DP,
3633                               (UINT16)sizeof (SATA_DEVICE_PATH)
3634                               );
3635  Sata->HBAPortNumber = (UINT16)Strtoi (Param1);
3636
3637  //
3638  // According to UEFI spec, if PMPN is not provided, the default is 0xFFFF
3639  //
3640  if (*Param2 == '\0' ) {
3641    Sata->PortMultiplierPortNumber = 0xFFFF;
3642  } else {
3643    Sata->PortMultiplierPortNumber = (UINT16)Strtoi (Param2);
3644  }
3645
3646  Sata->Lun = (UINT16)Strtoi (Param3);
3647
3648  return (EFI_DEVICE_PATH_PROTOCOL *)Sata;
3649}
3650
3651GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_FROM_TEXT_TABLE  mUefiDevicePathLibDevPathFromTextTable[] = {
3652  { "Path",                    DevPathFromTextPath                    },
3653
3654  { "HardwarePath",            DevPathFromTextHardwarePath            },
3655  { "Pci",                     DevPathFromTextPci                     },
3656  { "PcCard",                  DevPathFromTextPcCard                  },
3657  { "MemoryMapped",            DevPathFromTextMemoryMapped            },
3658  { "VenHw",                   DevPathFromTextVenHw                   },
3659  { "Ctrl",                    DevPathFromTextCtrl                    },
3660  { "BMC",                     DevPathFromTextBmc                     },
3661
3662  { "AcpiPath",                DevPathFromTextAcpiPath                },
3663  { "Acpi",                    DevPathFromTextAcpi                    },
3664  { "PciRoot",                 DevPathFromTextPciRoot                 },
3665  { "PcieRoot",                DevPathFromTextPcieRoot                },
3666  { "Floppy",                  DevPathFromTextFloppy                  },
3667  { "Keyboard",                DevPathFromTextKeyboard                },
3668  { "Serial",                  DevPathFromTextSerial                  },
3669  { "ParallelPort",            DevPathFromTextParallelPort            },
3670  { "AcpiEx",                  DevPathFromTextAcpiEx                  },
3671  { "AcpiExp",                 DevPathFromTextAcpiExp                 },
3672  { "AcpiAdr",                 DevPathFromTextAcpiAdr                 },
3673
3674  { "Msg",                     DevPathFromTextMsg                     },
3675  { "Ata",                     DevPathFromTextAta                     },
3676  { "Scsi",                    DevPathFromTextScsi                    },
3677  { "Fibre",                   DevPathFromTextFibre                   },
3678  { "FibreEx",                 DevPathFromTextFibreEx                 },
3679  { "I1394",                   DevPathFromText1394                    },
3680  { "USB",                     DevPathFromTextUsb                     },
3681  { "I2O",                     DevPathFromTextI2O                     },
3682  { "Infiniband",              DevPathFromTextInfiniband              },
3683  { "VenMsg",                  DevPathFromTextVenMsg                  },
3684  { "VenPcAnsi",               DevPathFromTextVenPcAnsi               },
3685  { "VenVt100",                DevPathFromTextVenVt100                },
3686  { "VenVt100Plus",            DevPathFromTextVenVt100Plus            },
3687  { "VenUtf8",                 DevPathFromTextVenUtf8                 },
3688  { "UartFlowCtrl",            DevPathFromTextUartFlowCtrl            },
3689  { "SAS",                     DevPathFromTextSAS                     },
3690  { "SasEx",                   DevPathFromTextSasEx                   },
3691  { "NVMe",                    DevPathFromTextNVMe                    },
3692  { "UFS",                     DevPathFromTextUfs                     },
3693  { "SD",                      DevPathFromTextSd                      },
3694  { "eMMC",                    DevPathFromTextEmmc                    },
3695  { "DebugPort",               DevPathFromTextDebugPort               },
3696  { "MAC",                     DevPathFromTextMAC                     },
3697  { "IPv4",                    DevPathFromTextIPv4                    },
3698  { "IPv6",                    DevPathFromTextIPv6                    },
3699  { "Uart",                    DevPathFromTextUart                    },
3700  { "UsbClass",                DevPathFromTextUsbClass                },
3701  { "UsbAudio",                DevPathFromTextUsbAudio                },
3702  { "UsbCDCControl",           DevPathFromTextUsbCDCControl           },
3703  { "UsbHID",                  DevPathFromTextUsbHID                  },
3704  { "UsbImage",                DevPathFromTextUsbImage                },
3705  { "UsbPrinter",              DevPathFromTextUsbPrinter              },
3706  { "UsbMassStorage",          DevPathFromTextUsbMassStorage          },
3707  { "UsbHub",                  DevPathFromTextUsbHub                  },
3708  { "UsbCDCData",              DevPathFromTextUsbCDCData              },
3709  { "UsbSmartCard",            DevPathFromTextUsbSmartCard            },
3710  { "UsbVideo",                DevPathFromTextUsbVideo                },
3711  { "UsbDiagnostic",           DevPathFromTextUsbDiagnostic           },
3712  { "UsbWireless",             DevPathFromTextUsbWireless             },
3713  { "UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate },
3714  { "UsbIrdaBridge",           DevPathFromTextUsbIrdaBridge           },
3715  { "UsbTestAndMeasurement",   DevPathFromTextUsbTestAndMeasurement   },
3716  { "UsbWwid",                 DevPathFromTextUsbWwid                 },
3717  { "Unit",                    DevPathFromTextUnit                    },
3718  { "iSCSI",                   DevPathFromTextiSCSI                   },
3719  { "Vlan",                    DevPathFromTextVlan                    },
3720  { "Dns",                     DevPathFromTextDns                     },
3721  { "Uri",                     DevPathFromTextUri                     },
3722  { "Bluetooth",               DevPathFromTextBluetooth               },
3723  { "Wi-Fi",                   DevPathFromTextWiFi                    },
3724  { "BluetoothLE",             DevPathFromTextBluetoothLE             },
3725  { "MediaPath",               DevPathFromTextMediaPath               },
3726  { "HD",                      DevPathFromTextHD                      },
3727  { "CDROM",                   DevPathFromTextCDROM                   },
3728  { "VenMedia",                DevPathFromTextVenMedia                },
3729  { "Media",                   DevPathFromTextMedia                   },
3730  { "Fv",                      DevPathFromTextFv                      },
3731  { "FvFile",                  DevPathFromTextFvFile                  },
3732  { "File",                    DevPathFromTextFilePath                },
3733  { "Offset",                  DevPathFromTextRelativeOffsetRange     },
3734  { "RamDisk",                 DevPathFromTextRamDisk                 },
3735  { "VirtualDisk",             DevPathFromTextVirtualDisk             },
3736  { "VirtualCD",               DevPathFromTextVirtualCd               },
3737  { "PersistentVirtualDisk",   DevPathFromTextPersistentVirtualDisk   },
3738  { "PersistentVirtualCD",     DevPathFromTextPersistentVirtualCd     },
3739
3740  { "BbsPath",                 DevPathFromTextBbsPath                 },
3741  { "BBS",                     DevPathFromTextBBS                     },
3742  { "Sata",                    DevPathFromTextSata                    },
3743  { NULL,                       NULL                                   }
3744};
3745
3746/**
3747  Convert text to the binary representation of a device node.
3748
3749  @param TextDeviceNode  TextDeviceNode points to the text representation of a device
3750                         node. Conversion starts with the first character and continues
3751                         until the first non-device node character.
3752
3753  @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
3754          insufficient memory or text unsupported.
3755
3756**/
3757static
3758EFI_DEVICE_PATH_PROTOCOL *
3759EFIAPI
3760UefiDevicePathLibConvertTextToDeviceNode (
3761  IN CONST CHAR16  *TextDeviceNode
3762  )
3763{
3764  DEVICE_PATH_FROM_TEXT     FromText;
3765  CHAR16                    *ParamStr;
3766  EFI_DEVICE_PATH_PROTOCOL  *DeviceNode;
3767  CHAR16                    *DeviceNodeStr;
3768  UINTN                     Index;
3769
3770  if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) {
3771    return NULL;
3772  }
3773
3774  ParamStr      = NULL;
3775  FromText      = NULL;
3776  DeviceNodeStr = UefiDevicePathLibStrDuplicate (TextDeviceNode);
3777  ASSERT (DeviceNodeStr != NULL);
3778
3779  for (Index = 0; mUefiDevicePathLibDevPathFromTextTable[Index].Function != NULL; Index++) {
3780    ParamStr = GetParamByNodeName (DeviceNodeStr, mUefiDevicePathLibDevPathFromTextTable[Index].DevicePathNodeText);
3781    if (ParamStr != NULL) {
3782      FromText = mUefiDevicePathLibDevPathFromTextTable[Index].Function;
3783      break;
3784    }
3785  }
3786
3787  if (FromText == NULL) {
3788    //
3789    // A file path
3790    //
3791    FromText   = DevPathFromTextFilePath;
3792    DeviceNode = FromText (DeviceNodeStr);
3793  } else {
3794    DeviceNode = FromText (ParamStr);
3795    FreePool (ParamStr);
3796  }
3797
3798  FreePool (DeviceNodeStr);
3799
3800  return DeviceNode;
3801}
3802
3803/**
3804  Convert text to the binary representation of a device path.
3805
3806
3807  @param TextDevicePath  TextDevicePath points to the text representation of a device
3808                         path. Conversion starts with the first character and continues
3809                         until the first non-device node character.
3810
3811  @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
3812          there was insufficient memory.
3813
3814**/
3815static
3816EFI_DEVICE_PATH_PROTOCOL *
3817EFIAPI
3818UefiDevicePathLibConvertTextToDevicePath (
3819  IN CONST CHAR16  *TextDevicePath
3820  )
3821{
3822  EFI_DEVICE_PATH_PROTOCOL  *DeviceNode;
3823  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
3824  CHAR16                    *DevicePathStr;
3825  CHAR16                    *Str;
3826  CHAR16                    *DeviceNodeStr;
3827  BOOLEAN                   IsInstanceEnd;
3828  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
3829
3830  if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) {
3831    return NULL;
3832  }
3833
3834  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocatePool (END_DEVICE_PATH_LENGTH);
3835  ASSERT (DevicePath != NULL);
3836  SetDevicePathEndNode (DevicePath);
3837
3838  DevicePathStr = UefiDevicePathLibStrDuplicate (TextDevicePath);
3839
3840  Str = DevicePathStr;
3841  while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) {
3842    DeviceNode = UefiDevicePathLibConvertTextToDeviceNode (DeviceNodeStr);
3843
3844    NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode);
3845    FreePool (DevicePath);
3846    FreePool (DeviceNode);
3847    DevicePath = NewDevicePath;
3848
3849    if (IsInstanceEnd) {
3850      DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *)AllocatePool (END_DEVICE_PATH_LENGTH);
3851      ASSERT (DeviceNode != NULL);
3852      SetDevicePathEndNode (DeviceNode);
3853      DeviceNode->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
3854
3855      NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode);
3856      FreePool (DevicePath);
3857      FreePool (DeviceNode);
3858      DevicePath = NewDevicePath;
3859    }
3860  }
3861
3862  FreePool (DevicePathStr);
3863  return DevicePath;
3864}
3865
3866ssize_t
3867efidp_parse_device_path(char *path, efidp out, size_t max)
3868{
3869	EFI_DEVICE_PATH_PROTOCOL *dp;
3870	UINTN len;
3871
3872	dp = UefiDevicePathLibConvertTextToDevicePath (path);
3873	if (dp == NULL)
3874		return -1;
3875	len = GetDevicePathSize(dp);
3876	if (len > max) {
3877		free(dp);
3878		return -1;
3879	}
3880	memcpy(out, dp, len);
3881	free(dp);
3882
3883	return len;
3884}
3885