]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/CommonLib.c
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / C / Common / CommonLib.c
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
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
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
97 ZeroMem (
98 IN VOID *Buffer,
99 IN UINTN Size
100 )
101 {
102 PeiZeroMem (Buffer, Size);
103 }
104
105 VOID
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
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
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
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
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
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
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
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
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
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
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__
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 *
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
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
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 *
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 *
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 *
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
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
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
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
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
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
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
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
1147 StrSize (
1148 CONST CHAR16 *String
1149 )
1150 {
1151 return (StrLen (String) + 1) * sizeof (*String);
1152 }
1153
1154
1155 UINT64
1156 ReadUnaligned64 (
1157 CONST UINT64 *Buffer
1158 )
1159 {
1160 ASSERT (Buffer != NULL);
1161
1162 return *Buffer;
1163 }
1164
1165 UINT64
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 *
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
1195 SwapBytes16 (
1196 UINT16 Value
1197 )
1198 {
1199 return (UINT16) ((Value<< 8) | (Value>> 8));
1200 }
1201
1202
1203 UINT32
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
1217 InternalIsDecimalDigitCharacter (
1218 CHAR16 Char
1219 )
1220 {
1221 return (BOOLEAN) (Char >= L'0' && Char <= L'9');
1222 }
1223
1224 VOID *
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
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
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
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
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
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 *
1558 AllocateCopyPool (
1559 UINTN AllocationSize,
1560 CONST VOID *Buffer
1561 )
1562 {
1563 return InternalAllocateCopyPool (AllocationSize, Buffer);
1564 }
1565
1566 INTN
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
1586 SwapBytes64 (
1587 UINT64 Value
1588 )
1589 {
1590 return InternalMathSwapBytes64 (Value);
1591 }
1592
1593 UINT64
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
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
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
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
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 *
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 *
2012 AllocatePool (
2013 UINTN AllocationSize
2014 )
2015 {
2016 return InternalAllocatePool (AllocationSize);
2017 }
2018
2019 UINT16
2020 WriteUnaligned16 (
2021 UINT16 *Buffer,
2022 UINT16 Value
2023 )
2024 {
2025 ASSERT (Buffer != NULL);
2026
2027 return *Buffer = Value;
2028 }
2029
2030 UINT16
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
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
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
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
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 *
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