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