+\r
+/**\r
+ Prompt the user and return the resultant answer to the requestor.\r
+\r
+ This function will display the requested question on the shell prompt and then\r
+ wait for an apropriate answer to be input from the console.\r
+\r
+ if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue\r
+ or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.\r
+\r
+ if the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type\r
+ CHAR16*.\r
+\r
+ In either case *Response must be callee freed if Response was not NULL;\r
+\r
+ @param Type What type of question is asked. This is used to filter the input\r
+ to prevent invalid answers to question.\r
+ @param Prompt Pointer to string prompt to use to request input.\r
+ @param Response Pointer to Response which will be populated upon return.\r
+\r
+ @retval EFI_SUCCESS The operation was sucessful.\r
+ @retval EFI_UNSUPPORTED The operation is not supported as requested.\r
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
+ @return other The operation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPromptForResponse (\r
+ IN SHELL_PROMPT_REQUEST_TYPE Type,\r
+ IN CHAR16 *Prompt OPTIONAL,\r
+ IN OUT VOID **Response OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ UINTN EventIndex;\r
+ SHELL_PROMPT_RESPONSE *Resp;\r
+ UINTN Size;\r
+ CHAR16 *Buffer;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ Resp = NULL;\r
+ Buffer = NULL;\r
+ Size = 0;\r
+ if (Type != ShellPromptResponseTypeFreeform) {\r
+ Resp = (SHELL_PROMPT_RESPONSE*)AllocateZeroPool(sizeof(SHELL_PROMPT_RESPONSE));\r
+ if (Resp == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ }\r
+\r
+ switch(Type) {\r
+ case ShellPromptResponseTypeQuitContinue:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {\r
+ *Resp = ShellPromptResponseQuit;\r
+ } else {\r
+ *Resp = ShellPromptResponseContinue;\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeYesNoCancel:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ switch (Key.UnicodeChar) {\r
+ case L'Y':\r
+ case L'y':\r
+ *Resp = ShellPromptResponseYes;\r
+ break;\r
+ case L'N':\r
+ case L'n':\r
+ *Resp = ShellPromptResponseNo;\r
+ break;\r
+ case L'C':\r
+ case L'c':\r
+ *Resp = ShellPromptResponseCancel;\r
+ break;\r
+ }\r
+ }\r
+ break; case ShellPromptResponseTypeYesNoAllCancel:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ switch (Key.UnicodeChar) {\r
+ case L'Y':\r
+ case L'y':\r
+ *Resp = ShellPromptResponseYes;\r
+ break;\r
+ case L'N':\r
+ case L'n':\r
+ *Resp = ShellPromptResponseNo;\r
+ break;\r
+ case L'A':\r
+ case L'a':\r
+ *Resp = ShellPromptResponseAll;\r
+ break;\r
+ case L'C':\r
+ case L'c':\r
+ *Resp = ShellPromptResponseCancel;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeEnterContinue:\r
+ case ShellPromptResponseTypeAnyKeyContinue:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ if (Type == ShellPromptResponseTypeEnterContinue) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ *Resp = ShellPromptResponseContinue;\r
+ break;\r
+ }\r
+ }\r
+ if (Type == ShellPromptResponseTypeAnyKeyContinue) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ ASSERT_EFI_ERROR(Status);\r
+ *Resp = ShellPromptResponseContinue;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeYesNo:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ switch (Key.UnicodeChar) {\r
+ case L'Y':\r
+ case L'y':\r
+ *Resp = ShellPromptResponseYes;\r
+ break;\r
+ case L'N':\r
+ case L'n':\r
+ *Resp = ShellPromptResponseNo;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeFreeform:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ while(1) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ break;\r
+ }\r
+ ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL));\r
+ StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1);\r
+ }\r
+ break;\r
+ //\r
+ // This is the location to add new prompt types.\r
+ // If your new type loops remember to add ExecutionBreak support.\r
+ //\r
+ default:\r
+ ASSERT(FALSE);\r
+ }\r
+\r
+ if (Response != NULL) {\r
+ if (Resp != NULL) {\r
+ *Response = Resp;\r
+ } else if (Buffer != NULL) {\r
+ *Response = Buffer;\r
+ }\r
+ } else {\r
+ if (Resp != NULL) {\r
+ FreePool(Resp);\r
+ }\r
+ if (Buffer != NULL) {\r
+ FreePool(Buffer);\r
+ }\r
+ }\r
+\r
+ ShellPrintEx(-1, -1, L"\r\n");\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Prompt the user and return the resultant answer to the requestor.\r
+\r
+ This function is the same as ShellPromptForResponse, except that the prompt is\r
+ automatically pulled from HII.\r
+\r
+ @param Type What type of question is asked. This is used to filter the input\r
+ to prevent invalid answers to question.\r
+ @param[in] HiiFormatStringId The format string Id for getting from Hii.\r
+ @param[in] HiiFormatHandle The format string Handle for getting from Hii.\r
+ @param Response Pointer to Response which will be populated upon return.\r
+\r
+ @retval EFI_SUCCESS the operation was sucessful.\r
+ @return other the operation failed.\r
+\r
+ @sa ShellPromptForResponse\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPromptForResponseHii (\r
+ IN SHELL_PROMPT_REQUEST_TYPE Type,\r
+ IN CONST EFI_STRING_ID HiiFormatStringId,\r
+ IN CONST EFI_HANDLE HiiFormatHandle,\r
+ IN OUT VOID **Response\r
+ )\r
+{\r
+ CHAR16 *Prompt;\r
+ EFI_STATUS Status;\r
+\r
+ Prompt = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL);\r
+ Status = ShellPromptForResponse(Type, Prompt, Response);\r
+ FreePool(Prompt);\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
+\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
+ // stop at spaces if requested\r
+ //\r
+ if (StopAtSpace && *String == L' ') {\r
+ break;\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
+\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
+ShellIsHexOrDecimalNumber (\r
+ IN CONST CHAR16 *String,\r
+ IN CONST BOOLEAN ForceHex,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ if (ShellConvertStringToUint64(String, NULL, ForceHex, StopAtSpace) == EFI_NOT_FOUND) {\r
+ return (TRUE);\r
+ }\r
+ return (FALSE);\r
+}\r
+\r
+/**\r
+ Function to read a single line from a SHELL_FILE_HANDLE. The \n is not included in the returned\r
+ buffer. The returned buffer must be callee freed.\r
+\r
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be\r
+ maintained and not changed for all operations with the same file.\r
+\r
+ @param[in] Handle SHELL_FILE_HANDLE to read from.\r
+ @param[in, out] Ascii Boolean value for indicating whether the file is\r
+ Ascii (TRUE) or UCS2 (FALSE).\r
+\r
+ @return The line of text from the file.\r
+ @retval NULL There was not enough memory available.\r
+\r
+ @sa ShellFileHandleReadLine\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+ShellFileHandleReturnLine(\r
+ IN SHELL_FILE_HANDLE Handle,\r
+ IN OUT BOOLEAN *Ascii\r
+ )\r
+{\r
+ CHAR16 *RetVal;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ Size = 0;\r
+ RetVal = NULL;\r
+\r
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ RetVal = AllocateZeroPool(Size);\r
+ if (RetVal == NULL) {\r
+ return (NULL);\r
+ }\r
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
+\r
+ }\r
+ if (EFI_ERROR(Status) && (RetVal != NULL)) {\r
+ FreePool(RetVal);\r
+ RetVal = NULL;\r
+ }\r
+ return (RetVal);\r
+}\r
+\r
+/**\r
+ Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE.\r
+\r
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be\r
+ maintained and not changed for all operations with the same file.\r
+\r
+ @param[in] Handle SHELL_FILE_HANDLE to read from.\r
+ @param[in, out] Buffer The pointer to buffer to read into.\r
+ @param[in, out] Size The pointer to number of bytes in Buffer.\r
+ @param[in] Truncate If the buffer is large enough, this has no effect.\r
+ If the buffer is is too small and Truncate is TRUE,\r
+ the line will be truncated.\r
+ If the buffer is is too small and Truncate is FALSE,\r
+ then no read will occur.\r
+\r
+ @param[in, out] Ascii Boolean value for indicating whether the file is\r
+ Ascii (TRUE) or UCS2 (FALSE).\r
+\r
+ @retval EFI_SUCCESS The operation was successful. The line is stored in\r
+ Buffer.\r
+ @retval EFI_INVALID_PARAMETER Handle was NULL.\r
+ @retval EFI_INVALID_PARAMETER Size was NULL.\r
+ @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.\r
+ Size was updated to the minimum space required.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFileHandleReadLine(\r
+ IN SHELL_FILE_HANDLE Handle,\r
+ IN OUT CHAR16 *Buffer,\r
+ IN OUT UINTN *Size,\r
+ IN BOOLEAN Truncate,\r
+ IN OUT BOOLEAN *Ascii\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 CharBuffer;\r
+ UINTN CharSize;\r
+ UINTN CountSoFar;\r
+ UINT64 OriginalFilePosition;\r
+\r
+\r
+ if (Handle == NULL\r
+ ||Size == NULL\r
+ ){\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ if (Buffer == NULL) {\r
+ ASSERT(*Size == 0);\r
+ } else {\r
+ *Buffer = CHAR_NULL;\r
+ }\r
+ gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
+ if (OriginalFilePosition == 0) {\r
+ CharSize = sizeof(CHAR16);\r
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
+ ASSERT_EFI_ERROR(Status);\r
+ if (CharBuffer == gUnicodeFileTag) {\r
+ *Ascii = FALSE;\r
+ } else {\r
+ *Ascii = TRUE;\r
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+ }\r
+ }\r
+\r
+ for (CountSoFar = 0;;CountSoFar++){\r
+ CharBuffer = 0;\r
+ if (*Ascii) {\r
+ CharSize = sizeof(CHAR8);\r
+ } else {\r
+ CharSize = sizeof(CHAR16);\r
+ }\r
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
+ if ( EFI_ERROR(Status)\r
+ || CharSize == 0\r
+ || (CharBuffer == L'\n' && !(*Ascii))\r
+ || (CharBuffer == '\n' && *Ascii)\r
+ ){\r
+ break;\r
+ }\r
+ //\r
+ // if we have space save it...\r
+ //\r
+ if ((CountSoFar+1)*sizeof(CHAR16) < *Size){\r
+ ASSERT(Buffer != NULL);\r
+ ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
+ ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // if we ran out of space tell when...\r
+ //\r
+ if ((CountSoFar+1)*sizeof(CHAR16) > *Size){\r
+ *Size = (CountSoFar+1)*sizeof(CHAR16);\r
+ if (!Truncate) {\r
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+ } else {\r
+ DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));\r
+ }\r
+ return (EFI_BUFFER_TOO_SMALL);\r
+ }\r
+ while(Buffer[StrLen(Buffer)-1] == L'\r') {\r
+ Buffer[StrLen(Buffer)-1] = CHAR_NULL;\r
+ }\r
+\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function.\r
+\r
+ @param[in] CommandToGetHelpOn Pointer to a string containing the command name of help file to be printed.\r
+ @param[in] SectionToGetHelpOn Pointer to the section specifier(s).\r
+ @param[in] PrintCommandText If TRUE, prints the command followed by the help content, otherwise prints \r
+ the help content only.\r
+ @retval EFI_DEVICE_ERROR The help data format was incorrect.\r
+ @retval EFI_NOT_FOUND The help data could not be found.\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPrintHelp (\r
+ IN CONST CHAR16 *CommandToGetHelpOn,\r
+ IN CONST CHAR16 *SectionToGetHelpOn,\r
+ IN BOOLEAN PrintCommandText\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *OutText;\r
+ \r
+ OutText = NULL;\r
+ \r
+ //\r
+ // Get the string to print based\r
+ //\r
+ Status = gEfiShellProtocol->GetHelpText (CommandToGetHelpOn, SectionToGetHelpOn, &OutText);\r
+ \r
+ //\r
+ // make sure we got a valid string\r
+ //\r
+ if (EFI_ERROR(Status)){\r
+ return Status;\r
+ } \r
+ if (OutText == NULL || StrLen(OutText) == 0) {\r
+ return EFI_NOT_FOUND; \r
+ }\r
+ \r
+ //\r
+ // Chop off trailing stuff we dont need\r
+ //\r
+ while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') {\r
+ OutText[StrLen(OutText)-1] = CHAR_NULL;\r
+ }\r
+ \r
+ //\r
+ // Print this out to the console\r
+ //\r
+ if (PrintCommandText) {\r
+ ShellPrintEx(-1, -1, L"%H%-14s%N- %s\r\n", CommandToGetHelpOn, OutText);\r
+ } else {\r
+ ShellPrintEx(-1, -1, L"%N%s\r\n", OutText);\r
+ }\r
+ \r
+ SHELL_FREE_NON_NULL(OutText);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Function to delete a file by name\r
+ \r
+ @param[in] FileName Pointer to file name to delete.\r
+ \r
+ @retval EFI_SUCCESS the file was deleted sucessfully\r
+ @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
+ deleted\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_NOT_FOUND The specified file could not be found on the\r
+ device or the file system could not be found\r
+ on the device.\r
+ @retval EFI_NO_MEDIA The device has no medium.\r
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
+ medium is no longer supported.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+ file.\r
+ @retval other The file failed to open\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellDeleteFileByName(\r
+ IN CONST CHAR16 *FileName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SHELL_FILE_HANDLE FileHandle;\r
+ \r
+ Status = ShellFileExists(FileName);\r
+ \r
+ if (Status == EFI_SUCCESS){\r
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0x0);\r
+ if (Status == EFI_SUCCESS){\r
+ Status = ShellDeleteFile(&FileHandle);\r
+ }\r
+ } \r
+\r
+ return(Status);\r
+ \r
+}\r