]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/CommonLib.c
5c40fdb5fd491ac9eda8356cc9e5a2580b98f978
[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 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 /**
886 Convert a Null-terminated Unicode decimal string to a value of type UINT64.
887
888 This function outputs a value of type UINT64 by interpreting the contents of
889 the Unicode string specified by String as a decimal number. The format of the
890 input Unicode string String is:
891
892 [spaces] [decimal digits].
893
894 The valid decimal digit character is in the range [0-9]. The function will
895 ignore the pad space, which includes spaces or tab characters, before
896 [decimal digits]. The running zero in the beginning of [decimal digits] will
897 be ignored. Then, the function stops at the first character that is a not a
898 valid decimal character or a Null-terminator, whichever one comes first.
899
900 If String is NULL, then ASSERT().
901 If Data is NULL, then ASSERT().
902 If String is not aligned in a 16-bit boundary, then ASSERT().
903 If PcdMaximumUnicodeStringLength is not zero, and String contains more than
904 PcdMaximumUnicodeStringLength Unicode characters, not including the
905 Null-terminator, then ASSERT().
906
907 If String has no valid decimal digits in the above format, then 0 is stored
908 at the location pointed to by Data.
909 If the number represented by String exceeds the range defined by UINT64, then
910 MAX_UINT64 is stored at the location pointed to by Data.
911
912 If EndPointer is not NULL, a pointer to the character that stopped the scan
913 is stored at the location pointed to by EndPointer. If String has no valid
914 decimal digits right after the optional pad spaces, the value of String is
915 stored at the location pointed to by EndPointer.
916
917 @param String Pointer to a Null-terminated Unicode string.
918 @param EndPointer Pointer to character that stops scan.
919 @param Data Pointer to the converted value.
920
921 @retval RETURN_SUCCESS Value is translated from String.
922 @retval RETURN_INVALID_PARAMETER If String is NULL.
923 If Data is NULL.
924 If PcdMaximumUnicodeStringLength is not
925 zero, and String contains more than
926 PcdMaximumUnicodeStringLength Unicode
927 characters, not including the
928 Null-terminator.
929 @retval RETURN_UNSUPPORTED If the number represented by String exceeds
930 the range defined by UINT64.
931
932 **/
933 RETURN_STATUS
934 StrDecimalToUint64S (
935 CONST CHAR16 *String,
936 CHAR16 **EndPointer, OPTIONAL
937 UINT64 *Data
938 )
939 {
940 ASSERT (((UINTN) String & BIT0) == 0);
941
942 //
943 // 1. Neither String nor Data shall be a null pointer.
944 //
945 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
946 SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
947
948 //
949 // 2. The length of String shall not be greater than RSIZE_MAX.
950 //
951 if (RSIZE_MAX != 0) {
952 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
953 }
954
955 if (EndPointer != NULL) {
956 *EndPointer = (CHAR16 *) String;
957 }
958
959 //
960 // Ignore the pad spaces (space or tab)
961 //
962 while ((*String == L' ') || (*String == L'\t')) {
963 String++;
964 }
965
966 //
967 // Ignore leading Zeros after the spaces
968 //
969 while (*String == L'0') {
970 String++;
971 }
972
973 *Data = 0;
974
975 while (InternalIsDecimalDigitCharacter (*String)) {
976 //
977 // If the number represented by String overflows according to the range
978 // defined by UINT64, then MAX_UINT64 is stored in *Data and
979 // RETURN_UNSUPPORTED is returned.
980 //
981 if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {
982 *Data = MAX_UINT64;
983 if (EndPointer != NULL) {
984 *EndPointer = (CHAR16 *) String;
985 }
986 return RETURN_UNSUPPORTED;
987 }
988
989 *Data = (*Data) * 10 + (*String - L'0');
990 String++;
991 }
992
993 if (EndPointer != NULL) {
994 *EndPointer = (CHAR16 *) String;
995 }
996 return RETURN_SUCCESS;
997 }
998
999 /**
1000 Convert a Null-terminated Unicode hexadecimal string to a value of type
1001 UINT64.
1002
1003 This function outputs a value of type UINT64 by interpreting the contents of
1004 the Unicode string specified by String as a hexadecimal number. The format of
1005 the input Unicode string String is:
1006
1007 [spaces][zeros][x][hexadecimal digits].
1008
1009 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
1010 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
1011 If "x" appears in the input string, it must be prefixed with at least one 0.
1012 The function will ignore the pad space, which includes spaces or tab
1013 characters, before [zeros], [x] or [hexadecimal digit]. The running zero
1014 before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
1015 after [x] or the first valid hexadecimal digit. Then, the function stops at
1016 the first character that is a not a valid hexadecimal character or NULL,
1017 whichever one comes first.
1018
1019 If String is NULL, then ASSERT().
1020 If Data is NULL, then ASSERT().
1021 If String is not aligned in a 16-bit boundary, then ASSERT().
1022 If PcdMaximumUnicodeStringLength is not zero, and String contains more than
1023 PcdMaximumUnicodeStringLength Unicode characters, not including the
1024 Null-terminator, then ASSERT().
1025
1026 If String has no valid hexadecimal digits in the above format, then 0 is
1027 stored at the location pointed to by Data.
1028 If the number represented by String exceeds the range defined by UINT64, then
1029 MAX_UINT64 is stored at the location pointed to by Data.
1030
1031 If EndPointer is not NULL, a pointer to the character that stopped the scan
1032 is stored at the location pointed to by EndPointer. If String has no valid
1033 hexadecimal digits right after the optional pad spaces, the value of String
1034 is stored at the location pointed to by EndPointer.
1035
1036 @param String Pointer to a Null-terminated Unicode string.
1037 @param EndPointer Pointer to character that stops scan.
1038 @param Data Pointer to the converted value.
1039
1040 @retval RETURN_SUCCESS Value is translated from String.
1041 @retval RETURN_INVALID_PARAMETER If String is NULL.
1042 If Data is NULL.
1043 If PcdMaximumUnicodeStringLength is not
1044 zero, and String contains more than
1045 PcdMaximumUnicodeStringLength Unicode
1046 characters, not including the
1047 Null-terminator.
1048 @retval RETURN_UNSUPPORTED If the number represented by String exceeds
1049 the range defined by UINT64.
1050
1051 **/
1052 RETURN_STATUS
1053 StrHexToUint64S (
1054 CONST CHAR16 *String,
1055 CHAR16 **EndPointer, OPTIONAL
1056 UINT64 *Data
1057 )
1058 {
1059 ASSERT (((UINTN) String & BIT0) == 0);
1060
1061 //
1062 // 1. Neither String nor Data shall be a null pointer.
1063 //
1064 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1065 SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
1066
1067 //
1068 // 2. The length of String shall not be greater than RSIZE_MAX.
1069 //
1070 if (RSIZE_MAX != 0) {
1071 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1072 }
1073
1074 if (EndPointer != NULL) {
1075 *EndPointer = (CHAR16 *) String;
1076 }
1077
1078 //
1079 // Ignore the pad spaces (space or tab)
1080 //
1081 while ((*String == L' ') || (*String == L'\t')) {
1082 String++;
1083 }
1084
1085 //
1086 // Ignore leading Zeros after the spaces
1087 //
1088 while (*String == L'0') {
1089 String++;
1090 }
1091
1092 if (InternalCharToUpper (*String) == L'X') {
1093 if (*(String - 1) != L'0') {
1094 *Data = 0;
1095 return RETURN_SUCCESS;
1096 }
1097 //
1098 // Skip the 'X'
1099 //
1100 String++;
1101 }
1102
1103 *Data = 0;
1104
1105 while (InternalIsHexaDecimalDigitCharacter (*String)) {
1106 //
1107 // If the number represented by String overflows according to the range
1108 // defined by UINT64, then MAX_UINT64 is stored in *Data and
1109 // RETURN_UNSUPPORTED is returned.
1110 //
1111 if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {
1112 *Data = MAX_UINT64;
1113 if (EndPointer != NULL) {
1114 *EndPointer = (CHAR16 *) String;
1115 }
1116 return RETURN_UNSUPPORTED;
1117 }
1118
1119 *Data = ((*Data) << 4) + InternalHexCharToUintn (*String);
1120 String++;
1121 }
1122
1123 if (EndPointer != NULL) {
1124 *EndPointer = (CHAR16 *) String;
1125 }
1126 return RETURN_SUCCESS;
1127 }
1128
1129 UINT64
1130 StrDecimalToUint64 (
1131 CONST CHAR16 *String
1132 )
1133 {
1134 UINT64 Result;
1135
1136 StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);
1137 return Result;
1138 }
1139
1140
1141 UINT64
1142 StrHexToUint64 (
1143 CONST CHAR16 *String
1144 )
1145 {
1146 UINT64 Result;
1147
1148 StrHexToUint64S (String, (CHAR16 **) NULL, &Result);
1149 return Result;
1150 }
1151
1152 UINTN
1153 StrSize (
1154 CONST CHAR16 *String
1155 )
1156 {
1157 return (StrLen (String) + 1) * sizeof (*String);
1158 }
1159
1160
1161 UINT64
1162 ReadUnaligned64 (
1163 CONST UINT64 *Buffer
1164 )
1165 {
1166 ASSERT (Buffer != NULL);
1167
1168 return *Buffer;
1169 }
1170
1171 UINT64
1172 WriteUnaligned64 (
1173 UINT64 *Buffer,
1174 UINT64 Value
1175 )
1176 {
1177 ASSERT (Buffer != NULL);
1178
1179 return *Buffer = Value;
1180 }
1181
1182
1183 EFI_GUID *
1184 CopyGuid (
1185 EFI_GUID *DestinationGuid,
1186 CONST EFI_GUID *SourceGuid
1187 )
1188 {
1189 WriteUnaligned64 (
1190 (UINT64*)DestinationGuid,
1191 ReadUnaligned64 ((CONST UINT64*)SourceGuid)
1192 );
1193 WriteUnaligned64 (
1194 (UINT64*)DestinationGuid + 1,
1195 ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
1196 );
1197 return DestinationGuid;
1198 }
1199
1200 UINT16
1201 SwapBytes16 (
1202 UINT16 Value
1203 )
1204 {
1205 return (UINT16) ((Value<< 8) | (Value>> 8));
1206 }
1207
1208
1209 UINT32
1210 SwapBytes32 (
1211 UINT32 Value
1212 )
1213 {
1214 UINT32 LowerBytes;
1215 UINT32 HigherBytes;
1216
1217 LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value);
1218 HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));
1219 return (LowerBytes << 16 | HigherBytes);
1220 }
1221
1222 BOOLEAN
1223 InternalIsDecimalDigitCharacter (
1224 CHAR16 Char
1225 )
1226 {
1227 return (BOOLEAN) (Char >= L'0' && Char <= L'9');
1228 }
1229
1230 VOID *
1231 InternalAllocateCopyPool (
1232 UINTN AllocationSize,
1233 CONST VOID *Buffer
1234 )
1235 {
1236 VOID *Memory;
1237
1238 ASSERT (Buffer != NULL);
1239
1240 Memory = malloc (AllocationSize);
1241 if (Memory != NULL) {
1242 Memory = memcpy (Memory, Buffer, AllocationSize);
1243 }
1244 return Memory;
1245 }
1246
1247 BOOLEAN
1248 InternalIsHexaDecimalDigitCharacter (
1249 CHAR16 Char
1250 )
1251 {
1252
1253 return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||
1254 (Char >= L'A' && Char <= L'F') ||
1255 (Char >= L'a' && Char <= L'f'));
1256 }
1257
1258 UINTN
1259 InternalHexCharToUintn (
1260 CHAR16 Char
1261 )
1262 {
1263 if (InternalIsDecimalDigitCharacter (Char)) {
1264 return Char - L'0';
1265 }
1266
1267 return (10 + InternalCharToUpper (Char) - L'A');
1268 }
1269
1270
1271 /**
1272 Convert a Null-terminated Unicode hexadecimal string to a byte array.
1273
1274 This function outputs a byte array by interpreting the contents of
1275 the Unicode string specified by String in hexadecimal format. The format of
1276 the input Unicode string String is:
1277
1278 [XX]*
1279
1280 X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
1281 The function decodes every two hexadecimal digit characters as one byte. The
1282 decoding stops after Length of characters and outputs Buffer containing
1283 (Length / 2) bytes.
1284
1285 If String is not aligned in a 16-bit boundary, then ASSERT().
1286
1287 If String is NULL, then ASSERT().
1288
1289 If Buffer is NULL, then ASSERT().
1290
1291 If Length is not multiple of 2, then ASSERT().
1292
1293 If PcdMaximumUnicodeStringLength is not zero and Length is greater than
1294 PcdMaximumUnicodeStringLength, then ASSERT().
1295
1296 If MaxBufferSize is less than (Length / 2), then ASSERT().
1297
1298 @param String Pointer to a Null-terminated Unicode string.
1299 @param Length The number of Unicode characters to decode.
1300 @param Buffer Pointer to the converted bytes array.
1301 @param MaxBufferSize The maximum size of Buffer.
1302
1303 @retval RETURN_SUCCESS Buffer is translated from String.
1304 @retval RETURN_INVALID_PARAMETER If String is NULL.
1305 If Data is NULL.
1306 If Length is not multiple of 2.
1307 If PcdMaximumUnicodeStringLength is not zero,
1308 and Length is greater than
1309 PcdMaximumUnicodeStringLength.
1310 @retval RETURN_UNSUPPORTED If Length of characters from String contain
1311 a character that is not valid hexadecimal
1312 digit characters, or a Null-terminator.
1313 @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2).
1314 **/
1315 RETURN_STATUS
1316 StrHexToBytes (
1317 CONST CHAR16 *String,
1318 UINTN Length,
1319 UINT8 *Buffer,
1320 UINTN MaxBufferSize
1321 )
1322 {
1323 UINTN Index;
1324
1325 ASSERT (((UINTN) String & BIT0) == 0);
1326
1327 //
1328 // 1. None of String or Buffer shall be a null pointer.
1329 //
1330 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1331 SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);
1332
1333 //
1334 // 2. Length shall not be greater than RSIZE_MAX.
1335 //
1336 if (RSIZE_MAX != 0) {
1337 SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1338 }
1339
1340 //
1341 // 3. Length shall not be odd.
1342 //
1343 SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);
1344
1345 //
1346 // 4. MaxBufferSize shall equal to or greater than Length / 2.
1347 //
1348 SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);
1349
1350 //
1351 // 5. String shall not contains invalid hexadecimal digits.
1352 //
1353 for (Index = 0; Index < Length; Index++) {
1354 if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {
1355 break;
1356 }
1357 }
1358 if (Index != Length) {
1359 return RETURN_UNSUPPORTED;
1360 }
1361
1362 //
1363 // Convert the hex string to bytes.
1364 //
1365 for(Index = 0; Index < Length; Index++) {
1366
1367 //
1368 // For even characters, write the upper nibble for each buffer byte,
1369 // and for even characters, the lower nibble.
1370 //
1371 if ((Index & BIT0) == 0) {
1372 Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4;
1373 } else {
1374 Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);
1375 }
1376 }
1377 return RETURN_SUCCESS;
1378 }
1379
1380 /**
1381 Convert a Null-terminated Unicode GUID string to a value of type
1382 EFI_GUID.
1383
1384 This function outputs a GUID value by interpreting the contents of
1385 the Unicode string specified by String. The format of the input
1386 Unicode string String consists of 36 characters, as follows:
1387
1388 aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
1389
1390 The pairs aa - pp are two characters in the range [0-9], [a-f] and
1391 [A-F], with each pair representing a single byte hexadecimal value.
1392
1393 The mapping between String and the EFI_GUID structure is as follows:
1394 aa Data1[24:31]
1395 bb Data1[16:23]
1396 cc Data1[8:15]
1397 dd Data1[0:7]
1398 ee Data2[8:15]
1399 ff Data2[0:7]
1400 gg Data3[8:15]
1401 hh Data3[0:7]
1402 ii Data4[0:7]
1403 jj Data4[8:15]
1404 kk Data4[16:23]
1405 ll Data4[24:31]
1406 mm Data4[32:39]
1407 nn Data4[40:47]
1408 oo Data4[48:55]
1409 pp Data4[56:63]
1410
1411 If String is NULL, then ASSERT().
1412 If Guid is NULL, then ASSERT().
1413 If String is not aligned in a 16-bit boundary, then ASSERT().
1414
1415 @param String Pointer to a Null-terminated Unicode string.
1416 @param Guid Pointer to the converted GUID.
1417
1418 @retval RETURN_SUCCESS Guid is translated from String.
1419 @retval RETURN_INVALID_PARAMETER If String is NULL.
1420 If Data is NULL.
1421 @retval RETURN_UNSUPPORTED If String is not as the above format.
1422
1423 **/
1424 RETURN_STATUS
1425 StrToGuid (
1426 CONST CHAR16 *String,
1427 EFI_GUID *Guid
1428 )
1429 {
1430 RETURN_STATUS Status;
1431 EFI_GUID LocalGuid;
1432
1433 ASSERT (((UINTN) String & BIT0) == 0);
1434
1435 //
1436 // 1. None of String or Guid shall be a null pointer.
1437 //
1438 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1439 SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);
1440
1441 //
1442 // Get aabbccdd in big-endian.
1443 //
1444 Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));
1445 if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {
1446 return RETURN_UNSUPPORTED;
1447 }
1448 //
1449 // Convert big-endian to little-endian.
1450 //
1451 LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);
1452 String += 2 * sizeof (LocalGuid.Data1) + 1;
1453
1454 //
1455 // Get eeff in big-endian.
1456 //
1457 Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));
1458 if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {
1459 return RETURN_UNSUPPORTED;
1460 }
1461 //
1462 // Convert big-endian to little-endian.
1463 //
1464 LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);
1465 String += 2 * sizeof (LocalGuid.Data2) + 1;
1466
1467 //
1468 // Get gghh in big-endian.
1469 //
1470 Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));
1471 if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {
1472 return RETURN_UNSUPPORTED;
1473 }
1474 //
1475 // Convert big-endian to little-endian.
1476 //
1477 LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);
1478 String += 2 * sizeof (LocalGuid.Data3) + 1;
1479
1480 //
1481 // Get iijj.
1482 //
1483 Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);
1484 if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {
1485 return RETURN_UNSUPPORTED;
1486 }
1487 String += 2 * 2 + 1;
1488
1489 //
1490 // Get kkllmmnnoopp.
1491 //
1492 Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);
1493 if (RETURN_ERROR (Status)) {
1494 return RETURN_UNSUPPORTED;
1495 }
1496
1497 CopyGuid (Guid, &LocalGuid);
1498 return RETURN_SUCCESS;
1499 }
1500
1501 /**
1502 Compares up to a specified length the contents of two Null-terminated Unicode strings,
1503 and returns the difference between the first mismatched Unicode characters.
1504
1505 This function compares the Null-terminated Unicode string FirstString to the
1506 Null-terminated Unicode string SecondString. At most, Length Unicode
1507 characters will be compared. If Length is 0, then 0 is returned. If
1508 FirstString is identical to SecondString, then 0 is returned. Otherwise, the
1509 value returned is the first mismatched Unicode character in SecondString
1510 subtracted from the first mismatched Unicode character in FirstString.
1511
1512 If Length > 0 and FirstString is NULL, then ASSERT().
1513 If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().
1514 If Length > 0 and SecondString is NULL, then ASSERT().
1515 If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().
1516 If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
1517 PcdMaximumUnicodeStringLength, then ASSERT().
1518 If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than
1519 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
1520 then ASSERT().
1521 If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than
1522 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
1523 then ASSERT().
1524
1525 @param FirstString A pointer to a Null-terminated Unicode string.
1526 @param SecondString A pointer to a Null-terminated Unicode string.
1527 @param Length The maximum number of Unicode characters to compare.
1528
1529 @retval 0 FirstString is identical to SecondString.
1530 @return others FirstString is not identical to SecondString.
1531
1532 **/
1533 INTN
1534 StrnCmp (
1535 CONST CHAR16 *FirstString,
1536 CONST CHAR16 *SecondString,
1537 UINTN Length
1538 )
1539 {
1540 if (Length == 0) {
1541 return 0;
1542 }
1543
1544 //
1545 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
1546 // Length tests are performed inside StrLen().
1547 //
1548 ASSERT (StrSize (FirstString) != 0);
1549 ASSERT (StrSize (SecondString) != 0);
1550
1551 while ((*FirstString != L'\0') &&
1552 (*SecondString != L'\0') &&
1553 (*FirstString == *SecondString) &&
1554 (Length > 1)) {
1555 FirstString++;
1556 SecondString++;
1557 Length--;
1558 }
1559
1560 return *FirstString - *SecondString;
1561 }
1562
1563 VOID *
1564 AllocateCopyPool (
1565 UINTN AllocationSize,
1566 CONST VOID *Buffer
1567 )
1568 {
1569 return InternalAllocateCopyPool (AllocationSize, Buffer);
1570 }
1571
1572 INTN
1573 StrCmp (
1574 CONST CHAR16 *FirstString,
1575 CONST CHAR16 *SecondString
1576 )
1577 {
1578 //
1579 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
1580 //
1581 ASSERT (StrSize (FirstString) != 0);
1582 ASSERT (StrSize (SecondString) != 0);
1583
1584 while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
1585 FirstString++;
1586 SecondString++;
1587 }
1588 return *FirstString - *SecondString;
1589 }
1590
1591 UINT64
1592 SwapBytes64 (
1593 UINT64 Value
1594 )
1595 {
1596 return InternalMathSwapBytes64 (Value);
1597 }
1598
1599 UINT64
1600 InternalMathSwapBytes64 (
1601 UINT64 Operand
1602 )
1603 {
1604 UINT64 LowerBytes;
1605 UINT64 HigherBytes;
1606
1607 LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand);
1608 HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
1609
1610 return (LowerBytes << 32 | HigherBytes);
1611 }
1612
1613 RETURN_STATUS
1614 StrToIpv4Address (
1615 CONST CHAR16 *String,
1616 CHAR16 **EndPointer,
1617 EFI_IPv4_ADDRESS *Address,
1618 UINT8 *PrefixLength
1619 )
1620 {
1621 RETURN_STATUS Status;
1622 UINTN AddressIndex;
1623 UINT64 Uint64;
1624 EFI_IPv4_ADDRESS LocalAddress;
1625 UINT8 LocalPrefixLength;
1626 CHAR16 *Pointer;
1627
1628 LocalPrefixLength = MAX_UINT8;
1629 LocalAddress.Addr[0] = 0;
1630
1631 ASSERT (((UINTN) String & BIT0) == 0);
1632
1633 //
1634 // 1. None of String or Guid shall be a null pointer.
1635 //
1636 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1637 SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
1638
1639 for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
1640 if (!InternalIsDecimalDigitCharacter (*Pointer)) {
1641 //
1642 // D or P contains invalid characters.
1643 //
1644 break;
1645 }
1646
1647 //
1648 // Get D or P.
1649 //
1650 Status = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64);
1651 if (RETURN_ERROR (Status)) {
1652 return RETURN_UNSUPPORTED;
1653 }
1654 if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
1655 //
1656 // It's P.
1657 //
1658 if (Uint64 > 32) {
1659 return RETURN_UNSUPPORTED;
1660 }
1661 LocalPrefixLength = (UINT8) Uint64;
1662 } else {
1663 //
1664 // It's D.
1665 //
1666 if (Uint64 > MAX_UINT8) {
1667 return RETURN_UNSUPPORTED;
1668 }
1669 LocalAddress.Addr[AddressIndex] = (UINT8) Uint64;
1670 AddressIndex++;
1671 }
1672
1673 //
1674 // Check the '.' or '/', depending on the AddressIndex.
1675 //
1676 if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
1677 if (*Pointer == L'/') {
1678 //
1679 // '/P' is in the String.
1680 // Skip "/" and get P in next loop.
1681 //
1682 Pointer++;
1683 } else {
1684 //
1685 // '/P' is not in the String.
1686 //
1687 break;
1688 }
1689 } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
1690 if (*Pointer == L'.') {
1691 //
1692 // D should be followed by '.'
1693 //
1694 Pointer++;
1695 } else {
1696 return RETURN_UNSUPPORTED;
1697 }
1698 }
1699 }
1700
1701 if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
1702 return RETURN_UNSUPPORTED;
1703 }
1704
1705 memcpy (Address, &LocalAddress, sizeof (*Address));
1706 if (PrefixLength != NULL) {
1707 *PrefixLength = LocalPrefixLength;
1708 }
1709 if (EndPointer != NULL) {
1710 *EndPointer = Pointer;
1711 }
1712
1713 return RETURN_SUCCESS;
1714 }
1715
1716 RETURN_STATUS
1717 StrToIpv6Address (
1718 CONST CHAR16 *String,
1719 CHAR16 **EndPointer,
1720 EFI_IPv6_ADDRESS *Address,
1721 UINT8 *PrefixLength
1722 )
1723 {
1724 RETURN_STATUS Status;
1725 UINTN AddressIndex;
1726 UINT64 Uint64;
1727 EFI_IPv6_ADDRESS LocalAddress;
1728 UINT8 LocalPrefixLength;
1729 CONST CHAR16 *Pointer;
1730 CHAR16 *End;
1731 UINTN CompressStart;
1732 BOOLEAN ExpectPrefix;
1733
1734 LocalPrefixLength = MAX_UINT8;
1735 CompressStart = ARRAY_SIZE (Address->Addr);
1736 ExpectPrefix = FALSE;
1737
1738 ASSERT (((UINTN) String & BIT0) == 0);
1739
1740 //
1741 // 1. None of String or Guid shall be a null pointer.
1742 //
1743 SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
1744 SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
1745
1746 for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
1747 if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
1748 if (*Pointer != L':') {
1749 //
1750 // ":" or "/" should be followed by digit characters.
1751 //
1752 return RETURN_UNSUPPORTED;
1753 }
1754
1755 //
1756 // Meet second ":" after previous ":" or "/"
1757 // or meet first ":" in the beginning of String.
1758 //
1759 if (ExpectPrefix) {
1760 //
1761 // ":" shall not be after "/"
1762 //
1763 return RETURN_UNSUPPORTED;
1764 }
1765
1766 if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {
1767 //
1768 // "::" can only appear once.
1769 // "::" can only appear when address is not full length.
1770 //
1771 return RETURN_UNSUPPORTED;
1772 } else {
1773 //
1774 // Remember the start of zero compressing.
1775 //
1776 CompressStart = AddressIndex;
1777 Pointer++;
1778
1779 if (CompressStart == 0) {
1780 if (*Pointer != L':') {
1781 //
1782 // Single ":" shall not be in the beginning of String.
1783 //
1784 return RETURN_UNSUPPORTED;
1785 }
1786 Pointer++;
1787 }
1788 }
1789 }
1790
1791 if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
1792 if (*Pointer == L'/') {
1793 //
1794 // Might be optional "/P" after "::".
1795 //
1796 if (CompressStart != AddressIndex) {
1797 return RETURN_UNSUPPORTED;
1798 }
1799 } else {
1800 break;
1801 }
1802 } else {
1803 if (!ExpectPrefix) {
1804 //
1805 // Get X.
1806 //
1807 Status = StrHexToUint64S (Pointer, &End, &Uint64);
1808 if (RETURN_ERROR (Status) || End - Pointer > 4) {
1809 //
1810 // Number of hexadecimal digit characters is no more than 4.
1811 //
1812 return RETURN_UNSUPPORTED;
1813 }
1814 Pointer = End;
1815 //
1816 // Uint64 won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.
1817 //
1818 ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));
1819 LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uint64 >> 8);
1820 LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64;
1821 AddressIndex += 2;
1822 } else {
1823 //
1824 // Get P, then exit the loop.
1825 //
1826 Status = StrDecimalToUint64S (Pointer, &End, &Uint64);
1827 if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) {
1828 //
1829 // Prefix length should not exceed 128.
1830 //
1831 return RETURN_UNSUPPORTED;
1832 }
1833 LocalPrefixLength = (UINT8) Uint64;
1834 Pointer = End;
1835 break;
1836 }
1837 }
1838
1839 //
1840 // Skip ':' or "/"
1841 //
1842 if (*Pointer == L'/') {
1843 ExpectPrefix = TRUE;
1844 } else if (*Pointer == L':') {
1845 if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
1846 //
1847 // Meet additional ":" after all 8 16-bit address
1848 //
1849 break;
1850 }
1851 } else {
1852 //
1853 // Meet other character that is not "/" or ":" after all 8 16-bit address
1854 //
1855 break;
1856 }
1857 Pointer++;
1858 }
1859
1860 if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||
1861 (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))
1862 ) {
1863 //
1864 // Full length of address shall not have compressing zeros.
1865 // Non-full length of address shall have compressing zeros.
1866 //
1867 return RETURN_UNSUPPORTED;
1868 }
1869 memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);
1870 if (AddressIndex > CompressStart) {
1871 memset (&Address->Addr[CompressStart], 0, ARRAY_SIZE (Address->Addr) - AddressIndex);
1872 memcpy (
1873 &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],
1874 &LocalAddress.Addr[CompressStart],
1875 AddressIndex - CompressStart
1876 );
1877 }
1878
1879 if (PrefixLength != NULL) {
1880 *PrefixLength = LocalPrefixLength;
1881 }
1882 if (EndPointer != NULL) {
1883 *EndPointer = (CHAR16 *) Pointer;
1884 }
1885
1886 return RETURN_SUCCESS;
1887 }
1888
1889
1890 RETURN_STATUS
1891 UnicodeStrToAsciiStrS (
1892 CONST CHAR16 *Source,
1893 CHAR8 *Destination,
1894 UINTN DestMax
1895 )
1896 {
1897 UINTN SourceLen;
1898
1899 ASSERT (((UINTN) Source & BIT0) == 0);
1900
1901 //
1902 // 1. Neither Destination nor Source shall be a null pointer.
1903 //
1904 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
1905 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
1906
1907 //
1908 // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
1909 //
1910 if (ASCII_RSIZE_MAX != 0) {
1911 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
1912 }
1913 if (RSIZE_MAX != 0) {
1914 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1915 }
1916
1917 //
1918 // 3. DestMax shall not equal zero.
1919 //
1920 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
1921
1922 //
1923 // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
1924 //
1925 SourceLen = StrnLenS (Source, DestMax);
1926 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
1927
1928 //
1929 // 5. Copying shall not take place between objects that overlap.
1930 //
1931 SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);
1932
1933 //
1934 // convert string
1935 //
1936 while (*Source != '\0') {
1937 //
1938 // If any Unicode characters in Source contain
1939 // non-zero value in the upper 8 bits, then ASSERT().
1940 //
1941 ASSERT (*Source < 0x100);
1942 *(Destination++) = (CHAR8) *(Source++);
1943 }
1944 *Destination = '\0';
1945
1946 return RETURN_SUCCESS;
1947 }
1948
1949 RETURN_STATUS
1950 StrCpyS (
1951 CHAR16 *Destination,
1952 UINTN DestMax,
1953 CONST CHAR16 *Source
1954 )
1955 {
1956 UINTN SourceLen;
1957
1958 ASSERT (((UINTN) Destination & BIT0) == 0);
1959 ASSERT (((UINTN) Source & BIT0) == 0);
1960
1961 //
1962 // 1. Neither Destination nor Source shall be a null pointer.
1963 //
1964 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
1965 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
1966
1967 //
1968 // 2. DestMax shall not be greater than RSIZE_MAX.
1969 //
1970 if (RSIZE_MAX != 0) {
1971 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1972 }
1973
1974 //
1975 // 3. DestMax shall not equal zero.
1976 //
1977 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
1978
1979 //
1980 // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
1981 //
1982 SourceLen = StrnLenS (Source, DestMax);
1983 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
1984
1985 //
1986 // 5. Copying shall not take place between objects that overlap.
1987 //
1988 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
1989
1990 //
1991 // The StrCpyS function copies the string pointed to by Source (including the terminating
1992 // null character) into the array pointed to by Destination.
1993 //
1994 while (*Source != 0) {
1995 *(Destination++) = *(Source++);
1996 }
1997 *Destination = 0;
1998
1999 return RETURN_SUCCESS;
2000 }
2001
2002 VOID *
2003 AllocateZeroPool (
2004 UINTN AllocationSize
2005 )
2006 {
2007 VOID * Memory;
2008 Memory = malloc(AllocationSize);
2009 ASSERT (Memory != NULL);
2010 if (Memory == NULL) {
2011 fprintf(stderr, "Not memory for malloc\n");
2012 }
2013 memset(Memory, 0, AllocationSize);
2014 return Memory;
2015 }
2016
2017 VOID *
2018 AllocatePool (
2019 UINTN AllocationSize
2020 )
2021 {
2022 return InternalAllocatePool (AllocationSize);
2023 }
2024
2025 UINT16
2026 WriteUnaligned16 (
2027 UINT16 *Buffer,
2028 UINT16 Value
2029 )
2030 {
2031 ASSERT (Buffer != NULL);
2032
2033 return *Buffer = Value;
2034 }
2035
2036 UINT16
2037 ReadUnaligned16 (
2038 CONST UINT16 *Buffer
2039 )
2040 {
2041 ASSERT (Buffer != NULL);
2042
2043 return *Buffer;
2044 }
2045 /**
2046 Return whether the integer string is a hex string.
2047
2048 @param Str The integer string
2049
2050 @retval TRUE Hex string
2051 @retval FALSE Decimal string
2052
2053 **/
2054 BOOLEAN
2055 IsHexStr (
2056 CHAR16 *Str
2057 )
2058 {
2059 //
2060 // skip preceeding white space
2061 //
2062 while ((*Str != 0) && *Str == L' ') {
2063 Str ++;
2064 }
2065 //
2066 // skip preceeding zeros
2067 //
2068 while ((*Str != 0) && *Str == L'0') {
2069 Str ++;
2070 }
2071
2072 return (BOOLEAN) (*Str == L'x' || *Str == L'X');
2073 }
2074
2075 /**
2076
2077 Convert integer string to uint.
2078
2079 @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
2080
2081 @return A UINTN value represented by Str
2082
2083 **/
2084 UINTN
2085 Strtoi (
2086 CHAR16 *Str
2087 )
2088 {
2089 if (IsHexStr (Str)) {
2090 return (UINTN)StrHexToUint64 (Str);
2091 } else {
2092 return (UINTN)StrDecimalToUint64 (Str);
2093 }
2094 }
2095
2096 /**
2097
2098 Convert integer string to 64 bit data.
2099
2100 @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
2101 @param Data A pointer to the UINT64 value represented by Str
2102
2103 **/
2104 VOID
2105 Strtoi64 (
2106 CHAR16 *Str,
2107 UINT64 *Data
2108 )
2109 {
2110 if (IsHexStr (Str)) {
2111 *Data = StrHexToUint64 (Str);
2112 } else {
2113 *Data = StrDecimalToUint64 (Str);
2114 }
2115 }
2116
2117 /**
2118 Converts a Unicode string to ASCII string.
2119
2120 @param Str The equivalent Unicode string
2121 @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points
2122 to the next ASCII string next to it
2123
2124 **/
2125 VOID
2126 StrToAscii (
2127 CHAR16 *Str,
2128 CHAR8 **AsciiStr
2129 )
2130 {
2131 CHAR8 *Dest;
2132
2133 Dest = *AsciiStr;
2134 while (!IS_NULL (*Str)) {
2135 *(Dest++) = (CHAR8) *(Str++);
2136 }
2137 *Dest = 0;
2138
2139 //
2140 // Return the string next to it
2141 //
2142 *AsciiStr = Dest + 1;
2143 }
2144
2145 /**
2146 Gets current sub-string from a string list, before return
2147 the list header is moved to next sub-string. The sub-string is separated
2148 by the specified character. For example, the separator is ',', the string
2149 list is "2,0,3", it returns "2", the remain list move to "0,3"
2150
2151 @param List A string list separated by the specified separator
2152 @param Separator The separator character
2153
2154 @return A pointer to the current sub-string
2155
2156 **/
2157 CHAR16 *
2158 SplitStr (
2159 CHAR16 **List,
2160 CHAR16 Separator
2161 )
2162 {
2163 CHAR16 *Str;
2164 CHAR16 *ReturnStr;
2165
2166 Str = *List;
2167 ReturnStr = Str;
2168
2169 if (IS_NULL (*Str)) {
2170 return ReturnStr;
2171 }
2172
2173 //
2174 // Find first occurrence of the separator
2175 //
2176 while (!IS_NULL (*Str)) {
2177 if (*Str == Separator) {
2178 break;
2179 }
2180 Str++;
2181 }
2182
2183 if (*Str == Separator) {
2184 //
2185 // Find a sub-string, terminate it
2186 //
2187 *Str = L'\0';
2188 Str++;
2189 }
2190
2191 //
2192 // Move to next sub-string
2193 //
2194 *List = Str;
2195 return ReturnStr;
2196 }
2197