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