]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
MdeModulePkg:System hangs in setup menu
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / IfrParse.c
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 *
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
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
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 *
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 *
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
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 *
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
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
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 *
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 *
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 *
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
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
692 Storage = Question->Storage;
693 if (Storage == NULL) {
694 return EFI_INVALID_PARAMETER;
695 }
696
697 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
698 //
699 // <ConfigRequest> is unnecessary for EFI variable storage,
700 // GetVariable()/SetVariable() will be used to retrieve/save values
701 //
702 return EFI_SUCCESS;
703 }
704
705 //
706 // Prepare <RequestElement>
707 //
708 if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
709 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
710 StrLen = UnicodeSPrint (
711 RequestElement,
712 30 * sizeof (CHAR16),
713 L"&OFFSET=%04x&WIDTH=%04x",
714 Question->VarStoreInfo.VarOffset,
715 Question->StorageWidth
716 );
717 Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);
718 } else {
719 StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
720 }
721
722 if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
723 //
724 // Password with CALLBACK flag is stored in encoded format,
725 // so don't need to append it to <ConfigRequest>
726 //
727 return EFI_SUCCESS;
728 }
729
730 //
731 // Find Formset Storage for this Question
732 //
733 FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);
734 ASSERT (FormsetStorage != NULL);
735
736 //
737 // Append <RequestElement> to <ConfigRequest>
738 //
739 if (StrLen > FormsetStorage->SpareStrLen) {
740 //
741 // Old String buffer is not sufficient for RequestElement, allocate a new one
742 //
743 StringSize = (FormsetStorage->ConfigRequest != NULL) ? StrSize (FormsetStorage->ConfigRequest) : sizeof (CHAR16);
744 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
745 ASSERT (NewStr != NULL);
746 if (FormsetStorage->ConfigRequest != NULL) {
747 CopyMem (NewStr, FormsetStorage->ConfigRequest, StringSize);
748 FreePool (FormsetStorage->ConfigRequest);
749 }
750 FormsetStorage->ConfigRequest = NewStr;
751 FormsetStorage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
752 }
753
754 StrCat (FormsetStorage->ConfigRequest, RequestElement);
755 FormsetStorage->ElementCount++;
756 FormsetStorage->SpareStrLen -= StrLen;
757
758 //
759 // Update the Config Request info saved in the form.
760 //
761 ConfigInfo = NULL;
762 Find = FALSE;
763 Link = GetFirstNode (&Form->ConfigRequestHead);
764 while (!IsNull (&Form->ConfigRequestHead, Link)) {
765 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
766
767 if (ConfigInfo != NULL && ConfigInfo->Storage == FormsetStorage->BrowserStorage) {
768 Find = TRUE;
769 break;
770 }
771
772 Link = GetNextNode (&Form->ConfigRequestHead, Link);
773 }
774
775 if (!Find) {
776 ConfigInfo = AllocateZeroPool(sizeof (FORM_BROWSER_CONFIG_REQUEST));
777 ASSERT (ConfigInfo != NULL);
778 ConfigInfo->Signature = FORM_BROWSER_CONFIG_REQUEST_SIGNATURE;
779 ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (FormsetStorage->ConfigHdr), FormsetStorage->ConfigHdr);
780 ASSERT (ConfigInfo->ConfigRequest != NULL);
781 ConfigInfo->SpareStrLen = 0;
782 ConfigInfo->Storage = FormsetStorage->BrowserStorage;
783 InsertTailList(&Form->ConfigRequestHead, &ConfigInfo->Link);
784 }
785
786 //
787 // Append <RequestElement> to <ConfigRequest>
788 //
789 if (StrLen > ConfigInfo->SpareStrLen) {
790 //
791 // Old String buffer is not sufficient for RequestElement, allocate a new one
792 //
793 StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16);
794 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
795 ASSERT (NewStr != NULL);
796 if (ConfigInfo->ConfigRequest != NULL) {
797 CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);
798 FreePool (ConfigInfo->ConfigRequest);
799 }
800 ConfigInfo->ConfigRequest = NewStr;
801 ConfigInfo->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
802 }
803
804 StrCat (ConfigInfo->ConfigRequest, RequestElement);
805 ConfigInfo->ElementCount++;
806 ConfigInfo->SpareStrLen -= StrLen;
807 return EFI_SUCCESS;
808 }
809
810
811 /**
812 Free resources of a Expression.
813
814 @param FormSet Pointer of the Expression
815
816 **/
817 VOID
818 DestroyExpression (
819 IN FORM_EXPRESSION *Expression
820 )
821 {
822 LIST_ENTRY *Link;
823 EXPRESSION_OPCODE *OpCode;
824 LIST_ENTRY *SubExpressionLink;
825 FORM_EXPRESSION *SubExpression;
826
827 while (!IsListEmpty (&Expression->OpCodeListHead)) {
828 Link = GetFirstNode (&Expression->OpCodeListHead);
829 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
830 RemoveEntryList (&OpCode->Link);
831
832 if (OpCode->ValueList != NULL) {
833 FreePool (OpCode->ValueList);
834 }
835
836 if (OpCode->ValueName != NULL) {
837 FreePool (OpCode->ValueName);
838 }
839
840 if (OpCode->MapExpressionList.ForwardLink != NULL) {
841 while (!IsListEmpty (&OpCode->MapExpressionList)) {
842 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
843 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
844 RemoveEntryList(&SubExpression->Link);
845 DestroyExpression (SubExpression);
846 }
847 }
848 }
849
850 //
851 // Free this Expression
852 //
853 FreePool (Expression);
854 }
855
856 /**
857 Free resources of a storage.
858
859 @param Storage Pointer of the storage
860
861 **/
862 VOID
863 DestroyStorage (
864 IN FORMSET_STORAGE *Storage
865 )
866 {
867 if (Storage == NULL) {
868 return;
869 }
870
871 if (Storage->ConfigRequest != NULL) {
872 FreePool (Storage->ConfigRequest);
873 }
874
875 FreePool (Storage);
876 }
877
878
879 /**
880 Free resources of a Statement.
881
882 @param FormSet Pointer of the FormSet
883 @param Statement Pointer of the Statement
884
885 **/
886 VOID
887 DestroyStatement (
888 IN FORM_BROWSER_FORMSET *FormSet,
889 IN OUT FORM_BROWSER_STATEMENT *Statement
890 )
891 {
892 LIST_ENTRY *Link;
893 QUESTION_DEFAULT *Default;
894 QUESTION_OPTION *Option;
895 FORM_EXPRESSION *Expression;
896
897 //
898 // Free Default value List
899 //
900 while (!IsListEmpty (&Statement->DefaultListHead)) {
901 Link = GetFirstNode (&Statement->DefaultListHead);
902 Default = QUESTION_DEFAULT_FROM_LINK (Link);
903 RemoveEntryList (&Default->Link);
904
905 if (Default->Value.Buffer != NULL) {
906 FreePool (Default->Value.Buffer);
907 }
908 FreePool (Default);
909 }
910
911 //
912 // Free Options List
913 //
914 while (!IsListEmpty (&Statement->OptionListHead)) {
915 Link = GetFirstNode (&Statement->OptionListHead);
916 Option = QUESTION_OPTION_FROM_LINK (Link);
917 if (Option->SuppressExpression != NULL) {
918 FreePool (Option->SuppressExpression);
919 }
920 RemoveEntryList (&Option->Link);
921
922 FreePool (Option);
923 }
924
925 //
926 // Free Inconsistent List
927 //
928 while (!IsListEmpty (&Statement->InconsistentListHead)) {
929 Link = GetFirstNode (&Statement->InconsistentListHead);
930 Expression = FORM_EXPRESSION_FROM_LINK (Link);
931 RemoveEntryList (&Expression->Link);
932
933 DestroyExpression (Expression);
934 }
935
936 //
937 // Free NoSubmit List
938 //
939 while (!IsListEmpty (&Statement->NoSubmitListHead)) {
940 Link = GetFirstNode (&Statement->NoSubmitListHead);
941 Expression = FORM_EXPRESSION_FROM_LINK (Link);
942 RemoveEntryList (&Expression->Link);
943
944 DestroyExpression (Expression);
945 }
946
947 //
948 // Free WarningIf List
949 //
950 while (!IsListEmpty (&Statement->WarningListHead)) {
951 Link = GetFirstNode (&Statement->WarningListHead);
952 Expression = FORM_EXPRESSION_FROM_LINK (Link);
953 RemoveEntryList (&Expression->Link);
954
955 DestroyExpression (Expression);
956 }
957
958 if (Statement->Expression != NULL) {
959 FreePool (Statement->Expression);
960 }
961
962 if (Statement->VariableName != NULL) {
963 FreePool (Statement->VariableName);
964 }
965 if (Statement->BlockName != NULL) {
966 FreePool (Statement->BlockName);
967 }
968 if (Statement->BufferValue != NULL) {
969 FreePool (Statement->BufferValue);
970 }
971 if (Statement->Operand == EFI_IFR_STRING_OP || Statement->Operand == EFI_IFR_PASSWORD_OP) {
972 DeleteString(Statement->HiiValue.Value.string, FormSet->HiiHandle);
973 }
974 }
975
976
977 /**
978 Free resources of a Form.
979
980 @param FormSet Pointer of the FormSet
981 @param Form Pointer of the Form.
982
983 **/
984 VOID
985 DestroyForm (
986 IN FORM_BROWSER_FORMSET *FormSet,
987 IN OUT FORM_BROWSER_FORM *Form
988 )
989 {
990 LIST_ENTRY *Link;
991 FORM_EXPRESSION *Expression;
992 FORM_BROWSER_STATEMENT *Statement;
993 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
994
995 //
996 // Free Form Expressions
997 //
998 while (!IsListEmpty (&Form->ExpressionListHead)) {
999 Link = GetFirstNode (&Form->ExpressionListHead);
1000 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1001 RemoveEntryList (&Expression->Link);
1002
1003 DestroyExpression (Expression);
1004 }
1005
1006 //
1007 // Free Statements/Questions
1008 //
1009 while (!IsListEmpty (&Form->StatementListHead)) {
1010 Link = GetFirstNode (&Form->StatementListHead);
1011 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
1012 RemoveEntryList (&Statement->Link);
1013
1014 DestroyStatement (FormSet, Statement);
1015 }
1016
1017 //
1018 // Free ConfigRequest string.
1019 //
1020 while (!IsListEmpty (&Form->ConfigRequestHead)) {
1021 Link = GetFirstNode (&Form->ConfigRequestHead);
1022 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
1023 RemoveEntryList (&ConfigInfo->Link);
1024
1025 FreePool (ConfigInfo->ConfigRequest);
1026 FreePool (ConfigInfo);
1027 }
1028
1029 if (Form->SuppressExpression != NULL) {
1030 FreePool (Form->SuppressExpression);
1031 }
1032
1033 UiFreeMenuList (&Form->FormViewListHead);
1034
1035 //
1036 // Free this Form
1037 //
1038 FreePool (Form);
1039 }
1040
1041
1042 /**
1043 Free resources allocated for a FormSet.
1044
1045 @param FormSet Pointer of the FormSet
1046
1047 **/
1048 VOID
1049 DestroyFormSet (
1050 IN OUT FORM_BROWSER_FORMSET *FormSet
1051 )
1052 {
1053 LIST_ENTRY *Link;
1054 FORMSET_STORAGE *Storage;
1055 FORMSET_DEFAULTSTORE *DefaultStore;
1056 FORM_EXPRESSION *Expression;
1057 FORM_BROWSER_FORM *Form;
1058
1059 if (FormSet->IfrBinaryData == NULL) {
1060 //
1061 // Uninitialized FormSet
1062 //
1063 FreePool (FormSet);
1064 return;
1065 }
1066
1067 //
1068 // Free IFR binary buffer
1069 //
1070 FreePool (FormSet->IfrBinaryData);
1071
1072 //
1073 // Free FormSet Storage
1074 //
1075 if (FormSet->StorageListHead.ForwardLink != NULL) {
1076 while (!IsListEmpty (&FormSet->StorageListHead)) {
1077 Link = GetFirstNode (&FormSet->StorageListHead);
1078 Storage = FORMSET_STORAGE_FROM_LINK (Link);
1079 RemoveEntryList (&Storage->Link);
1080
1081 DestroyStorage (Storage);
1082 }
1083 }
1084
1085 //
1086 // Free FormSet Default Store
1087 //
1088 if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
1089 while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
1090 Link = GetFirstNode (&FormSet->DefaultStoreListHead);
1091 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
1092 RemoveEntryList (&DefaultStore->Link);
1093
1094 FreePool (DefaultStore);
1095 }
1096 }
1097
1098 //
1099 // Free Formset Expressions
1100 //
1101 while (!IsListEmpty (&FormSet->ExpressionListHead)) {
1102 Link = GetFirstNode (&FormSet->ExpressionListHead);
1103 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1104 RemoveEntryList (&Expression->Link);
1105
1106 DestroyExpression (Expression);
1107 }
1108
1109 //
1110 // Free Forms
1111 //
1112 if (FormSet->FormListHead.ForwardLink != NULL) {
1113 while (!IsListEmpty (&FormSet->FormListHead)) {
1114 Link = GetFirstNode (&FormSet->FormListHead);
1115 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
1116 RemoveEntryList (&Form->Link);
1117
1118 DestroyForm (FormSet, Form);
1119 }
1120 }
1121
1122 if (FormSet->StatementBuffer != NULL) {
1123 FreePool (FormSet->StatementBuffer);
1124 }
1125 if (FormSet->ExpressionBuffer != NULL) {
1126 FreePool (FormSet->ExpressionBuffer);
1127 }
1128
1129 FreePool (FormSet);
1130 }
1131
1132
1133 /**
1134 Tell whether this Operand is an Expression OpCode or not
1135
1136 @param Operand Operand of an IFR OpCode.
1137
1138 @retval TRUE This is an Expression OpCode.
1139 @retval FALSE Not an Expression OpCode.
1140
1141 **/
1142 BOOLEAN
1143 IsExpressionOpCode (
1144 IN UINT8 Operand
1145 )
1146 {
1147 if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
1148 ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) ||
1149 ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
1150 (Operand == EFI_IFR_CATENATE_OP) ||
1151 (Operand == EFI_IFR_TO_LOWER_OP) ||
1152 (Operand == EFI_IFR_TO_UPPER_OP) ||
1153 (Operand == EFI_IFR_MAP_OP) ||
1154 (Operand == EFI_IFR_VERSION_OP) ||
1155 (Operand == EFI_IFR_SECURITY_OP) ||
1156 (Operand == EFI_IFR_MATCH2_OP)) {
1157 return TRUE;
1158 } else {
1159 return FALSE;
1160 }
1161 }
1162
1163 /**
1164 Tell whether this Operand is an Statement OpCode.
1165
1166 @param Operand Operand of an IFR OpCode.
1167
1168 @retval TRUE This is an Statement OpCode.
1169 @retval FALSE Not an Statement OpCode.
1170
1171 **/
1172 BOOLEAN
1173 IsStatementOpCode (
1174 IN UINT8 Operand
1175 )
1176 {
1177 if ((Operand == EFI_IFR_SUBTITLE_OP) ||
1178 (Operand == EFI_IFR_TEXT_OP) ||
1179 (Operand == EFI_IFR_RESET_BUTTON_OP) ||
1180 (Operand == EFI_IFR_REF_OP) ||
1181 (Operand == EFI_IFR_ACTION_OP) ||
1182 (Operand == EFI_IFR_NUMERIC_OP) ||
1183 (Operand == EFI_IFR_ORDERED_LIST_OP) ||
1184 (Operand == EFI_IFR_CHECKBOX_OP) ||
1185 (Operand == EFI_IFR_STRING_OP) ||
1186 (Operand == EFI_IFR_PASSWORD_OP) ||
1187 (Operand == EFI_IFR_DATE_OP) ||
1188 (Operand == EFI_IFR_TIME_OP) ||
1189 (Operand == EFI_IFR_GUID_OP) ||
1190 (Operand == EFI_IFR_ONE_OF_OP)) {
1191 return TRUE;
1192 } else {
1193 return FALSE;
1194 }
1195 }
1196
1197 /**
1198 Tell whether this Operand is an known OpCode.
1199
1200 @param Operand Operand of an IFR OpCode.
1201
1202 @retval TRUE This is an Statement OpCode.
1203 @retval FALSE Not an Statement OpCode.
1204
1205 **/
1206 BOOLEAN
1207 IsUnKnownOpCode (
1208 IN UINT8 Operand
1209 )
1210 {
1211 return Operand > EFI_IFR_MATCH2_OP ? TRUE : FALSE;
1212 }
1213
1214 /**
1215 Calculate number of Statemens(Questions) and Expression OpCodes.
1216
1217 @param FormSet The FormSet to be counted.
1218 @param NumberOfStatement Number of Statemens(Questions)
1219 @param NumberOfExpression Number of Expression OpCodes
1220
1221 **/
1222 VOID
1223 CountOpCodes (
1224 IN FORM_BROWSER_FORMSET *FormSet,
1225 IN OUT UINT16 *NumberOfStatement,
1226 IN OUT UINT16 *NumberOfExpression
1227 )
1228 {
1229 UINT16 StatementCount;
1230 UINT16 ExpressionCount;
1231 UINT8 *OpCodeData;
1232 UINTN Offset;
1233 UINTN OpCodeLen;
1234
1235 Offset = 0;
1236 StatementCount = 0;
1237 ExpressionCount = 0;
1238
1239 while (Offset < FormSet->IfrBinaryLength) {
1240 OpCodeData = FormSet->IfrBinaryData + Offset;
1241 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1242 Offset += OpCodeLen;
1243
1244 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
1245 ExpressionCount++;
1246 } else {
1247 StatementCount++;
1248 }
1249 }
1250
1251 *NumberOfStatement = StatementCount;
1252 *NumberOfExpression = ExpressionCount;
1253 }
1254
1255
1256
1257 /**
1258 Parse opcodes in the formset IFR binary.
1259
1260 @param FormSet Pointer of the FormSet data structure.
1261
1262 @retval EFI_SUCCESS Opcode parse success.
1263 @retval Other Opcode parse fail.
1264
1265 **/
1266 EFI_STATUS
1267 ParseOpCodes (
1268 IN FORM_BROWSER_FORMSET *FormSet
1269 )
1270 {
1271 EFI_STATUS Status;
1272 FORM_BROWSER_FORM *CurrentForm;
1273 FORM_BROWSER_STATEMENT *CurrentStatement;
1274 FORM_BROWSER_STATEMENT *ParentStatement;
1275 EXPRESSION_OPCODE *ExpressionOpCode;
1276 FORM_EXPRESSION *CurrentExpression;
1277 UINT8 Operand;
1278 UINT8 Scope;
1279 UINTN OpCodeOffset;
1280 UINTN OpCodeLength;
1281 UINT8 *OpCodeData;
1282 UINT8 ScopeOpCode;
1283 FORMSET_STORAGE *Storage;
1284 FORMSET_DEFAULTSTORE *DefaultStore;
1285 QUESTION_DEFAULT *CurrentDefault;
1286 QUESTION_OPTION *CurrentOption;
1287 UINT8 Width;
1288 UINT16 NumberOfStatement;
1289 UINT16 NumberOfExpression;
1290 EFI_IMAGE_ID *ImageId;
1291 BOOLEAN SuppressForQuestion;
1292 BOOLEAN SuppressForOption;
1293 UINT16 DepthOfDisable;
1294 BOOLEAN OpCodeDisabled;
1295 BOOLEAN SingleOpCodeExpression;
1296 BOOLEAN InScopeDefault;
1297 EFI_HII_VALUE *Value;
1298 EFI_IFR_FORM_MAP_METHOD *MapMethod;
1299 UINT8 MapScopeDepth;
1300 LIST_ENTRY *Link;
1301 FORMSET_STORAGE *VarStorage;
1302 LIST_ENTRY *MapExpressionList;
1303 EFI_VARSTORE_ID TempVarstoreId;
1304 BOOLEAN InScopeDisable;
1305 INTN ConditionalExprCount;
1306 BOOLEAN InUnknownScope;
1307 UINT8 UnknownDepth;
1308
1309 SuppressForQuestion = FALSE;
1310 SuppressForOption = FALSE;
1311 InScopeDisable = FALSE;
1312 DepthOfDisable = 0;
1313 OpCodeDisabled = FALSE;
1314 SingleOpCodeExpression = FALSE;
1315 InScopeDefault = FALSE;
1316 CurrentExpression = NULL;
1317 CurrentDefault = NULL;
1318 CurrentOption = NULL;
1319 ImageId = NULL;
1320 MapMethod = NULL;
1321 MapScopeDepth = 0;
1322 Link = NULL;
1323 VarStorage = NULL;
1324 MapExpressionList = NULL;
1325 TempVarstoreId = 0;
1326 ConditionalExprCount = 0;
1327 InUnknownScope = FALSE;
1328 UnknownDepth = 0;
1329
1330 //
1331 // Get the number of Statements and Expressions
1332 //
1333 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
1334
1335 mStatementIndex = 0;
1336 mUsedQuestionId = 1;
1337 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
1338 if (FormSet->StatementBuffer == NULL) {
1339 return EFI_OUT_OF_RESOURCES;
1340 }
1341
1342 mExpressionOpCodeIndex = 0;
1343 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
1344 if (FormSet->ExpressionBuffer == NULL) {
1345 return EFI_OUT_OF_RESOURCES;
1346 }
1347
1348 InitializeListHead (&FormSet->StatementListOSF);
1349 InitializeListHead (&FormSet->StorageListHead);
1350 InitializeListHead (&FormSet->SaveFailStorageListHead);
1351 InitializeListHead (&FormSet->DefaultStoreListHead);
1352 InitializeListHead (&FormSet->FormListHead);
1353 InitializeListHead (&FormSet->ExpressionListHead);
1354 ResetCurrentExpressionStack ();
1355 ResetMapExpressionListStack ();
1356
1357 CurrentForm = NULL;
1358 CurrentStatement = NULL;
1359 ParentStatement = NULL;
1360
1361 ResetScopeStack ();
1362
1363 OpCodeOffset = 0;
1364 while (OpCodeOffset < FormSet->IfrBinaryLength) {
1365 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
1366
1367 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1368 OpCodeOffset += OpCodeLength;
1369 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
1370 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
1371
1372 if (InUnknownScope) {
1373 if (Operand == EFI_IFR_END_OP) {
1374 UnknownDepth --;
1375
1376 if (UnknownDepth == 0) {
1377 InUnknownScope = FALSE;
1378 }
1379 } else {
1380 if (Scope != 0) {
1381 UnknownDepth ++;
1382 }
1383 }
1384
1385 continue;
1386 }
1387
1388 if (IsUnKnownOpCode(Operand)) {
1389 if (Scope != 0) {
1390 InUnknownScope = TRUE;
1391 UnknownDepth ++;
1392 }
1393
1394 continue;
1395 }
1396
1397 //
1398 // If scope bit set, push onto scope stack
1399 //
1400 if (Scope != 0) {
1401 PushScope (Operand);
1402 }
1403
1404 if (OpCodeDisabled) {
1405 //
1406 // DisableIf Expression is evaluated to be TRUE, try to find its end.
1407 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
1408 //
1409 if (Operand == EFI_IFR_DISABLE_IF_OP) {
1410 DepthOfDisable++;
1411 } else if (Operand == EFI_IFR_END_OP) {
1412 Status = PopScope (&ScopeOpCode);
1413 if (EFI_ERROR (Status)) {
1414 return Status;
1415 }
1416
1417 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
1418 if (DepthOfDisable == 0) {
1419 InScopeDisable = FALSE;
1420 OpCodeDisabled = FALSE;
1421 } else {
1422 DepthOfDisable--;
1423 }
1424 }
1425 }
1426 continue;
1427 }
1428
1429 if (IsExpressionOpCode (Operand)) {
1430 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
1431 mExpressionOpCodeIndex++;
1432
1433 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
1434 ExpressionOpCode->Operand = Operand;
1435 Value = &ExpressionOpCode->Value;
1436
1437 switch (Operand) {
1438 case EFI_IFR_EQ_ID_VAL_OP:
1439 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1440
1441 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1442 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
1443 break;
1444
1445 case EFI_IFR_EQ_ID_ID_OP:
1446 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
1447 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
1448 break;
1449
1450 case EFI_IFR_EQ_ID_VAL_LIST_OP:
1451 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1452 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
1453 ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
1454 break;
1455
1456 case EFI_IFR_TO_STRING_OP:
1457 case EFI_IFR_FIND_OP:
1458 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
1459 break;
1460
1461 case EFI_IFR_STRING_REF1_OP:
1462 Value->Type = EFI_IFR_TYPE_STRING;
1463 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
1464 break;
1465
1466 case EFI_IFR_RULE_REF_OP:
1467 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
1468 break;
1469
1470 case EFI_IFR_SPAN_OP:
1471 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
1472 break;
1473
1474 case EFI_IFR_THIS_OP:
1475 ASSERT (ParentStatement != NULL);
1476 ExpressionOpCode->QuestionId = ParentStatement->QuestionId;
1477 break;
1478
1479 case EFI_IFR_SECURITY_OP:
1480 CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
1481 break;
1482
1483 case EFI_IFR_MATCH2_OP:
1484 CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_MATCH2 *) OpCodeData)->SyntaxType, sizeof (EFI_GUID));
1485 break;
1486
1487 case EFI_IFR_GET_OP:
1488 case EFI_IFR_SET_OP:
1489 CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
1490 if (TempVarstoreId != 0) {
1491 if (FormSet->StorageListHead.ForwardLink != NULL) {
1492 Link = GetFirstNode (&FormSet->StorageListHead);
1493 while (!IsNull (&FormSet->StorageListHead, Link)) {
1494 VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
1495 if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
1496 ExpressionOpCode->VarStorage = VarStorage->BrowserStorage;
1497 break;
1498 }
1499 Link = GetNextNode (&FormSet->StorageListHead, Link);
1500 }
1501 }
1502 if (ExpressionOpCode->VarStorage == NULL) {
1503 //
1504 // VarStorage is not found.
1505 //
1506 return EFI_INVALID_PARAMETER;
1507 }
1508 }
1509 ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;
1510 switch (ExpressionOpCode->ValueType) {
1511 case EFI_IFR_TYPE_BOOLEAN:
1512 case EFI_IFR_TYPE_NUM_SIZE_8:
1513 ExpressionOpCode->ValueWidth = 1;
1514 break;
1515
1516 case EFI_IFR_TYPE_NUM_SIZE_16:
1517 case EFI_IFR_TYPE_STRING:
1518 ExpressionOpCode->ValueWidth = 2;
1519 break;
1520
1521 case EFI_IFR_TYPE_NUM_SIZE_32:
1522 ExpressionOpCode->ValueWidth = 4;
1523 break;
1524
1525 case EFI_IFR_TYPE_NUM_SIZE_64:
1526 ExpressionOpCode->ValueWidth = 8;
1527 break;
1528
1529 case EFI_IFR_TYPE_DATE:
1530 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_DATE);
1531 break;
1532
1533 case EFI_IFR_TYPE_TIME:
1534 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_TIME);
1535 break;
1536
1537 case EFI_IFR_TYPE_REF:
1538 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);
1539 break;
1540
1541 case EFI_IFR_TYPE_OTHER:
1542 case EFI_IFR_TYPE_UNDEFINED:
1543 case EFI_IFR_TYPE_ACTION:
1544 case EFI_IFR_TYPE_BUFFER:
1545 default:
1546 //
1547 // Invalid value type for Get/Set opcode.
1548 //
1549 return EFI_INVALID_PARAMETER;
1550 }
1551 CopyMem (&ExpressionOpCode->VarStoreInfo.VarName, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName, sizeof (EFI_STRING_ID));
1552 CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));
1553 if ((ExpressionOpCode->VarStorage != NULL) &&
1554 (ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE ||
1555 ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
1556 ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle);
1557 if (ExpressionOpCode->ValueName == NULL) {
1558 //
1559 // String ID is invalid.
1560 //
1561 return EFI_INVALID_PARAMETER;
1562 }
1563 }
1564 break;
1565
1566 case EFI_IFR_QUESTION_REF1_OP:
1567 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1568 break;
1569
1570 case EFI_IFR_QUESTION_REF3_OP:
1571 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
1572 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1573
1574 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
1575 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
1576 }
1577 }
1578 break;
1579
1580 //
1581 // constant
1582 //
1583 case EFI_IFR_TRUE_OP:
1584 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1585 Value->Value.b = TRUE;
1586 break;
1587
1588 case EFI_IFR_FALSE_OP:
1589 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1590 Value->Value.b = FALSE;
1591 break;
1592
1593 case EFI_IFR_ONE_OP:
1594 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1595 Value->Value.u8 = 1;
1596 break;
1597
1598 case EFI_IFR_ZERO_OP:
1599 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1600 Value->Value.u8 = 0;
1601 break;
1602
1603 case EFI_IFR_ONES_OP:
1604 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1605 Value->Value.u64 = 0xffffffffffffffffULL;
1606 break;
1607
1608 case EFI_IFR_UINT8_OP:
1609 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1610 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
1611 break;
1612
1613 case EFI_IFR_UINT16_OP:
1614 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1615 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
1616 break;
1617
1618 case EFI_IFR_UINT32_OP:
1619 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1620 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
1621 break;
1622
1623 case EFI_IFR_UINT64_OP:
1624 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1625 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
1626 break;
1627
1628 case EFI_IFR_UNDEFINED_OP:
1629 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1630 break;
1631
1632 case EFI_IFR_VERSION_OP:
1633 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1634 Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
1635 break;
1636
1637 default:
1638 break;
1639 }
1640 //
1641 // Create sub expression nested in MAP opcode
1642 //
1643 if (CurrentExpression == NULL && MapScopeDepth > 0) {
1644 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
1645 ASSERT (MapExpressionList != NULL);
1646 InsertTailList (MapExpressionList, &CurrentExpression->Link);
1647 if (Scope == 0) {
1648 SingleOpCodeExpression = TRUE;
1649 }
1650 }
1651 ASSERT (CurrentExpression != NULL);
1652 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
1653 if (Operand == EFI_IFR_MAP_OP) {
1654 //
1655 // Store current Map Expression List.
1656 //
1657 if (MapExpressionList != NULL) {
1658 PushMapExpressionList (MapExpressionList);
1659 }
1660 //
1661 // Initialize new Map Expression List.
1662 //
1663 MapExpressionList = &ExpressionOpCode->MapExpressionList;
1664 InitializeListHead (MapExpressionList);
1665 //
1666 // Store current expression.
1667 //
1668 PushCurrentExpression (CurrentExpression);
1669 CurrentExpression = NULL;
1670 MapScopeDepth ++;
1671 } else if (SingleOpCodeExpression) {
1672 //
1673 // There are two cases to indicate the end of an Expression:
1674 // for single OpCode expression: one Expression OpCode
1675 // for expression consists of more than one OpCode: EFI_IFR_END
1676 //
1677 SingleOpCodeExpression = FALSE;
1678
1679 if (InScopeDisable && CurrentForm == NULL) {
1680 //
1681 // This is DisableIf expression for Form, it should be a constant expression
1682 //
1683 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1684 if (EFI_ERROR (Status)) {
1685 return Status;
1686 }
1687
1688 OpCodeDisabled = IsTrue(&CurrentExpression->Result);
1689 }
1690
1691 CurrentExpression = NULL;
1692 }
1693
1694 continue;
1695 }
1696
1697 //
1698 // Parse the Opcode
1699 //
1700 switch (Operand) {
1701
1702 case EFI_IFR_FORM_SET_OP:
1703 //
1704 // Check the formset GUID
1705 //
1706 if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1707 return EFI_INVALID_PARAMETER;
1708 }
1709
1710 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1711 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
1712 FormSet->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData;//save the opcode address of formset
1713
1714 if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
1715 //
1716 // The formset OpCode contains ClassGuid
1717 //
1718 FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
1719 CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
1720 }
1721 break;
1722
1723 case EFI_IFR_FORM_OP:
1724 //
1725 // Create a new Form for this FormSet
1726 //
1727 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1728 ASSERT (CurrentForm != NULL);
1729 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1730 InitializeListHead (&CurrentForm->ExpressionListHead);
1731 InitializeListHead (&CurrentForm->StatementListHead);
1732 InitializeListHead (&CurrentForm->ConfigRequestHead);
1733 InitializeListHead (&CurrentForm->FormViewListHead);
1734
1735 CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
1736 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1737 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1738
1739 ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1740 if ( ConditionalExprCount > 0) {
1741 //
1742 // Form is inside of suppressif
1743 //
1744 CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1745 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1746 ASSERT (CurrentForm->SuppressExpression != NULL);
1747 CurrentForm->SuppressExpression->Count = (UINTN) ConditionalExprCount;
1748 CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1749 CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
1750 }
1751
1752 if (Scope != 0) {
1753 //
1754 // Enter scope of a Form, suppressif will be used for Question or Option
1755 //
1756 SuppressForQuestion = TRUE;
1757 }
1758
1759 //
1760 // Insert into Form list of this FormSet
1761 //
1762 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1763 break;
1764
1765 case EFI_IFR_FORM_MAP_OP:
1766 //
1767 // Create a new Form for this FormSet
1768 //
1769 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1770 ASSERT (CurrentForm != NULL);
1771 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1772 InitializeListHead (&CurrentForm->ExpressionListHead);
1773 InitializeListHead (&CurrentForm->StatementListHead);
1774 InitializeListHead (&CurrentForm->ConfigRequestHead);
1775 InitializeListHead (&CurrentForm->FormViewListHead);
1776
1777 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1778
1779 MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1780 //
1781 // FormMap Form must contain at least one Map Method.
1782 //
1783 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) {
1784 return EFI_INVALID_PARAMETER;
1785 }
1786 //
1787 // Try to find the standard form map method.
1788 //
1789 while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) {
1790 if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {
1791 CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1792 CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
1793 break;
1794 }
1795 MapMethod ++;
1796 }
1797 //
1798 // If the standard form map method is not found, the first map method title will be used.
1799 //
1800 if (CurrentForm->FormTitle == 0) {
1801 MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1802 CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1803 }
1804
1805 ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1806 if ( ConditionalExprCount > 0) {
1807 //
1808 // Form is inside of suppressif
1809 //
1810 CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1811 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1812 ASSERT (CurrentForm->SuppressExpression != NULL);
1813 CurrentForm->SuppressExpression->Count = (UINTN) ConditionalExprCount;
1814 CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1815 CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
1816 }
1817
1818 if (Scope != 0) {
1819 //
1820 // Enter scope of a Form, suppressif will be used for Question or Option
1821 //
1822 SuppressForQuestion = TRUE;
1823 }
1824
1825 //
1826 // Insert into Form list of this FormSet
1827 //
1828 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1829 break;
1830
1831 //
1832 // Storage
1833 //
1834 case EFI_IFR_VARSTORE_OP:
1835 //
1836 // Create a buffer Storage for this FormSet
1837 //
1838 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);
1839 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1840 break;
1841
1842 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1843 //
1844 // Create a name/value Storage for this FormSet
1845 //
1846 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);
1847 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1848 break;
1849
1850 case EFI_IFR_VARSTORE_EFI_OP:
1851 //
1852 // Create a EFI variable Storage for this FormSet
1853 //
1854 if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
1855 //
1856 // Create efi varstore with format follow UEFI spec before 2.3.1.
1857 //
1858 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);
1859 } else {
1860 //
1861 // Create efi varstore with format follow UEFI spec 2.3.1 and later.
1862 //
1863 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
1864 }
1865 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1866 break;
1867
1868 //
1869 // DefaultStore
1870 //
1871 case EFI_IFR_DEFAULTSTORE_OP:
1872 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
1873 ASSERT (DefaultStore != NULL);
1874 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1875
1876 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
1877 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1878
1879 //
1880 // Insert to DefaultStore list of this Formset
1881 //
1882 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1883 break;
1884
1885 //
1886 // Statements
1887 //
1888 case EFI_IFR_SUBTITLE_OP:
1889 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1890 ASSERT (CurrentStatement != NULL);
1891
1892 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
1893 CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1894 break;
1895
1896 case EFI_IFR_TEXT_OP:
1897 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1898 ASSERT (CurrentStatement != NULL);
1899 CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1900 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1901 break;
1902
1903 case EFI_IFR_RESET_BUTTON_OP:
1904 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1905 ASSERT (CurrentStatement != NULL);
1906 CurrentStatement->FakeQuestionId = mUsedQuestionId++;
1907 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1908 break;
1909
1910 //
1911 // Questions
1912 //
1913 case EFI_IFR_ACTION_OP:
1914 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1915 ASSERT (CurrentStatement != NULL);
1916 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
1917
1918 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1919 //
1920 // No QuestionConfig present, so no configuration string will be processed
1921 //
1922 CurrentStatement->QuestionConfig = 0;
1923 } else {
1924 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1925 }
1926 break;
1927
1928 case EFI_IFR_REF_OP:
1929 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1930 ASSERT (CurrentStatement != NULL);
1931 Value = &CurrentStatement->HiiValue;
1932 Value->Type = EFI_IFR_TYPE_REF;
1933 if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
1934 CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
1935
1936 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1937 CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1938
1939 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1940 CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1941
1942 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1943 CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1944 }
1945 }
1946 }
1947 }
1948 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
1949 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
1950 break;
1951
1952 case EFI_IFR_ONE_OF_OP:
1953 case EFI_IFR_NUMERIC_OP:
1954 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1955 ASSERT(CurrentStatement != NULL);
1956
1957 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1958 Value = &CurrentStatement->HiiValue;
1959
1960 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1961 case EFI_IFR_NUMERIC_SIZE_1:
1962 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1963 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1964 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
1965 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
1966 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1967 break;
1968
1969 case EFI_IFR_NUMERIC_SIZE_2:
1970 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1971 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1972 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
1973 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
1974 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1975 break;
1976
1977 case EFI_IFR_NUMERIC_SIZE_4:
1978 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
1979 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
1980 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
1981 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
1982 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1983 break;
1984
1985 case EFI_IFR_NUMERIC_SIZE_8:
1986 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
1987 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
1988 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
1989 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
1990 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1991 break;
1992
1993 default:
1994 break;
1995 }
1996
1997 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
1998
1999 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
2000 SuppressForOption = TRUE;
2001 }
2002 break;
2003
2004 case EFI_IFR_ORDERED_LIST_OP:
2005 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2006 ASSERT(CurrentStatement != NULL);
2007
2008 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
2009 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
2010
2011 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
2012 CurrentStatement->BufferValue = NULL;
2013
2014 if (Scope != 0) {
2015 SuppressForOption = TRUE;
2016 }
2017 break;
2018
2019 case EFI_IFR_CHECKBOX_OP:
2020 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2021 ASSERT(CurrentStatement != NULL);
2022
2023 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
2024 CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
2025 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
2026
2027 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2028
2029 break;
2030
2031 case EFI_IFR_STRING_OP:
2032 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2033 ASSERT (CurrentStatement != NULL);
2034 //
2035 // MinSize is the minimum number of characters that can be accepted for this opcode,
2036 // MaxSize is the maximum number of characters that can be accepted for this opcode.
2037 // The characters are stored as Unicode, so the storage width should multiply 2.
2038 //
2039 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
2040 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
2041 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2042 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
2043
2044 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2045 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
2046 CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
2047
2048 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2049 break;
2050
2051 case EFI_IFR_PASSWORD_OP:
2052 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2053 ASSERT (CurrentStatement != NULL);
2054 //
2055 // MinSize is the minimum number of characters that can be accepted for this opcode,
2056 // MaxSize is the maximum number of characters that can be accepted for this opcode.
2057 // The characters are stored as Unicode, so the storage width should multiply 2.
2058 //
2059 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
2060 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
2061 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2062
2063 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2064 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
2065 CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
2066
2067 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2068 break;
2069
2070 case EFI_IFR_DATE_OP:
2071 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2072 ASSERT(CurrentStatement != NULL);
2073
2074 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
2075 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
2076
2077 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
2078 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
2079
2080 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2081 } else {
2082 //
2083 // Don't assign storage for RTC type of date/time
2084 //
2085 CurrentStatement->Storage = NULL;
2086 CurrentStatement->StorageWidth = 0;
2087 }
2088 break;
2089
2090 case EFI_IFR_TIME_OP:
2091 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2092 ASSERT(CurrentStatement != NULL);
2093
2094 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
2095 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
2096
2097 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
2098 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
2099
2100 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
2101 } else {
2102 //
2103 // Don't assign storage for RTC type of date/time
2104 //
2105 CurrentStatement->Storage = NULL;
2106 CurrentStatement->StorageWidth = 0;
2107 }
2108 break;
2109
2110 //
2111 // Default
2112 //
2113 case EFI_IFR_DEFAULT_OP:
2114 //
2115 // EFI_IFR_DEFAULT appear in scope of a Question,
2116 // It creates a default value for the current question.
2117 // A Question may have more than one Default value which have different default types.
2118 //
2119 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
2120 ASSERT (CurrentDefault != NULL);
2121 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2122
2123 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
2124 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
2125 if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {
2126 CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2127 CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *) OpCodeData)->Value);
2128 ASSERT (CurrentDefault->Value.Buffer != NULL);
2129 } else {
2130 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
2131 ExtendValueToU64 (&CurrentDefault->Value);
2132 }
2133
2134 //
2135 // Insert to Default Value list of current Question
2136 //
2137 InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
2138
2139 if (Scope != 0) {
2140 InScopeDefault = TRUE;
2141 }
2142 break;
2143
2144 //
2145 // Option
2146 //
2147 case EFI_IFR_ONE_OF_OPTION_OP:
2148 ASSERT (ParentStatement != NULL);
2149 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)) {
2150 //
2151 // It's keep the default value for ordered list opcode.
2152 //
2153 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
2154 ASSERT (CurrentDefault != NULL);
2155 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2156
2157 CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;
2158 if ((((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
2159 CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2160 } else {
2161 CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2162 }
2163
2164 CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2165 CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value);
2166 ASSERT (CurrentDefault->Value.Buffer != NULL);
2167
2168 //
2169 // Insert to Default Value list of current Question
2170 //
2171 InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
2172 break;
2173 }
2174
2175 //
2176 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
2177 // It create a selection for use in current Question.
2178 //
2179 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
2180 ASSERT (CurrentOption != NULL);
2181 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
2182 CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION *) OpCodeData;
2183
2184 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
2185 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
2186 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
2187 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2188 ExtendValueToU64 (&CurrentOption->Value);
2189
2190 ConditionalExprCount = GetConditionalExpressionCount(ExpressOption);
2191 if ( ConditionalExprCount > 0) {
2192 //
2193 // Form is inside of suppressif
2194 //
2195 CurrentOption->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
2196 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
2197 ASSERT (CurrentOption->SuppressExpression != NULL);
2198 CurrentOption->SuppressExpression->Count = (UINTN) ConditionalExprCount;
2199 CurrentOption->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
2200 CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList(ExpressOption), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
2201 }
2202
2203 //
2204 // Insert to Option list of current Question
2205 //
2206 InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link);
2207 //
2208 // Now we know the Storage width of nested Ordered List
2209 //
2210 if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->BufferValue == NULL)) {
2211 Width = 1;
2212 switch (CurrentOption->Value.Type) {
2213 case EFI_IFR_TYPE_NUM_SIZE_8:
2214 Width = 1;
2215 break;
2216
2217 case EFI_IFR_TYPE_NUM_SIZE_16:
2218 Width = 2;
2219 break;
2220
2221 case EFI_IFR_TYPE_NUM_SIZE_32:
2222 Width = 4;
2223 break;
2224
2225 case EFI_IFR_TYPE_NUM_SIZE_64:
2226 Width = 8;
2227 break;
2228
2229 default:
2230 //
2231 // Invalid type for Ordered List
2232 //
2233 break;
2234 }
2235
2236 ParentStatement->StorageWidth = (UINT16) (ParentStatement->MaxContainers * Width);
2237 ParentStatement->BufferValue = AllocateZeroPool (ParentStatement->StorageWidth);
2238 ParentStatement->ValueType = CurrentOption->Value.Type;
2239 if (ParentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
2240 ParentStatement->HiiValue.Buffer = ParentStatement->BufferValue;
2241 ParentStatement->HiiValue.BufferLen = ParentStatement->StorageWidth;
2242 }
2243
2244 InitializeRequestElement (FormSet, ParentStatement, CurrentForm);
2245 }
2246 break;
2247
2248 //
2249 // Conditional
2250 //
2251 case EFI_IFR_NO_SUBMIT_IF_OP:
2252 case EFI_IFR_INCONSISTENT_IF_OP:
2253 //
2254 // Create an Expression node
2255 //
2256 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2257 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
2258
2259 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
2260 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
2261 InsertTailList (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link);
2262 } else {
2263 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
2264 InsertTailList (&ParentStatement->InconsistentListHead, &CurrentExpression->Link);
2265 }
2266
2267 //
2268 // Take a look at next OpCode to see whether current expression consists
2269 // of single OpCode
2270 //
2271 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2272 SingleOpCodeExpression = TRUE;
2273 }
2274 break;
2275
2276 case EFI_IFR_WARNING_IF_OP:
2277 //
2278 // Create an Expression node
2279 //
2280 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2281 CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));
2282 CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;
2283 CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF;
2284 InsertTailList (&ParentStatement->WarningListHead, &CurrentExpression->Link);
2285
2286 //
2287 // Take a look at next OpCode to see whether current expression consists
2288 // of single OpCode
2289 //
2290 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2291 SingleOpCodeExpression = TRUE;
2292 }
2293 break;
2294
2295 case EFI_IFR_SUPPRESS_IF_OP:
2296 //
2297 // Question and Option will appear in scope of this OpCode
2298 //
2299 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2300 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
2301
2302 if (CurrentForm == NULL) {
2303 InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
2304 } else {
2305 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2306 }
2307
2308 if (SuppressForOption) {
2309 PushConditionalExpression(CurrentExpression, ExpressOption);
2310 } else if (SuppressForQuestion) {
2311 PushConditionalExpression(CurrentExpression, ExpressStatement);
2312 } else {
2313 PushConditionalExpression(CurrentExpression, ExpressForm);
2314 }
2315
2316 //
2317 // Take a look at next OpCode to see whether current expression consists
2318 // of single OpCode
2319 //
2320 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2321 SingleOpCodeExpression = TRUE;
2322 }
2323 break;
2324
2325 case EFI_IFR_GRAY_OUT_IF_OP:
2326 //
2327 // Questions will appear in scope of this OpCode
2328 //
2329 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2330 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
2331 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2332 PushConditionalExpression(CurrentExpression, ExpressStatement);
2333
2334 //
2335 // Take a look at next OpCode to see whether current expression consists
2336 // of single OpCode
2337 //
2338 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2339 SingleOpCodeExpression = TRUE;
2340 }
2341 break;
2342
2343 case EFI_IFR_DISABLE_IF_OP:
2344 //
2345 // The DisableIf expression should only rely on constant, so it could be
2346 // evaluated at initialization and it will not be queued
2347 //
2348 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
2349 ASSERT (CurrentExpression != NULL);
2350 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
2351 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
2352 InitializeListHead (&CurrentExpression->OpCodeListHead);
2353
2354 if (CurrentForm != NULL) {
2355 //
2356 // This is DisableIf for Question, enqueue it to Form expression list
2357 //
2358 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2359 PushConditionalExpression(CurrentExpression, ExpressStatement);
2360 }
2361
2362 OpCodeDisabled = FALSE;
2363 InScopeDisable = TRUE;
2364 //
2365 // Take a look at next OpCode to see whether current expression consists
2366 // of single OpCode
2367 //
2368 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2369 SingleOpCodeExpression = TRUE;
2370 }
2371 break;
2372
2373 //
2374 // Expression
2375 //
2376 case EFI_IFR_VALUE_OP:
2377 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2378 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
2379 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2380
2381 if (InScopeDefault) {
2382 //
2383 // Used for default (EFI_IFR_DEFAULT)
2384 //
2385 CurrentDefault->ValueExpression = CurrentExpression;
2386 } else {
2387 //
2388 // If used for a question, then the question will be read-only
2389 //
2390 //
2391 // Make sure CurrentStatement is not NULL.
2392 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2393 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2394 //
2395 ASSERT (ParentStatement != NULL);
2396 ParentStatement->ValueExpression = CurrentExpression;
2397 }
2398
2399 //
2400 // Take a look at next OpCode to see whether current expression consists
2401 // of single OpCode
2402 //
2403 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2404 SingleOpCodeExpression = TRUE;
2405 }
2406 break;
2407
2408 case EFI_IFR_RULE_OP:
2409 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2410 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
2411
2412 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
2413 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2414
2415 //
2416 // Take a look at next OpCode to see whether current expression consists
2417 // of single OpCode
2418 //
2419 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2420 SingleOpCodeExpression = TRUE;
2421 }
2422 break;
2423
2424 case EFI_IFR_READ_OP:
2425 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2426 CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
2427 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2428
2429 //
2430 // Make sure CurrentStatement is not NULL.
2431 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2432 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2433 //
2434 ASSERT (ParentStatement != NULL);
2435 ParentStatement->ReadExpression = CurrentExpression;
2436
2437 //
2438 // Take a look at next OpCode to see whether current expression consists
2439 // of single OpCode
2440 //
2441 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2442 SingleOpCodeExpression = TRUE;
2443 }
2444 break;
2445
2446 case EFI_IFR_WRITE_OP:
2447 CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
2448 CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
2449 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2450
2451 //
2452 // Make sure CurrentStatement is not NULL.
2453 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2454 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2455 //
2456 ASSERT (ParentStatement != NULL);
2457 ParentStatement->WriteExpression = CurrentExpression;
2458
2459 //
2460 // Take a look at next OpCode to see whether current expression consists
2461 // of single OpCode
2462 //
2463 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2464 SingleOpCodeExpression = TRUE;
2465 }
2466 break;
2467
2468 //
2469 // Image
2470 //
2471 case EFI_IFR_IMAGE_OP:
2472 //
2473 // Get ScopeOpcode from top of stack
2474 //
2475 PopScope (&ScopeOpCode);
2476 PushScope (ScopeOpCode);
2477
2478 switch (ScopeOpCode) {
2479 case EFI_IFR_FORM_SET_OP:
2480 ImageId = &FormSet->ImageId;
2481 break;
2482
2483 case EFI_IFR_FORM_OP:
2484 case EFI_IFR_FORM_MAP_OP:
2485 ASSERT (CurrentForm != NULL);
2486 ImageId = &CurrentForm->ImageId;
2487 break;
2488
2489 case EFI_IFR_ONE_OF_OPTION_OP:
2490 ASSERT (CurrentOption != NULL);
2491 ImageId = &CurrentOption->ImageId;
2492 break;
2493
2494 default:
2495 //
2496 // Make sure CurrentStatement is not NULL.
2497 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2498 // file is wrongly generated by tools such as VFR Compiler.
2499 //
2500 ASSERT (ParentStatement != NULL);
2501 ImageId = &ParentStatement->ImageId;
2502 break;
2503 }
2504
2505 ASSERT (ImageId != NULL);
2506 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
2507 break;
2508
2509 //
2510 // Refresh
2511 //
2512 case EFI_IFR_REFRESH_OP:
2513 ASSERT (ParentStatement != NULL);
2514 ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
2515 break;
2516
2517 //
2518 // Refresh guid.
2519 //
2520 case EFI_IFR_REFRESH_ID_OP:
2521 //
2522 // Get ScopeOpcode from top of stack
2523 //
2524 PopScope (&ScopeOpCode);
2525 PushScope (ScopeOpCode);
2526
2527 switch (ScopeOpCode) {
2528 case EFI_IFR_FORM_OP:
2529 case EFI_IFR_FORM_MAP_OP:
2530 ASSERT (CurrentForm != NULL);
2531 CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
2532 break;
2533
2534 default:
2535 ASSERT (ParentStatement != NULL);
2536 CopyMem (&ParentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
2537 break;
2538 }
2539 break;
2540
2541 //
2542 // Modal tag
2543 //
2544 case EFI_IFR_MODAL_TAG_OP:
2545 ASSERT (CurrentForm != NULL);
2546 CurrentForm->ModalForm = TRUE;
2547 break;
2548
2549 //
2550 // Lock tag, used by form and statement.
2551 //
2552 case EFI_IFR_LOCKED_OP:
2553 //
2554 // Get ScopeOpcode from top of stack
2555 //
2556 PopScope (&ScopeOpCode);
2557 PushScope (ScopeOpCode);
2558 switch (ScopeOpCode) {
2559 case EFI_IFR_FORM_OP:
2560 case EFI_IFR_FORM_MAP_OP:
2561 ASSERT (CurrentForm != NULL);
2562 CurrentForm->Locked = TRUE;
2563 break;
2564
2565 default:
2566 ASSERT (ParentStatement != NULL);
2567 ParentStatement->Locked = TRUE;
2568 }
2569 break;
2570
2571 //
2572 // Vendor specific
2573 //
2574 case EFI_IFR_GUID_OP:
2575 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
2576 break;
2577
2578 //
2579 // Scope End
2580 //
2581 case EFI_IFR_END_OP:
2582 Status = PopScope (&ScopeOpCode);
2583 if (EFI_ERROR (Status)) {
2584 ResetScopeStack ();
2585 return Status;
2586 }
2587
2588 //
2589 // Parent statement end tag found, update ParentStatement info.
2590 //
2591 if (IsStatementOpCode(ScopeOpCode) && (ParentStatement != NULL) && (ParentStatement->Operand == ScopeOpCode)) {
2592 ParentStatement = ParentStatement->ParentStatement;
2593 }
2594
2595 switch (ScopeOpCode) {
2596 case EFI_IFR_FORM_SET_OP:
2597 //
2598 // End of FormSet, update FormSet IFR binary length
2599 // to stop parsing substantial OpCodes
2600 //
2601 FormSet->IfrBinaryLength = OpCodeOffset;
2602 break;
2603
2604 case EFI_IFR_FORM_OP:
2605 case EFI_IFR_FORM_MAP_OP:
2606 //
2607 // End of Form
2608 //
2609 CurrentForm = NULL;
2610 SuppressForQuestion = FALSE;
2611 break;
2612
2613 case EFI_IFR_ONE_OF_OPTION_OP:
2614 //
2615 // End of Option
2616 //
2617 CurrentOption = NULL;
2618 break;
2619
2620 case EFI_IFR_NO_SUBMIT_IF_OP:
2621 case EFI_IFR_INCONSISTENT_IF_OP:
2622 case EFI_IFR_WARNING_IF_OP:
2623 //
2624 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
2625 //
2626 break;
2627
2628 case EFI_IFR_SUPPRESS_IF_OP:
2629 if (SuppressForOption) {
2630 PopConditionalExpression(ExpressOption);
2631 } else if (SuppressForQuestion) {
2632 PopConditionalExpression(ExpressStatement);
2633 } else {
2634 PopConditionalExpression(ExpressForm);
2635 }
2636 break;
2637
2638 case EFI_IFR_GRAY_OUT_IF_OP:
2639 PopConditionalExpression(ExpressStatement);
2640 break;
2641
2642 case EFI_IFR_DISABLE_IF_OP:
2643 if (CurrentForm != NULL) {
2644 PopConditionalExpression(ExpressStatement);
2645 }
2646 InScopeDisable = FALSE;
2647 OpCodeDisabled = FALSE;
2648 break;
2649
2650 case EFI_IFR_ONE_OF_OP:
2651 case EFI_IFR_ORDERED_LIST_OP:
2652 SuppressForOption = FALSE;
2653 break;
2654
2655 case EFI_IFR_DEFAULT_OP:
2656 InScopeDefault = FALSE;
2657 break;
2658
2659 case EFI_IFR_MAP_OP:
2660 //
2661 // Get current Map Expression List.
2662 //
2663 Status = PopMapExpressionList ((VOID **) &MapExpressionList);
2664 if (Status == EFI_ACCESS_DENIED) {
2665 MapExpressionList = NULL;
2666 }
2667 //
2668 // Get current expression.
2669 //
2670 Status = PopCurrentExpression ((VOID **) &CurrentExpression);
2671 ASSERT_EFI_ERROR (Status);
2672 ASSERT (MapScopeDepth > 0);
2673 MapScopeDepth --;
2674 break;
2675
2676 default:
2677 if (IsExpressionOpCode (ScopeOpCode)) {
2678 if (InScopeDisable && CurrentForm == NULL) {
2679 //
2680 // This is DisableIf expression for Form, it should be a constant expression
2681 //
2682 ASSERT (CurrentExpression != NULL);
2683 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
2684 if (EFI_ERROR (Status)) {
2685 return Status;
2686 }
2687
2688 OpCodeDisabled = IsTrue (&CurrentExpression->Result);
2689
2690 //
2691 // DisableIf Expression is only used once and not queued, free it
2692 //
2693 DestroyExpression (CurrentExpression);
2694 }
2695
2696 //
2697 // End of current Expression
2698 //
2699 CurrentExpression = NULL;
2700 }
2701 break;
2702 }
2703 break;
2704
2705 default:
2706 break;
2707 }
2708
2709 if (IsStatementOpCode(Operand)) {
2710 CurrentStatement->ParentStatement = ParentStatement;
2711 if (Scope != 0) {
2712 //
2713 // Scope != 0, other statements or options may nest in this statement.
2714 // Update the ParentStatement info.
2715 //
2716 ParentStatement = CurrentStatement;
2717 }
2718 }
2719 }
2720
2721 return EFI_SUCCESS;
2722 }