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