2 Common basic Library Functions
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
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.
24 #include "CommonLib.h"
25 #include "EfiUtilityMsgs.h"
27 #define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \
29 ASSERT (Expression); \
30 if (!(Expression)) { \
44 Set Buffer to zero for Size bytes.
48 Buffer - Memory to set.
50 Size - Number of bytes to set
76 Copy Length bytes from Source to Destination.
80 Destination - Target of copy
82 Source - Place to copy from
84 Length - Number of bytes to copy
95 Destination8
= Destination
;
98 *(Destination8
++) = *(Source8
++);
108 PeiZeroMem (Buffer
, Size
);
113 IN VOID
*Destination
,
118 PeiCopyMem (Destination
, Source
, Length
);
134 Guid1 - guid to compare
135 Guid2 - guid to compare
138 = 0 if Guid1 == Guid2
139 != 0 if Guid1 != Guid2
148 // Compare 32 bits at a time
150 g1
= (INT32
*) Guid1
;
151 g2
= (INT32
*) Guid2
;
164 IN CHAR8
*InputFileName
,
165 OUT CHAR8
**InputFileImage
,
166 OUT UINT32
*BytesRead
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.
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.
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.
194 // Verify input parameters.
196 if (InputFileName
== NULL
|| strlen (InputFileName
) == 0 || InputFileImage
== NULL
) {
197 return EFI_INVALID_PARAMETER
;
200 // Open the file and copy contents into a memory buffer.
205 InputFile
= fopen (LongFilePath (InputFileName
), "rb");
206 if (InputFile
== NULL
) {
207 Error (NULL
, 0, 0001, "Error opening the input file", InputFileName
);
211 // Go to the end so that we can determine the file size
213 if (fseek (InputFile
, 0, SEEK_END
)) {
214 Error (NULL
, 0, 0004, "Error reading the input file", InputFileName
);
221 FileSize
= ftell (InputFile
);
222 if (FileSize
== -1) {
223 Error (NULL
, 0, 0003, "Error parsing the input file", InputFileName
);
230 *InputFileImage
= malloc (FileSize
);
231 if (*InputFileImage
== NULL
) {
233 return EFI_OUT_OF_RESOURCES
;
236 // Reset to the beginning of the file
238 if (fseek (InputFile
, 0, SEEK_SET
)) {
239 Error (NULL
, 0, 0004, "Error reading the input file", InputFileName
);
241 free (*InputFileImage
);
242 *InputFileImage
= NULL
;
246 // Read all of the file contents.
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
);
252 free (*InputFileImage
);
253 *InputFileImage
= NULL
;
266 IN CHAR8
*OutputFileName
,
267 IN CHAR8
*OutputFileImage
,
268 IN UINT32 BytesToWrite
274 This function opens a file and writes OutputFileImage into the file.
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.
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.
295 // Verify input parameters.
297 if (OutputFileName
== NULL
|| strlen (OutputFileName
) == 0 || OutputFileImage
== NULL
) {
298 return EFI_INVALID_PARAMETER
;
301 // Open the file and copy contents into a memory buffer.
306 OutputFile
= fopen (LongFilePath (OutputFileName
), "wb");
307 if (OutputFile
== NULL
) {
308 Error (NULL
, 0, 0001, "Error opening the output file", OutputFileName
);
313 // Write all of the file contents.
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
);
338 This function calculates the value needed for a valid UINT8 checksum
342 Buffer Pointer to buffer containing byte data of component.
343 Size Size of the buffer
347 The 8 bit checksum value needed.
351 return (UINT8
) (0x100 - CalculateSum8 (Buffer
, Size
));
361 Routine Description::
363 This function calculates the UINT8 sum for the requested region.
367 Buffer Pointer to buffer containing byte data of component.
368 Size Size of the buffer
372 The 8 bit checksum value needed.
382 // Perform the byte sum for buffer
384 for (Index
= 0; Index
< Size
; Index
++) {
385 Sum
= (UINT8
) (Sum
+ Buffer
[Index
]);
392 CalculateChecksum16 (
398 Routine Description::
400 This function calculates the value needed for a valid UINT16 checksum
404 Buffer Pointer to buffer containing byte data of component.
405 Size Size of the buffer
409 The 16 bit checksum value needed.
413 return (UINT16
) (0x10000 - CalculateSum16 (Buffer
, Size
));
425 This function calculates the UINT16 sum for the requested region.
429 Buffer Pointer to buffer containing byte data of component.
430 Size Size of the buffer
444 // Perform the word sum for buffer
446 for (Index
= 0; Index
< Size
; Index
++) {
447 Sum
= (UINT16
) (Sum
+ Buffer
[Index
]);
461 This function prints a GUID to STDOUT.
465 Guid Pointer to a GUID to print.
469 EFI_SUCCESS The GUID was printed.
470 EFI_INVALID_PARAMETER The input was NULL.
475 Error (NULL
, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
476 return EFI_INVALID_PARAMETER
;
480 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
481 (unsigned) Guid
->Data1
,
499 IN OUT UINT8
*Buffer
,
507 This function prints a GUID to a buffer
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.
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
525 Error (NULL
, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
526 return EFI_INVALID_PARAMETER
;
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
;
537 "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
538 (unsigned) Guid
->Data1
,
553 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
554 (unsigned) Guid
->Data1
,
573 size_t _filelength(int fd
)
575 struct stat stat_buf
;
576 fstat(fd
, &stat_buf
);
577 return stat_buf
.st_size
;
581 char *strlwr(char *s
)
592 #define WINDOWS_EXTENSION_PATH "\\\\?\\"
593 #define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"
596 // Global data to store full file path. It is not required to be free.
598 CHAR8 mCommonLibFullPath
[MAX_LONG_FILE_PATH
];
607 Convert FileName to the long file path, which can support larger than 260 length.
613 LongFilePath A pointer to the converted long file path.
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.
628 PathPointer
= (CHAR8
*) FileName
;
630 if (FileName
!= NULL
) {
632 // Add the extension string first to support long file path.
634 mCommonLibFullPath
[0] = 0;
635 strcpy (mCommonLibFullPath
, WINDOWS_EXTENSION_PATH
);
637 if (strlen (FileName
) > 1 && FileName
[0] == '\\' && FileName
[1] == '\\') {
639 // network path like \\server\share to \\?\UNC\server\share
641 strcpy (mCommonLibFullPath
, WINDOWS_UNC_EXTENSION_PATH
);
643 } else if (strlen (FileName
) < 3 || FileName
[1] != ':' || (FileName
[2] != '\\' && FileName
[2] != '/')) {
645 // Relative file path. Convert it to absolute path.
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!");
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!");
662 // Attach directory separator
664 strncat (mCommonLibFullPath
, "\\", MAX_LONG_FILE_PATH
- strlen (mCommonLibFullPath
) - 1);
671 // Construct the full file path
673 if (strlen (mCommonLibFullPath
) + strlen (FileName
) > MAX_LONG_FILE_PATH
- 1) {
674 Error (NULL
, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName
);
677 strncat (mCommonLibFullPath
, FileName
, MAX_LONG_FILE_PATH
- strlen (mCommonLibFullPath
) - 1);
680 // Convert directory separator '/' to '\\'
682 PathPointer
= (CHAR8
*) mCommonLibFullPath
;
684 if (*PathPointer
== '/') {
687 } while (*PathPointer
++ != '\0');
690 // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
692 if ((PathPointer
= strstr (mCommonLibFullPath
, ":\\\\")) != NULL
) {
693 *(PathPointer
+ 2) = '\0';
694 strncat (mCommonLibFullPath
, PathPointer
+ 3, MAX_LONG_FILE_PATH
- strlen (mCommonLibFullPath
) - 1);
698 // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.
700 while ((PathPointer
= strstr (mCommonLibFullPath
, ".\\")) != NULL
) {
702 strncat (mCommonLibFullPath
, PathPointer
+ 2, MAX_LONG_FILE_PATH
- strlen (mCommonLibFullPath
) - 1);
706 // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
708 while ((PathPointer
= strstr (mCommonLibFullPath
, "\\.\\")) != NULL
) {
710 strncat (mCommonLibFullPath
, PathPointer
+ 2, MAX_LONG_FILE_PATH
- strlen (mCommonLibFullPath
) - 1);
714 // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.
716 while ((PathPointer
= strstr (mCommonLibFullPath
, "\\..\\")) != NULL
) {
717 NextPointer
= PathPointer
+ 3;
720 } while (PathPointer
> mCommonLibFullPath
&& *PathPointer
!= ':' && *PathPointer
!= '\\');
722 if (*PathPointer
== '\\') {
724 // Skip one directory
727 strncat (mCommonLibFullPath
, NextPointer
, MAX_LONG_FILE_PATH
- strlen (mCommonLibFullPath
) - 1);
730 // No directory is found. Just break.
736 PathPointer
= mCommonLibFullPath
;
744 InternalCharToUpper (
748 if (Char
>= L
'a' && Char
<= L
'z') {
749 return (CHAR16
) (Char
- (L
'a' - L
'A'));
757 CONST CHAR16
*String
,
763 ASSERT (((UINTN
) String
& BIT0
) == 0);
766 // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.
768 if ((String
== NULL
) || (MaxSize
== 0)) {
773 while (String
[Length
] != 0) {
774 if (Length
>= MaxSize
- 1) {
784 InternalAllocatePool (
790 Memory
= malloc(AllocationSize
);
791 ASSERT(Memory
!= NULL
);
797 InternalReallocatePool (
800 VOID
*OldBuffer OPTIONAL
805 NewBuffer
= AllocateZeroPool (NewSize
);
806 if (NewBuffer
!= NULL
&& OldBuffer
!= NULL
) {
807 memcpy (NewBuffer
, OldBuffer
, MIN (OldSize
, NewSize
));
817 VOID
*OldBuffer OPTIONAL
820 return InternalReallocatePool (OldSize
, NewSize
, OldBuffer
);
824 Returns the length of a Null-terminated Unicode string.
826 This function returns the number of Unicode characters in the Null-terminated
827 Unicode string specified by String.
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().
835 @param String A pointer to a Null-terminated Unicode string.
837 @return The length of String.
847 ASSERT (String
!= NULL
);
848 ASSERT (((UINTN
) String
& BIT0
) == 0);
850 for (Length
= 0; *String
!= L
'\0'; String
++, Length
++) {
852 // If PcdMaximumUnicodeStringLength is not zero,
853 // length should not more than PcdMaximumUnicodeStringLength
860 InternalSafeStringIsOverlap (
867 if ((((UINTN
)Base1
>= (UINTN
)Base2
) && ((UINTN
)Base1
< (UINTN
)Base2
+ Size2
)) ||
868 (((UINTN
)Base2
>= (UINTN
)Base1
) && ((UINTN
)Base2
< (UINTN
)Base1
+ Size1
))) {
875 InternalSafeStringNoStrOverlap (
882 return !InternalSafeStringIsOverlap (Str1
, Size1
* sizeof(CHAR16
), Str2
, Size2
* sizeof(CHAR16
));
887 CONST CHAR16
*String
,
888 CHAR16
**EndPointer
, OPTIONAL
892 ASSERT (((UINTN
) String
& BIT0
) == 0);
895 // 1. Neither String nor Data shall be a null pointer.
897 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
898 SAFE_STRING_CONSTRAINT_CHECK ((Data
!= NULL
), RETURN_INVALID_PARAMETER
);
901 // 2. The length of String shall not be greater than RSIZE_MAX.
903 if (RSIZE_MAX
!= 0) {
904 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String
, RSIZE_MAX
+ 1) <= RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
907 if (EndPointer
!= NULL
) {
908 *EndPointer
= (CHAR16
*) String
;
912 // Ignore the pad spaces (space or tab)
914 while ((*String
== L
' ') || (*String
== L
'\t')) {
919 // Ignore leading Zeros after the spaces
921 while (*String
== L
'0') {
927 while (InternalIsDecimalDigitCharacter (*String
)) {
929 // If the number represented by String overflows according to the range
930 // defined by UINTN, then MAX_UINTN is stored in *Data and
931 // RETURN_UNSUPPORTED is returned.
933 if (*Data
> ((MAX_UINTN
- (*String
- L
'0')) / 10)) {
935 if (EndPointer
!= NULL
) {
936 *EndPointer
= (CHAR16
*) String
;
938 return RETURN_UNSUPPORTED
;
941 *Data
= *Data
* 10 + (*String
- L
'0');
945 if (EndPointer
!= NULL
) {
946 *EndPointer
= (CHAR16
*) String
;
948 return RETURN_SUCCESS
;
952 Convert a Null-terminated Unicode decimal string to a value of type UINT64.
954 This function outputs a value of type UINT64 by interpreting the contents of
955 the Unicode string specified by String as a decimal number. The format of the
956 input Unicode string String is:
958 [spaces] [decimal digits].
960 The valid decimal digit character is in the range [0-9]. The function will
961 ignore the pad space, which includes spaces or tab characters, before
962 [decimal digits]. The running zero in the beginning of [decimal digits] will
963 be ignored. Then, the function stops at the first character that is a not a
964 valid decimal character or a Null-terminator, whichever one comes first.
966 If String is NULL, then ASSERT().
967 If Data is NULL, then ASSERT().
968 If String is not aligned in a 16-bit boundary, then ASSERT().
969 If PcdMaximumUnicodeStringLength is not zero, and String contains more than
970 PcdMaximumUnicodeStringLength Unicode characters, not including the
971 Null-terminator, then ASSERT().
973 If String has no valid decimal digits in the above format, then 0 is stored
974 at the location pointed to by Data.
975 If the number represented by String exceeds the range defined by UINT64, then
976 MAX_UINT64 is stored at the location pointed to by Data.
978 If EndPointer is not NULL, a pointer to the character that stopped the scan
979 is stored at the location pointed to by EndPointer. If String has no valid
980 decimal digits right after the optional pad spaces, the value of String is
981 stored at the location pointed to by EndPointer.
983 @param String Pointer to a Null-terminated Unicode string.
984 @param EndPointer Pointer to character that stops scan.
985 @param Data Pointer to the converted value.
987 @retval RETURN_SUCCESS Value is translated from String.
988 @retval RETURN_INVALID_PARAMETER If String is NULL.
990 If PcdMaximumUnicodeStringLength is not
991 zero, and String contains more than
992 PcdMaximumUnicodeStringLength Unicode
993 characters, not including the
995 @retval RETURN_UNSUPPORTED If the number represented by String exceeds
996 the range defined by UINT64.
1000 StrDecimalToUint64S (
1001 CONST CHAR16
*String
,
1002 CHAR16
**EndPointer
, OPTIONAL
1006 ASSERT (((UINTN
) String
& BIT0
) == 0);
1009 // 1. Neither String nor Data shall be a null pointer.
1011 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
1012 SAFE_STRING_CONSTRAINT_CHECK ((Data
!= NULL
), RETURN_INVALID_PARAMETER
);
1015 // 2. The length of String shall not be greater than RSIZE_MAX.
1017 if (RSIZE_MAX
!= 0) {
1018 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String
, RSIZE_MAX
+ 1) <= RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
1021 if (EndPointer
!= NULL
) {
1022 *EndPointer
= (CHAR16
*) String
;
1026 // Ignore the pad spaces (space or tab)
1028 while ((*String
== L
' ') || (*String
== L
'\t')) {
1033 // Ignore leading Zeros after the spaces
1035 while (*String
== L
'0') {
1041 while (InternalIsDecimalDigitCharacter (*String
)) {
1043 // If the number represented by String overflows according to the range
1044 // defined by UINT64, then MAX_UINT64 is stored in *Data and
1045 // RETURN_UNSUPPORTED is returned.
1047 if (*Data
> ((MAX_UINT64
- (*String
- L
'0'))/10)) {
1049 if (EndPointer
!= NULL
) {
1050 *EndPointer
= (CHAR16
*) String
;
1052 return RETURN_UNSUPPORTED
;
1055 *Data
= (*Data
) * 10 + (*String
- L
'0');
1059 if (EndPointer
!= NULL
) {
1060 *EndPointer
= (CHAR16
*) String
;
1062 return RETURN_SUCCESS
;
1066 Convert a Null-terminated Unicode hexadecimal string to a value of type
1069 This function outputs a value of type UINTN by interpreting the contents of
1070 the Unicode string specified by String as a hexadecimal number. The format of
1071 the input Unicode string String is:
1073 [spaces][zeros][x][hexadecimal digits].
1075 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
1076 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
1077 If "x" appears in the input string, it must be prefixed with at least one 0.
1078 The function will ignore the pad space, which includes spaces or tab
1079 characters, before [zeros], [x] or [hexadecimal digit]. The running zero
1080 before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
1081 after [x] or the first valid hexadecimal digit. Then, the function stops at
1082 the first character that is a not a valid hexadecimal character or NULL,
1083 whichever one comes first.
1085 If String is NULL, then ASSERT().
1086 If Data is NULL, then ASSERT().
1087 If String is not aligned in a 16-bit boundary, then ASSERT().
1088 If PcdMaximumUnicodeStringLength is not zero, and String contains more than
1089 PcdMaximumUnicodeStringLength Unicode characters, not including the
1090 Null-terminator, then ASSERT().
1092 If String has no valid hexadecimal digits in the above format, then 0 is
1093 stored at the location pointed to by Data.
1094 If the number represented by String exceeds the range defined by UINTN, then
1095 MAX_UINTN is stored at the location pointed to by Data.
1097 If EndPointer is not NULL, a pointer to the character that stopped the scan
1098 is stored at the location pointed to by EndPointer. If String has no valid
1099 hexadecimal digits right after the optional pad spaces, the value of String
1100 is stored at the location pointed to by EndPointer.
1102 @param String Pointer to a Null-terminated Unicode string.
1103 @param EndPointer Pointer to character that stops scan.
1104 @param Data Pointer to the converted value.
1106 @retval RETURN_SUCCESS Value is translated from String.
1107 @retval RETURN_INVALID_PARAMETER If String is NULL.
1109 If PcdMaximumUnicodeStringLength is not
1110 zero, and String contains more than
1111 PcdMaximumUnicodeStringLength Unicode
1112 characters, not including the
1114 @retval RETURN_UNSUPPORTED If the number represented by String exceeds
1115 the range defined by UINTN.
1120 CONST CHAR16
*String
,
1121 CHAR16
**EndPointer
, OPTIONAL
1125 ASSERT (((UINTN
) String
& BIT0
) == 0);
1128 // 1. Neither String nor Data shall be a null pointer.
1130 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
1131 SAFE_STRING_CONSTRAINT_CHECK ((Data
!= NULL
), RETURN_INVALID_PARAMETER
);
1134 // 2. The length of String shall not be greater than RSIZE_MAX.
1136 if (RSIZE_MAX
!= 0) {
1137 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String
, RSIZE_MAX
+ 1) <= RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
1140 if (EndPointer
!= NULL
) {
1141 *EndPointer
= (CHAR16
*) String
;
1145 // Ignore the pad spaces (space or tab)
1147 while ((*String
== L
' ') || (*String
== L
'\t')) {
1152 // Ignore leading Zeros after the spaces
1154 while (*String
== L
'0') {
1158 if (InternalCharToUpper (*String
) == L
'X') {
1159 if (*(String
- 1) != L
'0') {
1161 return RETURN_SUCCESS
;
1171 while (InternalIsHexaDecimalDigitCharacter (*String
)) {
1173 // If the number represented by String overflows according to the range
1174 // defined by UINTN, then MAX_UINTN is stored in *Data and
1175 // RETURN_UNSUPPORTED is returned.
1177 if (*Data
> ((MAX_UINTN
- InternalHexCharToUintn (*String
)) >> 4)) {
1179 if (EndPointer
!= NULL
) {
1180 *EndPointer
= (CHAR16
*) String
;
1182 return RETURN_UNSUPPORTED
;
1185 *Data
= (*Data
<< 4) + InternalHexCharToUintn (*String
);
1189 if (EndPointer
!= NULL
) {
1190 *EndPointer
= (CHAR16
*) String
;
1192 return RETURN_SUCCESS
;
1196 CONST CHAR16
*String
,
1197 CHAR16
**EndPointer
, OPTIONAL
1201 ASSERT (((UINTN
) String
& BIT0
) == 0);
1204 // 1. Neither String nor Data shall be a null pointer.
1206 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
1207 SAFE_STRING_CONSTRAINT_CHECK ((Data
!= NULL
), RETURN_INVALID_PARAMETER
);
1210 // 2. The length of String shall not be greater than RSIZE_MAX.
1212 if (RSIZE_MAX
!= 0) {
1213 SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String
, RSIZE_MAX
+ 1) <= RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
1216 if (EndPointer
!= NULL
) {
1217 *EndPointer
= (CHAR16
*) String
;
1221 // Ignore the pad spaces (space or tab)
1223 while ((*String
== L
' ') || (*String
== L
'\t')) {
1228 // Ignore leading Zeros after the spaces
1230 while (*String
== L
'0') {
1234 if (InternalCharToUpper (*String
) == L
'X') {
1235 if (*(String
- 1) != L
'0') {
1237 return RETURN_SUCCESS
;
1247 while (InternalIsHexaDecimalDigitCharacter (*String
)) {
1249 // If the number represented by String overflows according to the range
1250 // defined by UINT64, then MAX_UINT64 is stored in *Data and
1251 // RETURN_UNSUPPORTED is returned.
1253 if (*Data
> ((MAX_UINT64
- InternalHexCharToUintn (*String
))>>4)) {
1255 if (EndPointer
!= NULL
) {
1256 *EndPointer
= (CHAR16
*) String
;
1258 return RETURN_UNSUPPORTED
;
1261 *Data
= ((*Data
) << 4) + InternalHexCharToUintn (*String
);
1265 if (EndPointer
!= NULL
) {
1266 *EndPointer
= (CHAR16
*) String
;
1268 return RETURN_SUCCESS
;
1272 StrDecimalToUint64 (
1273 CONST CHAR16
*String
1278 StrDecimalToUint64S (String
, (CHAR16
**) NULL
, &Result
);
1285 CONST CHAR16
*String
1290 StrHexToUint64S (String
, (CHAR16
**) NULL
, &Result
);
1296 CONST CHAR16
*String
1301 StrDecimalToUintnS (String
, (CHAR16
**) NULL
, &Result
);
1307 CONST CHAR16
*String
1312 StrHexToUintnS (String
, (CHAR16
**) NULL
, &Result
);
1318 CONST CHAR16
*String
1321 return (StrLen (String
) + 1) * sizeof (*String
);
1327 CONST UINT64
*Buffer
1330 ASSERT (Buffer
!= NULL
);
1341 ASSERT (Buffer
!= NULL
);
1343 return *Buffer
= Value
;
1349 EFI_GUID
*DestinationGuid
,
1350 CONST EFI_GUID
*SourceGuid
1354 (UINT64
*)DestinationGuid
,
1355 ReadUnaligned64 ((CONST UINT64
*)SourceGuid
)
1358 (UINT64
*)DestinationGuid
+ 1,
1359 ReadUnaligned64 ((CONST UINT64
*)SourceGuid
+ 1)
1361 return DestinationGuid
;
1369 return (UINT16
) ((Value
<< 8) | (Value
>> 8));
1381 LowerBytes
= (UINT32
) SwapBytes16 ((UINT16
) Value
);
1382 HigherBytes
= (UINT32
) SwapBytes16 ((UINT16
) (Value
>> 16));
1383 return (LowerBytes
<< 16 | HigherBytes
);
1387 InternalIsDecimalDigitCharacter (
1391 return (BOOLEAN
) (Char
>= L
'0' && Char
<= L
'9');
1395 InternalAllocateCopyPool (
1396 UINTN AllocationSize
,
1402 ASSERT (Buffer
!= NULL
);
1403 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
1405 Memory
= malloc (AllocationSize
);
1406 if (Memory
!= NULL
) {
1407 Memory
= memcpy (Memory
, Buffer
, AllocationSize
);
1413 InternalIsHexaDecimalDigitCharacter (
1418 return (BOOLEAN
) (InternalIsDecimalDigitCharacter (Char
) ||
1419 (Char
>= L
'A' && Char
<= L
'F') ||
1420 (Char
>= L
'a' && Char
<= L
'f'));
1424 InternalHexCharToUintn (
1428 if (InternalIsDecimalDigitCharacter (Char
)) {
1432 return (10 + InternalCharToUpper (Char
) - L
'A');
1437 Convert a Null-terminated Unicode hexadecimal string to a byte array.
1439 This function outputs a byte array by interpreting the contents of
1440 the Unicode string specified by String in hexadecimal format. The format of
1441 the input Unicode string String is:
1445 X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
1446 The function decodes every two hexadecimal digit characters as one byte. The
1447 decoding stops after Length of characters and outputs Buffer containing
1450 If String is not aligned in a 16-bit boundary, then ASSERT().
1452 If String is NULL, then ASSERT().
1454 If Buffer is NULL, then ASSERT().
1456 If Length is not multiple of 2, then ASSERT().
1458 If PcdMaximumUnicodeStringLength is not zero and Length is greater than
1459 PcdMaximumUnicodeStringLength, then ASSERT().
1461 If MaxBufferSize is less than (Length / 2), then ASSERT().
1463 @param String Pointer to a Null-terminated Unicode string.
1464 @param Length The number of Unicode characters to decode.
1465 @param Buffer Pointer to the converted bytes array.
1466 @param MaxBufferSize The maximum size of Buffer.
1468 @retval RETURN_SUCCESS Buffer is translated from String.
1469 @retval RETURN_INVALID_PARAMETER If String is NULL.
1471 If Length is not multiple of 2.
1472 If PcdMaximumUnicodeStringLength is not zero,
1473 and Length is greater than
1474 PcdMaximumUnicodeStringLength.
1475 @retval RETURN_UNSUPPORTED If Length of characters from String contain
1476 a character that is not valid hexadecimal
1477 digit characters, or a Null-terminator.
1478 @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2).
1482 CONST CHAR16
*String
,
1490 ASSERT (((UINTN
) String
& BIT0
) == 0);
1493 // 1. None of String or Buffer shall be a null pointer.
1495 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
1496 SAFE_STRING_CONSTRAINT_CHECK ((Buffer
!= NULL
), RETURN_INVALID_PARAMETER
);
1499 // 2. Length shall not be greater than RSIZE_MAX.
1501 if (RSIZE_MAX
!= 0) {
1502 SAFE_STRING_CONSTRAINT_CHECK ((Length
<= RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
1506 // 3. Length shall not be odd.
1508 SAFE_STRING_CONSTRAINT_CHECK (((Length
& BIT0
) == 0), RETURN_INVALID_PARAMETER
);
1511 // 4. MaxBufferSize shall equal to or greater than Length / 2.
1513 SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize
>= Length
/ 2), RETURN_BUFFER_TOO_SMALL
);
1516 // 5. String shall not contains invalid hexadecimal digits.
1518 for (Index
= 0; Index
< Length
; Index
++) {
1519 if (!InternalIsHexaDecimalDigitCharacter (String
[Index
])) {
1523 if (Index
!= Length
) {
1524 return RETURN_UNSUPPORTED
;
1528 // Convert the hex string to bytes.
1530 for(Index
= 0; Index
< Length
; Index
++) {
1533 // For even characters, write the upper nibble for each buffer byte,
1534 // and for even characters, the lower nibble.
1536 if ((Index
& BIT0
) == 0) {
1537 Buffer
[Index
/ 2] = (UINT8
) InternalHexCharToUintn (String
[Index
]) << 4;
1539 Buffer
[Index
/ 2] |= (UINT8
) InternalHexCharToUintn (String
[Index
]);
1542 return RETURN_SUCCESS
;
1546 Convert a Null-terminated Unicode GUID string to a value of type
1549 This function outputs a GUID value by interpreting the contents of
1550 the Unicode string specified by String. The format of the input
1551 Unicode string String consists of 36 characters, as follows:
1553 aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
1555 The pairs aa - pp are two characters in the range [0-9], [a-f] and
1556 [A-F], with each pair representing a single byte hexadecimal value.
1558 The mapping between String and the EFI_GUID structure is as follows:
1576 If String is NULL, then ASSERT().
1577 If Guid is NULL, then ASSERT().
1578 If String is not aligned in a 16-bit boundary, then ASSERT().
1580 @param String Pointer to a Null-terminated Unicode string.
1581 @param Guid Pointer to the converted GUID.
1583 @retval RETURN_SUCCESS Guid is translated from String.
1584 @retval RETURN_INVALID_PARAMETER If String is NULL.
1586 @retval RETURN_UNSUPPORTED If String is not as the above format.
1591 CONST CHAR16
*String
,
1595 RETURN_STATUS Status
;
1598 ASSERT (((UINTN
) String
& BIT0
) == 0);
1601 // 1. None of String or Guid shall be a null pointer.
1603 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
1604 SAFE_STRING_CONSTRAINT_CHECK ((Guid
!= NULL
), RETURN_INVALID_PARAMETER
);
1607 // Get aabbccdd in big-endian.
1609 Status
= StrHexToBytes (String
, 2 * sizeof (LocalGuid
.Data1
), (UINT8
*) &LocalGuid
.Data1
, sizeof (LocalGuid
.Data1
));
1610 if (RETURN_ERROR (Status
) || String
[2 * sizeof (LocalGuid
.Data1
)] != L
'-') {
1611 return RETURN_UNSUPPORTED
;
1614 // Convert big-endian to little-endian.
1616 LocalGuid
.Data1
= SwapBytes32 (LocalGuid
.Data1
);
1617 String
+= 2 * sizeof (LocalGuid
.Data1
) + 1;
1620 // Get eeff in big-endian.
1622 Status
= StrHexToBytes (String
, 2 * sizeof (LocalGuid
.Data2
), (UINT8
*) &LocalGuid
.Data2
, sizeof (LocalGuid
.Data2
));
1623 if (RETURN_ERROR (Status
) || String
[2 * sizeof (LocalGuid
.Data2
)] != L
'-') {
1624 return RETURN_UNSUPPORTED
;
1627 // Convert big-endian to little-endian.
1629 LocalGuid
.Data2
= SwapBytes16 (LocalGuid
.Data2
);
1630 String
+= 2 * sizeof (LocalGuid
.Data2
) + 1;
1633 // Get gghh in big-endian.
1635 Status
= StrHexToBytes (String
, 2 * sizeof (LocalGuid
.Data3
), (UINT8
*) &LocalGuid
.Data3
, sizeof (LocalGuid
.Data3
));
1636 if (RETURN_ERROR (Status
) || String
[2 * sizeof (LocalGuid
.Data3
)] != L
'-') {
1637 return RETURN_UNSUPPORTED
;
1640 // Convert big-endian to little-endian.
1642 LocalGuid
.Data3
= SwapBytes16 (LocalGuid
.Data3
);
1643 String
+= 2 * sizeof (LocalGuid
.Data3
) + 1;
1648 Status
= StrHexToBytes (String
, 2 * 2, &LocalGuid
.Data4
[0], 2);
1649 if (RETURN_ERROR (Status
) || String
[2 * 2] != L
'-') {
1650 return RETURN_UNSUPPORTED
;
1652 String
+= 2 * 2 + 1;
1655 // Get kkllmmnnoopp.
1657 Status
= StrHexToBytes (String
, 2 * 6, &LocalGuid
.Data4
[2], 6);
1658 if (RETURN_ERROR (Status
)) {
1659 return RETURN_UNSUPPORTED
;
1662 CopyGuid (Guid
, &LocalGuid
);
1663 return RETURN_SUCCESS
;
1667 Compares up to a specified length the contents of two Null-terminated Unicode strings,
1668 and returns the difference between the first mismatched Unicode characters.
1670 This function compares the Null-terminated Unicode string FirstString to the
1671 Null-terminated Unicode string SecondString. At most, Length Unicode
1672 characters will be compared. If Length is 0, then 0 is returned. If
1673 FirstString is identical to SecondString, then 0 is returned. Otherwise, the
1674 value returned is the first mismatched Unicode character in SecondString
1675 subtracted from the first mismatched Unicode character in FirstString.
1677 If Length > 0 and FirstString is NULL, then ASSERT().
1678 If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().
1679 If Length > 0 and SecondString is NULL, then ASSERT().
1680 If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().
1681 If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
1682 PcdMaximumUnicodeStringLength, then ASSERT().
1683 If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than
1684 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
1686 If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than
1687 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
1690 @param FirstString A pointer to a Null-terminated Unicode string.
1691 @param SecondString A pointer to a Null-terminated Unicode string.
1692 @param Length The maximum number of Unicode characters to compare.
1694 @retval 0 FirstString is identical to SecondString.
1695 @return others FirstString is not identical to SecondString.
1700 CONST CHAR16
*FirstString
,
1701 CONST CHAR16
*SecondString
,
1710 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
1711 // Length tests are performed inside StrLen().
1713 ASSERT (StrSize (FirstString
) != 0);
1714 ASSERT (StrSize (SecondString
) != 0);
1716 while ((*FirstString
!= L
'\0') &&
1717 (*SecondString
!= L
'\0') &&
1718 (*FirstString
== *SecondString
) &&
1725 return *FirstString
- *SecondString
;
1730 UINTN AllocationSize
,
1734 return InternalAllocateCopyPool (AllocationSize
, Buffer
);
1739 CONST CHAR16
*FirstString
,
1740 CONST CHAR16
*SecondString
1744 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
1746 ASSERT (StrSize (FirstString
) != 0);
1747 ASSERT (StrSize (SecondString
) != 0);
1749 while ((*FirstString
!= L
'\0') && (*FirstString
== *SecondString
)) {
1753 return *FirstString
- *SecondString
;
1761 return InternalMathSwapBytes64 (Value
);
1765 InternalMathSwapBytes64 (
1772 LowerBytes
= (UINT64
) SwapBytes32 ((UINT32
) Operand
);
1773 HigherBytes
= (UINT64
) SwapBytes32 ((UINT32
) (Operand
>> 32));
1775 return (LowerBytes
<< 32 | HigherBytes
);
1780 CONST CHAR16
*String
,
1781 CHAR16
**EndPointer
,
1782 EFI_IPv4_ADDRESS
*Address
,
1786 RETURN_STATUS Status
;
1789 EFI_IPv4_ADDRESS LocalAddress
;
1790 UINT8 LocalPrefixLength
;
1793 LocalPrefixLength
= MAX_UINT8
;
1794 LocalAddress
.Addr
[0] = 0;
1796 ASSERT (((UINTN
) String
& BIT0
) == 0);
1799 // 1. None of String or Guid shall be a null pointer.
1801 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
1802 SAFE_STRING_CONSTRAINT_CHECK ((Address
!= NULL
), RETURN_INVALID_PARAMETER
);
1804 for (Pointer
= (CHAR16
*) String
, AddressIndex
= 0; AddressIndex
< ARRAY_SIZE (Address
->Addr
) + 1;) {
1805 if (!InternalIsDecimalDigitCharacter (*Pointer
)) {
1807 // D or P contains invalid characters.
1815 Status
= StrDecimalToUintnS ((CONST CHAR16
*) Pointer
, &Pointer
, &Uintn
);
1816 if (RETURN_ERROR (Status
)) {
1817 return RETURN_UNSUPPORTED
;
1819 if (AddressIndex
== ARRAY_SIZE (Address
->Addr
)) {
1824 return RETURN_UNSUPPORTED
;
1826 LocalPrefixLength
= (UINT8
) Uintn
;
1831 if (Uintn
> MAX_UINT8
) {
1832 return RETURN_UNSUPPORTED
;
1834 LocalAddress
.Addr
[AddressIndex
] = (UINT8
) Uintn
;
1839 // Check the '.' or '/', depending on the AddressIndex.
1841 if (AddressIndex
== ARRAY_SIZE (Address
->Addr
)) {
1842 if (*Pointer
== L
'/') {
1844 // '/P' is in the String.
1845 // Skip "/" and get P in next loop.
1850 // '/P' is not in the String.
1854 } else if (AddressIndex
< ARRAY_SIZE (Address
->Addr
)) {
1855 if (*Pointer
== L
'.') {
1857 // D should be followed by '.'
1861 return RETURN_UNSUPPORTED
;
1866 if (AddressIndex
< ARRAY_SIZE (Address
->Addr
)) {
1867 return RETURN_UNSUPPORTED
;
1870 memcpy (Address
, &LocalAddress
, sizeof (*Address
));
1871 if (PrefixLength
!= NULL
) {
1872 *PrefixLength
= LocalPrefixLength
;
1874 if (EndPointer
!= NULL
) {
1875 *EndPointer
= Pointer
;
1878 return RETURN_SUCCESS
;
1883 CONST CHAR16
*String
,
1884 CHAR16
**EndPointer
,
1885 EFI_IPv6_ADDRESS
*Address
,
1889 RETURN_STATUS Status
;
1892 EFI_IPv6_ADDRESS LocalAddress
;
1893 UINT8 LocalPrefixLength
;
1894 CONST CHAR16
*Pointer
;
1896 UINTN CompressStart
;
1897 BOOLEAN ExpectPrefix
;
1899 LocalPrefixLength
= MAX_UINT8
;
1900 CompressStart
= ARRAY_SIZE (Address
->Addr
);
1901 ExpectPrefix
= FALSE
;
1903 ASSERT (((UINTN
) String
& BIT0
) == 0);
1906 // 1. None of String or Guid shall be a null pointer.
1908 SAFE_STRING_CONSTRAINT_CHECK ((String
!= NULL
), RETURN_INVALID_PARAMETER
);
1909 SAFE_STRING_CONSTRAINT_CHECK ((Address
!= NULL
), RETURN_INVALID_PARAMETER
);
1911 for (Pointer
= String
, AddressIndex
= 0; AddressIndex
< ARRAY_SIZE (Address
->Addr
) + 1;) {
1912 if (!InternalIsHexaDecimalDigitCharacter (*Pointer
)) {
1913 if (*Pointer
!= L
':') {
1915 // ":" or "/" should be followed by digit characters.
1917 return RETURN_UNSUPPORTED
;
1921 // Meet second ":" after previous ":" or "/"
1922 // or meet first ":" in the beginning of String.
1926 // ":" shall not be after "/"
1928 return RETURN_UNSUPPORTED
;
1931 if (CompressStart
!= ARRAY_SIZE (Address
->Addr
) || AddressIndex
== ARRAY_SIZE (Address
->Addr
)) {
1933 // "::" can only appear once.
1934 // "::" can only appear when address is not full length.
1936 return RETURN_UNSUPPORTED
;
1939 // Remember the start of zero compressing.
1941 CompressStart
= AddressIndex
;
1944 if (CompressStart
== 0) {
1945 if (*Pointer
!= L
':') {
1947 // Single ":" shall not be in the beginning of String.
1949 return RETURN_UNSUPPORTED
;
1956 if (!InternalIsHexaDecimalDigitCharacter (*Pointer
)) {
1957 if (*Pointer
== L
'/') {
1959 // Might be optional "/P" after "::".
1961 if (CompressStart
!= AddressIndex
) {
1962 return RETURN_UNSUPPORTED
;
1968 if (!ExpectPrefix
) {
1972 Status
= StrHexToUintnS (Pointer
, &End
, &Uintn
);
1973 if (RETURN_ERROR (Status
) || End
- Pointer
> 4) {
1975 // Number of hexadecimal digit characters is no more than 4.
1977 return RETURN_UNSUPPORTED
;
1981 // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.
1983 ASSERT (AddressIndex
+ 1 < ARRAY_SIZE (Address
->Addr
));
1984 LocalAddress
.Addr
[AddressIndex
] = (UINT8
) ((UINT16
) Uintn
>> 8);
1985 LocalAddress
.Addr
[AddressIndex
+ 1] = (UINT8
) Uintn
;
1989 // Get P, then exit the loop.
1991 Status
= StrDecimalToUintnS (Pointer
, &End
, &Uintn
);
1992 if (RETURN_ERROR (Status
) || End
== Pointer
|| Uintn
> 128) {
1994 // Prefix length should not exceed 128.
1996 return RETURN_UNSUPPORTED
;
1998 LocalPrefixLength
= (UINT8
) Uintn
;
2007 if (*Pointer
== L
'/') {
2008 ExpectPrefix
= TRUE
;
2009 } else if (*Pointer
== L
':') {
2010 if (AddressIndex
== ARRAY_SIZE (Address
->Addr
)) {
2012 // Meet additional ":" after all 8 16-bit address
2018 // Meet other character that is not "/" or ":" after all 8 16-bit address
2025 if ((AddressIndex
== ARRAY_SIZE (Address
->Addr
) && CompressStart
!= ARRAY_SIZE (Address
->Addr
)) ||
2026 (AddressIndex
!= ARRAY_SIZE (Address
->Addr
) && CompressStart
== ARRAY_SIZE (Address
->Addr
))
2029 // Full length of address shall not have compressing zeros.
2030 // Non-full length of address shall have compressing zeros.
2032 return RETURN_UNSUPPORTED
;
2034 memcpy (&Address
->Addr
[0], &LocalAddress
.Addr
[0], CompressStart
);
2035 if (AddressIndex
> CompressStart
) {
2036 memset (&Address
->Addr
[CompressStart
], 0, ARRAY_SIZE (Address
->Addr
) - AddressIndex
);
2038 &Address
->Addr
[CompressStart
+ ARRAY_SIZE (Address
->Addr
) - AddressIndex
],
2039 &LocalAddress
.Addr
[CompressStart
],
2040 AddressIndex
- CompressStart
2044 if (PrefixLength
!= NULL
) {
2045 *PrefixLength
= LocalPrefixLength
;
2047 if (EndPointer
!= NULL
) {
2048 *EndPointer
= (CHAR16
*) Pointer
;
2051 return RETURN_SUCCESS
;
2056 UnicodeStrToAsciiStrS (
2057 CONST CHAR16
*Source
,
2064 ASSERT (((UINTN
) Source
& BIT0
) == 0);
2067 // 1. Neither Destination nor Source shall be a null pointer.
2069 SAFE_STRING_CONSTRAINT_CHECK ((Destination
!= NULL
), RETURN_INVALID_PARAMETER
);
2070 SAFE_STRING_CONSTRAINT_CHECK ((Source
!= NULL
), RETURN_INVALID_PARAMETER
);
2073 // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
2075 if (ASCII_RSIZE_MAX
!= 0) {
2076 SAFE_STRING_CONSTRAINT_CHECK ((DestMax
<= ASCII_RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
2078 if (RSIZE_MAX
!= 0) {
2079 SAFE_STRING_CONSTRAINT_CHECK ((DestMax
<= RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
2083 // 3. DestMax shall not equal zero.
2085 SAFE_STRING_CONSTRAINT_CHECK ((DestMax
!= 0), RETURN_INVALID_PARAMETER
);
2088 // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
2090 SourceLen
= StrnLenS (Source
, DestMax
);
2091 SAFE_STRING_CONSTRAINT_CHECK ((DestMax
> SourceLen
), RETURN_BUFFER_TOO_SMALL
);
2094 // 5. Copying shall not take place between objects that overlap.
2096 SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination
, DestMax
, (VOID
*)Source
, (SourceLen
+ 1) * sizeof(CHAR16
)), RETURN_ACCESS_DENIED
);
2101 while (*Source
!= '\0') {
2103 // If any Unicode characters in Source contain
2104 // non-zero value in the upper 8 bits, then ASSERT().
2106 ASSERT (*Source
< 0x100);
2107 *(Destination
++) = (CHAR8
) *(Source
++);
2109 *Destination
= '\0';
2111 return RETURN_SUCCESS
;
2116 CHAR16
*Destination
,
2118 CONST CHAR16
*Source
2123 ASSERT (((UINTN
) Destination
& BIT0
) == 0);
2124 ASSERT (((UINTN
) Source
& BIT0
) == 0);
2127 // 1. Neither Destination nor Source shall be a null pointer.
2129 SAFE_STRING_CONSTRAINT_CHECK ((Destination
!= NULL
), RETURN_INVALID_PARAMETER
);
2130 SAFE_STRING_CONSTRAINT_CHECK ((Source
!= NULL
), RETURN_INVALID_PARAMETER
);
2133 // 2. DestMax shall not be greater than RSIZE_MAX.
2135 if (RSIZE_MAX
!= 0) {
2136 SAFE_STRING_CONSTRAINT_CHECK ((DestMax
<= RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
2140 // 3. DestMax shall not equal zero.
2142 SAFE_STRING_CONSTRAINT_CHECK ((DestMax
!= 0), RETURN_INVALID_PARAMETER
);
2145 // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
2147 SourceLen
= StrnLenS (Source
, DestMax
);
2148 SAFE_STRING_CONSTRAINT_CHECK ((DestMax
> SourceLen
), RETURN_BUFFER_TOO_SMALL
);
2151 // 5. Copying shall not take place between objects that overlap.
2153 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination
, DestMax
, (CHAR16
*)Source
, SourceLen
+ 1), RETURN_ACCESS_DENIED
);
2156 // The StrCpyS function copies the string pointed to by Source (including the terminating
2157 // null character) into the array pointed to by Destination.
2159 while (*Source
!= 0) {
2160 *(Destination
++) = *(Source
++);
2164 return RETURN_SUCCESS
;
2169 UINTN AllocationSize
2173 Memory
= malloc(AllocationSize
);
2174 ASSERT (Memory
!= NULL
);
2175 if (Memory
== NULL
) {
2176 fprintf(stderr
, "Not memory for malloc\n");
2178 memset(Memory
, 0, AllocationSize
);
2184 UINTN AllocationSize
2187 return InternalAllocatePool (AllocationSize
);
2196 ASSERT (Buffer
!= NULL
);
2198 return *Buffer
= Value
;
2203 CONST UINT16
*Buffer
2206 ASSERT (Buffer
!= NULL
);
2211 Return whether the integer string is a hex string.
2213 @param Str The integer string
2215 @retval TRUE Hex string
2216 @retval FALSE Decimal string
2225 // skip preceeding white space
2227 while ((*Str
!= 0) && *Str
== L
' ') {
2231 // skip preceeding zeros
2233 while ((*Str
!= 0) && *Str
== L
'0') {
2237 return (BOOLEAN
) (*Str
== L
'x' || *Str
== L
'X');
2242 Convert integer string to uint.
2244 @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
2246 @return A UINTN value represented by Str
2254 if (IsHexStr (Str
)) {
2255 return StrHexToUintn (Str
);
2257 return StrDecimalToUintn (Str
);
2263 Convert integer string to 64 bit data.
2265 @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
2266 @param Data A pointer to the UINT64 value represented by Str
2275 if (IsHexStr (Str
)) {
2276 *Data
= StrHexToUint64 (Str
);
2278 *Data
= StrDecimalToUint64 (Str
);
2283 Converts a Unicode string to ASCII string.
2285 @param Str The equivalent Unicode string
2286 @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points
2287 to the next ASCII string next to it
2299 while (!IS_NULL (*Str
)) {
2300 *(Dest
++) = (CHAR8
) *(Str
++);
2305 // Return the string next to it
2307 *AsciiStr
= Dest
+ 1;
2311 Gets current sub-string from a string list, before return
2312 the list header is moved to next sub-string. The sub-string is separated
2313 by the specified character. For example, the separator is ',', the string
2314 list is "2,0,3", it returns "2", the remain list move to "0,3"
2316 @param List A string list separated by the specified separator
2317 @param Separator The separator character
2319 @return A pointer to the current sub-string
2334 if (IS_NULL (*Str
)) {
2339 // Find first occurrence of the separator
2341 while (!IS_NULL (*Str
)) {
2342 if (*Str
== Separator
) {
2348 if (*Str
== Separator
) {
2350 // Find a sub-string, terminate it
2357 // Move to next sub-string