]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
141f953d668ffc82f8add319a5922072615686ff
[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 //
659 // Free IFR binary buffer
660 //
661 FreePool (FormSet->IfrBinaryData);
662
663 //
664 // Free FormSet Storage
665 //
666 if (FormSet->StorageListHead.ForwardLink != NULL) {
667 while (!IsListEmpty (&FormSet->StorageListHead)) {
668 Link = GetFirstNode (&FormSet->StorageListHead);
669 Storage = FORMSET_STORAGE_FROM_LINK (Link);
670 RemoveEntryList (&Storage->Link);
671
672 DestroyStorage (Storage);
673 }
674 }
675
676 //
677 // Free FormSet Default Store
678 //
679 if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
680 while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
681 Link = GetFirstNode (&FormSet->DefaultStoreListHead);
682 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
683 RemoveEntryList (&DefaultStore->Link);
684
685 FreePool (DefaultStore);
686 }
687 }
688
689 //
690 // Free Formset Expressions
691 //
692 while (!IsListEmpty (&FormSet->ExpressionListHead)) {
693 Link = GetFirstNode (&FormSet->ExpressionListHead);
694 Expression = FORM_EXPRESSION_FROM_LINK (Link);
695 RemoveEntryList (&Expression->Link);
696
697 DestroyExpression (Expression);
698 }
699
700 //
701 // Free Forms
702 //
703 if (FormSet->FormListHead.ForwardLink != NULL) {
704 while (!IsListEmpty (&FormSet->FormListHead)) {
705 Link = GetFirstNode (&FormSet->FormListHead);
706 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
707 RemoveEntryList (&Form->Link);
708
709 DestroyForm (Form);
710 }
711 }
712
713 if (FormSet->StatementBuffer != NULL) {
714 FreePool (FormSet->StatementBuffer);
715 }
716 if (FormSet->ExpressionBuffer != NULL) {
717 FreePool (FormSet->ExpressionBuffer);
718 }
719
720 FreePool (FormSet);
721 }
722
723
724 /**
725 Tell whether this Operand is an Expression OpCode or not
726
727 @param Operand Operand of an IFR OpCode.
728
729 @retval TRUE This is an Expression OpCode.
730 @retval FALSE Not an Expression OpCode.
731
732 **/
733 BOOLEAN
734 IsExpressionOpCode (
735 IN UINT8 Operand
736 )
737 {
738 if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
739 ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
740 (Operand == EFI_IFR_CATENATE_OP) ||
741 (Operand == EFI_IFR_TO_LOWER_OP) ||
742 (Operand == EFI_IFR_TO_UPPER_OP) ||
743 (Operand == EFI_IFR_VERSION_OP)
744 ) {
745 return TRUE;
746 } else {
747 return FALSE;
748 }
749 }
750
751
752 /**
753 Calculate number of Statemens(Questions) and Expression OpCodes.
754
755 @param FormSet The FormSet to be counted.
756 @param NumberOfStatement Number of Statemens(Questions)
757 @param NumberOfExpression Number of Expression OpCodes
758
759 **/
760 VOID
761 CountOpCodes (
762 IN FORM_BROWSER_FORMSET *FormSet,
763 IN OUT UINT16 *NumberOfStatement,
764 IN OUT UINT16 *NumberOfExpression
765 )
766 {
767 UINT16 StatementCount;
768 UINT16 ExpressionCount;
769 UINT8 *OpCodeData;
770 UINTN Offset;
771 UINTN OpCodeLen;
772
773 Offset = 0;
774 StatementCount = 0;
775 ExpressionCount = 0;
776
777 while (Offset < FormSet->IfrBinaryLength) {
778 OpCodeData = FormSet->IfrBinaryData + Offset;
779 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
780 Offset += OpCodeLen;
781
782 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
783 ExpressionCount++;
784 } else {
785 StatementCount++;
786 }
787 }
788
789 *NumberOfStatement = StatementCount;
790 *NumberOfExpression = ExpressionCount;
791 }
792
793
794
795 /**
796 Parse opcodes in the formset IFR binary.
797
798 @param FormSet Pointer of the FormSet data structure.
799
800 @retval EFI_SUCCESS Opcode parse success.
801 @retval Other Opcode parse fail.
802
803 **/
804 EFI_STATUS
805 ParseOpCodes (
806 IN FORM_BROWSER_FORMSET *FormSet
807 )
808 {
809 EFI_STATUS Status;
810 UINT16 Index;
811 FORM_BROWSER_FORM *CurrentForm;
812 FORM_BROWSER_STATEMENT *CurrentStatement;
813 EXPRESSION_OPCODE *ExpressionOpCode;
814 FORM_EXPRESSION *CurrentExpression;
815 UINT8 Operand;
816 UINT8 Scope;
817 UINTN OpCodeOffset;
818 UINTN OpCodeLength;
819 UINT8 *OpCodeData;
820 UINT8 ScopeOpCode;
821 FORMSET_STORAGE *Storage;
822 FORMSET_DEFAULTSTORE *DefaultStore;
823 QUESTION_DEFAULT *CurrentDefault;
824 QUESTION_OPTION *CurrentOption;
825 UINT8 Width;
826 CHAR8 *AsciiString;
827 UINT16 NumberOfStatement;
828 UINT16 NumberOfExpression;
829 EFI_IMAGE_ID *ImageId;
830 BOOLEAN SuppressForQuestion;
831 BOOLEAN SuppressForOption;
832 BOOLEAN InScopeOptionSuppress;
833 FORM_EXPRESSION *OptionSuppressExpression;
834 BOOLEAN InScopeFormSuppress;
835 FORM_EXPRESSION *FormSuppressExpression;
836 UINT16 DepthOfDisable;
837 BOOLEAN OpCodeDisabled;
838 BOOLEAN SingleOpCodeExpression;
839 BOOLEAN InScopeDefault;
840 EFI_HII_VALUE *Value;
841
842 mInScopeSubtitle = FALSE;
843 SuppressForQuestion = FALSE;
844 SuppressForOption = FALSE;
845 InScopeFormSuppress = FALSE;
846 mInScopeSuppress = FALSE;
847 InScopeOptionSuppress = FALSE;
848 mInScopeGrayOut = FALSE;
849 mInScopeDisable = FALSE;
850 DepthOfDisable = 0;
851 OpCodeDisabled = FALSE;
852 SingleOpCodeExpression = FALSE;
853 InScopeDefault = FALSE;
854 CurrentExpression = NULL;
855 CurrentDefault = NULL;
856 CurrentOption = NULL;
857 OptionSuppressExpression = NULL;
858 FormSuppressExpression = NULL;
859 ImageId = NULL;
860
861 //
862 // Get the number of Statements and Expressions
863 //
864 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
865
866 mStatementIndex = 0;
867 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
868 if (FormSet->StatementBuffer == NULL) {
869 return EFI_OUT_OF_RESOURCES;
870 }
871
872 mExpressionOpCodeIndex = 0;
873 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
874 if (FormSet->ExpressionBuffer == NULL) {
875 return EFI_OUT_OF_RESOURCES;
876 }
877
878 InitializeListHead (&FormSet->StorageListHead);
879 InitializeListHead (&FormSet->DefaultStoreListHead);
880 InitializeListHead (&FormSet->FormListHead);
881
882 CurrentForm = NULL;
883 CurrentStatement = NULL;
884
885 ResetScopeStack ();
886
887 OpCodeOffset = 0;
888 while (OpCodeOffset < FormSet->IfrBinaryLength) {
889 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
890
891 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
892 OpCodeOffset += OpCodeLength;
893 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
894 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
895
896 //
897 // If scope bit set, push onto scope stack
898 //
899 if (Scope != 0) {
900 PushScope (Operand);
901 }
902
903 if (OpCodeDisabled) {
904 //
905 // DisableIf Expression is evaluated to be TRUE, try to find its end.
906 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
907 //
908 if (Operand == EFI_IFR_DISABLE_IF_OP) {
909 DepthOfDisable++;
910 } else if (Operand == EFI_IFR_END_OP) {
911 Status = PopScope (&ScopeOpCode);
912 if (EFI_ERROR (Status)) {
913 return Status;
914 }
915
916 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
917 if (DepthOfDisable == 0) {
918 mInScopeDisable = FALSE;
919 OpCodeDisabled = FALSE;
920 } else {
921 DepthOfDisable--;
922 }
923 }
924 }
925 continue;
926 }
927
928 if (IsExpressionOpCode (Operand)) {
929 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
930 mExpressionOpCodeIndex++;
931
932 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
933 ExpressionOpCode->Operand = Operand;
934 Value = &ExpressionOpCode->Value;
935
936 switch (Operand) {
937 case EFI_IFR_EQ_ID_VAL_OP:
938 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
939
940 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
941 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
942 break;
943
944 case EFI_IFR_EQ_ID_ID_OP:
945 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
946 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
947 break;
948
949 case EFI_IFR_EQ_ID_LIST_OP:
950 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
951 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
952 ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
953 break;
954
955 case EFI_IFR_TO_STRING_OP:
956 case EFI_IFR_FIND_OP:
957 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
958 break;
959
960 case EFI_IFR_STRING_REF1_OP:
961 Value->Type = EFI_IFR_TYPE_STRING;
962 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
963 break;
964
965 case EFI_IFR_RULE_REF_OP:
966 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
967 break;
968
969 case EFI_IFR_SPAN_OP:
970 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
971 break;
972
973 case EFI_IFR_THIS_OP:
974 ASSERT (CurrentStatement != NULL);
975 ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
976 break;
977
978 case EFI_IFR_QUESTION_REF1_OP:
979 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
980 break;
981
982 case EFI_IFR_QUESTION_REF3_OP:
983 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
984 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
985
986 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
987 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
988 }
989 }
990 break;
991
992 //
993 // constant
994 //
995 case EFI_IFR_TRUE_OP:
996 Value->Type = EFI_IFR_TYPE_BOOLEAN;
997 Value->Value.b = TRUE;
998 break;
999
1000 case EFI_IFR_FALSE_OP:
1001 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1002 Value->Value.b = FALSE;
1003 break;
1004
1005 case EFI_IFR_ONE_OP:
1006 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1007 Value->Value.u8 = 1;
1008 break;
1009
1010 case EFI_IFR_ZERO_OP:
1011 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1012 Value->Value.u8 = 0;
1013 break;
1014
1015 case EFI_IFR_ONES_OP:
1016 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1017 Value->Value.u64 = 0xffffffffffffffffULL;
1018 break;
1019
1020 case EFI_IFR_UINT8_OP:
1021 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1022 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
1023 break;
1024
1025 case EFI_IFR_UINT16_OP:
1026 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1027 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
1028 break;
1029
1030 case EFI_IFR_UINT32_OP:
1031 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1032 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
1033 break;
1034
1035 case EFI_IFR_UINT64_OP:
1036 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1037 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
1038 break;
1039
1040 case EFI_IFR_UNDEFINED_OP:
1041 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1042 break;
1043
1044 case EFI_IFR_VERSION_OP:
1045 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1046 Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
1047 break;
1048
1049 default:
1050 break;
1051 }
1052
1053 ASSERT (CurrentExpression != NULL);
1054 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
1055
1056 if (SingleOpCodeExpression) {
1057 //
1058 // There are two cases to indicate the end of an Expression:
1059 // for single OpCode expression: one Expression OpCode
1060 // for expression consists of more than one OpCode: EFI_IFR_END
1061 //
1062 SingleOpCodeExpression = FALSE;
1063
1064 if (mInScopeDisable && CurrentForm == NULL) {
1065 //
1066 // This is DisableIf expression for Form, it should be a constant expression
1067 //
1068 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1069 if (EFI_ERROR (Status)) {
1070 return Status;
1071 }
1072
1073 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1074 return EFI_INVALID_PARAMETER;
1075 }
1076
1077 OpCodeDisabled = CurrentExpression->Result.Value.b;
1078 }
1079
1080 CurrentExpression = NULL;
1081 }
1082
1083 continue;
1084 }
1085
1086 //
1087 // Parse the Opcode
1088 //
1089 switch (Operand) {
1090
1091 case EFI_IFR_FORM_SET_OP:
1092 //
1093 // Check the formset GUID
1094 //
1095 if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1096 return EFI_INVALID_PARAMETER;
1097 }
1098
1099 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1100 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
1101
1102 //
1103 // The formset OpCode contains ClassGuid
1104 //
1105 FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
1106 CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
1107
1108 InitializeListHead (&FormSet->ExpressionListHead);
1109 break;
1110
1111 case EFI_IFR_FORM_OP:
1112 //
1113 // Create a new Form for this FormSet
1114 //
1115 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1116 ASSERT (CurrentForm != NULL);
1117 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1118 InitializeListHead (&CurrentForm->ExpressionListHead);
1119 InitializeListHead (&CurrentForm->StatementListHead);
1120
1121 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1122 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1123
1124 if (InScopeFormSuppress) {
1125 //
1126 // Form is inside of suppressif
1127 //
1128 CurrentForm->SuppressExpression = FormSuppressExpression;
1129 }
1130
1131 if (Scope != 0) {
1132 //
1133 // Enter scope of a Form, suppressif will be used for Question or Option
1134 //
1135 SuppressForQuestion = TRUE;
1136 }
1137
1138 //
1139 // Insert into Form list of this FormSet
1140 //
1141 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1142 break;
1143
1144 //
1145 // Storage
1146 //
1147 case EFI_IFR_VARSTORE_OP:
1148 //
1149 // Create a buffer Storage for this FormSet
1150 //
1151 Storage = CreateStorage (FormSet);
1152 Storage->Type = EFI_HII_VARSTORE_BUFFER;
1153
1154 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1155 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1156 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
1157
1158 Storage->Buffer = AllocateZeroPool (Storage->Size);
1159 Storage->EditBuffer = AllocateZeroPool (Storage->Size);
1160
1161 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
1162 Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
1163 ASSERT (Storage->Name != NULL);
1164 for (Index = 0; AsciiString[Index] != 0; Index++) {
1165 Storage->Name[Index] = (CHAR16) AsciiString[Index];
1166 }
1167
1168 //
1169 // Initialize <ConfigHdr>
1170 //
1171 InitializeConfigHdr (FormSet, Storage);
1172 break;
1173
1174 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1175 //
1176 // Create a name/value Storage for this FormSet
1177 //
1178 Storage = CreateStorage (FormSet);
1179 Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
1180
1181 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1182 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1183
1184 //
1185 // Initialize <ConfigHdr>
1186 //
1187 InitializeConfigHdr (FormSet, Storage);
1188 break;
1189
1190 case EFI_IFR_VARSTORE_EFI_OP:
1191 //
1192 // Create a EFI variable Storage for this FormSet
1193 //
1194 Storage = CreateStorage (FormSet);
1195 Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
1196
1197 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1198 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
1199 CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
1200 break;
1201
1202 //
1203 // DefaultStore
1204 //
1205 case EFI_IFR_DEFAULTSTORE_OP:
1206 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
1207 ASSERT (DefaultStore != NULL);
1208 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1209
1210 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
1211 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1212
1213 //
1214 // Insert to DefaultStore list of this Formset
1215 //
1216 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1217 break;
1218
1219 //
1220 // Statements
1221 //
1222 case EFI_IFR_SUBTITLE_OP:
1223 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1224 ASSERT (CurrentStatement != NULL);
1225
1226 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
1227
1228 if (Scope != 0) {
1229 mInScopeSubtitle = TRUE;
1230 }
1231 break;
1232
1233 case EFI_IFR_TEXT_OP:
1234 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1235 ASSERT (CurrentStatement != NULL);
1236
1237 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1238 break;
1239
1240 case EFI_IFR_RESET_BUTTON_OP:
1241 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1242 ASSERT (CurrentStatement != NULL);
1243 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1244 break;
1245
1246 //
1247 // Questions
1248 //
1249 case EFI_IFR_ACTION_OP:
1250 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1251 ASSERT (CurrentStatement != NULL);
1252 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
1253
1254 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1255 //
1256 // No QuestionConfig present, so no configuration string will be processed
1257 //
1258 CurrentStatement->QuestionConfig = 0;
1259 } else {
1260 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1261 }
1262 break;
1263
1264 case EFI_IFR_REF_OP:
1265 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1266 ASSERT (CurrentStatement != NULL);
1267 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_UNDEFINED;
1268 CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
1269 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1270 CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1271
1272 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1273 CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1274
1275 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1276 CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1277 }
1278 }
1279 }
1280 break;
1281
1282 case EFI_IFR_ONE_OF_OP:
1283 case EFI_IFR_NUMERIC_OP:
1284 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1285 ASSERT(CurrentStatement != NULL);
1286
1287 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1288 Value = &CurrentStatement->HiiValue;
1289
1290 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1291 case EFI_IFR_NUMERIC_SIZE_1:
1292 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1293 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1294 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
1295 CurrentStatement->StorageWidth = sizeof (UINT8);
1296 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1297 break;
1298
1299 case EFI_IFR_NUMERIC_SIZE_2:
1300 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1301 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1302 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
1303 CurrentStatement->StorageWidth = sizeof (UINT16);
1304 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1305 break;
1306
1307 case EFI_IFR_NUMERIC_SIZE_4:
1308 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
1309 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
1310 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
1311 CurrentStatement->StorageWidth = sizeof (UINT32);
1312 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1313 break;
1314
1315 case EFI_IFR_NUMERIC_SIZE_8:
1316 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
1317 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
1318 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
1319 CurrentStatement->StorageWidth = sizeof (UINT64);
1320 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1321 break;
1322
1323 default:
1324 break;
1325 }
1326
1327 InitializeRequestElement (FormSet, CurrentStatement);
1328
1329 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
1330 SuppressForOption = TRUE;
1331 }
1332 break;
1333
1334 case EFI_IFR_ORDERED_LIST_OP:
1335 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1336 ASSERT(CurrentStatement != NULL);
1337
1338 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
1339 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
1340
1341 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
1342
1343 if (Scope != 0) {
1344 SuppressForOption = TRUE;
1345 }
1346 break;
1347
1348 case EFI_IFR_CHECKBOX_OP:
1349 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1350 ASSERT(CurrentStatement != NULL);
1351
1352 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
1353 CurrentStatement->StorageWidth = sizeof (BOOLEAN);
1354 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
1355
1356 InitializeRequestElement (FormSet, CurrentStatement);
1357
1358 break;
1359
1360 case EFI_IFR_STRING_OP:
1361 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1362 ASSERT (CurrentStatement != NULL);
1363 //
1364 // MinSize is the minimum number of characters that can be accepted for this opcode,
1365 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1366 // The characters are stored as Unicode, so the storage width should multiply 2.
1367 //
1368 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
1369 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
1370 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1371 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
1372
1373 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1374 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
1375
1376 InitializeRequestElement (FormSet, CurrentStatement);
1377 break;
1378
1379 case EFI_IFR_PASSWORD_OP:
1380 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1381 ASSERT (CurrentStatement != NULL);
1382 //
1383 // MinSize is the minimum number of characters that can be accepted for this opcode,
1384 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1385 // The characters are stored as Unicode, so the storage width should multiply 2.
1386 //
1387 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
1388 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
1389 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1390
1391 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1392 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
1393
1394 InitializeRequestElement (FormSet, CurrentStatement);
1395 break;
1396
1397 case EFI_IFR_DATE_OP:
1398 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1399 ASSERT(CurrentStatement != NULL);
1400
1401 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
1402 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
1403
1404 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
1405 CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);
1406
1407 InitializeRequestElement (FormSet, CurrentStatement);
1408 } else {
1409 //
1410 // Don't assign storage for RTC type of date/time
1411 //
1412 CurrentStatement->Storage = NULL;
1413 CurrentStatement->StorageWidth = 0;
1414 }
1415 break;
1416
1417 case EFI_IFR_TIME_OP:
1418 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1419 ASSERT(CurrentStatement != NULL);
1420
1421 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
1422 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
1423
1424 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
1425 CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);
1426
1427 InitializeRequestElement (FormSet, CurrentStatement);
1428 } else {
1429 //
1430 // Don't assign storage for RTC type of date/time
1431 //
1432 CurrentStatement->Storage = NULL;
1433 CurrentStatement->StorageWidth = 0;
1434 }
1435 break;
1436
1437 //
1438 // Default
1439 //
1440 case EFI_IFR_DEFAULT_OP:
1441 //
1442 // EFI_IFR_DEFAULT appear in scope of a Question,
1443 // It creates a default value for the current question.
1444 // A Question may have more than one Default value which have different default types.
1445 //
1446 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
1447 ASSERT (CurrentDefault != NULL);
1448 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
1449
1450 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
1451 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
1452 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1453 ExtendValueToU64 (&CurrentDefault->Value);
1454
1455 //
1456 // Insert to Default Value list of current Question
1457 //
1458 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
1459
1460 if (Scope != 0) {
1461 InScopeDefault = TRUE;
1462 }
1463 break;
1464
1465 //
1466 // Option
1467 //
1468 case EFI_IFR_ONE_OF_OPTION_OP:
1469 //
1470 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
1471 // It create a selection for use in current Question.
1472 //
1473 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
1474 ASSERT (CurrentOption != NULL);
1475 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
1476
1477 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
1478 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
1479 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
1480 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1481 ExtendValueToU64 (&CurrentOption->Value);
1482
1483 if (InScopeOptionSuppress) {
1484 CurrentOption->SuppressExpression = OptionSuppressExpression;
1485 }
1486
1487 //
1488 // Insert to Option list of current Question
1489 //
1490 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
1491
1492 //
1493 // Now we know the Storage width of nested Ordered List
1494 //
1495 if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) {
1496 Width = 1;
1497 switch (CurrentOption->Value.Type) {
1498 case EFI_IFR_TYPE_NUM_SIZE_8:
1499 Width = 1;
1500 break;
1501
1502 case EFI_IFR_TYPE_NUM_SIZE_16:
1503 Width = 2;
1504 break;
1505
1506 case EFI_IFR_TYPE_NUM_SIZE_32:
1507 Width = 4;
1508 break;
1509
1510 case EFI_IFR_TYPE_NUM_SIZE_64:
1511 Width = 8;
1512 break;
1513
1514 default:
1515 //
1516 // Invalid type for Ordered List
1517 //
1518 break;
1519 }
1520
1521 CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width);
1522 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
1523 CurrentStatement->ValueType = CurrentOption->Value.Type;
1524
1525 InitializeRequestElement (FormSet, CurrentStatement);
1526 }
1527 break;
1528
1529 //
1530 // Conditional
1531 //
1532 case EFI_IFR_NO_SUBMIT_IF_OP:
1533 case EFI_IFR_INCONSISTENT_IF_OP:
1534 //
1535 // Create an Expression node
1536 //
1537 CurrentExpression = CreateExpression (CurrentForm);
1538 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
1539
1540 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
1541 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
1542 InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
1543 } else {
1544 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
1545 InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
1546 }
1547
1548 //
1549 // Take a look at next OpCode to see whether current expression consists
1550 // of single OpCode
1551 //
1552 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1553 SingleOpCodeExpression = TRUE;
1554 }
1555 break;
1556
1557 case EFI_IFR_SUPPRESS_IF_OP:
1558 //
1559 // Question and Option will appear in scope of this OpCode
1560 //
1561 CurrentExpression = CreateExpression (CurrentForm);
1562 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
1563
1564 if (CurrentForm == NULL) {
1565 InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
1566 } else {
1567 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1568 }
1569
1570 if (SuppressForOption) {
1571 InScopeOptionSuppress = TRUE;
1572 OptionSuppressExpression = CurrentExpression;
1573 } else if (SuppressForQuestion) {
1574 mInScopeSuppress = TRUE;
1575 mSuppressExpression = CurrentExpression;
1576 } else {
1577 InScopeFormSuppress = TRUE;
1578 FormSuppressExpression = CurrentExpression;
1579 }
1580
1581 //
1582 // Take a look at next OpCode to see whether current expression consists
1583 // of single OpCode
1584 //
1585 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1586 SingleOpCodeExpression = TRUE;
1587 }
1588 break;
1589
1590 case EFI_IFR_GRAY_OUT_IF_OP:
1591 //
1592 // Questions will appear in scope of this OpCode
1593 //
1594 CurrentExpression = CreateExpression (CurrentForm);
1595 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
1596 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1597
1598 mInScopeGrayOut = TRUE;
1599 mGrayOutExpression = CurrentExpression;
1600
1601 //
1602 // Take a look at next OpCode to see whether current expression consists
1603 // of single OpCode
1604 //
1605 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1606 SingleOpCodeExpression = TRUE;
1607 }
1608 break;
1609
1610 case EFI_IFR_DISABLE_IF_OP:
1611 //
1612 // The DisableIf expression should only rely on constant, so it could be
1613 // evaluated at initialization and it will not be queued
1614 //
1615 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
1616 ASSERT (CurrentExpression != NULL);
1617 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
1618 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
1619 InitializeListHead (&CurrentExpression->OpCodeListHead);
1620
1621 if (CurrentForm != NULL) {
1622 //
1623 // This is DisableIf for Question, enqueue it to Form expression list
1624 //
1625 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1626 }
1627
1628 mDisableExpression = CurrentExpression;
1629 mInScopeDisable = TRUE;
1630 OpCodeDisabled = FALSE;
1631
1632 //
1633 // Take a look at next OpCode to see whether current expression consists
1634 // of single OpCode
1635 //
1636 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1637 SingleOpCodeExpression = TRUE;
1638 }
1639 break;
1640
1641 //
1642 // Expression
1643 //
1644 case EFI_IFR_VALUE_OP:
1645 CurrentExpression = CreateExpression (CurrentForm);
1646 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
1647 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1648
1649 if (InScopeDefault) {
1650 //
1651 // Used for default (EFI_IFR_DEFAULT)
1652 //
1653 CurrentDefault->ValueExpression = CurrentExpression;
1654 } else {
1655 //
1656 // If used for a question, then the question will be read-only
1657 //
1658 //
1659 // Make sure CurrentStatement is not NULL.
1660 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1661 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
1662 //
1663 ASSERT (CurrentStatement != NULL);
1664 CurrentStatement->ValueExpression = CurrentExpression;
1665 }
1666
1667 //
1668 // Take a look at next OpCode to see whether current expression consists
1669 // of single OpCode
1670 //
1671 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1672 SingleOpCodeExpression = TRUE;
1673 }
1674 break;
1675
1676 case EFI_IFR_RULE_OP:
1677 CurrentExpression = CreateExpression (CurrentForm);
1678 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
1679
1680 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
1681 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1682
1683 //
1684 // Take a look at next OpCode to see whether current expression consists
1685 // of single OpCode
1686 //
1687 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1688 SingleOpCodeExpression = TRUE;
1689 }
1690 break;
1691
1692 //
1693 // Image
1694 //
1695 case EFI_IFR_IMAGE_OP:
1696 //
1697 // Get ScopeOpcode from top of stack
1698 //
1699 PopScope (&ScopeOpCode);
1700 PushScope (ScopeOpCode);
1701
1702 switch (ScopeOpCode) {
1703 case EFI_IFR_FORM_SET_OP:
1704 ImageId = &FormSet->ImageId;
1705 break;
1706
1707 case EFI_IFR_FORM_OP:
1708 ASSERT (CurrentForm != NULL);
1709 ImageId = &CurrentForm->ImageId;
1710 break;
1711
1712 case EFI_IFR_ONE_OF_OPTION_OP:
1713 ImageId = &CurrentOption->ImageId;
1714 break;
1715
1716 default:
1717 //
1718 // Make sure CurrentStatement is not NULL.
1719 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1720 // file is wrongly generated by tools such as VFR Compiler.
1721 //
1722 ASSERT (CurrentStatement != NULL);
1723 ImageId = &CurrentStatement->ImageId;
1724 break;
1725 }
1726
1727 ASSERT (ImageId != NULL);
1728 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
1729 break;
1730
1731 //
1732 // Refresh
1733 //
1734 case EFI_IFR_REFRESH_OP:
1735 ASSERT (CurrentStatement != NULL);
1736 CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
1737 break;
1738
1739 //
1740 // Vendor specific
1741 //
1742 case EFI_IFR_GUID_OP:
1743 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
1744 //
1745 // Tiano specific GUIDed opcodes
1746 //
1747 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
1748 case EFI_IFR_EXTEND_OP_LABEL:
1749 //
1750 // just ignore label
1751 //
1752 break;
1753
1754 case EFI_IFR_EXTEND_OP_BANNER:
1755 //
1756 // By SubClass to get Banner Data from Front Page
1757 //
1758 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
1759 CopyMem (
1760 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
1761 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
1762 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
1763 sizeof (EFI_STRING_ID)
1764 );
1765 }
1766 break;
1767
1768 case EFI_IFR_EXTEND_OP_CLASS:
1769 CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
1770 break;
1771
1772 case EFI_IFR_EXTEND_OP_SUBCLASS:
1773 CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
1774 break;
1775
1776 default:
1777 break;
1778 }
1779 }
1780
1781 break;
1782
1783 //
1784 // Scope End
1785 //
1786 case EFI_IFR_END_OP:
1787 Status = PopScope (&ScopeOpCode);
1788 if (EFI_ERROR (Status)) {
1789 ResetScopeStack ();
1790 return Status;
1791 }
1792
1793 switch (ScopeOpCode) {
1794 case EFI_IFR_FORM_SET_OP:
1795 //
1796 // End of FormSet, update FormSet IFR binary length
1797 // to stop parsing substantial OpCodes
1798 //
1799 FormSet->IfrBinaryLength = OpCodeOffset;
1800 break;
1801
1802 case EFI_IFR_FORM_OP:
1803 //
1804 // End of Form
1805 //
1806 CurrentForm = NULL;
1807 SuppressForQuestion = FALSE;
1808 break;
1809
1810 case EFI_IFR_ONE_OF_OPTION_OP:
1811 //
1812 // End of Option
1813 //
1814 CurrentOption = NULL;
1815 break;
1816
1817 case EFI_IFR_SUBTITLE_OP:
1818 mInScopeSubtitle = FALSE;
1819 break;
1820
1821 case EFI_IFR_NO_SUBMIT_IF_OP:
1822 case EFI_IFR_INCONSISTENT_IF_OP:
1823 //
1824 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1825 //
1826 break;
1827
1828 case EFI_IFR_SUPPRESS_IF_OP:
1829 if (SuppressForOption) {
1830 InScopeOptionSuppress = FALSE;
1831 } else if (SuppressForQuestion) {
1832 mInScopeSuppress = FALSE;
1833 } else {
1834 InScopeFormSuppress = FALSE;
1835 }
1836 break;
1837
1838 case EFI_IFR_GRAY_OUT_IF_OP:
1839 mInScopeGrayOut = FALSE;
1840 break;
1841
1842 case EFI_IFR_DISABLE_IF_OP:
1843 mInScopeDisable = FALSE;
1844 OpCodeDisabled = FALSE;
1845 break;
1846
1847 case EFI_IFR_ONE_OF_OP:
1848 case EFI_IFR_ORDERED_LIST_OP:
1849 SuppressForOption = FALSE;
1850 break;
1851
1852 case EFI_IFR_DEFAULT_OP:
1853 InScopeDefault = FALSE;
1854 break;
1855
1856 default:
1857 if (IsExpressionOpCode (ScopeOpCode)) {
1858 if (mInScopeDisable && CurrentForm == NULL) {
1859 //
1860 // This is DisableIf expression for Form, it should be a constant expression
1861 //
1862 ASSERT (CurrentExpression != NULL);
1863 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1864 if (EFI_ERROR (Status)) {
1865 return Status;
1866 }
1867
1868 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1869 return EFI_INVALID_PARAMETER;
1870 }
1871
1872 OpCodeDisabled = CurrentExpression->Result.Value.b;
1873 //
1874 // DisableIf Expression is only used once and not quequed, free it
1875 //
1876 DestroyExpression (CurrentExpression);
1877 }
1878
1879 //
1880 // End of current Expression
1881 //
1882 CurrentExpression = NULL;
1883 }
1884 break;
1885 }
1886 break;
1887
1888 default:
1889 break;
1890 }
1891 }
1892
1893 return EFI_SUCCESS;
1894 }