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