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