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