public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Hao Wu <hao.a.wu@intel.com>
To: edk2-devel@lists.01.org
Cc: Hao Wu <hao.a.wu@intel.com>, Jiewen Yao <jiewen.yao@intel.com>,
	Liming Gao <liming.gao@intel.com>,
	Michael Kinney <michael.d.kinney@intel.com>
Subject: [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value
Date: Wed,  4 Jan 2017 19:22:35 +0800	[thread overview]
Message-ID: <1483528957-28340-3-git-send-email-hao.a.wu@intel.com> (raw)
In-Reply-To: <1483528957-28340-1-git-send-email-hao.a.wu@intel.com>

Add the following 8 APIs:
[Ascii]StrDecimalToUintnS
[Ascii]StrDecimalToUint64S
[Ascii]StrHexToUintnS
[Ascii]StrHexToUint64S

These safe version APIs are used to enhance their counterpart (APIs
without trailing 'S' in function names).

These safe version APIs perform checks to the input string and will return
relative status to reflect the check result:
When the input string exceeds the range of UINTN/64, these APIs will
return RETURN_UNSUPPORTED and store MAX_UINTN/64 in the output data.
When no conversion can be performed for the input string, these APIs will
return RETURN_SUCCESS and store 0 in the output data.

The optional parameter 'EndPointer', if provided, will point to the
character that stopped the scan.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
---
 MdePkg/Include/Library/BaseLib.h          | 462 ++++++++++++++
 MdePkg/Library/BaseLib/BaseLibInternals.h | 166 ++++-
 MdePkg/Library/BaseLib/SafeString.c       | 975 +++++++++++++++++++++++++++++-
 3 files changed, 1598 insertions(+), 5 deletions(-)

diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h
index 72d1f0b..52011ee 100644
--- a/MdePkg/Include/Library/BaseLib.h
+++ b/MdePkg/Include/Library/BaseLib.h
@@ -390,6 +390,240 @@ StrnCatS (
   );
 
 /**
+  Convert a Null-terminated Unicode decimal 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 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 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
+  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 UINTN.
+
+**/
+RETURN_STATUS
+EFIAPI
+StrDecimalToUintnS (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       UINTN              *Data
+  );
+
+/**
+  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
+EFIAPI
+StrDecimalToUint64S (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       UINT64             *Data
+  );
+
+/**
+  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
+EFIAPI
+StrHexToUintnS (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       UINTN              *Data
+  );
+
+/**
+  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
+EFIAPI
+StrHexToUint64S (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       UINT64             *Data
+  );
+
+/**
   Returns the length of a Null-terminated Ascii string.
 
   This function is similar as strlen_s defined in C11.
@@ -582,6 +816,234 @@ AsciiStrnCatS (
   IN     UINTN        Length
   );
 
+/**
+  Convert a Null-terminated Ascii decimal string to a value of type UINTN.
+
+  This function outputs a value of type UINTN by interpreting the contents of
+  the Ascii string specified by String as a decimal number. The format of the
+  input Ascii 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 PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 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
+  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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINTN.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrDecimalToUintnS (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINTN              *Data
+  );
+
+/**
+  Convert a Null-terminated Ascii decimal string to a value of type UINT64.
+
+  This function outputs a value of type UINT64 by interpreting the contents of
+  the Ascii string specified by String as a decimal number. The format of the
+  input Ascii 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 PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINT64.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrDecimalToUint64S (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINT64             *Data
+  );
+
+/**
+  Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN.
+
+  This function outputs a value of type UINTN by interpreting the contents of
+  the Ascii string specified by String as a hexadecimal number. The format of
+  the input Ascii 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 digits]. The running zero before [x] or
+  [hexadecimal digits] 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-terminator,
+  whichever on comes first.
+
+  If String is NULL, then ASSERT().
+  If Data is NULL, then ASSERT().
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINTN.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrHexToUintnS (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINTN              *Data
+  );
+
+/**
+  Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64.
+
+  This function outputs a value of type UINT64 by interpreting the contents of
+  the Ascii string specified by String as a hexadecimal number. The format of
+  the input Ascii 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 digits]. The running zero before [x] or
+  [hexadecimal digits] 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-terminator,
+  whichever on comes first.
+
+  If String is NULL, then ASSERT().
+  If Data is NULL, then ASSERT().
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINT64.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrHexToUint64S (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINT64             *Data
+  );
+
 
 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
 
diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h b/MdePkg/Library/BaseLib/BaseLibInternals.h
index a8f712b..ea387ce 100644
--- a/MdePkg/Library/BaseLib/BaseLibInternals.h
+++ b/MdePkg/Library/BaseLib/BaseLibInternals.h
@@ -1,7 +1,7 @@
 /** @file
   Declaration of internal functions in BaseLib.
 
-  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2006 - 2017, 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
@@ -477,6 +477,170 @@ InternalLongJump (
   );
 
 
+/**
+  Check if a Unicode character is a decimal character.
+
+  This internal function checks if a Unicode character is a
+  decimal character. The valid decimal character is from
+  L'0' to L'9'.
+
+  @param  Char  The character to check against.
+
+  @retval TRUE  If the Char is a decmial character.
+  @retval FALSE If the Char is not a decmial character.
+
+**/
+BOOLEAN
+EFIAPI
+InternalIsDecimalDigitCharacter (
+  IN      CHAR16                    Char
+  );
+
+
+/**
+  Convert a Unicode character to upper case only if
+  it maps to a valid small-case ASCII character.
+
+  This internal function only deal with Unicode character
+  which maps to a valid small-case ASCII character, i.e.
+  L'a' to L'z'. For other Unicode character, the input character
+  is returned directly.
+
+  @param  Char  The character to convert.
+
+  @retval LowerCharacter   If the Char is with range L'a' to L'z'.
+  @retval Unchanged        Otherwise.
+
+**/
+CHAR16
+EFIAPI
+InternalCharToUpper (
+  IN      CHAR16                    Char
+  );
+
+
+/**
+  Convert a Unicode character to numerical value.
+
+  This internal function only deal with Unicode character
+  which maps to a valid hexadecimal ASII character, i.e.
+  L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
+  Unicode character, the value returned does not make sense.
+
+  @param  Char  The character to convert.
+
+  @return The numerical value converted.
+
+**/
+UINTN
+EFIAPI
+InternalHexCharToUintn (
+  IN      CHAR16                    Char
+  );
+
+
+/**
+  Check if a Unicode character is a hexadecimal character.
+
+  This internal function checks if a Unicode character is a
+  decimal character.  The valid hexadecimal character is
+  L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
+
+
+  @param  Char  The character to check against.
+
+  @retval TRUE  If the Char is a hexadecmial character.
+  @retval FALSE If the Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+InternalIsHexaDecimalDigitCharacter (
+  IN      CHAR16                    Char
+  );
+
+
+/**
+  Check if a ASCII character is a decimal character.
+
+  This internal function checks if a Unicode character is a
+  decimal character. The valid decimal character is from
+  '0' to '9'.
+
+  @param  Char  The character to check against.
+
+  @retval TRUE  If the Char is a decmial character.
+  @retval FALSE If the Char is not a decmial character.
+
+**/
+BOOLEAN
+EFIAPI
+InternalAsciiIsDecimalDigitCharacter (
+  IN      CHAR8                     Char
+  );
+
+
+/**
+  Converts a lowercase Ascii character to upper one.
+
+  If Chr is lowercase Ascii character, then converts it to upper one.
+
+  If Value >= 0xA0, then ASSERT().
+  If (Value & 0x0F) >= 0x0A, then ASSERT().
+
+  @param  Chr   one Ascii character
+
+  @return The uppercase value of Ascii character
+
+**/
+CHAR8
+EFIAPI
+InternalBaseLibAsciiToUpper (
+  IN      CHAR8                     Chr
+  );
+
+
+/**
+  Check if a ASCII character is a hexadecimal character.
+
+  This internal function checks if a ASCII character is a
+  decimal character.  The valid hexadecimal character is
+  L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
+
+
+  @param  Char  The character to check against.
+
+  @retval TRUE  If the Char is a hexadecmial character.
+  @retval FALSE If the Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+InternalAsciiIsHexaDecimalDigitCharacter (
+  IN      CHAR8                    Char
+  );
+
+
+/**
+  Convert a ASCII character to numerical value.
+
+  This internal function only deal with Unicode character
+  which maps to a valid hexadecimal ASII character, i.e.
+  '0' to '9', 'a' to 'f' or 'A' to 'F'. For other
+  ASCII character, the value returned does not make sense.
+
+  @param  Char  The character to convert.
+
+  @return The numerical value converted.
+
+**/
+UINTN
+EFIAPI
+InternalAsciiHexCharToUintn (
+  IN      CHAR8                    Char
+  );
+
+
 //
 // Ia32 and x64 specific functions
 //
diff --git a/MdePkg/Library/BaseLib/SafeString.c b/MdePkg/Library/BaseLib/SafeString.c
index f80db9f..5edc6ef 100644
--- a/MdePkg/Library/BaseLib/SafeString.c
+++ b/MdePkg/Library/BaseLib/SafeString.c
@@ -12,10 +12,7 @@
 
 **/
 
-#include <Base.h>
-#include <Library/DebugLib.h>
-#include <Library/PcdLib.h>
-#include <Library/BaseLib.h>
+#include "BaseLibInternals.h"
 
 #define RSIZE_MAX  (PcdGet32 (PcdMaximumUnicodeStringLength))
 
@@ -585,6 +582,498 @@ StrnCatS (
 }
 
 /**
+  Convert a Null-terminated Unicode decimal 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 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 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
+  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 UINTN.
+
+**/
+RETURN_STATUS
+EFIAPI
+StrDecimalToUintnS (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       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
+EFIAPI
+StrDecimalToUint64S (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       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 > DivU64x32 (MAX_UINT64 - (*String - L'0'), 10)) {
+      *Data = MAX_UINT64;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR16 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = MultU64x32 (*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
+EFIAPI
+StrHexToUintnS (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       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;
+}
+
+/**
+  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
+EFIAPI
+StrHexToUint64S (
+  IN  CONST CHAR16             *String,
+  OUT       CHAR16             **EndPointer,  OPTIONAL
+  OUT       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 > RShiftU64 (MAX_UINT64 - InternalHexCharToUintn (*String), 4)) {
+      *Data = MAX_UINT64;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR16 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = LShiftU64 (*Data, 4) + InternalHexCharToUintn (*String);
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR16 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
   Returns the length of a Null-terminated Ascii string.
 
   This function is similar as strlen_s defined in C11.
@@ -1041,6 +1530,484 @@ AsciiStrnCatS (
 }
 
 /**
+  Convert a Null-terminated Ascii decimal string to a value of type UINTN.
+
+  This function outputs a value of type UINTN by interpreting the contents of
+  the Ascii string specified by String as a decimal number. The format of the
+  input Ascii 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 PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 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
+  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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINTN.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrDecimalToUintnS (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINTN              *Data
+  )
+{
+  //
+  // 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 ASCII_RSIZE_MAX.
+  //
+  if (ASCII_RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == ' ') || (*String == '\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == '0') {
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalAsciiIsDecimalDigitCharacter (*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 - '0')) / 10)) {
+      *Data = MAX_UINTN;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR8 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = *Data * 10 + (*String - '0');
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
+  Convert a Null-terminated Ascii decimal string to a value of type UINT64.
+
+  This function outputs a value of type UINT64 by interpreting the contents of
+  the Ascii string specified by String as a decimal number. The format of the
+  input Ascii 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 PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINT64.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrDecimalToUint64S (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINT64             *Data
+  )
+{
+  //
+  // 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 ASCII_RSIZE_MAX.
+  //
+  if (ASCII_RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == ' ') || (*String == '\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == '0') {
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalAsciiIsDecimalDigitCharacter (*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 > DivU64x32 (MAX_UINT64 - (*String - '0'), 10)) {
+      *Data = MAX_UINT64;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR8 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = MultU64x32 (*Data, 10) + (*String - '0');
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
+  Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN.
+
+  This function outputs a value of type UINTN by interpreting the contents of
+  the Ascii string specified by String as a hexadecimal number. The format of
+  the input Ascii 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 digits]. The running zero before [x] or
+  [hexadecimal digits] 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-terminator,
+  whichever on comes first.
+
+  If String is NULL, then ASSERT().
+  If Data is NULL, then ASSERT().
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINTN.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrHexToUintnS (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINTN              *Data
+  )
+{
+  //
+  // 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 ASCII_RSIZE_MAX.
+  //
+  if (ASCII_RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == ' ') || (*String == '\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == '0') {
+    String++;
+  }
+
+  if (InternalBaseLibAsciiToUpper (*String) == 'X') {
+    if (*(String - 1) != '0') {
+      *Data = 0;
+      return RETURN_SUCCESS;
+    }
+    //
+    // Skip the 'X'
+    //
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalAsciiIsHexaDecimalDigitCharacter (*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 - InternalAsciiHexCharToUintn (*String)) >> 4)) {
+      *Data = MAX_UINTN;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR8 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = (*Data << 4) + InternalAsciiHexCharToUintn (*String);
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
+  Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64.
+
+  This function outputs a value of type UINT64 by interpreting the contents of
+  the Ascii string specified by String as a hexadecimal number. The format of
+  the input Ascii 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 digits]. The running zero before [x] or
+  [hexadecimal digits] 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-terminator,
+  whichever on comes first.
+
+  If String is NULL, then ASSERT().
+  If Data is NULL, then ASSERT().
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than
+  PcdMaximumAsciiStringLength Ascii 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 Ascii 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 PcdMaximumAsciiStringLength is not zero,
+                                   and String contains more than
+                                   PcdMaximumAsciiStringLength Ascii
+                                   characters, not including the
+                                   Null-terminator.
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds
+                                   the range defined by UINT64.
+
+**/
+RETURN_STATUS
+EFIAPI
+AsciiStrHexToUint64S (
+  IN  CONST CHAR8              *String,
+  OUT       CHAR8              **EndPointer,  OPTIONAL
+  OUT       UINT64             *Data
+  )
+{
+  //
+  // 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 ASCII_RSIZE_MAX.
+  //
+  if (ASCII_RSIZE_MAX != 0) {
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+
+  //
+  // Ignore the pad spaces (space or tab)
+  //
+  while ((*String == ' ') || (*String == '\t')) {
+    String++;
+  }
+
+  //
+  // Ignore leading Zeros after the spaces
+  //
+  while (*String == '0') {
+    String++;
+  }
+
+  if (InternalBaseLibAsciiToUpper (*String) == 'X') {
+    if (*(String - 1) != '0') {
+      *Data = 0;
+      return RETURN_SUCCESS;
+    }
+    //
+    // Skip the 'X'
+    //
+    String++;
+  }
+
+  *Data = 0;
+
+  while (InternalAsciiIsHexaDecimalDigitCharacter (*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 > RShiftU64 (MAX_UINT64 - InternalAsciiHexCharToUintn (*String), 4)) {
+      *Data = MAX_UINT64;
+      if (EndPointer != NULL) {
+        *EndPointer = (CHAR8 *) String;
+      }
+      return RETURN_UNSUPPORTED;
+    }
+
+    *Data = LShiftU64 (*Data, 4) + InternalAsciiHexCharToUintn (*String);
+    String++;
+  }
+
+  if (EndPointer != NULL) {
+    *EndPointer = (CHAR8 *) String;
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
   Convert a Null-terminated Unicode string to a Null-terminated
   ASCII string.
 
-- 
1.9.5.msysgit.0



  parent reply	other threads:[~2017-01-04 11:24 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-04 11:22 [PATCH 0/4] Add and refine sting APIs in MdePkg/BaseLib Hao Wu
2017-01-04 11:22 ` [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS Hao Wu
2017-01-05  2:02   ` Yao, Jiewen
2017-01-04 11:22 ` Hao Wu [this message]
2017-01-09  2:02   ` [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value Yao, Jiewen
2017-01-04 11:22 ` [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint functions Hao Wu
2017-01-09  2:03   ` Yao, Jiewen
2017-01-04 11:22 ` [PATCH 4/4] MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS Hao Wu
2017-01-09  2:03   ` Yao, Jiewen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1483528957-28340-3-git-send-email-hao.a.wu@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox