#include <Library/DevicePathLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/FileHandleLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
#include <Protocol/EfiShellEnvironment2.h>\r
#include <Protocol/EfiShellInterface.h>\r
#include <Protocol/EfiShell.h>\r
#include <Protocol/EfiShellParameters.h>\r
#include <Protocol/SimpleFileSystem.h>\r
\r
-#include "BaseShellLib.h"\r
+#include "UefiShellLib.h"\r
\r
#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)\r
#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)\r
mEfiShellInterface = NULL;\r
mEfiShellEnvironment2Handle = NULL;\r
\r
- ///@todo make a worker constructor so initialize function works\r
//\r
// verify that auto initialize is not set false\r
// \r
}\r
Status = gBS->OpenProtocol(*DeviceHandle,\r
&gEfiSimpleFileSystemProtocolGuid,\r
- (VOID**) &EfiSimpleFileSystemProtocol,\r
+ (VOID**)&EfiSimpleFileSystemProtocol,\r
gImageHandle,\r
NULL,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
{\r
EFI_HANDLE DeviceHandle;\r
EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
+ EFI_STATUS Status;\r
+ EFI_FILE_INFO *FileInfo;\r
\r
//\r
// ASSERT if FileName is NULL\r
//\r
// Use UEFI Shell 2.0 method\r
//\r
- return (mEfiShellProtocol->OpenFileByName(FileName,\r
- FileHandle,\r
- OpenMode));\r
-\r
- ///@todo add the attributes\r
+ Status = mEfiShellProtocol->OpenFileByName(FileName,\r
+ FileHandle,\r
+ OpenMode);\r
+ if (!EFI_ERROR(Status)){\r
+ FileInfo = FileHandleGetInfo(*FileHandle);\r
+ ASSERT(FileInfo != NULL);\r
+ FileInfo->Attribute = Attributes;\r
+ Status = FileHandleSetInfo(*FileHandle, FileInfo);\r
+ }\r
+ return (Status);\r
} \r
//\r
// Using EFI Shell version\r
//\r
// do nothing for NULL argv\r
//\r
- } else if (GetItemValue == TRUE) {\r
- ASSERT(CurrentItemPackage != NULL);\r
- //\r
- // get the item VALUE for the previous flag\r
- //\r
- GetItemValue = FALSE;\r
- CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter]));\r
- ASSERT(CurrentItemPackage->Value != NULL);\r
- StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
- InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
- } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
- //\r
- // add this one as a non-flag\r
- //\r
- CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
- ASSERT(CurrentItemPackage != NULL);\r
- CurrentItemPackage->Name = NULL;\r
- CurrentItemPackage->Type = TypePosition;\r
- CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));\r
- ASSERT(CurrentItemPackage->Value != NULL);\r
- StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
- CurrentItemPackage->OriginalPosition = Count++;\r
- InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
} else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) {\r
//\r
// this is a flag\r
StrCpy(CurrentItemPackage->Name, Argv[LoopCounter]);\r
CurrentItemPackage->Type = CurrentItemType;\r
CurrentItemPackage->OriginalPosition = (UINTN)(-1);\r
+ CurrentItemPackage->Value = NULL;\r
\r
//\r
// Does this flag require a value\r
//\r
// this item has no value expected; we are done\r
//\r
- CurrentItemPackage->Value = NULL;\r
- InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
+ InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
}\r
+ } else if (GetItemValue == TRUE && InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
+ ASSERT(CurrentItemPackage != NULL);\r
+ //\r
+ // get the item VALUE for the previous flag\r
+ //\r
+ GetItemValue = FALSE;\r
+ CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter]));\r
+ ASSERT(CurrentItemPackage->Value != NULL);\r
+ StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
+ InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
+ } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
+ //\r
+ // add this one as a non-flag\r
+ //\r
+ CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
+ ASSERT(CurrentItemPackage != NULL);\r
+ CurrentItemPackage->Name = NULL;\r
+ CurrentItemPackage->Type = TypePosition;\r
+ CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));\r
+ ASSERT(CurrentItemPackage->Value != NULL);\r
+ StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
+ CurrentItemPackage->OriginalPosition = Count++;\r
+ InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
} else if (ProblemParam) {\r
//\r
// this was a non-recognised flag... error!\r
}\r
}\r
return (NULL);\r
+}\r
+/**\r
+ This is a find and replace function. it will return the NewString as a copy of \r
+ SourceString with each instance of FindTarget replaced with ReplaceWith.\r
+\r
+ If the string would grow bigger than NewSize it will halt and return error.\r
+\r
+ @param[in] SourceString String with source buffer\r
+ @param[in][out] NewString String with resultant buffer\r
+ @param[in] NewSize Size in bytes of NewString\r
+ @param[in] FindTarget String to look for\r
+ @param[in[ ReplaceWith String to replace FindTarget with\r
+\r
+ @retval EFI_INVALID_PARAMETER SourceString was NULL\r
+ @retval EFI_INVALID_PARAMETER NewString was NULL\r
+ @retval EFI_INVALID_PARAMETER FindTarget was NULL\r
+ @retval EFI_INVALID_PARAMETER ReplaceWith was NULL\r
+ @retval EFI_INVALID_PARAMETER FindTarget had length < 1\r
+ @retval EFI_INVALID_PARAMETER SourceString had length < 1\r
+ @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold \r
+ the new string (truncation occurred)\r
+ @retval EFI_SUCCESS the string was sucessfully copied with replacement\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CopyReplace(\r
+ IN CHAR16 CONST *SourceString,\r
+ IN CHAR16 *NewString,\r
+ IN UINTN NewSize,\r
+ IN CONST CHAR16 *FindTarget,\r
+ IN CONST CHAR16 *ReplaceWith\r
+ ){\r
+ if ( (SourceString == NULL)\r
+ || (NewString == NULL)\r
+ || (FindTarget == NULL)\r
+ || (ReplaceWith == NULL)\r
+ || (StrLen(FindTarget) < 1)\r
+ || (StrLen(SourceString) < 1)\r
+ ){\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ NewString = SetMem16(NewString, NewSize, L'\0');\r
+ while (*SourceString != L'\0') {\r
+ if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0) {\r
+ SourceString += StrLen(FindTarget);\r
+ if (StrSize(NewString) + (StrLen(ReplaceWith)*sizeof(CHAR16)) > NewSize) {\r
+ return (EFI_BUFFER_TOO_SMALL);\r
+ }\r
+ StrCat(NewString, ReplaceWith);\r
+ } else {\r
+ if (StrSize(NewString) + sizeof(CHAR16) > NewSize) {\r
+ return (EFI_BUFFER_TOO_SMALL);\r
+ }\r
+ StrnCat(NewString, SourceString, 1);\r
+ SourceString++;\r
+ }\r
+ }\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Print at a specific location on the screen.\r
+\r
+ This function will move the cursor to a given screen location, print the specified string, \r
+ and return the cursor to the original locaiton. \r
+ \r
+ If -1 is specified for either the Row or Col the current screen location for BOTH \r
+ will be used and the cursor's position will not be moved back to an original location.\r
+\r
+ if either Row or Col is out of range for the current console, then ASSERT\r
+ if Format is NULL, then ASSERT\r
+\r
+ In addition to the standard %-based flags as supported by UefiLib Print() this supports \r
+ the following additional flags:\r
+ %N - Set output attribute to normal\r
+ %H - Set output attribute to highlight\r
+ %E - Set output attribute to error\r
+ %B - Set output attribute to blue color\r
+ %V - Set output attribute to green color\r
+\r
+ Note: The background color is controlled by the shell command cls.\r
+\r
+ @param[in] Row the row to print at\r
+ @param[in] Col the column to print at\r
+ @param[in] Format the format string\r
+\r
+ @return the number of characters printed to the screen\r
+**/\r
+\r
+UINTN\r
+EFIAPI\r
+ShellPrintEx(\r
+ IN INT32 Col OPTIONAL,\r
+ IN INT32 Row OPTIONAL,\r
+ IN CONST CHAR16 *Format,\r
+ ...\r
+ ){\r
+ VA_LIST Marker;\r
+ UINTN BufferSize;\r
+ CHAR16 *PostReplaceFormat;\r
+ CHAR16 *PostReplaceFormat2;\r
+ UINTN Return;\r
+ INT32 CurrentCol;\r
+ INT32 CurrentRow;\r
+ EFI_STATUS Status;\r
+ UINTN NormalAttribute;\r
+ CHAR16 *ResumeLocation;\r
+ CHAR16 *FormatWalker;\r
+\r
+ VA_START (Marker, Format);\r
+ \r
+ BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);\r
+ PostReplaceFormat = AllocateZeroPool (BufferSize);\r
+ ASSERT (PostReplaceFormat != NULL);\r
+ PostReplaceFormat2 = AllocateZeroPool (BufferSize);\r
+ ASSERT (PostReplaceFormat2 != NULL);\r
+\r
+ //\r
+ // Back and forth each time fixing up 1 of our flags...\r
+ //\r
+ Status = CopyReplace(Format, PostReplaceFormat, BufferSize, L"%N", L"%%N");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat, PostReplaceFormat2, BufferSize, L"%E", L"%%E");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat2, PostReplaceFormat, BufferSize, L"%H", L"%%H");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat, PostReplaceFormat2, BufferSize, L"%B", L"%%B");\r
+ ASSERT_EFI_ERROR(Status);\r
+ Status = CopyReplace(PostReplaceFormat2, PostReplaceFormat, BufferSize, L"%V", L"%%V");\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ //\r
+ // Use the last buffer from replacing to print from...\r
+ //\r
+ Return = UnicodeVSPrint (PostReplaceFormat2, BufferSize, PostReplaceFormat, Marker);\r
+\r
+ FreePool(PostReplaceFormat);\r
+\r
+ if (Col != -1 && Row != -1) {\r
+ CurrentCol = gST->ConOut->Mode->CursorColumn;\r
+ CurrentRow = gST->ConOut->Mode->CursorRow;\r
+ Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);\r
+ ASSERT_EFI_ERROR(Status);\r
+ } else {\r
+ CurrentCol = 0;\r
+ CurrentRow = 0;\r
+ }\r
+\r
+ NormalAttribute = gST->ConOut->Mode->Attribute;\r
+ FormatWalker = PostReplaceFormat2;\r
+ while (*FormatWalker != L'\0') {\r
+ //\r
+ // Find the next attribute change request\r
+ //\r
+ ResumeLocation = StrStr(FormatWalker, L"%");\r
+ if (ResumeLocation != NULL) {\r
+ *ResumeLocation = L'\0';\r
+ }\r
+ //\r
+ // print the current FormatWalker string\r
+ //\r
+ Status = gST->ConOut->OutputString(gST->ConOut, FormatWalker);\r
+ ASSERT_EFI_ERROR(Status);\r
+ //\r
+ // update the attribute\r
+ //\r
+ if (ResumeLocation != NULL) {\r
+ switch (*(ResumeLocation+1)) {\r
+ case (L'N'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
+ break;\r
+ case (L'E'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'H'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'B'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'V'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ default:\r
+ ASSERT(FALSE);\r
+ break;\r
+ }\r
+ } else {\r
+ //\r
+ // reset to normal now...\r
+ //\r
+ gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // update FormatWalker to Resume + 2 (skip the % and the indicator)\r
+ //\r
+ FormatWalker = ResumeLocation + 2;\r
+ }\r
+ \r
+ if (Col != -1 && Row != -1) {\r
+ Status = gST->ConOut->SetCursorPosition(gST->ConOut, CurrentCol, CurrentRow);\r
+ ASSERT_EFI_ERROR(Status);\r
+ }\r
+\r
+ FreePool(PostReplaceFormat2);\r
+\r
+ return (Return);\r
}
\ No newline at end of file