+/**\r
+ Function to determin if an entire string is a valid number.\r
+\r
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
+\r
+ @param[in] String The string to evaluate.\r
+ @param[in] ForceHex TRUE - always assume hex.\r
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.\r
+\r
+ @retval TRUE It is all numeric (dec/hex) characters.\r
+ @retval FALSE There is a non-numeric character.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalShellIsHexOrDecimalNumber (\r
+ IN CONST CHAR16 *String,\r
+ IN CONST BOOLEAN ForceHex,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ BOOLEAN Hex;\r
+\r
+ //\r
+ // chop off a single negative sign\r
+ //\r
+ if (String != NULL && *String == L'-') {\r
+ String++;\r
+ }\r
+ \r
+ if (String == NULL) {\r
+ return (FALSE);\r
+ }\r
+\r
+ //\r
+ // chop leading zeroes\r
+ //\r
+ while(String != NULL && *String == L'0'){\r
+ String++;\r
+ }\r
+ //\r
+ // allow '0x' or '0X', but not 'x' or 'X'\r
+ //\r
+ if (String != NULL && (*String == L'x' || *String == L'X')) {\r
+ if (*(String-1) != L'0') {\r
+ //\r
+ // we got an x without a preceeding 0\r
+ //\r
+ return (FALSE);\r
+ }\r
+ String++;\r
+ Hex = TRUE;\r
+ } else if (ForceHex) {\r
+ Hex = TRUE;\r
+ } else {\r
+ Hex = FALSE;\r
+ }\r
+\r
+ //\r
+ // loop through the remaining characters and use the lib function\r
+ //\r
+ for ( ; String != NULL && *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){\r
+ if (Hex) {\r
+ if (!ShellIsHexaDecimalDigitCharacter(*String)) {\r
+ return (FALSE);\r
+ }\r
+ } else {\r
+ if (!ShellIsDecimalDigitCharacter(*String)) {\r
+ return (FALSE);\r
+ }\r
+ }\r
+ }\r
+\r
+ return (TRUE);\r
+}\r
+\r
+/**\r
+ Function to determine if a given filename exists.\r
+\r
+ @param[in] Name Path to test.\r
+\r
+ @retval EFI_SUCCESS The Path represents a file.\r
+ @retval EFI_NOT_FOUND The Path does not represent a file.\r
+ @retval other The path failed to open.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFileExists(\r
+ IN CONST CHAR16 *Name\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SHELL_FILE_INFO *List;\r
+\r
+ ASSERT(Name != NULL);\r
+\r
+ List = NULL;\r
+ Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List);\r
+ if (EFI_ERROR(Status)) {\r
+ return (Status);\r
+ }\r
+\r
+ ShellCloseFileMetaArg(&List);\r
+\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Convert a Unicode character to upper case only if \r
+ it maps to a valid small-case ASCII character.\r
+\r
+ This internal function only deal with Unicode character\r
+ which maps to a valid small-case ASCII character, i.e.\r
+ L'a' to L'z'. For other Unicode character, the input character\r
+ is returned directly.\r
+\r
+ @param Char The character to convert.\r
+\r
+ @retval LowerCharacter If the Char is with range L'a' to L'z'.\r
+ @retval Unchanged Otherwise.\r
+\r
+**/\r
+CHAR16\r
+EFIAPI\r
+InternalShellCharToUpper (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ if (Char >= L'a' && Char <= L'z') {\r
+ return (CHAR16) (Char - (L'a' - L'A'));\r
+ }\r
+\r
+ return Char;\r
+}\r
+\r
+/**\r
+ Convert a Unicode character to numerical value.\r
+\r
+ This internal function only deal with Unicode character\r
+ which maps to a valid hexadecimal ASII character, i.e.\r
+ L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other \r
+ Unicode character, the value returned does not make sense.\r
+\r
+ @param Char The character to convert.\r
+\r
+ @return The numerical value converted.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+InternalShellHexCharToUintn (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ if (ShellIsDecimalDigitCharacter (Char)) {\r
+ return Char - L'0';\r
+ }\r
+\r
+ return (UINTN) (10 + InternalShellCharToUpper (Char) - L'A');\r
+}\r
+\r
+/**\r
+ Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
+\r
+ This function returns a value of type UINTN by interpreting the contents\r
+ of the Unicode string specified by String as a hexadecimal number.\r
+ The format of the input Unicode string String is:\r
+\r
+ [spaces][zeros][x][hexadecimal digits].\r
+\r
+ The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+ The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
+ If "x" appears in the input string, it must be prefixed with at least one 0.\r
+ The function will ignore the pad space, which includes spaces or tab characters,\r
+ before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
+ [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
+ first valid hexadecimal digit. Then, the function stops at the first character that is\r
+ a not a valid hexadecimal character or NULL, whichever one comes first.\r
+\r
+ If String has only pad spaces, then zero is returned.\r
+ If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
+ then zero is returned.\r
+\r
+ @param[in] String A pointer to a Null-terminated Unicode string.\r
+ @param[out] Value Upon a successful return the value of the conversion.\r
+ @param[in] StopAtSpace FALSE to skip spaces.\r
+\r
+ @retval EFI_SUCCESS The conversion was successful.\r
+ @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.\r
+ @retval EFI_DEVICE_ERROR An overflow occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalShellStrHexToUint64 (\r
+ IN CONST CHAR16 *String,\r
+ OUT UINT64 *Value,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ UINT64 Result;\r
+\r
+ if (String == NULL || StrSize(String) == 0 || Value == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ \r
+ //\r
+ // Ignore the pad spaces (space or tab) \r
+ //\r
+ while ((*String == L' ') || (*String == L'\t')) {\r
+ String++;\r
+ }\r
+\r
+ //\r
+ // Ignore leading Zeros after the spaces\r
+ //\r
+ while (*String == L'0') {\r
+ String++;\r
+ }\r
+\r
+ if (InternalShellCharToUpper (*String) == L'X') {\r
+ if (*(String - 1) != L'0') {\r
+ return 0;\r
+ }\r
+ //\r
+ // Skip the 'X'\r
+ //\r
+ String++;\r
+ }\r
+\r
+ Result = 0;\r
+ \r
+ //\r
+ // Skip spaces if requested\r
+ //\r
+ while (StopAtSpace && *String == L' ') {\r
+ String++;\r
+ }\r
+ \r
+ while (ShellIsHexaDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the Hex Number represented by String overflows according \r
+ // to the range defined by UINTN, then ASSERT().\r
+ //\r
+ if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) {\r
+// if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) {\r
+ return (EFI_DEVICE_ERROR);\r
+ }\r
+\r
+ Result = (LShiftU64(Result, 4));\r
+ Result += InternalShellHexCharToUintn (*String);\r
+ String++;\r
+\r
+ //\r
+ // Skip spaces if requested\r
+ //\r
+ while (StopAtSpace && *String == L' ') {\r
+ String++;\r
+ }\r
+ }\r
+\r
+ *Value = Result;\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Convert a Null-terminated Unicode decimal string to a value of\r
+ type UINT64.\r
+\r
+ This function returns a value of type UINT64 by interpreting the contents\r
+ of the Unicode string specified by String as a decimal number. The format\r
+ of the input Unicode string String is:\r
+\r
+ [spaces] [decimal digits].\r
+\r
+ The valid decimal digit character is in the range [0-9]. The\r
+ function will ignore the pad space, which includes spaces or\r
+ tab characters, before [decimal digits]. The running zero in the\r
+ beginning of [decimal digits] will be ignored. Then, the function\r
+ stops at the first character that is a not a valid decimal character\r
+ or a Null-terminator, whichever one comes first.\r
+\r
+ If String has only pad spaces, then 0 is returned.\r
+ If String has no pad spaces or valid decimal digits,\r
+ then 0 is returned.\r
+\r
+ @param[in] String A pointer to a Null-terminated Unicode string.\r
+ @param[out] Value Upon a successful return the value of the conversion.\r
+ @param[in] StopAtSpace FALSE to skip spaces.\r
+\r
+ @retval EFI_SUCCESS The conversion was successful.\r
+ @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.\r
+ @retval EFI_DEVICE_ERROR An overflow occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalShellStrDecimalToUint64 (\r
+ IN CONST CHAR16 *String,\r
+ OUT UINT64 *Value,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ UINT64 Result;\r
+\r
+ if (String == NULL || StrSize (String) == 0 || Value == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ //\r
+ // Ignore the pad spaces (space or tab)\r
+ //\r
+ while ((*String == L' ') || (*String == L'\t')) {\r
+ String++;\r
+ }\r
+\r
+ //\r
+ // Ignore leading Zeros after the spaces\r
+ //\r
+ while (*String == L'0') {\r
+ String++;\r
+ }\r
+\r
+ Result = 0;\r
+\r
+ //\r
+ // Skip spaces if requested\r
+ //\r
+ while (StopAtSpace && *String == L' ') {\r
+ String++;\r
+ }\r
+ while (ShellIsDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the number represented by String overflows according \r
+ // to the range defined by UINT64, then ASSERT().\r
+ //\r
+ \r
+ if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) {\r
+ return (EFI_DEVICE_ERROR);\r
+ }\r
+\r
+ Result = MultU64x32(Result, 10) + (*String - L'0');\r
+ String++;\r
+\r
+ //\r
+ // Stop at spaces if requested\r
+ //\r
+ if (StopAtSpace && *String == L' ') {\r
+ break;\r
+ }\r
+ }\r
+\r
+ *Value = Result;\r
+ \r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Function to verify and convert a string to its numerical value.\r
+\r
+ If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE.\r
+\r
+ @param[in] String The string to evaluate.\r
+ @param[out] Value Upon a successful return the value of the conversion.\r
+ @param[in] ForceHex TRUE - always assume hex.\r
+ @param[in] StopAtSpace FALSE to skip spaces.\r
+ \r
+ @retval EFI_SUCCESS The conversion was successful.\r
+ @retval EFI_INVALID_PARAMETER String contained an invalid character.\r
+ @retval EFI_NOT_FOUND String was a number, but Value was NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellConvertStringToUint64(\r
+ IN CONST CHAR16 *String,\r
+ OUT UINT64 *Value,\r
+ IN CONST BOOLEAN ForceHex,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ UINT64 RetVal;\r
+ CONST CHAR16 *Walker;\r
+ EFI_STATUS Status;\r
+ BOOLEAN Hex;\r
+\r
+ Hex = ForceHex;\r
+\r
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace)) {\r
+ if (!Hex) {\r
+ Hex = TRUE;\r
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace)) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ } else {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Chop off leading spaces\r
+ //\r
+ for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);\r
+\r
+ //\r
+ // make sure we have something left that is numeric.\r
+ //\r
+ if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace)) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ } \r
+\r
+ //\r
+ // do the conversion.\r
+ //\r
+ if (Hex || StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){\r
+ Status = InternalShellStrHexToUint64(Walker, &RetVal, StopAtSpace);\r
+ } else {\r
+ Status = InternalShellStrDecimalToUint64(Walker, &RetVal, StopAtSpace);\r
+ }\r
+\r
+ if (Value == NULL && !EFI_ERROR(Status)) {\r
+ return (EFI_NOT_FOUND);\r
+ }\r
+\r
+ if (Value != NULL) {\r
+ *Value = RetVal;\r
+ }\r
+\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Function to determin if an entire string is a valid number.\r
+\r
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
+\r
+ @param[in] String The string to evaluate.\r
+ @param[in] ForceHex TRUE - always assume hex.\r
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.\r