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