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