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