]>
Commit | Line | Data |
---|---|---|
a405b86d | 1 | /** @file\r |
2 | Main file for Parse shell level 2 function.\r | |
3 | \r | |
c011b6c9 | 4 | (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r |
ba0014b9 | 5 | Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r |
56ba3746 | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
a405b86d | 7 | \r |
8 | **/\r | |
9 | \r | |
10 | #include "UefiShellLevel2CommandsLib.h"\r | |
11 | \r | |
421fbf99 TS |
12 | /**\r |
13 | Check if data is coming from StdIn output.\r | |
14 | \r | |
15 | @param[in] None\r | |
ba0014b9 LG |
16 | \r |
17 | @retval TRUE StdIn stream data available to parse\r | |
18 | @retval FALSE StdIn stream data is not available to parse.\r | |
421fbf99 TS |
19 | **/\r |
20 | BOOLEAN\r | |
21 | IsStdInDataAvailable (\r | |
22 | VOID\r | |
23 | )\r | |
24 | {\r | |
47d20b54 MK |
25 | SHELL_FILE_HANDLE FileHandle;\r |
26 | EFI_STATUS Status;\r | |
27 | CHAR16 CharBuffer;\r | |
28 | UINTN CharSize;\r | |
29 | UINT64 OriginalFilePosition;\r | |
421fbf99 | 30 | \r |
ba0014b9 | 31 | Status = EFI_SUCCESS;\r |
421fbf99 TS |
32 | FileHandle = NULL;\r |
33 | OriginalFilePosition = 0;\r | |
34 | \r | |
35 | if (ShellOpenFileByName (L">i", &FileHandle, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) {\r | |
47d20b54 | 36 | CharSize = sizeof (CHAR16);\r |
421fbf99 TS |
37 | gEfiShellProtocol->GetFilePosition (FileHandle, &OriginalFilePosition);\r |
38 | Status = gEfiShellProtocol->ReadFile (FileHandle, &CharSize, &CharBuffer);\r | |
47d20b54 | 39 | if (EFI_ERROR (Status) || (CharSize != sizeof (CHAR16))) {\r |
421fbf99 TS |
40 | return FALSE;\r |
41 | }\r | |
47d20b54 MK |
42 | \r |
43 | gEfiShellProtocol->SetFilePosition (FileHandle, OriginalFilePosition);\r | |
421fbf99 TS |
44 | }\r |
45 | \r | |
46 | if (FileHandle == NULL) {\r | |
47 | return FALSE;\r | |
48 | } else {\r | |
49 | return TRUE;\r | |
50 | }\r | |
51 | }\r | |
52 | \r | |
307f2ce4 TS |
53 | /**\r |
54 | Handle stings for SFO Output with escape character ^ in a string\r | |
ba0014b9 | 55 | 1. Quotation marks in the string must be escaped by using a ^ character (i.e. ^").\r |
307f2ce4 TS |
56 | 2. The ^ character may be inserted using ^^.\r |
57 | \r | |
58 | @param[in] String The Unicode NULL-terminated string.\r | |
ba0014b9 | 59 | \r |
307f2ce4 TS |
60 | @retval NewString The new string handled for SFO.\r |
61 | **/\r | |
62 | EFI_STRING\r | |
63 | HandleStringWithEscapeCharForParse (\r | |
64 | IN CHAR16 *String\r | |
65 | )\r | |
66 | {\r | |
67 | EFI_STRING NewStr;\r | |
68 | EFI_STRING StrWalker;\r | |
69 | EFI_STRING ReturnStr;\r | |
70 | \r | |
71 | if (String == NULL) {\r | |
72 | return NULL;\r | |
73 | }\r | |
ba0014b9 | 74 | \r |
307f2ce4 TS |
75 | //\r |
76 | // start to parse the input string.\r | |
77 | //\r | |
78 | NewStr = AllocateZeroPool (StrSize (String));\r | |
79 | if (NewStr == NULL) {\r | |
80 | return NULL;\r | |
81 | }\r | |
47d20b54 | 82 | \r |
307f2ce4 TS |
83 | ReturnStr = NewStr;\r |
84 | StrWalker = String;\r | |
85 | while (*StrWalker != CHAR_NULL) {\r | |
47d20b54 | 86 | if ((*StrWalker == L'^') && ((*(StrWalker + 1) == L'^') || (*(StrWalker + 1) == L'"'))) {\r |
307f2ce4 TS |
87 | *NewStr = *(StrWalker + 1);\r |
88 | StrWalker++;\r | |
89 | } else {\r | |
90 | *NewStr = *StrWalker;\r | |
91 | }\r | |
47d20b54 | 92 | \r |
307f2ce4 TS |
93 | StrWalker++;\r |
94 | NewStr++;\r | |
95 | }\r | |
ba0014b9 | 96 | \r |
307f2ce4 TS |
97 | return ReturnStr;\r |
98 | }\r | |
99 | \r | |
b54fd049 | 100 | /**\r |
ba0014b9 | 101 | Do the actual parsing of the file. the file should be SFO output from a\r |
b54fd049 | 102 | shell command or a similar format.\r |
103 | \r | |
104 | @param[in] FileName The filename to open.\r | |
105 | @param[in] TableName The name of the table to find.\r | |
106 | @param[in] ColumnIndex The column number to get.\r | |
107 | @param[in] TableNameInstance Which instance of the table to get (row).\r | |
108 | @param[in] ShellCommandInstance Which instance of the command to get.\r | |
421fbf99 | 109 | @param[in] StreamingUnicode Indicates Input file is StdIn Unicode streaming data or not\r |
b54fd049 | 110 | \r |
111 | @retval SHELL_NOT_FOUND The requested instance was not found.\r | |
112 | @retval SHELL_SUCCESS The operation was successful.\r | |
113 | **/\r | |
a405b86d | 114 | SHELL_STATUS\r |
47d20b54 MK |
115 | PerformParsing (\r |
116 | IN CONST CHAR16 *FileName,\r | |
117 | IN CONST CHAR16 *TableName,\r | |
118 | IN CONST UINTN ColumnIndex,\r | |
119 | IN CONST UINTN TableNameInstance,\r | |
120 | IN CONST UINTN ShellCommandInstance,\r | |
121 | IN BOOLEAN StreamingUnicode\r | |
a405b86d | 122 | )\r |
123 | {\r | |
47d20b54 MK |
124 | SHELL_FILE_HANDLE FileHandle;\r |
125 | EFI_STATUS Status;\r | |
126 | BOOLEAN Ascii;\r | |
127 | UINTN LoopVariable;\r | |
128 | UINTN ColumnLoop;\r | |
129 | CHAR16 *TempLine;\r | |
130 | CHAR16 *ColumnPointer;\r | |
131 | SHELL_STATUS ShellStatus;\r | |
132 | CHAR16 *TempSpot;\r | |
133 | CHAR16 *SfoString;\r | |
134 | \r | |
135 | ASSERT (FileName != NULL);\r | |
136 | ASSERT (TableName != NULL);\r | |
137 | \r | |
138 | ShellStatus = SHELL_SUCCESS;\r | |
139 | \r | |
140 | Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);\r | |
141 | if (EFI_ERROR (Status)) {\r | |
142 | ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"parse", FileName);\r | |
a405b86d | 143 | ShellStatus = SHELL_NOT_FOUND;\r |
78d42190 | 144 | } else if (!EFI_ERROR (FileHandleIsDirectory (FileHandle))) {\r |
ba0014b9 | 145 | ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_FILE), gShellLevel2HiiHandle, L"parse", FileName);\r |
78d42190 | 146 | ShellStatus = SHELL_NOT_FOUND;\r |
a405b86d | 147 | } else {\r |
47d20b54 MK |
148 | for (LoopVariable = 0; LoopVariable < ShellCommandInstance && !ShellFileHandleEof (FileHandle);) {\r |
149 | TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii);\r | |
421fbf99 | 150 | \r |
47d20b54 MK |
151 | if ((TempLine == NULL) || ((*TempLine == CHAR_NULL) && StreamingUnicode)) {\r |
152 | break;\r | |
a405b86d | 153 | }\r |
78d42190 CP |
154 | \r |
155 | //\r | |
156 | // Search for "ShellCommand," in the file to start the SFO table\r | |
157 | // for a given ShellCommand. The UEFI Shell spec does not specify\r | |
158 | // a space after the comma.\r | |
159 | //\r | |
160 | if (StrStr (TempLine, L"ShellCommand,") == TempLine) {\r | |
a405b86d | 161 | LoopVariable++;\r |
162 | }\r | |
47d20b54 MK |
163 | \r |
164 | SHELL_FREE_NON_NULL (TempLine);\r | |
a405b86d | 165 | }\r |
47d20b54 | 166 | \r |
a405b86d | 167 | if (LoopVariable == ShellCommandInstance) {\r |
168 | LoopVariable = 0;\r | |
47d20b54 | 169 | while (1) {\r |
ba0014b9 | 170 | TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii);\r |
47d20b54 MK |
171 | if ( (TempLine == NULL)\r |
172 | || (*TempLine == CHAR_NULL)\r | |
173 | || (StrStr (TempLine, L"ShellCommand,") == TempLine))\r | |
174 | {\r | |
175 | SHELL_FREE_NON_NULL (TempLine);\r | |
a405b86d | 176 | break;\r |
177 | }\r | |
47d20b54 | 178 | \r |
78d42190 | 179 | if (StrStr (TempLine, TableName) == TempLine) {\r |
a405b86d | 180 | LoopVariable++;\r |
47d20b54 MK |
181 | if ( (LoopVariable == TableNameInstance)\r |
182 | || (TableNameInstance == (UINTN)-1))\r | |
183 | {\r | |
78d42190 | 184 | for (ColumnLoop = 1, ColumnPointer = TempLine; ColumnLoop < ColumnIndex && ColumnPointer != NULL && *ColumnPointer != CHAR_NULL; ColumnLoop++) {\r |
76c94bb2 | 185 | ColumnPointer = StrStr (ColumnPointer, L",\"");\r |
47d20b54 | 186 | if ((ColumnPointer != NULL) && (*ColumnPointer != CHAR_NULL)) {\r |
8fcf74a8 | 187 | ColumnPointer++;\r |
188 | }\r | |
78d42190 | 189 | }\r |
47d20b54 | 190 | \r |
78d42190 CP |
191 | if (ColumnLoop == ColumnIndex) {\r |
192 | if (ColumnPointer == NULL) {\r | |
47d20b54 | 193 | ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"parse", L"Column Index");\r |
78d42190 CP |
194 | ShellStatus = SHELL_INVALID_PARAMETER;\r |
195 | } else {\r | |
76c94bb2 | 196 | TempSpot = StrStr (ColumnPointer, L",\"");\r |
78d42190 CP |
197 | if (TempSpot != NULL) {\r |
198 | *TempSpot = CHAR_NULL;\r | |
199 | }\r | |
47d20b54 MK |
200 | \r |
201 | while (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L' ') {\r | |
78d42190 CP |
202 | ColumnPointer++;\r |
203 | }\r | |
47d20b54 MK |
204 | \r |
205 | if ((ColumnPointer != NULL) && (*ColumnPointer != CHAR_NULL) && (ColumnPointer[0] == L'\"')) {\r | |
78d42190 CP |
206 | ColumnPointer++;\r |
207 | }\r | |
47d20b54 MK |
208 | \r |
209 | if ((ColumnPointer != NULL) && (*ColumnPointer != CHAR_NULL) && (ColumnPointer[StrLen (ColumnPointer) - 1] == L'\"')) {\r | |
78d42190 CP |
210 | ColumnPointer[StrLen (ColumnPointer) - 1] = CHAR_NULL;\r |
211 | }\r | |
47d20b54 | 212 | \r |
307f2ce4 TS |
213 | SfoString = HandleStringWithEscapeCharForParse (ColumnPointer);\r |
214 | if (SfoString != NULL) {\r | |
215 | ShellPrintEx (-1, -1, L"%s\r\n", SfoString);\r | |
216 | SHELL_FREE_NON_NULL (SfoString);\r | |
217 | }\r | |
78d42190 | 218 | }\r |
8fcf74a8 | 219 | }\r |
a405b86d | 220 | }\r |
221 | }\r | |
47d20b54 MK |
222 | \r |
223 | SHELL_FREE_NON_NULL (TempLine);\r | |
a405b86d | 224 | }\r |
225 | }\r | |
226 | }\r | |
47d20b54 | 227 | \r |
a405b86d | 228 | return (ShellStatus);\r |
229 | }\r | |
230 | \r | |
47d20b54 MK |
231 | STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r |
232 | { L"-i", TypeValue },\r | |
233 | { L"-s", TypeValue },\r | |
234 | { NULL, TypeMax }\r | |
235 | };\r | |
a405b86d | 236 | \r |
237 | /**\r | |
238 | Function for 'parse' command.\r | |
239 | \r | |
240 | @param[in] ImageHandle Handle to the Image (NULL if Internal).\r | |
241 | @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r | |
242 | **/\r | |
243 | SHELL_STATUS\r | |
244 | EFIAPI\r | |
245 | ShellCommandRunParse (\r | |
246 | IN EFI_HANDLE ImageHandle,\r | |
247 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
248 | )\r | |
249 | {\r | |
47d20b54 MK |
250 | EFI_STATUS Status;\r |
251 | LIST_ENTRY *Package;\r | |
252 | CHAR16 *ProblemParam;\r | |
253 | CONST CHAR16 *FileName;\r | |
254 | CONST CHAR16 *TableName;\r | |
255 | CONST CHAR16 *ColumnString;\r | |
256 | SHELL_STATUS ShellStatus;\r | |
257 | UINTN ShellCommandInstance;\r | |
258 | UINTN TableNameInstance;\r | |
259 | BOOLEAN StreamingUnicode;\r | |
a405b86d | 260 | \r |
421fbf99 TS |
261 | ShellStatus = SHELL_SUCCESS;\r |
262 | ProblemParam = NULL;\r | |
263 | StreamingUnicode = FALSE;\r | |
a405b86d | 264 | \r |
265 | //\r | |
266 | // initialize the shell lib (we must be in non-auto-init...)\r | |
267 | //\r | |
47d20b54 MK |
268 | Status = ShellInitialize ();\r |
269 | ASSERT_EFI_ERROR (Status);\r | |
a405b86d | 270 | \r |
271 | //\r | |
272 | // parse the command line\r | |
273 | //\r | |
421fbf99 | 274 | Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, FALSE);\r |
47d20b54 MK |
275 | if (EFI_ERROR (Status)) {\r |
276 | if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {\r | |
277 | ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"parse", ProblemParam);\r | |
278 | FreePool (ProblemParam);\r | |
a405b86d | 279 | ShellStatus = SHELL_INVALID_PARAMETER;\r |
280 | } else {\r | |
47d20b54 | 281 | ASSERT (FALSE);\r |
a405b86d | 282 | }\r |
283 | } else {\r | |
421fbf99 | 284 | StreamingUnicode = IsStdInDataAvailable ();\r |
47d20b54 MK |
285 | if ((!StreamingUnicode && (ShellCommandLineGetCount (Package) < 4)) ||\r |
286 | (ShellCommandLineGetCount (Package) < 3))\r | |
287 | {\r | |
288 | ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"parse");\r | |
a405b86d | 289 | ShellStatus = SHELL_INVALID_PARAMETER;\r |
47d20b54 MK |
290 | } else if ((StreamingUnicode && (ShellCommandLineGetCount (Package) > 3)) ||\r |
291 | (ShellCommandLineGetCount (Package) > 4))\r | |
292 | {\r | |
293 | ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"parse");\r | |
a405b86d | 294 | ShellStatus = SHELL_INVALID_PARAMETER;\r |
295 | } else {\r | |
421fbf99 | 296 | if (StreamingUnicode) {\r |
47d20b54 MK |
297 | FileName = L">i";\r |
298 | TableName = ShellCommandLineGetRawValue (Package, 1);\r | |
299 | ColumnString = ShellCommandLineGetRawValue (Package, 2);\r | |
421fbf99 | 300 | } else {\r |
47d20b54 MK |
301 | FileName = ShellCommandLineGetRawValue (Package, 1);\r |
302 | TableName = ShellCommandLineGetRawValue (Package, 2);\r | |
303 | ColumnString = ShellCommandLineGetRawValue (Package, 3);\r | |
421fbf99 | 304 | }\r |
47d20b54 MK |
305 | \r |
306 | if (ShellCommandLineGetValue (Package, L"-i") == NULL) {\r | |
a405b86d | 307 | TableNameInstance = (UINTN)-1;\r |
308 | } else {\r | |
47d20b54 | 309 | TableNameInstance = ShellStrToUintn (ShellCommandLineGetValue (Package, L"-i"));\r |
a405b86d | 310 | }\r |
47d20b54 MK |
311 | \r |
312 | if (ShellCommandLineGetValue (Package, L"-s") == NULL) {\r | |
a405b86d | 313 | ShellCommandInstance = 1;\r |
314 | } else {\r | |
47d20b54 | 315 | ShellCommandInstance = ShellStrToUintn (ShellCommandLineGetValue (Package, L"-s"));\r |
a405b86d | 316 | }\r |
317 | \r | |
47d20b54 | 318 | ShellStatus = PerformParsing (FileName, TableName, ShellStrToUintn (ColumnString), TableNameInstance, ShellCommandInstance, StreamingUnicode);\r |
a405b86d | 319 | }\r |
320 | }\r | |
321 | \r | |
322 | //\r | |
323 | // free the command line package\r | |
324 | //\r | |
325 | ShellCommandLineFreeVarList (Package);\r | |
326 | \r | |
327 | return (ShellStatus);\r | |
328 | }\r |