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