summaryrefslogtreecommitdiff
path: root/BaseTools/Source/C/Common/CommonLib.c
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /BaseTools/Source/C/Common/CommonLib.c
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'BaseTools/Source/C/Common/CommonLib.c')
-rw-r--r--BaseTools/Source/C/Common/CommonLib.c4180
1 files changed, 2090 insertions, 2090 deletions
diff --git a/BaseTools/Source/C/Common/CommonLib.c b/BaseTools/Source/C/Common/CommonLib.c
index b2cde6d481..e224cd014b 100644
--- a/BaseTools/Source/C/Common/CommonLib.c
+++ b/BaseTools/Source/C/Common/CommonLib.c
@@ -1,2090 +1,2090 @@
-/** @file
-Common basic Library Functions
-
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#ifdef __GNUC__
-#include <unistd.h>
-#else
-#include <direct.h>
-#endif
-#include "CommonLib.h"
-#include "EfiUtilityMsgs.h"
-
-#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \
- do { \
- ASSERT (Expression); \
- if (!(Expression)) { \
- return Status; \
- } \
- } while (FALSE)
-
-/**
- Set Buffer to zero for Size bytes.
-
- @param Buffer Memory to set.
- @param Size Number of bytes to set
-**/
-VOID
-PeiZeroMem (
- IN VOID *Buffer,
- IN UINTN Size
- )
-{
- INT8 *Ptr;
-
- Ptr = Buffer;
- while (Size--) {
- *(Ptr++) = 0;
- }
-}
-
-/**
- Copy Length bytes from Source to Destination.
-
- @param Destination Target of copy
- @param Source Place to copy from
- @param Length Number of bytes to copy
-**/
-VOID
-PeiCopyMem (
- IN VOID *Destination,
- IN VOID *Source,
- IN UINTN Length
- )
-{
- CHAR8 *Destination8;
- CHAR8 *Source8;
-
- Destination8 = Destination;
- Source8 = Source;
- while (Length--) {
- *(Destination8++) = *(Source8++);
- }
-}
-
-VOID
-ZeroMem (
- IN VOID *Buffer,
- IN UINTN Size
- )
-{
- PeiZeroMem (Buffer, Size);
-}
-
-VOID
-CopyMem (
- IN VOID *Destination,
- IN VOID *Source,
- IN UINTN Length
- )
-{
- PeiCopyMem (Destination, Source, Length);
-}
-
-/**
- Compares to GUIDs
-
- @param Guid1 guid to compare
- @param Guid2 guid to compare
-
- @retval = 0 if Guid1 == Guid2
- @retval != 0 if Guid1 != Guid2
-**/
-INTN
-CompareGuid (
- IN EFI_GUID *Guid1,
- IN EFI_GUID *Guid2
- )
-{
- INT32 *g1;
- INT32 *g2;
- INT32 r;
-
- //
- // Compare 32 bits at a time
- //
- g1 = (INT32 *) Guid1;
- g2 = (INT32 *) Guid2;
-
- r = g1[0] - g2[0];
- r |= g1[1] - g2[1];
- r |= g1[2] - g2[2];
- r |= g1[3] - g2[3];
-
- return r;
-}
-
-/**
- This function opens a file and reads it into a memory buffer. The function
- will allocate the memory buffer and returns the size of the buffer.
-
- @param InputFileName The name of the file to read.
- @param InputFileImage A pointer to the memory buffer.
- @param BytesRead The size of the memory buffer.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER One of the input parameters was invalid.
- @retval EFI_ABORTED An error occurred.
- @retval EFI_OUT_OF_RESOURCES No resource to complete operations.
-**/
-EFI_STATUS
-GetFileImage (
- IN CHAR8 *InputFileName,
- OUT CHAR8 **InputFileImage,
- OUT UINT32 *BytesRead
- )
-{
- FILE *InputFile;
- UINT32 FileSize;
-
- //
- // Verify input parameters.
- //
- if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Open the file and copy contents into a memory buffer.
- //
- //
- // Open the file
- //
- InputFile = fopen (LongFilePath (InputFileName), "rb");
- if (InputFile == NULL) {
- Error (NULL, 0, 0001, "Error opening the input file", InputFileName);
- return EFI_ABORTED;
- }
- //
- // Go to the end so that we can determine the file size
- //
- if (fseek (InputFile, 0, SEEK_END)) {
- Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
- fclose (InputFile);
- return EFI_ABORTED;
- }
- //
- // Get the file size
- //
- FileSize = ftell (InputFile);
- if (FileSize == -1) {
- Error (NULL, 0, 0003, "Error parsing the input file", InputFileName);
- fclose (InputFile);
- return EFI_ABORTED;
- }
- //
- // Allocate a buffer
- //
- *InputFileImage = malloc (FileSize);
- if (*InputFileImage == NULL) {
- fclose (InputFile);
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Reset to the beginning of the file
- //
- if (fseek (InputFile, 0, SEEK_SET)) {
- Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
- fclose (InputFile);
- free (*InputFileImage);
- *InputFileImage = NULL;
- return EFI_ABORTED;
- }
- //
- // Read all of the file contents.
- //
- *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);
- if (*BytesRead != sizeof (UINT8) * FileSize) {
- Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
- fclose (InputFile);
- free (*InputFileImage);
- *InputFileImage = NULL;
- return EFI_ABORTED;
- }
- //
- // Close the file
- //
- fclose (InputFile);
-
- return EFI_SUCCESS;
-}
-
-/**
- This function opens a file and writes OutputFileImage into the file.
-
- @param OutputFileName The name of the file to write.
- @param OutputFileImage A pointer to the memory buffer.
- @param BytesToWrite The size of the memory buffer.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER One of the input parameters was invalid.
- @retval EFI_ABORTED An error occurred.
- @retval EFI_OUT_OF_RESOURCES No resource to complete operations.
-**/
-EFI_STATUS
-PutFileImage (
- IN CHAR8 *OutputFileName,
- IN CHAR8 *OutputFileImage,
- IN UINT32 BytesToWrite
- )
-{
- FILE *OutputFile;
- UINT32 BytesWrote;
-
- //
- // Verify input parameters.
- //
- if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Open the file and copy contents into a memory buffer.
- //
- //
- // Open the file
- //
- OutputFile = fopen (LongFilePath (OutputFileName), "wb");
- if (OutputFile == NULL) {
- Error (NULL, 0, 0001, "Error opening the output file", OutputFileName);
- return EFI_ABORTED;
- }
-
- //
- // Write all of the file contents.
- //
- BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile);
- if (BytesWrote != sizeof (UINT8) * BytesToWrite) {
- Error (NULL, 0, 0002, "Error writing the output file", OutputFileName);
- fclose (OutputFile);
- return EFI_ABORTED;
- }
- //
- // Close the file
- //
- fclose (OutputFile);
-
- return EFI_SUCCESS;
-}
-
-/**
- This function calculates the value needed for a valid UINT8 checksum
-
- @param Buffer Pointer to buffer containing byte data of component.
- @param Size Size of the buffer
-
- @return The 8 bit checksum value needed.
-**/
-UINT8
-CalculateChecksum8 (
- IN UINT8 *Buffer,
- IN UINTN Size
- )
-{
- return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));
-}
-
-/**
- This function calculates the UINT8 sum for the requested region.
-
- @param Buffer Pointer to buffer containing byte data of component.
- @param Size Size of the buffer
-
- @return The 8 bit checksum value needed.
-**/
-UINT8
-CalculateSum8 (
- IN UINT8 *Buffer,
- IN UINTN Size
- )
-{
- UINTN Index;
- UINT8 Sum;
-
- Sum = 0;
-
- //
- // Perform the byte sum for buffer
- //
- for (Index = 0; Index < Size; Index++) {
- Sum = (UINT8) (Sum + Buffer[Index]);
- }
-
- return Sum;
-}
-
-/**
- This function calculates the value needed for a valid UINT16 checksum
-
- @param Buffer Pointer to buffer containing byte data of component.
- @param Size Size of the buffer
-
- @return The 16 bit checksum value needed.
-**/
-UINT16
-CalculateChecksum16 (
- IN UINT16 *Buffer,
- IN UINTN Size
- )
-{
- return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));
-}
-
-/**
- This function calculates the UINT16 sum for the requested region.
-
- @param Buffer Pointer to buffer containing byte data of component.
- @param Size Size of the buffer
-
- @return The 16 bit checksum
-**/
-UINT16
-CalculateSum16 (
- IN UINT16 *Buffer,
- IN UINTN Size
- )
-{
- UINTN Index;
- UINT16 Sum;
-
- Sum = 0;
-
- //
- // Perform the word sum for buffer
- //
- for (Index = 0; Index < Size; Index++) {
- Sum = (UINT16) (Sum + Buffer[Index]);
- }
-
- return (UINT16) Sum;
-}
-
-/**
- This function prints a GUID to STDOUT.
-
- @param Guid Pointer to a GUID to print.
-
- @retval EFI_SUCCESS The GUID was printed.
- @retval EFI_INVALID_PARAMETER The input was NULL.
-**/
-EFI_STATUS
-PrintGuid (
- IN EFI_GUID *Guid
- )
-{
- if (Guid == NULL) {
- Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
- return EFI_INVALID_PARAMETER;
- }
-
- printf (
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
- (unsigned) Guid->Data1,
- Guid->Data2,
- Guid->Data3,
- Guid->Data4[0],
- Guid->Data4[1],
- Guid->Data4[2],
- Guid->Data4[3],
- Guid->Data4[4],
- Guid->Data4[5],
- Guid->Data4[6],
- Guid->Data4[7]
- );
- return EFI_SUCCESS;
-}
-
-/**
- This function prints a GUID to a buffer
-
- @param Guid Pointer to a GUID to print.
- @param Buffer Pointer to a user-provided buffer to print to
- @param BufferLen Size of the Buffer
- @param Uppercase If use upper case.
-
- @retval EFI_SUCCESS The GUID was printed.
- @retval EFI_INVALID_PARAMETER The input was NULL.
- @retval EFI_BUFFER_TOO_SMALL The input buffer was not big enough
-**/
-EFI_STATUS
-PrintGuidToBuffer (
- IN EFI_GUID *Guid,
- IN OUT UINT8 *Buffer,
- IN UINT32 BufferLen,
- IN BOOLEAN Uppercase
- )
-{
- if (Guid == NULL) {
- Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
- return EFI_INVALID_PARAMETER;
- }
-
- if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {
- Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size");
- return EFI_BUFFER_TOO_SMALL;
- }
-
- if (Uppercase) {
- sprintf (
- (CHAR8 *)Buffer,
- "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- (unsigned) Guid->Data1,
- Guid->Data2,
- Guid->Data3,
- Guid->Data4[0],
- Guid->Data4[1],
- Guid->Data4[2],
- Guid->Data4[3],
- Guid->Data4[4],
- Guid->Data4[5],
- Guid->Data4[6],
- Guid->Data4[7]
- );
- } else {
- sprintf (
- (CHAR8 *)Buffer,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- (unsigned) Guid->Data1,
- Guid->Data2,
- Guid->Data3,
- Guid->Data4[0],
- Guid->Data4[1],
- Guid->Data4[2],
- Guid->Data4[3],
- Guid->Data4[4],
- Guid->Data4[5],
- Guid->Data4[6],
- Guid->Data4[7]
- );
- }
-
- return EFI_SUCCESS;
-}
-
-#ifdef __GNUC__
-
-size_t _filelength(int fd)
-{
- struct stat stat_buf;
- fstat(fd, &stat_buf);
- return stat_buf.st_size;
-}
-
-#ifndef __CYGWIN__
-char *strlwr(char *s)
-{
- char *p = s;
- for(;*s;s++) {
- *s = tolower(*s);
- }
- return p;
-}
-#endif
-#endif
-
-#define WINDOWS_EXTENSION_PATH "\\\\?\\"
-#define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"
-
-//
-// Global data to store full file path. It is not required to be free.
-//
-CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH];
-
-/**
- Convert FileName to the long file path, which can support larger than 260 length.
-
- @param FileName FileName.
-
- @return LongFilePath A pointer to the converted long file path.
-**/
-CHAR8 *
-LongFilePath (
- IN CHAR8 *FileName
- )
-{
-#ifdef __GNUC__
- //
- // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here.
- // unix has no limitation on file path. Just return FileName.
- //
- return FileName;
-#else
- CHAR8 *RootPath;
- CHAR8 *PathPointer;
- CHAR8 *NextPointer;
-
- PathPointer = (CHAR8 *) FileName;
-
- if (FileName != NULL) {
- //
- // Add the extension string first to support long file path.
- //
- mCommonLibFullPath[0] = 0;
- strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH);
-
- if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') {
- //
- // network path like \\server\share to \\?\UNC\server\share
- //
- strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH);
- FileName ++;
- } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) {
- //
- // Relative file path. Convert it to absolute path.
- //
- RootPath = getcwd (NULL, 0);
- if (RootPath != NULL) {
- if (strlen (mCommonLibFullPath) + strlen (RootPath) > MAX_LONG_FILE_PATH - 1) {
- Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
- free (RootPath);
- return NULL;
- }
- strncat (mCommonLibFullPath, RootPath, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
- if (FileName[0] != '\\' && FileName[0] != '/') {
- if (strlen (mCommonLibFullPath) + 1 > MAX_LONG_FILE_PATH - 1) {
- Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
- free (RootPath);
- return NULL;
- }
- //
- // Attach directory separator
- //
- strncat (mCommonLibFullPath, "\\", MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
- }
- free (RootPath);
- }
- }
-
- //
- // Construct the full file path
- //
- if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) {
- Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName);
- return NULL;
- }
- strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
-
- //
- // Convert directory separator '/' to '\\'
- //
- PathPointer = (CHAR8 *) mCommonLibFullPath;
- do {
- if (*PathPointer == '/') {
- *PathPointer = '\\';
- }
- } while (*PathPointer ++ != '\0');
-
- //
- // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
- //
- if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {
- *(PathPointer + 2) = '\0';
- strncat (mCommonLibFullPath, PathPointer + 3, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
- }
-
- //
- // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.
- //
- while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {
- *PathPointer = '\0';
- strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
- }
-
- //
- // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
- //
- while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {
- *PathPointer = '\0';
- strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
- }
-
- //
- // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.
- //
- while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {
- NextPointer = PathPointer + 3;
- do {
- PathPointer --;
- } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');
-
- if (*PathPointer == '\\') {
- //
- // Skip one directory
- //
- *PathPointer = '\0';
- strncat (mCommonLibFullPath, NextPointer, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
- } else {
- //
- // No directory is found. Just break.
- //
- break;
- }
- }
-
- PathPointer = mCommonLibFullPath;
- }
-
- return PathPointer;
-#endif
-}
-
-CHAR16
-InternalCharToUpper (
- CHAR16 Char
- )
-{
- if (Char >= L'a' && Char <= L'z') {
- return (CHAR16) (Char - (L'a' - L'A'));
- }
-
- return Char;
-}
-
-UINTN
-StrnLenS (
- CONST CHAR16 *String,
- UINTN MaxSize
- )
-{
- UINTN Length;
-
- ASSERT (((UINTN) String & BIT0) == 0);
-
- //
- // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.
- //
- if ((String == NULL) || (MaxSize == 0)) {
- return 0;
- }
-
- Length = 0;
- while (String[Length] != 0) {
- if (Length >= MaxSize - 1) {
- return MaxSize;
- }
- Length++;
- }
- return Length;
-}
-
-
-VOID *
-InternalAllocatePool (
- UINTN AllocationSize
- )
-{
- VOID * Memory;
-
- Memory = malloc(AllocationSize);
- ASSERT(Memory != NULL);
- return Memory;
-}
-
-
-VOID *
-InternalReallocatePool (
- UINTN OldSize,
- UINTN NewSize,
- VOID *OldBuffer OPTIONAL
- )
-{
- VOID *NewBuffer;
-
- NewBuffer = AllocateZeroPool (NewSize);
- if (NewBuffer != NULL && OldBuffer != NULL) {
- memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
- free(OldBuffer);
- }
- return NewBuffer;
-}
-
-VOID *
-ReallocatePool (
- UINTN OldSize,
- UINTN NewSize,
- VOID *OldBuffer OPTIONAL
- )
-{
- return InternalReallocatePool (OldSize, NewSize, OldBuffer);
-}
-
-/**
- Returns the length of a Null-terminated Unicode string.
-
- This function returns the number of Unicode characters in the Null-terminated
- Unicode string specified by String.
-
- If String is NULL, then ASSERT().
- If String is not aligned on a 16-bit boundary, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and String contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
-
- @param String A pointer to a Null-terminated Unicode string.
-
- @return The length of String.
-
-**/
-UINTN
-StrLen (
- CONST CHAR16 *String
- )
-{
- UINTN Length;
-
- ASSERT (String != NULL);
- ASSERT (((UINTN) String & BIT0) == 0);
-
- for (Length = 0; *String != L'\0'; String++, Length++) {
- //
- // If PcdMaximumUnicodeStringLength is not zero,
- // length should not more than PcdMaximumUnicodeStringLength
- //
- }
- return Length;
-}
-
-BOOLEAN
-InternalSafeStringIsOverlap (
- IN VOID *Base1,
- IN UINTN Size1,
- IN VOID *Base2,
- IN UINTN Size2
- )
-{
- if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||
- (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {
- return TRUE;
- }
- return FALSE;
-}
-
-BOOLEAN
-InternalSafeStringNoStrOverlap (
- IN CHAR16 *Str1,
- IN UINTN Size1,
- IN CHAR16 *Str2,
- IN UINTN Size2
- )
-{
- return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));
-}
-
-/**
- Convert a Null-terminated Unicode decimal string to a value of type UINT64.
-
- This function outputs a value of type UINT64 by interpreting the contents of
- the Unicode string specified by String as a decimal number. The format of the
- input Unicode string String is:
-
- [spaces] [decimal digits].
-
- The valid decimal digit character is in the range [0-9]. The function will
- ignore the pad space, which includes spaces or tab characters, before
- [decimal digits]. The running zero in the beginning of [decimal digits] will
- be ignored. Then, the function stops at the first character that is a not a
- valid decimal character or a Null-terminator, whichever one comes first.
-
- If String is NULL, then ASSERT().
- If Data is NULL, then ASSERT().
- If String is not aligned in a 16-bit boundary, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and String contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
-
- If String has no valid decimal digits in the above format, then 0 is stored
- at the location pointed to by Data.
- If the number represented by String exceeds the range defined by UINT64, then
- MAX_UINT64 is stored at the location pointed to by Data.
-
- If EndPointer is not NULL, a pointer to the character that stopped the scan
- is stored at the location pointed to by EndPointer. If String has no valid
- decimal digits right after the optional pad spaces, the value of String is
- stored at the location pointed to by EndPointer.
-
- @param String Pointer to a Null-terminated Unicode string.
- @param EndPointer Pointer to character that stops scan.
- @param Data Pointer to the converted value.
-
- @retval RETURN_SUCCESS Value is translated from String.
- @retval RETURN_INVALID_PARAMETER If String is NULL.
- If Data is NULL.
- If PcdMaximumUnicodeStringLength is not
- zero, and String contains more than
- PcdMaximumUnicodeStringLength Unicode
- characters, not including the
- Null-terminator.
- @retval RETURN_UNSUPPORTED If the number represented by String exceeds
- the range defined by UINT64.
-
-**/
-RETURN_STATUS
-StrDecimalToUint64S (
- CONST CHAR16 *String,
- CHAR16 **EndPointer, OPTIONAL
- UINT64 *Data
- )
-{
- ASSERT (((UINTN) String & BIT0) == 0);
-
- //
- // 1. Neither String nor Data shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
-
- //
- // 2. The length of String shall not be greater than RSIZE_MAX.
- //
- if (RSIZE_MAX != 0) {
- SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
- }
-
- if (EndPointer != NULL) {
- *EndPointer = (CHAR16 *) String;
- }
-
- //
- // Ignore the pad spaces (space or tab)
- //
- while ((*String == L' ') || (*String == L'\t')) {
- String++;
- }
-
- //
- // Ignore leading Zeros after the spaces
- //
- while (*String == L'0') {
- String++;
- }
-
- *Data = 0;
-
- while (InternalIsDecimalDigitCharacter (*String)) {
- //
- // If the number represented by String overflows according to the range
- // defined by UINT64, then MAX_UINT64 is stored in *Data and
- // RETURN_UNSUPPORTED is returned.
- //
- if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {
- *Data = MAX_UINT64;
- if (EndPointer != NULL) {
- *EndPointer = (CHAR16 *) String;
- }
- return RETURN_UNSUPPORTED;
- }
-
- *Data = (*Data) * 10 + (*String - L'0');
- String++;
- }
-
- if (EndPointer != NULL) {
- *EndPointer = (CHAR16 *) String;
- }
- return RETURN_SUCCESS;
-}
-
-/**
- Convert a Null-terminated Unicode hexadecimal string to a value of type
- UINT64.
-
- This function outputs a value of type UINT64 by interpreting the contents of
- the Unicode string specified by String as a hexadecimal number. The format of
- the input Unicode string String is:
-
- [spaces][zeros][x][hexadecimal digits].
-
- The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
- The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
- If "x" appears in the input string, it must be prefixed with at least one 0.
- The function will ignore the pad space, which includes spaces or tab
- characters, before [zeros], [x] or [hexadecimal digit]. The running zero
- before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
- after [x] or the first valid hexadecimal digit. Then, the function stops at
- the first character that is a not a valid hexadecimal character or NULL,
- whichever one comes first.
-
- If String is NULL, then ASSERT().
- If Data is NULL, then ASSERT().
- If String is not aligned in a 16-bit boundary, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and String contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
-
- If String has no valid hexadecimal digits in the above format, then 0 is
- stored at the location pointed to by Data.
- If the number represented by String exceeds the range defined by UINT64, then
- MAX_UINT64 is stored at the location pointed to by Data.
-
- If EndPointer is not NULL, a pointer to the character that stopped the scan
- is stored at the location pointed to by EndPointer. If String has no valid
- hexadecimal digits right after the optional pad spaces, the value of String
- is stored at the location pointed to by EndPointer.
-
- @param String Pointer to a Null-terminated Unicode string.
- @param EndPointer Pointer to character that stops scan.
- @param Data Pointer to the converted value.
-
- @retval RETURN_SUCCESS Value is translated from String.
- @retval RETURN_INVALID_PARAMETER If String is NULL.
- If Data is NULL.
- If PcdMaximumUnicodeStringLength is not
- zero, and String contains more than
- PcdMaximumUnicodeStringLength Unicode
- characters, not including the
- Null-terminator.
- @retval RETURN_UNSUPPORTED If the number represented by String exceeds
- the range defined by UINT64.
-
-**/
-RETURN_STATUS
-StrHexToUint64S (
- CONST CHAR16 *String,
- CHAR16 **EndPointer, OPTIONAL
- UINT64 *Data
- )
-{
- ASSERT (((UINTN) String & BIT0) == 0);
-
- //
- // 1. Neither String nor Data shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
-
- //
- // 2. The length of String shall not be greater than RSIZE_MAX.
- //
- if (RSIZE_MAX != 0) {
- SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
- }
-
- if (EndPointer != NULL) {
- *EndPointer = (CHAR16 *) String;
- }
-
- //
- // Ignore the pad spaces (space or tab)
- //
- while ((*String == L' ') || (*String == L'\t')) {
- String++;
- }
-
- //
- // Ignore leading Zeros after the spaces
- //
- while (*String == L'0') {
- String++;
- }
-
- if (InternalCharToUpper (*String) == L'X') {
- if (*(String - 1) != L'0') {
- *Data = 0;
- return RETURN_SUCCESS;
- }
- //
- // Skip the 'X'
- //
- String++;
- }
-
- *Data = 0;
-
- while (InternalIsHexaDecimalDigitCharacter (*String)) {
- //
- // If the number represented by String overflows according to the range
- // defined by UINT64, then MAX_UINT64 is stored in *Data and
- // RETURN_UNSUPPORTED is returned.
- //
- if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {
- *Data = MAX_UINT64;
- if (EndPointer != NULL) {
- *EndPointer = (CHAR16 *) String;
- }
- return RETURN_UNSUPPORTED;
- }
-
- *Data = ((*Data) << 4) + InternalHexCharToUintn (*String);
- String++;
- }
-
- if (EndPointer != NULL) {
- *EndPointer = (CHAR16 *) String;
- }
- return RETURN_SUCCESS;
-}
-
-UINT64
-StrDecimalToUint64 (
- CONST CHAR16 *String
- )
-{
- UINT64 Result;
-
- StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);
- return Result;
-}
-
-
-UINT64
-StrHexToUint64 (
- CONST CHAR16 *String
- )
-{
- UINT64 Result;
-
- StrHexToUint64S (String, (CHAR16 **) NULL, &Result);
- return Result;
-}
-
-UINTN
-StrSize (
- CONST CHAR16 *String
- )
-{
- return (StrLen (String) + 1) * sizeof (*String);
-}
-
-
-UINT64
-ReadUnaligned64 (
- CONST UINT64 *Buffer
- )
-{
- ASSERT (Buffer != NULL);
-
- return *Buffer;
-}
-
-UINT64
-WriteUnaligned64 (
- UINT64 *Buffer,
- UINT64 Value
- )
-{
- ASSERT (Buffer != NULL);
-
- return *Buffer = Value;
-}
-
-
-EFI_GUID *
-CopyGuid (
- EFI_GUID *DestinationGuid,
- CONST EFI_GUID *SourceGuid
- )
-{
- WriteUnaligned64 (
- (UINT64*)DestinationGuid,
- ReadUnaligned64 ((CONST UINT64*)SourceGuid)
- );
- WriteUnaligned64 (
- (UINT64*)DestinationGuid + 1,
- ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
- );
- return DestinationGuid;
-}
-
-UINT16
-SwapBytes16 (
- UINT16 Value
- )
-{
- return (UINT16) ((Value<< 8) | (Value>> 8));
-}
-
-
-UINT32
-SwapBytes32 (
- UINT32 Value
- )
-{
- UINT32 LowerBytes;
- UINT32 HigherBytes;
-
- LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value);
- HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));
- return (LowerBytes << 16 | HigherBytes);
-}
-
-BOOLEAN
-InternalIsDecimalDigitCharacter (
- CHAR16 Char
- )
-{
- return (BOOLEAN) (Char >= L'0' && Char <= L'9');
-}
-
-VOID *
-InternalAllocateCopyPool (
- UINTN AllocationSize,
- CONST VOID *Buffer
- )
-{
- VOID *Memory;
-
- ASSERT (Buffer != NULL);
-
- Memory = malloc (AllocationSize);
- if (Memory != NULL) {
- Memory = memcpy (Memory, Buffer, AllocationSize);
- }
- return Memory;
-}
-
-BOOLEAN
-InternalIsHexaDecimalDigitCharacter (
- CHAR16 Char
- )
-{
-
- return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||
- (Char >= L'A' && Char <= L'F') ||
- (Char >= L'a' && Char <= L'f'));
-}
-
-UINTN
-InternalHexCharToUintn (
- CHAR16 Char
- )
-{
- if (InternalIsDecimalDigitCharacter (Char)) {
- return Char - L'0';
- }
-
- return (10 + InternalCharToUpper (Char) - L'A');
-}
-
-
-/**
- Convert a Null-terminated Unicode hexadecimal string to a byte array.
-
- This function outputs a byte array by interpreting the contents of
- the Unicode string specified by String in hexadecimal format. The format of
- the input Unicode string String is:
-
- [XX]*
-
- X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
- The function decodes every two hexadecimal digit characters as one byte. The
- decoding stops after Length of characters and outputs Buffer containing
- (Length / 2) bytes.
-
- If String is not aligned in a 16-bit boundary, then ASSERT().
-
- If String is NULL, then ASSERT().
-
- If Buffer is NULL, then ASSERT().
-
- If Length is not multiple of 2, then ASSERT().
-
- If PcdMaximumUnicodeStringLength is not zero and Length is greater than
- PcdMaximumUnicodeStringLength, then ASSERT().
-
- If MaxBufferSize is less than (Length / 2), then ASSERT().
-
- @param String Pointer to a Null-terminated Unicode string.
- @param Length The number of Unicode characters to decode.
- @param Buffer Pointer to the converted bytes array.
- @param MaxBufferSize The maximum size of Buffer.
-
- @retval RETURN_SUCCESS Buffer is translated from String.
- @retval RETURN_INVALID_PARAMETER If String is NULL.
- If Data is NULL.
- If Length is not multiple of 2.
- If PcdMaximumUnicodeStringLength is not zero,
- and Length is greater than
- PcdMaximumUnicodeStringLength.
- @retval RETURN_UNSUPPORTED If Length of characters from String contain
- a character that is not valid hexadecimal
- digit characters, or a Null-terminator.
- @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2).
-**/
-RETURN_STATUS
-StrHexToBytes (
- CONST CHAR16 *String,
- UINTN Length,
- UINT8 *Buffer,
- UINTN MaxBufferSize
- )
-{
- UINTN Index;
-
- ASSERT (((UINTN) String & BIT0) == 0);
-
- //
- // 1. None of String or Buffer shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);
-
- //
- // 2. Length shall not be greater than RSIZE_MAX.
- //
- if (RSIZE_MAX != 0) {
- SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
- }
-
- //
- // 3. Length shall not be odd.
- //
- SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);
-
- //
- // 4. MaxBufferSize shall equal to or greater than Length / 2.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);
-
- //
- // 5. String shall not contains invalid hexadecimal digits.
- //
- for (Index = 0; Index < Length; Index++) {
- if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {
- break;
- }
- }
- if (Index != Length) {
- return RETURN_UNSUPPORTED;
- }
-
- //
- // Convert the hex string to bytes.
- //
- for(Index = 0; Index < Length; Index++) {
-
- //
- // For even characters, write the upper nibble for each buffer byte,
- // and for even characters, the lower nibble.
- //
- if ((Index & BIT0) == 0) {
- Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4;
- } else {
- Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);
- }
- }
- return RETURN_SUCCESS;
-}
-
-/**
- Convert a Null-terminated Unicode GUID string to a value of type
- EFI_GUID.
-
- This function outputs a GUID value by interpreting the contents of
- the Unicode string specified by String. The format of the input
- Unicode string String consists of 36 characters, as follows:
-
- aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
-
- The pairs aa - pp are two characters in the range [0-9], [a-f] and
- [A-F], with each pair representing a single byte hexadecimal value.
-
- The mapping between String and the EFI_GUID structure is as follows:
- aa Data1[24:31]
- bb Data1[16:23]
- cc Data1[8:15]
- dd Data1[0:7]
- ee Data2[8:15]
- ff Data2[0:7]
- gg Data3[8:15]
- hh Data3[0:7]
- ii Data4[0:7]
- jj Data4[8:15]
- kk Data4[16:23]
- ll Data4[24:31]
- mm Data4[32:39]
- nn Data4[40:47]
- oo Data4[48:55]
- pp Data4[56:63]
-
- If String is NULL, then ASSERT().
- If Guid is NULL, then ASSERT().
- If String is not aligned in a 16-bit boundary, then ASSERT().
-
- @param String Pointer to a Null-terminated Unicode string.
- @param Guid Pointer to the converted GUID.
-
- @retval RETURN_SUCCESS Guid is translated from String.
- @retval RETURN_INVALID_PARAMETER If String is NULL.
- If Data is NULL.
- @retval RETURN_UNSUPPORTED If String is not as the above format.
-
-**/
-RETURN_STATUS
-StrToGuid (
- CONST CHAR16 *String,
- EFI_GUID *Guid
- )
-{
- RETURN_STATUS Status;
- EFI_GUID LocalGuid;
-
- ASSERT (((UINTN) String & BIT0) == 0);
-
- //
- // 1. None of String or Guid shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);
-
- //
- // Get aabbccdd in big-endian.
- //
- Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));
- if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {
- return RETURN_UNSUPPORTED;
- }
- //
- // Convert big-endian to little-endian.
- //
- LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);
- String += 2 * sizeof (LocalGuid.Data1) + 1;
-
- //
- // Get eeff in big-endian.
- //
- Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));
- if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {
- return RETURN_UNSUPPORTED;
- }
- //
- // Convert big-endian to little-endian.
- //
- LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);
- String += 2 * sizeof (LocalGuid.Data2) + 1;
-
- //
- // Get gghh in big-endian.
- //
- Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));
- if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {
- return RETURN_UNSUPPORTED;
- }
- //
- // Convert big-endian to little-endian.
- //
- LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);
- String += 2 * sizeof (LocalGuid.Data3) + 1;
-
- //
- // Get iijj.
- //
- Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);
- if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {
- return RETURN_UNSUPPORTED;
- }
- String += 2 * 2 + 1;
-
- //
- // Get kkllmmnnoopp.
- //
- Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);
- if (RETURN_ERROR (Status)) {
- return RETURN_UNSUPPORTED;
- }
-
- CopyGuid (Guid, &LocalGuid);
- return RETURN_SUCCESS;
-}
-
-/**
- Compares up to a specified length the contents of two Null-terminated Unicode strings,
- and returns the difference between the first mismatched Unicode characters.
-
- This function compares the Null-terminated Unicode string FirstString to the
- Null-terminated Unicode string SecondString. At most, Length Unicode
- characters will be compared. If Length is 0, then 0 is returned. If
- FirstString is identical to SecondString, then 0 is returned. Otherwise, the
- value returned is the first mismatched Unicode character in SecondString
- subtracted from the first mismatched Unicode character in FirstString.
-
- If Length > 0 and FirstString is NULL, then ASSERT().
- If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().
- If Length > 0 and SecondString is NULL, then ASSERT().
- If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
- PcdMaximumUnicodeStringLength, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
- then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
- then ASSERT().
-
- @param FirstString A pointer to a Null-terminated Unicode string.
- @param SecondString A pointer to a Null-terminated Unicode string.
- @param Length The maximum number of Unicode characters to compare.
-
- @retval 0 FirstString is identical to SecondString.
- @return others FirstString is not identical to SecondString.
-
-**/
-INTN
-StrnCmp (
- CONST CHAR16 *FirstString,
- CONST CHAR16 *SecondString,
- UINTN Length
- )
-{
- if (Length == 0) {
- return 0;
- }
-
- //
- // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
- // Length tests are performed inside StrLen().
- //
- ASSERT (StrSize (FirstString) != 0);
- ASSERT (StrSize (SecondString) != 0);
-
- while ((*FirstString != L'\0') &&
- (*SecondString != L'\0') &&
- (*FirstString == *SecondString) &&
- (Length > 1)) {
- FirstString++;
- SecondString++;
- Length--;
- }
-
- return *FirstString - *SecondString;
-}
-
-VOID *
-AllocateCopyPool (
- UINTN AllocationSize,
- CONST VOID *Buffer
- )
-{
- return InternalAllocateCopyPool (AllocationSize, Buffer);
-}
-
-INTN
-StrCmp (
- CONST CHAR16 *FirstString,
- CONST CHAR16 *SecondString
- )
-{
- //
- // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
- //
- ASSERT (StrSize (FirstString) != 0);
- ASSERT (StrSize (SecondString) != 0);
-
- while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
- FirstString++;
- SecondString++;
- }
- return *FirstString - *SecondString;
-}
-
-UINT64
-SwapBytes64 (
- UINT64 Value
- )
-{
- return InternalMathSwapBytes64 (Value);
-}
-
-UINT64
-InternalMathSwapBytes64 (
- UINT64 Operand
- )
-{
- UINT64 LowerBytes;
- UINT64 HigherBytes;
-
- LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand);
- HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
-
- return (LowerBytes << 32 | HigherBytes);
-}
-
-RETURN_STATUS
-StrToIpv4Address (
- CONST CHAR16 *String,
- CHAR16 **EndPointer,
- EFI_IPv4_ADDRESS *Address,
- UINT8 *PrefixLength
- )
-{
- RETURN_STATUS Status;
- UINTN AddressIndex;
- UINT64 Uint64;
- EFI_IPv4_ADDRESS LocalAddress;
- UINT8 LocalPrefixLength;
- CHAR16 *Pointer;
-
- LocalPrefixLength = MAX_UINT8;
- LocalAddress.Addr[0] = 0;
-
- ASSERT (((UINTN) String & BIT0) == 0);
-
- //
- // 1. None of String or Guid shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
-
- for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
- if (!InternalIsDecimalDigitCharacter (*Pointer)) {
- //
- // D or P contains invalid characters.
- //
- break;
- }
-
- //
- // Get D or P.
- //
- Status = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64);
- if (RETURN_ERROR (Status)) {
- return RETURN_UNSUPPORTED;
- }
- if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
- //
- // It's P.
- //
- if (Uint64 > 32) {
- return RETURN_UNSUPPORTED;
- }
- LocalPrefixLength = (UINT8) Uint64;
- } else {
- //
- // It's D.
- //
- if (Uint64 > MAX_UINT8) {
- return RETURN_UNSUPPORTED;
- }
- LocalAddress.Addr[AddressIndex] = (UINT8) Uint64;
- AddressIndex++;
- }
-
- //
- // Check the '.' or '/', depending on the AddressIndex.
- //
- if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
- if (*Pointer == L'/') {
- //
- // '/P' is in the String.
- // Skip "/" and get P in next loop.
- //
- Pointer++;
- } else {
- //
- // '/P' is not in the String.
- //
- break;
- }
- } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
- if (*Pointer == L'.') {
- //
- // D should be followed by '.'
- //
- Pointer++;
- } else {
- return RETURN_UNSUPPORTED;
- }
- }
- }
-
- if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
- return RETURN_UNSUPPORTED;
- }
-
- memcpy (Address, &LocalAddress, sizeof (*Address));
- if (PrefixLength != NULL) {
- *PrefixLength = LocalPrefixLength;
- }
- if (EndPointer != NULL) {
- *EndPointer = Pointer;
- }
-
- return RETURN_SUCCESS;
-}
-
-RETURN_STATUS
-StrToIpv6Address (
- CONST CHAR16 *String,
- CHAR16 **EndPointer,
- EFI_IPv6_ADDRESS *Address,
- UINT8 *PrefixLength
- )
-{
- RETURN_STATUS Status;
- UINTN AddressIndex;
- UINT64 Uint64;
- EFI_IPv6_ADDRESS LocalAddress;
- UINT8 LocalPrefixLength;
- CONST CHAR16 *Pointer;
- CHAR16 *End;
- UINTN CompressStart;
- BOOLEAN ExpectPrefix;
-
- LocalPrefixLength = MAX_UINT8;
- CompressStart = ARRAY_SIZE (Address->Addr);
- ExpectPrefix = FALSE;
-
- ASSERT (((UINTN) String & BIT0) == 0);
-
- //
- // 1. None of String or Guid shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
-
- for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
- if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
- if (*Pointer != L':') {
- //
- // ":" or "/" should be followed by digit characters.
- //
- return RETURN_UNSUPPORTED;
- }
-
- //
- // Meet second ":" after previous ":" or "/"
- // or meet first ":" in the beginning of String.
- //
- if (ExpectPrefix) {
- //
- // ":" shall not be after "/"
- //
- return RETURN_UNSUPPORTED;
- }
-
- if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {
- //
- // "::" can only appear once.
- // "::" can only appear when address is not full length.
- //
- return RETURN_UNSUPPORTED;
- } else {
- //
- // Remember the start of zero compressing.
- //
- CompressStart = AddressIndex;
- Pointer++;
-
- if (CompressStart == 0) {
- if (*Pointer != L':') {
- //
- // Single ":" shall not be in the beginning of String.
- //
- return RETURN_UNSUPPORTED;
- }
- Pointer++;
- }
- }
- }
-
- if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
- if (*Pointer == L'/') {
- //
- // Might be optional "/P" after "::".
- //
- if (CompressStart != AddressIndex) {
- return RETURN_UNSUPPORTED;
- }
- } else {
- break;
- }
- } else {
- if (!ExpectPrefix) {
- //
- // Get X.
- //
- Status = StrHexToUint64S (Pointer, &End, &Uint64);
- if (RETURN_ERROR (Status) || End - Pointer > 4) {
- //
- // Number of hexadecimal digit characters is no more than 4.
- //
- return RETURN_UNSUPPORTED;
- }
- Pointer = End;
- //
- // Uint64 won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.
- //
- ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));
- LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uint64 >> 8);
- LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64;
- AddressIndex += 2;
- } else {
- //
- // Get P, then exit the loop.
- //
- Status = StrDecimalToUint64S (Pointer, &End, &Uint64);
- if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) {
- //
- // Prefix length should not exceed 128.
- //
- return RETURN_UNSUPPORTED;
- }
- LocalPrefixLength = (UINT8) Uint64;
- Pointer = End;
- break;
- }
- }
-
- //
- // Skip ':' or "/"
- //
- if (*Pointer == L'/') {
- ExpectPrefix = TRUE;
- } else if (*Pointer == L':') {
- if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
- //
- // Meet additional ":" after all 8 16-bit address
- //
- break;
- }
- } else {
- //
- // Meet other character that is not "/" or ":" after all 8 16-bit address
- //
- break;
- }
- Pointer++;
- }
-
- if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||
- (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))
- ) {
- //
- // Full length of address shall not have compressing zeros.
- // Non-full length of address shall have compressing zeros.
- //
- return RETURN_UNSUPPORTED;
- }
- memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);
- if (AddressIndex > CompressStart) {
- memset (&Address->Addr[CompressStart], 0, ARRAY_SIZE (Address->Addr) - AddressIndex);
- memcpy (
- &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],
- &LocalAddress.Addr[CompressStart],
- AddressIndex - CompressStart
- );
- }
-
- if (PrefixLength != NULL) {
- *PrefixLength = LocalPrefixLength;
- }
- if (EndPointer != NULL) {
- *EndPointer = (CHAR16 *) Pointer;
- }
-
- return RETURN_SUCCESS;
-}
-
-
-RETURN_STATUS
-UnicodeStrToAsciiStrS (
- CONST CHAR16 *Source,
- CHAR8 *Destination,
- UINTN DestMax
- )
-{
- UINTN SourceLen;
-
- ASSERT (((UINTN) Source & BIT0) == 0);
-
- //
- // 1. Neither Destination nor Source shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
-
- //
- // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
- //
- if (ASCII_RSIZE_MAX != 0) {
- SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
- }
- if (RSIZE_MAX != 0) {
- SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
- }
-
- //
- // 3. DestMax shall not equal zero.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
-
- //
- // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
- //
- SourceLen = StrnLenS (Source, DestMax);
- SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
-
- //
- // 5. Copying shall not take place between objects that overlap.
- //
- SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);
-
- //
- // convert string
- //
- while (*Source != '\0') {
- //
- // If any Unicode characters in Source contain
- // non-zero value in the upper 8 bits, then ASSERT().
- //
- ASSERT (*Source < 0x100);
- *(Destination++) = (CHAR8) *(Source++);
- }
- *Destination = '\0';
-
- return RETURN_SUCCESS;
-}
-
-RETURN_STATUS
-StrCpyS (
- CHAR16 *Destination,
- UINTN DestMax,
- CONST CHAR16 *Source
- )
-{
- UINTN SourceLen;
-
- ASSERT (((UINTN) Destination & BIT0) == 0);
- ASSERT (((UINTN) Source & BIT0) == 0);
-
- //
- // 1. Neither Destination nor Source shall be a null pointer.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
- SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
-
- //
- // 2. DestMax shall not be greater than RSIZE_MAX.
- //
- if (RSIZE_MAX != 0) {
- SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
- }
-
- //
- // 3. DestMax shall not equal zero.
- //
- SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
-
- //
- // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
- //
- SourceLen = StrnLenS (Source, DestMax);
- SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
-
- //
- // 5. Copying shall not take place between objects that overlap.
- //
- SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
-
- //
- // The StrCpyS function copies the string pointed to by Source (including the terminating
- // null character) into the array pointed to by Destination.
- //
- while (*Source != 0) {
- *(Destination++) = *(Source++);
- }
- *Destination = 0;
-
- return RETURN_SUCCESS;
-}
-
-VOID *
-AllocateZeroPool (
- UINTN AllocationSize
- )
-{
- VOID * Memory;
- Memory = malloc(AllocationSize);
- ASSERT (Memory != NULL);
- if (Memory == NULL) {
- fprintf(stderr, "Not memory for malloc\n");
- }
- memset(Memory, 0, AllocationSize);
- return Memory;
-}
-
-VOID *
-AllocatePool (
- UINTN AllocationSize
- )
-{
- return InternalAllocatePool (AllocationSize);
-}
-
-UINT16
-WriteUnaligned16 (
- UINT16 *Buffer,
- UINT16 Value
- )
-{
- ASSERT (Buffer != NULL);
-
- return *Buffer = Value;
-}
-
-UINT16
-ReadUnaligned16 (
- CONST UINT16 *Buffer
- )
-{
- ASSERT (Buffer != NULL);
-
- return *Buffer;
-}
-/**
- Return whether the integer string is a hex string.
-
- @param Str The integer string
-
- @retval TRUE Hex string
- @retval FALSE Decimal string
-
-**/
-BOOLEAN
-IsHexStr (
- CHAR16 *Str
- )
-{
- //
- // skip preceding white space
- //
- while ((*Str != 0) && *Str == L' ') {
- Str ++;
- }
- //
- // skip preceding zeros
- //
- while ((*Str != 0) && *Str == L'0') {
- Str ++;
- }
-
- return (BOOLEAN) (*Str == L'x' || *Str == L'X');
-}
-
-/**
-
- Convert integer string to uint.
-
- @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
-
- @return A UINTN value represented by Str
-
-**/
-UINTN
-Strtoi (
- CHAR16 *Str
- )
-{
- if (IsHexStr (Str)) {
- return (UINTN)StrHexToUint64 (Str);
- } else {
- return (UINTN)StrDecimalToUint64 (Str);
- }
-}
-
-/**
-
- Convert integer string to 64 bit data.
-
- @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
- @param Data A pointer to the UINT64 value represented by Str
-
-**/
-VOID
-Strtoi64 (
- CHAR16 *Str,
- UINT64 *Data
- )
-{
- if (IsHexStr (Str)) {
- *Data = StrHexToUint64 (Str);
- } else {
- *Data = StrDecimalToUint64 (Str);
- }
-}
-
-/**
- Converts a Unicode string to ASCII string.
-
- @param Str The equivalent Unicode string
- @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points
- to the next ASCII string next to it
-
-**/
-VOID
-StrToAscii (
- CHAR16 *Str,
- CHAR8 **AsciiStr
- )
-{
- CHAR8 *Dest;
-
- Dest = *AsciiStr;
- while (!IS_NULL (*Str)) {
- *(Dest++) = (CHAR8) *(Str++);
- }
- *Dest = 0;
-
- //
- // Return the string next to it
- //
- *AsciiStr = Dest + 1;
-}
-
-/**
- Gets current sub-string from a string list, before return
- the list header is moved to next sub-string. The sub-string is separated
- by the specified character. For example, the separator is ',', the string
- list is "2,0,3", it returns "2", the remain list move to "0,3"
-
- @param List A string list separated by the specified separator
- @param Separator The separator character
-
- @return A pointer to the current sub-string
-
-**/
-CHAR16 *
-SplitStr (
- CHAR16 **List,
- CHAR16 Separator
- )
-{
- CHAR16 *Str;
- CHAR16 *ReturnStr;
-
- Str = *List;
- ReturnStr = Str;
-
- if (IS_NULL (*Str)) {
- return ReturnStr;
- }
-
- //
- // Find first occurrence of the separator
- //
- while (!IS_NULL (*Str)) {
- if (*Str == Separator) {
- break;
- }
- Str++;
- }
-
- if (*Str == Separator) {
- //
- // Find a sub-string, terminate it
- //
- *Str = L'\0';
- Str++;
- }
-
- //
- // Move to next sub-string
- //
- *List = Str;
- return ReturnStr;
-}
+/** @file
+Common basic Library Functions
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef __GNUC__
+#include <unistd.h>
+#else
+#include <direct.h>
+#endif
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \
+ do { \
+ ASSERT (Expression); \
+ if (!(Expression)) { \
+ return Status; \
+ } \
+ } while (FALSE)
+
+/**
+ Set Buffer to zero for Size bytes.
+
+ @param Buffer Memory to set.
+ @param Size Number of bytes to set
+**/
+VOID
+PeiZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+{
+ INT8 *Ptr;
+
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = 0;
+ }
+}
+
+/**
+ Copy Length bytes from Source to Destination.
+
+ @param Destination Target of copy
+ @param Source Place to copy from
+ @param Length Number of bytes to copy
+**/
+VOID
+PeiCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+
+ Destination8 = Destination;
+ Source8 = Source;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+}
+
+VOID
+ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+{
+ PeiZeroMem (Buffer, Size);
+}
+
+VOID
+CopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+{
+ PeiCopyMem (Destination, Source, Length);
+}
+
+/**
+ Compares to GUIDs
+
+ @param Guid1 guid to compare
+ @param Guid2 guid to compare
+
+ @retval = 0 if Guid1 == Guid2
+ @retval != 0 if Guid1 != Guid2
+**/
+INTN
+CompareGuid (
+ IN EFI_GUID *Guid1,
+ IN EFI_GUID *Guid2
+ )
+{
+ INT32 *g1;
+ INT32 *g2;
+ INT32 r;
+
+ //
+ // Compare 32 bits at a time
+ //
+ g1 = (INT32 *) Guid1;
+ g2 = (INT32 *) Guid2;
+
+ r = g1[0] - g2[0];
+ r |= g1[1] - g2[1];
+ r |= g1[2] - g2[2];
+ r |= g1[3] - g2[3];
+
+ return r;
+}
+
+/**
+ This function opens a file and reads it into a memory buffer. The function
+ will allocate the memory buffer and returns the size of the buffer.
+
+ @param InputFileName The name of the file to read.
+ @param InputFileImage A pointer to the memory buffer.
+ @param BytesRead The size of the memory buffer.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_OUT_OF_RESOURCES No resource to complete operations.
+**/
+EFI_STATUS
+GetFileImage (
+ IN CHAR8 *InputFileName,
+ OUT CHAR8 **InputFileImage,
+ OUT UINT32 *BytesRead
+ )
+{
+ FILE *InputFile;
+ UINT32 FileSize;
+
+ //
+ // Verify input parameters.
+ //
+ if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Open the file and copy contents into a memory buffer.
+ //
+ //
+ // Open the file
+ //
+ InputFile = fopen (LongFilePath (InputFileName), "rb");
+ if (InputFile == NULL) {
+ Error (NULL, 0, 0001, "Error opening the input file", InputFileName);
+ return EFI_ABORTED;
+ }
+ //
+ // Go to the end so that we can determine the file size
+ //
+ if (fseek (InputFile, 0, SEEK_END)) {
+ Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
+ fclose (InputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Get the file size
+ //
+ FileSize = ftell (InputFile);
+ if (FileSize == -1) {
+ Error (NULL, 0, 0003, "Error parsing the input file", InputFileName);
+ fclose (InputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Allocate a buffer
+ //
+ *InputFileImage = malloc (FileSize);
+ if (*InputFileImage == NULL) {
+ fclose (InputFile);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Reset to the beginning of the file
+ //
+ if (fseek (InputFile, 0, SEEK_SET)) {
+ Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
+ fclose (InputFile);
+ free (*InputFileImage);
+ *InputFileImage = NULL;
+ return EFI_ABORTED;
+ }
+ //
+ // Read all of the file contents.
+ //
+ *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);
+ if (*BytesRead != sizeof (UINT8) * FileSize) {
+ Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
+ fclose (InputFile);
+ free (*InputFileImage);
+ *InputFileImage = NULL;
+ return EFI_ABORTED;
+ }
+ //
+ // Close the file
+ //
+ fclose (InputFile);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function opens a file and writes OutputFileImage into the file.
+
+ @param OutputFileName The name of the file to write.
+ @param OutputFileImage A pointer to the memory buffer.
+ @param BytesToWrite The size of the memory buffer.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_OUT_OF_RESOURCES No resource to complete operations.
+**/
+EFI_STATUS
+PutFileImage (
+ IN CHAR8 *OutputFileName,
+ IN CHAR8 *OutputFileImage,
+ IN UINT32 BytesToWrite
+ )
+{
+ FILE *OutputFile;
+ UINT32 BytesWrote;
+
+ //
+ // Verify input parameters.
+ //
+ if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Open the file and copy contents into a memory buffer.
+ //
+ //
+ // Open the file
+ //
+ OutputFile = fopen (LongFilePath (OutputFileName), "wb");
+ if (OutputFile == NULL) {
+ Error (NULL, 0, 0001, "Error opening the output file", OutputFileName);
+ return EFI_ABORTED;
+ }
+
+ //
+ // Write all of the file contents.
+ //
+ BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile);
+ if (BytesWrote != sizeof (UINT8) * BytesToWrite) {
+ Error (NULL, 0, 0002, "Error writing the output file", OutputFileName);
+ fclose (OutputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Close the file
+ //
+ fclose (OutputFile);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function calculates the value needed for a valid UINT8 checksum
+
+ @param Buffer Pointer to buffer containing byte data of component.
+ @param Size Size of the buffer
+
+ @return The 8 bit checksum value needed.
+**/
+UINT8
+CalculateChecksum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+{
+ return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));
+}
+
+/**
+ This function calculates the UINT8 sum for the requested region.
+
+ @param Buffer Pointer to buffer containing byte data of component.
+ @param Size Size of the buffer
+
+ @return The 8 bit checksum value needed.
+**/
+UINT8
+CalculateSum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+{
+ UINTN Index;
+ UINT8 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the byte sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT8) (Sum + Buffer[Index]);
+ }
+
+ return Sum;
+}
+
+/**
+ This function calculates the value needed for a valid UINT16 checksum
+
+ @param Buffer Pointer to buffer containing byte data of component.
+ @param Size Size of the buffer
+
+ @return The 16 bit checksum value needed.
+**/
+UINT16
+CalculateChecksum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+{
+ return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));
+}
+
+/**
+ This function calculates the UINT16 sum for the requested region.
+
+ @param Buffer Pointer to buffer containing byte data of component.
+ @param Size Size of the buffer
+
+ @return The 16 bit checksum
+**/
+UINT16
+CalculateSum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+{
+ UINTN Index;
+ UINT16 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the word sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT16) (Sum + Buffer[Index]);
+ }
+
+ return (UINT16) Sum;
+}
+
+/**
+ This function prints a GUID to STDOUT.
+
+ @param Guid Pointer to a GUID to print.
+
+ @retval EFI_SUCCESS The GUID was printed.
+ @retval EFI_INVALID_PARAMETER The input was NULL.
+**/
+EFI_STATUS
+PrintGuid (
+ IN EFI_GUID *Guid
+ )
+{
+ if (Guid == NULL) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ printf (
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+ (unsigned) Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ This function prints a GUID to a buffer
+
+ @param Guid Pointer to a GUID to print.
+ @param Buffer Pointer to a user-provided buffer to print to
+ @param BufferLen Size of the Buffer
+ @param Uppercase If use upper case.
+
+ @retval EFI_SUCCESS The GUID was printed.
+ @retval EFI_INVALID_PARAMETER The input was NULL.
+ @retval EFI_BUFFER_TOO_SMALL The input buffer was not big enough
+**/
+EFI_STATUS
+PrintGuidToBuffer (
+ IN EFI_GUID *Guid,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 BufferLen,
+ IN BOOLEAN Uppercase
+ )
+{
+ if (Guid == NULL) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size");
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (Uppercase) {
+ sprintf (
+ (CHAR8 *)Buffer,
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ (unsigned) Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ } else {
+ sprintf (
+ (CHAR8 *)Buffer,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (unsigned) Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+#ifdef __GNUC__
+
+size_t _filelength(int fd)
+{
+ struct stat stat_buf;
+ fstat(fd, &stat_buf);
+ return stat_buf.st_size;
+}
+
+#ifndef __CYGWIN__
+char *strlwr(char *s)
+{
+ char *p = s;
+ for(;*s;s++) {
+ *s = tolower(*s);
+ }
+ return p;
+}
+#endif
+#endif
+
+#define WINDOWS_EXTENSION_PATH "\\\\?\\"
+#define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"
+
+//
+// Global data to store full file path. It is not required to be free.
+//
+CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH];
+
+/**
+ Convert FileName to the long file path, which can support larger than 260 length.
+
+ @param FileName FileName.
+
+ @return LongFilePath A pointer to the converted long file path.
+**/
+CHAR8 *
+LongFilePath (
+ IN CHAR8 *FileName
+ )
+{
+#ifdef __GNUC__
+ //
+ // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here.
+ // unix has no limitation on file path. Just return FileName.
+ //
+ return FileName;
+#else
+ CHAR8 *RootPath;
+ CHAR8 *PathPointer;
+ CHAR8 *NextPointer;
+
+ PathPointer = (CHAR8 *) FileName;
+
+ if (FileName != NULL) {
+ //
+ // Add the extension string first to support long file path.
+ //
+ mCommonLibFullPath[0] = 0;
+ strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH);
+
+ if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') {
+ //
+ // network path like \\server\share to \\?\UNC\server\share
+ //
+ strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH);
+ FileName ++;
+ } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) {
+ //
+ // Relative file path. Convert it to absolute path.
+ //
+ RootPath = getcwd (NULL, 0);
+ if (RootPath != NULL) {
+ if (strlen (mCommonLibFullPath) + strlen (RootPath) > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
+ free (RootPath);
+ return NULL;
+ }
+ strncat (mCommonLibFullPath, RootPath, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ if (FileName[0] != '\\' && FileName[0] != '/') {
+ if (strlen (mCommonLibFullPath) + 1 > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
+ free (RootPath);
+ return NULL;
+ }
+ //
+ // Attach directory separator
+ //
+ strncat (mCommonLibFullPath, "\\", MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+ free (RootPath);
+ }
+ }
+
+ //
+ // Construct the full file path
+ //
+ if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName);
+ return NULL;
+ }
+ strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+
+ //
+ // Convert directory separator '/' to '\\'
+ //
+ PathPointer = (CHAR8 *) mCommonLibFullPath;
+ do {
+ if (*PathPointer == '/') {
+ *PathPointer = '\\';
+ }
+ } while (*PathPointer ++ != '\0');
+
+ //
+ // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {
+ *(PathPointer + 2) = '\0';
+ strncat (mCommonLibFullPath, PathPointer + 3, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+
+ //
+ // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {
+ *PathPointer = '\0';
+ strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+
+ //
+ // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {
+ *PathPointer = '\0';
+ strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+
+ //
+ // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {
+ NextPointer = PathPointer + 3;
+ do {
+ PathPointer --;
+ } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');
+
+ if (*PathPointer == '\\') {
+ //
+ // Skip one directory
+ //
+ *PathPointer = '\0';
+ strncat (mCommonLibFullPath, NextPointer, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ } else {
+ //
+ // No directory is found. Just break.
+ //
+ break;
+ }
+ }
+
+ PathPointer = mCommonLibFullPath;
+ }
+
+ return PathPointer;
+#endif
+}
+
+CHAR16
+InternalCharToUpper (
+ CHAR16 Char
+ )
+{
+ if (Char >= L'a' && Char <= L'z') {
+ return (CHAR16) (Char - (L'a' - L'A'));
+ }
+
+ return Char;
+}
+
+UINTN
+StrnLenS (
+ CONST CHAR16 *String,
+ UINTN MaxSize
+ )
+{
+ UINTN Length;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.
+ //
+ if ((String == NULL) || (MaxSize == 0)) {
+ return 0;
+ }
+
+ Length = 0;
+ while (String[Length] != 0) {
+ if (Length >= MaxSize - 1) {
+ return MaxSize;
+ }
+ Length++;
+ }
+ return Length;
+}
+
+
+VOID *
+InternalAllocatePool (
+ UINTN AllocationSize
+ )
+{
+ VOID * Memory;
+
+ Memory = malloc(AllocationSize);
+ ASSERT(Memory != NULL);
+ return Memory;
+}
+
+
+VOID *
+InternalReallocatePool (
+ UINTN OldSize,
+ UINTN NewSize,
+ VOID *OldBuffer OPTIONAL
+ )
+{
+ VOID *NewBuffer;
+
+ NewBuffer = AllocateZeroPool (NewSize);
+ if (NewBuffer != NULL && OldBuffer != NULL) {
+ memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
+ free(OldBuffer);
+ }
+ return NewBuffer;
+}
+
+VOID *
+ReallocatePool (
+ UINTN OldSize,
+ UINTN NewSize,
+ VOID *OldBuffer OPTIONAL
+ )
+{
+ return InternalReallocatePool (OldSize, NewSize, OldBuffer);
+}
+
+/**
+ Returns the length of a Null-terminated Unicode string.
+
+ This function returns the number of Unicode characters in the Null-terminated
+ Unicode string specified by String.
+
+ If String is NULL, then ASSERT().
+ If String is not aligned on a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the
+ Null-terminator, then ASSERT().
+
+ @param String A pointer to a Null-terminated Unicode string.
+
+ @return The length of String.
+
+**/
+UINTN
+StrLen (
+ CONST CHAR16 *String
+ )
+{
+ UINTN Length;
+
+ ASSERT (String != NULL);
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ for (Length = 0; *String != L'\0'; String++, Length++) {
+ //
+ // If PcdMaximumUnicodeStringLength is not zero,
+ // length should not more than PcdMaximumUnicodeStringLength
+ //
+ }
+ return Length;
+}
+
+BOOLEAN
+InternalSafeStringIsOverlap (
+ IN VOID *Base1,
+ IN UINTN Size1,
+ IN VOID *Base2,
+ IN UINTN Size2
+ )
+{
+ if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||
+ (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+InternalSafeStringNoStrOverlap (
+ IN CHAR16 *Str1,
+ IN UINTN Size1,
+ IN CHAR16 *Str2,
+ IN UINTN Size2
+ )
+{
+ return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));
+}
+
+/**
+ Convert a Null-terminated Unicode decimal string to a value of type UINT64.
+
+ This function outputs a value of type UINT64 by interpreting the contents of
+ the Unicode string specified by String as a decimal number. The format of the
+ input Unicode string String is:
+
+ [spaces] [decimal digits].
+
+ The valid decimal digit character is in the range [0-9]. The function will
+ ignore the pad space, which includes spaces or tab characters, before
+ [decimal digits]. The running zero in the beginning of [decimal digits] will
+ be ignored. Then, the function stops at the first character that is a not a
+ valid decimal character or a Null-terminator, whichever one comes first.
+
+ If String is NULL, then ASSERT().
+ If Data is NULL, then ASSERT().
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the
+ Null-terminator, then ASSERT().
+
+ If String has no valid decimal digits in the above format, then 0 is stored
+ at the location pointed to by Data.
+ If the number represented by String exceeds the range defined by UINT64, then
+ MAX_UINT64 is stored at the location pointed to by Data.
+
+ If EndPointer is not NULL, a pointer to the character that stopped the scan
+ is stored at the location pointed to by EndPointer. If String has no valid
+ decimal digits right after the optional pad spaces, the value of String is
+ stored at the location pointed to by EndPointer.
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param EndPointer Pointer to character that stops scan.
+ @param Data Pointer to the converted value.
+
+ @retval RETURN_SUCCESS Value is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ If PcdMaximumUnicodeStringLength is not
+ zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode
+ characters, not including the
+ Null-terminator.
+ @retval RETURN_UNSUPPORTED If the number represented by String exceeds
+ the range defined by UINT64.
+
+**/
+RETURN_STATUS
+StrDecimalToUint64S (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer, OPTIONAL
+ UINT64 *Data
+ )
+{
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. Neither String nor Data shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. The length of String shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*String == L' ') || (*String == L'\t')) {
+ String++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*String == L'0') {
+ String++;
+ }
+
+ *Data = 0;
+
+ while (InternalIsDecimalDigitCharacter (*String)) {
+ //
+ // If the number represented by String overflows according to the range
+ // defined by UINT64, then MAX_UINT64 is stored in *Data and
+ // RETURN_UNSUPPORTED is returned.
+ //
+ if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {
+ *Data = MAX_UINT64;
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_UNSUPPORTED;
+ }
+
+ *Data = (*Data) * 10 + (*String - L'0');
+ String++;
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_SUCCESS;
+}
+
+/**
+ Convert a Null-terminated Unicode hexadecimal string to a value of type
+ UINT64.
+
+ This function outputs a value of type UINT64 by interpreting the contents of
+ the Unicode string specified by String as a hexadecimal number. The format of
+ the input Unicode string String is:
+
+ [spaces][zeros][x][hexadecimal digits].
+
+ The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
+ The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
+ If "x" appears in the input string, it must be prefixed with at least one 0.
+ The function will ignore the pad space, which includes spaces or tab
+ characters, before [zeros], [x] or [hexadecimal digit]. The running zero
+ before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
+ after [x] or the first valid hexadecimal digit. Then, the function stops at
+ the first character that is a not a valid hexadecimal character or NULL,
+ whichever one comes first.
+
+ If String is NULL, then ASSERT().
+ If Data is NULL, then ASSERT().
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the
+ Null-terminator, then ASSERT().
+
+ If String has no valid hexadecimal digits in the above format, then 0 is
+ stored at the location pointed to by Data.
+ If the number represented by String exceeds the range defined by UINT64, then
+ MAX_UINT64 is stored at the location pointed to by Data.
+
+ If EndPointer is not NULL, a pointer to the character that stopped the scan
+ is stored at the location pointed to by EndPointer. If String has no valid
+ hexadecimal digits right after the optional pad spaces, the value of String
+ is stored at the location pointed to by EndPointer.
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param EndPointer Pointer to character that stops scan.
+ @param Data Pointer to the converted value.
+
+ @retval RETURN_SUCCESS Value is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ If PcdMaximumUnicodeStringLength is not
+ zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode
+ characters, not including the
+ Null-terminator.
+ @retval RETURN_UNSUPPORTED If the number represented by String exceeds
+ the range defined by UINT64.
+
+**/
+RETURN_STATUS
+StrHexToUint64S (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer, OPTIONAL
+ UINT64 *Data
+ )
+{
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. Neither String nor Data shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. The length of String shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*String == L' ') || (*String == L'\t')) {
+ String++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*String == L'0') {
+ String++;
+ }
+
+ if (InternalCharToUpper (*String) == L'X') {
+ if (*(String - 1) != L'0') {
+ *Data = 0;
+ return RETURN_SUCCESS;
+ }
+ //
+ // Skip the 'X'
+ //
+ String++;
+ }
+
+ *Data = 0;
+
+ while (InternalIsHexaDecimalDigitCharacter (*String)) {
+ //
+ // If the number represented by String overflows according to the range
+ // defined by UINT64, then MAX_UINT64 is stored in *Data and
+ // RETURN_UNSUPPORTED is returned.
+ //
+ if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {
+ *Data = MAX_UINT64;
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_UNSUPPORTED;
+ }
+
+ *Data = ((*Data) << 4) + InternalHexCharToUintn (*String);
+ String++;
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_SUCCESS;
+}
+
+UINT64
+StrDecimalToUint64 (
+ CONST CHAR16 *String
+ )
+{
+ UINT64 Result;
+
+ StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);
+ return Result;
+}
+
+
+UINT64
+StrHexToUint64 (
+ CONST CHAR16 *String
+ )
+{
+ UINT64 Result;
+
+ StrHexToUint64S (String, (CHAR16 **) NULL, &Result);
+ return Result;
+}
+
+UINTN
+StrSize (
+ CONST CHAR16 *String
+ )
+{
+ return (StrLen (String) + 1) * sizeof (*String);
+}
+
+
+UINT64
+ReadUnaligned64 (
+ CONST UINT64 *Buffer
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer;
+}
+
+UINT64
+WriteUnaligned64 (
+ UINT64 *Buffer,
+ UINT64 Value
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer = Value;
+}
+
+
+EFI_GUID *
+CopyGuid (
+ EFI_GUID *DestinationGuid,
+ CONST EFI_GUID *SourceGuid
+ )
+{
+ WriteUnaligned64 (
+ (UINT64*)DestinationGuid,
+ ReadUnaligned64 ((CONST UINT64*)SourceGuid)
+ );
+ WriteUnaligned64 (
+ (UINT64*)DestinationGuid + 1,
+ ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
+ );
+ return DestinationGuid;
+}
+
+UINT16
+SwapBytes16 (
+ UINT16 Value
+ )
+{
+ return (UINT16) ((Value<< 8) | (Value>> 8));
+}
+
+
+UINT32
+SwapBytes32 (
+ UINT32 Value
+ )
+{
+ UINT32 LowerBytes;
+ UINT32 HigherBytes;
+
+ LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value);
+ HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));
+ return (LowerBytes << 16 | HigherBytes);
+}
+
+BOOLEAN
+InternalIsDecimalDigitCharacter (
+ CHAR16 Char
+ )
+{
+ return (BOOLEAN) (Char >= L'0' && Char <= L'9');
+}
+
+VOID *
+InternalAllocateCopyPool (
+ UINTN AllocationSize,
+ CONST VOID *Buffer
+ )
+{
+ VOID *Memory;
+
+ ASSERT (Buffer != NULL);
+
+ Memory = malloc (AllocationSize);
+ if (Memory != NULL) {
+ Memory = memcpy (Memory, Buffer, AllocationSize);
+ }
+ return Memory;
+}
+
+BOOLEAN
+InternalIsHexaDecimalDigitCharacter (
+ CHAR16 Char
+ )
+{
+
+ return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||
+ (Char >= L'A' && Char <= L'F') ||
+ (Char >= L'a' && Char <= L'f'));
+}
+
+UINTN
+InternalHexCharToUintn (
+ CHAR16 Char
+ )
+{
+ if (InternalIsDecimalDigitCharacter (Char)) {
+ return Char - L'0';
+ }
+
+ return (10 + InternalCharToUpper (Char) - L'A');
+}
+
+
+/**
+ Convert a Null-terminated Unicode hexadecimal string to a byte array.
+
+ This function outputs a byte array by interpreting the contents of
+ the Unicode string specified by String in hexadecimal format. The format of
+ the input Unicode string String is:
+
+ [XX]*
+
+ X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
+ The function decodes every two hexadecimal digit characters as one byte. The
+ decoding stops after Length of characters and outputs Buffer containing
+ (Length / 2) bytes.
+
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+
+ If String is NULL, then ASSERT().
+
+ If Buffer is NULL, then ASSERT().
+
+ If Length is not multiple of 2, then ASSERT().
+
+ If PcdMaximumUnicodeStringLength is not zero and Length is greater than
+ PcdMaximumUnicodeStringLength, then ASSERT().
+
+ If MaxBufferSize is less than (Length / 2), then ASSERT().
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param Length The number of Unicode characters to decode.
+ @param Buffer Pointer to the converted bytes array.
+ @param MaxBufferSize The maximum size of Buffer.
+
+ @retval RETURN_SUCCESS Buffer is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ If Length is not multiple of 2.
+ If PcdMaximumUnicodeStringLength is not zero,
+ and Length is greater than
+ PcdMaximumUnicodeStringLength.
+ @retval RETURN_UNSUPPORTED If Length of characters from String contain
+ a character that is not valid hexadecimal
+ digit characters, or a Null-terminator.
+ @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2).
+**/
+RETURN_STATUS
+StrHexToBytes (
+ CONST CHAR16 *String,
+ UINTN Length,
+ UINT8 *Buffer,
+ UINTN MaxBufferSize
+ )
+{
+ UINTN Index;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Buffer shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. Length shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ //
+ // 3. Length shall not be odd.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);
+
+ //
+ // 4. MaxBufferSize shall equal to or greater than Length / 2.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);
+
+ //
+ // 5. String shall not contains invalid hexadecimal digits.
+ //
+ for (Index = 0; Index < Length; Index++) {
+ if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {
+ break;
+ }
+ }
+ if (Index != Length) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Convert the hex string to bytes.
+ //
+ for(Index = 0; Index < Length; Index++) {
+
+ //
+ // For even characters, write the upper nibble for each buffer byte,
+ // and for even characters, the lower nibble.
+ //
+ if ((Index & BIT0) == 0) {
+ Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4;
+ } else {
+ Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);
+ }
+ }
+ return RETURN_SUCCESS;
+}
+
+/**
+ Convert a Null-terminated Unicode GUID string to a value of type
+ EFI_GUID.
+
+ This function outputs a GUID value by interpreting the contents of
+ the Unicode string specified by String. The format of the input
+ Unicode string String consists of 36 characters, as follows:
+
+ aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
+
+ The pairs aa - pp are two characters in the range [0-9], [a-f] and
+ [A-F], with each pair representing a single byte hexadecimal value.
+
+ The mapping between String and the EFI_GUID structure is as follows:
+ aa Data1[24:31]
+ bb Data1[16:23]
+ cc Data1[8:15]
+ dd Data1[0:7]
+ ee Data2[8:15]
+ ff Data2[0:7]
+ gg Data3[8:15]
+ hh Data3[0:7]
+ ii Data4[0:7]
+ jj Data4[8:15]
+ kk Data4[16:23]
+ ll Data4[24:31]
+ mm Data4[32:39]
+ nn Data4[40:47]
+ oo Data4[48:55]
+ pp Data4[56:63]
+
+ If String is NULL, then ASSERT().
+ If Guid is NULL, then ASSERT().
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param Guid Pointer to the converted GUID.
+
+ @retval RETURN_SUCCESS Guid is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ @retval RETURN_UNSUPPORTED If String is not as the above format.
+
+**/
+RETURN_STATUS
+StrToGuid (
+ CONST CHAR16 *String,
+ EFI_GUID *Guid
+ )
+{
+ RETURN_STATUS Status;
+ EFI_GUID LocalGuid;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Guid shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // Get aabbccdd in big-endian.
+ //
+ Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));
+ if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ //
+ // Convert big-endian to little-endian.
+ //
+ LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);
+ String += 2 * sizeof (LocalGuid.Data1) + 1;
+
+ //
+ // Get eeff in big-endian.
+ //
+ Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));
+ if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ //
+ // Convert big-endian to little-endian.
+ //
+ LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);
+ String += 2 * sizeof (LocalGuid.Data2) + 1;
+
+ //
+ // Get gghh in big-endian.
+ //
+ Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));
+ if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ //
+ // Convert big-endian to little-endian.
+ //
+ LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);
+ String += 2 * sizeof (LocalGuid.Data3) + 1;
+
+ //
+ // Get iijj.
+ //
+ Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);
+ if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ String += 2 * 2 + 1;
+
+ //
+ // Get kkllmmnnoopp.
+ //
+ Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);
+ if (RETURN_ERROR (Status)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ CopyGuid (Guid, &LocalGuid);
+ return RETURN_SUCCESS;
+}
+
+/**
+ Compares up to a specified length the contents of two Null-terminated Unicode strings,
+ and returns the difference between the first mismatched Unicode characters.
+
+ This function compares the Null-terminated Unicode string FirstString to the
+ Null-terminated Unicode string SecondString. At most, Length Unicode
+ characters will be compared. If Length is 0, then 0 is returned. If
+ FirstString is identical to SecondString, then 0 is returned. Otherwise, the
+ value returned is the first mismatched Unicode character in SecondString
+ subtracted from the first mismatched Unicode character in FirstString.
+
+ If Length > 0 and FirstString is NULL, then ASSERT().
+ If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().
+ If Length > 0 and SecondString is NULL, then ASSERT().
+ If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
+ PcdMaximumUnicodeStringLength, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
+ then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
+ then ASSERT().
+
+ @param FirstString A pointer to a Null-terminated Unicode string.
+ @param SecondString A pointer to a Null-terminated Unicode string.
+ @param Length The maximum number of Unicode characters to compare.
+
+ @retval 0 FirstString is identical to SecondString.
+ @return others FirstString is not identical to SecondString.
+
+**/
+INTN
+StrnCmp (
+ CONST CHAR16 *FirstString,
+ CONST CHAR16 *SecondString,
+ UINTN Length
+ )
+{
+ if (Length == 0) {
+ return 0;
+ }
+
+ //
+ // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
+ // Length tests are performed inside StrLen().
+ //
+ ASSERT (StrSize (FirstString) != 0);
+ ASSERT (StrSize (SecondString) != 0);
+
+ while ((*FirstString != L'\0') &&
+ (*SecondString != L'\0') &&
+ (*FirstString == *SecondString) &&
+ (Length > 1)) {
+ FirstString++;
+ SecondString++;
+ Length--;
+ }
+
+ return *FirstString - *SecondString;
+}
+
+VOID *
+AllocateCopyPool (
+ UINTN AllocationSize,
+ CONST VOID *Buffer
+ )
+{
+ return InternalAllocateCopyPool (AllocationSize, Buffer);
+}
+
+INTN
+StrCmp (
+ CONST CHAR16 *FirstString,
+ CONST CHAR16 *SecondString
+ )
+{
+ //
+ // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
+ //
+ ASSERT (StrSize (FirstString) != 0);
+ ASSERT (StrSize (SecondString) != 0);
+
+ while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
+ FirstString++;
+ SecondString++;
+ }
+ return *FirstString - *SecondString;
+}
+
+UINT64
+SwapBytes64 (
+ UINT64 Value
+ )
+{
+ return InternalMathSwapBytes64 (Value);
+}
+
+UINT64
+InternalMathSwapBytes64 (
+ UINT64 Operand
+ )
+{
+ UINT64 LowerBytes;
+ UINT64 HigherBytes;
+
+ LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand);
+ HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
+
+ return (LowerBytes << 32 | HigherBytes);
+}
+
+RETURN_STATUS
+StrToIpv4Address (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer,
+ EFI_IPv4_ADDRESS *Address,
+ UINT8 *PrefixLength
+ )
+{
+ RETURN_STATUS Status;
+ UINTN AddressIndex;
+ UINT64 Uint64;
+ EFI_IPv4_ADDRESS LocalAddress;
+ UINT8 LocalPrefixLength;
+ CHAR16 *Pointer;
+
+ LocalPrefixLength = MAX_UINT8;
+ LocalAddress.Addr[0] = 0;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Guid shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
+
+ for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
+ if (!InternalIsDecimalDigitCharacter (*Pointer)) {
+ //
+ // D or P contains invalid characters.
+ //
+ break;
+ }
+
+ //
+ // Get D or P.
+ //
+ Status = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64);
+ if (RETURN_ERROR (Status)) {
+ return RETURN_UNSUPPORTED;
+ }
+ if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ //
+ // It's P.
+ //
+ if (Uint64 > 32) {
+ return RETURN_UNSUPPORTED;
+ }
+ LocalPrefixLength = (UINT8) Uint64;
+ } else {
+ //
+ // It's D.
+ //
+ if (Uint64 > MAX_UINT8) {
+ return RETURN_UNSUPPORTED;
+ }
+ LocalAddress.Addr[AddressIndex] = (UINT8) Uint64;
+ AddressIndex++;
+ }
+
+ //
+ // Check the '.' or '/', depending on the AddressIndex.
+ //
+ if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ if (*Pointer == L'/') {
+ //
+ // '/P' is in the String.
+ // Skip "/" and get P in next loop.
+ //
+ Pointer++;
+ } else {
+ //
+ // '/P' is not in the String.
+ //
+ break;
+ }
+ } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
+ if (*Pointer == L'.') {
+ //
+ // D should be followed by '.'
+ //
+ Pointer++;
+ } else {
+ return RETURN_UNSUPPORTED;
+ }
+ }
+ }
+
+ if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ memcpy (Address, &LocalAddress, sizeof (*Address));
+ if (PrefixLength != NULL) {
+ *PrefixLength = LocalPrefixLength;
+ }
+ if (EndPointer != NULL) {
+ *EndPointer = Pointer;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+StrToIpv6Address (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer,
+ EFI_IPv6_ADDRESS *Address,
+ UINT8 *PrefixLength
+ )
+{
+ RETURN_STATUS Status;
+ UINTN AddressIndex;
+ UINT64 Uint64;
+ EFI_IPv6_ADDRESS LocalAddress;
+ UINT8 LocalPrefixLength;
+ CONST CHAR16 *Pointer;
+ CHAR16 *End;
+ UINTN CompressStart;
+ BOOLEAN ExpectPrefix;
+
+ LocalPrefixLength = MAX_UINT8;
+ CompressStart = ARRAY_SIZE (Address->Addr);
+ ExpectPrefix = FALSE;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Guid shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
+
+ for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
+ if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
+ if (*Pointer != L':') {
+ //
+ // ":" or "/" should be followed by digit characters.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Meet second ":" after previous ":" or "/"
+ // or meet first ":" in the beginning of String.
+ //
+ if (ExpectPrefix) {
+ //
+ // ":" shall not be after "/"
+ //
+ return RETURN_UNSUPPORTED;
+ }
+
+ if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ //
+ // "::" can only appear once.
+ // "::" can only appear when address is not full length.
+ //
+ return RETURN_UNSUPPORTED;
+ } else {
+ //
+ // Remember the start of zero compressing.
+ //
+ CompressStart = AddressIndex;
+ Pointer++;
+
+ if (CompressStart == 0) {
+ if (*Pointer != L':') {
+ //
+ // Single ":" shall not be in the beginning of String.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ Pointer++;
+ }
+ }
+ }
+
+ if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
+ if (*Pointer == L'/') {
+ //
+ // Might be optional "/P" after "::".
+ //
+ if (CompressStart != AddressIndex) {
+ return RETURN_UNSUPPORTED;
+ }
+ } else {
+ break;
+ }
+ } else {
+ if (!ExpectPrefix) {
+ //
+ // Get X.
+ //
+ Status = StrHexToUint64S (Pointer, &End, &Uint64);
+ if (RETURN_ERROR (Status) || End - Pointer > 4) {
+ //
+ // Number of hexadecimal digit characters is no more than 4.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ Pointer = End;
+ //
+ // Uint64 won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.
+ //
+ ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));
+ LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uint64 >> 8);
+ LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64;
+ AddressIndex += 2;
+ } else {
+ //
+ // Get P, then exit the loop.
+ //
+ Status = StrDecimalToUint64S (Pointer, &End, &Uint64);
+ if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) {
+ //
+ // Prefix length should not exceed 128.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ LocalPrefixLength = (UINT8) Uint64;
+ Pointer = End;
+ break;
+ }
+ }
+
+ //
+ // Skip ':' or "/"
+ //
+ if (*Pointer == L'/') {
+ ExpectPrefix = TRUE;
+ } else if (*Pointer == L':') {
+ if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ //
+ // Meet additional ":" after all 8 16-bit address
+ //
+ break;
+ }
+ } else {
+ //
+ // Meet other character that is not "/" or ":" after all 8 16-bit address
+ //
+ break;
+ }
+ Pointer++;
+ }
+
+ if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||
+ (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))
+ ) {
+ //
+ // Full length of address shall not have compressing zeros.
+ // Non-full length of address shall have compressing zeros.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);
+ if (AddressIndex > CompressStart) {
+ memset (&Address->Addr[CompressStart], 0, ARRAY_SIZE (Address->Addr) - AddressIndex);
+ memcpy (
+ &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],
+ &LocalAddress.Addr[CompressStart],
+ AddressIndex - CompressStart
+ );
+ }
+
+ if (PrefixLength != NULL) {
+ *PrefixLength = LocalPrefixLength;
+ }
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) Pointer;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+
+RETURN_STATUS
+UnicodeStrToAsciiStrS (
+ CONST CHAR16 *Source,
+ CHAR8 *Destination,
+ UINTN DestMax
+ )
+{
+ UINTN SourceLen;
+
+ ASSERT (((UINTN) Source & BIT0) == 0);
+
+ //
+ // 1. Neither Destination nor Source shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
+ //
+ if (ASCII_RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ //
+ // 3. DestMax shall not equal zero.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
+
+ //
+ // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
+ //
+ SourceLen = StrnLenS (Source, DestMax);
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
+
+ //
+ // 5. Copying shall not take place between objects that overlap.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);
+
+ //
+ // convert string
+ //
+ while (*Source != '\0') {
+ //
+ // If any Unicode characters in Source contain
+ // non-zero value in the upper 8 bits, then ASSERT().
+ //
+ ASSERT (*Source < 0x100);
+ *(Destination++) = (CHAR8) *(Source++);
+ }
+ *Destination = '\0';
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+StrCpyS (
+ CHAR16 *Destination,
+ UINTN DestMax,
+ CONST CHAR16 *Source
+ )
+{
+ UINTN SourceLen;
+
+ ASSERT (((UINTN) Destination & BIT0) == 0);
+ ASSERT (((UINTN) Source & BIT0) == 0);
+
+ //
+ // 1. Neither Destination nor Source shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. DestMax shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ //
+ // 3. DestMax shall not equal zero.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
+
+ //
+ // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
+ //
+ SourceLen = StrnLenS (Source, DestMax);
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
+
+ //
+ // 5. Copying shall not take place between objects that overlap.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
+
+ //
+ // The StrCpyS function copies the string pointed to by Source (including the terminating
+ // null character) into the array pointed to by Destination.
+ //
+ while (*Source != 0) {
+ *(Destination++) = *(Source++);
+ }
+ *Destination = 0;
+
+ return RETURN_SUCCESS;
+}
+
+VOID *
+AllocateZeroPool (
+ UINTN AllocationSize
+ )
+{
+ VOID * Memory;
+ Memory = malloc(AllocationSize);
+ ASSERT (Memory != NULL);
+ if (Memory == NULL) {
+ fprintf(stderr, "Not memory for malloc\n");
+ }
+ memset(Memory, 0, AllocationSize);
+ return Memory;
+}
+
+VOID *
+AllocatePool (
+ UINTN AllocationSize
+ )
+{
+ return InternalAllocatePool (AllocationSize);
+}
+
+UINT16
+WriteUnaligned16 (
+ UINT16 *Buffer,
+ UINT16 Value
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer = Value;
+}
+
+UINT16
+ReadUnaligned16 (
+ CONST UINT16 *Buffer
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer;
+}
+/**
+ Return whether the integer string is a hex string.
+
+ @param Str The integer string
+
+ @retval TRUE Hex string
+ @retval FALSE Decimal string
+
+**/
+BOOLEAN
+IsHexStr (
+ CHAR16 *Str
+ )
+{
+ //
+ // skip preceding white space
+ //
+ while ((*Str != 0) && *Str == L' ') {
+ Str ++;
+ }
+ //
+ // skip preceding zeros
+ //
+ while ((*Str != 0) && *Str == L'0') {
+ Str ++;
+ }
+
+ return (BOOLEAN) (*Str == L'x' || *Str == L'X');
+}
+
+/**
+
+ Convert integer string to uint.
+
+ @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
+
+ @return A UINTN value represented by Str
+
+**/
+UINTN
+Strtoi (
+ CHAR16 *Str
+ )
+{
+ if (IsHexStr (Str)) {
+ return (UINTN)StrHexToUint64 (Str);
+ } else {
+ return (UINTN)StrDecimalToUint64 (Str);
+ }
+}
+
+/**
+
+ Convert integer string to 64 bit data.
+
+ @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
+ @param Data A pointer to the UINT64 value represented by Str
+
+**/
+VOID
+Strtoi64 (
+ CHAR16 *Str,
+ UINT64 *Data
+ )
+{
+ if (IsHexStr (Str)) {
+ *Data = StrHexToUint64 (Str);
+ } else {
+ *Data = StrDecimalToUint64 (Str);
+ }
+}
+
+/**
+ Converts a Unicode string to ASCII string.
+
+ @param Str The equivalent Unicode string
+ @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points
+ to the next ASCII string next to it
+
+**/
+VOID
+StrToAscii (
+ CHAR16 *Str,
+ CHAR8 **AsciiStr
+ )
+{
+ CHAR8 *Dest;
+
+ Dest = *AsciiStr;
+ while (!IS_NULL (*Str)) {
+ *(Dest++) = (CHAR8) *(Str++);
+ }
+ *Dest = 0;
+
+ //
+ // Return the string next to it
+ //
+ *AsciiStr = Dest + 1;
+}
+
+/**
+ Gets current sub-string from a string list, before return
+ the list header is moved to next sub-string. The sub-string is separated
+ by the specified character. For example, the separator is ',', the string
+ list is "2,0,3", it returns "2", the remain list move to "0,3"
+
+ @param List A string list separated by the specified separator
+ @param Separator The separator character
+
+ @return A pointer to the current sub-string
+
+**/
+CHAR16 *
+SplitStr (
+ CHAR16 **List,
+ CHAR16 Separator
+ )
+{
+ CHAR16 *Str;
+ CHAR16 *ReturnStr;
+
+ Str = *List;
+ ReturnStr = Str;
+
+ if (IS_NULL (*Str)) {
+ return ReturnStr;
+ }
+
+ //
+ // Find first occurrence of the separator
+ //
+ while (!IS_NULL (*Str)) {
+ if (*Str == Separator) {
+ break;
+ }
+ Str++;
+ }
+
+ if (*Str == Separator) {
+ //
+ // Find a sub-string, terminate it
+ //
+ *Str = L'\0';
+ Str++;
+ }
+
+ //
+ // Move to next sub-string
+ //
+ *List = Str;
+ return ReturnStr;
+}