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