]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel1CommandsLib/If.c
pointer verification (not NULL) and buffer overrun fixes.
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel1CommandsLib / If.c
CommitLineData
a405b86d 1/** @file\r
2 Main file for If and else shell level 1 function.\r
3\r
77dcec12 4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
a405b86d 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "UefiShellLevel1CommandsLib.h"\r
16#include <Library/PrintLib.h>\r
17\r
a405b86d 18typedef enum {\r
77dcec12 19 EndTagOr,\r
20 EndTagAnd,\r
21 EndTagThen,\r
22 EndTagMax\r
a405b86d 23} END_TAG_TYPE;\r
24\r
25typedef enum {\r
77dcec12 26 OperatorGreaterThan,\r
27 OperatorLessThan,\r
28 OperatorEqual,\r
29 OperatorNotEqual,\r
30 OperatorGreatorOrEqual,\r
31 OperatorLessOrEqual,\r
32 OperatorUnisgnedGreaterThan,\r
33 OperatorUnsignedLessThan,\r
34 OperatorUnsignedGreaterOrEqual,\r
35 OperatorUnsignedLessOrEqual,\r
36 OperatorMax\r
a405b86d 37} BIN_OPERATOR_TYPE;\r
38\r
77dcec12 39/**\r
40 Extract the next fragment, if there is one.\r
41\r
42 @param[in,out] Statement The current remaining statement.\r
43 @param[in] Fragment The current fragment.\r
44\r
45 @retval FALSE There is not another fragment.\r
46 @retval TRUE There is another fragment.\r
47**/\r
a405b86d 48BOOLEAN\r
49EFIAPI\r
50IsNextFragment (\r
77dcec12 51 IN OUT CONST CHAR16 **Statement,\r
a405b86d 52 IN CONST CHAR16 *Fragment\r
53 )\r
54{\r
55 CHAR16 *Tester;\r
56\r
57 Tester = NULL;\r
58\r
59 Tester = StrnCatGrow(&Tester, NULL, *Statement, StrLen(Fragment));\r
60 ASSERT(Tester != NULL);\r
61 Tester[StrLen(Fragment)] = CHAR_NULL;\r
62 if (gUnicodeCollation->StriColl(\r
63 gUnicodeCollation,\r
64 (CHAR16*)Fragment,\r
65 Tester) == 0) {\r
66 //\r
67 // increment the string pointer to the end of what we found and then chop off spaces...\r
68 //\r
69 *Statement+=StrLen(Fragment);\r
70 while (*Statement[0] == L' ') {\r
1ca79586 71 (*Statement)++;\r
a405b86d 72 }\r
73 FreePool(Tester);\r
74 return (TRUE);\r
75 }\r
76 FreePool(Tester);\r
77 return (FALSE);\r
78}\r
79\r
77dcec12 80/**\r
81 Determine if String represents a valid profile.\r
82\r
83 @param[in] String The pointer to the string to test.\r
84\r
85 @retval TRUE String is a valid profile.\r
86 @retval FALSE String is not a valid profile.\r
87**/\r
a405b86d 88BOOLEAN\r
89EFIAPI\r
90IsValidProfile (\r
91 IN CONST CHAR16 *String\r
92 )\r
93{\r
94 CONST CHAR16 *ProfilesString;\r
95 CONST CHAR16 *TempLocation;\r
96\r
97 ProfilesString = ShellGetEnvironmentVariable(L"profiles");\r
98 TempLocation = StrStr(ProfilesString, String);\r
99 if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen(String)) == L';')) {\r
100 return (TRUE);\r
101 }\r
102 return (FALSE);\r
103}\r
104\r
77dcec12 105/**\r
106 Do a comparison between 2 things.\r
107\r
108 @param[in] Compare1 The first item to compare.\r
109 @param[in] Compare2 The second item to compare.\r
110 @param[in] BinOp The type of comparison to perform.\r
111 @param[in] CaseInsensitive TRUE to do non-case comparison, FALSE otherwise.\r
112 @param[in] ForceStringCompare TRUE to force string comparison, FALSE otherwise.\r
113\r
114 @return The result of the comparison.\r
115**/\r
a405b86d 116BOOLEAN\r
117EFIAPI\r
118TestOperation (\r
119 IN CONST CHAR16 *Compare1,\r
120 IN CONST CHAR16 *Compare2,\r
121 IN CONST BIN_OPERATOR_TYPE BinOp,\r
122 IN CONST BOOLEAN CaseInsensitive,\r
123 IN CONST BOOLEAN ForceStringCompare\r
124 )\r
125{\r
126 INTN Cmp1;\r
127 INTN Cmp2;\r
128\r
129 //\r
130 // "Compare1 BinOp Compare2"\r
131 //\r
132 switch (BinOp) {\r
77dcec12 133 case OperatorUnisgnedGreaterThan:\r
134 case OperatorGreaterThan:\r
a405b86d 135 if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {\r
136 //\r
137 // string compare\r
138 //\r
139 if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) {\r
140 return (TRUE);\r
141 }\r
142 } else {\r
143 //\r
144 // numeric compare\r
145 //\r
146 if (Compare1[0] == L'-') {\r
77dcec12 147 Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);\r
a405b86d 148 } else {\r
77dcec12 149 Cmp1 = (INTN)ShellStrToUintn(Compare1);\r
a405b86d 150 }\r
151 if (Compare2[0] == L'-') {\r
77dcec12 152 Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);\r
a405b86d 153 } else {\r
77dcec12 154 Cmp2 = (INTN)ShellStrToUintn(Compare2);\r
a405b86d 155 }\r
77dcec12 156 if (BinOp == OperatorGreaterThan) {\r
a405b86d 157 if (Cmp1 > Cmp2) {\r
158 return (TRUE);\r
159 }\r
160 } else {\r
161 if ((UINTN)Cmp1 > (UINTN)Cmp2) {\r
162 return (TRUE);\r
163 }\r
164 }\r
165 }\r
166 return (FALSE);\r
167 break;\r
77dcec12 168 case OperatorUnsignedLessThan:\r
169 case OperatorLessThan:\r
a405b86d 170 if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {\r
171 //\r
172 // string compare\r
173 //\r
174 if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) {\r
175 return (TRUE);\r
176 }\r
177 } else {\r
178 //\r
179 // numeric compare\r
180 //\r
181 if (Compare1[0] == L'-') {\r
77dcec12 182 Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);\r
a405b86d 183 } else {\r
77dcec12 184 Cmp1 = (INTN)ShellStrToUintn(Compare1);\r
a405b86d 185 }\r
186 if (Compare2[0] == L'-') {\r
77dcec12 187 Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);\r
a405b86d 188 } else {\r
77dcec12 189 Cmp2 = (INTN)ShellStrToUintn(Compare2);\r
a405b86d 190 }\r
77dcec12 191 if (BinOp == OperatorLessThan) {\r
a405b86d 192 if (Cmp1 < Cmp2) {\r
193 return (TRUE);\r
194 }\r
195 } else {\r
196 if ((UINTN)Cmp1 < (UINTN)Cmp2) {\r
197 return (TRUE);\r
198 }\r
199 }\r
200\r
201 }\r
202 return (FALSE);\r
203 break;\r
77dcec12 204 case OperatorEqual:\r
a405b86d 205 if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {\r
206 //\r
207 // string compare\r
208 //\r
209 if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) {\r
210 return (TRUE);\r
211 }\r
212 } else {\r
213 //\r
214 // numeric compare\r
215 //\r
216 if (Compare1[0] == L'-') {\r
217 Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);\r
218 } else {\r
219 Cmp1 = (INTN)ShellStrToUintn(Compare1);\r
220 }\r
221 if (Compare2[0] == L'-') {\r
222 Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);\r
223 } else {\r
224 Cmp2 = (INTN)ShellStrToUintn(Compare2);\r
225 }\r
226 if (Cmp1 == Cmp2) {\r
227 return (TRUE);\r
228 }\r
229 }\r
230 return (FALSE);\r
231 break;\r
77dcec12 232 case OperatorNotEqual:\r
a405b86d 233 if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {\r
234 //\r
235 // string compare\r
236 //\r
237 if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) {\r
238 return (TRUE);\r
239 }\r
240 } else {\r
241 //\r
242 // numeric compare\r
243 //\r
244 if (Compare1[0] == L'-') {\r
77dcec12 245 Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);\r
a405b86d 246 } else {\r
77dcec12 247 Cmp1 = (INTN)ShellStrToUintn(Compare1);\r
a405b86d 248 }\r
249 if (Compare2[0] == L'-') {\r
77dcec12 250 Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);\r
a405b86d 251 } else {\r
77dcec12 252 Cmp2 = (INTN)ShellStrToUintn(Compare2);\r
a405b86d 253 }\r
254 if (Cmp1 != Cmp2) {\r
255 return (TRUE);\r
256 }\r
257 }\r
258 return (FALSE);\r
259 break;\r
77dcec12 260 case OperatorUnsignedGreaterOrEqual:\r
261 case OperatorGreatorOrEqual:\r
a405b86d 262 if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {\r
263 //\r
264 // string compare\r
265 //\r
266 if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) {\r
267 return (TRUE);\r
268 }\r
269 } else {\r
270 //\r
271 // numeric compare\r
272 //\r
273 if (Compare1[0] == L'-') {\r
77dcec12 274 Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);\r
a405b86d 275 } else {\r
77dcec12 276 Cmp1 = (INTN)ShellStrToUintn(Compare1);\r
a405b86d 277 }\r
278 if (Compare2[0] == L'-') {\r
77dcec12 279 Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);\r
a405b86d 280 } else {\r
77dcec12 281 Cmp2 = (INTN)ShellStrToUintn(Compare2);\r
a405b86d 282 }\r
77dcec12 283 if (BinOp == OperatorGreatorOrEqual) {\r
a405b86d 284 if (Cmp1 >= Cmp2) {\r
285 return (TRUE);\r
286 }\r
287 } else {\r
288 if ((UINTN)Cmp1 >= (UINTN)Cmp2) {\r
289 return (TRUE);\r
290 }\r
291 }\r
292 }\r
293 return (FALSE);\r
294 break;\r
77dcec12 295 case OperatorLessOrEqual:\r
296 case OperatorUnsignedLessOrEqual:\r
a405b86d 297 if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {\r
298 //\r
299 // string compare\r
300 //\r
301 if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) {\r
302 return (TRUE);\r
303 }\r
304 } else {\r
305 //\r
306 // numeric compare\r
307 //\r
308 if (Compare1[0] == L'-') {\r
77dcec12 309 Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);\r
a405b86d 310 } else {\r
77dcec12 311 Cmp1 = (INTN)ShellStrToUintn(Compare1);\r
a405b86d 312 }\r
313 if (Compare2[0] == L'-') {\r
77dcec12 314 Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);\r
a405b86d 315 } else {\r
77dcec12 316 Cmp2 = (INTN)ShellStrToUintn(Compare2);\r
a405b86d 317 }\r
77dcec12 318 if (BinOp == OperatorLessOrEqual) {\r
a405b86d 319 if (Cmp1 <= Cmp2) {\r
320 return (TRUE);\r
321 }\r
322 } else {\r
323 if ((UINTN)Cmp1 <= (UINTN)Cmp2) {\r
324 return (TRUE);\r
325 }\r
326 }\r
327 }\r
328 return (FALSE);\r
329 break;\r
e9723321 330 default:\r
331 ASSERT(FALSE);\r
332 return (FALSE);\r
a405b86d 333 }\r
a405b86d 334}\r
335\r
77dcec12 336/**\r
337 Process an if statement and determine if its is valid or not.\r
338\r
339 @param[in,out] PassingState Opon entry, the current state. Upon exit, \r
340 the new state.\r
341 @param[in] StartParameterNumber The number of the first parameter of\r
342 this statement.\r
343 @param[in] EndParameterNumber The number of the final parameter of\r
344 this statement.\r
345 @param[in] OperatorToUse The type of termination operator.\r
346 @param[in] CaseInsensitive TRUE for case insensitive, FALSE otherwise.\r
347 @param[in] ForceStringCompare TRUE for all string based, FALSE otherwise.\r
348\r
349 @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
350 @retval EFI_SUCCESS The operation was successful. \r
351**/\r
a405b86d 352EFI_STATUS\r
353EFIAPI\r
354ProcessStatement (\r
355 IN OUT BOOLEAN *PassingState,\r
356 IN UINTN StartParameterNumber,\r
357 IN UINTN EndParameterNumber,\r
358 IN CONST END_TAG_TYPE OperatorToUse,\r
359 IN CONST BOOLEAN CaseInsensitive,\r
360 IN CONST BOOLEAN ForceStringCompare\r
361 )\r
362{\r
363 EFI_STATUS Status;\r
364 BOOLEAN OperationResult;\r
365 BOOLEAN NotPresent;\r
366 CHAR16 *StatementWalker;\r
367 BIN_OPERATOR_TYPE BinOp;\r
368 CHAR16 *Compare1;\r
369 CHAR16 *Compare2;\r
370 CHAR16 HexString[20];\r
371 CHAR16 *TempSpot;\r
372\r
77dcec12 373 ASSERT((END_TAG_TYPE)OperatorToUse != EndTagThen);\r
a405b86d 374\r
375 Status = EFI_SUCCESS;\r
77dcec12 376 BinOp = OperatorMax;\r
a405b86d 377 OperationResult = FALSE;\r
378 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];\r
379 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not")) {\r
380 NotPresent = TRUE;\r
381 StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber];\r
382 } else {\r
383 NotPresent = FALSE;\r
384 }\r
385\r
386 //\r
387 // now check for 'boolfunc' operators\r
388 //\r
389 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint")) {\r
390 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {\r
391 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;\r
392 OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE);\r
393 } else {\r
394 Status = EFI_INVALID_PARAMETER;\r
395 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint");\r
396 }\r
397 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists") || IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist")) {\r
398 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {\r
399 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;\r
400 //\r
401 // is what remains a file in CWD???\r
402 //\r
403 OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS);\r
404 } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) {\r
405 OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS);\r
406 } else {\r
407 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)");\r
408 Status = EFI_INVALID_PARAMETER;\r
409 }\r
410 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available")) {\r
411 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {\r
412 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;\r
413 //\r
414 // is what remains a file in the CWD or path???\r
415 //\r
416 OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS);\r
417 } else {\r
418 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available");\r
419 Status = EFI_INVALID_PARAMETER;\r
420 }\r
421 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile")) {\r
422 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {\r
423 //\r
424 // Chop off that ')'\r
425 //\r
426 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;\r
427 OperationResult = IsValidProfile(StatementWalker);\r
428 } else {\r
429 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile");\r
430 Status = EFI_INVALID_PARAMETER;\r
431 }\r
432 } else if (StartParameterNumber+1 >= EndParameterNumber) {\r
433 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]);\r
434 Status = EFI_INVALID_PARAMETER;\r
435 } else {\r
436 //\r
437 // must be 'item binop item' style\r
438 //\r
439 Compare1 = NULL;\r
440 Compare2 = NULL;\r
77dcec12 441 BinOp = OperatorMax;\r
a405b86d 442\r
443 //\r
444 // get the first item\r
445 //\r
446 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];\r
447 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {\r
448 TempSpot = StrStr(StatementWalker, L")");\r
449 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {\r
450 *TempSpot = CHAR_NULL;\r
451 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {\r
452 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);\r
453 ASSERT(Compare1 == NULL);\r
454 Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);\r
455 StatementWalker += StrLen(StatementWalker) + 1;\r
456 } else {\r
457 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
458 Status = EFI_INVALID_PARAMETER;\r
459 }\r
460 } else {\r
461 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
462 Status = EFI_INVALID_PARAMETER;\r
463 }\r
464 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {\r
465 TempSpot = StrStr(StatementWalker, L")");\r
466 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {\r
467 *TempSpot = CHAR_NULL;\r
468 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {\r
469 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));\r
470 ASSERT(Compare1 == NULL);\r
471 Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);\r
472 StatementWalker += StrLen(StatementWalker) + 1;\r
473 } else {\r
474 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
475 Status = EFI_INVALID_PARAMETER;\r
476 }\r
477 } else {\r
478 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
479 Status = EFI_INVALID_PARAMETER;\r
480 }\r
481 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {\r
482 TempSpot = StrStr(StatementWalker, L")");\r
483 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {\r
484 TempSpot = CHAR_NULL;\r
485 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {\r
486 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));\r
487 ASSERT(Compare1 == NULL);\r
488 Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);\r
489 StatementWalker += StrLen(StatementWalker) + 1;\r
490 } else {\r
491 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
492 Status = EFI_INVALID_PARAMETER;\r
493 }\r
494 } else {\r
495 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
496 Status = EFI_INVALID_PARAMETER;\r
497 }\r
498 } else {\r
499 ASSERT(Compare1 == NULL);\r
500 if (EndParameterNumber - StartParameterNumber > 2) {\r
501 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]);\r
502 Status = EFI_INVALID_PARAMETER;\r
503 } else {\r
504 //\r
505 // must be a raw string\r
506 //\r
507 Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0);\r
508 }\r
509 }\r
510\r
511 //\r
512 // get the operator\r
513 //\r
514 ASSERT(StartParameterNumber+1<EndParameterNumber);\r
515 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+1];\r
516 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt")) {\r
77dcec12 517 BinOp = OperatorGreaterThan;\r
a405b86d 518 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt")) {\r
77dcec12 519 BinOp = OperatorLessThan;\r
a405b86d 520 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq")) {\r
77dcec12 521 BinOp = OperatorEqual;\r
a405b86d 522 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne")) {\r
77dcec12 523 BinOp = OperatorNotEqual;\r
a405b86d 524 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge")) {\r
77dcec12 525 BinOp = OperatorGreatorOrEqual;\r
a405b86d 526 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le")) {\r
77dcec12 527 BinOp = OperatorLessOrEqual;\r
a405b86d 528 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==")) {\r
77dcec12 529 BinOp = OperatorEqual;\r
a405b86d 530 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt")) {\r
77dcec12 531 BinOp = OperatorUnisgnedGreaterThan;\r
a405b86d 532 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult")) {\r
77dcec12 533 BinOp = OperatorUnsignedLessThan;\r
a405b86d 534 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge")) {\r
77dcec12 535 BinOp = OperatorUnsignedGreaterOrEqual;\r
a405b86d 536 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule")) {\r
77dcec12 537 BinOp = OperatorUnsignedLessOrEqual;\r
a405b86d 538 } else {\r
539 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker);\r
540 Status = EFI_INVALID_PARAMETER;\r
541 }\r
542\r
543 //\r
544 // get the second item\r
545 //\r
546 ASSERT(StartParameterNumber+2<=EndParameterNumber);\r
547 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2];\r
548 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {\r
549 TempSpot = StrStr(StatementWalker, L")");\r
550 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {\r
551 TempSpot = CHAR_NULL;\r
552 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {\r
553 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);\r
554 ASSERT(Compare2 == NULL);\r
555 Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);\r
556 StatementWalker += StrLen(StatementWalker) + 1;\r
557 } else {\r
558 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
559 Status = EFI_INVALID_PARAMETER;\r
560 }\r
561 } else {\r
562 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
563 Status = EFI_INVALID_PARAMETER;\r
564 }\r
565 //\r
566 // can this be collapsed into the above?\r
567 //\r
568 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {\r
569 TempSpot = StrStr(StatementWalker, L")");\r
570 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {\r
571 TempSpot = CHAR_NULL;\r
572 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {\r
573 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));\r
574 ASSERT(Compare2 == NULL);\r
575 Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);\r
576 StatementWalker += StrLen(StatementWalker) + 1;\r
577 } else {\r
578 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
579 Status = EFI_INVALID_PARAMETER;\r
580 }\r
581 } else {\r
582 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
583 Status = EFI_INVALID_PARAMETER;\r
584 }\r
585 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {\r
586 TempSpot = StrStr(StatementWalker, L")");\r
587 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {\r
588 TempSpot = CHAR_NULL;\r
589 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {\r
590 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));\r
591 ASSERT(Compare2 == NULL);\r
592 Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);\r
593 StatementWalker += StrLen(StatementWalker) + 1;\r
594 } else {\r
595 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
596 Status = EFI_INVALID_PARAMETER;\r
597 }\r
598 } else {\r
599 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
600 Status = EFI_INVALID_PARAMETER;\r
601 }\r
602 } else {\r
603 //\r
604 // must be a raw string\r
605 //\r
606 ASSERT(Compare2 == NULL);\r
607 Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0);\r
608 }\r
609\r
77dcec12 610 if (Compare1 != NULL && Compare2 != NULL && BinOp != OperatorMax) {\r
a405b86d 611 OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare);\r
612 }\r
613\r
614 SHELL_FREE_NON_NULL(Compare1);\r
615 SHELL_FREE_NON_NULL(Compare2);\r
616 }\r
617\r
618 //\r
619 // done processing do result...\r
620 //\r
621\r
622 if (!EFI_ERROR(Status)) {\r
623 if (NotPresent) {\r
624 OperationResult = (BOOLEAN)(!OperationResult);\r
625 }\r
626 switch(OperatorToUse) {\r
77dcec12 627 case EndTagOr:\r
a405b86d 628 *PassingState = (BOOLEAN)(*PassingState || OperationResult);\r
629 break;\r
77dcec12 630 case EndTagAnd:\r
a405b86d 631 *PassingState = (BOOLEAN)(*PassingState && OperationResult);\r
632 break;\r
77dcec12 633 case EndTagMax:\r
a405b86d 634 *PassingState = (BOOLEAN)(OperationResult);\r
635 break;\r
636 default:\r
637 ASSERT(FALSE);\r
638 }\r
639 }\r
640 return (Status);\r
641}\r
642\r
77dcec12 643/**\r
644 Break up the next part of the if statement (until the next 'and', 'or', or 'then').\r
645\r
646 @param[in] ParameterNumber The current parameter number.\r
647 @param[out] EndParameter Upon successful return, will point to the \r
648 parameter to start the next iteration with.\r
649 @param[out] EndTag Upon successful return, will point to the \r
650 type that was found at the end of this statement.\r
651\r
652 @retval TRUE A valid statement was found.\r
653 @retval FALSE A valid statement was not found.\r
654**/\r
a405b86d 655BOOLEAN\r
656EFIAPI\r
657BuildNextStatement (\r
658 IN UINTN ParameterNumber,\r
659 OUT UINTN *EndParameter,\r
660 OUT END_TAG_TYPE *EndTag\r
661 )\r
662{\r
663 CHAR16 *Buffer;\r
664 UINTN BufferSize;\r
665\r
77dcec12 666 *EndTag = EndTagMax;\r
a405b86d 667\r
668 for(Buffer = NULL, BufferSize = 0\r
669 ; ParameterNumber < gEfiShellParametersProtocol->Argc\r
670 ; ParameterNumber++\r
671 ) {\r
672 if (gUnicodeCollation->StriColl(\r
673 gUnicodeCollation,\r
674 gEfiShellParametersProtocol->Argv[ParameterNumber],\r
675 L"or") == 0) {\r
676 *EndParameter = ParameterNumber - 1;\r
77dcec12 677 *EndTag = EndTagOr;\r
a405b86d 678 break;\r
679 } else if (gUnicodeCollation->StriColl(\r
680 gUnicodeCollation,\r
681 gEfiShellParametersProtocol->Argv[ParameterNumber],\r
682 L"and") == 0) {\r
683 *EndParameter = ParameterNumber - 1;\r
77dcec12 684 *EndTag = EndTagAnd;\r
a405b86d 685 break;\r
686 } else if (gUnicodeCollation->StriColl(\r
687 gUnicodeCollation,\r
688 gEfiShellParametersProtocol->Argv[ParameterNumber],\r
689 L"then") == 0) {\r
690 *EndParameter = ParameterNumber - 1;\r
77dcec12 691 *EndTag = EndTagThen;\r
a405b86d 692 break;\r
693 }\r
694 }\r
77dcec12 695 if (*EndTag == EndTagMax) {\r
a405b86d 696 return (FALSE);\r
697 }\r
698 return (TRUE);\r
699}\r
700\r
77dcec12 701/**\r
702 Move the script file pointer to a different place in the script file.\r
703 This one is special since it handles the if/else/endif syntax.\r
704\r
705 @param[in] ScriptFile The script file from GetCurrnetScriptFile().\r
706\r
707 @retval TRUE The move target was found and the move was successful.\r
708 @retval FALSE Something went wrong.\r
709**/\r
a405b86d 710BOOLEAN\r
711EFIAPI\r
712MoveToTagSpecial (\r
713 IN SCRIPT_FILE *ScriptFile\r
714 )\r
715{\r
716 SCRIPT_COMMAND_LIST *CommandNode;\r
717 BOOLEAN Found;\r
718 UINTN TargetCount;\r
719 CHAR16 *CommandName;\r
720 CHAR16 *CommandWalker;\r
721 CHAR16 *TempLocation;\r
722\r
723 TargetCount = 1;\r
724 Found = FALSE;\r
725\r
726 if (ScriptFile == NULL) {\r
727 return FALSE;\r
728 }\r
729\r
730 for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE\r
731 ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found\r
732 ; CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link)\r
733 ){\r
734\r
735 //\r
736 // get just the first part of the command line...\r
737 //\r
738 CommandName = NULL;\r
739 CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);\r
740 CommandWalker = CommandName;\r
741 while (CommandWalker[0] == L' ') {\r
742 CommandWalker++;\r
743 }\r
744 TempLocation = StrStr(CommandWalker, L" ");\r
745\r
746 if (TempLocation != NULL) {\r
747 *TempLocation = CHAR_NULL;\r
748 }\r
749\r
750 //\r
751 // did we find a nested item ?\r
752 //\r
753 if (gUnicodeCollation->StriColl(\r
754 gUnicodeCollation,\r
755 (CHAR16*)CommandWalker,\r
756 L"If") == 0) {\r
757 TargetCount++;\r
758 } else if (TargetCount == 1 && gUnicodeCollation->StriColl(\r
759 gUnicodeCollation,\r
760 (CHAR16*)CommandWalker,\r
761 (CHAR16*)L"else") == 0) {\r
762 //\r
763 // else can only decrement the last part... not an nested if\r
764 // hence the TargetCount compare added\r
765 //\r
766 TargetCount--;\r
767 } else if (gUnicodeCollation->StriColl(\r
768 gUnicodeCollation,\r
769 (CHAR16*)CommandWalker,\r
770 (CHAR16*)L"endif") == 0) {\r
771 TargetCount--;\r
772 }\r
773 if (TargetCount == 0) {\r
774 ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link);\r
775 Found = TRUE;\r
776 }\r
777\r
778 //\r
779 // Free the memory for this loop...\r
780 //\r
781 SHELL_FREE_NON_NULL(CommandName);\r
782 }\r
783 return (Found);\r
784}\r
785\r
77dcec12 786/**\r
787 Deal with the result of the if operation.\r
788\r
789 @param[in] Result The result of the if.\r
790\r
791 @retval EFI_SUCCESS The operation was successful.\r
792 @retval EFI_NOT_FOUND The ending tag could not be found.\r
793**/\r
a405b86d 794EFI_STATUS\r
795EFIAPI\r
796PerformResultOperation (\r
797 IN CONST BOOLEAN Result\r
798 )\r
799{\r
800 if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) {\r
801 return (EFI_SUCCESS);\r
802 }\r
803 return (EFI_NOT_FOUND);\r
804}\r
805\r
806/**\r
807 Function for 'if' command.\r
808\r
809 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
810 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
811**/\r
812SHELL_STATUS\r
813EFIAPI\r
814ShellCommandRunIf (\r
815 IN EFI_HANDLE ImageHandle,\r
816 IN EFI_SYSTEM_TABLE *SystemTable\r
817 )\r
818{\r
819 EFI_STATUS Status;\r
820 SHELL_STATUS ShellStatus;\r
821 BOOLEAN CaseInsensitive;\r
822 BOOLEAN ForceString;\r
823 UINTN CurrentParameter;\r
824 UINTN EndParameter;\r
825 BOOLEAN CurrentValue;\r
826 END_TAG_TYPE Ending;\r
827 END_TAG_TYPE PreviousEnding;\r
828\r
829\r
830 Status = CommandInit();\r
831 ASSERT_EFI_ERROR(Status);\r
832\r
833 if (!gEfiShellProtocol->BatchIsActive()) {\r
834 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"If");\r
835 return (SHELL_UNSUPPORTED);\r
836 }\r
837\r
838 if (gEfiShellParametersProtocol->Argc < 3) {\r
839 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle);\r
840 return (SHELL_INVALID_PARAMETER);\r
841 }\r
842\r
843 //\r
844 // Make sure that an End exists.\r
845 //\r
846 if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), TRUE, TRUE, FALSE)) {\r
33c031ee 847 ShellPrintHiiEx(\r
848 -1, \r
849 -1, \r
850 NULL, \r
851 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), \r
852 gShellLevel1HiiHandle, \r
853 L"EnfIf", \r
854 L"If", \r
855 ShellCommandGetCurrentScriptFile()!=NULL\r
856 &&ShellCommandGetCurrentScriptFile()->CurrentCommand!=NULL\r
857 ?ShellCommandGetCurrentScriptFile()->CurrentCommand->Line:0);\r
a405b86d 858 return (SHELL_DEVICE_ERROR);\r
859 }\r
860\r
861 //\r
862 // initialize the shell lib (we must be in non-auto-init...)\r
863 //\r
864 Status = ShellInitialize();\r
865 ASSERT_EFI_ERROR(Status);\r
866\r
867 CurrentParameter = 1;\r
868 EndParameter = 0;\r
869\r
870 if (gUnicodeCollation->StriColl(\r
871 gUnicodeCollation,\r
872 gEfiShellParametersProtocol->Argv[1],\r
873 L"/i") == 0 ||\r
874 gUnicodeCollation->StriColl(\r
875 gUnicodeCollation,\r
876 gEfiShellParametersProtocol->Argv[2],\r
877 L"/i") == 0 ||\r
878 (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(\r
879 gUnicodeCollation,\r
880 gEfiShellParametersProtocol->Argv[3],\r
881 L"/i") == 0)) {\r
882 CaseInsensitive = TRUE;\r
883 CurrentParameter++;\r
884 } else {\r
885 CaseInsensitive = FALSE;\r
886 }\r
887 if (gUnicodeCollation->StriColl(\r
888 gUnicodeCollation,\r
889 gEfiShellParametersProtocol->Argv[1],\r
890 L"/s") == 0 ||\r
891 gUnicodeCollation->StriColl(\r
892 gUnicodeCollation,\r
893 gEfiShellParametersProtocol->Argv[2],\r
894 L"/s") == 0 ||\r
895 (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(\r
896 gUnicodeCollation,\r
897 gEfiShellParametersProtocol->Argv[3],\r
898 L"/s") == 0)) {\r
899 ForceString = TRUE;\r
900 CurrentParameter++;\r
901 } else {\r
902 ForceString = FALSE;\r
903 }\r
904\r
77dcec12 905 for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = EndTagMax\r
a405b86d 906 ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS\r
907 ; CurrentParameter++) {\r
908 if (gUnicodeCollation->StriColl(\r
909 gUnicodeCollation,\r
910 gEfiShellParametersProtocol->Argv[CurrentParameter],\r
911 L"then") == 0) {\r
912 //\r
913 // we are at the then\r
914 //\r
915 if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) {\r
916 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle);\r
917 ShellStatus = SHELL_INVALID_PARAMETER;\r
918 } else {\r
919 Status = PerformResultOperation(CurrentValue);\r
920 if (EFI_ERROR(Status)) {\r
921 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);\r
922 ShellStatus = SHELL_INVALID_PARAMETER;\r
923 }\r
924 }\r
925 } else {\r
926 PreviousEnding = Ending;\r
927 //\r
928 // build up the next statement for analysis\r
929 //\r
930 if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) {\r
931 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"Then", L"If", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
932 ShellStatus = SHELL_INVALID_PARAMETER;\r
933 } else {\r
934 //\r
935 // Analyze the statement\r
936 //\r
937 Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString);\r
938 if (EFI_ERROR(Status)) {\r
939// ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);\r
940 ShellStatus = SHELL_INVALID_PARAMETER;\r
941 } else {\r
942 //\r
943 // Optomize to get out of the loop early...\r
944 //\r
77dcec12 945 if ((Ending == EndTagOr && CurrentValue) || (Ending == EndTagAnd && !CurrentValue)) {\r
a405b86d 946 Status = PerformResultOperation(CurrentValue);\r
947 if (EFI_ERROR(Status)) {\r
948 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);\r
949 ShellStatus = SHELL_INVALID_PARAMETER;\r
950 }\r
951 break;\r
952 }\r
953 }\r
954 }\r
955 if (ShellStatus == SHELL_SUCCESS){\r
956 CurrentParameter = EndParameter;\r
957 //\r
958 // Skip over the or or and parameter.\r
959 //\r
77dcec12 960 if (Ending == EndTagOr || Ending == EndTagAnd) {\r
a405b86d 961 CurrentParameter++;\r
962 }\r
963 }\r
964 }\r
965 }\r
966 return (ShellStatus);\r
967}\r
968\r
969/**\r
970 Function for 'else' command.\r
971\r
972 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
973 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
974**/\r
975SHELL_STATUS\r
976EFIAPI\r
977ShellCommandRunElse (\r
978 IN EFI_HANDLE ImageHandle,\r
979 IN EFI_SYSTEM_TABLE *SystemTable\r
980 )\r
981{\r
982 ASSERT_EFI_ERROR(CommandInit());\r
983\r
984 if (gEfiShellParametersProtocol->Argc > 1) {\r
985 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);\r
986 return (SHELL_INVALID_PARAMETER);\r
987 }\r
988\r
989 if (!gEfiShellProtocol->BatchIsActive()) {\r
990 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else");\r
991 return (SHELL_UNSUPPORTED);\r
992 }\r
993\r
994\r
995 if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {\r
33c031ee 996 ShellPrintHiiEx(\r
997 -1, \r
998 -1, \r
999 NULL, \r
1000 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), \r
1001 gShellLevel1HiiHandle, \r
1002 L"If", \r
1003 L"Else", \r
1004 ShellCommandGetCurrentScriptFile()!=NULL\r
1005 &&ShellCommandGetCurrentScriptFile()->CurrentCommand!=NULL\r
1006 ?ShellCommandGetCurrentScriptFile()->CurrentCommand->Line:0);\r
a405b86d 1007 return (SHELL_DEVICE_ERROR);\r
1008 }\r
1009 if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {\r
33c031ee 1010 ShellPrintHiiEx(\r
1011 -1, \r
1012 -1, \r
1013 NULL, \r
1014 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), \r
1015 gShellLevel1HiiHandle, \r
1016 L"If", \r
1017 L"Else", \r
1018 ShellCommandGetCurrentScriptFile()!=NULL\r
1019 &&ShellCommandGetCurrentScriptFile()->CurrentCommand!=NULL\r
1020 ?ShellCommandGetCurrentScriptFile()->CurrentCommand->Line:0);\r
a405b86d 1021 return (SHELL_DEVICE_ERROR);\r
1022 }\r
1023\r
1024 if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE)) {\r
33c031ee 1025 ShellPrintHiiEx(\r
1026 -1, \r
1027 -1, \r
1028 NULL, \r
1029 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), \r
1030 gShellLevel1HiiHandle, \r
1031 L"EndIf", \r
1032 "Else", \r
1033 ShellCommandGetCurrentScriptFile()!=NULL\r
1034 &&ShellCommandGetCurrentScriptFile()->CurrentCommand!=NULL\r
1035 ?ShellCommandGetCurrentScriptFile()->CurrentCommand->Line:0);\r
a405b86d 1036 return (SHELL_DEVICE_ERROR);\r
1037 }\r
1038\r
1039 return (SHELL_SUCCESS);\r
1040}\r
1041\r
1042/**\r
1043 Function for 'endif' command.\r
1044\r
1045 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
1046 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
1047**/\r
1048SHELL_STATUS\r
1049EFIAPI\r
1050ShellCommandRunEndIf (\r
1051 IN EFI_HANDLE ImageHandle,\r
1052 IN EFI_SYSTEM_TABLE *SystemTable\r
1053 )\r
1054{\r
1055 ASSERT_EFI_ERROR(CommandInit());\r
1056\r
1057 if (gEfiShellParametersProtocol->Argc > 1) {\r
1058 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);\r
1059 return (SHELL_INVALID_PARAMETER);\r
1060 }\r
1061\r
1062 if (!gEfiShellProtocol->BatchIsActive()) {\r
1063 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif");\r
1064 return (SHELL_UNSUPPORTED);\r
1065 }\r
1066\r
1067 if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {\r
33c031ee 1068 ShellPrintHiiEx(\r
1069 -1, \r
1070 -1, \r
1071 NULL, \r
1072 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), \r
1073 gShellLevel1HiiHandle, \r
1074 L"If", \r
1075 L"EndIf", \r
1076 ShellCommandGetCurrentScriptFile()!=NULL\r
1077 &&ShellCommandGetCurrentScriptFile()->CurrentCommand!=NULL\r
1078 ?ShellCommandGetCurrentScriptFile()->CurrentCommand->Line:0);\r
a405b86d 1079 return (SHELL_DEVICE_ERROR);\r
1080 }\r
1081\r
1082 return (SHELL_SUCCESS);\r
1083}\r