1 /** @file
2 Common basic Library Functions
3 
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13 #ifdef __GNUC__
14 #include <unistd.h>
15 #else
16 #include <direct.h>
17 #endif
18 #include "CommonLib.h"
19 #include "EfiUtilityMsgs.h"
20 
21 #define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status)  \
22   do { \
23     ASSERT (Expression); \
24     if (!(Expression)) { \
25       return Status; \
26     } \
27   } while (FALSE)
28 
29 VOID
PeiZeroMem(IN VOID * Buffer,IN UINTN Size)30 PeiZeroMem (
31   IN VOID   *Buffer,
32   IN UINTN  Size
33   )
34 /*++
35 
36 Routine Description:
37 
38   Set Buffer to zero for Size bytes.
39 
40 Arguments:
41 
42   Buffer  - Memory to set.
43 
44   Size    - Number of bytes to set
45 
46 Returns:
47 
48   None
49 
50 --*/
51 {
52   INT8  *Ptr;
53 
54   Ptr = Buffer;
55   while (Size--) {
56     *(Ptr++) = 0;
57   }
58 }
59 
60 VOID
PeiCopyMem(IN VOID * Destination,IN VOID * Source,IN UINTN Length)61 PeiCopyMem (
62   IN VOID   *Destination,
63   IN VOID   *Source,
64   IN UINTN  Length
65   )
66 /*++
67 
68 Routine Description:
69 
70   Copy Length bytes from Source to Destination.
71 
72 Arguments:
73 
74   Destination - Target of copy
75 
76   Source      - Place to copy from
77 
78   Length      - Number of bytes to copy
79 
80 Returns:
81 
82   None
83 
84 --*/
85 {
86   CHAR8 *Destination8;
87   CHAR8 *Source8;
88 
89   Destination8  = Destination;
90   Source8       = Source;
91   while (Length--) {
92     *(Destination8++) = *(Source8++);
93   }
94 }
95 
96 VOID
ZeroMem(IN VOID * Buffer,IN UINTN Size)97 ZeroMem (
98   IN VOID   *Buffer,
99   IN UINTN  Size
100   )
101 {
102   PeiZeroMem (Buffer, Size);
103 }
104 
105 VOID
CopyMem(IN VOID * Destination,IN VOID * Source,IN UINTN Length)106 CopyMem (
107   IN VOID   *Destination,
108   IN VOID   *Source,
109   IN UINTN  Length
110   )
111 {
112   PeiCopyMem (Destination, Source, Length);
113 }
114 
115 INTN
CompareGuid(IN EFI_GUID * Guid1,IN EFI_GUID * Guid2)116 CompareGuid (
117   IN EFI_GUID     *Guid1,
118   IN EFI_GUID     *Guid2
119   )
120 /*++
121 
122 Routine Description:
123 
124   Compares to GUIDs
125 
126 Arguments:
127 
128   Guid1 - guid to compare
129   Guid2 - guid to compare
130 
131 Returns:
132   =  0  if Guid1 == Guid2
133   != 0  if Guid1 != Guid2
134 
135 --*/
136 {
137   INT32 *g1;
138   INT32 *g2;
139   INT32 r;
140 
141   //
142   // Compare 32 bits at a time
143   //
144   g1  = (INT32 *) Guid1;
145   g2  = (INT32 *) Guid2;
146 
147   r   = g1[0] - g2[0];
148   r |= g1[1] - g2[1];
149   r |= g1[2] - g2[2];
150   r |= g1[3] - g2[3];
151 
152   return r;
153 }
154 
155 
156 EFI_STATUS
GetFileImage(IN CHAR8 * InputFileName,OUT CHAR8 ** InputFileImage,OUT UINT32 * BytesRead)157 GetFileImage (
158   IN CHAR8    *InputFileName,
159   OUT CHAR8   **InputFileImage,
160   OUT UINT32  *BytesRead
161   )
162 /*++
163 
164 Routine Description:
165 
166   This function opens a file and reads it into a memory buffer.  The function
167   will allocate the memory buffer and returns the size of the buffer.
168 
169 Arguments:
170 
171   InputFileName     The name of the file to read.
172   InputFileImage    A pointer to the memory buffer.
173   BytesRead         The size of the memory buffer.
174 
175 Returns:
176 
177   EFI_SUCCESS              The function completed successfully.
178   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
179   EFI_ABORTED              An error occurred.
180   EFI_OUT_OF_RESOURCES     No resource to complete operations.
181 
182 --*/
183 {
184   FILE    *InputFile;
185   UINT32  FileSize;
186 
187   //
188   // Verify input parameters.
189   //
190   if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {
191     return EFI_INVALID_PARAMETER;
192   }
193   //
194   // Open the file and copy contents into a memory buffer.
195   //
196   //
197   // Open the file
198   //
199   InputFile = fopen (LongFilePath (InputFileName), "rb");
200   if (InputFile == NULL) {
201     Error (NULL, 0, 0001, "Error opening the input file", InputFileName);
202     return EFI_ABORTED;
203   }
204   //
205   // Go to the end so that we can determine the file size
206   //
207   if (fseek (InputFile, 0, SEEK_END)) {
208     Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
209     fclose (InputFile);
210     return EFI_ABORTED;
211   }
212   //
213   // Get the file size
214   //
215   FileSize = ftell (InputFile);
216   if (FileSize == -1) {
217     Error (NULL, 0, 0003, "Error parsing the input file", InputFileName);
218     fclose (InputFile);
219     return EFI_ABORTED;
220   }
221   //
222   // Allocate a buffer
223   //
224   *InputFileImage = malloc (FileSize);
225   if (*InputFileImage == NULL) {
226     fclose (InputFile);
227     return EFI_OUT_OF_RESOURCES;
228   }
229   //
230   // Reset to the beginning of the file
231   //
232   if (fseek (InputFile, 0, SEEK_SET)) {
233     Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
234     fclose (InputFile);
235     free (*InputFileImage);
236     *InputFileImage = NULL;
237     return EFI_ABORTED;
238   }
239   //
240   // Read all of the file contents.
241   //
242   *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);
243   if (*BytesRead != sizeof (UINT8) * FileSize) {
244     Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
245     fclose (InputFile);
246     free (*InputFileImage);
247     *InputFileImage = NULL;
248     return EFI_ABORTED;
249   }
250   //
251   // Close the file
252   //
253   fclose (InputFile);
254 
255   return EFI_SUCCESS;
256 }
257 
258 EFI_STATUS
PutFileImage(IN CHAR8 * OutputFileName,IN CHAR8 * OutputFileImage,IN UINT32 BytesToWrite)259 PutFileImage (
260   IN CHAR8    *OutputFileName,
261   IN CHAR8    *OutputFileImage,
262   IN UINT32   BytesToWrite
263   )
264 /*++
265 
266 Routine Description:
267 
268   This function opens a file and writes OutputFileImage into the file.
269 
270 Arguments:
271 
272   OutputFileName     The name of the file to write.
273   OutputFileImage    A pointer to the memory buffer.
274   BytesToWrite       The size of the memory buffer.
275 
276 Returns:
277 
278   EFI_SUCCESS              The function completed successfully.
279   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
280   EFI_ABORTED              An error occurred.
281   EFI_OUT_OF_RESOURCES     No resource to complete operations.
282 
283 --*/
284 {
285   FILE    *OutputFile;
286   UINT32  BytesWrote;
287 
288   //
289   // Verify input parameters.
290   //
291   if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) {
292     return EFI_INVALID_PARAMETER;
293   }
294   //
295   // Open the file and copy contents into a memory buffer.
296   //
297   //
298   // Open the file
299   //
300   OutputFile = fopen (LongFilePath (OutputFileName), "wb");
301   if (OutputFile == NULL) {
302     Error (NULL, 0, 0001, "Error opening the output file", OutputFileName);
303     return EFI_ABORTED;
304   }
305 
306   //
307   // Write all of the file contents.
308   //
309   BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile);
310   if (BytesWrote != sizeof (UINT8) * BytesToWrite) {
311     Error (NULL, 0, 0002, "Error writing the output file", OutputFileName);
312     fclose (OutputFile);
313     return EFI_ABORTED;
314   }
315   //
316   // Close the file
317   //
318   fclose (OutputFile);
319 
320   return EFI_SUCCESS;
321 }
322 
323 UINT8
CalculateChecksum8(IN UINT8 * Buffer,IN UINTN Size)324 CalculateChecksum8 (
325   IN UINT8        *Buffer,
326   IN UINTN        Size
327   )
328 /*++
329 
330 Routine Description:
331 
332   This function calculates the value needed for a valid UINT8 checksum
333 
334 Arguments:
335 
336   Buffer      Pointer to buffer containing byte data of component.
337   Size        Size of the buffer
338 
339 Returns:
340 
341   The 8 bit checksum value needed.
342 
343 --*/
344 {
345   return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));
346 }
347 
348 UINT8
CalculateSum8(IN UINT8 * Buffer,IN UINTN Size)349 CalculateSum8 (
350   IN UINT8  *Buffer,
351   IN UINTN  Size
352   )
353 /*++
354 
355 Routine Description::
356 
357   This function calculates the UINT8 sum for the requested region.
358 
359 Arguments:
360 
361   Buffer      Pointer to buffer containing byte data of component.
362   Size        Size of the buffer
363 
364 Returns:
365 
366   The 8 bit checksum value needed.
367 
368 --*/
369 {
370   UINTN Index;
371   UINT8 Sum;
372 
373   Sum = 0;
374 
375   //
376   // Perform the byte sum for buffer
377   //
378   for (Index = 0; Index < Size; Index++) {
379     Sum = (UINT8) (Sum + Buffer[Index]);
380   }
381 
382   return Sum;
383 }
384 
385 UINT16
CalculateChecksum16(IN UINT16 * Buffer,IN UINTN Size)386 CalculateChecksum16 (
387   IN UINT16       *Buffer,
388   IN UINTN        Size
389   )
390 /*++
391 
392 Routine Description::
393 
394   This function calculates the value needed for a valid UINT16 checksum
395 
396 Arguments:
397 
398   Buffer      Pointer to buffer containing byte data of component.
399   Size        Size of the buffer
400 
401 Returns:
402 
403   The 16 bit checksum value needed.
404 
405 --*/
406 {
407   return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));
408 }
409 
410 UINT16
CalculateSum16(IN UINT16 * Buffer,IN UINTN Size)411 CalculateSum16 (
412   IN UINT16       *Buffer,
413   IN UINTN        Size
414   )
415 /*++
416 
417 Routine Description:
418 
419   This function calculates the UINT16 sum for the requested region.
420 
421 Arguments:
422 
423   Buffer      Pointer to buffer containing byte data of component.
424   Size        Size of the buffer
425 
426 Returns:
427 
428   The 16 bit checksum
429 
430 --*/
431 {
432   UINTN   Index;
433   UINT16  Sum;
434 
435   Sum = 0;
436 
437   //
438   // Perform the word sum for buffer
439   //
440   for (Index = 0; Index < Size; Index++) {
441     Sum = (UINT16) (Sum + Buffer[Index]);
442   }
443 
444   return (UINT16) Sum;
445 }
446 
447 EFI_STATUS
PrintGuid(IN EFI_GUID * Guid)448 PrintGuid (
449   IN EFI_GUID *Guid
450   )
451 /*++
452 
453 Routine Description:
454 
455   This function prints a GUID to STDOUT.
456 
457 Arguments:
458 
459   Guid    Pointer to a GUID to print.
460 
461 Returns:
462 
463   EFI_SUCCESS             The GUID was printed.
464   EFI_INVALID_PARAMETER   The input was NULL.
465 
466 --*/
467 {
468   if (Guid == NULL) {
469     Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
470     return EFI_INVALID_PARAMETER;
471   }
472 
473   printf (
474     "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
475     (unsigned) Guid->Data1,
476     Guid->Data2,
477     Guid->Data3,
478     Guid->Data4[0],
479     Guid->Data4[1],
480     Guid->Data4[2],
481     Guid->Data4[3],
482     Guid->Data4[4],
483     Guid->Data4[5],
484     Guid->Data4[6],
485     Guid->Data4[7]
486     );
487   return EFI_SUCCESS;
488 }
489 
490 EFI_STATUS
PrintGuidToBuffer(IN EFI_GUID * Guid,IN OUT UINT8 * Buffer,IN UINT32 BufferLen,IN BOOLEAN Uppercase)491 PrintGuidToBuffer (
492   IN EFI_GUID     *Guid,
493   IN OUT UINT8    *Buffer,
494   IN UINT32       BufferLen,
495   IN BOOLEAN      Uppercase
496   )
497 /*++
498 
499 Routine Description:
500 
501   This function prints a GUID to a buffer
502 
503 Arguments:
504 
505   Guid      - Pointer to a GUID to print.
506   Buffer    - Pointer to a user-provided buffer to print to
507   BufferLen - Size of the Buffer
508   Uppercase - If use upper case.
509 
510 Returns:
511 
512   EFI_SUCCESS             The GUID was printed.
513   EFI_INVALID_PARAMETER   The input was NULL.
514   EFI_BUFFER_TOO_SMALL    The input buffer was not big enough
515 
516 --*/
517 {
518   if (Guid == NULL) {
519     Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
520     return EFI_INVALID_PARAMETER;
521   }
522 
523   if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {
524     Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size");
525     return EFI_BUFFER_TOO_SMALL;
526   }
527 
528   if (Uppercase) {
529     sprintf (
530       (CHAR8 *)Buffer,
531       "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
532       (unsigned) Guid->Data1,
533       Guid->Data2,
534       Guid->Data3,
535       Guid->Data4[0],
536       Guid->Data4[1],
537       Guid->Data4[2],
538       Guid->Data4[3],
539       Guid->Data4[4],
540       Guid->Data4[5],
541       Guid->Data4[6],
542       Guid->Data4[7]
543       );
544   } else {
545     sprintf (
546       (CHAR8 *)Buffer,
547       "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
548       (unsigned) Guid->Data1,
549       Guid->Data2,
550       Guid->Data3,
551       Guid->Data4[0],
552       Guid->Data4[1],
553       Guid->Data4[2],
554       Guid->Data4[3],
555       Guid->Data4[4],
556       Guid->Data4[5],
557       Guid->Data4[6],
558       Guid->Data4[7]
559       );
560   }
561 
562   return EFI_SUCCESS;
563 }
564 
565 #ifdef __GNUC__
566 
_filelength(int fd)567 size_t _filelength(int fd)
568 {
569   struct stat stat_buf;
570   fstat(fd, &stat_buf);
571   return stat_buf.st_size;
572 }
573 
574 #ifndef __CYGWIN__
strlwr(char * s)575 char *strlwr(char *s)
576 {
577   char *p = s;
578   for(;*s;s++) {
579     *s = tolower(*s);
580   }
581   return p;
582 }
583 #endif
584 #endif
585 
586 #define WINDOWS_EXTENSION_PATH "\\\\?\\"
587 #define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"
588 
589 //
590 // Global data to store full file path. It is not required to be free.
591 //
592 CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH];
593 
594 CHAR8 *
LongFilePath(IN CHAR8 * FileName)595 LongFilePath (
596  IN CHAR8 *FileName
597  )
598 /*++
599 
600 Routine Description:
601   Convert FileName to the long file path, which can support larger than 260 length.
602 
603 Arguments:
604   FileName         - FileName.
605 
606 Returns:
607   LongFilePath      A pointer to the converted long file path.
608 
609 --*/
610 {
611 #ifdef __GNUC__
612   //
613   // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here.
614   // unix has no limitation on file path. Just return FileName.
615   //
616   return FileName;
617 #else
618   CHAR8 *RootPath;
619   CHAR8 *PathPointer;
620   CHAR8 *NextPointer;
621 
622   PathPointer = (CHAR8 *) FileName;
623 
624   if (FileName != NULL) {
625     //
626     // Add the extension string first to support long file path.
627     //
628     mCommonLibFullPath[0] = 0;
629     strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH);
630 
631     if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') {
632       //
633       // network path like \\server\share to \\?\UNC\server\share
634       //
635       strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH);
636       FileName ++;
637     } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) {
638       //
639       // Relative file path. Convert it to absolute path.
640       //
641       RootPath = getcwd (NULL, 0);
642       if (RootPath != NULL) {
643         if (strlen (mCommonLibFullPath) + strlen (RootPath) > MAX_LONG_FILE_PATH - 1) {
644           Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
645           free (RootPath);
646           return NULL;
647         }
648         strncat (mCommonLibFullPath, RootPath, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
649         if (FileName[0] != '\\' && FileName[0] != '/') {
650           if (strlen (mCommonLibFullPath) + 1 > MAX_LONG_FILE_PATH - 1) {
651             Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
652             free (RootPath);
653             return NULL;
654           }
655           //
656           // Attach directory separator
657           //
658           strncat (mCommonLibFullPath, "\\", MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
659         }
660         free (RootPath);
661       }
662     }
663 
664     //
665     // Construct the full file path
666     //
667     if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) {
668       Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName);
669       return NULL;
670     }
671     strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
672 
673     //
674     // Convert directory separator '/' to '\\'
675     //
676     PathPointer = (CHAR8 *) mCommonLibFullPath;
677     do {
678       if (*PathPointer == '/') {
679         *PathPointer = '\\';
680       }
681     } while (*PathPointer ++ != '\0');
682 
683     //
684     // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
685     //
686     if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {
687       *(PathPointer + 2) = '\0';
688       strncat (mCommonLibFullPath, PathPointer + 3, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
689     }
690 
691     //
692     // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.
693     //
694     while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {
695       *PathPointer = '\0';
696       strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
697     }
698 
699     //
700     // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
701     //
702     while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {
703       *PathPointer = '\0';
704       strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
705     }
706 
707     //
708     // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.
709     //
710     while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {
711       NextPointer = PathPointer + 3;
712       do {
713         PathPointer --;
714       } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');
715 
716       if (*PathPointer == '\\') {
717         //
718         // Skip one directory
719         //
720         *PathPointer = '\0';
721         strncat (mCommonLibFullPath, NextPointer, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
722       } else {
723         //
724         // No directory is found. Just break.
725         //
726         break;
727       }
728     }
729 
730     PathPointer = mCommonLibFullPath;
731   }
732 
733   return PathPointer;
734 #endif
735 }
736 
737 CHAR16
InternalCharToUpper(CHAR16 Char)738 InternalCharToUpper (
739         CHAR16                    Char
740   )
741 {
742   if (Char >= L'a' && Char <= L'z') {
743     return (CHAR16) (Char - (L'a' - L'A'));
744   }
745 
746   return Char;
747 }
748 
749 UINTN
StrnLenS(CONST CHAR16 * String,UINTN MaxSize)750 StrnLenS (
751    CONST CHAR16              *String,
752    UINTN                     MaxSize
753   )
754 {
755   UINTN     Length;
756 
757   ASSERT (((UINTN) String & BIT0) == 0);
758 
759   //
760   // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.
761   //
762   if ((String == NULL) || (MaxSize == 0)) {
763     return 0;
764   }
765 
766   Length = 0;
767   while (String[Length] != 0) {
768     if (Length >= MaxSize - 1) {
769       return MaxSize;
770     }
771     Length++;
772   }
773   return Length;
774 }
775 
776 
777 VOID *
InternalAllocatePool(UINTN AllocationSize)778 InternalAllocatePool (
779    UINTN   AllocationSize
780   )
781 {
782   VOID * Memory;
783 
784   Memory = malloc(AllocationSize);
785   ASSERT(Memory != NULL);
786   return Memory;
787 }
788 
789 
790 VOID *
InternalReallocatePool(UINTN OldSize,UINTN NewSize,VOID * OldBuffer OPTIONAL)791 InternalReallocatePool (
792    UINTN            OldSize,
793    UINTN            NewSize,
794    VOID             *OldBuffer  OPTIONAL
795   )
796 {
797   VOID  *NewBuffer;
798 
799   NewBuffer = AllocateZeroPool (NewSize);
800   if (NewBuffer != NULL && OldBuffer != NULL) {
801     memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
802     free(OldBuffer);
803   }
804   return NewBuffer;
805 }
806 
807 VOID *
ReallocatePool(UINTN OldSize,UINTN NewSize,VOID * OldBuffer OPTIONAL)808 ReallocatePool (
809    UINTN  OldSize,
810    UINTN  NewSize,
811    VOID   *OldBuffer  OPTIONAL
812   )
813 {
814   return InternalReallocatePool (OldSize, NewSize, OldBuffer);
815 }
816 
817 /**
818   Returns the length of a Null-terminated Unicode string.
819 
820   This function returns the number of Unicode characters in the Null-terminated
821   Unicode string specified by String.
822 
823   If String is NULL, then ASSERT().
824   If String is not aligned on a 16-bit boundary, then ASSERT().
825   If PcdMaximumUnicodeStringLength is not zero, and String contains more than
826   PcdMaximumUnicodeStringLength Unicode characters, not including the
827   Null-terminator, then ASSERT().
828 
829   @param  String  A pointer to a Null-terminated Unicode string.
830 
831   @return The length of String.
832 
833 **/
834 UINTN
StrLen(CONST CHAR16 * String)835 StrLen (
836   CONST CHAR16              *String
837   )
838 {
839   UINTN   Length;
840 
841   ASSERT (String != NULL);
842   ASSERT (((UINTN) String & BIT0) == 0);
843 
844   for (Length = 0; *String != L'\0'; String++, Length++) {
845     //
846     // If PcdMaximumUnicodeStringLength is not zero,
847     // length should not more than PcdMaximumUnicodeStringLength
848     //
849   }
850   return Length;
851 }
852 
853 BOOLEAN
InternalSafeStringIsOverlap(IN VOID * Base1,IN UINTN Size1,IN VOID * Base2,IN UINTN Size2)854 InternalSafeStringIsOverlap (
855   IN VOID    *Base1,
856   IN UINTN   Size1,
857   IN VOID    *Base2,
858   IN UINTN   Size2
859   )
860 {
861   if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||
862       (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {
863     return TRUE;
864   }
865   return FALSE;
866 }
867 
868 BOOLEAN
InternalSafeStringNoStrOverlap(IN CHAR16 * Str1,IN UINTN Size1,IN CHAR16 * Str2,IN UINTN Size2)869 InternalSafeStringNoStrOverlap (
870   IN CHAR16  *Str1,
871   IN UINTN   Size1,
872   IN CHAR16  *Str2,
873   IN UINTN   Size2
874   )
875 {
876   return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));
877 }
878 
879 /**
880   Convert a Null-terminated Unicode decimal string to a value of type UINT64.
881 
882   This function outputs a value of type UINT64 by interpreting the contents of
883   the Unicode string specified by String as a decimal number. The format of the
884   input Unicode string String is:
885 
886                   [spaces] [decimal digits].
887 
888   The valid decimal digit character is in the range [0-9]. The function will
889   ignore the pad space, which includes spaces or tab characters, before
890   [decimal digits]. The running zero in the beginning of [decimal digits] will
891   be ignored. Then, the function stops at the first character that is a not a
892   valid decimal character or a Null-terminator, whichever one comes first.
893 
894   If String is NULL, then ASSERT().
895   If Data is NULL, then ASSERT().
896   If String is not aligned in a 16-bit boundary, then ASSERT().
897   If PcdMaximumUnicodeStringLength is not zero, and String contains more than
898   PcdMaximumUnicodeStringLength Unicode characters, not including the
899   Null-terminator, then ASSERT().
900 
901   If String has no valid decimal digits in the above format, then 0 is stored
902   at the location pointed to by Data.
903   If the number represented by String exceeds the range defined by UINT64, then
904   MAX_UINT64 is stored at the location pointed to by Data.
905 
906   If EndPointer is not NULL, a pointer to the character that stopped the scan
907   is stored at the location pointed to by EndPointer. If String has no valid
908   decimal digits right after the optional pad spaces, the value of String is
909   stored at the location pointed to by EndPointer.
910 
911   @param  String                   Pointer to a Null-terminated Unicode string.
912   @param  EndPointer               Pointer to character that stops scan.
913   @param  Data                     Pointer to the converted value.
914 
915   @retval RETURN_SUCCESS           Value is translated from String.
916   @retval RETURN_INVALID_PARAMETER If String is NULL.
917                                    If Data is NULL.
918                                    If PcdMaximumUnicodeStringLength is not
919                                    zero, and String contains more than
920                                    PcdMaximumUnicodeStringLength Unicode
921                                    characters, not including the
922                                    Null-terminator.
923   @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
924                                    the range defined by UINT64.
925 
926 **/
927 RETURN_STATUS
StrDecimalToUint64S(CONST CHAR16 * String,CHAR16 ** EndPointer,OPTIONAL UINT64 * Data)928 StrDecimalToUint64S (
929     CONST CHAR16             *String,
930          CHAR16             **EndPointer,  OPTIONAL
931          UINT64             *Data
932   )
933 {
934   ASSERT (((UINTN) String & BIT0) == 0);
935 
936   //
937   // 1. Neither String nor Data shall be a null pointer.
938   //
939   SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
940   SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
941 
942   //
943   // 2. The length of String shall not be greater than RSIZE_MAX.
944   //
945   if (RSIZE_MAX != 0) {
946     SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
947   }
948 
949   if (EndPointer != NULL) {
950     *EndPointer = (CHAR16 *) String;
951   }
952 
953   //
954   // Ignore the pad spaces (space or tab)
955   //
956   while ((*String == L' ') || (*String == L'\t')) {
957     String++;
958   }
959 
960   //
961   // Ignore leading Zeros after the spaces
962   //
963   while (*String == L'0') {
964     String++;
965   }
966 
967   *Data = 0;
968 
969   while (InternalIsDecimalDigitCharacter (*String)) {
970     //
971     // If the number represented by String overflows according to the range
972     // defined by UINT64, then MAX_UINT64 is stored in *Data and
973     // RETURN_UNSUPPORTED is returned.
974     //
975     if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {
976       *Data = MAX_UINT64;
977       if (EndPointer != NULL) {
978         *EndPointer = (CHAR16 *) String;
979       }
980       return RETURN_UNSUPPORTED;
981     }
982 
983     *Data = (*Data) * 10 + (*String - L'0');
984     String++;
985   }
986 
987   if (EndPointer != NULL) {
988     *EndPointer = (CHAR16 *) String;
989   }
990   return RETURN_SUCCESS;
991 }
992 
993 /**
994   Convert a Null-terminated Unicode hexadecimal string to a value of type
995   UINT64.
996 
997   This function outputs a value of type UINT64 by interpreting the contents of
998   the Unicode string specified by String as a hexadecimal number. The format of
999   the input Unicode string String is:
1000 
1001                   [spaces][zeros][x][hexadecimal digits].
1002 
1003   The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
1004   The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
1005   If "x" appears in the input string, it must be prefixed with at least one 0.
1006   The function will ignore the pad space, which includes spaces or tab
1007   characters, before [zeros], [x] or [hexadecimal digit]. The running zero
1008   before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
1009   after [x] or the first valid hexadecimal digit. Then, the function stops at
1010   the first character that is a not a valid hexadecimal character or NULL,
1011   whichever one comes first.
1012 
1013   If String is NULL, then ASSERT().
1014   If Data is NULL, then ASSERT().
1015   If String is not aligned in a 16-bit boundary, then ASSERT().
1016   If PcdMaximumUnicodeStringLength is not zero, and String contains more than
1017   PcdMaximumUnicodeStringLength Unicode characters, not including the
1018   Null-terminator, then ASSERT().
1019 
1020   If String has no valid hexadecimal digits in the above format, then 0 is
1021   stored at the location pointed to by Data.
1022   If the number represented by String exceeds the range defined by UINT64, then
1023   MAX_UINT64 is stored at the location pointed to by Data.
1024 
1025   If EndPointer is not NULL, a pointer to the character that stopped the scan
1026   is stored at the location pointed to by EndPointer. If String has no valid
1027   hexadecimal digits right after the optional pad spaces, the value of String
1028   is stored at the location pointed to by EndPointer.
1029 
1030   @param  String                   Pointer to a Null-terminated Unicode string.
1031   @param  EndPointer               Pointer to character that stops scan.
1032   @param  Data                     Pointer to the converted value.
1033 
1034   @retval RETURN_SUCCESS           Value is translated from String.
1035   @retval RETURN_INVALID_PARAMETER If String is NULL.
1036                                    If Data is NULL.
1037                                    If PcdMaximumUnicodeStringLength is not
1038                                    zero, and String contains more than
1039                                    PcdMaximumUnicodeStringLength Unicode
1040                                    characters, not including the
1041                                    Null-terminator.
1042   @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
1043                                    the range defined by UINT64.
1044 
1045 **/
1046 RETURN_STATUS
StrHexToUint64S(CONST CHAR16 * String,CHAR16 ** EndPointer,OPTIONAL UINT64 * Data)1047 StrHexToUint64S (
1048     CONST CHAR16             *String,
1049          CHAR16             **EndPointer,  OPTIONAL
1050          UINT64             *Data
1051   )
1052 {
1053   ASSERT (((UINTN) String & BIT0) == 0);
1054 
1055   //
1056   // 1. Neither String nor Data shall be a null pointer.
1057   //
1058   SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1059   SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
1060 
1061   //
1062   // 2. The length of String shall not be greater than RSIZE_MAX.
1063   //
1064   if (RSIZE_MAX != 0) {
1065     SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1066   }
1067 
1068   if (EndPointer != NULL) {
1069     *EndPointer = (CHAR16 *) String;
1070   }
1071 
1072   //
1073   // Ignore the pad spaces (space or tab)
1074   //
1075   while ((*String == L' ') || (*String == L'\t')) {
1076     String++;
1077   }
1078 
1079   //
1080   // Ignore leading Zeros after the spaces
1081   //
1082   while (*String == L'0') {
1083     String++;
1084   }
1085 
1086   if (InternalCharToUpper (*String) == L'X') {
1087     if (*(String - 1) != L'0') {
1088       *Data = 0;
1089       return RETURN_SUCCESS;
1090     }
1091     //
1092     // Skip the 'X'
1093     //
1094     String++;
1095   }
1096 
1097   *Data = 0;
1098 
1099   while (InternalIsHexaDecimalDigitCharacter (*String)) {
1100     //
1101     // If the number represented by String overflows according to the range
1102     // defined by UINT64, then MAX_UINT64 is stored in *Data and
1103     // RETURN_UNSUPPORTED is returned.
1104     //
1105     if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {
1106       *Data = MAX_UINT64;
1107       if (EndPointer != NULL) {
1108         *EndPointer = (CHAR16 *) String;
1109       }
1110       return RETURN_UNSUPPORTED;
1111     }
1112 
1113     *Data =  ((*Data) << 4) + InternalHexCharToUintn (*String);
1114     String++;
1115   }
1116 
1117   if (EndPointer != NULL) {
1118     *EndPointer = (CHAR16 *) String;
1119   }
1120   return RETURN_SUCCESS;
1121 }
1122 
1123 UINT64
StrDecimalToUint64(CONST CHAR16 * String)1124 StrDecimalToUint64 (
1125   CONST CHAR16              *String
1126   )
1127 {
1128   UINT64     Result;
1129 
1130   StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);
1131   return Result;
1132 }
1133 
1134 
1135 UINT64
StrHexToUint64(CONST CHAR16 * String)1136 StrHexToUint64 (
1137   CONST CHAR16             *String
1138   )
1139 {
1140   UINT64    Result;
1141 
1142   StrHexToUint64S (String, (CHAR16 **) NULL, &Result);
1143   return Result;
1144 }
1145 
1146 UINTN
StrSize(CONST CHAR16 * String)1147 StrSize (
1148   CONST CHAR16              *String
1149   )
1150 {
1151   return (StrLen (String) + 1) * sizeof (*String);
1152 }
1153 
1154 
1155 UINT64
ReadUnaligned64(CONST UINT64 * Buffer)1156 ReadUnaligned64 (
1157    CONST UINT64              *Buffer
1158   )
1159 {
1160   ASSERT (Buffer != NULL);
1161 
1162   return *Buffer;
1163 }
1164 
1165 UINT64
WriteUnaligned64(UINT64 * Buffer,UINT64 Value)1166 WriteUnaligned64 (
1167    UINT64                    *Buffer,
1168    UINT64                    Value
1169   )
1170 {
1171   ASSERT (Buffer != NULL);
1172 
1173   return *Buffer = Value;
1174 }
1175 
1176 
1177 EFI_GUID *
CopyGuid(EFI_GUID * DestinationGuid,CONST EFI_GUID * SourceGuid)1178 CopyGuid (
1179    EFI_GUID         *DestinationGuid,
1180    CONST EFI_GUID  *SourceGuid
1181   )
1182 {
1183   WriteUnaligned64 (
1184     (UINT64*)DestinationGuid,
1185     ReadUnaligned64 ((CONST UINT64*)SourceGuid)
1186     );
1187   WriteUnaligned64 (
1188     (UINT64*)DestinationGuid + 1,
1189     ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
1190     );
1191   return DestinationGuid;
1192 }
1193 
1194 UINT16
SwapBytes16(UINT16 Value)1195 SwapBytes16 (
1196   UINT16                    Value
1197   )
1198 {
1199   return (UINT16) ((Value<< 8) | (Value>> 8));
1200 }
1201 
1202 
1203 UINT32
SwapBytes32(UINT32 Value)1204 SwapBytes32 (
1205   UINT32                    Value
1206   )
1207 {
1208   UINT32  LowerBytes;
1209   UINT32  HigherBytes;
1210 
1211   LowerBytes  = (UINT32) SwapBytes16 ((UINT16) Value);
1212   HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));
1213   return (LowerBytes << 16 | HigherBytes);
1214 }
1215 
1216 BOOLEAN
InternalIsDecimalDigitCharacter(CHAR16 Char)1217 InternalIsDecimalDigitCharacter (
1218   CHAR16                    Char
1219   )
1220 {
1221   return (BOOLEAN) (Char >= L'0' && Char <= L'9');
1222 }
1223 
1224 VOID *
InternalAllocateCopyPool(UINTN AllocationSize,CONST VOID * Buffer)1225 InternalAllocateCopyPool (
1226    UINTN            AllocationSize,
1227    CONST VOID       *Buffer
1228   )
1229 {
1230   VOID  *Memory;
1231 
1232   ASSERT (Buffer != NULL);
1233 
1234   Memory = malloc (AllocationSize);
1235   if (Memory != NULL) {
1236      Memory = memcpy (Memory, Buffer, AllocationSize);
1237   }
1238   return Memory;
1239 }
1240 
1241 BOOLEAN
InternalIsHexaDecimalDigitCharacter(CHAR16 Char)1242 InternalIsHexaDecimalDigitCharacter (
1243   CHAR16                    Char
1244   )
1245 {
1246 
1247   return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||
1248     (Char >= L'A' && Char <= L'F') ||
1249     (Char >= L'a' && Char <= L'f'));
1250 }
1251 
1252 UINTN
InternalHexCharToUintn(CHAR16 Char)1253 InternalHexCharToUintn (
1254         CHAR16                    Char
1255   )
1256 {
1257   if (InternalIsDecimalDigitCharacter (Char)) {
1258     return Char - L'0';
1259   }
1260 
1261   return (10 + InternalCharToUpper (Char) - L'A');
1262 }
1263 
1264 
1265 /**
1266   Convert a Null-terminated Unicode hexadecimal string to a byte array.
1267 
1268   This function outputs a byte array by interpreting the contents of
1269   the Unicode string specified by String in hexadecimal format. The format of
1270   the input Unicode string String is:
1271 
1272                   [XX]*
1273 
1274   X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
1275   The function decodes every two hexadecimal digit characters as one byte. The
1276   decoding stops after Length of characters and outputs Buffer containing
1277   (Length / 2) bytes.
1278 
1279   If String is not aligned in a 16-bit boundary, then ASSERT().
1280 
1281   If String is NULL, then ASSERT().
1282 
1283   If Buffer is NULL, then ASSERT().
1284 
1285   If Length is not multiple of 2, then ASSERT().
1286 
1287   If PcdMaximumUnicodeStringLength is not zero and Length is greater than
1288   PcdMaximumUnicodeStringLength, then ASSERT().
1289 
1290   If MaxBufferSize is less than (Length / 2), then ASSERT().
1291 
1292   @param  String                   Pointer to a Null-terminated Unicode string.
1293   @param  Length                   The number of Unicode characters to decode.
1294   @param  Buffer                   Pointer to the converted bytes array.
1295   @param  MaxBufferSize            The maximum size of Buffer.
1296 
1297   @retval RETURN_SUCCESS           Buffer is translated from String.
1298   @retval RETURN_INVALID_PARAMETER If String is NULL.
1299                                    If Data is NULL.
1300                                    If Length is not multiple of 2.
1301                                    If PcdMaximumUnicodeStringLength is not zero,
1302                                     and Length is greater than
1303                                     PcdMaximumUnicodeStringLength.
1304   @retval RETURN_UNSUPPORTED       If Length of characters from String contain
1305                                     a character that is not valid hexadecimal
1306                                     digit characters, or a Null-terminator.
1307   @retval RETURN_BUFFER_TOO_SMALL  If MaxBufferSize is less than (Length / 2).
1308 **/
1309 RETURN_STATUS
StrHexToBytes(CONST CHAR16 * String,UINTN Length,UINT8 * Buffer,UINTN MaxBufferSize)1310 StrHexToBytes (
1311    CONST CHAR16       *String,
1312    UINTN              Length,
1313    UINT8              *Buffer,
1314    UINTN              MaxBufferSize
1315   )
1316 {
1317   UINTN                  Index;
1318 
1319   ASSERT (((UINTN) String & BIT0) == 0);
1320 
1321   //
1322   // 1. None of String or Buffer shall be a null pointer.
1323   //
1324   SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1325   SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);
1326 
1327   //
1328   // 2. Length shall not be greater than RSIZE_MAX.
1329   //
1330   if (RSIZE_MAX != 0) {
1331     SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1332   }
1333 
1334   //
1335   // 3. Length shall not be odd.
1336   //
1337   SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);
1338 
1339   //
1340   // 4. MaxBufferSize shall equal to or greater than Length / 2.
1341   //
1342   SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);
1343 
1344   //
1345   // 5. String shall not contains invalid hexadecimal digits.
1346   //
1347   for (Index = 0; Index < Length; Index++) {
1348     if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {
1349       break;
1350     }
1351   }
1352   if (Index != Length) {
1353     return RETURN_UNSUPPORTED;
1354   }
1355 
1356   //
1357   // Convert the hex string to bytes.
1358   //
1359   for(Index = 0; Index < Length; Index++) {
1360 
1361     //
1362     // For even characters, write the upper nibble for each buffer byte,
1363     // and for even characters, the lower nibble.
1364     //
1365     if ((Index & BIT0) == 0) {
1366       Buffer[Index / 2]  = (UINT8) InternalHexCharToUintn (String[Index]) << 4;
1367     } else {
1368       Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);
1369     }
1370   }
1371   return RETURN_SUCCESS;
1372 }
1373 
1374 /**
1375   Convert a Null-terminated Unicode GUID string to a value of type
1376   EFI_GUID.
1377 
1378   This function outputs a GUID value by interpreting the contents of
1379   the Unicode string specified by String. The format of the input
1380   Unicode string String consists of 36 characters, as follows:
1381 
1382                   aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
1383 
1384   The pairs aa - pp are two characters in the range [0-9], [a-f] and
1385   [A-F], with each pair representing a single byte hexadecimal value.
1386 
1387   The mapping between String and the EFI_GUID structure is as follows:
1388                   aa          Data1[24:31]
1389                   bb          Data1[16:23]
1390                   cc          Data1[8:15]
1391                   dd          Data1[0:7]
1392                   ee          Data2[8:15]
1393                   ff          Data2[0:7]
1394                   gg          Data3[8:15]
1395                   hh          Data3[0:7]
1396                   ii          Data4[0:7]
1397                   jj          Data4[8:15]
1398                   kk          Data4[16:23]
1399                   ll          Data4[24:31]
1400                   mm          Data4[32:39]
1401                   nn          Data4[40:47]
1402                   oo          Data4[48:55]
1403                   pp          Data4[56:63]
1404 
1405   If String is NULL, then ASSERT().
1406   If Guid is NULL, then ASSERT().
1407   If String is not aligned in a 16-bit boundary, then ASSERT().
1408 
1409   @param  String                   Pointer to a Null-terminated Unicode string.
1410   @param  Guid                     Pointer to the converted GUID.
1411 
1412   @retval RETURN_SUCCESS           Guid is translated from String.
1413   @retval RETURN_INVALID_PARAMETER If String is NULL.
1414                                    If Data is NULL.
1415   @retval RETURN_UNSUPPORTED       If String is not as the above format.
1416 
1417 **/
1418 RETURN_STATUS
StrToGuid(CONST CHAR16 * String,EFI_GUID * Guid)1419 StrToGuid (
1420    CONST CHAR16       *String,
1421    EFI_GUID           *Guid
1422   )
1423 {
1424   RETURN_STATUS          Status;
1425   EFI_GUID               LocalGuid;
1426 
1427   ASSERT (((UINTN) String & BIT0) == 0);
1428 
1429   //
1430   // 1. None of String or Guid shall be a null pointer.
1431   //
1432   SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1433   SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);
1434 
1435   //
1436   // Get aabbccdd in big-endian.
1437   //
1438   Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));
1439   if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {
1440     return RETURN_UNSUPPORTED;
1441   }
1442   //
1443   // Convert big-endian to little-endian.
1444   //
1445   LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);
1446   String += 2 * sizeof (LocalGuid.Data1) + 1;
1447 
1448   //
1449   // Get eeff in big-endian.
1450   //
1451   Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));
1452   if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {
1453     return RETURN_UNSUPPORTED;
1454   }
1455   //
1456   // Convert big-endian to little-endian.
1457   //
1458   LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);
1459   String += 2 * sizeof (LocalGuid.Data2) + 1;
1460 
1461   //
1462   // Get gghh in big-endian.
1463   //
1464   Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));
1465   if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {
1466     return RETURN_UNSUPPORTED;
1467   }
1468   //
1469   // Convert big-endian to little-endian.
1470   //
1471   LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);
1472   String += 2 * sizeof (LocalGuid.Data3) + 1;
1473 
1474   //
1475   // Get iijj.
1476   //
1477   Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);
1478   if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {
1479     return RETURN_UNSUPPORTED;
1480   }
1481   String += 2 * 2 + 1;
1482 
1483   //
1484   // Get kkllmmnnoopp.
1485   //
1486   Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);
1487   if (RETURN_ERROR (Status)) {
1488     return RETURN_UNSUPPORTED;
1489   }
1490 
1491   CopyGuid (Guid, &LocalGuid);
1492   return RETURN_SUCCESS;
1493 }
1494 
1495 /**
1496   Compares up to a specified length the contents of two Null-terminated Unicode strings,
1497   and returns the difference between the first mismatched Unicode characters.
1498 
1499   This function compares the Null-terminated Unicode string FirstString to the
1500   Null-terminated Unicode string SecondString. At most, Length Unicode
1501   characters will be compared. If Length is 0, then 0 is returned. If
1502   FirstString is identical to SecondString, then 0 is returned. Otherwise, the
1503   value returned is the first mismatched Unicode character in SecondString
1504   subtracted from the first mismatched Unicode character in FirstString.
1505 
1506   If Length > 0 and FirstString is NULL, then ASSERT().
1507   If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().
1508   If Length > 0 and SecondString is NULL, then ASSERT().
1509   If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().
1510   If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
1511   PcdMaximumUnicodeStringLength, then ASSERT().
1512   If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than
1513   PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
1514   then ASSERT().
1515   If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than
1516   PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
1517   then ASSERT().
1518 
1519   @param  FirstString   A pointer to a Null-terminated Unicode string.
1520   @param  SecondString  A pointer to a Null-terminated Unicode string.
1521   @param  Length        The maximum number of Unicode characters to compare.
1522 
1523   @retval 0      FirstString is identical to SecondString.
1524   @return others FirstString is not identical to SecondString.
1525 
1526 **/
1527 INTN
StrnCmp(CONST CHAR16 * FirstString,CONST CHAR16 * SecondString,UINTN Length)1528 StrnCmp (
1529         CONST CHAR16              *FirstString,
1530         CONST CHAR16              *SecondString,
1531         UINTN                     Length
1532   )
1533 {
1534   if (Length == 0) {
1535     return 0;
1536   }
1537 
1538   //
1539   // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
1540   // Length tests are performed inside StrLen().
1541   //
1542   ASSERT (StrSize (FirstString) != 0);
1543   ASSERT (StrSize (SecondString) != 0);
1544 
1545   while ((*FirstString != L'\0') &&
1546          (*SecondString != L'\0') &&
1547          (*FirstString == *SecondString) &&
1548          (Length > 1)) {
1549     FirstString++;
1550     SecondString++;
1551     Length--;
1552   }
1553 
1554   return *FirstString - *SecondString;
1555 }
1556 
1557 VOID *
AllocateCopyPool(UINTN AllocationSize,CONST VOID * Buffer)1558 AllocateCopyPool (
1559    UINTN       AllocationSize,
1560    CONST VOID  *Buffer
1561   )
1562 {
1563   return InternalAllocateCopyPool (AllocationSize, Buffer);
1564 }
1565 
1566 INTN
StrCmp(CONST CHAR16 * FirstString,CONST CHAR16 * SecondString)1567 StrCmp (
1568   CONST CHAR16              *FirstString,
1569   CONST CHAR16              *SecondString
1570   )
1571 {
1572   //
1573   // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
1574   //
1575   ASSERT (StrSize (FirstString) != 0);
1576   ASSERT (StrSize (SecondString) != 0);
1577 
1578   while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
1579     FirstString++;
1580     SecondString++;
1581   }
1582   return *FirstString - *SecondString;
1583 }
1584 
1585 UINT64
SwapBytes64(UINT64 Value)1586 SwapBytes64 (
1587   UINT64                    Value
1588   )
1589 {
1590   return InternalMathSwapBytes64 (Value);
1591 }
1592 
1593 UINT64
InternalMathSwapBytes64(UINT64 Operand)1594 InternalMathSwapBytes64 (
1595   UINT64                    Operand
1596   )
1597 {
1598   UINT64  LowerBytes;
1599   UINT64  HigherBytes;
1600 
1601   LowerBytes  = (UINT64) SwapBytes32 ((UINT32) Operand);
1602   HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
1603 
1604   return (LowerBytes << 32 | HigherBytes);
1605 }
1606 
1607 RETURN_STATUS
StrToIpv4Address(CONST CHAR16 * String,CHAR16 ** EndPointer,EFI_IPv4_ADDRESS * Address,UINT8 * PrefixLength)1608 StrToIpv4Address (
1609   CONST CHAR16       *String,
1610   CHAR16             **EndPointer,
1611   EFI_IPv4_ADDRESS       *Address,
1612   UINT8              *PrefixLength
1613   )
1614 {
1615   RETURN_STATUS          Status;
1616   UINTN                  AddressIndex;
1617   UINT64                 Uint64;
1618   EFI_IPv4_ADDRESS       LocalAddress;
1619   UINT8                  LocalPrefixLength;
1620   CHAR16                 *Pointer;
1621 
1622   LocalPrefixLength = MAX_UINT8;
1623   LocalAddress.Addr[0] = 0;
1624 
1625   ASSERT (((UINTN) String & BIT0) == 0);
1626 
1627   //
1628   // 1. None of String or Guid shall be a null pointer.
1629   //
1630   SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1631   SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
1632 
1633   for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
1634     if (!InternalIsDecimalDigitCharacter (*Pointer)) {
1635       //
1636       // D or P contains invalid characters.
1637       //
1638       break;
1639     }
1640 
1641     //
1642     // Get D or P.
1643     //
1644     Status = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64);
1645     if (RETURN_ERROR (Status)) {
1646       return RETURN_UNSUPPORTED;
1647     }
1648     if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
1649       //
1650       // It's P.
1651       //
1652       if (Uint64 > 32) {
1653         return RETURN_UNSUPPORTED;
1654       }
1655       LocalPrefixLength = (UINT8) Uint64;
1656     } else {
1657       //
1658       // It's D.
1659       //
1660       if (Uint64 > MAX_UINT8) {
1661         return RETURN_UNSUPPORTED;
1662       }
1663       LocalAddress.Addr[AddressIndex] = (UINT8) Uint64;
1664       AddressIndex++;
1665     }
1666 
1667     //
1668     // Check the '.' or '/', depending on the AddressIndex.
1669     //
1670     if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
1671       if (*Pointer == L'/') {
1672         //
1673         // '/P' is in the String.
1674         // Skip "/" and get P in next loop.
1675         //
1676         Pointer++;
1677       } else {
1678         //
1679         // '/P' is not in the String.
1680         //
1681         break;
1682       }
1683     } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
1684       if (*Pointer == L'.') {
1685         //
1686         // D should be followed by '.'
1687         //
1688         Pointer++;
1689       } else {
1690         return RETURN_UNSUPPORTED;
1691       }
1692     }
1693   }
1694 
1695   if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
1696     return RETURN_UNSUPPORTED;
1697   }
1698 
1699   memcpy (Address, &LocalAddress, sizeof (*Address));
1700   if (PrefixLength != NULL) {
1701     *PrefixLength = LocalPrefixLength;
1702   }
1703   if (EndPointer != NULL) {
1704     *EndPointer = Pointer;
1705   }
1706 
1707   return RETURN_SUCCESS;
1708 }
1709 
1710 RETURN_STATUS
StrToIpv6Address(CONST CHAR16 * String,CHAR16 ** EndPointer,EFI_IPv6_ADDRESS * Address,UINT8 * PrefixLength)1711 StrToIpv6Address (
1712   CONST CHAR16       *String,
1713   CHAR16             **EndPointer,
1714   EFI_IPv6_ADDRESS   *Address,
1715   UINT8              *PrefixLength
1716   )
1717 {
1718   RETURN_STATUS          Status;
1719   UINTN                  AddressIndex;
1720   UINT64                 Uint64;
1721   EFI_IPv6_ADDRESS       LocalAddress;
1722   UINT8                  LocalPrefixLength;
1723   CONST CHAR16           *Pointer;
1724   CHAR16                 *End;
1725   UINTN                  CompressStart;
1726   BOOLEAN                ExpectPrefix;
1727 
1728   LocalPrefixLength = MAX_UINT8;
1729   CompressStart     = ARRAY_SIZE (Address->Addr);
1730   ExpectPrefix      = FALSE;
1731 
1732   ASSERT (((UINTN) String & BIT0) == 0);
1733 
1734   //
1735   // 1. None of String or Guid shall be a null pointer.
1736   //
1737   SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1738   SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
1739 
1740   for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
1741     if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
1742       if (*Pointer != L':') {
1743         //
1744         // ":" or "/" should be followed by digit characters.
1745         //
1746         return RETURN_UNSUPPORTED;
1747       }
1748 
1749       //
1750       // Meet second ":" after previous ":" or "/"
1751       // or meet first ":" in the beginning of String.
1752       //
1753       if (ExpectPrefix) {
1754         //
1755         // ":" shall not be after "/"
1756         //
1757         return RETURN_UNSUPPORTED;
1758       }
1759 
1760       if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {
1761         //
1762         // "::" can only appear once.
1763         // "::" can only appear when address is not full length.
1764         //
1765         return RETURN_UNSUPPORTED;
1766       } else {
1767         //
1768         // Remember the start of zero compressing.
1769         //
1770         CompressStart = AddressIndex;
1771         Pointer++;
1772 
1773         if (CompressStart == 0) {
1774           if (*Pointer != L':') {
1775             //
1776             // Single ":" shall not be in the beginning of String.
1777             //
1778             return RETURN_UNSUPPORTED;
1779           }
1780           Pointer++;
1781         }
1782       }
1783     }
1784 
1785     if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
1786       if (*Pointer == L'/') {
1787         //
1788         // Might be optional "/P" after "::".
1789         //
1790         if (CompressStart != AddressIndex) {
1791           return RETURN_UNSUPPORTED;
1792         }
1793       } else {
1794         break;
1795       }
1796     } else {
1797       if (!ExpectPrefix) {
1798         //
1799         // Get X.
1800         //
1801         Status = StrHexToUint64S (Pointer, &End, &Uint64);
1802         if (RETURN_ERROR (Status) || End - Pointer > 4) {
1803           //
1804           // Number of hexadecimal digit characters is no more than 4.
1805           //
1806           return RETURN_UNSUPPORTED;
1807         }
1808         Pointer = End;
1809         //
1810         // Uint64 won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.
1811         //
1812         ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));
1813         LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uint64 >> 8);
1814         LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64;
1815         AddressIndex += 2;
1816       } else {
1817         //
1818         // Get P, then exit the loop.
1819         //
1820         Status = StrDecimalToUint64S (Pointer, &End, &Uint64);
1821         if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) {
1822           //
1823           // Prefix length should not exceed 128.
1824           //
1825           return RETURN_UNSUPPORTED;
1826         }
1827         LocalPrefixLength = (UINT8) Uint64;
1828         Pointer = End;
1829         break;
1830       }
1831     }
1832 
1833     //
1834     // Skip ':' or "/"
1835     //
1836     if (*Pointer == L'/') {
1837       ExpectPrefix = TRUE;
1838     } else if (*Pointer == L':') {
1839       if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
1840         //
1841         // Meet additional ":" after all 8 16-bit address
1842         //
1843         break;
1844       }
1845     } else {
1846       //
1847       // Meet other character that is not "/" or ":" after all 8 16-bit address
1848       //
1849       break;
1850     }
1851     Pointer++;
1852   }
1853 
1854   if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||
1855     (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))
1856       ) {
1857     //
1858     // Full length of address shall not have compressing zeros.
1859     // Non-full length of address shall have compressing zeros.
1860     //
1861     return RETURN_UNSUPPORTED;
1862   }
1863   memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);
1864   if (AddressIndex > CompressStart) {
1865     memset (&Address->Addr[CompressStart], 0,  ARRAY_SIZE (Address->Addr) - AddressIndex);
1866     memcpy (
1867       &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],
1868       &LocalAddress.Addr[CompressStart],
1869       AddressIndex - CompressStart
1870       );
1871   }
1872 
1873   if (PrefixLength != NULL) {
1874     *PrefixLength = LocalPrefixLength;
1875   }
1876   if (EndPointer != NULL) {
1877     *EndPointer = (CHAR16 *) Pointer;
1878   }
1879 
1880   return RETURN_SUCCESS;
1881 }
1882 
1883 
1884 RETURN_STATUS
UnicodeStrToAsciiStrS(CONST CHAR16 * Source,CHAR8 * Destination,UINTN DestMax)1885 UnicodeStrToAsciiStrS (
1886   CONST CHAR16              *Source,
1887   CHAR8                     *Destination,
1888   UINTN                     DestMax
1889   )
1890 {
1891   UINTN            SourceLen;
1892 
1893   ASSERT (((UINTN) Source & BIT0) == 0);
1894 
1895   //
1896   // 1. Neither Destination nor Source shall be a null pointer.
1897   //
1898   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
1899   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
1900 
1901   //
1902   // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
1903   //
1904   if (ASCII_RSIZE_MAX != 0) {
1905     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
1906   }
1907   if (RSIZE_MAX != 0) {
1908     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1909   }
1910 
1911   //
1912   // 3. DestMax shall not equal zero.
1913   //
1914   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
1915 
1916   //
1917   // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
1918   //
1919   SourceLen = StrnLenS (Source, DestMax);
1920   SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
1921 
1922   //
1923   // 5. Copying shall not take place between objects that overlap.
1924   //
1925   SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);
1926 
1927   //
1928   // convert string
1929   //
1930   while (*Source != '\0') {
1931     //
1932     // If any Unicode characters in Source contain
1933     // non-zero value in the upper 8 bits, then ASSERT().
1934     //
1935     ASSERT (*Source < 0x100);
1936     *(Destination++) = (CHAR8) *(Source++);
1937   }
1938   *Destination = '\0';
1939 
1940   return RETURN_SUCCESS;
1941 }
1942 
1943 RETURN_STATUS
StrCpyS(CHAR16 * Destination,UINTN DestMax,CONST CHAR16 * Source)1944 StrCpyS (
1945   CHAR16       *Destination,
1946   UINTN        DestMax,
1947   CONST CHAR16 *Source
1948   )
1949 {
1950   UINTN            SourceLen;
1951 
1952   ASSERT (((UINTN) Destination & BIT0) == 0);
1953   ASSERT (((UINTN) Source & BIT0) == 0);
1954 
1955   //
1956   // 1. Neither Destination nor Source shall be a null pointer.
1957   //
1958   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
1959   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
1960 
1961   //
1962   // 2. DestMax shall not be greater than RSIZE_MAX.
1963   //
1964   if (RSIZE_MAX != 0) {
1965     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1966   }
1967 
1968   //
1969   // 3. DestMax shall not equal zero.
1970   //
1971   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
1972 
1973   //
1974   // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
1975   //
1976   SourceLen = StrnLenS (Source, DestMax);
1977   SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
1978 
1979   //
1980   // 5. Copying shall not take place between objects that overlap.
1981   //
1982   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
1983 
1984   //
1985   // The StrCpyS function copies the string pointed to by Source (including the terminating
1986   // null character) into the array pointed to by Destination.
1987   //
1988   while (*Source != 0) {
1989     *(Destination++) = *(Source++);
1990   }
1991   *Destination = 0;
1992 
1993   return RETURN_SUCCESS;
1994 }
1995 
1996 VOID *
AllocateZeroPool(UINTN AllocationSize)1997 AllocateZeroPool (
1998   UINTN  AllocationSize
1999   )
2000 {
2001   VOID * Memory;
2002   Memory = malloc(AllocationSize);
2003   ASSERT (Memory != NULL);
2004   if (Memory == NULL) {
2005     fprintf(stderr, "Not memory for malloc\n");
2006   }
2007   memset(Memory, 0, AllocationSize);
2008   return Memory;
2009 }
2010 
2011 VOID *
AllocatePool(UINTN AllocationSize)2012 AllocatePool (
2013   UINTN  AllocationSize
2014   )
2015 {
2016   return InternalAllocatePool (AllocationSize);
2017 }
2018 
2019 UINT16
WriteUnaligned16(UINT16 * Buffer,UINT16 Value)2020 WriteUnaligned16 (
2021   UINT16                    *Buffer,
2022   UINT16                    Value
2023   )
2024 {
2025   ASSERT (Buffer != NULL);
2026 
2027   return *Buffer = Value;
2028 }
2029 
2030 UINT16
ReadUnaligned16(CONST UINT16 * Buffer)2031 ReadUnaligned16 (
2032   CONST UINT16              *Buffer
2033   )
2034 {
2035   ASSERT (Buffer != NULL);
2036 
2037   return *Buffer;
2038 }
2039 /**
2040   Return whether the integer string is a hex string.
2041 
2042   @param Str             The integer string
2043 
2044   @retval TRUE   Hex string
2045   @retval FALSE  Decimal string
2046 
2047 **/
2048 BOOLEAN
IsHexStr(CHAR16 * Str)2049 IsHexStr (
2050    CHAR16   *Str
2051   )
2052 {
2053   //
2054   // skip preceding white space
2055   //
2056   while ((*Str != 0) && *Str == L' ') {
2057     Str ++;
2058   }
2059   //
2060   // skip preceding zeros
2061   //
2062   while ((*Str != 0) && *Str == L'0') {
2063     Str ++;
2064   }
2065 
2066   return (BOOLEAN) (*Str == L'x' || *Str == L'X');
2067 }
2068 
2069 /**
2070 
2071   Convert integer string to uint.
2072 
2073   @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.
2074 
2075   @return A UINTN value represented by Str
2076 
2077 **/
2078 UINTN
Strtoi(CHAR16 * Str)2079 Strtoi (
2080    CHAR16  *Str
2081   )
2082 {
2083   if (IsHexStr (Str)) {
2084     return (UINTN)StrHexToUint64 (Str);
2085   } else {
2086     return (UINTN)StrDecimalToUint64 (Str);
2087   }
2088 }
2089 
2090 /**
2091 
2092   Convert integer string to 64 bit data.
2093 
2094   @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.
2095   @param Data            A pointer to the UINT64 value represented by Str
2096 
2097 **/
2098 VOID
Strtoi64(CHAR16 * Str,UINT64 * Data)2099 Strtoi64 (
2100     CHAR16  *Str,
2101    UINT64  *Data
2102   )
2103 {
2104   if (IsHexStr (Str)) {
2105     *Data = StrHexToUint64 (Str);
2106   } else {
2107     *Data = StrDecimalToUint64 (Str);
2108   }
2109 }
2110 
2111 /**
2112   Converts a Unicode string to ASCII string.
2113 
2114   @param Str             The equivalent Unicode string
2115   @param AsciiStr        On input, it points to destination ASCII string buffer; on output, it points
2116                          to the next ASCII string next to it
2117 
2118 **/
2119 VOID
StrToAscii(CHAR16 * Str,CHAR8 ** AsciiStr)2120 StrToAscii (
2121        CHAR16 *Str,
2122     CHAR8  **AsciiStr
2123   )
2124 {
2125   CHAR8 *Dest;
2126 
2127   Dest = *AsciiStr;
2128   while (!IS_NULL (*Str)) {
2129     *(Dest++) = (CHAR8) *(Str++);
2130   }
2131   *Dest = 0;
2132 
2133   //
2134   // Return the string next to it
2135   //
2136   *AsciiStr = Dest + 1;
2137 }
2138 
2139 /**
2140   Gets current sub-string from a string list, before return
2141   the list header is moved to next sub-string. The sub-string is separated
2142   by the specified character. For example, the separator is ',', the string
2143   list is "2,0,3", it returns "2", the remain list move to "0,3"
2144 
2145   @param  List        A string list separated by the specified separator
2146   @param  Separator   The separator character
2147 
2148   @return A pointer to the current sub-string
2149 
2150 **/
2151 CHAR16 *
SplitStr(CHAR16 ** List,CHAR16 Separator)2152 SplitStr (
2153     CHAR16 **List,
2154        CHAR16 Separator
2155   )
2156 {
2157   CHAR16  *Str;
2158   CHAR16  *ReturnStr;
2159 
2160   Str = *List;
2161   ReturnStr = Str;
2162 
2163   if (IS_NULL (*Str)) {
2164     return ReturnStr;
2165   }
2166 
2167   //
2168   // Find first occurrence of the separator
2169   //
2170   while (!IS_NULL (*Str)) {
2171     if (*Str == Separator) {
2172       break;
2173     }
2174     Str++;
2175   }
2176 
2177   if (*Str == Separator) {
2178     //
2179     // Find a sub-string, terminate it
2180     //
2181     *Str = L'\0';
2182     Str++;
2183   }
2184 
2185   //
2186   // Move to next sub-string
2187   //
2188   *List = Str;
2189   return ReturnStr;
2190 }
2191 
2192