• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 Parser for IFR binary encoding.
3 
4 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
5 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 EFI_QUESTION_ID  mUsedQuestionId;
20 extern LIST_ENTRY      gBrowserStorageList;
21 /**
22   Initialize Statement header members.
23 
24   @param  OpCodeData             Pointer of the raw OpCode data.
25   @param  FormSet                Pointer of the current FormSet.
26   @param  Form                   Pointer of the current Form.
27 
28   @return The Statement.
29 
30 **/
31 FORM_BROWSER_STATEMENT *
CreateStatement(IN UINT8 * OpCodeData,IN OUT FORM_BROWSER_FORMSET * FormSet,IN OUT FORM_BROWSER_FORM * Form)32 CreateStatement (
33   IN UINT8                        *OpCodeData,
34   IN OUT FORM_BROWSER_FORMSET     *FormSet,
35   IN OUT FORM_BROWSER_FORM        *Form
36   )
37 {
38   FORM_BROWSER_STATEMENT    *Statement;
39   EFI_IFR_STATEMENT_HEADER  *StatementHdr;
40   INTN                      ConditionalExprCount;
41 
42   if (Form == NULL) {
43     //
44     // Only guid op may out side the form level.
45     //
46     ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP);
47   }
48 
49   Statement = &FormSet->StatementBuffer[mStatementIndex];
50   mStatementIndex++;
51 
52   InitializeListHead (&Statement->DefaultListHead);
53   InitializeListHead (&Statement->OptionListHead);
54   InitializeListHead (&Statement->InconsistentListHead);
55   InitializeListHead (&Statement->NoSubmitListHead);
56   InitializeListHead (&Statement->WarningListHead);
57 
58   Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
59 
60   Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
61   Statement->OpCode  = (EFI_IFR_OP_HEADER *) OpCodeData;
62 
63   StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
64   CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
65   CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
66 
67   ConditionalExprCount = GetConditionalExpressionCount(ExpressStatement);
68   if (ConditionalExprCount > 0) {
69     //
70     // Form is inside of suppressif
71     //
72 
73     Statement->Expression = (FORM_EXPRESSION_LIST *) AllocatePool(
74                                              (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
75     ASSERT (Statement->Expression != NULL);
76     Statement->Expression->Count     = (UINTN) ConditionalExprCount;
77     Statement->Expression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
78     CopyMem (Statement->Expression->Expression, GetConditionalExpressionList(ExpressStatement), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
79   }
80 
81   //
82   // Insert this Statement into current Form
83   //
84   if (Form == NULL) {
85     InsertTailList (&FormSet->StatementListOSF, &Statement->Link);
86   } else {
87     InsertTailList (&Form->StatementListHead, &Statement->Link);
88   }
89   return Statement;
90 }
91 
92 /**
93   Convert a numeric value to a Unicode String and insert it to String Package.
94   This string is used as the Unicode Name for the EFI Variable. This is to support
95   the deprecated vareqval opcode.
96 
97   @param FormSet        The FormSet.
98   @param Statement      The numeric question whose VarStoreInfo.VarName is the
99                         numeric value which is used to produce the Unicode Name
100                         for the EFI Variable.
101 
102   If the Statement is NULL, the ASSERT.
103   If the opcode is not Numeric, then ASSERT.
104 
105   @retval EFI_SUCCESS The funtion always succeeds.
106 **/
107 EFI_STATUS
UpdateCheckBoxStringToken(IN CONST FORM_BROWSER_FORMSET * FormSet,IN FORM_BROWSER_STATEMENT * Statement)108 UpdateCheckBoxStringToken (
109   IN CONST FORM_BROWSER_FORMSET *FormSet,
110   IN       FORM_BROWSER_STATEMENT *Statement
111   )
112 {
113   CHAR16                  Str[MAXIMUM_VALUE_CHARACTERS];
114   EFI_STRING_ID           Id;
115 
116   ASSERT (Statement != NULL);
117   ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP);
118 
119   UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1);
120 
121   Id = HiiSetString (FormSet->HiiHandle, 0, Str, NULL);
122   if (Id == 0) {
123     return EFI_OUT_OF_RESOURCES;
124   }
125 
126   Statement->VarStoreInfo.VarName = Id;
127 
128   return EFI_SUCCESS;
129 }
130 
131 /**
132   Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME.
133 
134   @param OpCodeData     The current opcode.
135 
136   @retval TRUE Yes.
137   @retval FALSE No.
138 **/
139 BOOLEAN
IsNextOpCodeGuidedVarEqName(IN UINT8 * OpCodeData)140 IsNextOpCodeGuidedVarEqName (
141   IN UINT8 *OpCodeData
142   )
143 {
144   //
145   // Get next opcode
146   //
147   OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
148   if (*OpCodeData == EFI_IFR_GUID_OP) {
149     if (CompareGuid (&gEfiIfrFrameworkGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
150       //
151       // Specific GUIDed opcodes to support IFR generated from Framework HII VFR
152       //
153       if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) {
154         return TRUE;
155       }
156     }
157   }
158 
159   return FALSE;
160 }
161 
162 /**
163   Initialize Question's members.
164 
165   @param  OpCodeData             Pointer of the raw OpCode data.
166   @param  FormSet                Pointer of the current FormSet.
167   @param  Form                   Pointer of the current Form.
168 
169   @return The Question.
170 
171 **/
172 FORM_BROWSER_STATEMENT *
CreateQuestion(IN UINT8 * OpCodeData,IN OUT FORM_BROWSER_FORMSET * FormSet,IN OUT FORM_BROWSER_FORM * Form)173 CreateQuestion (
174   IN UINT8                        *OpCodeData,
175   IN OUT FORM_BROWSER_FORMSET     *FormSet,
176   IN OUT FORM_BROWSER_FORM        *Form
177   )
178 {
179   FORM_BROWSER_STATEMENT   *Statement;
180   EFI_IFR_QUESTION_HEADER  *QuestionHdr;
181   LIST_ENTRY               *Link;
182   FORMSET_STORAGE          *Storage;
183   NAME_VALUE_NODE          *NameValueNode;
184   EFI_STATUS               Status;
185   BOOLEAN                  Find;
186 
187   Statement = CreateStatement (OpCodeData, FormSet, Form);
188   if (Statement == NULL) {
189     return NULL;
190   }
191 
192   QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
193   CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
194   CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
195   CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
196 
197   Statement->QuestionFlags = QuestionHdr->Flags;
198 
199   if (Statement->VarStoreId == 0) {
200     //
201     // VarStoreId of zero indicates no variable storage
202     //
203     return Statement;
204   }
205 
206   //
207   // Take a look at next OpCode to see whether it is a GUIDed opcode to support
208   // Framework Compatibility
209   //
210   if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
211     if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {
212       Status = UpdateCheckBoxStringToken (FormSet, Statement);
213       if (EFI_ERROR (Status)) {
214         return NULL;
215       }
216     }
217   }
218 
219   //
220   // Find Storage for this Question
221   //
222   Link = GetFirstNode (&FormSet->StorageListHead);
223   while (!IsNull (&FormSet->StorageListHead, Link)) {
224     Storage = FORMSET_STORAGE_FROM_LINK (Link);
225 
226     if (Storage->VarStoreId == Statement->VarStoreId) {
227       Statement->Storage = Storage->BrowserStorage;
228       break;
229     }
230 
231     Link = GetNextNode (&FormSet->StorageListHead, Link);
232   }
233   ASSERT (Statement->Storage != NULL);
234 
235   //
236   // Initialilze varname for Name/Value or EFI Variable
237   //
238   if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
239       (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
240     Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);
241     ASSERT (Statement->VariableName != NULL);
242 
243     if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
244       //
245       // Check whether old string node already exist.
246       //
247       Find = FALSE;
248       if (!IsListEmpty(&Statement->Storage->NameValueListHead)) {
249         Link = GetFirstNode (&Statement->Storage->NameValueListHead);
250         while (!IsNull (&Statement->Storage->NameValueListHead, Link)) {
251           NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
252 
253           if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) {
254             Find = TRUE;
255             break;
256           }
257 
258           Link = GetNextNode (&Statement->Storage->NameValueListHead, Link);
259         }
260       }
261 
262       if (!Find) {
263         //
264         // Insert to Name/Value varstore list
265         //
266         NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
267         ASSERT (NameValueNode != NULL);
268         NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
269         NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
270         ASSERT (NameValueNode->Name != NULL);
271         NameValueNode->Value = AllocateZeroPool (0x10);
272         ASSERT (NameValueNode->Value != NULL);
273         NameValueNode->EditValue = AllocateZeroPool (0x10);
274         ASSERT (NameValueNode->EditValue != NULL);
275 
276         InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
277       }
278     }
279   }
280 
281   return Statement;
282 }
283 
284 
285 /**
286   Allocate a FORM_EXPRESSION node.
287 
288   @param  Form                   The Form associated with this Expression
289   @param  OpCode                 The binary opcode data.
290 
291   @return Pointer to a FORM_EXPRESSION data structure.
292 
293 **/
294 FORM_EXPRESSION *
CreateExpression(IN OUT FORM_BROWSER_FORM * Form,IN UINT8 * OpCode)295 CreateExpression (
296   IN OUT FORM_BROWSER_FORM        *Form,
297   IN     UINT8                    *OpCode
298   )
299 {
300   FORM_EXPRESSION  *Expression;
301 
302   Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
303   ASSERT (Expression != NULL);
304   Expression->Signature = FORM_EXPRESSION_SIGNATURE;
305   InitializeListHead (&Expression->OpCodeListHead);
306   Expression->OpCode = (EFI_IFR_OP_HEADER *) OpCode;
307 
308   return Expression;
309 }
310 
311 /**
312   Create ConfigHdr string for a storage.
313 
314   @param  FormSet                Pointer of the current FormSet
315   @param  Storage                Pointer of the storage
316 
317   @retval EFI_SUCCESS            Initialize ConfigHdr success
318 
319 **/
320 EFI_STATUS
InitializeConfigHdr(IN FORM_BROWSER_FORMSET * FormSet,IN OUT FORMSET_STORAGE * Storage)321 InitializeConfigHdr (
322   IN FORM_BROWSER_FORMSET  *FormSet,
323   IN OUT FORMSET_STORAGE   *Storage
324   )
325 {
326   CHAR16      *Name;
327 
328   if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||
329       Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
330     Name = Storage->BrowserStorage->Name;
331   } else {
332     Name = NULL;
333   }
334 
335   Storage->ConfigHdr = HiiConstructConfigHdr (
336                          &Storage->BrowserStorage->Guid,
337                          Name,
338                          FormSet->DriverHandle
339                          );
340 
341   if (Storage->ConfigHdr == NULL) {
342     return EFI_NOT_FOUND;
343   }
344 
345   return EFI_SUCCESS;
346 }
347 
348 /**
349   Find the global storage link base on the input storate type, name and guid.
350 
351   For EFI_HII_VARSTORE_EFI_VARIABLE and EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER,
352   same guid + name = same storage
353 
354   For EFI_HII_VARSTORE_NAME_VALUE:
355   same guid + HiiHandle = same storage
356 
357   For EFI_HII_VARSTORE_BUFFER:
358   same guid + name + HiiHandle = same storage
359 
360   @param  StorageType                Storage type.
361   @param  StorageGuid                Storage guid.
362   @param  StorageName                Storage Name.
363   @param  HiiHandle                  HiiHandle for this varstore.
364 
365   @return Pointer to a GLOBAL_STORAGE data structure.
366 
367 **/
368 BROWSER_STORAGE *
FindStorageInList(IN UINT8 StorageType,IN EFI_GUID * StorageGuid,IN CHAR16 * StorageName,IN EFI_HII_HANDLE HiiHandle)369 FindStorageInList (
370   IN UINT8                 StorageType,
371   IN EFI_GUID              *StorageGuid,
372   IN CHAR16                *StorageName,
373   IN EFI_HII_HANDLE        HiiHandle
374   )
375 {
376   LIST_ENTRY       *Link;
377   BROWSER_STORAGE  *BrowserStorage;
378 
379   Link  = GetFirstNode (&gBrowserStorageList);
380   while (!IsNull (&gBrowserStorageList, Link)) {
381     BrowserStorage = BROWSER_STORAGE_FROM_LINK (Link);
382     Link = GetNextNode (&gBrowserStorageList, Link);
383 
384     if ((BrowserStorage->Type == StorageType) && CompareGuid (&BrowserStorage->Guid, StorageGuid)) {
385       if (StorageType == EFI_HII_VARSTORE_NAME_VALUE) {
386         if (BrowserStorage->HiiHandle == HiiHandle) {
387           return BrowserStorage;
388         }
389 
390         continue;
391       }
392 
393       ASSERT (StorageName != NULL);
394       if (StrCmp (BrowserStorage->Name, StorageName) == 0) {
395         if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE || StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
396           return BrowserStorage;
397         } else if (StorageType == EFI_HII_VARSTORE_BUFFER && BrowserStorage->HiiHandle == HiiHandle) {
398           return BrowserStorage;
399         }
400       }
401     }
402   }
403 
404   return NULL;
405 }
406 
407 /**
408   Intialize the Global Storage.
409 
410   @param  BrowserStorage              Pointer to the global storage.
411   @param  StorageType                Storage type.
412   @param  OpCodeData                 Binary data for this opcode.
413 
414 **/
415 VOID
IntializeBrowserStorage(IN BROWSER_STORAGE * BrowserStorage,IN UINT8 StorageType,IN UINT8 * OpCodeData)416 IntializeBrowserStorage (
417   IN BROWSER_STORAGE       *BrowserStorage,
418   IN UINT8                 StorageType,
419   IN UINT8                 *OpCodeData
420   )
421 {
422   switch (StorageType) {
423     case EFI_HII_VARSTORE_BUFFER:
424       CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
425       CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
426 
427       BrowserStorage->Buffer     = AllocateZeroPool (BrowserStorage->Size);
428       BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);
429       break;
430 
431     case EFI_HII_VARSTORE_EFI_VARIABLE:
432     case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
433       CopyMem (&BrowserStorage->Guid,       &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid,       sizeof (EFI_GUID));
434       CopyMem (&BrowserStorage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
435       CopyMem (&BrowserStorage->Size,       &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size,       sizeof (UINT16));
436 
437       if (StorageType ==  EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
438         BrowserStorage->Buffer     = AllocateZeroPool (BrowserStorage->Size);
439         BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);
440       }
441       break;
442 
443     case EFI_HII_VARSTORE_NAME_VALUE:
444       CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
445 
446       InitializeListHead (&BrowserStorage->NameValueListHead);
447       break;
448 
449     default:
450       break;
451   }
452 }
453 
454 /**
455   Check whether exist device path info in the ConfigHdr string.
456 
457   @param  String                 UEFI configuration string
458 
459   @retval TRUE                   Device Path exist.
460   @retval FALSE                  Not exist device path info.
461 
462 **/
463 BOOLEAN
IsDevicePathExist(IN EFI_STRING String)464 IsDevicePathExist (
465   IN  EFI_STRING                   String
466   )
467 {
468   UINTN                    Length;
469 
470   for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);
471   if (*String == 0) {
472     return FALSE;
473   }
474 
475   String += StrLen (L"PATH=");
476   if (*String == 0) {
477     return FALSE;
478   }
479 
480   for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
481   if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
482     return FALSE;
483   }
484 
485   return TRUE;
486 }
487 
488 /**
489   Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
490 
491   @param  FormSet                    Pointer of the current FormSet
492   @param  StorageType                Storage type.
493   @param  OpCodeData                 Binary data for this opcode.
494 
495   @return Pointer to a FORMSET_STORAGE data structure.
496 
497 **/
498 FORMSET_STORAGE *
CreateStorage(IN FORM_BROWSER_FORMSET * FormSet,IN UINT8 StorageType,IN UINT8 * OpCodeData)499 CreateStorage (
500   IN FORM_BROWSER_FORMSET  *FormSet,
501   IN UINT8                 StorageType,
502   IN UINT8                 *OpCodeData
503   )
504 {
505   FORMSET_STORAGE         *Storage;
506   CHAR16                  *UnicodeString;
507   UINT16                  Index;
508   BROWSER_STORAGE         *BrowserStorage;
509   EFI_GUID                *StorageGuid;
510   CHAR8                   *StorageName;
511 
512   UnicodeString = NULL;
513   StorageName   = NULL;
514   switch (StorageType) {
515     case EFI_HII_VARSTORE_BUFFER:
516       StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE *) OpCodeData)->Guid;
517       StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
518       break;
519 
520     case EFI_HII_VARSTORE_EFI_VARIABLE:
521     case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
522       StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid;
523       StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;
524       break;
525 
526     default:
527       ASSERT (StorageType == EFI_HII_VARSTORE_NAME_VALUE);
528       StorageGuid = &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid;
529       break;
530   }
531 
532   if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {
533     ASSERT (StorageName != NULL);
534 
535     UnicodeString = AllocateZeroPool (AsciiStrSize (StorageName) * 2);
536     ASSERT (UnicodeString != NULL);
537     for (Index = 0; StorageName[Index] != 0; Index++) {
538       UnicodeString[Index] = (CHAR16) StorageName[Index];
539     }
540   }
541 
542   Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
543   ASSERT (Storage != NULL);
544   Storage->Signature = FORMSET_STORAGE_SIGNATURE;
545   InsertTailList (&FormSet->StorageListHead, &Storage->Link);
546 
547   BrowserStorage = FindStorageInList(StorageType, StorageGuid, UnicodeString, FormSet->HiiHandle);
548   if (BrowserStorage == NULL) {
549     BrowserStorage = AllocateZeroPool (sizeof (BROWSER_STORAGE));
550     ASSERT (BrowserStorage != NULL);
551 
552     BrowserStorage->Signature = BROWSER_STORAGE_SIGNATURE;
553     InsertTailList (&gBrowserStorageList, &BrowserStorage->Link);
554 
555     IntializeBrowserStorage (BrowserStorage, StorageType, OpCodeData);
556     BrowserStorage->Type = StorageType;
557     if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {
558       BrowserStorage->Name = UnicodeString;
559     }
560 
561     BrowserStorage->HiiHandle = FormSet->HiiHandle;
562 
563     BrowserStorage->Initialized = FALSE;
564   }
565 
566   Storage->BrowserStorage = BrowserStorage;
567   InitializeConfigHdr (FormSet, Storage);
568   Storage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);
569   Storage->SpareStrLen = 0;
570 
571   return Storage;
572 }
573 
574 /**
575   Get Formset_storage base on the input varstoreid info.
576 
577   @param  FormSet                Pointer of the current FormSet.
578   @param  VarStoreId             Varstore ID info.
579 
580   @return Pointer to a FORMSET_STORAGE data structure.
581 
582 **/
583 FORMSET_STORAGE *
GetFstStgFromVarId(IN FORM_BROWSER_FORMSET * FormSet,IN EFI_VARSTORE_ID VarStoreId)584 GetFstStgFromVarId (
585   IN FORM_BROWSER_FORMSET  *FormSet,
586   IN EFI_VARSTORE_ID       VarStoreId
587   )
588 {
589   FORMSET_STORAGE  *FormsetStorage;
590   LIST_ENTRY       *Link;
591   BOOLEAN          Found;
592 
593   Found = FALSE;
594   FormsetStorage = NULL;
595   //
596   // Find Formset Storage for this Question
597   //
598   Link = GetFirstNode (&FormSet->StorageListHead);
599   while (!IsNull (&FormSet->StorageListHead, Link)) {
600     FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);
601 
602     if (FormsetStorage->VarStoreId == VarStoreId) {
603       Found = TRUE;
604       break;
605     }
606 
607     Link = GetNextNode (&FormSet->StorageListHead, Link);
608   }
609 
610   return Found ? FormsetStorage : NULL;
611 }
612 
613 /**
614   Get Formset_storage base on the input browser storage.
615 
616   More than one formsets may share the same browser storage,
617   this function just get the first formset storage which
618   share the browser storage.
619 
620   @param  Storage              browser storage info.
621 
622   @return Pointer to a FORMSET_STORAGE data structure.
623 
624 
625 **/
626 FORMSET_STORAGE *
GetFstStgFromBrsStg(IN BROWSER_STORAGE * Storage)627 GetFstStgFromBrsStg (
628   IN BROWSER_STORAGE       *Storage
629   )
630 {
631   FORMSET_STORAGE      *FormsetStorage;
632   LIST_ENTRY           *Link;
633   LIST_ENTRY           *FormsetLink;
634   FORM_BROWSER_FORMSET *FormSet;
635   BOOLEAN              Found;
636 
637   Found = FALSE;
638   FormsetStorage = NULL;
639 
640   FormsetLink = GetFirstNode (&gBrowserFormSetList);
641   while (!IsNull (&gBrowserFormSetList, FormsetLink)) {
642     FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormsetLink);
643     FormsetLink = GetNextNode (&gBrowserFormSetList, FormsetLink);
644 
645     Link = GetFirstNode (&FormSet->StorageListHead);
646     while (!IsNull (&FormSet->StorageListHead, Link)) {
647       FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);
648       Link = GetNextNode (&FormSet->StorageListHead, Link);
649 
650       if (FormsetStorage->BrowserStorage == Storage) {
651         Found = TRUE;
652         break;
653       }
654     }
655 
656     if (Found) {
657       break;
658     }
659   }
660 
661   return Found ? FormsetStorage : NULL;
662 }
663 
664 /**
665   Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
666 
667   @param  FormSet                Pointer of the current FormSet.
668   @param  Question               The Question to be initialized.
669   @param  Form                   Pointer of the current form.
670 
671   @retval EFI_SUCCESS            Function success.
672   @retval EFI_INVALID_PARAMETER  No storage associated with the Question.
673 
674 **/
675 EFI_STATUS
InitializeRequestElement(IN OUT FORM_BROWSER_FORMSET * FormSet,IN OUT FORM_BROWSER_STATEMENT * Question,IN OUT FORM_BROWSER_FORM * Form)676 InitializeRequestElement (
677   IN OUT FORM_BROWSER_FORMSET     *FormSet,
678   IN OUT FORM_BROWSER_STATEMENT   *Question,
679   IN OUT FORM_BROWSER_FORM        *Form
680   )
681 {
682   BROWSER_STORAGE  *Storage;
683   FORMSET_STORAGE  *FormsetStorage;
684   UINTN            StrLen;
685   UINTN            StringSize;
686   CHAR16           *NewStr;
687   CHAR16           RequestElement[30];
688   LIST_ENTRY       *Link;
689   BOOLEAN          Find;
690   FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;
691   UINTN            MaxLen;
692 
693   Storage = Question->Storage;
694   if (Storage == NULL) {
695     return EFI_INVALID_PARAMETER;
696   }
697 
698   if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
699     //
700     // <ConfigRequest> is unnecessary for EFI variable storage,
701     // GetVariable()/SetVariable() will be used to retrieve/save values
702     //
703     return EFI_SUCCESS;
704   }
705 
706   //
707   // Prepare <RequestElement>
708   //
709   if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
710       Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
711     StrLen = UnicodeSPrint (
712                RequestElement,
713                30 * sizeof (CHAR16),
714                L"&OFFSET=%04x&WIDTH=%04x",
715                Question->VarStoreInfo.VarOffset,
716                Question->StorageWidth
717                );
718     HiiToLower(RequestElement);
719     Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);
720   } else {
721     StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
722   }
723 
724   if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
725     //
726     // Password with CALLBACK flag is stored in encoded format,
727     // so don't need to append it to <ConfigRequest>
728     //
729     return EFI_SUCCESS;
730   }
731 
732   //
733   // Find Formset Storage for this Question
734   //
735   FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);
736   ASSERT (FormsetStorage != NULL);
737   StringSize = (FormsetStorage->ConfigRequest != NULL) ? StrSize (FormsetStorage->ConfigRequest) : sizeof (CHAR16);
738   MaxLen = StringSize / sizeof (CHAR16) + FormsetStorage->SpareStrLen;
739 
740   //
741   // Append <RequestElement> to <ConfigRequest>
742   //
743   if (StrLen > FormsetStorage->SpareStrLen) {
744     //
745     // Old String buffer is not sufficient for RequestElement, allocate a new one
746     //
747     MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;
748     NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
749     ASSERT (NewStr != NULL);
750     if (FormsetStorage->ConfigRequest != NULL) {
751       CopyMem (NewStr, FormsetStorage->ConfigRequest, StringSize);
752       FreePool (FormsetStorage->ConfigRequest);
753     }
754     FormsetStorage->ConfigRequest = NewStr;
755     FormsetStorage->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;
756   }
757 
758   StrCatS (FormsetStorage->ConfigRequest, MaxLen, RequestElement);
759   FormsetStorage->ElementCount++;
760   FormsetStorage->SpareStrLen -= StrLen;
761 
762   //
763   // Update the Config Request info saved in the form.
764   //
765   ConfigInfo = NULL;
766   Find       = FALSE;
767   Link = GetFirstNode (&Form->ConfigRequestHead);
768   while (!IsNull (&Form->ConfigRequestHead, Link)) {
769     ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
770 
771     if (ConfigInfo != NULL && ConfigInfo->Storage == FormsetStorage->BrowserStorage) {
772       Find = TRUE;
773       break;
774     }
775 
776     Link = GetNextNode (&Form->ConfigRequestHead, Link);
777   }
778 
779   if (!Find) {
780     ConfigInfo = AllocateZeroPool(sizeof (FORM_BROWSER_CONFIG_REQUEST));
781     ASSERT (ConfigInfo != NULL);
782     ConfigInfo->Signature     = FORM_BROWSER_CONFIG_REQUEST_SIGNATURE;
783     ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (FormsetStorage->ConfigHdr), FormsetStorage->ConfigHdr);
784     ASSERT (ConfigInfo->ConfigRequest != NULL);
785     ConfigInfo->SpareStrLen   = 0;
786     ConfigInfo->Storage       = FormsetStorage->BrowserStorage;
787     InsertTailList(&Form->ConfigRequestHead, &ConfigInfo->Link);
788   }
789   StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16);
790   MaxLen = StringSize / sizeof (CHAR16) + ConfigInfo->SpareStrLen;
791 
792   //
793   // Append <RequestElement> to <ConfigRequest>
794   //
795   if (StrLen > ConfigInfo->SpareStrLen) {
796     //
797     // Old String buffer is not sufficient for RequestElement, allocate a new one
798     //
799     MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;
800     NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
801     ASSERT (NewStr != NULL);
802     if (ConfigInfo->ConfigRequest != NULL) {
803       CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);
804       FreePool (ConfigInfo->ConfigRequest);
805     }
806     ConfigInfo->ConfigRequest = NewStr;
807     ConfigInfo->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;
808   }
809 
810   StrCatS (ConfigInfo->ConfigRequest, MaxLen, RequestElement);
811   ConfigInfo->ElementCount++;
812   ConfigInfo->SpareStrLen -= StrLen;
813   return EFI_SUCCESS;
814 }
815 
816 
817 /**
818   Free resources of a Expression.
819 
820   @param  FormSet                Pointer of the Expression
821 
822 **/
823 VOID
DestroyExpression(IN FORM_EXPRESSION * Expression)824 DestroyExpression (
825   IN FORM_EXPRESSION   *Expression
826   )
827 {
828   LIST_ENTRY         *Link;
829   EXPRESSION_OPCODE  *OpCode;
830   LIST_ENTRY         *SubExpressionLink;
831   FORM_EXPRESSION    *SubExpression;
832 
833   while (!IsListEmpty (&Expression->OpCodeListHead)) {
834     Link = GetFirstNode (&Expression->OpCodeListHead);
835     OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
836     RemoveEntryList (&OpCode->Link);
837 
838     if (OpCode->ValueList != NULL) {
839       FreePool (OpCode->ValueList);
840     }
841 
842     if (OpCode->ValueName != NULL) {
843       FreePool (OpCode->ValueName);
844     }
845 
846     if (OpCode->MapExpressionList.ForwardLink != NULL) {
847       while (!IsListEmpty (&OpCode->MapExpressionList)) {
848         SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
849         SubExpression     = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
850         RemoveEntryList(&SubExpression->Link);
851         DestroyExpression (SubExpression);
852       }
853     }
854   }
855 
856   //
857   // Free this Expression
858   //
859   FreePool (Expression);
860 }
861 
862 /**
863   Free resources of a storage.
864 
865   @param  Storage                Pointer of the storage
866 
867 **/
868 VOID
DestroyStorage(IN FORMSET_STORAGE * Storage)869 DestroyStorage (
870   IN FORMSET_STORAGE   *Storage
871   )
872 {
873   if (Storage == NULL) {
874     return;
875   }
876 
877   if (Storage->ConfigRequest != NULL) {
878     FreePool (Storage->ConfigRequest);
879   }
880 
881   FreePool (Storage);
882 }
883 
884 
885 /**
886   Free resources of a Statement.
887 
888   @param  FormSet                Pointer of the FormSet
889   @param  Statement              Pointer of the Statement
890 
891 **/
892 VOID
DestroyStatement(IN FORM_BROWSER_FORMSET * FormSet,IN OUT FORM_BROWSER_STATEMENT * Statement)893 DestroyStatement (
894   IN     FORM_BROWSER_FORMSET    *FormSet,
895   IN OUT FORM_BROWSER_STATEMENT  *Statement
896   )
897 {
898   LIST_ENTRY        *Link;
899   QUESTION_DEFAULT  *Default;
900   QUESTION_OPTION   *Option;
901   FORM_EXPRESSION   *Expression;
902 
903   //
904   // Free Default value List
905   //
906   while (!IsListEmpty (&Statement->DefaultListHead)) {
907     Link = GetFirstNode (&Statement->DefaultListHead);
908     Default = QUESTION_DEFAULT_FROM_LINK (Link);
909     RemoveEntryList (&Default->Link);
910 
911     if (Default->Value.Buffer != NULL) {
912       FreePool (Default->Value.Buffer);
913     }
914     FreePool (Default);
915   }
916 
917   //
918   // Free Options List
919   //
920   while (!IsListEmpty (&Statement->OptionListHead)) {
921     Link = GetFirstNode (&Statement->OptionListHead);
922     Option = QUESTION_OPTION_FROM_LINK (Link);
923     if (Option->SuppressExpression != NULL) {
924       FreePool (Option->SuppressExpression);
925     }
926     RemoveEntryList (&Option->Link);
927 
928     FreePool (Option);
929   }
930 
931   //
932   // Free Inconsistent List
933   //
934   while (!IsListEmpty (&Statement->InconsistentListHead)) {
935     Link = GetFirstNode (&Statement->InconsistentListHead);
936     Expression = FORM_EXPRESSION_FROM_LINK (Link);
937     RemoveEntryList (&Expression->Link);
938 
939     DestroyExpression (Expression);
940   }
941 
942   //
943   // Free NoSubmit List
944   //
945   while (!IsListEmpty (&Statement->NoSubmitListHead)) {
946     Link = GetFirstNode (&Statement->NoSubmitListHead);
947     Expression = FORM_EXPRESSION_FROM_LINK (Link);
948     RemoveEntryList (&Expression->Link);
949 
950     DestroyExpression (Expression);
951   }
952 
953   //
954   // Free WarningIf List
955   //
956   while (!IsListEmpty (&Statement->WarningListHead)) {
957     Link = GetFirstNode (&Statement->WarningListHead);
958     Expression = FORM_EXPRESSION_FROM_LINK (Link);
959     RemoveEntryList (&Expression->Link);
960 
961     DestroyExpression (Expression);
962   }
963 
964   if (Statement->Expression != NULL) {
965     FreePool (Statement->Expression);
966   }
967 
968   if (Statement->VariableName != NULL) {
969     FreePool (Statement->VariableName);
970   }
971   if (Statement->BlockName != NULL) {
972     FreePool (Statement->BlockName);
973   }
974   if (Statement->BufferValue != NULL) {
975     FreePool (Statement->BufferValue);
976   }
977   if (Statement->Operand == EFI_IFR_STRING_OP || Statement->Operand == EFI_IFR_PASSWORD_OP) {
978     DeleteString(Statement->HiiValue.Value.string, FormSet->HiiHandle);
979   }
980 }
981 
982 
983 /**
984   Free resources of a Form.
985 
986   @param  FormSet                Pointer of the FormSet
987   @param  Form                   Pointer of the Form.
988 
989 **/
990 VOID
DestroyForm(IN FORM_BROWSER_FORMSET * FormSet,IN OUT FORM_BROWSER_FORM * Form)991 DestroyForm (
992   IN     FORM_BROWSER_FORMSET  *FormSet,
993   IN OUT FORM_BROWSER_FORM     *Form
994   )
995 {
996   LIST_ENTRY              *Link;
997   FORM_EXPRESSION         *Expression;
998   FORM_BROWSER_STATEMENT  *Statement;
999   FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;
1000 
1001   //
1002   // Free Form Expressions
1003   //
1004   while (!IsListEmpty (&Form->ExpressionListHead)) {
1005     Link = GetFirstNode (&Form->ExpressionListHead);
1006     Expression = FORM_EXPRESSION_FROM_LINK (Link);
1007     RemoveEntryList (&Expression->Link);
1008 
1009     DestroyExpression (Expression);
1010   }
1011 
1012   //
1013   // Free Statements/Questions
1014   //
1015   while (!IsListEmpty (&Form->StatementListHead)) {
1016     Link = GetFirstNode (&Form->StatementListHead);
1017     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
1018     RemoveEntryList (&Statement->Link);
1019 
1020     DestroyStatement (FormSet, Statement);
1021   }
1022 
1023   //
1024   // Free ConfigRequest string.
1025   //
1026   while (!IsListEmpty (&Form->ConfigRequestHead)) {
1027     Link = GetFirstNode (&Form->ConfigRequestHead);
1028     ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
1029     RemoveEntryList (&ConfigInfo->Link);
1030 
1031     FreePool (ConfigInfo->ConfigRequest);
1032     FreePool (ConfigInfo);
1033   }
1034 
1035   if (Form->SuppressExpression != NULL) {
1036     FreePool (Form->SuppressExpression);
1037   }
1038 
1039   UiFreeMenuList (&Form->FormViewListHead);
1040 
1041   //
1042   // Free this Form
1043   //
1044   FreePool (Form);
1045 }
1046 
1047 
1048 /**
1049   Free resources allocated for a FormSet.
1050 
1051   @param  FormSet                Pointer of the FormSet
1052 
1053 **/
1054 VOID
DestroyFormSet(IN OUT FORM_BROWSER_FORMSET * FormSet)1055 DestroyFormSet (
1056   IN OUT FORM_BROWSER_FORMSET  *FormSet
1057   )
1058 {
1059   LIST_ENTRY            *Link;
1060   FORMSET_STORAGE       *Storage;
1061   FORMSET_DEFAULTSTORE  *DefaultStore;
1062   FORM_EXPRESSION       *Expression;
1063   FORM_BROWSER_FORM     *Form;
1064 
1065   if (FormSet->IfrBinaryData == NULL) {
1066     //
1067     // Uninitialized FormSet
1068     //
1069     FreePool (FormSet);
1070     return;
1071   }
1072 
1073   //
1074   // Free IFR binary buffer
1075   //
1076   FreePool (FormSet->IfrBinaryData);
1077 
1078   //
1079   // Free FormSet Storage
1080   //
1081   if (FormSet->StorageListHead.ForwardLink != NULL) {
1082     while (!IsListEmpty (&FormSet->StorageListHead)) {
1083       Link = GetFirstNode (&FormSet->StorageListHead);
1084       Storage = FORMSET_STORAGE_FROM_LINK (Link);
1085       RemoveEntryList (&Storage->Link);
1086 
1087       DestroyStorage (Storage);
1088     }
1089   }
1090 
1091   //
1092   // Free FormSet Default Store
1093   //
1094   if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
1095     while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
1096       Link = GetFirstNode (&FormSet->DefaultStoreListHead);
1097       DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
1098       RemoveEntryList (&DefaultStore->Link);
1099 
1100       FreePool (DefaultStore);
1101     }
1102   }
1103 
1104   //
1105   // Free Formset Expressions
1106   //
1107   while (!IsListEmpty (&FormSet->ExpressionListHead)) {
1108     Link = GetFirstNode (&FormSet->ExpressionListHead);
1109     Expression = FORM_EXPRESSION_FROM_LINK (Link);
1110     RemoveEntryList (&Expression->Link);
1111 
1112     DestroyExpression (Expression);
1113   }
1114 
1115   //
1116   // Free Forms
1117   //
1118   if (FormSet->FormListHead.ForwardLink != NULL) {
1119     while (!IsListEmpty (&FormSet->FormListHead)) {
1120       Link = GetFirstNode (&FormSet->FormListHead);
1121       Form = FORM_BROWSER_FORM_FROM_LINK (Link);
1122       RemoveEntryList (&Form->Link);
1123 
1124       DestroyForm (FormSet, Form);
1125     }
1126   }
1127 
1128   if (FormSet->StatementBuffer != NULL) {
1129     FreePool (FormSet->StatementBuffer);
1130   }
1131   if (FormSet->ExpressionBuffer != NULL) {
1132     FreePool (FormSet->ExpressionBuffer);
1133   }
1134 
1135   FreePool (FormSet);
1136 }
1137 
1138 
1139 /**
1140   Tell whether this Operand is an Expression OpCode or not
1141 
1142   @param  Operand                Operand of an IFR OpCode.
1143 
1144   @retval TRUE                   This is an Expression OpCode.
1145   @retval FALSE                  Not an Expression OpCode.
1146 
1147 **/
1148 BOOLEAN
IsExpressionOpCode(IN UINT8 Operand)1149 IsExpressionOpCode (
1150   IN UINT8              Operand
1151   )
1152 {
1153   if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
1154       ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP))  ||
1155       ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
1156       (Operand == EFI_IFR_CATENATE_OP) ||
1157       (Operand == EFI_IFR_TO_LOWER_OP) ||
1158       (Operand == EFI_IFR_TO_UPPER_OP) ||
1159       (Operand == EFI_IFR_MAP_OP)      ||
1160       (Operand == EFI_IFR_VERSION_OP)  ||
1161       (Operand == EFI_IFR_SECURITY_OP) ||
1162       (Operand == EFI_IFR_MATCH2_OP)) {
1163     return TRUE;
1164   } else {
1165     return FALSE;
1166   }
1167 }
1168 
1169 /**
1170   Tell whether this Operand is an Statement OpCode.
1171 
1172   @param  Operand                Operand of an IFR OpCode.
1173 
1174   @retval TRUE                   This is an Statement OpCode.
1175   @retval FALSE                  Not an Statement OpCode.
1176 
1177 **/
1178 BOOLEAN
IsStatementOpCode(IN UINT8 Operand)1179 IsStatementOpCode (
1180   IN UINT8              Operand
1181   )
1182 {
1183   if ((Operand == EFI_IFR_SUBTITLE_OP) ||
1184       (Operand == EFI_IFR_TEXT_OP) ||
1185       (Operand == EFI_IFR_RESET_BUTTON_OP) ||
1186       (Operand == EFI_IFR_REF_OP) ||
1187       (Operand == EFI_IFR_ACTION_OP) ||
1188       (Operand == EFI_IFR_NUMERIC_OP) ||
1189       (Operand == EFI_IFR_ORDERED_LIST_OP) ||
1190       (Operand == EFI_IFR_CHECKBOX_OP) ||
1191       (Operand == EFI_IFR_STRING_OP) ||
1192       (Operand == EFI_IFR_PASSWORD_OP) ||
1193       (Operand == EFI_IFR_DATE_OP) ||
1194       (Operand == EFI_IFR_TIME_OP) ||
1195       (Operand == EFI_IFR_GUID_OP) ||
1196       (Operand == EFI_IFR_ONE_OF_OP)) {
1197     return TRUE;
1198   } else {
1199     return FALSE;
1200   }
1201 }
1202 
1203 /**
1204   Tell whether this Operand is an known OpCode.
1205 
1206   @param  Operand                Operand of an IFR OpCode.
1207 
1208   @retval TRUE                   This is an Statement OpCode.
1209   @retval FALSE                  Not an Statement OpCode.
1210 
1211 **/
1212 BOOLEAN
IsUnKnownOpCode(IN UINT8 Operand)1213 IsUnKnownOpCode (
1214   IN UINT8              Operand
1215   )
1216 {
1217   return Operand > EFI_IFR_MATCH2_OP ? TRUE : FALSE;
1218 }
1219 
1220 /**
1221   Calculate number of Statemens(Questions) and Expression OpCodes.
1222 
1223   @param  FormSet                The FormSet to be counted.
1224   @param  NumberOfStatement      Number of Statemens(Questions)
1225   @param  NumberOfExpression     Number of Expression OpCodes
1226 
1227 **/
1228 VOID
CountOpCodes(IN FORM_BROWSER_FORMSET * FormSet,IN OUT UINT16 * NumberOfStatement,IN OUT UINT16 * NumberOfExpression)1229 CountOpCodes (
1230   IN  FORM_BROWSER_FORMSET  *FormSet,
1231   IN OUT  UINT16            *NumberOfStatement,
1232   IN OUT  UINT16            *NumberOfExpression
1233   )
1234 {
1235   UINT16  StatementCount;
1236   UINT16  ExpressionCount;
1237   UINT8   *OpCodeData;
1238   UINTN   Offset;
1239   UINTN   OpCodeLen;
1240 
1241   Offset = 0;
1242   StatementCount = 0;
1243   ExpressionCount = 0;
1244 
1245   while (Offset < FormSet->IfrBinaryLength) {
1246     OpCodeData = FormSet->IfrBinaryData + Offset;
1247     OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1248     Offset += OpCodeLen;
1249 
1250     if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
1251       ExpressionCount++;
1252     } else {
1253       StatementCount++;
1254     }
1255   }
1256 
1257   *NumberOfStatement = StatementCount;
1258   *NumberOfExpression = ExpressionCount;
1259 }
1260 
1261 
1262 
1263 /**
1264   Parse opcodes in the formset IFR binary.
1265 
1266   @param  FormSet                Pointer of the FormSet data structure.
1267 
1268   @retval EFI_SUCCESS            Opcode parse success.
1269   @retval Other                  Opcode parse fail.
1270 
1271 **/
1272 EFI_STATUS
ParseOpCodes(IN FORM_BROWSER_FORMSET * FormSet)1273 ParseOpCodes (
1274   IN FORM_BROWSER_FORMSET              *FormSet
1275   )
1276 {
1277   EFI_STATUS              Status;
1278   FORM_BROWSER_FORM       *CurrentForm;
1279   FORM_BROWSER_STATEMENT  *CurrentStatement;
1280   FORM_BROWSER_STATEMENT  *ParentStatement;
1281   EXPRESSION_OPCODE       *ExpressionOpCode;
1282   FORM_EXPRESSION         *CurrentExpression;
1283   UINT8                   Operand;
1284   UINT8                   Scope;
1285   UINTN                   OpCodeOffset;
1286   UINTN                   OpCodeLength;
1287   UINT8                   *OpCodeData;
1288   UINT8                   ScopeOpCode;
1289   FORMSET_STORAGE         *Storage;
1290   FORMSET_DEFAULTSTORE    *DefaultStore;
1291   QUESTION_DEFAULT        *CurrentDefault;
1292   QUESTION_OPTION         *CurrentOption;
1293   UINT8                   Width;
1294   UINT16                  NumberOfStatement;
1295   UINT16                  NumberOfExpression;
1296   EFI_IMAGE_ID            *ImageId;
1297   BOOLEAN                 SuppressForQuestion;
1298   BOOLEAN                 SuppressForOption;
1299   UINT16                  DepthOfDisable;
1300   BOOLEAN                 OpCodeDisabled;
1301   BOOLEAN                 SingleOpCodeExpression;
1302   BOOLEAN                 InScopeDefault;
1303   EFI_HII_VALUE           *Value;
1304   EFI_IFR_FORM_MAP_METHOD *MapMethod;
1305   UINT8                   MapScopeDepth;
1306   LIST_ENTRY              *Link;
1307   FORMSET_STORAGE         *VarStorage;
1308   LIST_ENTRY              *MapExpressionList;
1309   EFI_VARSTORE_ID         TempVarstoreId;
1310   BOOLEAN                 InScopeDisable;
1311   INTN                    ConditionalExprCount;
1312   BOOLEAN                 InUnknownScope;
1313   UINT8                   UnknownDepth;
1314   FORMSET_DEFAULTSTORE    *PreDefaultStore;
1315   LIST_ENTRY              *DefaultLink;
1316   BOOLEAN                 HaveInserted;
1317 
1318   SuppressForQuestion      = FALSE;
1319   SuppressForOption        = FALSE;
1320   InScopeDisable           = FALSE;
1321   DepthOfDisable           = 0;
1322   OpCodeDisabled           = FALSE;
1323   SingleOpCodeExpression   = FALSE;
1324   InScopeDefault           = FALSE;
1325   CurrentExpression        = NULL;
1326   CurrentDefault           = NULL;
1327   CurrentOption            = NULL;
1328   ImageId                  = NULL;
1329   MapMethod                = NULL;
1330   MapScopeDepth            = 0;
1331   Link                     = NULL;
1332   VarStorage               = NULL;
1333   MapExpressionList        = NULL;
1334   TempVarstoreId           = 0;
1335   ConditionalExprCount     = 0;
1336   InUnknownScope           = FALSE;
1337   UnknownDepth             = 0;
1338 
1339   //
1340   // Get the number of Statements and Expressions
1341   //
1342   CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
1343 
1344   mStatementIndex = 0;
1345   mUsedQuestionId = 1;
1346   FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
1347   if (FormSet->StatementBuffer == NULL) {
1348     return EFI_OUT_OF_RESOURCES;
1349   }
1350 
1351   mExpressionOpCodeIndex = 0;
1352   FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
1353   if (FormSet->ExpressionBuffer == NULL) {
1354     return EFI_OUT_OF_RESOURCES;
1355   }
1356 
1357   InitializeListHead (&FormSet->StatementListOSF);
1358   InitializeListHead (&FormSet->StorageListHead);
1359   InitializeListHead (&FormSet->SaveFailStorageListHead);
1360   InitializeListHead (&FormSet->DefaultStoreListHead);
1361   InitializeListHead (&FormSet->FormListHead);
1362   InitializeListHead (&FormSet->ExpressionListHead);
1363   ResetCurrentExpressionStack ();
1364   ResetMapExpressionListStack ();
1365 
1366   CurrentForm = NULL;
1367   CurrentStatement = NULL;
1368   ParentStatement  = NULL;
1369 
1370   ResetScopeStack ();
1371 
1372   OpCodeOffset = 0;
1373   while (OpCodeOffset < FormSet->IfrBinaryLength) {
1374     OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
1375 
1376     OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1377     OpCodeOffset += OpCodeLength;
1378     Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
1379     Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
1380 
1381     if (InUnknownScope) {
1382       if (Operand == EFI_IFR_END_OP) {
1383         UnknownDepth --;
1384 
1385         if (UnknownDepth == 0) {
1386           InUnknownScope = FALSE;
1387         }
1388       } else {
1389         if (Scope != 0) {
1390           UnknownDepth ++;
1391         }
1392       }
1393 
1394       continue;
1395     }
1396 
1397     if (IsUnKnownOpCode(Operand)) {
1398       if (Scope != 0) {
1399         InUnknownScope = TRUE;
1400         UnknownDepth ++;
1401       }
1402 
1403       continue;
1404     }
1405 
1406     //
1407     // If scope bit set, push onto scope stack
1408     //
1409     if (Scope != 0) {
1410       PushScope (Operand);
1411     }
1412 
1413     if (OpCodeDisabled) {
1414       //
1415       // DisableIf Expression is evaluated to be TRUE, try to find its end.
1416       // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
1417       //
1418       if (Operand == EFI_IFR_DISABLE_IF_OP) {
1419         DepthOfDisable++;
1420       } else if (Operand == EFI_IFR_END_OP) {
1421         Status = PopScope (&ScopeOpCode);
1422         if (EFI_ERROR (Status)) {
1423           return Status;
1424         }
1425 
1426         if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
1427           if (DepthOfDisable == 0) {
1428             InScopeDisable = FALSE;
1429             OpCodeDisabled = FALSE;
1430           } else {
1431             DepthOfDisable--;
1432           }
1433         }
1434       }
1435       continue;
1436     }
1437 
1438     if (IsExpressionOpCode (Operand)) {
1439       ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
1440       mExpressionOpCodeIndex++;
1441 
1442       ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
1443       ExpressionOpCode->Operand = Operand;
1444       Value = &ExpressionOpCode->Value;
1445 
1446       switch (Operand) {
1447       case EFI_IFR_EQ_ID_VAL_OP:
1448         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1449 
1450         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1451         CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
1452         break;
1453 
1454       case EFI_IFR_EQ_ID_ID_OP:
1455         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
1456         CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
1457         break;
1458 
1459       case EFI_IFR_EQ_ID_VAL_LIST_OP:
1460         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1461         CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
1462         ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
1463         break;
1464 
1465       case EFI_IFR_TO_STRING_OP:
1466       case EFI_IFR_FIND_OP:
1467         ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
1468         break;
1469 
1470       case EFI_IFR_STRING_REF1_OP:
1471         Value->Type = EFI_IFR_TYPE_STRING;
1472         CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
1473         break;
1474 
1475       case EFI_IFR_RULE_REF_OP:
1476         ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
1477         break;
1478 
1479       case EFI_IFR_SPAN_OP:
1480         ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
1481         break;
1482 
1483       case EFI_IFR_THIS_OP:
1484         ASSERT (ParentStatement != NULL);
1485         ExpressionOpCode->QuestionId = ParentStatement->QuestionId;
1486         break;
1487 
1488       case EFI_IFR_SECURITY_OP:
1489         CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
1490         break;
1491 
1492       case EFI_IFR_MATCH2_OP:
1493         CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_MATCH2 *) OpCodeData)->SyntaxType, sizeof (EFI_GUID));
1494         break;
1495 
1496       case EFI_IFR_GET_OP:
1497       case EFI_IFR_SET_OP:
1498         CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
1499         if (TempVarstoreId != 0) {
1500           if (FormSet->StorageListHead.ForwardLink != NULL) {
1501             Link = GetFirstNode (&FormSet->StorageListHead);
1502             while (!IsNull (&FormSet->StorageListHead, Link)) {
1503               VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
1504               if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
1505                 ExpressionOpCode->VarStorage = VarStorage->BrowserStorage;
1506                 break;
1507               }
1508               Link = GetNextNode (&FormSet->StorageListHead, Link);
1509             }
1510           }
1511           if (ExpressionOpCode->VarStorage == NULL) {
1512             //
1513             // VarStorage is not found.
1514             //
1515             return EFI_INVALID_PARAMETER;
1516           }
1517         }
1518         ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;
1519         switch (ExpressionOpCode->ValueType) {
1520         case EFI_IFR_TYPE_BOOLEAN:
1521         case EFI_IFR_TYPE_NUM_SIZE_8:
1522           ExpressionOpCode->ValueWidth = 1;
1523           break;
1524 
1525         case EFI_IFR_TYPE_NUM_SIZE_16:
1526         case EFI_IFR_TYPE_STRING:
1527           ExpressionOpCode->ValueWidth = 2;
1528           break;
1529 
1530         case EFI_IFR_TYPE_NUM_SIZE_32:
1531           ExpressionOpCode->ValueWidth = 4;
1532           break;
1533 
1534         case EFI_IFR_TYPE_NUM_SIZE_64:
1535           ExpressionOpCode->ValueWidth = 8;
1536           break;
1537 
1538         case EFI_IFR_TYPE_DATE:
1539           ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_DATE);
1540           break;
1541 
1542         case EFI_IFR_TYPE_TIME:
1543           ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_TIME);
1544           break;
1545 
1546         case EFI_IFR_TYPE_REF:
1547           ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);
1548           break;
1549 
1550         case EFI_IFR_TYPE_OTHER:
1551         case EFI_IFR_TYPE_UNDEFINED:
1552         case EFI_IFR_TYPE_ACTION:
1553         case EFI_IFR_TYPE_BUFFER:
1554         default:
1555           //
1556           // Invalid value type for Get/Set opcode.
1557           //
1558           return EFI_INVALID_PARAMETER;
1559         }
1560         CopyMem (&ExpressionOpCode->VarStoreInfo.VarName,   &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName,   sizeof (EFI_STRING_ID));
1561         CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));
1562         if ((ExpressionOpCode->VarStorage != NULL) &&
1563             (ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE ||
1564              ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
1565           ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle);
1566           if (ExpressionOpCode->ValueName == NULL) {
1567             //
1568             // String ID is invalid.
1569             //
1570             return EFI_INVALID_PARAMETER;
1571           }
1572         }
1573         break;
1574 
1575       case EFI_IFR_QUESTION_REF1_OP:
1576         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1577         break;
1578 
1579       case EFI_IFR_QUESTION_REF3_OP:
1580         if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
1581           CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1582 
1583           if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
1584             CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
1585           }
1586         }
1587         break;
1588 
1589       //
1590       // constant
1591       //
1592       case EFI_IFR_TRUE_OP:
1593         Value->Type = EFI_IFR_TYPE_BOOLEAN;
1594         Value->Value.b = TRUE;
1595         break;
1596 
1597       case EFI_IFR_FALSE_OP:
1598         Value->Type = EFI_IFR_TYPE_BOOLEAN;
1599         Value->Value.b = FALSE;
1600         break;
1601 
1602       case EFI_IFR_ONE_OP:
1603         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1604         Value->Value.u8 = 1;
1605         break;
1606 
1607       case EFI_IFR_ZERO_OP:
1608         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1609         Value->Value.u8 = 0;
1610         break;
1611 
1612       case EFI_IFR_ONES_OP:
1613         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1614         Value->Value.u64 = 0xffffffffffffffffULL;
1615         break;
1616 
1617       case EFI_IFR_UINT8_OP:
1618         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1619         Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
1620         break;
1621 
1622       case EFI_IFR_UINT16_OP:
1623         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1624         CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
1625         break;
1626 
1627       case EFI_IFR_UINT32_OP:
1628         Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1629         CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
1630         break;
1631 
1632       case EFI_IFR_UINT64_OP:
1633         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1634         CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
1635         break;
1636 
1637       case EFI_IFR_UNDEFINED_OP:
1638         Value->Type = EFI_IFR_TYPE_UNDEFINED;
1639         break;
1640 
1641       case EFI_IFR_VERSION_OP:
1642         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1643         Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
1644         break;
1645 
1646       default:
1647         break;
1648       }
1649       //
1650       // Create sub expression nested in MAP opcode
1651       //
1652       if (CurrentExpression == NULL && MapScopeDepth > 0) {
1653         CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
1654         ASSERT (MapExpressionList != NULL);
1655         InsertTailList (MapExpressionList, &CurrentExpression->Link);
1656         if (Scope == 0) {
1657           SingleOpCodeExpression = TRUE;
1658         }
1659       }
1660       ASSERT (CurrentExpression != NULL);
1661       InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
1662       if (Operand == EFI_IFR_MAP_OP) {
1663         //
1664         // Store current Map Expression List.
1665         //
1666         if (MapExpressionList != NULL) {
1667           PushMapExpressionList (MapExpressionList);
1668         }
1669         //
1670         // Initialize new Map Expression List.
1671         //
1672         MapExpressionList = &ExpressionOpCode->MapExpressionList;
1673         InitializeListHead (MapExpressionList);
1674         //
1675         // Store current expression.
1676         //
1677         PushCurrentExpression (CurrentExpression);
1678         CurrentExpression = NULL;
1679         MapScopeDepth ++;
1680       } else if (SingleOpCodeExpression) {
1681         //
1682         // There are two cases to indicate the end of an Expression:
1683         // for single OpCode expression: one Expression OpCode
1684         // for expression consists of more than one OpCode: EFI_IFR_END
1685         //
1686         SingleOpCodeExpression = FALSE;
1687 
1688         if (InScopeDisable && CurrentForm == NULL) {
1689           //
1690           // This is DisableIf expression for Form, it should be a constant expression
1691           //
1692           Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1693           if (EFI_ERROR (Status)) {
1694             return Status;
1695           }
1696 
1697           OpCodeDisabled = IsTrue(&CurrentExpression->Result);
1698         }
1699 
1700         CurrentExpression = NULL;
1701       }
1702 
1703       continue;
1704     }
1705 
1706     //
1707     // Parse the Opcode
1708     //
1709     switch (Operand) {
1710 
1711     case EFI_IFR_FORM_SET_OP:
1712       //
1713       // Check the formset GUID
1714       //
1715       if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1716         return EFI_INVALID_PARAMETER;
1717       }
1718 
1719       CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1720       CopyMem (&FormSet->Help,         &((EFI_IFR_FORM_SET *) OpCodeData)->Help,         sizeof (EFI_STRING_ID));
1721       FormSet->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData;//save the opcode address of formset
1722 
1723       if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
1724         //
1725         // The formset OpCode contains ClassGuid
1726         //
1727         FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
1728         CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
1729       }
1730       break;
1731 
1732     case EFI_IFR_FORM_OP:
1733       //
1734       // Create a new Form for this FormSet
1735       //
1736       CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1737       ASSERT (CurrentForm != NULL);
1738       CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1739       InitializeListHead (&CurrentForm->ExpressionListHead);
1740       InitializeListHead (&CurrentForm->StatementListHead);
1741       InitializeListHead (&CurrentForm->ConfigRequestHead);
1742       InitializeListHead (&CurrentForm->FormViewListHead);
1743 
1744       CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
1745       CopyMem (&CurrentForm->FormId,    &((EFI_IFR_FORM *) OpCodeData)->FormId,    sizeof (UINT16));
1746       CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1747 
1748       ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1749       if ( ConditionalExprCount > 0) {
1750         //
1751         // Form is inside of suppressif
1752         //
1753         CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1754                                                  (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1755         ASSERT (CurrentForm->SuppressExpression != NULL);
1756         CurrentForm->SuppressExpression->Count     = (UINTN) ConditionalExprCount;
1757         CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1758         CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
1759       }
1760 
1761       if (Scope != 0) {
1762         //
1763         // Enter scope of a Form, suppressif will be used for Question or Option
1764         //
1765         SuppressForQuestion = TRUE;
1766       }
1767 
1768       //
1769       // Insert into Form list of this FormSet
1770       //
1771       InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1772       break;
1773 
1774     case EFI_IFR_FORM_MAP_OP:
1775       //
1776       // Create a new Form for this FormSet
1777       //
1778       CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1779       ASSERT (CurrentForm != NULL);
1780       CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1781       InitializeListHead (&CurrentForm->ExpressionListHead);
1782       InitializeListHead (&CurrentForm->StatementListHead);
1783       InitializeListHead (&CurrentForm->ConfigRequestHead);
1784       InitializeListHead (&CurrentForm->FormViewListHead);
1785 
1786       CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1787 
1788       MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1789       //
1790       // FormMap Form must contain at least one Map Method.
1791       //
1792       if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) {
1793         return EFI_INVALID_PARAMETER;
1794       }
1795       //
1796       // Try to find the standard form map method.
1797       //
1798       while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) {
1799         if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {
1800           CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1801           CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
1802           break;
1803         }
1804         MapMethod ++;
1805       }
1806       //
1807       // If the standard form map method is not found, the first map method title will be used.
1808       //
1809       if (CurrentForm->FormTitle == 0) {
1810         MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1811         CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1812       }
1813 
1814       ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1815       if ( ConditionalExprCount > 0) {
1816         //
1817         // Form is inside of suppressif
1818         //
1819         CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1820                                                  (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1821         ASSERT (CurrentForm->SuppressExpression != NULL);
1822         CurrentForm->SuppressExpression->Count     = (UINTN) ConditionalExprCount;
1823         CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1824         CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
1825       }
1826 
1827       if (Scope != 0) {
1828         //
1829         // Enter scope of a Form, suppressif will be used for Question or Option
1830         //
1831         SuppressForQuestion = TRUE;
1832       }
1833 
1834       //
1835       // Insert into Form list of this FormSet
1836       //
1837       InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1838       break;
1839 
1840     //
1841     // Storage
1842     //
1843     case EFI_IFR_VARSTORE_OP:
1844       //
1845       // Create a buffer Storage for this FormSet
1846       //
1847       Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);
1848       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1849       break;
1850 
1851     case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1852       //
1853       // Create a name/value Storage for this FormSet
1854       //
1855       Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);
1856       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1857       break;
1858 
1859     case EFI_IFR_VARSTORE_EFI_OP:
1860       //
1861       // Create a EFI variable Storage for this FormSet
1862       //
1863       if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
1864         //
1865         // Create efi varstore with format follow UEFI spec before 2.3.1.
1866         //
1867         Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);
1868       } else {
1869         //
1870         // Create efi varstore with format follow UEFI spec 2.3.1 and later.
1871         //
1872         Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
1873       }
1874       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1875       break;
1876 
1877     //
1878     // DefaultStore
1879     //
1880     case EFI_IFR_DEFAULTSTORE_OP:
1881       HaveInserted = FALSE;
1882       DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
1883       ASSERT (DefaultStore != NULL);
1884       DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1885 
1886       CopyMem (&DefaultStore->DefaultId,   &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId,   sizeof (UINT16));
1887       CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1888       //
1889       // Insert it to the DefaultStore list of this Formset with ascending order.
1890       //
1891       if (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
1892         DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
1893         while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
1894           PreDefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
1895           DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
1896           if (DefaultStore->DefaultId < PreDefaultStore->DefaultId) {
1897             InsertTailList (&PreDefaultStore->Link, &DefaultStore->Link);
1898             HaveInserted = TRUE;
1899             break;
1900           }
1901         }
1902       }
1903       if (!HaveInserted) {
1904         InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1905       }
1906       break;
1907 
1908     //
1909     // Statements
1910     //
1911     case EFI_IFR_SUBTITLE_OP:
1912       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1913       ASSERT (CurrentStatement != NULL);
1914 
1915       CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
1916       CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1917       break;
1918 
1919     case EFI_IFR_TEXT_OP:
1920       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1921       ASSERT (CurrentStatement != NULL);
1922       CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1923       CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1924       break;
1925 
1926     case EFI_IFR_RESET_BUTTON_OP:
1927       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1928       ASSERT (CurrentStatement != NULL);
1929       CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1930       CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1931       break;
1932 
1933     //
1934     // Questions
1935     //
1936     case EFI_IFR_ACTION_OP:
1937       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1938       ASSERT (CurrentStatement != NULL);
1939       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
1940 
1941       if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1942         //
1943         // No QuestionConfig present, so no configuration string will be processed
1944         //
1945         CurrentStatement->QuestionConfig = 0;
1946       } else {
1947         CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1948       }
1949       break;
1950 
1951     case EFI_IFR_REF_OP:
1952       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1953       ASSERT (CurrentStatement != NULL);
1954       Value = &CurrentStatement->HiiValue;
1955       Value->Type = EFI_IFR_TYPE_REF;
1956       if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
1957         CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
1958 
1959         if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1960           CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1961 
1962           if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1963             CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1964 
1965             if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1966               CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1967             }
1968           }
1969         }
1970       }
1971       CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
1972       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
1973       break;
1974 
1975     case EFI_IFR_ONE_OF_OP:
1976     case EFI_IFR_NUMERIC_OP:
1977       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1978       ASSERT(CurrentStatement != NULL);
1979 
1980       CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1981       Value = &CurrentStatement->HiiValue;
1982 
1983       switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1984       case EFI_IFR_NUMERIC_SIZE_1:
1985         CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1986         CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1987         CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
1988         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
1989         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1990         break;
1991 
1992       case EFI_IFR_NUMERIC_SIZE_2:
1993         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1994         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1995         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step,     sizeof (UINT16));
1996         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
1997         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1998         break;
1999 
2000       case EFI_IFR_NUMERIC_SIZE_4:
2001         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
2002         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
2003         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step,     sizeof (UINT32));
2004         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
2005         Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
2006         break;
2007 
2008       case EFI_IFR_NUMERIC_SIZE_8:
2009         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
2010         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
2011         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step,     sizeof (UINT64));
2012         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
2013         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2014         break;
2015 
2016       default:
2017         break;
2018       }
2019 
2020       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2021 
2022       if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
2023         SuppressForOption = TRUE;
2024       }
2025       break;
2026 
2027     case EFI_IFR_ORDERED_LIST_OP:
2028       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2029       ASSERT(CurrentStatement != NULL);
2030 
2031       CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
2032       CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
2033 
2034       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
2035       CurrentStatement->BufferValue = NULL;
2036 
2037       if (Scope != 0) {
2038         SuppressForOption = TRUE;
2039       }
2040       break;
2041 
2042     case EFI_IFR_CHECKBOX_OP:
2043       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2044       ASSERT(CurrentStatement != NULL);
2045 
2046       CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
2047       CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
2048       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
2049 
2050       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2051 
2052       break;
2053 
2054     case EFI_IFR_STRING_OP:
2055       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2056       ASSERT (CurrentStatement != NULL);
2057       //
2058       // MinSize is the minimum number of characters that can be accepted for this opcode,
2059       // MaxSize is the maximum number of characters that can be accepted for this opcode.
2060       // The characters are stored as Unicode, so the storage width should multiply 2.
2061       //
2062       CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
2063       CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
2064       CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2065       CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
2066 
2067       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2068       CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
2069       CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
2070 
2071       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2072       break;
2073 
2074     case EFI_IFR_PASSWORD_OP:
2075       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2076       ASSERT (CurrentStatement != NULL);
2077       //
2078       // MinSize is the minimum number of characters that can be accepted for this opcode,
2079       // MaxSize is the maximum number of characters that can be accepted for this opcode.
2080       // The characters are stored as Unicode, so the storage width should multiply 2.
2081       //
2082       CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
2083       CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
2084       CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2085 
2086       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2087       CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
2088       CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
2089 
2090       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2091       break;
2092 
2093     case EFI_IFR_DATE_OP:
2094       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2095       ASSERT(CurrentStatement != NULL);
2096 
2097       CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
2098       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
2099 
2100       if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
2101         CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
2102 
2103         InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2104       } else {
2105         //
2106         // Don't assign storage for RTC type of date/time
2107         //
2108         CurrentStatement->Storage = NULL;
2109         CurrentStatement->StorageWidth = 0;
2110       }
2111       break;
2112 
2113     case EFI_IFR_TIME_OP:
2114       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2115       ASSERT(CurrentStatement != NULL);
2116 
2117       CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
2118       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
2119 
2120       if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
2121         CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
2122 
2123         InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2124       } else {
2125         //
2126         // Don't assign storage for RTC type of date/time
2127         //
2128         CurrentStatement->Storage = NULL;
2129         CurrentStatement->StorageWidth = 0;
2130       }
2131       break;
2132 
2133     //
2134     // Default
2135     //
2136     case EFI_IFR_DEFAULT_OP:
2137       //
2138       // EFI_IFR_DEFAULT appear in scope of a Question,
2139       // It creates a default value for the current question.
2140       // A Question may have more than one Default value which have different default types.
2141       //
2142       CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
2143       ASSERT (CurrentDefault != NULL);
2144       CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2145 
2146       CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
2147       CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
2148       if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {
2149         CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2150         CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *) OpCodeData)->Value);
2151         ASSERT (CurrentDefault->Value.Buffer != NULL);
2152       } else {
2153         CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2154         ExtendValueToU64 (&CurrentDefault->Value);
2155       }
2156 
2157       //
2158       // Insert to Default Value list of current Question
2159       //
2160       InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
2161 
2162       if (Scope != 0) {
2163         InScopeDefault = TRUE;
2164       }
2165       break;
2166 
2167     //
2168     // Option
2169     //
2170     case EFI_IFR_ONE_OF_OPTION_OP:
2171       ASSERT (ParentStatement != NULL);
2172       if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP && ((((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0)) {
2173         //
2174         // It's keep the default value for ordered list opcode.
2175         //
2176         CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
2177         ASSERT (CurrentDefault != NULL);
2178         CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2179 
2180         CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;
2181         if ((((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
2182           CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2183         } else {
2184           CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2185         }
2186 
2187         CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2188         CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value);
2189         ASSERT (CurrentDefault->Value.Buffer != NULL);
2190 
2191         //
2192         // Insert to Default Value list of current Question
2193         //
2194         InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
2195         break;
2196       }
2197 
2198       //
2199       // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
2200       // It create a selection for use in current Question.
2201       //
2202       CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
2203       ASSERT (CurrentOption != NULL);
2204       CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
2205       CurrentOption->OpCode    = (EFI_IFR_ONE_OF_OPTION *) OpCodeData;
2206 
2207       CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
2208       CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
2209       CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
2210       CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2211       ExtendValueToU64 (&CurrentOption->Value);
2212 
2213       ConditionalExprCount = GetConditionalExpressionCount(ExpressOption);
2214       if ( ConditionalExprCount > 0) {
2215         //
2216         // Form is inside of suppressif
2217         //
2218         CurrentOption->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
2219                                                  (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
2220         ASSERT (CurrentOption->SuppressExpression != NULL);
2221         CurrentOption->SuppressExpression->Count     = (UINTN) ConditionalExprCount;
2222         CurrentOption->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
2223         CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList(ExpressOption), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
2224       }
2225 
2226       //
2227       // Insert to Option list of current Question
2228       //
2229       InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link);
2230       //
2231       // Now we know the Storage width of nested Ordered List
2232       //
2233       if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->BufferValue == NULL)) {
2234         Width = 1;
2235         switch (CurrentOption->Value.Type) {
2236         case EFI_IFR_TYPE_NUM_SIZE_8:
2237           Width = 1;
2238           break;
2239 
2240         case EFI_IFR_TYPE_NUM_SIZE_16:
2241           Width = 2;
2242           break;
2243 
2244         case EFI_IFR_TYPE_NUM_SIZE_32:
2245           Width = 4;
2246           break;
2247 
2248         case EFI_IFR_TYPE_NUM_SIZE_64:
2249           Width = 8;
2250           break;
2251 
2252         default:
2253           //
2254           // Invalid type for Ordered List
2255           //
2256           break;
2257         }
2258 
2259         ParentStatement->StorageWidth = (UINT16) (ParentStatement->MaxContainers * Width);
2260         ParentStatement->BufferValue = AllocateZeroPool (ParentStatement->StorageWidth);
2261         ParentStatement->ValueType = CurrentOption->Value.Type;
2262         if (ParentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
2263           ParentStatement->HiiValue.Buffer = ParentStatement->BufferValue;
2264           ParentStatement->HiiValue.BufferLen = ParentStatement->StorageWidth;
2265         }
2266 
2267         InitializeRequestElement (FormSet, ParentStatement, CurrentForm);
2268       }
2269       break;
2270 
2271     //
2272     // Conditional
2273     //
2274     case EFI_IFR_NO_SUBMIT_IF_OP:
2275     case EFI_IFR_INCONSISTENT_IF_OP:
2276       //
2277       // Create an Expression node
2278       //
2279       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2280       CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
2281 
2282       if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
2283         CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
2284         InsertTailList (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link);
2285       } else {
2286         CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
2287         InsertTailList (&ParentStatement->InconsistentListHead, &CurrentExpression->Link);
2288       }
2289 
2290       //
2291       // Take a look at next OpCode to see whether current expression consists
2292       // of single OpCode
2293       //
2294       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2295         SingleOpCodeExpression = TRUE;
2296       }
2297       break;
2298 
2299     case EFI_IFR_WARNING_IF_OP:
2300       //
2301       // Create an Expression node
2302       //
2303       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2304       CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));
2305       CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;
2306       CurrentExpression->Type    = EFI_HII_EXPRESSION_WARNING_IF;
2307       InsertTailList (&ParentStatement->WarningListHead, &CurrentExpression->Link);
2308 
2309       //
2310       // Take a look at next OpCode to see whether current expression consists
2311       // of single OpCode
2312       //
2313       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2314         SingleOpCodeExpression = TRUE;
2315       }
2316       break;
2317 
2318     case EFI_IFR_SUPPRESS_IF_OP:
2319       //
2320       // Question and Option will appear in scope of this OpCode
2321       //
2322       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2323       CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
2324 
2325       if (CurrentForm == NULL) {
2326         InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
2327       } else {
2328         InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2329       }
2330 
2331       if (SuppressForOption) {
2332         PushConditionalExpression(CurrentExpression, ExpressOption);
2333       } else if (SuppressForQuestion) {
2334         PushConditionalExpression(CurrentExpression, ExpressStatement);
2335       } else {
2336         PushConditionalExpression(CurrentExpression, ExpressForm);
2337       }
2338 
2339       //
2340       // Take a look at next OpCode to see whether current expression consists
2341       // of single OpCode
2342       //
2343       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2344         SingleOpCodeExpression = TRUE;
2345       }
2346       break;
2347 
2348     case EFI_IFR_GRAY_OUT_IF_OP:
2349       //
2350       // Questions will appear in scope of this OpCode
2351       //
2352       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2353       CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
2354       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2355       PushConditionalExpression(CurrentExpression, ExpressStatement);
2356 
2357       //
2358       // Take a look at next OpCode to see whether current expression consists
2359       // of single OpCode
2360       //
2361       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2362         SingleOpCodeExpression = TRUE;
2363       }
2364       break;
2365 
2366     case EFI_IFR_DISABLE_IF_OP:
2367       //
2368       // The DisableIf expression should only rely on constant, so it could be
2369       // evaluated at initialization and it will not be queued
2370       //
2371       CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
2372       ASSERT (CurrentExpression != NULL);
2373       CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
2374       CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
2375       InitializeListHead (&CurrentExpression->OpCodeListHead);
2376 
2377       if (CurrentForm != NULL) {
2378         //
2379         // This is DisableIf for Question, enqueue it to Form expression list
2380         //
2381         InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2382         PushConditionalExpression(CurrentExpression, ExpressStatement);
2383       }
2384 
2385       OpCodeDisabled  = FALSE;
2386       InScopeDisable  = TRUE;
2387       //
2388       // Take a look at next OpCode to see whether current expression consists
2389       // of single OpCode
2390       //
2391       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2392         SingleOpCodeExpression = TRUE;
2393       }
2394       break;
2395 
2396     //
2397     // Expression
2398     //
2399     case EFI_IFR_VALUE_OP:
2400       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2401       CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
2402       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2403 
2404       if (InScopeDefault) {
2405         //
2406         // Used for default (EFI_IFR_DEFAULT)
2407         //
2408         CurrentDefault->ValueExpression = CurrentExpression;
2409       } else {
2410         //
2411         // If used for a question, then the question will be read-only
2412         //
2413         //
2414         // Make sure CurrentStatement is not NULL.
2415         // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2416         // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2417         //
2418         ASSERT (ParentStatement != NULL);
2419         ParentStatement->ValueExpression = CurrentExpression;
2420       }
2421 
2422       //
2423       // Take a look at next OpCode to see whether current expression consists
2424       // of single OpCode
2425       //
2426       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2427         SingleOpCodeExpression = TRUE;
2428       }
2429       break;
2430 
2431     case EFI_IFR_RULE_OP:
2432       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2433       CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
2434 
2435       CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
2436       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2437 
2438       //
2439       // Take a look at next OpCode to see whether current expression consists
2440       // of single OpCode
2441       //
2442       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2443         SingleOpCodeExpression = TRUE;
2444       }
2445       break;
2446 
2447     case EFI_IFR_READ_OP:
2448       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2449       CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
2450       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2451 
2452       //
2453       // Make sure CurrentStatement is not NULL.
2454       // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2455       // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2456       //
2457       ASSERT (ParentStatement != NULL);
2458       ParentStatement->ReadExpression = CurrentExpression;
2459 
2460       //
2461       // Take a look at next OpCode to see whether current expression consists
2462       // of single OpCode
2463       //
2464       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2465         SingleOpCodeExpression = TRUE;
2466       }
2467       break;
2468 
2469     case EFI_IFR_WRITE_OP:
2470       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2471       CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
2472       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2473 
2474       //
2475       // Make sure CurrentStatement is not NULL.
2476       // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2477       // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2478       //
2479       ASSERT (ParentStatement != NULL);
2480       ParentStatement->WriteExpression = CurrentExpression;
2481 
2482       //
2483       // Take a look at next OpCode to see whether current expression consists
2484       // of single OpCode
2485       //
2486       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2487         SingleOpCodeExpression = TRUE;
2488       }
2489       break;
2490 
2491     //
2492     // Image
2493     //
2494     case EFI_IFR_IMAGE_OP:
2495       //
2496       // Get ScopeOpcode from top of stack
2497       //
2498       PopScope (&ScopeOpCode);
2499       PushScope (ScopeOpCode);
2500 
2501       switch (ScopeOpCode) {
2502       case EFI_IFR_FORM_SET_OP:
2503         ImageId = &FormSet->ImageId;
2504         break;
2505 
2506       case EFI_IFR_FORM_OP:
2507       case EFI_IFR_FORM_MAP_OP:
2508         ASSERT (CurrentForm != NULL);
2509         ImageId = &CurrentForm->ImageId;
2510         break;
2511 
2512       case EFI_IFR_ONE_OF_OPTION_OP:
2513         ASSERT (CurrentOption != NULL);
2514         ImageId = &CurrentOption->ImageId;
2515         break;
2516 
2517       default:
2518         //
2519         // Make sure CurrentStatement is not NULL.
2520         // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2521         // file is wrongly generated by tools such as VFR Compiler.
2522         //
2523         ASSERT (ParentStatement != NULL);
2524         ImageId = &ParentStatement->ImageId;
2525         break;
2526       }
2527 
2528       ASSERT (ImageId != NULL);
2529       CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
2530       break;
2531 
2532     //
2533     // Refresh
2534     //
2535     case EFI_IFR_REFRESH_OP:
2536       ASSERT (ParentStatement != NULL);
2537       ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
2538       break;
2539 
2540     //
2541     // Refresh guid.
2542     //
2543     case EFI_IFR_REFRESH_ID_OP:
2544       //
2545       // Get ScopeOpcode from top of stack
2546       //
2547       PopScope (&ScopeOpCode);
2548       PushScope (ScopeOpCode);
2549 
2550       switch (ScopeOpCode) {
2551       case EFI_IFR_FORM_OP:
2552       case EFI_IFR_FORM_MAP_OP:
2553         ASSERT (CurrentForm != NULL);
2554         CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
2555         break;
2556 
2557       default:
2558         ASSERT (ParentStatement != NULL);
2559         CopyMem (&ParentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
2560         break;
2561       }
2562       break;
2563 
2564     //
2565     // Modal tag
2566     //
2567     case EFI_IFR_MODAL_TAG_OP:
2568       ASSERT (CurrentForm != NULL);
2569       CurrentForm->ModalForm = TRUE;
2570       break;
2571 
2572     //
2573     // Lock tag, used by form and statement.
2574     //
2575     case EFI_IFR_LOCKED_OP:
2576       //
2577       // Get ScopeOpcode from top of stack
2578       //
2579       PopScope (&ScopeOpCode);
2580       PushScope (ScopeOpCode);
2581       switch (ScopeOpCode) {
2582       case EFI_IFR_FORM_OP:
2583       case EFI_IFR_FORM_MAP_OP:
2584         ASSERT (CurrentForm != NULL);
2585         CurrentForm->Locked = TRUE;
2586         break;
2587 
2588       default:
2589         ASSERT (ParentStatement != NULL);
2590         ParentStatement->Locked = TRUE;
2591       }
2592       break;
2593 
2594     //
2595     // Vendor specific
2596     //
2597     case EFI_IFR_GUID_OP:
2598       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
2599       break;
2600 
2601     //
2602     // Scope End
2603     //
2604     case EFI_IFR_END_OP:
2605       Status = PopScope (&ScopeOpCode);
2606       if (EFI_ERROR (Status)) {
2607         ResetScopeStack ();
2608         return Status;
2609       }
2610 
2611       //
2612       // Parent statement end tag found, update ParentStatement info.
2613       //
2614       if (IsStatementOpCode(ScopeOpCode) && (ParentStatement != NULL) && (ParentStatement->Operand == ScopeOpCode)) {
2615         ParentStatement  = ParentStatement->ParentStatement;
2616       }
2617 
2618       switch (ScopeOpCode) {
2619       case EFI_IFR_FORM_SET_OP:
2620         //
2621         // End of FormSet, update FormSet IFR binary length
2622         // to stop parsing substantial OpCodes
2623         //
2624         FormSet->IfrBinaryLength = OpCodeOffset;
2625         break;
2626 
2627       case EFI_IFR_FORM_OP:
2628       case EFI_IFR_FORM_MAP_OP:
2629         //
2630         // End of Form
2631         //
2632         CurrentForm = NULL;
2633         SuppressForQuestion = FALSE;
2634         break;
2635 
2636       case EFI_IFR_ONE_OF_OPTION_OP:
2637         //
2638         // End of Option
2639         //
2640         CurrentOption = NULL;
2641         break;
2642 
2643       case EFI_IFR_NO_SUBMIT_IF_OP:
2644       case EFI_IFR_INCONSISTENT_IF_OP:
2645       case EFI_IFR_WARNING_IF_OP:
2646         //
2647         // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
2648         //
2649         break;
2650 
2651       case EFI_IFR_SUPPRESS_IF_OP:
2652         if (SuppressForOption) {
2653           PopConditionalExpression(ExpressOption);
2654         } else if (SuppressForQuestion) {
2655           PopConditionalExpression(ExpressStatement);
2656         } else {
2657           PopConditionalExpression(ExpressForm);
2658         }
2659         break;
2660 
2661       case EFI_IFR_GRAY_OUT_IF_OP:
2662         PopConditionalExpression(ExpressStatement);
2663         break;
2664 
2665       case EFI_IFR_DISABLE_IF_OP:
2666         if (CurrentForm != NULL) {
2667           PopConditionalExpression(ExpressStatement);
2668         }
2669         InScopeDisable = FALSE;
2670         OpCodeDisabled = FALSE;
2671         break;
2672 
2673       case EFI_IFR_ONE_OF_OP:
2674       case EFI_IFR_ORDERED_LIST_OP:
2675         SuppressForOption = FALSE;
2676         break;
2677 
2678       case EFI_IFR_DEFAULT_OP:
2679         InScopeDefault = FALSE;
2680         break;
2681 
2682       case EFI_IFR_MAP_OP:
2683         //
2684         // Get current Map Expression List.
2685         //
2686         Status = PopMapExpressionList ((VOID **) &MapExpressionList);
2687         if (Status == EFI_ACCESS_DENIED) {
2688           MapExpressionList = NULL;
2689         }
2690         //
2691         // Get current expression.
2692         //
2693         Status = PopCurrentExpression ((VOID **) &CurrentExpression);
2694         ASSERT_EFI_ERROR (Status);
2695         ASSERT (MapScopeDepth > 0);
2696         MapScopeDepth --;
2697         break;
2698 
2699       default:
2700         if (IsExpressionOpCode (ScopeOpCode)) {
2701           if (InScopeDisable && CurrentForm == NULL) {
2702             //
2703             // This is DisableIf expression for Form, it should be a constant expression
2704             //
2705             ASSERT (CurrentExpression != NULL);
2706             Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
2707             if (EFI_ERROR (Status)) {
2708               return Status;
2709             }
2710 
2711             OpCodeDisabled = IsTrue (&CurrentExpression->Result);
2712 
2713             //
2714             // DisableIf Expression is only used once and not queued, free it
2715             //
2716             DestroyExpression (CurrentExpression);
2717           }
2718 
2719           //
2720           // End of current Expression
2721           //
2722           CurrentExpression = NULL;
2723         }
2724         break;
2725       }
2726       break;
2727 
2728     default:
2729       break;
2730     }
2731 
2732     if (IsStatementOpCode(Operand)) {
2733       CurrentStatement->ParentStatement = ParentStatement;
2734       if (Scope != 0) {
2735         //
2736         // Scope != 0, other statements or options may nest in this statement.
2737         // Update the ParentStatement info.
2738         //
2739         ParentStatement = CurrentStatement;
2740       }
2741     }
2742   }
2743 
2744   return EFI_SUCCESS;
2745 }
2746