1 /** @file
2 Parser for IFR binary encoding.
3 
4 Copyright (c) 2007 - 2015, 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 FormSe.
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 
1315   SuppressForQuestion      = FALSE;
1316   SuppressForOption        = FALSE;
1317   InScopeDisable           = FALSE;
1318   DepthOfDisable           = 0;
1319   OpCodeDisabled           = FALSE;
1320   SingleOpCodeExpression   = FALSE;
1321   InScopeDefault           = FALSE;
1322   CurrentExpression        = NULL;
1323   CurrentDefault           = NULL;
1324   CurrentOption            = NULL;
1325   ImageId                  = NULL;
1326   MapMethod                = NULL;
1327   MapScopeDepth            = 0;
1328   Link                     = NULL;
1329   VarStorage               = NULL;
1330   MapExpressionList        = NULL;
1331   TempVarstoreId           = 0;
1332   ConditionalExprCount     = 0;
1333   InUnknownScope           = FALSE;
1334   UnknownDepth             = 0;
1335 
1336   //
1337   // Get the number of Statements and Expressions
1338   //
1339   CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
1340 
1341   mStatementIndex = 0;
1342   mUsedQuestionId = 1;
1343   FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
1344   if (FormSet->StatementBuffer == NULL) {
1345     return EFI_OUT_OF_RESOURCES;
1346   }
1347 
1348   mExpressionOpCodeIndex = 0;
1349   FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
1350   if (FormSet->ExpressionBuffer == NULL) {
1351     return EFI_OUT_OF_RESOURCES;
1352   }
1353 
1354   InitializeListHead (&FormSet->StatementListOSF);
1355   InitializeListHead (&FormSet->StorageListHead);
1356   InitializeListHead (&FormSet->SaveFailStorageListHead);
1357   InitializeListHead (&FormSet->DefaultStoreListHead);
1358   InitializeListHead (&FormSet->FormListHead);
1359   InitializeListHead (&FormSet->ExpressionListHead);
1360   ResetCurrentExpressionStack ();
1361   ResetMapExpressionListStack ();
1362 
1363   CurrentForm = NULL;
1364   CurrentStatement = NULL;
1365   ParentStatement  = NULL;
1366 
1367   ResetScopeStack ();
1368 
1369   OpCodeOffset = 0;
1370   while (OpCodeOffset < FormSet->IfrBinaryLength) {
1371     OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
1372 
1373     OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1374     OpCodeOffset += OpCodeLength;
1375     Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
1376     Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
1377 
1378     if (InUnknownScope) {
1379       if (Operand == EFI_IFR_END_OP) {
1380         UnknownDepth --;
1381 
1382         if (UnknownDepth == 0) {
1383           InUnknownScope = FALSE;
1384         }
1385       } else {
1386         if (Scope != 0) {
1387           UnknownDepth ++;
1388         }
1389       }
1390 
1391       continue;
1392     }
1393 
1394     if (IsUnKnownOpCode(Operand)) {
1395       if (Scope != 0) {
1396         InUnknownScope = TRUE;
1397         UnknownDepth ++;
1398       }
1399 
1400       continue;
1401     }
1402 
1403     //
1404     // If scope bit set, push onto scope stack
1405     //
1406     if (Scope != 0) {
1407       PushScope (Operand);
1408     }
1409 
1410     if (OpCodeDisabled) {
1411       //
1412       // DisableIf Expression is evaluated to be TRUE, try to find its end.
1413       // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
1414       //
1415       if (Operand == EFI_IFR_DISABLE_IF_OP) {
1416         DepthOfDisable++;
1417       } else if (Operand == EFI_IFR_END_OP) {
1418         Status = PopScope (&ScopeOpCode);
1419         if (EFI_ERROR (Status)) {
1420           return Status;
1421         }
1422 
1423         if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
1424           if (DepthOfDisable == 0) {
1425             InScopeDisable = FALSE;
1426             OpCodeDisabled = FALSE;
1427           } else {
1428             DepthOfDisable--;
1429           }
1430         }
1431       }
1432       continue;
1433     }
1434 
1435     if (IsExpressionOpCode (Operand)) {
1436       ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
1437       mExpressionOpCodeIndex++;
1438 
1439       ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
1440       ExpressionOpCode->Operand = Operand;
1441       Value = &ExpressionOpCode->Value;
1442 
1443       switch (Operand) {
1444       case EFI_IFR_EQ_ID_VAL_OP:
1445         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1446 
1447         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1448         CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
1449         break;
1450 
1451       case EFI_IFR_EQ_ID_ID_OP:
1452         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
1453         CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
1454         break;
1455 
1456       case EFI_IFR_EQ_ID_VAL_LIST_OP:
1457         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1458         CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
1459         ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
1460         break;
1461 
1462       case EFI_IFR_TO_STRING_OP:
1463       case EFI_IFR_FIND_OP:
1464         ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
1465         break;
1466 
1467       case EFI_IFR_STRING_REF1_OP:
1468         Value->Type = EFI_IFR_TYPE_STRING;
1469         CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
1470         break;
1471 
1472       case EFI_IFR_RULE_REF_OP:
1473         ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
1474         break;
1475 
1476       case EFI_IFR_SPAN_OP:
1477         ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
1478         break;
1479 
1480       case EFI_IFR_THIS_OP:
1481         ASSERT (ParentStatement != NULL);
1482         ExpressionOpCode->QuestionId = ParentStatement->QuestionId;
1483         break;
1484 
1485       case EFI_IFR_SECURITY_OP:
1486         CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
1487         break;
1488 
1489       case EFI_IFR_MATCH2_OP:
1490         CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_MATCH2 *) OpCodeData)->SyntaxType, sizeof (EFI_GUID));
1491         break;
1492 
1493       case EFI_IFR_GET_OP:
1494       case EFI_IFR_SET_OP:
1495         CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
1496         if (TempVarstoreId != 0) {
1497           if (FormSet->StorageListHead.ForwardLink != NULL) {
1498             Link = GetFirstNode (&FormSet->StorageListHead);
1499             while (!IsNull (&FormSet->StorageListHead, Link)) {
1500               VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
1501               if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
1502                 ExpressionOpCode->VarStorage = VarStorage->BrowserStorage;
1503                 break;
1504               }
1505               Link = GetNextNode (&FormSet->StorageListHead, Link);
1506             }
1507           }
1508           if (ExpressionOpCode->VarStorage == NULL) {
1509             //
1510             // VarStorage is not found.
1511             //
1512             return EFI_INVALID_PARAMETER;
1513           }
1514         }
1515         ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;
1516         switch (ExpressionOpCode->ValueType) {
1517         case EFI_IFR_TYPE_BOOLEAN:
1518         case EFI_IFR_TYPE_NUM_SIZE_8:
1519           ExpressionOpCode->ValueWidth = 1;
1520           break;
1521 
1522         case EFI_IFR_TYPE_NUM_SIZE_16:
1523         case EFI_IFR_TYPE_STRING:
1524           ExpressionOpCode->ValueWidth = 2;
1525           break;
1526 
1527         case EFI_IFR_TYPE_NUM_SIZE_32:
1528           ExpressionOpCode->ValueWidth = 4;
1529           break;
1530 
1531         case EFI_IFR_TYPE_NUM_SIZE_64:
1532           ExpressionOpCode->ValueWidth = 8;
1533           break;
1534 
1535         case EFI_IFR_TYPE_DATE:
1536           ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_DATE);
1537           break;
1538 
1539         case EFI_IFR_TYPE_TIME:
1540           ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_TIME);
1541           break;
1542 
1543         case EFI_IFR_TYPE_REF:
1544           ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);
1545           break;
1546 
1547         case EFI_IFR_TYPE_OTHER:
1548         case EFI_IFR_TYPE_UNDEFINED:
1549         case EFI_IFR_TYPE_ACTION:
1550         case EFI_IFR_TYPE_BUFFER:
1551         default:
1552           //
1553           // Invalid value type for Get/Set opcode.
1554           //
1555           return EFI_INVALID_PARAMETER;
1556         }
1557         CopyMem (&ExpressionOpCode->VarStoreInfo.VarName,   &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName,   sizeof (EFI_STRING_ID));
1558         CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));
1559         if ((ExpressionOpCode->VarStorage != NULL) &&
1560             (ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE ||
1561              ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
1562           ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle);
1563           if (ExpressionOpCode->ValueName == NULL) {
1564             //
1565             // String ID is invalid.
1566             //
1567             return EFI_INVALID_PARAMETER;
1568           }
1569         }
1570         break;
1571 
1572       case EFI_IFR_QUESTION_REF1_OP:
1573         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1574         break;
1575 
1576       case EFI_IFR_QUESTION_REF3_OP:
1577         if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
1578           CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1579 
1580           if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
1581             CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
1582           }
1583         }
1584         break;
1585 
1586       //
1587       // constant
1588       //
1589       case EFI_IFR_TRUE_OP:
1590         Value->Type = EFI_IFR_TYPE_BOOLEAN;
1591         Value->Value.b = TRUE;
1592         break;
1593 
1594       case EFI_IFR_FALSE_OP:
1595         Value->Type = EFI_IFR_TYPE_BOOLEAN;
1596         Value->Value.b = FALSE;
1597         break;
1598 
1599       case EFI_IFR_ONE_OP:
1600         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1601         Value->Value.u8 = 1;
1602         break;
1603 
1604       case EFI_IFR_ZERO_OP:
1605         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1606         Value->Value.u8 = 0;
1607         break;
1608 
1609       case EFI_IFR_ONES_OP:
1610         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1611         Value->Value.u64 = 0xffffffffffffffffULL;
1612         break;
1613 
1614       case EFI_IFR_UINT8_OP:
1615         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1616         Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
1617         break;
1618 
1619       case EFI_IFR_UINT16_OP:
1620         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1621         CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
1622         break;
1623 
1624       case EFI_IFR_UINT32_OP:
1625         Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1626         CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
1627         break;
1628 
1629       case EFI_IFR_UINT64_OP:
1630         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1631         CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
1632         break;
1633 
1634       case EFI_IFR_UNDEFINED_OP:
1635         Value->Type = EFI_IFR_TYPE_UNDEFINED;
1636         break;
1637 
1638       case EFI_IFR_VERSION_OP:
1639         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1640         Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
1641         break;
1642 
1643       default:
1644         break;
1645       }
1646       //
1647       // Create sub expression nested in MAP opcode
1648       //
1649       if (CurrentExpression == NULL && MapScopeDepth > 0) {
1650         CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
1651         ASSERT (MapExpressionList != NULL);
1652         InsertTailList (MapExpressionList, &CurrentExpression->Link);
1653         if (Scope == 0) {
1654           SingleOpCodeExpression = TRUE;
1655         }
1656       }
1657       ASSERT (CurrentExpression != NULL);
1658       InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
1659       if (Operand == EFI_IFR_MAP_OP) {
1660         //
1661         // Store current Map Expression List.
1662         //
1663         if (MapExpressionList != NULL) {
1664           PushMapExpressionList (MapExpressionList);
1665         }
1666         //
1667         // Initialize new Map Expression List.
1668         //
1669         MapExpressionList = &ExpressionOpCode->MapExpressionList;
1670         InitializeListHead (MapExpressionList);
1671         //
1672         // Store current expression.
1673         //
1674         PushCurrentExpression (CurrentExpression);
1675         CurrentExpression = NULL;
1676         MapScopeDepth ++;
1677       } else if (SingleOpCodeExpression) {
1678         //
1679         // There are two cases to indicate the end of an Expression:
1680         // for single OpCode expression: one Expression OpCode
1681         // for expression consists of more than one OpCode: EFI_IFR_END
1682         //
1683         SingleOpCodeExpression = FALSE;
1684 
1685         if (InScopeDisable && CurrentForm == NULL) {
1686           //
1687           // This is DisableIf expression for Form, it should be a constant expression
1688           //
1689           Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1690           if (EFI_ERROR (Status)) {
1691             return Status;
1692           }
1693 
1694           OpCodeDisabled = IsTrue(&CurrentExpression->Result);
1695         }
1696 
1697         CurrentExpression = NULL;
1698       }
1699 
1700       continue;
1701     }
1702 
1703     //
1704     // Parse the Opcode
1705     //
1706     switch (Operand) {
1707 
1708     case EFI_IFR_FORM_SET_OP:
1709       //
1710       // Check the formset GUID
1711       //
1712       if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1713         return EFI_INVALID_PARAMETER;
1714       }
1715 
1716       CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1717       CopyMem (&FormSet->Help,         &((EFI_IFR_FORM_SET *) OpCodeData)->Help,         sizeof (EFI_STRING_ID));
1718       FormSet->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData;//save the opcode address of formset
1719 
1720       if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
1721         //
1722         // The formset OpCode contains ClassGuid
1723         //
1724         FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
1725         CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
1726       }
1727       break;
1728 
1729     case EFI_IFR_FORM_OP:
1730       //
1731       // Create a new Form for this FormSet
1732       //
1733       CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1734       ASSERT (CurrentForm != NULL);
1735       CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1736       InitializeListHead (&CurrentForm->ExpressionListHead);
1737       InitializeListHead (&CurrentForm->StatementListHead);
1738       InitializeListHead (&CurrentForm->ConfigRequestHead);
1739       InitializeListHead (&CurrentForm->FormViewListHead);
1740 
1741       CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
1742       CopyMem (&CurrentForm->FormId,    &((EFI_IFR_FORM *) OpCodeData)->FormId,    sizeof (UINT16));
1743       CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1744 
1745       ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1746       if ( ConditionalExprCount > 0) {
1747         //
1748         // Form is inside of suppressif
1749         //
1750         CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1751                                                  (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1752         ASSERT (CurrentForm->SuppressExpression != NULL);
1753         CurrentForm->SuppressExpression->Count     = (UINTN) ConditionalExprCount;
1754         CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1755         CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
1756       }
1757 
1758       if (Scope != 0) {
1759         //
1760         // Enter scope of a Form, suppressif will be used for Question or Option
1761         //
1762         SuppressForQuestion = TRUE;
1763       }
1764 
1765       //
1766       // Insert into Form list of this FormSet
1767       //
1768       InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1769       break;
1770 
1771     case EFI_IFR_FORM_MAP_OP:
1772       //
1773       // Create a new Form for this FormSet
1774       //
1775       CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1776       ASSERT (CurrentForm != NULL);
1777       CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1778       InitializeListHead (&CurrentForm->ExpressionListHead);
1779       InitializeListHead (&CurrentForm->StatementListHead);
1780       InitializeListHead (&CurrentForm->ConfigRequestHead);
1781       InitializeListHead (&CurrentForm->FormViewListHead);
1782 
1783       CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1784 
1785       MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1786       //
1787       // FormMap Form must contain at least one Map Method.
1788       //
1789       if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) {
1790         return EFI_INVALID_PARAMETER;
1791       }
1792       //
1793       // Try to find the standard form map method.
1794       //
1795       while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) {
1796         if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {
1797           CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1798           CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
1799           break;
1800         }
1801         MapMethod ++;
1802       }
1803       //
1804       // If the standard form map method is not found, the first map method title will be used.
1805       //
1806       if (CurrentForm->FormTitle == 0) {
1807         MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1808         CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1809       }
1810 
1811       ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1812       if ( ConditionalExprCount > 0) {
1813         //
1814         // Form is inside of suppressif
1815         //
1816         CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1817                                                  (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1818         ASSERT (CurrentForm->SuppressExpression != NULL);
1819         CurrentForm->SuppressExpression->Count     = (UINTN) ConditionalExprCount;
1820         CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1821         CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
1822       }
1823 
1824       if (Scope != 0) {
1825         //
1826         // Enter scope of a Form, suppressif will be used for Question or Option
1827         //
1828         SuppressForQuestion = TRUE;
1829       }
1830 
1831       //
1832       // Insert into Form list of this FormSet
1833       //
1834       InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1835       break;
1836 
1837     //
1838     // Storage
1839     //
1840     case EFI_IFR_VARSTORE_OP:
1841       //
1842       // Create a buffer Storage for this FormSet
1843       //
1844       Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);
1845       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1846       break;
1847 
1848     case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1849       //
1850       // Create a name/value Storage for this FormSet
1851       //
1852       Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);
1853       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1854       break;
1855 
1856     case EFI_IFR_VARSTORE_EFI_OP:
1857       //
1858       // Create a EFI variable Storage for this FormSet
1859       //
1860       if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
1861         //
1862         // Create efi varstore with format follow UEFI spec before 2.3.1.
1863         //
1864         Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);
1865       } else {
1866         //
1867         // Create efi varstore with format follow UEFI spec 2.3.1 and later.
1868         //
1869         Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
1870       }
1871       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1872       break;
1873 
1874     //
1875     // DefaultStore
1876     //
1877     case EFI_IFR_DEFAULTSTORE_OP:
1878       DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
1879       ASSERT (DefaultStore != NULL);
1880       DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1881 
1882       CopyMem (&DefaultStore->DefaultId,   &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId,   sizeof (UINT16));
1883       CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1884 
1885       //
1886       // Insert to DefaultStore list of this Formset
1887       //
1888       InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1889       break;
1890 
1891     //
1892     // Statements
1893     //
1894     case EFI_IFR_SUBTITLE_OP:
1895       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1896       ASSERT (CurrentStatement != NULL);
1897 
1898       CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
1899       CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1900       break;
1901 
1902     case EFI_IFR_TEXT_OP:
1903       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1904       ASSERT (CurrentStatement != NULL);
1905       CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1906       CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1907       break;
1908 
1909     case EFI_IFR_RESET_BUTTON_OP:
1910       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1911       ASSERT (CurrentStatement != NULL);
1912       CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1913       CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1914       break;
1915 
1916     //
1917     // Questions
1918     //
1919     case EFI_IFR_ACTION_OP:
1920       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1921       ASSERT (CurrentStatement != NULL);
1922       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
1923 
1924       if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1925         //
1926         // No QuestionConfig present, so no configuration string will be processed
1927         //
1928         CurrentStatement->QuestionConfig = 0;
1929       } else {
1930         CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1931       }
1932       break;
1933 
1934     case EFI_IFR_REF_OP:
1935       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1936       ASSERT (CurrentStatement != NULL);
1937       Value = &CurrentStatement->HiiValue;
1938       Value->Type = EFI_IFR_TYPE_REF;
1939       if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
1940         CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
1941 
1942         if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1943           CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1944 
1945           if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1946             CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1947 
1948             if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1949               CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1950             }
1951           }
1952         }
1953       }
1954       CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
1955       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
1956       break;
1957 
1958     case EFI_IFR_ONE_OF_OP:
1959     case EFI_IFR_NUMERIC_OP:
1960       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1961       ASSERT(CurrentStatement != NULL);
1962 
1963       CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1964       Value = &CurrentStatement->HiiValue;
1965 
1966       switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1967       case EFI_IFR_NUMERIC_SIZE_1:
1968         CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1969         CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1970         CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
1971         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
1972         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1973         break;
1974 
1975       case EFI_IFR_NUMERIC_SIZE_2:
1976         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1977         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1978         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step,     sizeof (UINT16));
1979         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
1980         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1981         break;
1982 
1983       case EFI_IFR_NUMERIC_SIZE_4:
1984         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
1985         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
1986         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step,     sizeof (UINT32));
1987         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
1988         Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1989         break;
1990 
1991       case EFI_IFR_NUMERIC_SIZE_8:
1992         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
1993         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
1994         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step,     sizeof (UINT64));
1995         CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
1996         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1997         break;
1998 
1999       default:
2000         break;
2001       }
2002 
2003       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2004 
2005       if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
2006         SuppressForOption = TRUE;
2007       }
2008       break;
2009 
2010     case EFI_IFR_ORDERED_LIST_OP:
2011       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2012       ASSERT(CurrentStatement != NULL);
2013 
2014       CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
2015       CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
2016 
2017       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
2018       CurrentStatement->BufferValue = NULL;
2019 
2020       if (Scope != 0) {
2021         SuppressForOption = TRUE;
2022       }
2023       break;
2024 
2025     case EFI_IFR_CHECKBOX_OP:
2026       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2027       ASSERT(CurrentStatement != NULL);
2028 
2029       CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
2030       CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
2031       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
2032 
2033       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2034 
2035       break;
2036 
2037     case EFI_IFR_STRING_OP:
2038       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2039       ASSERT (CurrentStatement != NULL);
2040       //
2041       // MinSize is the minimum number of characters that can be accepted for this opcode,
2042       // MaxSize is the maximum number of characters that can be accepted for this opcode.
2043       // The characters are stored as Unicode, so the storage width should multiply 2.
2044       //
2045       CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
2046       CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
2047       CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2048       CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
2049 
2050       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2051       CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
2052       CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
2053 
2054       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2055       break;
2056 
2057     case EFI_IFR_PASSWORD_OP:
2058       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2059       ASSERT (CurrentStatement != NULL);
2060       //
2061       // MinSize is the minimum number of characters that can be accepted for this opcode,
2062       // MaxSize is the maximum number of characters that can be accepted for this opcode.
2063       // The characters are stored as Unicode, so the storage width should multiply 2.
2064       //
2065       CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
2066       CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
2067       CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2068 
2069       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2070       CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
2071       CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
2072 
2073       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2074       break;
2075 
2076     case EFI_IFR_DATE_OP:
2077       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2078       ASSERT(CurrentStatement != NULL);
2079 
2080       CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
2081       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
2082 
2083       if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
2084         CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
2085 
2086         InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2087       } else {
2088         //
2089         // Don't assign storage for RTC type of date/time
2090         //
2091         CurrentStatement->Storage = NULL;
2092         CurrentStatement->StorageWidth = 0;
2093       }
2094       break;
2095 
2096     case EFI_IFR_TIME_OP:
2097       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2098       ASSERT(CurrentStatement != NULL);
2099 
2100       CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
2101       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
2102 
2103       if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
2104         CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
2105 
2106         InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2107       } else {
2108         //
2109         // Don't assign storage for RTC type of date/time
2110         //
2111         CurrentStatement->Storage = NULL;
2112         CurrentStatement->StorageWidth = 0;
2113       }
2114       break;
2115 
2116     //
2117     // Default
2118     //
2119     case EFI_IFR_DEFAULT_OP:
2120       //
2121       // EFI_IFR_DEFAULT appear in scope of a Question,
2122       // It creates a default value for the current question.
2123       // A Question may have more than one Default value which have different default types.
2124       //
2125       CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
2126       ASSERT (CurrentDefault != NULL);
2127       CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2128 
2129       CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
2130       CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
2131       if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {
2132         CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2133         CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *) OpCodeData)->Value);
2134         ASSERT (CurrentDefault->Value.Buffer != NULL);
2135       } else {
2136         CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2137         ExtendValueToU64 (&CurrentDefault->Value);
2138       }
2139 
2140       //
2141       // Insert to Default Value list of current Question
2142       //
2143       InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
2144 
2145       if (Scope != 0) {
2146         InScopeDefault = TRUE;
2147       }
2148       break;
2149 
2150     //
2151     // Option
2152     //
2153     case EFI_IFR_ONE_OF_OPTION_OP:
2154       ASSERT (ParentStatement != NULL);
2155       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)) {
2156         //
2157         // It's keep the default value for ordered list opcode.
2158         //
2159         CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
2160         ASSERT (CurrentDefault != NULL);
2161         CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2162 
2163         CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;
2164         if ((((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
2165           CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2166         } else {
2167           CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2168         }
2169 
2170         CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2171         CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value);
2172         ASSERT (CurrentDefault->Value.Buffer != NULL);
2173 
2174         //
2175         // Insert to Default Value list of current Question
2176         //
2177         InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
2178         break;
2179       }
2180 
2181       //
2182       // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
2183       // It create a selection for use in current Question.
2184       //
2185       CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
2186       ASSERT (CurrentOption != NULL);
2187       CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
2188       CurrentOption->OpCode    = (EFI_IFR_ONE_OF_OPTION *) OpCodeData;
2189 
2190       CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
2191       CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
2192       CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
2193       CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2194       ExtendValueToU64 (&CurrentOption->Value);
2195 
2196       ConditionalExprCount = GetConditionalExpressionCount(ExpressOption);
2197       if ( ConditionalExprCount > 0) {
2198         //
2199         // Form is inside of suppressif
2200         //
2201         CurrentOption->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
2202                                                  (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
2203         ASSERT (CurrentOption->SuppressExpression != NULL);
2204         CurrentOption->SuppressExpression->Count     = (UINTN) ConditionalExprCount;
2205         CurrentOption->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
2206         CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList(ExpressOption), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
2207       }
2208 
2209       //
2210       // Insert to Option list of current Question
2211       //
2212       InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link);
2213       //
2214       // Now we know the Storage width of nested Ordered List
2215       //
2216       if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->BufferValue == NULL)) {
2217         Width = 1;
2218         switch (CurrentOption->Value.Type) {
2219         case EFI_IFR_TYPE_NUM_SIZE_8:
2220           Width = 1;
2221           break;
2222 
2223         case EFI_IFR_TYPE_NUM_SIZE_16:
2224           Width = 2;
2225           break;
2226 
2227         case EFI_IFR_TYPE_NUM_SIZE_32:
2228           Width = 4;
2229           break;
2230 
2231         case EFI_IFR_TYPE_NUM_SIZE_64:
2232           Width = 8;
2233           break;
2234 
2235         default:
2236           //
2237           // Invalid type for Ordered List
2238           //
2239           break;
2240         }
2241 
2242         ParentStatement->StorageWidth = (UINT16) (ParentStatement->MaxContainers * Width);
2243         ParentStatement->BufferValue = AllocateZeroPool (ParentStatement->StorageWidth);
2244         ParentStatement->ValueType = CurrentOption->Value.Type;
2245         if (ParentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
2246           ParentStatement->HiiValue.Buffer = ParentStatement->BufferValue;
2247           ParentStatement->HiiValue.BufferLen = ParentStatement->StorageWidth;
2248         }
2249 
2250         InitializeRequestElement (FormSet, ParentStatement, CurrentForm);
2251       }
2252       break;
2253 
2254     //
2255     // Conditional
2256     //
2257     case EFI_IFR_NO_SUBMIT_IF_OP:
2258     case EFI_IFR_INCONSISTENT_IF_OP:
2259       //
2260       // Create an Expression node
2261       //
2262       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2263       CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
2264 
2265       if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
2266         CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
2267         InsertTailList (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link);
2268       } else {
2269         CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
2270         InsertTailList (&ParentStatement->InconsistentListHead, &CurrentExpression->Link);
2271       }
2272 
2273       //
2274       // Take a look at next OpCode to see whether current expression consists
2275       // of single OpCode
2276       //
2277       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2278         SingleOpCodeExpression = TRUE;
2279       }
2280       break;
2281 
2282     case EFI_IFR_WARNING_IF_OP:
2283       //
2284       // Create an Expression node
2285       //
2286       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2287       CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));
2288       CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;
2289       CurrentExpression->Type    = EFI_HII_EXPRESSION_WARNING_IF;
2290       InsertTailList (&ParentStatement->WarningListHead, &CurrentExpression->Link);
2291 
2292       //
2293       // Take a look at next OpCode to see whether current expression consists
2294       // of single OpCode
2295       //
2296       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2297         SingleOpCodeExpression = TRUE;
2298       }
2299       break;
2300 
2301     case EFI_IFR_SUPPRESS_IF_OP:
2302       //
2303       // Question and Option will appear in scope of this OpCode
2304       //
2305       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2306       CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
2307 
2308       if (CurrentForm == NULL) {
2309         InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
2310       } else {
2311         InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2312       }
2313 
2314       if (SuppressForOption) {
2315         PushConditionalExpression(CurrentExpression, ExpressOption);
2316       } else if (SuppressForQuestion) {
2317         PushConditionalExpression(CurrentExpression, ExpressStatement);
2318       } else {
2319         PushConditionalExpression(CurrentExpression, ExpressForm);
2320       }
2321 
2322       //
2323       // Take a look at next OpCode to see whether current expression consists
2324       // of single OpCode
2325       //
2326       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2327         SingleOpCodeExpression = TRUE;
2328       }
2329       break;
2330 
2331     case EFI_IFR_GRAY_OUT_IF_OP:
2332       //
2333       // Questions will appear in scope of this OpCode
2334       //
2335       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2336       CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
2337       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2338       PushConditionalExpression(CurrentExpression, ExpressStatement);
2339 
2340       //
2341       // Take a look at next OpCode to see whether current expression consists
2342       // of single OpCode
2343       //
2344       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2345         SingleOpCodeExpression = TRUE;
2346       }
2347       break;
2348 
2349     case EFI_IFR_DISABLE_IF_OP:
2350       //
2351       // The DisableIf expression should only rely on constant, so it could be
2352       // evaluated at initialization and it will not be queued
2353       //
2354       CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
2355       ASSERT (CurrentExpression != NULL);
2356       CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
2357       CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
2358       InitializeListHead (&CurrentExpression->OpCodeListHead);
2359 
2360       if (CurrentForm != NULL) {
2361         //
2362         // This is DisableIf for Question, enqueue it to Form expression list
2363         //
2364         InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2365         PushConditionalExpression(CurrentExpression, ExpressStatement);
2366       }
2367 
2368       OpCodeDisabled  = FALSE;
2369       InScopeDisable  = TRUE;
2370       //
2371       // Take a look at next OpCode to see whether current expression consists
2372       // of single OpCode
2373       //
2374       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2375         SingleOpCodeExpression = TRUE;
2376       }
2377       break;
2378 
2379     //
2380     // Expression
2381     //
2382     case EFI_IFR_VALUE_OP:
2383       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2384       CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
2385       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2386 
2387       if (InScopeDefault) {
2388         //
2389         // Used for default (EFI_IFR_DEFAULT)
2390         //
2391         CurrentDefault->ValueExpression = CurrentExpression;
2392       } else {
2393         //
2394         // If used for a question, then the question will be read-only
2395         //
2396         //
2397         // Make sure CurrentStatement is not NULL.
2398         // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2399         // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2400         //
2401         ASSERT (ParentStatement != NULL);
2402         ParentStatement->ValueExpression = CurrentExpression;
2403       }
2404 
2405       //
2406       // Take a look at next OpCode to see whether current expression consists
2407       // of single OpCode
2408       //
2409       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2410         SingleOpCodeExpression = TRUE;
2411       }
2412       break;
2413 
2414     case EFI_IFR_RULE_OP:
2415       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2416       CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
2417 
2418       CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
2419       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2420 
2421       //
2422       // Take a look at next OpCode to see whether current expression consists
2423       // of single OpCode
2424       //
2425       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2426         SingleOpCodeExpression = TRUE;
2427       }
2428       break;
2429 
2430     case EFI_IFR_READ_OP:
2431       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2432       CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
2433       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2434 
2435       //
2436       // Make sure CurrentStatement is not NULL.
2437       // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2438       // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2439       //
2440       ASSERT (ParentStatement != NULL);
2441       ParentStatement->ReadExpression = CurrentExpression;
2442 
2443       //
2444       // Take a look at next OpCode to see whether current expression consists
2445       // of single OpCode
2446       //
2447       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2448         SingleOpCodeExpression = TRUE;
2449       }
2450       break;
2451 
2452     case EFI_IFR_WRITE_OP:
2453       CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2454       CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
2455       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2456 
2457       //
2458       // Make sure CurrentStatement is not NULL.
2459       // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2460       // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2461       //
2462       ASSERT (ParentStatement != NULL);
2463       ParentStatement->WriteExpression = CurrentExpression;
2464 
2465       //
2466       // Take a look at next OpCode to see whether current expression consists
2467       // of single OpCode
2468       //
2469       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2470         SingleOpCodeExpression = TRUE;
2471       }
2472       break;
2473 
2474     //
2475     // Image
2476     //
2477     case EFI_IFR_IMAGE_OP:
2478       //
2479       // Get ScopeOpcode from top of stack
2480       //
2481       PopScope (&ScopeOpCode);
2482       PushScope (ScopeOpCode);
2483 
2484       switch (ScopeOpCode) {
2485       case EFI_IFR_FORM_SET_OP:
2486         ImageId = &FormSet->ImageId;
2487         break;
2488 
2489       case EFI_IFR_FORM_OP:
2490       case EFI_IFR_FORM_MAP_OP:
2491         ASSERT (CurrentForm != NULL);
2492         ImageId = &CurrentForm->ImageId;
2493         break;
2494 
2495       case EFI_IFR_ONE_OF_OPTION_OP:
2496         ASSERT (CurrentOption != NULL);
2497         ImageId = &CurrentOption->ImageId;
2498         break;
2499 
2500       default:
2501         //
2502         // Make sure CurrentStatement is not NULL.
2503         // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2504         // file is wrongly generated by tools such as VFR Compiler.
2505         //
2506         ASSERT (ParentStatement != NULL);
2507         ImageId = &ParentStatement->ImageId;
2508         break;
2509       }
2510 
2511       ASSERT (ImageId != NULL);
2512       CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
2513       break;
2514 
2515     //
2516     // Refresh
2517     //
2518     case EFI_IFR_REFRESH_OP:
2519       ASSERT (ParentStatement != NULL);
2520       ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
2521       break;
2522 
2523     //
2524     // Refresh guid.
2525     //
2526     case EFI_IFR_REFRESH_ID_OP:
2527       //
2528       // Get ScopeOpcode from top of stack
2529       //
2530       PopScope (&ScopeOpCode);
2531       PushScope (ScopeOpCode);
2532 
2533       switch (ScopeOpCode) {
2534       case EFI_IFR_FORM_OP:
2535       case EFI_IFR_FORM_MAP_OP:
2536         ASSERT (CurrentForm != NULL);
2537         CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
2538         break;
2539 
2540       default:
2541         ASSERT (ParentStatement != NULL);
2542         CopyMem (&ParentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
2543         break;
2544       }
2545       break;
2546 
2547     //
2548     // Modal tag
2549     //
2550     case EFI_IFR_MODAL_TAG_OP:
2551       ASSERT (CurrentForm != NULL);
2552       CurrentForm->ModalForm = TRUE;
2553       break;
2554 
2555     //
2556     // Lock tag, used by form and statement.
2557     //
2558     case EFI_IFR_LOCKED_OP:
2559       //
2560       // Get ScopeOpcode from top of stack
2561       //
2562       PopScope (&ScopeOpCode);
2563       PushScope (ScopeOpCode);
2564       switch (ScopeOpCode) {
2565       case EFI_IFR_FORM_OP:
2566       case EFI_IFR_FORM_MAP_OP:
2567         ASSERT (CurrentForm != NULL);
2568         CurrentForm->Locked = TRUE;
2569         break;
2570 
2571       default:
2572         ASSERT (ParentStatement != NULL);
2573         ParentStatement->Locked = TRUE;
2574       }
2575       break;
2576 
2577     //
2578     // Vendor specific
2579     //
2580     case EFI_IFR_GUID_OP:
2581       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
2582       break;
2583 
2584     //
2585     // Scope End
2586     //
2587     case EFI_IFR_END_OP:
2588       Status = PopScope (&ScopeOpCode);
2589       if (EFI_ERROR (Status)) {
2590         ResetScopeStack ();
2591         return Status;
2592       }
2593 
2594       //
2595       // Parent statement end tag found, update ParentStatement info.
2596       //
2597       if (IsStatementOpCode(ScopeOpCode) && (ParentStatement != NULL) && (ParentStatement->Operand == ScopeOpCode)) {
2598         ParentStatement  = ParentStatement->ParentStatement;
2599       }
2600 
2601       switch (ScopeOpCode) {
2602       case EFI_IFR_FORM_SET_OP:
2603         //
2604         // End of FormSet, update FormSet IFR binary length
2605         // to stop parsing substantial OpCodes
2606         //
2607         FormSet->IfrBinaryLength = OpCodeOffset;
2608         break;
2609 
2610       case EFI_IFR_FORM_OP:
2611       case EFI_IFR_FORM_MAP_OP:
2612         //
2613         // End of Form
2614         //
2615         CurrentForm = NULL;
2616         SuppressForQuestion = FALSE;
2617         break;
2618 
2619       case EFI_IFR_ONE_OF_OPTION_OP:
2620         //
2621         // End of Option
2622         //
2623         CurrentOption = NULL;
2624         break;
2625 
2626       case EFI_IFR_NO_SUBMIT_IF_OP:
2627       case EFI_IFR_INCONSISTENT_IF_OP:
2628       case EFI_IFR_WARNING_IF_OP:
2629         //
2630         // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
2631         //
2632         break;
2633 
2634       case EFI_IFR_SUPPRESS_IF_OP:
2635         if (SuppressForOption) {
2636           PopConditionalExpression(ExpressOption);
2637         } else if (SuppressForQuestion) {
2638           PopConditionalExpression(ExpressStatement);
2639         } else {
2640           PopConditionalExpression(ExpressForm);
2641         }
2642         break;
2643 
2644       case EFI_IFR_GRAY_OUT_IF_OP:
2645         PopConditionalExpression(ExpressStatement);
2646         break;
2647 
2648       case EFI_IFR_DISABLE_IF_OP:
2649         if (CurrentForm != NULL) {
2650           PopConditionalExpression(ExpressStatement);
2651         }
2652         InScopeDisable = FALSE;
2653         OpCodeDisabled = FALSE;
2654         break;
2655 
2656       case EFI_IFR_ONE_OF_OP:
2657       case EFI_IFR_ORDERED_LIST_OP:
2658         SuppressForOption = FALSE;
2659         break;
2660 
2661       case EFI_IFR_DEFAULT_OP:
2662         InScopeDefault = FALSE;
2663         break;
2664 
2665       case EFI_IFR_MAP_OP:
2666         //
2667         // Get current Map Expression List.
2668         //
2669         Status = PopMapExpressionList ((VOID **) &MapExpressionList);
2670         if (Status == EFI_ACCESS_DENIED) {
2671           MapExpressionList = NULL;
2672         }
2673         //
2674         // Get current expression.
2675         //
2676         Status = PopCurrentExpression ((VOID **) &CurrentExpression);
2677         ASSERT_EFI_ERROR (Status);
2678         ASSERT (MapScopeDepth > 0);
2679         MapScopeDepth --;
2680         break;
2681 
2682       default:
2683         if (IsExpressionOpCode (ScopeOpCode)) {
2684           if (InScopeDisable && CurrentForm == NULL) {
2685             //
2686             // This is DisableIf expression for Form, it should be a constant expression
2687             //
2688             ASSERT (CurrentExpression != NULL);
2689             Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
2690             if (EFI_ERROR (Status)) {
2691               return Status;
2692             }
2693 
2694             OpCodeDisabled = IsTrue (&CurrentExpression->Result);
2695 
2696             //
2697             // DisableIf Expression is only used once and not queued, free it
2698             //
2699             DestroyExpression (CurrentExpression);
2700           }
2701 
2702           //
2703           // End of current Expression
2704           //
2705           CurrentExpression = NULL;
2706         }
2707         break;
2708       }
2709       break;
2710 
2711     default:
2712       break;
2713     }
2714 
2715     if (IsStatementOpCode(Operand)) {
2716       CurrentStatement->ParentStatement = ParentStatement;
2717       if (Scope != 0) {
2718         //
2719         // Scope != 0, other statements or options may nest in this statement.
2720         // Update the ParentStatement info.
2721         //
2722         ParentStatement = CurrentStatement;
2723       }
2724     }
2725   }
2726 
2727   return EFI_SUCCESS;
2728 }
2729