/** @file\r
Main file for Parse shell level 2 function.\r
\r
- (C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P.\r
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
\r
#include "UefiShellLevel2CommandsLib.h"\r
\r
+/**\r
+ Check if data is coming from StdIn output.\r
+\r
+ @param[in] None\r
+ \r
+ @retval TRUE StdIn stream data available to parse \r
+ @retval FALSE StdIn stream data is not available to parse. \r
+**/\r
+BOOLEAN\r
+IsStdInDataAvailable (\r
+ VOID\r
+ )\r
+{\r
+ SHELL_FILE_HANDLE FileHandle;\r
+ EFI_STATUS Status;\r
+ CHAR16 CharBuffer; \r
+ UINTN CharSize;\r
+ UINT64 OriginalFilePosition;\r
+\r
+ Status = EFI_SUCCESS; \r
+ FileHandle = NULL;\r
+ OriginalFilePosition = 0;\r
+\r
+ if (ShellOpenFileByName (L">i", &FileHandle, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) {\r
+ CharSize = sizeof(CHAR16);\r
+ gEfiShellProtocol->GetFilePosition (FileHandle, &OriginalFilePosition);\r
+ Status = gEfiShellProtocol->ReadFile (FileHandle, &CharSize, &CharBuffer);\r
+ if (EFI_ERROR (Status) || (CharSize != sizeof(CHAR16))) {\r
+ return FALSE;\r
+ }\r
+ gEfiShellProtocol->SetFilePosition(FileHandle, OriginalFilePosition);\r
+ }\r
+\r
+ if (FileHandle == NULL) {\r
+ return FALSE;\r
+ } else {\r
+ return TRUE;\r
+ }\r
+}\r
+\r
+/**\r
+ Function to read a single line (up to but not including the \n) using StdIn data 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
+ @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
+ShellFileHandleReadStdInLine(\r
+ IN SHELL_FILE_HANDLE Handle,\r
+ IN OUT CHAR16 *Buffer,\r
+ IN OUT UINTN *Size,\r
+ IN BOOLEAN Truncate\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
+\r
+ for (CountSoFar = 0;;CountSoFar++){\r
+ CharBuffer = 0;\r
+ CharSize = sizeof(CHAR16);\r
+ Status = gEfiShellProtocol->ReadFile (Handle, &CharSize, &CharBuffer);\r
+ if ( EFI_ERROR(Status)\r
+ || CharSize == 0\r
+ || (CharBuffer == L'\n')\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
+/**\r
+ Function to read a single line using StdIn 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
+\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
+ParseReturnStdInLine (\r
+ IN SHELL_FILE_HANDLE Handle\r
+ )\r
+{\r
+ CHAR16 *RetVal;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ Size = 0;\r
+ RetVal = NULL;\r
+\r
+ Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ RetVal = AllocateZeroPool(Size);\r
+ if (RetVal == NULL) {\r
+ return (NULL);\r
+ }\r
+ Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);\r
+\r
+ }\r
+ if (EFI_ERROR(Status) && (RetVal != NULL)) {\r
+ FreePool(RetVal);\r
+ RetVal = NULL;\r
+ }\r
+ return (RetVal);\r
+}\r
+\r
+/**\r
+ Handle stings for SFO Output with escape character ^ in a string\r
+ 1. Quotation marks in the string must be escaped by using a ^ character (i.e. ^"). \r
+ 2. The ^ character may be inserted using ^^.\r
+\r
+ @param[in] String The Unicode NULL-terminated string.\r
+ \r
+ @retval NewString The new string handled for SFO.\r
+**/\r
+EFI_STRING\r
+HandleStringWithEscapeCharForParse (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ EFI_STRING NewStr;\r
+ EFI_STRING StrWalker;\r
+ EFI_STRING ReturnStr;\r
+\r
+ if (String == NULL) {\r
+ return NULL;\r
+ }\r
+ \r
+ //\r
+ // start to parse the input string.\r
+ //\r
+ NewStr = AllocateZeroPool (StrSize (String));\r
+ if (NewStr == NULL) {\r
+ return NULL;\r
+ }\r
+ ReturnStr = NewStr;\r
+ StrWalker = String;\r
+ while (*StrWalker != CHAR_NULL) {\r
+ if (*StrWalker == L'^' && (*(StrWalker + 1) == L'^' || *(StrWalker + 1) == L'"')) {\r
+ *NewStr = *(StrWalker + 1);\r
+ StrWalker++;\r
+ } else {\r
+ *NewStr = *StrWalker;\r
+ }\r
+ StrWalker++;\r
+ NewStr++;\r
+ }\r
+ \r
+ return ReturnStr;\r
+}\r
+\r
+\r
/**\r
Do the actual parsing of the file. the file should be SFO output from a \r
shell command or a similar format.\r
@param[in] ColumnIndex The column number to get.\r
@param[in] TableNameInstance Which instance of the table to get (row).\r
@param[in] ShellCommandInstance Which instance of the command to get.\r
+ @param[in] StreamingUnicode Indicates Input file is StdIn Unicode streaming data or not\r
\r
@retval SHELL_NOT_FOUND The requested instance was not found.\r
@retval SHELL_SUCCESS The operation was successful.\r
IN CONST CHAR16 *TableName,\r
IN CONST UINTN ColumnIndex,\r
IN CONST UINTN TableNameInstance,\r
- IN CONST UINTN ShellCommandInstance\r
+ IN CONST UINTN ShellCommandInstance,\r
+ IN BOOLEAN StreamingUnicode\r
)\r
{\r
SHELL_FILE_HANDLE FileHandle;\r
CHAR16 *ColumnPointer;\r
SHELL_STATUS ShellStatus;\r
CHAR16 *TempSpot;\r
+ CHAR16 *SfoString;\r
\r
ASSERT(FileName != NULL);\r
ASSERT(TableName != NULL);\r
\r
Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);\r
if (EFI_ERROR(Status)) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, FileName);\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"parse", FileName); \r
ShellStatus = SHELL_NOT_FOUND;\r
} else if (!EFI_ERROR (FileHandleIsDirectory (FileHandle))) {\r
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_FILE), gShellLevel2HiiHandle, FileName);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_FILE), gShellLevel2HiiHandle, L"parse", FileName); \r
ShellStatus = SHELL_NOT_FOUND;\r
} else {\r
for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) {\r
- TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii);\r
- if (TempLine == NULL) {\r
- break;\r
+ if (StreamingUnicode) {\r
+ TempLine = ParseReturnStdInLine (FileHandle);\r
+ } else {\r
+ TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii); \r
+ }\r
+\r
+ if ((TempLine == NULL) || (*TempLine == CHAR_NULL && StreamingUnicode)) {\r
+ break;\r
}\r
\r
//\r
if (LoopVariable == ShellCommandInstance) {\r
LoopVariable = 0;\r
while(1) {\r
- TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii);\r
+ if (StreamingUnicode) {\r
+ TempLine = ParseReturnStdInLine (FileHandle);\r
+ } else {\r
+ TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii); \r
+ }\r
if (TempLine == NULL\r
|| *TempLine == CHAR_NULL\r
|| StrStr (TempLine, L"ShellCommand,") == TempLine) {\r
}\r
if (ColumnLoop == ColumnIndex) {\r
if (ColumnPointer == NULL) {\r
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"Column Index");\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"parse", L"Column Index"); \r
ShellStatus = SHELL_INVALID_PARAMETER;\r
} else {\r
TempSpot = StrStr (ColumnPointer, L",\"");\r
if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[StrLen (ColumnPointer) - 1] == L'\"'){\r
ColumnPointer[StrLen (ColumnPointer) - 1] = CHAR_NULL;\r
}\r
-\r
- ShellPrintEx (-1, -1, L"%s\r\n", ColumnPointer);\r
+ SfoString = HandleStringWithEscapeCharForParse (ColumnPointer);\r
+ if (SfoString != NULL) {\r
+ ShellPrintEx (-1, -1, L"%s\r\n", SfoString);\r
+ SHELL_FREE_NON_NULL (SfoString);\r
+ }\r
}\r
}\r
}\r
SHELL_STATUS ShellStatus;\r
UINTN ShellCommandInstance;\r
UINTN TableNameInstance;\r
+ BOOLEAN StreamingUnicode;\r
\r
- ShellStatus = SHELL_SUCCESS;\r
- ProblemParam = NULL;\r
+ ShellStatus = SHELL_SUCCESS;\r
+ ProblemParam = NULL;\r
+ StreamingUnicode = FALSE;\r
\r
//\r
// initialize the shell lib (we must be in non-auto-init...)\r
//\r
// parse the command line\r
//\r
- Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
+ Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, FALSE);\r
if (EFI_ERROR(Status)) {\r
if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"parse", ProblemParam); \r
FreePool(ProblemParam);\r
ShellStatus = SHELL_INVALID_PARAMETER;\r
} else {\r
ASSERT(FALSE);\r
}\r
} else {\r
- if (ShellCommandLineGetCount(Package) < 4) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);\r
+ StreamingUnicode = IsStdInDataAvailable ();\r
+ if ((!StreamingUnicode && (ShellCommandLineGetCount(Package) < 4)) ||\r
+ (ShellCommandLineGetCount(Package) < 3)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"parse"); \r
ShellStatus = SHELL_INVALID_PARAMETER;\r
- } else if (ShellCommandLineGetCount(Package) > 4) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
+ } else if ((StreamingUnicode && (ShellCommandLineGetCount(Package) > 3)) ||\r
+ (ShellCommandLineGetCount(Package) > 4)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"parse"); \r
ShellStatus = SHELL_INVALID_PARAMETER;\r
} else {\r
- FileName = ShellCommandLineGetRawValue(Package, 1);\r
- TableName = ShellCommandLineGetRawValue(Package, 2);\r
- ColumnString = ShellCommandLineGetRawValue(Package, 3);\r
-\r
+ if (StreamingUnicode) {\r
+ FileName = L">i";\r
+ TableName = ShellCommandLineGetRawValue(Package, 1);\r
+ ColumnString = ShellCommandLineGetRawValue(Package, 2);\r
+ } else {\r
+ FileName = ShellCommandLineGetRawValue(Package, 1);\r
+ TableName = ShellCommandLineGetRawValue(Package, 2);\r
+ ColumnString = ShellCommandLineGetRawValue(Package, 3);\r
+ }\r
if (ShellCommandLineGetValue(Package, L"-i") == NULL) {\r
TableNameInstance = (UINTN)-1;\r
} else {\r
ShellCommandInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-s"));\r
}\r
\r
- ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance);\r
+ ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance, StreamingUnicode);\r
}\r
}\r
\r