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