]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
7f6ff67f58cd58797e7a0f7d44c086fe6b86207f
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / IfrParse.c
1 /** @file
2 Parser for IFR binary encoding.
3
4 Copyright (c) 2007 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Setup.h"
16 #include "Ui.h"
17
18 UINT16 mStatementIndex;
19 UINT16 mExpressionOpCodeIndex;
20
21 BOOLEAN mInScopeSubtitle;
22 BOOLEAN mInScopeSuppress;
23 BOOLEAN mInScopeGrayOut;
24 BOOLEAN mInScopeDisable;
25 FORM_EXPRESSION *mSuppressExpression;
26 FORM_EXPRESSION *mGrayOutExpression;
27 FORM_EXPRESSION *mDisableExpression;
28
29 /**
30 Initialize Statement header members.
31
32 @param OpCodeData Pointer of the raw OpCode data.
33 @param FormSet Pointer of the current FormSe.
34 @param Form Pointer of the current Form.
35
36 @return The Statement.
37
38 **/
39 FORM_BROWSER_STATEMENT *
40 CreateStatement (
41 IN UINT8 *OpCodeData,
42 IN OUT FORM_BROWSER_FORMSET *FormSet,
43 IN OUT FORM_BROWSER_FORM *Form
44 )
45 {
46 FORM_BROWSER_STATEMENT *Statement;
47 EFI_IFR_STATEMENT_HEADER *StatementHdr;
48
49 if (Form == NULL) {
50 //
51 // We are currently not in a Form Scope, so just skip this Statement
52 //
53 return NULL;
54 }
55
56 Statement = &FormSet->StatementBuffer[mStatementIndex];
57 mStatementIndex++;
58
59 InitializeListHead (&Statement->DefaultListHead);
60 InitializeListHead (&Statement->OptionListHead);
61 InitializeListHead (&Statement->InconsistentListHead);
62 InitializeListHead (&Statement->NoSubmitListHead);
63
64 Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
65
66 Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
67
68 StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
69 CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
70 CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
71
72 if (mInScopeSuppress) {
73 Statement->SuppressExpression = mSuppressExpression;
74 }
75
76 if (mInScopeGrayOut) {
77 Statement->GrayOutExpression = mGrayOutExpression;
78 }
79
80
81 if (mInScopeDisable) {
82 Statement->DisableExpression = mDisableExpression;
83 }
84
85 Statement->InSubtitle = mInScopeSubtitle;
86
87 //
88 // Insert this Statement into current Form
89 //
90 InsertTailList (&Form->StatementListHead, &Statement->Link);
91
92 return Statement;
93 }
94
95 /**
96 Convert a numeric value to a Unicode String and insert it to String Package.
97 This string is used as the Unicode Name for the EFI Variable. This is to support
98 the deprecated vareqval opcode.
99
100 @param FormSet The FormSet.
101 @param Statement The numeric question whose VarStoreInfo.VarName is the
102 numeric value which is used to produce the Unicode Name
103 for the EFI Variable.
104
105 If the Statement is NULL, the ASSERT.
106 If the opcode is not Numeric, then ASSERT.
107
108 @retval EFI_SUCCESS The funtion always succeeds.
109 **/
110 EFI_STATUS
111 UpdateCheckBoxStringToken (
112 IN CONST FORM_BROWSER_FORMSET *FormSet,
113 IN FORM_BROWSER_STATEMENT *Statement
114 )
115 {
116 CHAR16 Str[MAXIMUM_VALUE_CHARACTERS];
117 EFI_STRING_ID Id;
118
119 ASSERT (Statement != NULL);
120 ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP);
121
122 UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1);
123
124 Id = HiiSetString (FormSet->HiiHandle, 0, Str, NULL);
125 if (Id == 0) {
126 return EFI_OUT_OF_RESOURCES;
127 }
128
129 Statement->VarStoreInfo.VarName = Id;
130
131 return EFI_SUCCESS;
132 }
133
134 /**
135 Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME.
136
137 @param OpCodeData The current opcode.
138
139 @retval TRUE Yes.
140 @retval FALSE No.
141 **/
142 BOOLEAN
143 IsNextOpCodeGuidedVarEqName (
144 IN UINT8 *OpCodeData
145 )
146 {
147 //
148 // Get next opcode
149 //
150 OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
151 if (*OpCodeData == EFI_IFR_GUID_OP) {
152 if (CompareGuid (&gEfiIfrFrameworkGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
153 //
154 // Specific GUIDed opcodes to support IFR generated from Framework HII VFR
155 //
156 if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) {
157 return TRUE;
158 }
159 }
160 }
161
162 return FALSE;
163 }
164
165 /**
166 Initialize Question's members.
167
168 @param OpCodeData Pointer of the raw OpCode data.
169 @param FormSet Pointer of the current FormSet.
170 @param Form Pointer of the current Form.
171
172 @return The Question.
173
174 **/
175 FORM_BROWSER_STATEMENT *
176 CreateQuestion (
177 IN UINT8 *OpCodeData,
178 IN OUT FORM_BROWSER_FORMSET *FormSet,
179 IN OUT FORM_BROWSER_FORM *Form
180 )
181 {
182 FORM_BROWSER_STATEMENT *Statement;
183 EFI_IFR_QUESTION_HEADER *QuestionHdr;
184 LIST_ENTRY *Link;
185 FORMSET_STORAGE *Storage;
186 NAME_VALUE_NODE *NameValueNode;
187 EFI_STATUS Status;
188
189 Statement = CreateStatement (OpCodeData, FormSet, Form);
190 if (Statement == NULL) {
191 return NULL;
192 }
193
194 QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
195 CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
196 CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
197 CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
198
199 Statement->QuestionFlags = QuestionHdr->Flags;
200
201 if (Statement->VarStoreId == 0) {
202 //
203 // VarStoreId of zero indicates no variable storage
204 //
205 return Statement;
206 }
207
208 //
209 // Take a look at next OpCode to see whether it is a GUIDed opcode to support
210 // Framework Compatibility
211 //
212 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
213 if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {
214 Status = UpdateCheckBoxStringToken (FormSet, Statement);
215 if (EFI_ERROR (Status)) {
216 return NULL;
217 }
218 }
219 }
220
221 //
222 // Find Storage for this Question
223 //
224 Link = GetFirstNode (&FormSet->StorageListHead);
225 while (!IsNull (&FormSet->StorageListHead, Link)) {
226 Storage = FORMSET_STORAGE_FROM_LINK (Link);
227
228 if (Storage->VarStoreId == Statement->VarStoreId) {
229 Statement->Storage = Storage;
230 break;
231 }
232
233 Link = GetNextNode (&FormSet->StorageListHead, Link);
234 }
235 ASSERT (Statement->Storage != NULL);
236
237 //
238 // Initialilze varname for Name/Value or EFI Variable
239 //
240 if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
241 (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
242 Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);
243 ASSERT (Statement->VariableName != NULL);
244
245 if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
246 //
247 // Insert to Name/Value varstore list
248 //
249 NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
250 ASSERT (NameValueNode != NULL);
251 NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
252 NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
253 ASSERT (NameValueNode->Name != NULL);
254 NameValueNode->Value = AllocateZeroPool (0x10);
255 ASSERT (NameValueNode->Value != NULL);
256 NameValueNode->EditValue = AllocateZeroPool (0x10);
257 ASSERT (NameValueNode->EditValue != NULL);
258
259 InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
260 }
261 }
262
263 return Statement;
264 }
265
266
267 /**
268 Allocate a FORM_EXPRESSION node.
269
270 @param Form The Form associated with this Expression
271
272 @return Pointer to a FORM_EXPRESSION data structure.
273
274 **/
275 FORM_EXPRESSION *
276 CreateExpression (
277 IN OUT FORM_BROWSER_FORM *Form
278 )
279 {
280 FORM_EXPRESSION *Expression;
281
282 Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
283 ASSERT (Expression != NULL);
284 Expression->Signature = FORM_EXPRESSION_SIGNATURE;
285 InitializeListHead (&Expression->OpCodeListHead);
286
287 return Expression;
288 }
289
290
291 /**
292 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
293
294 @param FormSet Pointer of the current FormSet
295
296 @return Pointer to a FORMSET_STORAGE data structure.
297
298 **/
299 FORMSET_STORAGE *
300 CreateStorage (
301 IN FORM_BROWSER_FORMSET *FormSet
302 )
303 {
304 FORMSET_STORAGE *Storage;
305
306 Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
307 ASSERT (Storage != NULL);
308 Storage->Signature = FORMSET_STORAGE_SIGNATURE;
309 InitializeListHead (&Storage->NameValueListHead);
310 InsertTailList (&FormSet->StorageListHead, &Storage->Link);
311
312 return Storage;
313 }
314
315
316 /**
317 Create ConfigHdr string for a storage.
318
319 @param FormSet Pointer of the current FormSet
320 @param Storage Pointer of the storage
321
322 @retval EFI_SUCCESS Initialize ConfigHdr success
323
324 **/
325 EFI_STATUS
326 InitializeConfigHdr (
327 IN FORM_BROWSER_FORMSET *FormSet,
328 IN OUT FORMSET_STORAGE *Storage
329 )
330 {
331 CHAR16 *Name;
332
333 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
334 Name = Storage->Name;
335 } else {
336 Name = NULL;
337 }
338
339 Storage->ConfigHdr = HiiConstructConfigHdr (
340 &Storage->Guid,
341 Name,
342 FormSet->DriverHandle
343 );
344
345 if (Storage->ConfigHdr == NULL) {
346 return EFI_NOT_FOUND;
347 }
348
349 Storage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);
350 Storage->SpareStrLen = 0;
351
352 return EFI_SUCCESS;
353 }
354
355
356 /**
357 Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
358
359 @param FormSet Pointer of the current FormSet.
360 @param Question The Question to be initialized.
361
362 @retval EFI_SUCCESS Function success.
363 @retval EFI_INVALID_PARAMETER No storage associated with the Question.
364
365 **/
366 EFI_STATUS
367 InitializeRequestElement (
368 IN OUT FORM_BROWSER_FORMSET *FormSet,
369 IN OUT FORM_BROWSER_STATEMENT *Question
370 )
371 {
372 FORMSET_STORAGE *Storage;
373 UINTN StrLen;
374 UINTN StringSize;
375 CHAR16 *NewStr;
376 CHAR16 RequestElement[30];
377
378 Storage = Question->Storage;
379 if (Storage == NULL) {
380 return EFI_INVALID_PARAMETER;
381 }
382
383 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
384 //
385 // <ConfigRequest> is unnecessary for EFI variable storage,
386 // GetVariable()/SetVariable() will be used to retrieve/save values
387 //
388 return EFI_SUCCESS;
389 }
390
391 //
392 // Prepare <RequestElement>
393 //
394 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
395 StrLen = UnicodeSPrint (
396 RequestElement,
397 30 * sizeof (CHAR16),
398 L"&OFFSET=%x&WIDTH=%x",
399 Question->VarStoreInfo.VarOffset,
400 Question->StorageWidth
401 );
402 Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);
403 } else {
404 StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
405 }
406
407 if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
408 //
409 // Password with CALLBACK flag is stored in encoded format,
410 // so don't need to append it to <ConfigRequest>
411 //
412 return EFI_SUCCESS;
413 }
414
415 //
416 // Append <RequestElement> to <ConfigRequest>
417 //
418 if (StrLen > Storage->SpareStrLen) {
419 //
420 // Old String buffer is not sufficient for RequestElement, allocate a new one
421 //
422 StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);
423 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
424 ASSERT (NewStr != NULL);
425 if (Storage->ConfigRequest != NULL) {
426 CopyMem (NewStr, Storage->ConfigRequest, StringSize);
427 FreePool (Storage->ConfigRequest);
428 }
429 Storage->ConfigRequest = NewStr;
430 Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
431 }
432
433 StrCat (Storage->ConfigRequest, RequestElement);
434 Storage->ElementCount++;
435 Storage->SpareStrLen -= StrLen;
436
437 return EFI_SUCCESS;
438 }
439
440
441 /**
442 Free resources of a Expression.
443
444 @param FormSet Pointer of the Expression
445
446 **/
447 VOID
448 DestroyExpression (
449 IN FORM_EXPRESSION *Expression
450 )
451 {
452 LIST_ENTRY *Link;
453 EXPRESSION_OPCODE *OpCode;
454
455 while (!IsListEmpty (&Expression->OpCodeListHead)) {
456 Link = GetFirstNode (&Expression->OpCodeListHead);
457 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
458 RemoveEntryList (&OpCode->Link);
459
460 if (OpCode->ValueList != NULL) {
461 FreePool (OpCode->ValueList);
462 }
463 }
464
465 //
466 // Free this Expression
467 //
468 FreePool (Expression);
469 }
470
471
472 /**
473 Free resources of a storage.
474
475 @param Storage Pointer of the storage
476
477 **/
478 VOID
479 DestroyStorage (
480 IN FORMSET_STORAGE *Storage
481 )
482 {
483 LIST_ENTRY *Link;
484 NAME_VALUE_NODE *NameValueNode;
485
486 if (Storage == NULL) {
487 return;
488 }
489
490 if (Storage->Name != NULL) {
491 FreePool (Storage->Name);
492 }
493 if (Storage->Buffer != NULL) {
494 FreePool (Storage->Buffer);
495 }
496 if (Storage->EditBuffer != NULL) {
497 FreePool (Storage->EditBuffer);
498 }
499
500 while (!IsListEmpty (&Storage->NameValueListHead)) {
501 Link = GetFirstNode (&Storage->NameValueListHead);
502 NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
503 RemoveEntryList (&NameValueNode->Link);
504
505 if (NameValueNode->Name != NULL) {
506 FreePool (NameValueNode->Name);
507 }
508 if (NameValueNode->Value != NULL) {
509 FreePool (NameValueNode->Value);
510 }
511 if (NameValueNode->EditValue != NULL) {
512 FreePool (NameValueNode->EditValue);
513 }
514 FreePool (NameValueNode);
515 }
516
517 if (Storage->ConfigHdr != NULL) {
518 FreePool (Storage->ConfigHdr);
519 }
520 if (Storage->ConfigRequest != NULL) {
521 FreePool (Storage->ConfigRequest);
522 }
523
524 FreePool (Storage);
525 }
526
527
528 /**
529 Free resources of a Statement.
530
531 @param Statement Pointer of the Statement
532
533 **/
534 VOID
535 DestroyStatement (
536 IN OUT FORM_BROWSER_STATEMENT *Statement
537 )
538 {
539 LIST_ENTRY *Link;
540 QUESTION_DEFAULT *Default;
541 QUESTION_OPTION *Option;
542 FORM_EXPRESSION *Expression;
543
544 //
545 // Free Default value List
546 //
547 while (!IsListEmpty (&Statement->DefaultListHead)) {
548 Link = GetFirstNode (&Statement->DefaultListHead);
549 Default = QUESTION_DEFAULT_FROM_LINK (Link);
550 RemoveEntryList (&Default->Link);
551
552 FreePool (Default);
553 }
554
555 //
556 // Free Options List
557 //
558 while (!IsListEmpty (&Statement->OptionListHead)) {
559 Link = GetFirstNode (&Statement->OptionListHead);
560 Option = QUESTION_OPTION_FROM_LINK (Link);
561 RemoveEntryList (&Option->Link);
562
563 FreePool (Option);
564 }
565
566 //
567 // Free Inconsistent List
568 //
569 while (!IsListEmpty (&Statement->InconsistentListHead)) {
570 Link = GetFirstNode (&Statement->InconsistentListHead);
571 Expression = FORM_EXPRESSION_FROM_LINK (Link);
572 RemoveEntryList (&Expression->Link);
573
574 DestroyExpression (Expression);
575 }
576
577 //
578 // Free NoSubmit List
579 //
580 while (!IsListEmpty (&Statement->NoSubmitListHead)) {
581 Link = GetFirstNode (&Statement->NoSubmitListHead);
582 Expression = FORM_EXPRESSION_FROM_LINK (Link);
583 RemoveEntryList (&Expression->Link);
584
585 DestroyExpression (Expression);
586 }
587
588 if (Statement->VariableName != NULL) {
589 FreePool (Statement->VariableName);
590 }
591 if (Statement->BlockName != NULL) {
592 FreePool (Statement->BlockName);
593 }
594 }
595
596
597 /**
598 Free resources of a Form.
599
600 @param Form Pointer of the Form.
601
602 **/
603 VOID
604 DestroyForm (
605 IN OUT FORM_BROWSER_FORM *Form
606 )
607 {
608 LIST_ENTRY *Link;
609 FORM_EXPRESSION *Expression;
610 FORM_BROWSER_STATEMENT *Statement;
611
612 //
613 // Free Form Expressions
614 //
615 while (!IsListEmpty (&Form->ExpressionListHead)) {
616 Link = GetFirstNode (&Form->ExpressionListHead);
617 Expression = FORM_EXPRESSION_FROM_LINK (Link);
618 RemoveEntryList (&Expression->Link);
619
620 DestroyExpression (Expression);
621 }
622
623 //
624 // Free Statements/Questions
625 //
626 while (!IsListEmpty (&Form->StatementListHead)) {
627 Link = GetFirstNode (&Form->StatementListHead);
628 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
629 RemoveEntryList (&Statement->Link);
630
631 DestroyStatement (Statement);
632 }
633
634 //
635 // Free this Form
636 //
637 FreePool (Form);
638 }
639
640
641 /**
642 Free resources allocated for a FormSet.
643
644 @param FormSet Pointer of the FormSet
645
646 **/
647 VOID
648 DestroyFormSet (
649 IN OUT FORM_BROWSER_FORMSET *FormSet
650 )
651 {
652 LIST_ENTRY *Link;
653 FORMSET_STORAGE *Storage;
654 FORMSET_DEFAULTSTORE *DefaultStore;
655 FORM_EXPRESSION *Expression;
656 FORM_BROWSER_FORM *Form;
657
658 if (FormSet->IfrBinaryData == NULL) {
659 //
660 // Uninitialized FormSet
661 //
662 FreePool (FormSet);
663 return;
664 }
665
666 //
667 // Free IFR binary buffer
668 //
669 FreePool (FormSet->IfrBinaryData);
670
671 //
672 // Free FormSet Storage
673 //
674 if (FormSet->StorageListHead.ForwardLink != NULL) {
675 while (!IsListEmpty (&FormSet->StorageListHead)) {
676 Link = GetFirstNode (&FormSet->StorageListHead);
677 Storage = FORMSET_STORAGE_FROM_LINK (Link);
678 RemoveEntryList (&Storage->Link);
679
680 DestroyStorage (Storage);
681 }
682 }
683
684 //
685 // Free FormSet Default Store
686 //
687 if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
688 while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
689 Link = GetFirstNode (&FormSet->DefaultStoreListHead);
690 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
691 RemoveEntryList (&DefaultStore->Link);
692
693 FreePool (DefaultStore);
694 }
695 }
696
697 //
698 // Free Formset Expressions
699 //
700 while (!IsListEmpty (&FormSet->ExpressionListHead)) {
701 Link = GetFirstNode (&FormSet->ExpressionListHead);
702 Expression = FORM_EXPRESSION_FROM_LINK (Link);
703 RemoveEntryList (&Expression->Link);
704
705 DestroyExpression (Expression);
706 }
707
708 //
709 // Free Forms
710 //
711 if (FormSet->FormListHead.ForwardLink != NULL) {
712 while (!IsListEmpty (&FormSet->FormListHead)) {
713 Link = GetFirstNode (&FormSet->FormListHead);
714 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
715 RemoveEntryList (&Form->Link);
716
717 DestroyForm (Form);
718 }
719 }
720
721 if (FormSet->StatementBuffer != NULL) {
722 FreePool (FormSet->StatementBuffer);
723 }
724 if (FormSet->ExpressionBuffer != NULL) {
725 FreePool (FormSet->ExpressionBuffer);
726 }
727
728 FreePool (FormSet);
729 }
730
731
732 /**
733 Tell whether this Operand is an Expression OpCode or not
734
735 @param Operand Operand of an IFR OpCode.
736
737 @retval TRUE This is an Expression OpCode.
738 @retval FALSE Not an Expression OpCode.
739
740 **/
741 BOOLEAN
742 IsExpressionOpCode (
743 IN UINT8 Operand
744 )
745 {
746 if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
747 ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
748 (Operand == EFI_IFR_CATENATE_OP) ||
749 (Operand == EFI_IFR_TO_LOWER_OP) ||
750 (Operand == EFI_IFR_TO_UPPER_OP) ||
751 (Operand == EFI_IFR_VERSION_OP)
752 ) {
753 return TRUE;
754 } else {
755 return FALSE;
756 }
757 }
758
759
760 /**
761 Calculate number of Statemens(Questions) and Expression OpCodes.
762
763 @param FormSet The FormSet to be counted.
764 @param NumberOfStatement Number of Statemens(Questions)
765 @param NumberOfExpression Number of Expression OpCodes
766
767 **/
768 VOID
769 CountOpCodes (
770 IN FORM_BROWSER_FORMSET *FormSet,
771 IN OUT UINT16 *NumberOfStatement,
772 IN OUT UINT16 *NumberOfExpression
773 )
774 {
775 UINT16 StatementCount;
776 UINT16 ExpressionCount;
777 UINT8 *OpCodeData;
778 UINTN Offset;
779 UINTN OpCodeLen;
780
781 Offset = 0;
782 StatementCount = 0;
783 ExpressionCount = 0;
784
785 while (Offset < FormSet->IfrBinaryLength) {
786 OpCodeData = FormSet->IfrBinaryData + Offset;
787 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
788 Offset += OpCodeLen;
789
790 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
791 ExpressionCount++;
792 } else {
793 StatementCount++;
794 }
795 }
796
797 *NumberOfStatement = StatementCount;
798 *NumberOfExpression = ExpressionCount;
799 }
800
801
802
803 /**
804 Parse opcodes in the formset IFR binary.
805
806 @param FormSet Pointer of the FormSet data structure.
807
808 @retval EFI_SUCCESS Opcode parse success.
809 @retval Other Opcode parse fail.
810
811 **/
812 EFI_STATUS
813 ParseOpCodes (
814 IN FORM_BROWSER_FORMSET *FormSet
815 )
816 {
817 EFI_STATUS Status;
818 UINT16 Index;
819 FORM_BROWSER_FORM *CurrentForm;
820 FORM_BROWSER_STATEMENT *CurrentStatement;
821 EXPRESSION_OPCODE *ExpressionOpCode;
822 FORM_EXPRESSION *CurrentExpression;
823 UINT8 Operand;
824 UINT8 Scope;
825 UINTN OpCodeOffset;
826 UINTN OpCodeLength;
827 UINT8 *OpCodeData;
828 UINT8 ScopeOpCode;
829 FORMSET_STORAGE *Storage;
830 FORMSET_DEFAULTSTORE *DefaultStore;
831 QUESTION_DEFAULT *CurrentDefault;
832 QUESTION_OPTION *CurrentOption;
833 UINT8 Width;
834 CHAR8 *AsciiString;
835 UINT16 NumberOfStatement;
836 UINT16 NumberOfExpression;
837 EFI_IMAGE_ID *ImageId;
838 BOOLEAN SuppressForQuestion;
839 BOOLEAN SuppressForOption;
840 BOOLEAN InScopeOptionSuppress;
841 FORM_EXPRESSION *OptionSuppressExpression;
842 BOOLEAN InScopeFormSuppress;
843 FORM_EXPRESSION *FormSuppressExpression;
844 UINT16 DepthOfDisable;
845 BOOLEAN OpCodeDisabled;
846 BOOLEAN SingleOpCodeExpression;
847 BOOLEAN InScopeDefault;
848 EFI_HII_VALUE *Value;
849
850 mInScopeSubtitle = FALSE;
851 SuppressForQuestion = FALSE;
852 SuppressForOption = FALSE;
853 InScopeFormSuppress = FALSE;
854 mInScopeSuppress = FALSE;
855 InScopeOptionSuppress = FALSE;
856 mInScopeGrayOut = FALSE;
857 mInScopeDisable = FALSE;
858 DepthOfDisable = 0;
859 OpCodeDisabled = FALSE;
860 SingleOpCodeExpression = FALSE;
861 InScopeDefault = FALSE;
862 CurrentExpression = NULL;
863 CurrentDefault = NULL;
864 CurrentOption = NULL;
865 OptionSuppressExpression = NULL;
866 FormSuppressExpression = NULL;
867 ImageId = NULL;
868
869 //
870 // Get the number of Statements and Expressions
871 //
872 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
873
874 mStatementIndex = 0;
875 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
876 if (FormSet->StatementBuffer == NULL) {
877 return EFI_OUT_OF_RESOURCES;
878 }
879
880 mExpressionOpCodeIndex = 0;
881 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
882 if (FormSet->ExpressionBuffer == NULL) {
883 return EFI_OUT_OF_RESOURCES;
884 }
885
886 InitializeListHead (&FormSet->StorageListHead);
887 InitializeListHead (&FormSet->DefaultStoreListHead);
888 InitializeListHead (&FormSet->FormListHead);
889
890 CurrentForm = NULL;
891 CurrentStatement = NULL;
892
893 ResetScopeStack ();
894
895 OpCodeOffset = 0;
896 while (OpCodeOffset < FormSet->IfrBinaryLength) {
897 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
898
899 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
900 OpCodeOffset += OpCodeLength;
901 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
902 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
903
904 //
905 // If scope bit set, push onto scope stack
906 //
907 if (Scope != 0) {
908 PushScope (Operand);
909 }
910
911 if (OpCodeDisabled) {
912 //
913 // DisableIf Expression is evaluated to be TRUE, try to find its end.
914 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
915 //
916 if (Operand == EFI_IFR_DISABLE_IF_OP) {
917 DepthOfDisable++;
918 } else if (Operand == EFI_IFR_END_OP) {
919 Status = PopScope (&ScopeOpCode);
920 if (EFI_ERROR (Status)) {
921 return Status;
922 }
923
924 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
925 if (DepthOfDisable == 0) {
926 mInScopeDisable = FALSE;
927 OpCodeDisabled = FALSE;
928 } else {
929 DepthOfDisable--;
930 }
931 }
932 }
933 continue;
934 }
935
936 if (IsExpressionOpCode (Operand)) {
937 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
938 mExpressionOpCodeIndex++;
939
940 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
941 ExpressionOpCode->Operand = Operand;
942 Value = &ExpressionOpCode->Value;
943
944 switch (Operand) {
945 case EFI_IFR_EQ_ID_VAL_OP:
946 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
947
948 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
949 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
950 break;
951
952 case EFI_IFR_EQ_ID_ID_OP:
953 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
954 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
955 break;
956
957 case EFI_IFR_EQ_ID_LIST_OP:
958 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
959 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
960 ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
961 break;
962
963 case EFI_IFR_TO_STRING_OP:
964 case EFI_IFR_FIND_OP:
965 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
966 break;
967
968 case EFI_IFR_STRING_REF1_OP:
969 Value->Type = EFI_IFR_TYPE_STRING;
970 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
971 break;
972
973 case EFI_IFR_RULE_REF_OP:
974 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
975 break;
976
977 case EFI_IFR_SPAN_OP:
978 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
979 break;
980
981 case EFI_IFR_THIS_OP:
982 ASSERT (CurrentStatement != NULL);
983 ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
984 break;
985
986 case EFI_IFR_QUESTION_REF1_OP:
987 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
988 break;
989
990 case EFI_IFR_QUESTION_REF3_OP:
991 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
992 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
993
994 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
995 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
996 }
997 }
998 break;
999
1000 //
1001 // constant
1002 //
1003 case EFI_IFR_TRUE_OP:
1004 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1005 Value->Value.b = TRUE;
1006 break;
1007
1008 case EFI_IFR_FALSE_OP:
1009 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1010 Value->Value.b = FALSE;
1011 break;
1012
1013 case EFI_IFR_ONE_OP:
1014 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1015 Value->Value.u8 = 1;
1016 break;
1017
1018 case EFI_IFR_ZERO_OP:
1019 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1020 Value->Value.u8 = 0;
1021 break;
1022
1023 case EFI_IFR_ONES_OP:
1024 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1025 Value->Value.u64 = 0xffffffffffffffffULL;
1026 break;
1027
1028 case EFI_IFR_UINT8_OP:
1029 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1030 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
1031 break;
1032
1033 case EFI_IFR_UINT16_OP:
1034 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1035 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
1036 break;
1037
1038 case EFI_IFR_UINT32_OP:
1039 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1040 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
1041 break;
1042
1043 case EFI_IFR_UINT64_OP:
1044 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1045 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
1046 break;
1047
1048 case EFI_IFR_UNDEFINED_OP:
1049 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1050 break;
1051
1052 case EFI_IFR_VERSION_OP:
1053 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1054 Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
1055 break;
1056
1057 default:
1058 break;
1059 }
1060
1061 ASSERT (CurrentExpression != NULL);
1062 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
1063
1064 if (SingleOpCodeExpression) {
1065 //
1066 // There are two cases to indicate the end of an Expression:
1067 // for single OpCode expression: one Expression OpCode
1068 // for expression consists of more than one OpCode: EFI_IFR_END
1069 //
1070 SingleOpCodeExpression = FALSE;
1071
1072 if (mInScopeDisable && CurrentForm == NULL) {
1073 //
1074 // This is DisableIf expression for Form, it should be a constant expression
1075 //
1076 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1077 if (EFI_ERROR (Status)) {
1078 return Status;
1079 }
1080
1081 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1082 return EFI_INVALID_PARAMETER;
1083 }
1084
1085 OpCodeDisabled = CurrentExpression->Result.Value.b;
1086 }
1087
1088 CurrentExpression = NULL;
1089 }
1090
1091 continue;
1092 }
1093
1094 //
1095 // Parse the Opcode
1096 //
1097 switch (Operand) {
1098
1099 case EFI_IFR_FORM_SET_OP:
1100 //
1101 // Check the formset GUID
1102 //
1103 if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1104 return EFI_INVALID_PARAMETER;
1105 }
1106
1107 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1108 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
1109
1110 //
1111 // The formset OpCode contains ClassGuid
1112 //
1113 FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
1114 CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
1115
1116 InitializeListHead (&FormSet->ExpressionListHead);
1117 break;
1118
1119 case EFI_IFR_FORM_OP:
1120 //
1121 // Create a new Form for this FormSet
1122 //
1123 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1124 ASSERT (CurrentForm != NULL);
1125 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1126 InitializeListHead (&CurrentForm->ExpressionListHead);
1127 InitializeListHead (&CurrentForm->StatementListHead);
1128
1129 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1130 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1131
1132 if (InScopeFormSuppress) {
1133 //
1134 // Form is inside of suppressif
1135 //
1136 CurrentForm->SuppressExpression = FormSuppressExpression;
1137 }
1138
1139 if (Scope != 0) {
1140 //
1141 // Enter scope of a Form, suppressif will be used for Question or Option
1142 //
1143 SuppressForQuestion = TRUE;
1144 }
1145
1146 //
1147 // Insert into Form list of this FormSet
1148 //
1149 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1150 break;
1151
1152 //
1153 // Storage
1154 //
1155 case EFI_IFR_VARSTORE_OP:
1156 //
1157 // Create a buffer Storage for this FormSet
1158 //
1159 Storage = CreateStorage (FormSet);
1160 Storage->Type = EFI_HII_VARSTORE_BUFFER;
1161
1162 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1163 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1164 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
1165
1166 Storage->Buffer = AllocateZeroPool (Storage->Size);
1167 Storage->EditBuffer = AllocateZeroPool (Storage->Size);
1168
1169 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
1170 Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
1171 ASSERT (Storage->Name != NULL);
1172 for (Index = 0; AsciiString[Index] != 0; Index++) {
1173 Storage->Name[Index] = (CHAR16) AsciiString[Index];
1174 }
1175
1176 //
1177 // Initialize <ConfigHdr>
1178 //
1179 InitializeConfigHdr (FormSet, Storage);
1180 break;
1181
1182 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1183 //
1184 // Create a name/value Storage for this FormSet
1185 //
1186 Storage = CreateStorage (FormSet);
1187 Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
1188
1189 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1190 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1191
1192 //
1193 // Initialize <ConfigHdr>
1194 //
1195 InitializeConfigHdr (FormSet, Storage);
1196 break;
1197
1198 case EFI_IFR_VARSTORE_EFI_OP:
1199 //
1200 // Create a EFI variable Storage for this FormSet
1201 //
1202 Storage = CreateStorage (FormSet);
1203 Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
1204
1205 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1206 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
1207 CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
1208 break;
1209
1210 //
1211 // DefaultStore
1212 //
1213 case EFI_IFR_DEFAULTSTORE_OP:
1214 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
1215 ASSERT (DefaultStore != NULL);
1216 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1217
1218 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
1219 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1220
1221 //
1222 // Insert to DefaultStore list of this Formset
1223 //
1224 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1225 break;
1226
1227 //
1228 // Statements
1229 //
1230 case EFI_IFR_SUBTITLE_OP:
1231 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1232 ASSERT (CurrentStatement != NULL);
1233
1234 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
1235
1236 if (Scope != 0) {
1237 mInScopeSubtitle = TRUE;
1238 }
1239 break;
1240
1241 case EFI_IFR_TEXT_OP:
1242 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1243 ASSERT (CurrentStatement != NULL);
1244
1245 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1246 break;
1247
1248 case EFI_IFR_RESET_BUTTON_OP:
1249 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1250 ASSERT (CurrentStatement != NULL);
1251 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1252 break;
1253
1254 //
1255 // Questions
1256 //
1257 case EFI_IFR_ACTION_OP:
1258 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1259 ASSERT (CurrentStatement != NULL);
1260 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
1261
1262 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1263 //
1264 // No QuestionConfig present, so no configuration string will be processed
1265 //
1266 CurrentStatement->QuestionConfig = 0;
1267 } else {
1268 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1269 }
1270 break;
1271
1272 case EFI_IFR_REF_OP:
1273 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1274 ASSERT (CurrentStatement != NULL);
1275 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_UNDEFINED;
1276 CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
1277 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1278 CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1279
1280 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1281 CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1282
1283 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1284 CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1285 }
1286 }
1287 }
1288 break;
1289
1290 case EFI_IFR_ONE_OF_OP:
1291 case EFI_IFR_NUMERIC_OP:
1292 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1293 ASSERT(CurrentStatement != NULL);
1294
1295 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1296 Value = &CurrentStatement->HiiValue;
1297
1298 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1299 case EFI_IFR_NUMERIC_SIZE_1:
1300 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1301 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1302 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
1303 CurrentStatement->StorageWidth = sizeof (UINT8);
1304 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1305 break;
1306
1307 case EFI_IFR_NUMERIC_SIZE_2:
1308 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1309 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1310 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
1311 CurrentStatement->StorageWidth = sizeof (UINT16);
1312 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1313 break;
1314
1315 case EFI_IFR_NUMERIC_SIZE_4:
1316 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
1317 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
1318 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
1319 CurrentStatement->StorageWidth = sizeof (UINT32);
1320 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1321 break;
1322
1323 case EFI_IFR_NUMERIC_SIZE_8:
1324 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
1325 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
1326 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
1327 CurrentStatement->StorageWidth = sizeof (UINT64);
1328 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1329 break;
1330
1331 default:
1332 break;
1333 }
1334
1335 InitializeRequestElement (FormSet, CurrentStatement);
1336
1337 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
1338 SuppressForOption = TRUE;
1339 }
1340 break;
1341
1342 case EFI_IFR_ORDERED_LIST_OP:
1343 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1344 ASSERT(CurrentStatement != NULL);
1345
1346 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
1347 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
1348
1349 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
1350
1351 if (Scope != 0) {
1352 SuppressForOption = TRUE;
1353 }
1354 break;
1355
1356 case EFI_IFR_CHECKBOX_OP:
1357 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1358 ASSERT(CurrentStatement != NULL);
1359
1360 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
1361 CurrentStatement->StorageWidth = sizeof (BOOLEAN);
1362 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
1363
1364 InitializeRequestElement (FormSet, CurrentStatement);
1365
1366 break;
1367
1368 case EFI_IFR_STRING_OP:
1369 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1370 ASSERT (CurrentStatement != NULL);
1371 //
1372 // MinSize is the minimum number of characters that can be accepted for this opcode,
1373 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1374 // The characters are stored as Unicode, so the storage width should multiply 2.
1375 //
1376 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
1377 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
1378 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1379 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
1380
1381 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1382 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
1383
1384 InitializeRequestElement (FormSet, CurrentStatement);
1385 break;
1386
1387 case EFI_IFR_PASSWORD_OP:
1388 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1389 ASSERT (CurrentStatement != NULL);
1390 //
1391 // MinSize is the minimum number of characters that can be accepted for this opcode,
1392 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1393 // The characters are stored as Unicode, so the storage width should multiply 2.
1394 //
1395 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
1396 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
1397 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1398
1399 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1400 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
1401
1402 InitializeRequestElement (FormSet, CurrentStatement);
1403 break;
1404
1405 case EFI_IFR_DATE_OP:
1406 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1407 ASSERT(CurrentStatement != NULL);
1408
1409 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
1410 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
1411
1412 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
1413 CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);
1414
1415 InitializeRequestElement (FormSet, CurrentStatement);
1416 } else {
1417 //
1418 // Don't assign storage for RTC type of date/time
1419 //
1420 CurrentStatement->Storage = NULL;
1421 CurrentStatement->StorageWidth = 0;
1422 }
1423 break;
1424
1425 case EFI_IFR_TIME_OP:
1426 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1427 ASSERT(CurrentStatement != NULL);
1428
1429 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
1430 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
1431
1432 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
1433 CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);
1434
1435 InitializeRequestElement (FormSet, CurrentStatement);
1436 } else {
1437 //
1438 // Don't assign storage for RTC type of date/time
1439 //
1440 CurrentStatement->Storage = NULL;
1441 CurrentStatement->StorageWidth = 0;
1442 }
1443 break;
1444
1445 //
1446 // Default
1447 //
1448 case EFI_IFR_DEFAULT_OP:
1449 //
1450 // EFI_IFR_DEFAULT appear in scope of a Question,
1451 // It creates a default value for the current question.
1452 // A Question may have more than one Default value which have different default types.
1453 //
1454 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
1455 ASSERT (CurrentDefault != NULL);
1456 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
1457
1458 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
1459 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
1460 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1461 ExtendValueToU64 (&CurrentDefault->Value);
1462
1463 //
1464 // Insert to Default Value list of current Question
1465 //
1466 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
1467
1468 if (Scope != 0) {
1469 InScopeDefault = TRUE;
1470 }
1471 break;
1472
1473 //
1474 // Option
1475 //
1476 case EFI_IFR_ONE_OF_OPTION_OP:
1477 //
1478 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
1479 // It create a selection for use in current Question.
1480 //
1481 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
1482 ASSERT (CurrentOption != NULL);
1483 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
1484
1485 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
1486 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
1487 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
1488 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1489 ExtendValueToU64 (&CurrentOption->Value);
1490
1491 if (InScopeOptionSuppress) {
1492 CurrentOption->SuppressExpression = OptionSuppressExpression;
1493 }
1494
1495 //
1496 // Insert to Option list of current Question
1497 //
1498 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
1499
1500 //
1501 // Now we know the Storage width of nested Ordered List
1502 //
1503 if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) {
1504 Width = 1;
1505 switch (CurrentOption->Value.Type) {
1506 case EFI_IFR_TYPE_NUM_SIZE_8:
1507 Width = 1;
1508 break;
1509
1510 case EFI_IFR_TYPE_NUM_SIZE_16:
1511 Width = 2;
1512 break;
1513
1514 case EFI_IFR_TYPE_NUM_SIZE_32:
1515 Width = 4;
1516 break;
1517
1518 case EFI_IFR_TYPE_NUM_SIZE_64:
1519 Width = 8;
1520 break;
1521
1522 default:
1523 //
1524 // Invalid type for Ordered List
1525 //
1526 break;
1527 }
1528
1529 CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width);
1530 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
1531 CurrentStatement->ValueType = CurrentOption->Value.Type;
1532
1533 InitializeRequestElement (FormSet, CurrentStatement);
1534 }
1535 break;
1536
1537 //
1538 // Conditional
1539 //
1540 case EFI_IFR_NO_SUBMIT_IF_OP:
1541 case EFI_IFR_INCONSISTENT_IF_OP:
1542 //
1543 // Create an Expression node
1544 //
1545 CurrentExpression = CreateExpression (CurrentForm);
1546 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
1547
1548 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
1549 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
1550 InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
1551 } else {
1552 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
1553 InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
1554 }
1555
1556 //
1557 // Take a look at next OpCode to see whether current expression consists
1558 // of single OpCode
1559 //
1560 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1561 SingleOpCodeExpression = TRUE;
1562 }
1563 break;
1564
1565 case EFI_IFR_SUPPRESS_IF_OP:
1566 //
1567 // Question and Option will appear in scope of this OpCode
1568 //
1569 CurrentExpression = CreateExpression (CurrentForm);
1570 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
1571
1572 if (CurrentForm == NULL) {
1573 InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
1574 } else {
1575 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1576 }
1577
1578 if (SuppressForOption) {
1579 InScopeOptionSuppress = TRUE;
1580 OptionSuppressExpression = CurrentExpression;
1581 } else if (SuppressForQuestion) {
1582 mInScopeSuppress = TRUE;
1583 mSuppressExpression = CurrentExpression;
1584 } else {
1585 InScopeFormSuppress = TRUE;
1586 FormSuppressExpression = CurrentExpression;
1587 }
1588
1589 //
1590 // Take a look at next OpCode to see whether current expression consists
1591 // of single OpCode
1592 //
1593 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1594 SingleOpCodeExpression = TRUE;
1595 }
1596 break;
1597
1598 case EFI_IFR_GRAY_OUT_IF_OP:
1599 //
1600 // Questions will appear in scope of this OpCode
1601 //
1602 CurrentExpression = CreateExpression (CurrentForm);
1603 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
1604 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1605
1606 mInScopeGrayOut = TRUE;
1607 mGrayOutExpression = CurrentExpression;
1608
1609 //
1610 // Take a look at next OpCode to see whether current expression consists
1611 // of single OpCode
1612 //
1613 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1614 SingleOpCodeExpression = TRUE;
1615 }
1616 break;
1617
1618 case EFI_IFR_DISABLE_IF_OP:
1619 //
1620 // The DisableIf expression should only rely on constant, so it could be
1621 // evaluated at initialization and it will not be queued
1622 //
1623 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
1624 ASSERT (CurrentExpression != NULL);
1625 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
1626 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
1627 InitializeListHead (&CurrentExpression->OpCodeListHead);
1628
1629 if (CurrentForm != NULL) {
1630 //
1631 // This is DisableIf for Question, enqueue it to Form expression list
1632 //
1633 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1634 }
1635
1636 mDisableExpression = CurrentExpression;
1637 mInScopeDisable = TRUE;
1638 OpCodeDisabled = FALSE;
1639
1640 //
1641 // Take a look at next OpCode to see whether current expression consists
1642 // of single OpCode
1643 //
1644 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1645 SingleOpCodeExpression = TRUE;
1646 }
1647 break;
1648
1649 //
1650 // Expression
1651 //
1652 case EFI_IFR_VALUE_OP:
1653 CurrentExpression = CreateExpression (CurrentForm);
1654 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
1655 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1656
1657 if (InScopeDefault) {
1658 //
1659 // Used for default (EFI_IFR_DEFAULT)
1660 //
1661 CurrentDefault->ValueExpression = CurrentExpression;
1662 } else {
1663 //
1664 // If used for a question, then the question will be read-only
1665 //
1666 //
1667 // Make sure CurrentStatement is not NULL.
1668 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1669 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
1670 //
1671 ASSERT (CurrentStatement != NULL);
1672 CurrentStatement->ValueExpression = CurrentExpression;
1673 }
1674
1675 //
1676 // Take a look at next OpCode to see whether current expression consists
1677 // of single OpCode
1678 //
1679 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1680 SingleOpCodeExpression = TRUE;
1681 }
1682 break;
1683
1684 case EFI_IFR_RULE_OP:
1685 CurrentExpression = CreateExpression (CurrentForm);
1686 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
1687
1688 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
1689 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1690
1691 //
1692 // Take a look at next OpCode to see whether current expression consists
1693 // of single OpCode
1694 //
1695 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1696 SingleOpCodeExpression = TRUE;
1697 }
1698 break;
1699
1700 //
1701 // Image
1702 //
1703 case EFI_IFR_IMAGE_OP:
1704 //
1705 // Get ScopeOpcode from top of stack
1706 //
1707 PopScope (&ScopeOpCode);
1708 PushScope (ScopeOpCode);
1709
1710 switch (ScopeOpCode) {
1711 case EFI_IFR_FORM_SET_OP:
1712 ImageId = &FormSet->ImageId;
1713 break;
1714
1715 case EFI_IFR_FORM_OP:
1716 ASSERT (CurrentForm != NULL);
1717 ImageId = &CurrentForm->ImageId;
1718 break;
1719
1720 case EFI_IFR_ONE_OF_OPTION_OP:
1721 ImageId = &CurrentOption->ImageId;
1722 break;
1723
1724 default:
1725 //
1726 // Make sure CurrentStatement is not NULL.
1727 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1728 // file is wrongly generated by tools such as VFR Compiler.
1729 //
1730 ASSERT (CurrentStatement != NULL);
1731 ImageId = &CurrentStatement->ImageId;
1732 break;
1733 }
1734
1735 ASSERT (ImageId != NULL);
1736 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
1737 break;
1738
1739 //
1740 // Refresh
1741 //
1742 case EFI_IFR_REFRESH_OP:
1743 ASSERT (CurrentStatement != NULL);
1744 CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
1745 break;
1746
1747 //
1748 // Vendor specific
1749 //
1750 case EFI_IFR_GUID_OP:
1751 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
1752 //
1753 // Tiano specific GUIDed opcodes
1754 //
1755 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
1756 case EFI_IFR_EXTEND_OP_LABEL:
1757 //
1758 // just ignore label
1759 //
1760 break;
1761
1762 case EFI_IFR_EXTEND_OP_BANNER:
1763 //
1764 // By SubClass to get Banner Data from Front Page
1765 //
1766 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
1767 CopyMem (
1768 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
1769 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
1770 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
1771 sizeof (EFI_STRING_ID)
1772 );
1773 }
1774 break;
1775
1776 case EFI_IFR_EXTEND_OP_CLASS:
1777 CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
1778 break;
1779
1780 case EFI_IFR_EXTEND_OP_SUBCLASS:
1781 CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
1782 break;
1783
1784 default:
1785 break;
1786 }
1787 }
1788
1789 break;
1790
1791 //
1792 // Scope End
1793 //
1794 case EFI_IFR_END_OP:
1795 Status = PopScope (&ScopeOpCode);
1796 if (EFI_ERROR (Status)) {
1797 ResetScopeStack ();
1798 return Status;
1799 }
1800
1801 switch (ScopeOpCode) {
1802 case EFI_IFR_FORM_SET_OP:
1803 //
1804 // End of FormSet, update FormSet IFR binary length
1805 // to stop parsing substantial OpCodes
1806 //
1807 FormSet->IfrBinaryLength = OpCodeOffset;
1808 break;
1809
1810 case EFI_IFR_FORM_OP:
1811 //
1812 // End of Form
1813 //
1814 CurrentForm = NULL;
1815 SuppressForQuestion = FALSE;
1816 break;
1817
1818 case EFI_IFR_ONE_OF_OPTION_OP:
1819 //
1820 // End of Option
1821 //
1822 CurrentOption = NULL;
1823 break;
1824
1825 case EFI_IFR_SUBTITLE_OP:
1826 mInScopeSubtitle = FALSE;
1827 break;
1828
1829 case EFI_IFR_NO_SUBMIT_IF_OP:
1830 case EFI_IFR_INCONSISTENT_IF_OP:
1831 //
1832 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1833 //
1834 break;
1835
1836 case EFI_IFR_SUPPRESS_IF_OP:
1837 if (SuppressForOption) {
1838 InScopeOptionSuppress = FALSE;
1839 } else if (SuppressForQuestion) {
1840 mInScopeSuppress = FALSE;
1841 } else {
1842 InScopeFormSuppress = FALSE;
1843 }
1844 break;
1845
1846 case EFI_IFR_GRAY_OUT_IF_OP:
1847 mInScopeGrayOut = FALSE;
1848 break;
1849
1850 case EFI_IFR_DISABLE_IF_OP:
1851 mInScopeDisable = FALSE;
1852 OpCodeDisabled = FALSE;
1853 break;
1854
1855 case EFI_IFR_ONE_OF_OP:
1856 case EFI_IFR_ORDERED_LIST_OP:
1857 SuppressForOption = FALSE;
1858 break;
1859
1860 case EFI_IFR_DEFAULT_OP:
1861 InScopeDefault = FALSE;
1862 break;
1863
1864 default:
1865 if (IsExpressionOpCode (ScopeOpCode)) {
1866 if (mInScopeDisable && CurrentForm == NULL) {
1867 //
1868 // This is DisableIf expression for Form, it should be a constant expression
1869 //
1870 ASSERT (CurrentExpression != NULL);
1871 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1872 if (EFI_ERROR (Status)) {
1873 return Status;
1874 }
1875
1876 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1877 return EFI_INVALID_PARAMETER;
1878 }
1879
1880 OpCodeDisabled = CurrentExpression->Result.Value.b;
1881 //
1882 // DisableIf Expression is only used once and not quequed, free it
1883 //
1884 DestroyExpression (CurrentExpression);
1885 }
1886
1887 //
1888 // End of current Expression
1889 //
1890 CurrentExpression = NULL;
1891 }
1892 break;
1893 }
1894 break;
1895
1896 default:
1897 break;
1898 }
1899 }
1900
1901 return EFI_SUCCESS;
1902 }