+/**\r
+ Function to determine if a given filename represents a file.\r
+\r
+ @param[in] Name Path to file 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
+ShellIsFile(\r
+ IN CONST CHAR16 *Name\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FILE_HANDLE Handle;\r
+\r
+ ASSERT(Name != NULL);\r
+\r
+ Handle = NULL;\r
+\r
+ Status = ShellOpenFileByName(Name, &Handle, EFI_FILE_MODE_READ, 0);\r
+ if (EFI_ERROR(Status)) {\r
+ return (Status);\r
+ }\r
+\r
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
+ ShellCloseFile(&Handle);\r
+ return (EFI_SUCCESS);\r
+ }\r
+ ShellCloseFile(&Handle);\r
+ return (EFI_NOT_FOUND);\r
+}\r
+\r
+/**\r
+ Function to determine if a given filename represents a file.\r
+\r
+ This will search the CWD and then the Path.\r
+\r
+ If Name is NULL, then ASSERT.\r
+\r
+ @param[in] Name Path to file 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
+ShellIsFileInPath(\r
+ IN CONST CHAR16 *Name\r
+ ) {\r
+ CHAR16 *NewName;\r
+ EFI_STATUS Status;\r
+\r
+ if (!EFI_ERROR(ShellIsFile(Name))) {\r
+ return (TRUE);\r
+ }\r
+\r
+ NewName = ShellFindFilePath(Name);\r
+ if (NewName == NULL) {\r
+ return (EFI_NOT_FOUND);\r
+ }\r
+ Status = ShellIsFile(NewName);\r
+ FreePool(NewName);\r
+ return (Status);\r
+}\r
+/**\r
+ Function to determine whether a string is decimal or hex representation of a number\r
+ and return the number converted from the string.\r
+\r
+ @param[in] String String representation of a number\r
+\r
+ @retval all the number\r
+**/\r
+UINTN\r
+EFIAPI\r
+ShellStrToUintn(\r
+ IN CONST CHAR16 *String\r
+ )\r
+{\r
+ CONST CHAR16 *Walker;\r
+ for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);\r
+ if (Walker == NULL || *Walker == CHAR_NULL) {\r
+ ASSERT(FALSE);\r
+ return ((UINTN)(-1));\r
+ } else {\r
+ if (StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){\r
+ return (StrHexToUintn(Walker));\r
+ }\r
+ return (StrDecimalToUintn(Walker));\r
+ }\r
+}\r
+\r
+/**\r
+ Safely append with automatic string resizing given length of Destination and\r
+ desired length of copy from Source.\r
+\r
+ append the first D characters of Source to the end of Destination, where D is\r
+ the lesser of Count and the StrLen() of Source. If appending those D characters\r
+ will fit within Destination (whose Size is given as CurrentSize) and\r
+ still leave room for a NULL terminator, then those characters are appended,\r
+ starting at the original terminating NULL of Destination, and a new terminating\r
+ NULL is appended.\r
+\r
+ If appending D characters onto Destination will result in a overflow of the size\r
+ given in CurrentSize the string will be grown such that the copy can be performed\r
+ and CurrentSize will be updated to the new size.\r
+\r
+ If Source is NULL, there is nothing to append, just return the current buffer in\r
+ Destination.\r
+\r
+ if Destination is NULL, then ASSERT()\r
+ if Destination's current length (including NULL terminator) is already more then\r
+ CurrentSize, then ASSERT()\r
+\r
+ @param[in,out] Destination The String to append onto\r
+ @param[in,out] CurrentSize on call the number of bytes in Destination. On\r
+ return possibly the new size (still in bytes). if NULL\r
+ then allocate whatever is needed.\r
+ @param[in] Source The String to append from\r
+ @param[in] Count Maximum number of characters to append. if 0 then\r
+ all are appended.\r
+\r
+ @return Destination return the resultant string.\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+StrnCatGrow (\r
+ IN OUT CHAR16 **Destination,\r
+ IN OUT UINTN *CurrentSize,\r
+ IN CONST CHAR16 *Source,\r
+ IN UINTN Count\r
+ )\r
+{\r
+ UINTN DestinationStartSize;\r
+ UINTN NewSize;\r
+\r
+ //\r
+ // ASSERTs\r
+ //\r
+ ASSERT(Destination != NULL);\r
+\r
+ //\r
+ // If there's nothing to do then just return Destination\r
+ //\r
+ if (Source == NULL) {\r
+ return (*Destination);\r
+ }\r
+\r
+ //\r
+ // allow for un-initialized pointers, based on size being 0\r
+ //\r
+ if (CurrentSize != NULL && *CurrentSize == 0) {\r
+ *Destination = NULL;\r
+ }\r
+\r
+ //\r
+ // allow for NULL pointers address as Destination\r
+ //\r
+ if (*Destination != NULL) {\r
+ ASSERT(CurrentSize != 0);\r
+ DestinationStartSize = StrSize(*Destination);\r
+ ASSERT(DestinationStartSize <= *CurrentSize);\r
+ } else {\r
+ DestinationStartSize = 0;\r
+// ASSERT(*CurrentSize == 0);\r
+ }\r
+\r
+ //\r
+ // Append all of Source?\r
+ //\r
+ if (Count == 0) {\r
+ Count = StrLen(Source);\r
+ }\r
+\r
+ //\r
+ // Test and grow if required\r
+ //\r
+ if (CurrentSize != NULL) {\r
+ NewSize = *CurrentSize;\r
+ while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
+ NewSize += 2 * Count * sizeof(CHAR16);\r
+ }\r
+ *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
+ ASSERT(*Destination != NULL);\r
+ *CurrentSize = NewSize;\r
+ } else {\r
+ *Destination = AllocateZeroPool((Count+1)*sizeof(CHAR16));\r
+ ASSERT(*Destination != NULL);\r
+ }\r
+\r
+ //\r
+ // Now use standard StrnCat on a big enough buffer\r
+ //\r
+ if (*Destination == NULL) {\r
+ return (NULL);\r
+ }\r
+ return StrnCat(*Destination, Source, Count);\r
+}\r
+\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, SHELL_PROMPT_REQUEST_TYPE_QUIT_CONTINUE\r
+ or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.\r
+\r
+ if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_FREEFORM 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
+\r
+ Status = EFI_SUCCESS;\r
+ Resp = (SHELL_PROMPT_RESPONSE*)AllocatePool(sizeof(SHELL_PROMPT_RESPONSE));\r
+\r
+ switch(Type) {\r
+ case SHELL_PROMPT_REQUEST_TYPE_QUIT_CONTINUE:\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
+ ASSERT_EFI_ERROR(Status);\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {\r
+ *Resp = SHELL_PROMPT_RESPONSE_QUIT;\r
+ } else {\r
+ *Resp = SHELL_PROMPT_RESPONSE_CONTINUE;\r
+ }\r
+ break;\r
+ case SHELL_PROMPT_REQUEST_TYPE_YES_NO_ALL_CANCEL:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = SHELL_PROMPT_RESPONSE_MAX;\r
+ while (*Resp == SHELL_PROMPT_RESPONSE_MAX) {\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ ASSERT_EFI_ERROR(Status);\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ switch (Key.UnicodeChar) {\r
+ case L'Y':\r
+ case L'y':\r
+ *Resp = SHELL_PROMPT_RESPONSE_YES;\r
+ break;\r
+ case L'N':\r
+ case L'n':\r
+ *Resp = SHELL_PROMPT_RESPONSE_NO;\r
+ break;\r
+ case L'A':\r
+ case L'a':\r
+ *Resp = SHELL_PROMPT_RESPONSE_ALL;\r
+ break;\r
+ case L'C':\r
+ case L'c':\r
+ *Resp = SHELL_PROMPT_RESPONSE_CANCEL;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case SHELL_PROMPT_REQUEST_TYPE_ENTER_TO_COMTINUE:\r
+ case SHELL_PROMPT_REQUEST_TYPE_ANYKEY_TO_COMTINUE:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = SHELL_PROMPT_RESPONSE_MAX;\r
+ while (*Resp == SHELL_PROMPT_RESPONSE_MAX) {\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ if (Type == SHELL_PROMPT_REQUEST_TYPE_ENTER_TO_COMTINUE) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ ASSERT_EFI_ERROR(Status);\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ *Resp = SHELL_PROMPT_RESPONSE_CONTINUE;\r
+ break;\r
+ }\r
+ }\r
+ if (Type == SHELL_PROMPT_REQUEST_TYPE_ANYKEY_TO_COMTINUE) {\r
+ *Resp = SHELL_PROMPT_RESPONSE_CONTINUE;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ ///@todo add more request types here!\r
+ default:\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (Response != NULL) {\r
+ *Response = Resp;\r
+ } else {\r
+ FreePool(Resp);\r
+ }\r
+\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 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
+ @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