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