mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-03 21:17:23 +01:00 
			
		
		
		
	The change doesn't impact the functionality. Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			2363 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2363 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
Common basic Library Functions
 | 
						|
 | 
						|
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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)
 | 
						|
 | 
						|
VOID
 | 
						|
PeiZeroMem (
 | 
						|
  IN VOID   *Buffer,
 | 
						|
  IN UINTN  Size
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Set Buffer to zero for Size bytes.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Buffer  - Memory to set.
 | 
						|
 | 
						|
  Size    - Number of bytes to set
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  INT8  *Ptr;
 | 
						|
 | 
						|
  Ptr = Buffer;
 | 
						|
  while (Size--) {
 | 
						|
    *(Ptr++) = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
PeiCopyMem (
 | 
						|
  IN VOID   *Destination,
 | 
						|
  IN VOID   *Source,
 | 
						|
  IN UINTN  Length
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Copy Length bytes from Source to Destination.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Destination - Target of copy
 | 
						|
 | 
						|
  Source      - Place to copy from
 | 
						|
 | 
						|
  Length      - Number of bytes to copy
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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);
 | 
						|
}
 | 
						|
 | 
						|
INTN
 | 
						|
CompareGuid (
 | 
						|
  IN EFI_GUID     *Guid1,
 | 
						|
  IN EFI_GUID     *Guid2
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Compares to GUIDs
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Guid1 - guid to compare
 | 
						|
  Guid2 - guid to compare
 | 
						|
 | 
						|
Returns:
 | 
						|
  =  0  if Guid1 == Guid2
 | 
						|
  != 0  if Guid1 != 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GetFileImage (
 | 
						|
  IN CHAR8    *InputFileName,
 | 
						|
  OUT CHAR8   **InputFileImage,
 | 
						|
  OUT UINT32  *BytesRead
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  InputFileName     The name of the file to read.
 | 
						|
  InputFileImage    A pointer to the memory buffer.
 | 
						|
  BytesRead         The size of the memory buffer.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS              The function completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
 | 
						|
  EFI_ABORTED              An error occurred.
 | 
						|
  EFI_OUT_OF_RESOURCES     No resource to complete operations.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
PutFileImage (
 | 
						|
  IN CHAR8    *OutputFileName,
 | 
						|
  IN CHAR8    *OutputFileImage,
 | 
						|
  IN UINT32   BytesToWrite
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function opens a file and writes OutputFileImage into the file.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  OutputFileName     The name of the file to write.
 | 
						|
  OutputFileImage    A pointer to the memory buffer.
 | 
						|
  BytesToWrite       The size of the memory buffer.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS              The function completed successfully.
 | 
						|
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
 | 
						|
  EFI_ABORTED              An error occurred.
 | 
						|
  EFI_OUT_OF_RESOURCES     No resource to complete operations.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
UINT8
 | 
						|
CalculateChecksum8 (
 | 
						|
  IN UINT8        *Buffer,
 | 
						|
  IN UINTN        Size
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function calculates the value needed for a valid UINT8 checksum
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Buffer      Pointer to buffer containing byte data of component.
 | 
						|
  Size        Size of the buffer
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The 8 bit checksum value needed.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));
 | 
						|
}
 | 
						|
 | 
						|
UINT8
 | 
						|
CalculateSum8 (
 | 
						|
  IN UINT8  *Buffer,
 | 
						|
  IN UINTN  Size
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
Routine Description::
 | 
						|
 | 
						|
  This function calculates the UINT8 sum for the requested region.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Buffer      Pointer to buffer containing byte data of component.
 | 
						|
  Size        Size of the buffer
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The 8 bit checksum value needed.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
UINT16
 | 
						|
CalculateChecksum16 (
 | 
						|
  IN UINT16       *Buffer,
 | 
						|
  IN UINTN        Size
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
Routine Description::
 | 
						|
 | 
						|
  This function calculates the value needed for a valid UINT16 checksum
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Buffer      Pointer to buffer containing byte data of component.
 | 
						|
  Size        Size of the buffer
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The 16 bit checksum value needed.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));
 | 
						|
}
 | 
						|
 | 
						|
UINT16
 | 
						|
CalculateSum16 (
 | 
						|
  IN UINT16       *Buffer,
 | 
						|
  IN UINTN        Size
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function calculates the UINT16 sum for the requested region.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Buffer      Pointer to buffer containing byte data of component.
 | 
						|
  Size        Size of the buffer
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The 16 bit checksum
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
PrintGuid (
 | 
						|
  IN EFI_GUID *Guid
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function prints a GUID to STDOUT.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Guid    Pointer to a GUID to print.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             The GUID was printed.
 | 
						|
  EFI_INVALID_PARAMETER   The input was NULL.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
PrintGuidToBuffer (
 | 
						|
  IN EFI_GUID     *Guid,
 | 
						|
  IN OUT UINT8    *Buffer,
 | 
						|
  IN UINT32       BufferLen,
 | 
						|
  IN BOOLEAN      Uppercase
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function prints a GUID to a buffer
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Guid      - Pointer to a GUID to print.
 | 
						|
  Buffer    - Pointer to a user-provided buffer to print to
 | 
						|
  BufferLen - Size of the Buffer
 | 
						|
  Uppercase - If use upper case.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             The GUID was printed.
 | 
						|
  EFI_INVALID_PARAMETER   The input was NULL.
 | 
						|
  EFI_BUFFER_TOO_SMALL    The input buffer was not big enough
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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];
 | 
						|
 | 
						|
CHAR8 *
 | 
						|
LongFilePath (
 | 
						|
 IN CHAR8 *FileName
 | 
						|
 )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Convert FileName to the long file path, which can support larger than 260 length. 
 | 
						|
 | 
						|
Arguments:
 | 
						|
  FileName         - FileName. 
 | 
						|
 | 
						|
Returns:
 | 
						|
  LongFilePath      A pointer to the converted long file path.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
#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));
 | 
						|
}
 | 
						|
 | 
						|
RETURN_STATUS
 | 
						|
StrDecimalToUintnS (
 | 
						|
    CONST CHAR16             *String,
 | 
						|
         CHAR16             **EndPointer,  OPTIONAL
 | 
						|
         UINTN              *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 UINTN, then MAX_UINTN is stored in *Data and
 | 
						|
    // RETURN_UNSUPPORTED is returned.
 | 
						|
    //
 | 
						|
    if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) {
 | 
						|
      *Data = MAX_UINTN;
 | 
						|
      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 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
 | 
						|
  UINTN.
 | 
						|
 | 
						|
  This function outputs a value of type UINTN 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 UINTN, then
 | 
						|
  MAX_UINTN 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 UINTN.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
StrHexToUintnS (
 | 
						|
    CONST CHAR16             *String,
 | 
						|
         CHAR16             **EndPointer,  OPTIONAL
 | 
						|
         UINTN              *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 UINTN, then MAX_UINTN is stored in *Data and
 | 
						|
    // RETURN_UNSUPPORTED is returned.
 | 
						|
    //
 | 
						|
    if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) {
 | 
						|
      *Data = MAX_UINTN;
 | 
						|
      if (EndPointer != NULL) {
 | 
						|
        *EndPointer = (CHAR16 *) String;
 | 
						|
      }
 | 
						|
      return RETURN_UNSUPPORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    *Data = (*Data << 4) + InternalHexCharToUintn (*String);
 | 
						|
    String++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EndPointer != NULL) {
 | 
						|
    *EndPointer = (CHAR16 *) String;
 | 
						|
  }
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
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
 | 
						|
StrDecimalToUintn (
 | 
						|
  CONST CHAR16              *String
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN     Result;
 | 
						|
 | 
						|
  StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result);
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
UINTN
 | 
						|
StrHexToUintn (
 | 
						|
  CONST CHAR16              *String
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN     Result;
 | 
						|
 | 
						|
  StrHexToUintnS (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);
 | 
						|
  ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
 | 
						|
 | 
						|
  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;
 | 
						|
  UINTN                  Uintn;
 | 
						|
  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 = StrDecimalToUintnS ((CONST CHAR16 *) Pointer, &Pointer, &Uintn);
 | 
						|
    if (RETURN_ERROR (Status)) {
 | 
						|
      return RETURN_UNSUPPORTED;
 | 
						|
    }
 | 
						|
    if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
 | 
						|
      //
 | 
						|
      // It's P.
 | 
						|
      //
 | 
						|
      if (Uintn > 32) {
 | 
						|
        return RETURN_UNSUPPORTED;
 | 
						|
      }
 | 
						|
      LocalPrefixLength = (UINT8) Uintn;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // It's D.
 | 
						|
      //
 | 
						|
      if (Uintn > MAX_UINT8) {
 | 
						|
        return RETURN_UNSUPPORTED;
 | 
						|
      }
 | 
						|
      LocalAddress.Addr[AddressIndex] = (UINT8) Uintn;
 | 
						|
      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;
 | 
						|
  UINTN                  Uintn;
 | 
						|
  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 = StrHexToUintnS (Pointer, &End, &Uintn);
 | 
						|
        if (RETURN_ERROR (Status) || End - Pointer > 4) {
 | 
						|
          //
 | 
						|
          // Number of hexadecimal digit characters is no more than 4.
 | 
						|
          //
 | 
						|
          return RETURN_UNSUPPORTED;
 | 
						|
        }
 | 
						|
        Pointer = End;
 | 
						|
        //
 | 
						|
        // Uintn 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) Uintn >> 8);
 | 
						|
        LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn;
 | 
						|
        AddressIndex += 2;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Get P, then exit the loop.
 | 
						|
        //
 | 
						|
        Status = StrDecimalToUintnS (Pointer, &End, &Uintn);
 | 
						|
        if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) {
 | 
						|
          //
 | 
						|
          // Prefix length should not exceed 128.
 | 
						|
          //
 | 
						|
          return RETURN_UNSUPPORTED;
 | 
						|
        }
 | 
						|
        LocalPrefixLength = (UINT8) Uintn;
 | 
						|
        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 preceeding white space
 | 
						|
  //
 | 
						|
  while ((*Str != 0) && *Str == L' ') {
 | 
						|
    Str ++;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // skip preceeding 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 StrHexToUintn (Str);
 | 
						|
  } else {
 | 
						|
    return StrDecimalToUintn (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;
 | 
						|
}
 | 
						|
 |