blob: 11839ad6cee5602ec884bffeafab54bde41544c9 [file] [log] [blame]
qhuang8c60a0612008-10-31 04:41:33 +00001/** @file
2Parser for IFR binary encoding.
3
ydong10a7f87052013-01-06 06:12:50 +00004Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
hhtiane5eed7d2010-04-24 09:33:45 +00005This program and the accompanying materials
qhuang8c60a0612008-10-31 04:41:33 +00006are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "Setup.h"
qhuang8c60a0612008-10-31 04:41:33 +000016
17UINT16 mStatementIndex;
18UINT16 mExpressionOpCodeIndex;
Eric Dong7c6c0642013-08-12 02:19:56 +000019EFI_QUESTION_ID mUsedQuestionId;
qhuang8c60a0612008-10-31 04:41:33 +000020BOOLEAN mInScopeSubtitle;
ydong1094f3aae2013-04-16 10:53:22 +000021extern LIST_ENTRY gBrowserStorageList;
qhuang8c60a0612008-10-31 04:41:33 +000022/**
23 Initialize Statement header members.
24
25 @param OpCodeData Pointer of the raw OpCode data.
26 @param FormSet Pointer of the current FormSe.
27 @param Form Pointer of the current Form.
28
29 @return The Statement.
30
31**/
32FORM_BROWSER_STATEMENT *
33CreateStatement (
34 IN UINT8 *OpCodeData,
35 IN OUT FORM_BROWSER_FORMSET *FormSet,
36 IN OUT FORM_BROWSER_FORM *Form
37 )
38{
39 FORM_BROWSER_STATEMENT *Statement;
40 EFI_IFR_STATEMENT_HEADER *StatementHdr;
ydong1031585af2012-01-31 07:17:42 +000041 INTN ConditionalExprCount;
qhuang8c60a0612008-10-31 04:41:33 +000042
43 if (Form == NULL) {
44 //
Eric Dong7c6c0642013-08-12 02:19:56 +000045 // Only guid op may out side the form level.
qhuang8c60a0612008-10-31 04:41:33 +000046 //
Eric Dong7c6c0642013-08-12 02:19:56 +000047 ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP);
qhuang8c60a0612008-10-31 04:41:33 +000048 }
49
50 Statement = &FormSet->StatementBuffer[mStatementIndex];
51 mStatementIndex++;
52
53 InitializeListHead (&Statement->DefaultListHead);
54 InitializeListHead (&Statement->OptionListHead);
55 InitializeListHead (&Statement->InconsistentListHead);
56 InitializeListHead (&Statement->NoSubmitListHead);
57
58 Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
59
60 Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
Eric Dong7c6c0642013-08-12 02:19:56 +000061 Statement->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData;
qhuang8c60a0612008-10-31 04:41:33 +000062
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
ydong1031585af2012-01-31 07:17:42 +000067 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));
lgao40a1147e2009-04-22 03:18:37 +000079 }
80
qhuang8c60a0612008-10-31 04:41:33 +000081 Statement->InSubtitle = mInScopeSubtitle;
82
83 //
84 // Insert this Statement into current Form
85 //
Eric Dong7c6c0642013-08-12 02:19:56 +000086 if (Form == NULL) {
87 InsertTailList (&FormSet->StatementListOSF, &Statement->Link);
88 } else {
89 InsertTailList (&Form->StatementListHead, &Statement->Link);
90 }
qhuang8c60a0612008-10-31 04:41:33 +000091 return Statement;
92}
93
qwang127064c0a2008-11-19 13:36:34 +000094/**
95 Convert a numeric value to a Unicode String and insert it to String Package.
96 This string is used as the Unicode Name for the EFI Variable. This is to support
97 the deprecated vareqval opcode.
xdu28b0fc5c2009-10-26 03:05:16 +000098
qwang127064c0a2008-11-19 13:36:34 +000099 @param FormSet The FormSet.
100 @param Statement The numeric question whose VarStoreInfo.VarName is the
101 numeric value which is used to produce the Unicode Name
102 for the EFI Variable.
xdu28b0fc5c2009-10-26 03:05:16 +0000103
qwang127064c0a2008-11-19 13:36:34 +0000104 If the Statement is NULL, the ASSERT.
105 If the opcode is not Numeric, then ASSERT.
xdu28b0fc5c2009-10-26 03:05:16 +0000106
qwang127064c0a2008-11-19 13:36:34 +0000107 @retval EFI_SUCCESS The funtion always succeeds.
108**/
qhuang8c60a0612008-10-31 04:41:33 +0000109EFI_STATUS
110UpdateCheckBoxStringToken (
111 IN CONST FORM_BROWSER_FORMSET *FormSet,
112 IN FORM_BROWSER_STATEMENT *Statement
113 )
114{
115 CHAR16 Str[MAXIMUM_VALUE_CHARACTERS];
116 EFI_STRING_ID Id;
qhuang8c60a0612008-10-31 04:41:33 +0000117
118 ASSERT (Statement != NULL);
119 ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP);
xdu28b0fc5c2009-10-26 03:05:16 +0000120
qhuang8c60a0612008-10-31 04:41:33 +0000121 UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1);
qhuang8c60a0612008-10-31 04:41:33 +0000122
rsun3cb7d01c2009-04-14 10:47:19 +0000123 Id = HiiSetString (FormSet->HiiHandle, 0, Str, NULL);
124 if (Id == 0) {
125 return EFI_OUT_OF_RESOURCES;
qhuang8c60a0612008-10-31 04:41:33 +0000126 }
127
128 Statement->VarStoreInfo.VarName = Id;
xdu28b0fc5c2009-10-26 03:05:16 +0000129
qhuang8c60a0612008-10-31 04:41:33 +0000130 return EFI_SUCCESS;
131}
132
qwang127064c0a2008-11-19 13:36:34 +0000133/**
134 Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME.
xdu28b0fc5c2009-10-26 03:05:16 +0000135
qwang127064c0a2008-11-19 13:36:34 +0000136 @param OpCodeData The current opcode.
xdu28b0fc5c2009-10-26 03:05:16 +0000137
qwang127064c0a2008-11-19 13:36:34 +0000138 @retval TRUE Yes.
139 @retval FALSE No.
140**/
qhuang8c60a0612008-10-31 04:41:33 +0000141BOOLEAN
142IsNextOpCodeGuidedVarEqName (
xdu28b0fc5c2009-10-26 03:05:16 +0000143 IN UINT8 *OpCodeData
qhuang8c60a0612008-10-31 04:41:33 +0000144 )
145{
146 //
147 // Get next opcode
148 //
149 OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
150 if (*OpCodeData == EFI_IFR_GUID_OP) {
lgao45c526732009-02-23 15:18:48 +0000151 if (CompareGuid (&gEfiIfrFrameworkGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
qhuang8c60a0612008-10-31 04:41:33 +0000152 //
xdu28b0fc5c2009-10-26 03:05:16 +0000153 // Specific GUIDed opcodes to support IFR generated from Framework HII VFR
qhuang8c60a0612008-10-31 04:41:33 +0000154 //
155 if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) {
156 return TRUE;
157 }
158 }
159 }
160
161 return FALSE;
162}
163
164/**
165 Initialize Question's members.
166
167 @param OpCodeData Pointer of the raw OpCode data.
168 @param FormSet Pointer of the current FormSet.
169 @param Form Pointer of the current Form.
170
171 @return The Question.
172
173**/
174FORM_BROWSER_STATEMENT *
175CreateQuestion (
176 IN UINT8 *OpCodeData,
177 IN OUT FORM_BROWSER_FORMSET *FormSet,
178 IN OUT FORM_BROWSER_FORM *Form
179 )
180{
181 FORM_BROWSER_STATEMENT *Statement;
182 EFI_IFR_QUESTION_HEADER *QuestionHdr;
183 LIST_ENTRY *Link;
184 FORMSET_STORAGE *Storage;
185 NAME_VALUE_NODE *NameValueNode;
186 EFI_STATUS Status;
ydong1094f3aae2013-04-16 10:53:22 +0000187 BOOLEAN Find;
qhuang8c60a0612008-10-31 04:41:33 +0000188
189 Statement = CreateStatement (OpCodeData, FormSet, Form);
190 if (Statement == NULL) {
191 return NULL;
192 }
193
194 QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
195 CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
196 CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
197 CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
198
199 Statement->QuestionFlags = QuestionHdr->Flags;
200
201 if (Statement->VarStoreId == 0) {
202 //
203 // VarStoreId of zero indicates no variable storage
204 //
205 return Statement;
206 }
207
208 //
209 // Take a look at next OpCode to see whether it is a GUIDed opcode to support
210 // Framework Compatibility
211 //
lgao4f806dd22009-02-25 09:04:47 +0000212 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
qhuang8c60a0612008-10-31 04:41:33 +0000213 if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {
214 Status = UpdateCheckBoxStringToken (FormSet, Statement);
215 if (EFI_ERROR (Status)) {
216 return NULL;
217 }
218 }
219 }
220
221 //
222 // Find Storage for this Question
223 //
224 Link = GetFirstNode (&FormSet->StorageListHead);
225 while (!IsNull (&FormSet->StorageListHead, Link)) {
226 Storage = FORMSET_STORAGE_FROM_LINK (Link);
227
228 if (Storage->VarStoreId == Statement->VarStoreId) {
ydong1094f3aae2013-04-16 10:53:22 +0000229 Statement->Storage = Storage->BrowserStorage;
qhuang8c60a0612008-10-31 04:41:33 +0000230 break;
231 }
232
233 Link = GetNextNode (&FormSet->StorageListHead, Link);
234 }
235 ASSERT (Statement->Storage != NULL);
236
237 //
238 // Initialilze varname for Name/Value or EFI Variable
239 //
240 if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
241 (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
242 Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);
243 ASSERT (Statement->VariableName != NULL);
244
245 if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
246 //
ydong1094f3aae2013-04-16 10:53:22 +0000247 // Check whether old string node already exist.
qhuang8c60a0612008-10-31 04:41:33 +0000248 //
ydong1094f3aae2013-04-16 10:53:22 +0000249 Find = FALSE;
250 if (!IsListEmpty(&Statement->Storage->NameValueListHead)) {
251 Link = GetFirstNode (&Statement->Storage->NameValueListHead);
252 while (!IsNull (&Statement->Storage->NameValueListHead, Link)) {
253 NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
qhuang8c60a0612008-10-31 04:41:33 +0000254
ydong1094f3aae2013-04-16 10:53:22 +0000255 if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) {
256 Find = TRUE;
257 break;
258 }
259
260 Link = GetNextNode (&Statement->Storage->NameValueListHead, Link);
261 }
262 }
263
264 if (!Find) {
265 //
266 // Insert to Name/Value varstore list
267 //
268 NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
269 ASSERT (NameValueNode != NULL);
270 NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
271 NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
272 ASSERT (NameValueNode->Name != NULL);
273 NameValueNode->Value = AllocateZeroPool (0x10);
274 ASSERT (NameValueNode->Value != NULL);
275 NameValueNode->EditValue = AllocateZeroPool (0x10);
276 ASSERT (NameValueNode->EditValue != NULL);
277
278 InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
279 }
qhuang8c60a0612008-10-31 04:41:33 +0000280 }
281 }
282
283 return Statement;
284}
285
286
287/**
288 Allocate a FORM_EXPRESSION node.
289
290 @param Form The Form associated with this Expression
291
292 @return Pointer to a FORM_EXPRESSION data structure.
293
294**/
295FORM_EXPRESSION *
296CreateExpression (
297 IN OUT FORM_BROWSER_FORM *Form
298 )
299{
300 FORM_EXPRESSION *Expression;
301
302 Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
jji41ac628e2009-01-19 07:58:58 +0000303 ASSERT (Expression != NULL);
qhuang8c60a0612008-10-31 04:41:33 +0000304 Expression->Signature = FORM_EXPRESSION_SIGNATURE;
305 InitializeListHead (&Expression->OpCodeListHead);
306
307 return Expression;
308}
309
qhuang8c60a0612008-10-31 04:41:33 +0000310/**
311 Create ConfigHdr string for a storage.
312
313 @param FormSet Pointer of the current FormSet
314 @param Storage Pointer of the storage
315
316 @retval EFI_SUCCESS Initialize ConfigHdr success
317
318**/
319EFI_STATUS
320InitializeConfigHdr (
321 IN FORM_BROWSER_FORMSET *FormSet,
ydong1094f3aae2013-04-16 10:53:22 +0000322 IN OUT BROWSER_STORAGE *Storage
qhuang8c60a0612008-10-31 04:41:33 +0000323 )
324{
qhuang8c60a0612008-10-31 04:41:33 +0000325 CHAR16 *Name;
xdu28b0fc5c2009-10-26 03:05:16 +0000326
ydong10cce62302011-07-12 07:24:36 +0000327 if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
328 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
qhuang8c60a0612008-10-31 04:41:33 +0000329 Name = Storage->Name;
330 } else {
331 Name = NULL;
332 }
xdu28b0fc5c2009-10-26 03:05:16 +0000333
lgao47e3bccc2009-04-13 06:05:15 +0000334 Storage->ConfigHdr = HiiConstructConfigHdr (
335 &Storage->Guid,
336 Name,
337 FormSet->DriverHandle
338 );
xdu28b0fc5c2009-10-26 03:05:16 +0000339
lgao47e3bccc2009-04-13 06:05:15 +0000340 if (Storage->ConfigHdr == NULL) {
341 return EFI_NOT_FOUND;
qhuang8c60a0612008-10-31 04:41:33 +0000342 }
343
qhuang8c60a0612008-10-31 04:41:33 +0000344 return EFI_SUCCESS;
345}
346
ydong1094f3aae2013-04-16 10:53:22 +0000347/**
348 Find the global storage link base on the input storate type, name and guid.
349
350 @param StorageType Storage type.
351 @param StorageGuid Storage guid.
352 @param StorageName Storage Name.
353
354 @return Pointer to a GLOBAL_STORAGE data structure.
355
356**/
357BROWSER_STORAGE *
358FindStorageInList (
359 IN UINT8 StorageType,
360 IN EFI_GUID *StorageGuid,
361 IN CHAR16 *StorageName
362 )
363{
364 LIST_ENTRY *Link;
365 BROWSER_STORAGE *BrowserStorage;
366
367 Link = GetFirstNode (&gBrowserStorageList);
368 while (!IsNull (&gBrowserStorageList, Link)) {
369 BrowserStorage = BROWSER_STORAGE_FROM_LINK (Link);
370
371 if ((BrowserStorage->Type == StorageType) && CompareGuid (&BrowserStorage->Guid, StorageGuid)) {
372 if (StorageType == EFI_HII_VARSTORE_NAME_VALUE) {
373 return BrowserStorage;
374 }
375
376 if (StrCmp (BrowserStorage->Name, StorageName) == 0) {
377 return BrowserStorage;
378 }
379 }
380
381 //
382 // Get Next Storage.
383 //
384 Link = GetNextNode (&gBrowserStorageList, Link);
385 }
386
387 return NULL;
388}
389
390/**
391 Intialize the Global Storage.
392
393 @param BrowserStorage Pointer to the global storage.
394 @param StorageType Storage type.
395 @param OpCodeData Binary data for this opcode.
396
397**/
398VOID
399IntializeBrowserStorage (
400 IN BROWSER_STORAGE *BrowserStorage,
401 IN UINT8 StorageType,
402 IN UINT8 *OpCodeData
403 )
404{
405 switch (StorageType) {
406 case EFI_HII_VARSTORE_BUFFER:
407 CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
408 CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
409
410 BrowserStorage->Buffer = AllocateZeroPool (BrowserStorage->Size);
411 BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);
412 break;
413
414 case EFI_HII_VARSTORE_EFI_VARIABLE:
415 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
416 CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
417 CopyMem (&BrowserStorage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
418 CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size, sizeof (UINT16));
419
420 if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
421 BrowserStorage->Buffer = AllocateZeroPool (BrowserStorage->Size);
422 BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);
423 }
424 break;
425
426 case EFI_HII_VARSTORE_NAME_VALUE:
427 CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
428
429 InitializeListHead (&BrowserStorage->NameValueListHead);
430 break;
431
432 default:
433 break;
434 }
435}
436
437/**
438 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
439
440 @param FormSet Pointer of the current FormSet
441 @param StorageType Storage type.
442 @param OpCodeData Binary data for this opcode.
443
444 @return Pointer to a FORMSET_STORAGE data structure.
445
446**/
447FORMSET_STORAGE *
448CreateStorage (
449 IN FORM_BROWSER_FORMSET *FormSet,
450 IN UINT8 StorageType,
451 IN UINT8 *OpCodeData
452 )
453{
454 FORMSET_STORAGE *Storage;
455 CHAR16 *UnicodeString;
456 UINT16 Index;
457 BROWSER_STORAGE *BrowserStorage;
458 EFI_GUID *StorageGuid;
459 CHAR8 *StorageName;
460
461 UnicodeString = NULL;
462 StorageName = NULL;
463 switch (StorageType) {
464 case EFI_HII_VARSTORE_BUFFER:
465 StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE *) OpCodeData)->Guid;
466 StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
467 break;
468
469 case EFI_HII_VARSTORE_EFI_VARIABLE:
470 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
471 StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid;
472 StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;
473 break;
474
475 default:
476 ASSERT (StorageType == EFI_HII_VARSTORE_NAME_VALUE);
477 StorageGuid = &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid;
478 break;
479 }
480
481 if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {
482 ASSERT (StorageName != NULL);
483
484 UnicodeString = AllocateZeroPool (AsciiStrSize (StorageName) * 2);
485 ASSERT (UnicodeString != NULL);
486 for (Index = 0; StorageName[Index] != 0; Index++) {
487 UnicodeString[Index] = (CHAR16) StorageName[Index];
488 }
489 }
490
491 Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
492 ASSERT (Storage != NULL);
493 Storage->Signature = FORMSET_STORAGE_SIGNATURE;
494 InsertTailList (&FormSet->StorageListHead, &Storage->Link);
495
496 BrowserStorage = FindStorageInList(StorageType, StorageGuid, UnicodeString);
497 if (BrowserStorage == NULL) {
498 BrowserStorage = AllocateZeroPool (sizeof (BROWSER_STORAGE));
499 ASSERT (BrowserStorage != NULL);
500
501 BrowserStorage->Signature = BROWSER_STORAGE_SIGNATURE;
502 InsertTailList (&gBrowserStorageList, &BrowserStorage->Link);
503
504 IntializeBrowserStorage (BrowserStorage, StorageType, OpCodeData);
505 BrowserStorage->Type = StorageType;
506 if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {
507 BrowserStorage->Name = UnicodeString;
508 }
509
510 InitializeConfigHdr (FormSet, BrowserStorage);
511 }
512 //
513 // Add count because one formset storage use this global storage.
514 //
515 BrowserStorage->ReferenceCount++;
516
517 Storage->BrowserStorage = BrowserStorage;
518 Storage->ConfigRequest = AllocateCopyPool (StrSize (BrowserStorage->ConfigHdr), BrowserStorage->ConfigHdr);
519 Storage->SpareStrLen = 0;
520
521 return Storage;
522}
qhuang8c60a0612008-10-31 04:41:33 +0000523
524/**
525 Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
526
527 @param FormSet Pointer of the current FormSet.
528 @param Question The Question to be initialized.
ydong10b18e7052011-05-31 00:59:15 +0000529 @param Form Pointer of the current form.
qhuang8c60a0612008-10-31 04:41:33 +0000530
531 @retval EFI_SUCCESS Function success.
532 @retval EFI_INVALID_PARAMETER No storage associated with the Question.
533
534**/
535EFI_STATUS
536InitializeRequestElement (
537 IN OUT FORM_BROWSER_FORMSET *FormSet,
ydong10b18e7052011-05-31 00:59:15 +0000538 IN OUT FORM_BROWSER_STATEMENT *Question,
539 IN OUT FORM_BROWSER_FORM *Form
qhuang8c60a0612008-10-31 04:41:33 +0000540 )
541{
ydong1094f3aae2013-04-16 10:53:22 +0000542 BROWSER_STORAGE *Storage;
543 FORMSET_STORAGE *FormsetStorage;
qhuang8c60a0612008-10-31 04:41:33 +0000544 UINTN StrLen;
545 UINTN StringSize;
546 CHAR16 *NewStr;
547 CHAR16 RequestElement[30];
ydong10b18e7052011-05-31 00:59:15 +0000548 LIST_ENTRY *Link;
549 BOOLEAN Find;
550 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
qhuang8c60a0612008-10-31 04:41:33 +0000551
552 Storage = Question->Storage;
553 if (Storage == NULL) {
554 return EFI_INVALID_PARAMETER;
555 }
556
557 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
558 //
559 // <ConfigRequest> is unnecessary for EFI variable storage,
560 // GetVariable()/SetVariable() will be used to retrieve/save values
561 //
562 return EFI_SUCCESS;
563 }
564
565 //
566 // Prepare <RequestElement>
567 //
ydong10cce62302011-07-12 07:24:36 +0000568 if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
569 Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
qhuang8c60a0612008-10-31 04:41:33 +0000570 StrLen = UnicodeSPrint (
571 RequestElement,
572 30 * sizeof (CHAR16),
573 L"&OFFSET=%x&WIDTH=%x",
574 Question->VarStoreInfo.VarOffset,
575 Question->StorageWidth
576 );
577 Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);
578 } else {
579 StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
580 }
581
582 if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
583 //
584 // Password with CALLBACK flag is stored in encoded format,
585 // so don't need to append it to <ConfigRequest>
586 //
587 return EFI_SUCCESS;
588 }
589
590 //
ydong1094f3aae2013-04-16 10:53:22 +0000591 // Find Formset Storage for this Question
592 //
593 FormsetStorage = NULL;
594 Link = GetFirstNode (&FormSet->StorageListHead);
595 while (!IsNull (&FormSet->StorageListHead, Link)) {
596 FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);
597
598 if (FormsetStorage->VarStoreId == Question->VarStoreId) {
599 break;
600 }
601
602 Link = GetNextNode (&FormSet->StorageListHead, Link);
603 }
604 ASSERT (FormsetStorage != NULL);
605
606 //
qhuang8c60a0612008-10-31 04:41:33 +0000607 // Append <RequestElement> to <ConfigRequest>
608 //
ydong1094f3aae2013-04-16 10:53:22 +0000609 if (StrLen > FormsetStorage->SpareStrLen) {
qhuang8c60a0612008-10-31 04:41:33 +0000610 //
611 // Old String buffer is not sufficient for RequestElement, allocate a new one
612 //
ydong1094f3aae2013-04-16 10:53:22 +0000613 StringSize = (FormsetStorage->ConfigRequest != NULL) ? StrSize (FormsetStorage->ConfigRequest) : sizeof (CHAR16);
qhuang8c60a0612008-10-31 04:41:33 +0000614 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
jji41ac628e2009-01-19 07:58:58 +0000615 ASSERT (NewStr != NULL);
ydong1094f3aae2013-04-16 10:53:22 +0000616 if (FormsetStorage->ConfigRequest != NULL) {
617 CopyMem (NewStr, FormsetStorage->ConfigRequest, StringSize);
618 FreePool (FormsetStorage->ConfigRequest);
qhuang8c60a0612008-10-31 04:41:33 +0000619 }
ydong1094f3aae2013-04-16 10:53:22 +0000620 FormsetStorage->ConfigRequest = NewStr;
621 FormsetStorage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
qhuang8c60a0612008-10-31 04:41:33 +0000622 }
623
ydong1094f3aae2013-04-16 10:53:22 +0000624 StrCat (FormsetStorage->ConfigRequest, RequestElement);
625 FormsetStorage->ElementCount++;
626 FormsetStorage->SpareStrLen -= StrLen;
qhuang8c60a0612008-10-31 04:41:33 +0000627
ydong10b18e7052011-05-31 00:59:15 +0000628 //
629 // Update the Config Request info saved in the form.
630 //
631 ConfigInfo = NULL;
632 Find = FALSE;
633 Link = GetFirstNode (&Form->ConfigRequestHead);
634 while (!IsNull (&Form->ConfigRequestHead, Link)) {
635 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
636
ydong1094f3aae2013-04-16 10:53:22 +0000637 if (ConfigInfo != NULL && ConfigInfo->Storage == Storage) {
ydong10b18e7052011-05-31 00:59:15 +0000638 Find = TRUE;
639 break;
640 }
641
642 Link = GetNextNode (&Form->ConfigRequestHead, Link);
643 }
644
645 if (!Find) {
646 ConfigInfo = AllocateZeroPool(sizeof (FORM_BROWSER_CONFIG_REQUEST));
ydong100194d262011-06-13 05:20:23 +0000647 ASSERT (ConfigInfo != NULL);
ydong10b18e7052011-05-31 00:59:15 +0000648 ConfigInfo->Signature = FORM_BROWSER_CONFIG_REQUEST_SIGNATURE;
649 ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);
650 ConfigInfo->SpareStrLen = 0;
651 ConfigInfo->Storage = Storage;
652 InsertTailList(&Form->ConfigRequestHead, &ConfigInfo->Link);
653 }
654
655 //
656 // Append <RequestElement> to <ConfigRequest>
657 //
658 if (StrLen > ConfigInfo->SpareStrLen) {
659 //
660 // Old String buffer is not sufficient for RequestElement, allocate a new one
661 //
662 StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16);
663 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
664 ASSERT (NewStr != NULL);
665 if (ConfigInfo->ConfigRequest != NULL) {
666 CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);
667 FreePool (ConfigInfo->ConfigRequest);
668 }
669 ConfigInfo->ConfigRequest = NewStr;
670 ConfigInfo->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
671 }
672
673 StrCat (ConfigInfo->ConfigRequest, RequestElement);
674 ConfigInfo->ElementCount++;
675 ConfigInfo->SpareStrLen -= StrLen;
qhuang8c60a0612008-10-31 04:41:33 +0000676 return EFI_SUCCESS;
677}
678
679
680/**
681 Free resources of a Expression.
682
683 @param FormSet Pointer of the Expression
684
685**/
686VOID
687DestroyExpression (
688 IN FORM_EXPRESSION *Expression
689 )
690{
691 LIST_ENTRY *Link;
692 EXPRESSION_OPCODE *OpCode;
lgao425737122010-02-25 10:10:59 +0000693 LIST_ENTRY *SubExpressionLink;
694 FORM_EXPRESSION *SubExpression;
qhuang8c60a0612008-10-31 04:41:33 +0000695
696 while (!IsListEmpty (&Expression->OpCodeListHead)) {
697 Link = GetFirstNode (&Expression->OpCodeListHead);
698 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
699 RemoveEntryList (&OpCode->Link);
700
701 if (OpCode->ValueList != NULL) {
702 FreePool (OpCode->ValueList);
703 }
lgao425737122010-02-25 10:10:59 +0000704
705 if (OpCode->ValueName != NULL) {
706 FreePool (OpCode->ValueName);
707 }
708
709 if (OpCode->MapExpressionList.ForwardLink != NULL) {
710 while (!IsListEmpty (&OpCode->MapExpressionList)) {
711 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
712 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
713 RemoveEntryList(&SubExpression->Link);
714 DestroyExpression (SubExpression);
715 }
716 }
qhuang8c60a0612008-10-31 04:41:33 +0000717 }
718
719 //
720 // Free this Expression
721 //
qwang12f4113e12008-11-21 06:59:58 +0000722 FreePool (Expression);
qhuang8c60a0612008-10-31 04:41:33 +0000723}
724
qhuang8c60a0612008-10-31 04:41:33 +0000725/**
726 Free resources of a storage.
727
728 @param Storage Pointer of the storage
729
730**/
731VOID
732DestroyStorage (
733 IN FORMSET_STORAGE *Storage
734 )
735{
qhuang8c60a0612008-10-31 04:41:33 +0000736 if (Storage == NULL) {
737 return;
738 }
739
qhuang8c60a0612008-10-31 04:41:33 +0000740 if (Storage->ConfigRequest != NULL) {
741 FreePool (Storage->ConfigRequest);
742 }
743
ydong1094f3aae2013-04-16 10:53:22 +0000744 //
745 // Minus the reference to the global storage.
746 //
747 ASSERT (Storage->BrowserStorage->ReferenceCount > 0);
748 Storage->BrowserStorage->ReferenceCount--;
749
qhuang8c60a0612008-10-31 04:41:33 +0000750 FreePool (Storage);
751}
752
753
754/**
755 Free resources of a Statement.
756
ydong10e2100bf2010-12-23 06:47:50 +0000757 @param FormSet Pointer of the FormSet
qhuang8c60a0612008-10-31 04:41:33 +0000758 @param Statement Pointer of the Statement
759
760**/
761VOID
762DestroyStatement (
ydong10e2100bf2010-12-23 06:47:50 +0000763 IN FORM_BROWSER_FORMSET *FormSet,
qhuang8c60a0612008-10-31 04:41:33 +0000764 IN OUT FORM_BROWSER_STATEMENT *Statement
765 )
766{
767 LIST_ENTRY *Link;
768 QUESTION_DEFAULT *Default;
769 QUESTION_OPTION *Option;
770 FORM_EXPRESSION *Expression;
771
772 //
773 // Free Default value List
774 //
775 while (!IsListEmpty (&Statement->DefaultListHead)) {
776 Link = GetFirstNode (&Statement->DefaultListHead);
777 Default = QUESTION_DEFAULT_FROM_LINK (Link);
778 RemoveEntryList (&Default->Link);
779
qwang12f4113e12008-11-21 06:59:58 +0000780 FreePool (Default);
qhuang8c60a0612008-10-31 04:41:33 +0000781 }
782
783 //
784 // Free Options List
785 //
786 while (!IsListEmpty (&Statement->OptionListHead)) {
787 Link = GetFirstNode (&Statement->OptionListHead);
788 Option = QUESTION_OPTION_FROM_LINK (Link);
ydong1031585af2012-01-31 07:17:42 +0000789 if (Option->SuppressExpression != NULL) {
790 FreePool (Option->SuppressExpression);
791 }
qhuang8c60a0612008-10-31 04:41:33 +0000792 RemoveEntryList (&Option->Link);
793
qwang12f4113e12008-11-21 06:59:58 +0000794 FreePool (Option);
qhuang8c60a0612008-10-31 04:41:33 +0000795 }
796
797 //
798 // Free Inconsistent List
799 //
800 while (!IsListEmpty (&Statement->InconsistentListHead)) {
801 Link = GetFirstNode (&Statement->InconsistentListHead);
802 Expression = FORM_EXPRESSION_FROM_LINK (Link);
803 RemoveEntryList (&Expression->Link);
804
805 DestroyExpression (Expression);
806 }
807
808 //
809 // Free NoSubmit List
810 //
811 while (!IsListEmpty (&Statement->NoSubmitListHead)) {
812 Link = GetFirstNode (&Statement->NoSubmitListHead);
813 Expression = FORM_EXPRESSION_FROM_LINK (Link);
814 RemoveEntryList (&Expression->Link);
815
816 DestroyExpression (Expression);
817 }
818
ydong1031585af2012-01-31 07:17:42 +0000819 if (Statement->Expression != NULL) {
820 FreePool (Statement->Expression);
821 }
822
qhuang8c60a0612008-10-31 04:41:33 +0000823 if (Statement->VariableName != NULL) {
824 FreePool (Statement->VariableName);
825 }
826 if (Statement->BlockName != NULL) {
827 FreePool (Statement->BlockName);
828 }
lgao4b86b4132010-02-22 06:30:41 +0000829 if (Statement->BufferValue != NULL) {
830 FreePool (Statement->BufferValue);
831 }
ydong10e2100bf2010-12-23 06:47:50 +0000832 if (Statement->Operand == EFI_IFR_STRING_OP || Statement->Operand == EFI_IFR_PASSWORD_OP) {
833 DeleteString(Statement->HiiValue.Value.string, FormSet->HiiHandle);
834 }
qhuang8c60a0612008-10-31 04:41:33 +0000835}
836
837
838/**
839 Free resources of a Form.
840
ydong10e2100bf2010-12-23 06:47:50 +0000841 @param FormSet Pointer of the FormSet
qhuang8c60a0612008-10-31 04:41:33 +0000842 @param Form Pointer of the Form.
843
844**/
845VOID
846DestroyForm (
ydong10e2100bf2010-12-23 06:47:50 +0000847 IN FORM_BROWSER_FORMSET *FormSet,
848 IN OUT FORM_BROWSER_FORM *Form
qhuang8c60a0612008-10-31 04:41:33 +0000849 )
850{
851 LIST_ENTRY *Link;
852 FORM_EXPRESSION *Expression;
853 FORM_BROWSER_STATEMENT *Statement;
ydong10b18e7052011-05-31 00:59:15 +0000854 FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
qhuang8c60a0612008-10-31 04:41:33 +0000855
856 //
857 // Free Form Expressions
858 //
859 while (!IsListEmpty (&Form->ExpressionListHead)) {
860 Link = GetFirstNode (&Form->ExpressionListHead);
861 Expression = FORM_EXPRESSION_FROM_LINK (Link);
862 RemoveEntryList (&Expression->Link);
863
864 DestroyExpression (Expression);
865 }
866
867 //
868 // Free Statements/Questions
869 //
870 while (!IsListEmpty (&Form->StatementListHead)) {
871 Link = GetFirstNode (&Form->StatementListHead);
872 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
873 RemoveEntryList (&Statement->Link);
874
ydong10e2100bf2010-12-23 06:47:50 +0000875 DestroyStatement (FormSet, Statement);
qhuang8c60a0612008-10-31 04:41:33 +0000876 }
877
878 //
ydong10b18e7052011-05-31 00:59:15 +0000879 // Free ConfigRequest string.
880 //
881 while (!IsListEmpty (&Form->ConfigRequestHead)) {
882 Link = GetFirstNode (&Form->ConfigRequestHead);
883 ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
884 RemoveEntryList (&ConfigInfo->Link);
885
886 FreePool (ConfigInfo->ConfigRequest);
887 FreePool (ConfigInfo);
888 }
889
ydong1031585af2012-01-31 07:17:42 +0000890 if (Form->SuppressExpression != NULL) {
891 FreePool (Form->SuppressExpression);
892 }
893
ydong10b18e7052011-05-31 00:59:15 +0000894 //
qhuang8c60a0612008-10-31 04:41:33 +0000895 // Free this Form
896 //
qwang12f4113e12008-11-21 06:59:58 +0000897 FreePool (Form);
qhuang8c60a0612008-10-31 04:41:33 +0000898}
899
900
901/**
902 Free resources allocated for a FormSet.
903
904 @param FormSet Pointer of the FormSet
905
906**/
907VOID
908DestroyFormSet (
909 IN OUT FORM_BROWSER_FORMSET *FormSet
910 )
911{
912 LIST_ENTRY *Link;
913 FORMSET_STORAGE *Storage;
914 FORMSET_DEFAULTSTORE *DefaultStore;
lgao40c66bc72009-11-12 01:16:12 +0000915 FORM_EXPRESSION *Expression;
qhuang8c60a0612008-10-31 04:41:33 +0000916 FORM_BROWSER_FORM *Form;
917
xdu24c8358c2009-11-13 05:40:21 +0000918 if (FormSet->IfrBinaryData == NULL) {
919 //
920 // Uninitialized FormSet
921 //
922 FreePool (FormSet);
923 return;
924 }
925
qhuang8c60a0612008-10-31 04:41:33 +0000926 //
927 // Free IFR binary buffer
928 //
929 FreePool (FormSet->IfrBinaryData);
930
931 //
932 // Free FormSet Storage
933 //
934 if (FormSet->StorageListHead.ForwardLink != NULL) {
935 while (!IsListEmpty (&FormSet->StorageListHead)) {
936 Link = GetFirstNode (&FormSet->StorageListHead);
937 Storage = FORMSET_STORAGE_FROM_LINK (Link);
938 RemoveEntryList (&Storage->Link);
939
940 DestroyStorage (Storage);
941 }
942 }
943
944 //
945 // Free FormSet Default Store
946 //
947 if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
948 while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
949 Link = GetFirstNode (&FormSet->DefaultStoreListHead);
950 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
951 RemoveEntryList (&DefaultStore->Link);
952
qwang12f4113e12008-11-21 06:59:58 +0000953 FreePool (DefaultStore);
qhuang8c60a0612008-10-31 04:41:33 +0000954 }
955 }
956
957 //
lgao40c66bc72009-11-12 01:16:12 +0000958 // Free Formset Expressions
959 //
960 while (!IsListEmpty (&FormSet->ExpressionListHead)) {
961 Link = GetFirstNode (&FormSet->ExpressionListHead);
962 Expression = FORM_EXPRESSION_FROM_LINK (Link);
963 RemoveEntryList (&Expression->Link);
964
965 DestroyExpression (Expression);
966 }
967
968 //
qhuang8c60a0612008-10-31 04:41:33 +0000969 // Free Forms
970 //
971 if (FormSet->FormListHead.ForwardLink != NULL) {
972 while (!IsListEmpty (&FormSet->FormListHead)) {
973 Link = GetFirstNode (&FormSet->FormListHead);
974 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
975 RemoveEntryList (&Form->Link);
976
ydong10e2100bf2010-12-23 06:47:50 +0000977 DestroyForm (FormSet, Form);
qhuang8c60a0612008-10-31 04:41:33 +0000978 }
979 }
980
981 if (FormSet->StatementBuffer != NULL) {
982 FreePool (FormSet->StatementBuffer);
983 }
984 if (FormSet->ExpressionBuffer != NULL) {
985 FreePool (FormSet->ExpressionBuffer);
986 }
987
988 FreePool (FormSet);
989}
990
991
992/**
993 Tell whether this Operand is an Expression OpCode or not
994
995 @param Operand Operand of an IFR OpCode.
996
997 @retval TRUE This is an Expression OpCode.
998 @retval FALSE Not an Expression OpCode.
999
1000**/
1001BOOLEAN
1002IsExpressionOpCode (
1003 IN UINT8 Operand
1004 )
1005{
1006 if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
lgao425737122010-02-25 10:10:59 +00001007 ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) ||
1008 ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
qhuang8c60a0612008-10-31 04:41:33 +00001009 (Operand == EFI_IFR_CATENATE_OP) ||
1010 (Operand == EFI_IFR_TO_LOWER_OP) ||
1011 (Operand == EFI_IFR_TO_UPPER_OP) ||
lgao425737122010-02-25 10:10:59 +00001012 (Operand == EFI_IFR_MAP_OP) ||
rsun3cbf73e52009-11-26 09:26:42 +00001013 (Operand == EFI_IFR_VERSION_OP) ||
1014 (Operand == EFI_IFR_SECURITY_OP)) {
qhuang8c60a0612008-10-31 04:41:33 +00001015 return TRUE;
1016 } else {
1017 return FALSE;
1018 }
1019}
1020
1021
1022/**
1023 Calculate number of Statemens(Questions) and Expression OpCodes.
1024
1025 @param FormSet The FormSet to be counted.
1026 @param NumberOfStatement Number of Statemens(Questions)
1027 @param NumberOfExpression Number of Expression OpCodes
1028
1029**/
1030VOID
1031CountOpCodes (
1032 IN FORM_BROWSER_FORMSET *FormSet,
1033 IN OUT UINT16 *NumberOfStatement,
1034 IN OUT UINT16 *NumberOfExpression
1035 )
1036{
1037 UINT16 StatementCount;
1038 UINT16 ExpressionCount;
1039 UINT8 *OpCodeData;
1040 UINTN Offset;
1041 UINTN OpCodeLen;
1042
1043 Offset = 0;
1044 StatementCount = 0;
1045 ExpressionCount = 0;
1046
1047 while (Offset < FormSet->IfrBinaryLength) {
1048 OpCodeData = FormSet->IfrBinaryData + Offset;
1049 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1050 Offset += OpCodeLen;
1051
1052 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
1053 ExpressionCount++;
1054 } else {
1055 StatementCount++;
1056 }
1057 }
1058
1059 *NumberOfStatement = StatementCount;
1060 *NumberOfExpression = ExpressionCount;
1061}
1062
1063
1064
1065/**
1066 Parse opcodes in the formset IFR binary.
1067
1068 @param FormSet Pointer of the FormSet data structure.
1069
1070 @retval EFI_SUCCESS Opcode parse success.
1071 @retval Other Opcode parse fail.
1072
1073**/
1074EFI_STATUS
1075ParseOpCodes (
1076 IN FORM_BROWSER_FORMSET *FormSet
1077 )
1078{
1079 EFI_STATUS Status;
qhuang8c60a0612008-10-31 04:41:33 +00001080 FORM_BROWSER_FORM *CurrentForm;
1081 FORM_BROWSER_STATEMENT *CurrentStatement;
1082 EXPRESSION_OPCODE *ExpressionOpCode;
1083 FORM_EXPRESSION *CurrentExpression;
1084 UINT8 Operand;
1085 UINT8 Scope;
1086 UINTN OpCodeOffset;
1087 UINTN OpCodeLength;
1088 UINT8 *OpCodeData;
1089 UINT8 ScopeOpCode;
1090 FORMSET_STORAGE *Storage;
1091 FORMSET_DEFAULTSTORE *DefaultStore;
1092 QUESTION_DEFAULT *CurrentDefault;
1093 QUESTION_OPTION *CurrentOption;
xdu2d02847d2009-10-26 03:03:47 +00001094 UINT8 Width;
qhuang8c60a0612008-10-31 04:41:33 +00001095 UINT16 NumberOfStatement;
1096 UINT16 NumberOfExpression;
1097 EFI_IMAGE_ID *ImageId;
lgao40c66bc72009-11-12 01:16:12 +00001098 BOOLEAN SuppressForQuestion;
qhuang8c60a0612008-10-31 04:41:33 +00001099 BOOLEAN SuppressForOption;
qhuang8c60a0612008-10-31 04:41:33 +00001100 UINT16 DepthOfDisable;
1101 BOOLEAN OpCodeDisabled;
1102 BOOLEAN SingleOpCodeExpression;
1103 BOOLEAN InScopeDefault;
1104 EFI_HII_VALUE *Value;
lgao425737122010-02-25 10:10:59 +00001105 EFI_IFR_FORM_MAP_METHOD *MapMethod;
1106 UINT8 MapScopeDepth;
1107 LIST_ENTRY *Link;
1108 FORMSET_STORAGE *VarStorage;
1109 LIST_ENTRY *MapExpressionList;
1110 EFI_VARSTORE_ID TempVarstoreId;
ydong1031585af2012-01-31 07:17:42 +00001111 BOOLEAN InScopeDisable;
1112 INTN ConditionalExprCount;
qhuang8c60a0612008-10-31 04:41:33 +00001113
1114 mInScopeSubtitle = FALSE;
lgao40c66bc72009-11-12 01:16:12 +00001115 SuppressForQuestion = FALSE;
qhuang8c60a0612008-10-31 04:41:33 +00001116 SuppressForOption = FALSE;
ydong1031585af2012-01-31 07:17:42 +00001117 InScopeDisable = FALSE;
qhuang8c60a0612008-10-31 04:41:33 +00001118 DepthOfDisable = 0;
1119 OpCodeDisabled = FALSE;
1120 SingleOpCodeExpression = FALSE;
1121 InScopeDefault = FALSE;
1122 CurrentExpression = NULL;
1123 CurrentDefault = NULL;
1124 CurrentOption = NULL;
qwang12c4105892009-02-06 06:34:43 +00001125 ImageId = NULL;
lgao425737122010-02-25 10:10:59 +00001126 MapMethod = NULL;
1127 MapScopeDepth = 0;
1128 Link = NULL;
1129 VarStorage = NULL;
1130 MapExpressionList = NULL;
1131 TempVarstoreId = 0;
ydong1031585af2012-01-31 07:17:42 +00001132 ConditionalExprCount = 0;
qhuang8c60a0612008-10-31 04:41:33 +00001133
1134 //
1135 // Get the number of Statements and Expressions
1136 //
1137 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
1138
1139 mStatementIndex = 0;
Eric Dong7c6c0642013-08-12 02:19:56 +00001140 mUsedQuestionId = 1;
qhuang8c60a0612008-10-31 04:41:33 +00001141 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
1142 if (FormSet->StatementBuffer == NULL) {
1143 return EFI_OUT_OF_RESOURCES;
1144 }
1145
1146 mExpressionOpCodeIndex = 0;
1147 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
1148 if (FormSet->ExpressionBuffer == NULL) {
1149 return EFI_OUT_OF_RESOURCES;
1150 }
1151
Eric Dong7c6c0642013-08-12 02:19:56 +00001152 InitializeListHead (&FormSet->StatementListOSF);
qhuang8c60a0612008-10-31 04:41:33 +00001153 InitializeListHead (&FormSet->StorageListHead);
1154 InitializeListHead (&FormSet->DefaultStoreListHead);
1155 InitializeListHead (&FormSet->FormListHead);
lgao448a9d5f2011-09-13 09:32:54 +00001156 InitializeListHead (&FormSet->ExpressionListHead);
lgao425737122010-02-25 10:10:59 +00001157 ResetCurrentExpressionStack ();
1158 ResetMapExpressionListStack ();
qhuang8c60a0612008-10-31 04:41:33 +00001159
1160 CurrentForm = NULL;
1161 CurrentStatement = NULL;
1162
1163 ResetScopeStack ();
1164
1165 OpCodeOffset = 0;
1166 while (OpCodeOffset < FormSet->IfrBinaryLength) {
1167 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
1168
1169 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1170 OpCodeOffset += OpCodeLength;
1171 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
1172 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
1173
1174 //
1175 // If scope bit set, push onto scope stack
1176 //
1177 if (Scope != 0) {
1178 PushScope (Operand);
1179 }
1180
1181 if (OpCodeDisabled) {
1182 //
1183 // DisableIf Expression is evaluated to be TRUE, try to find its end.
1184 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
1185 //
1186 if (Operand == EFI_IFR_DISABLE_IF_OP) {
1187 DepthOfDisable++;
1188 } else if (Operand == EFI_IFR_END_OP) {
1189 Status = PopScope (&ScopeOpCode);
1190 if (EFI_ERROR (Status)) {
1191 return Status;
1192 }
1193
1194 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
1195 if (DepthOfDisable == 0) {
ydong1031585af2012-01-31 07:17:42 +00001196 InScopeDisable = FALSE;
qhuang8c60a0612008-10-31 04:41:33 +00001197 OpCodeDisabled = FALSE;
1198 } else {
1199 DepthOfDisable--;
1200 }
1201 }
1202 }
1203 continue;
1204 }
1205
1206 if (IsExpressionOpCode (Operand)) {
1207 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
1208 mExpressionOpCodeIndex++;
1209
1210 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
1211 ExpressionOpCode->Operand = Operand;
1212 Value = &ExpressionOpCode->Value;
1213
1214 switch (Operand) {
1215 case EFI_IFR_EQ_ID_VAL_OP:
1216 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1217
1218 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1219 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
1220 break;
1221
1222 case EFI_IFR_EQ_ID_ID_OP:
1223 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
1224 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
1225 break;
1226
ydong10e8ef4282012-01-12 13:03:56 +00001227 case EFI_IFR_EQ_ID_VAL_LIST_OP:
qhuang82654f642009-09-21 14:15:35 +00001228 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1229 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
1230 ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
qhuang8c60a0612008-10-31 04:41:33 +00001231 break;
1232
1233 case EFI_IFR_TO_STRING_OP:
1234 case EFI_IFR_FIND_OP:
1235 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
1236 break;
1237
1238 case EFI_IFR_STRING_REF1_OP:
1239 Value->Type = EFI_IFR_TYPE_STRING;
1240 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
1241 break;
1242
1243 case EFI_IFR_RULE_REF_OP:
1244 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
1245 break;
1246
1247 case EFI_IFR_SPAN_OP:
1248 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
1249 break;
1250
1251 case EFI_IFR_THIS_OP:
qwang12d0720b52009-01-20 01:55:11 +00001252 ASSERT (CurrentStatement != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001253 ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
1254 break;
1255
rsun3cbf73e52009-11-26 09:26:42 +00001256 case EFI_IFR_SECURITY_OP:
1257 CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
1258 break;
1259
lgao425737122010-02-25 10:10:59 +00001260 case EFI_IFR_GET_OP:
1261 case EFI_IFR_SET_OP:
1262 CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
1263 if (TempVarstoreId != 0) {
1264 if (FormSet->StorageListHead.ForwardLink != NULL) {
1265 Link = GetFirstNode (&FormSet->StorageListHead);
1266 while (!IsNull (&FormSet->StorageListHead, Link)) {
1267 VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
1268 if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
ydong1094f3aae2013-04-16 10:53:22 +00001269 ExpressionOpCode->VarStorage = VarStorage->BrowserStorage;
lgao425737122010-02-25 10:10:59 +00001270 break;
1271 }
1272 Link = GetNextNode (&FormSet->StorageListHead, Link);
1273 }
1274 }
1275 if (ExpressionOpCode->VarStorage == NULL) {
1276 //
1277 // VarStorage is not found.
1278 //
1279 return EFI_INVALID_PARAMETER;
1280 }
1281 }
1282 ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;
1283 switch (ExpressionOpCode->ValueType) {
1284 case EFI_IFR_TYPE_BOOLEAN:
1285 case EFI_IFR_TYPE_NUM_SIZE_8:
1286 ExpressionOpCode->ValueWidth = 1;
1287 break;
1288
1289 case EFI_IFR_TYPE_NUM_SIZE_16:
1290 case EFI_IFR_TYPE_STRING:
1291 ExpressionOpCode->ValueWidth = 2;
1292 break;
1293
1294 case EFI_IFR_TYPE_NUM_SIZE_32:
1295 ExpressionOpCode->ValueWidth = 4;
1296 break;
1297
1298 case EFI_IFR_TYPE_NUM_SIZE_64:
1299 ExpressionOpCode->ValueWidth = 8;
1300 break;
1301
1302 case EFI_IFR_TYPE_DATE:
ydong10c9325702010-09-15 07:48:11 +00001303 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_DATE);
lgao425737122010-02-25 10:10:59 +00001304 break;
1305
1306 case EFI_IFR_TYPE_TIME:
ydong10c9325702010-09-15 07:48:11 +00001307 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_TIME);
lgao425737122010-02-25 10:10:59 +00001308 break;
1309
ydong108ca61802011-06-28 06:41:28 +00001310 case EFI_IFR_TYPE_REF:
1311 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);
1312 break;
1313
lgao425737122010-02-25 10:10:59 +00001314 case EFI_IFR_TYPE_OTHER:
1315 case EFI_IFR_TYPE_UNDEFINED:
1316 case EFI_IFR_TYPE_ACTION:
1317 case EFI_IFR_TYPE_BUFFER:
1318 default:
1319 //
1320 // Invalid value type for Get/Set opcode.
1321 //
1322 return EFI_INVALID_PARAMETER;
1323 }
1324 CopyMem (&ExpressionOpCode->VarStoreInfo.VarName, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName, sizeof (EFI_STRING_ID));
1325 CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));
1326 if ((ExpressionOpCode->VarStorage != NULL) &&
1327 (ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE ||
1328 ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
1329 ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle);
1330 if (ExpressionOpCode->ValueName == NULL) {
1331 //
1332 // String ID is invalid.
1333 //
1334 return EFI_INVALID_PARAMETER;
1335 }
1336 }
1337 break;
1338
qhuang8c60a0612008-10-31 04:41:33 +00001339 case EFI_IFR_QUESTION_REF1_OP:
qhuang82654f642009-09-21 14:15:35 +00001340 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
qhuang8c60a0612008-10-31 04:41:33 +00001341 break;
1342
1343 case EFI_IFR_QUESTION_REF3_OP:
1344 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
1345 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1346
1347 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
1348 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
1349 }
1350 }
1351 break;
1352
1353 //
1354 // constant
1355 //
1356 case EFI_IFR_TRUE_OP:
1357 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1358 Value->Value.b = TRUE;
1359 break;
1360
1361 case EFI_IFR_FALSE_OP:
1362 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1363 Value->Value.b = FALSE;
1364 break;
1365
1366 case EFI_IFR_ONE_OP:
1367 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1368 Value->Value.u8 = 1;
1369 break;
1370
1371 case EFI_IFR_ZERO_OP:
1372 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1373 Value->Value.u8 = 0;
1374 break;
1375
1376 case EFI_IFR_ONES_OP:
1377 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1378 Value->Value.u64 = 0xffffffffffffffffULL;
1379 break;
1380
1381 case EFI_IFR_UINT8_OP:
1382 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1383 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
1384 break;
1385
1386 case EFI_IFR_UINT16_OP:
1387 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1388 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
1389 break;
1390
1391 case EFI_IFR_UINT32_OP:
1392 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1393 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
1394 break;
1395
1396 case EFI_IFR_UINT64_OP:
1397 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1398 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
1399 break;
1400
1401 case EFI_IFR_UNDEFINED_OP:
xdu2d02847d2009-10-26 03:03:47 +00001402 Value->Type = EFI_IFR_TYPE_UNDEFINED;
qhuang8c60a0612008-10-31 04:41:33 +00001403 break;
1404
1405 case EFI_IFR_VERSION_OP:
1406 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1407 Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
1408 break;
1409
1410 default:
1411 break;
1412 }
lgao425737122010-02-25 10:10:59 +00001413 //
1414 // Create sub expression nested in MAP opcode
1415 //
1416 if (CurrentExpression == NULL && MapScopeDepth > 0) {
1417 CurrentExpression = CreateExpression (CurrentForm);
lgao4771ecec2010-02-27 09:04:11 +00001418 ASSERT (MapExpressionList != NULL);
lgao425737122010-02-25 10:10:59 +00001419 InsertTailList (MapExpressionList, &CurrentExpression->Link);
1420 if (Scope == 0) {
1421 SingleOpCodeExpression = TRUE;
1422 }
1423 }
xdu2f8a1c222009-10-20 03:01:10 +00001424 ASSERT (CurrentExpression != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001425 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
lgao425737122010-02-25 10:10:59 +00001426 if (Operand == EFI_IFR_MAP_OP) {
1427 //
1428 // Store current Map Expression List.
1429 //
1430 if (MapExpressionList != NULL) {
1431 PushMapExpressionList (MapExpressionList);
1432 }
1433 //
1434 // Initialize new Map Expression List.
1435 //
1436 MapExpressionList = &ExpressionOpCode->MapExpressionList;
1437 InitializeListHead (MapExpressionList);
1438 //
1439 // Store current expression.
1440 //
1441 PushCurrentExpression (CurrentExpression);
1442 CurrentExpression = NULL;
1443 MapScopeDepth ++;
1444 } else if (SingleOpCodeExpression) {
qhuang8c60a0612008-10-31 04:41:33 +00001445 //
1446 // There are two cases to indicate the end of an Expression:
1447 // for single OpCode expression: one Expression OpCode
1448 // for expression consists of more than one OpCode: EFI_IFR_END
1449 //
1450 SingleOpCodeExpression = FALSE;
1451
ydong1031585af2012-01-31 07:17:42 +00001452 if (InScopeDisable && CurrentForm == NULL) {
qhuang8c60a0612008-10-31 04:41:33 +00001453 //
lgao40a1147e2009-04-22 03:18:37 +00001454 // This is DisableIf expression for Form, it should be a constant expression
qhuang8c60a0612008-10-31 04:41:33 +00001455 //
1456 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1457 if (EFI_ERROR (Status)) {
1458 return Status;
1459 }
qwang12c4105892009-02-06 06:34:43 +00001460
qhuang8c60a0612008-10-31 04:41:33 +00001461 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1462 return EFI_INVALID_PARAMETER;
1463 }
1464
1465 OpCodeDisabled = CurrentExpression->Result.Value.b;
1466 }
1467
1468 CurrentExpression = NULL;
1469 }
1470
1471 continue;
1472 }
1473
1474 //
1475 // Parse the Opcode
1476 //
1477 switch (Operand) {
1478
1479 case EFI_IFR_FORM_SET_OP:
1480 //
xdu2f8a1c222009-10-20 03:01:10 +00001481 // Check the formset GUID
qhuang8c60a0612008-10-31 04:41:33 +00001482 //
1483 if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1484 return EFI_INVALID_PARAMETER;
1485 }
1486
1487 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1488 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
lgao40a1147e2009-04-22 03:18:37 +00001489
lgao4d2285262010-02-02 01:38:00 +00001490 if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
1491 //
1492 // The formset OpCode contains ClassGuid
1493 //
1494 FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
1495 CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
1496 }
qhuang8c60a0612008-10-31 04:41:33 +00001497 break;
1498
1499 case EFI_IFR_FORM_OP:
1500 //
1501 // Create a new Form for this FormSet
1502 //
1503 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
jji41ac628e2009-01-19 07:58:58 +00001504 ASSERT (CurrentForm != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001505 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1506 InitializeListHead (&CurrentForm->ExpressionListHead);
1507 InitializeListHead (&CurrentForm->StatementListHead);
ydong10b18e7052011-05-31 00:59:15 +00001508 InitializeListHead (&CurrentForm->ConfigRequestHead);
qhuang8c60a0612008-10-31 04:41:33 +00001509
lgao425737122010-02-25 10:10:59 +00001510 CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
qhuang8c60a0612008-10-31 04:41:33 +00001511 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1512 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1513
ydong1031585af2012-01-31 07:17:42 +00001514 ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1515 if ( ConditionalExprCount > 0) {
lgao40c66bc72009-11-12 01:16:12 +00001516 //
1517 // Form is inside of suppressif
1518 //
ydong1031585af2012-01-31 07:17:42 +00001519 CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1520 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1521 ASSERT (CurrentForm->SuppressExpression != NULL);
1522 CurrentForm->SuppressExpression->Count = (UINTN) ConditionalExprCount;
1523 CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1524 CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
lgao40c66bc72009-11-12 01:16:12 +00001525 }
1526
1527 if (Scope != 0) {
1528 //
1529 // Enter scope of a Form, suppressif will be used for Question or Option
1530 //
1531 SuppressForQuestion = TRUE;
1532 }
1533
qhuang8c60a0612008-10-31 04:41:33 +00001534 //
1535 // Insert into Form list of this FormSet
1536 //
1537 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1538 break;
1539
lgao425737122010-02-25 10:10:59 +00001540 case EFI_IFR_FORM_MAP_OP:
1541 //
1542 // Create a new Form for this FormSet
1543 //
1544 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1545 ASSERT (CurrentForm != NULL);
1546 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1547 InitializeListHead (&CurrentForm->ExpressionListHead);
1548 InitializeListHead (&CurrentForm->StatementListHead);
ydong10b18e7052011-05-31 00:59:15 +00001549 InitializeListHead (&CurrentForm->ConfigRequestHead);
lgao425737122010-02-25 10:10:59 +00001550 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1551
1552 MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1553 //
1554 // FormMap Form must contain at least one Map Method.
1555 //
1556 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) {
1557 return EFI_INVALID_PARAMETER;
1558 }
1559 //
1560 // Try to find the standard form map method.
1561 //
1562 while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) {
1563 if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {
1564 CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1565 CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
1566 break;
1567 }
1568 MapMethod ++;
1569 }
1570 //
1571 // If the standard form map method is not found, the first map method title will be used.
1572 //
1573 if (CurrentForm->FormTitle == 0) {
1574 MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
1575 CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
1576 }
1577
ydong1031585af2012-01-31 07:17:42 +00001578 ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);
1579 if ( ConditionalExprCount > 0) {
lgao425737122010-02-25 10:10:59 +00001580 //
1581 // Form is inside of suppressif
1582 //
ydong1031585af2012-01-31 07:17:42 +00001583 CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1584 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1585 ASSERT (CurrentForm->SuppressExpression != NULL);
1586 CurrentForm->SuppressExpression->Count = (UINTN) ConditionalExprCount;
1587 CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1588 CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
lgao425737122010-02-25 10:10:59 +00001589 }
1590
1591 if (Scope != 0) {
1592 //
1593 // Enter scope of a Form, suppressif will be used for Question or Option
1594 //
1595 SuppressForQuestion = TRUE;
1596 }
1597
1598 //
1599 // Insert into Form list of this FormSet
1600 //
1601 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1602 break;
1603
qhuang8c60a0612008-10-31 04:41:33 +00001604 //
1605 // Storage
1606 //
1607 case EFI_IFR_VARSTORE_OP:
1608 //
1609 // Create a buffer Storage for this FormSet
1610 //
ydong1094f3aae2013-04-16 10:53:22 +00001611 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);
qhuang8c60a0612008-10-31 04:41:33 +00001612 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
qhuang8c60a0612008-10-31 04:41:33 +00001613 break;
1614
1615 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1616 //
1617 // Create a name/value Storage for this FormSet
1618 //
ydong1094f3aae2013-04-16 10:53:22 +00001619 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);
qhuang8c60a0612008-10-31 04:41:33 +00001620 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
qhuang8c60a0612008-10-31 04:41:33 +00001621 break;
1622
1623 case EFI_IFR_VARSTORE_EFI_OP:
1624 //
1625 // Create a EFI variable Storage for this FormSet
1626 //
ydong10cce62302011-07-12 07:24:36 +00001627 if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
Eric Dongc0462ea2013-08-23 05:54:33 +00001628 //
1629 // Create efi varstore with format follow UEFI spec before 2.3.1.
1630 //
ydong1094f3aae2013-04-16 10:53:22 +00001631 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);
1632 } else {
Eric Dongc0462ea2013-08-23 05:54:33 +00001633 //
1634 // Create efi varstore with format follow UEFI spec 2.3.1 and later.
1635 //
ydong1094f3aae2013-04-16 10:53:22 +00001636 Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
ydong10cce62302011-07-12 07:24:36 +00001637 }
ydong1094f3aae2013-04-16 10:53:22 +00001638 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
qhuang8c60a0612008-10-31 04:41:33 +00001639 break;
1640
1641 //
1642 // DefaultStore
1643 //
1644 case EFI_IFR_DEFAULTSTORE_OP:
1645 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
jji41ac628e2009-01-19 07:58:58 +00001646 ASSERT (DefaultStore != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001647 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1648
1649 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
1650 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1651
1652 //
1653 // Insert to DefaultStore list of this Formset
1654 //
1655 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1656 break;
1657
1658 //
1659 // Statements
1660 //
1661 case EFI_IFR_SUBTITLE_OP:
1662 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
qwang12bc166db2009-02-02 07:18:59 +00001663 ASSERT (CurrentStatement != NULL);
xdu28b0fc5c2009-10-26 03:05:16 +00001664
qhuang8c60a0612008-10-31 04:41:33 +00001665 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
Eric Dong7c6c0642013-08-12 02:19:56 +00001666 CurrentStatement->FakeQuestionId = mUsedQuestionId++;
qhuang8c60a0612008-10-31 04:41:33 +00001667 if (Scope != 0) {
1668 mInScopeSubtitle = TRUE;
1669 }
1670 break;
1671
1672 case EFI_IFR_TEXT_OP:
1673 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
qwang12bc166db2009-02-02 07:18:59 +00001674 ASSERT (CurrentStatement != NULL);
Eric Dong7c6c0642013-08-12 02:19:56 +00001675 CurrentStatement->FakeQuestionId = mUsedQuestionId++;
qhuang8c60a0612008-10-31 04:41:33 +00001676 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1677 break;
1678
xdu2f8a1c222009-10-20 03:01:10 +00001679 case EFI_IFR_RESET_BUTTON_OP:
1680 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1681 ASSERT (CurrentStatement != NULL);
Eric Dong7c6c0642013-08-12 02:19:56 +00001682 CurrentStatement->FakeQuestionId = mUsedQuestionId++;
xdu2f8a1c222009-10-20 03:01:10 +00001683 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1684 break;
1685
qhuang8c60a0612008-10-31 04:41:33 +00001686 //
1687 // Questions
1688 //
1689 case EFI_IFR_ACTION_OP:
1690 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
qwang12bc166db2009-02-02 07:18:59 +00001691 ASSERT (CurrentStatement != NULL);
xdu2d02847d2009-10-26 03:03:47 +00001692 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
qhuang8c60a0612008-10-31 04:41:33 +00001693
1694 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1695 //
1696 // No QuestionConfig present, so no configuration string will be processed
1697 //
1698 CurrentStatement->QuestionConfig = 0;
1699 } else {
1700 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1701 }
1702 break;
1703
qhuang8c60a0612008-10-31 04:41:33 +00001704 case EFI_IFR_REF_OP:
1705 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidyb347c1b2009-05-15 03:39:01 +00001706 ASSERT (CurrentStatement != NULL);
ydong108ca61802011-06-28 06:41:28 +00001707 Value = &CurrentStatement->HiiValue;
1708 Value->Type = EFI_IFR_TYPE_REF;
1709 if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
1710 CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
qhuang8c60a0612008-10-31 04:41:33 +00001711
ydong108ca61802011-06-28 06:41:28 +00001712 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1713 CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
qhuang8c60a0612008-10-31 04:41:33 +00001714
ydong108ca61802011-06-28 06:41:28 +00001715 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1716 CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1717
1718 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1719 CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1720 }
qhuang8c60a0612008-10-31 04:41:33 +00001721 }
1722 }
1723 }
ydong108ca61802011-06-28 06:41:28 +00001724 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
1725 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00001726 break;
1727
1728 case EFI_IFR_ONE_OF_OP:
1729 case EFI_IFR_NUMERIC_OP:
1730 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidy945e3ae2009-05-13 09:24:25 +00001731 ASSERT(CurrentStatement != NULL);
xdu28b0fc5c2009-10-26 03:05:16 +00001732
qhuang8c60a0612008-10-31 04:41:33 +00001733 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1734 Value = &CurrentStatement->HiiValue;
1735
1736 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1737 case EFI_IFR_NUMERIC_SIZE_1:
1738 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1739 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1740 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
ydong10cd7bfc22010-09-16 04:51:25 +00001741 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
qhuang8c60a0612008-10-31 04:41:33 +00001742 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1743 break;
1744
1745 case EFI_IFR_NUMERIC_SIZE_2:
1746 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1747 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1748 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
ydong10cd7bfc22010-09-16 04:51:25 +00001749 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
qhuang8c60a0612008-10-31 04:41:33 +00001750 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1751 break;
1752
1753 case EFI_IFR_NUMERIC_SIZE_4:
1754 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
1755 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
1756 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
ydong10cd7bfc22010-09-16 04:51:25 +00001757 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
qhuang8c60a0612008-10-31 04:41:33 +00001758 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1759 break;
1760
1761 case EFI_IFR_NUMERIC_SIZE_8:
1762 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
1763 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
1764 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
ydong10cd7bfc22010-09-16 04:51:25 +00001765 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
qhuang8c60a0612008-10-31 04:41:33 +00001766 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1767 break;
1768
1769 default:
1770 break;
1771 }
1772
ydong10b18e7052011-05-31 00:59:15 +00001773 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00001774
1775 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
1776 SuppressForOption = TRUE;
1777 }
1778 break;
1779
1780 case EFI_IFR_ORDERED_LIST_OP:
1781 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidyb347c1b2009-05-15 03:39:01 +00001782 ASSERT(CurrentStatement != NULL);
xdu28b0fc5c2009-10-26 03:05:16 +00001783
qhuang8c60a0612008-10-31 04:41:33 +00001784 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
1785 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
qhuang8c60a0612008-10-31 04:41:33 +00001786
xdu2d02847d2009-10-26 03:03:47 +00001787 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
lgao4b86b4132010-02-22 06:30:41 +00001788 CurrentStatement->BufferValue = NULL;
qhuang8c60a0612008-10-31 04:41:33 +00001789
1790 if (Scope != 0) {
1791 SuppressForOption = TRUE;
1792 }
1793 break;
1794
1795 case EFI_IFR_CHECKBOX_OP:
1796 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidyb347c1b2009-05-15 03:39:01 +00001797 ASSERT(CurrentStatement != NULL);
xdu28b0fc5c2009-10-26 03:05:16 +00001798
qhuang8c60a0612008-10-31 04:41:33 +00001799 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
ydong10cd7bfc22010-09-16 04:51:25 +00001800 CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
qhuang8c60a0612008-10-31 04:41:33 +00001801 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
1802
ydong10b18e7052011-05-31 00:59:15 +00001803 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00001804
1805 break;
1806
1807 case EFI_IFR_STRING_OP:
1808 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidyb347c1b2009-05-15 03:39:01 +00001809 ASSERT (CurrentStatement != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001810 //
1811 // MinSize is the minimum number of characters that can be accepted for this opcode,
1812 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1813 // The characters are stored as Unicode, so the storage width should multiply 2.
1814 //
1815 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
1816 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
1817 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1818 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
1819
1820 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1821 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
ydong10e2100bf2010-12-23 06:47:50 +00001822 CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
qhuang8c60a0612008-10-31 04:41:33 +00001823
ydong10b18e7052011-05-31 00:59:15 +00001824 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00001825 break;
1826
1827 case EFI_IFR_PASSWORD_OP:
1828 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidyb347c1b2009-05-15 03:39:01 +00001829 ASSERT (CurrentStatement != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001830 //
1831 // MinSize is the minimum number of characters that can be accepted for this opcode,
1832 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1833 // The characters are stored as Unicode, so the storage width should multiply 2.
1834 //
1835 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
1836 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
1837 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1838
1839 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1840 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
ydong10e2100bf2010-12-23 06:47:50 +00001841 CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);
qhuang8c60a0612008-10-31 04:41:33 +00001842
ydong10b18e7052011-05-31 00:59:15 +00001843 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00001844 break;
1845
1846 case EFI_IFR_DATE_OP:
1847 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidyb347c1b2009-05-15 03:39:01 +00001848 ASSERT(CurrentStatement != NULL);
xdu28b0fc5c2009-10-26 03:05:16 +00001849
qhuang8c60a0612008-10-31 04:41:33 +00001850 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
1851 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
1852
1853 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
ydong10cd7bfc22010-09-16 04:51:25 +00001854 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
qhuang8c60a0612008-10-31 04:41:33 +00001855
ydong10b18e7052011-05-31 00:59:15 +00001856 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00001857 } else {
1858 //
1859 // Don't assign storage for RTC type of date/time
1860 //
1861 CurrentStatement->Storage = NULL;
1862 CurrentStatement->StorageWidth = 0;
1863 }
1864 break;
1865
1866 case EFI_IFR_TIME_OP:
1867 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
gikidyb347c1b2009-05-15 03:39:01 +00001868 ASSERT(CurrentStatement != NULL);
xdu28b0fc5c2009-10-26 03:05:16 +00001869
qhuang8c60a0612008-10-31 04:41:33 +00001870 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
1871 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
1872
1873 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
ydong105ec56d12011-05-17 01:27:05 +00001874 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
qhuang8c60a0612008-10-31 04:41:33 +00001875
ydong10b18e7052011-05-31 00:59:15 +00001876 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00001877 } else {
1878 //
1879 // Don't assign storage for RTC type of date/time
1880 //
1881 CurrentStatement->Storage = NULL;
1882 CurrentStatement->StorageWidth = 0;
1883 }
1884 break;
1885
1886 //
1887 // Default
1888 //
1889 case EFI_IFR_DEFAULT_OP:
1890 //
1891 // EFI_IFR_DEFAULT appear in scope of a Question,
1892 // It creates a default value for the current question.
1893 // A Question may have more than one Default value which have different default types.
1894 //
1895 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
jji41ac628e2009-01-19 07:58:58 +00001896 ASSERT (CurrentDefault != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001897 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
1898
1899 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
1900 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
ydong1023fe74d2012-12-17 03:30:43 +00001901 if (OpCodeLength > OFFSET_OF (EFI_IFR_DEFAULT, Value)) {
1902 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
ydong104706ff42012-09-27 11:19:56 +00001903 ExtendValueToU64 (&CurrentDefault->Value);
1904 }
qhuang8c60a0612008-10-31 04:41:33 +00001905
1906 //
1907 // Insert to Default Value list of current Question
1908 //
1909 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
1910
1911 if (Scope != 0) {
1912 InScopeDefault = TRUE;
1913 }
1914 break;
1915
1916 //
1917 // Option
1918 //
1919 case EFI_IFR_ONE_OF_OPTION_OP:
1920 //
1921 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
1922 // It create a selection for use in current Question.
1923 //
1924 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
jji41ac628e2009-01-19 07:58:58 +00001925 ASSERT (CurrentOption != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00001926 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
Eric Dong7c6c0642013-08-12 02:19:56 +00001927 CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION *) OpCodeData;
qhuang8c60a0612008-10-31 04:41:33 +00001928
1929 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
1930 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
1931 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
ydong10a7f87052013-01-06 06:12:50 +00001932 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
qhuang8c60a0612008-10-31 04:41:33 +00001933 ExtendValueToU64 (&CurrentOption->Value);
1934
ydong1031585af2012-01-31 07:17:42 +00001935 ConditionalExprCount = GetConditionalExpressionCount(ExpressOption);
1936 if ( ConditionalExprCount > 0) {
1937 //
1938 // Form is inside of suppressif
1939 //
1940 CurrentOption->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool(
1941 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));
1942 ASSERT (CurrentOption->SuppressExpression != NULL);
1943 CurrentOption->SuppressExpression->Count = (UINTN) ConditionalExprCount;
1944 CurrentOption->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
1945 CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList(ExpressOption), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));
qhuang8c60a0612008-10-31 04:41:33 +00001946 }
1947
1948 //
1949 // Insert to Option list of current Question
1950 //
1951 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
xdu2d02847d2009-10-26 03:03:47 +00001952
1953 //
1954 // Now we know the Storage width of nested Ordered List
1955 //
xdu21b2bf3c2010-02-05 06:13:18 +00001956 ASSERT (CurrentStatement != NULL);
xdu2d02847d2009-10-26 03:03:47 +00001957 if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) {
1958 Width = 1;
1959 switch (CurrentOption->Value.Type) {
1960 case EFI_IFR_TYPE_NUM_SIZE_8:
1961 Width = 1;
1962 break;
1963
1964 case EFI_IFR_TYPE_NUM_SIZE_16:
1965 Width = 2;
1966 break;
1967
1968 case EFI_IFR_TYPE_NUM_SIZE_32:
1969 Width = 4;
1970 break;
1971
1972 case EFI_IFR_TYPE_NUM_SIZE_64:
1973 Width = 8;
1974 break;
1975
1976 default:
1977 //
1978 // Invalid type for Ordered List
1979 //
1980 break;
1981 }
1982
1983 CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width);
1984 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
1985 CurrentStatement->ValueType = CurrentOption->Value.Type;
ydong10901ba0e2011-11-18 07:07:31 +00001986 if (CurrentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
1987 CurrentStatement->HiiValue.Buffer = CurrentStatement->BufferValue;
1988 CurrentStatement->HiiValue.BufferLen = CurrentStatement->StorageWidth;
1989 }
xdu2d02847d2009-10-26 03:03:47 +00001990
ydong10b18e7052011-05-31 00:59:15 +00001991 InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
xdu2d02847d2009-10-26 03:03:47 +00001992 }
qhuang8c60a0612008-10-31 04:41:33 +00001993 break;
1994
1995 //
1996 // Conditional
1997 //
1998 case EFI_IFR_NO_SUBMIT_IF_OP:
1999 case EFI_IFR_INCONSISTENT_IF_OP:
2000 //
2001 // Create an Expression node
2002 //
2003 CurrentExpression = CreateExpression (CurrentForm);
2004 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
2005
2006 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
2007 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
2008 InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
2009 } else {
2010 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
2011 InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
2012 }
lgao40c66bc72009-11-12 01:16:12 +00002013
2014 //
2015 // Take a look at next OpCode to see whether current expression consists
2016 // of single OpCode
2017 //
2018 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2019 SingleOpCodeExpression = TRUE;
2020 }
qhuang8c60a0612008-10-31 04:41:33 +00002021 break;
2022
2023 case EFI_IFR_SUPPRESS_IF_OP:
2024 //
2025 // Question and Option will appear in scope of this OpCode
2026 //
2027 CurrentExpression = CreateExpression (CurrentForm);
2028 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
lgao40c66bc72009-11-12 01:16:12 +00002029
2030 if (CurrentForm == NULL) {
2031 InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
2032 } else {
2033 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2034 }
qhuang8c60a0612008-10-31 04:41:33 +00002035
2036 if (SuppressForOption) {
ydong1031585af2012-01-31 07:17:42 +00002037 PushConditionalExpression(CurrentExpression, ExpressOption);
lgao40c66bc72009-11-12 01:16:12 +00002038 } else if (SuppressForQuestion) {
ydong1031585af2012-01-31 07:17:42 +00002039 PushConditionalExpression(CurrentExpression, ExpressStatement);
lgao40c66bc72009-11-12 01:16:12 +00002040 } else {
ydong1031585af2012-01-31 07:17:42 +00002041 PushConditionalExpression(CurrentExpression, ExpressForm);
lgao40c66bc72009-11-12 01:16:12 +00002042 }
2043
2044 //
2045 // Take a look at next OpCode to see whether current expression consists
2046 // of single OpCode
2047 //
2048 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2049 SingleOpCodeExpression = TRUE;
qhuang8c60a0612008-10-31 04:41:33 +00002050 }
2051 break;
2052
2053 case EFI_IFR_GRAY_OUT_IF_OP:
2054 //
2055 // Questions will appear in scope of this OpCode
2056 //
2057 CurrentExpression = CreateExpression (CurrentForm);
2058 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
2059 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
ydong1031585af2012-01-31 07:17:42 +00002060 PushConditionalExpression(CurrentExpression, ExpressStatement);
lgao40c66bc72009-11-12 01:16:12 +00002061
2062 //
2063 // Take a look at next OpCode to see whether current expression consists
2064 // of single OpCode
2065 //
2066 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2067 SingleOpCodeExpression = TRUE;
2068 }
qhuang8c60a0612008-10-31 04:41:33 +00002069 break;
2070
2071 case EFI_IFR_DISABLE_IF_OP:
2072 //
2073 // The DisableIf expression should only rely on constant, so it could be
2074 // evaluated at initialization and it will not be queued
2075 //
2076 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
jji41ac628e2009-01-19 07:58:58 +00002077 ASSERT (CurrentExpression != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00002078 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
2079 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
2080 InitializeListHead (&CurrentExpression->OpCodeListHead);
2081
lgao40a1147e2009-04-22 03:18:37 +00002082 if (CurrentForm != NULL) {
2083 //
2084 // This is DisableIf for Question, enqueue it to Form expression list
2085 //
2086 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
ydong1031585af2012-01-31 07:17:42 +00002087 PushConditionalExpression(CurrentExpression, ExpressStatement);
lgao40a1147e2009-04-22 03:18:37 +00002088 }
2089
ydong1031585af2012-01-31 07:17:42 +00002090 OpCodeDisabled = FALSE;
2091 InScopeDisable = TRUE;
qhuang8c60a0612008-10-31 04:41:33 +00002092 //
2093 // Take a look at next OpCode to see whether current expression consists
2094 // of single OpCode
2095 //
2096 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2097 SingleOpCodeExpression = TRUE;
2098 }
2099 break;
2100
2101 //
2102 // Expression
2103 //
2104 case EFI_IFR_VALUE_OP:
2105 CurrentExpression = CreateExpression (CurrentForm);
2106 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
2107 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2108
2109 if (InScopeDefault) {
2110 //
2111 // Used for default (EFI_IFR_DEFAULT)
2112 //
2113 CurrentDefault->ValueExpression = CurrentExpression;
2114 } else {
2115 //
2116 // If used for a question, then the question will be read-only
2117 //
qwang12bc166db2009-02-02 07:18:59 +00002118 //
2119 // Make sure CurrentStatement is not NULL.
2120 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2121 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2122 //
2123 ASSERT (CurrentStatement != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00002124 CurrentStatement->ValueExpression = CurrentExpression;
2125 }
lgao40c66bc72009-11-12 01:16:12 +00002126
2127 //
2128 // Take a look at next OpCode to see whether current expression consists
2129 // of single OpCode
2130 //
2131 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2132 SingleOpCodeExpression = TRUE;
2133 }
qhuang8c60a0612008-10-31 04:41:33 +00002134 break;
2135
2136 case EFI_IFR_RULE_OP:
2137 CurrentExpression = CreateExpression (CurrentForm);
2138 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
2139
2140 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
2141 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
lgao40c66bc72009-11-12 01:16:12 +00002142
2143 //
2144 // Take a look at next OpCode to see whether current expression consists
2145 // of single OpCode
2146 //
2147 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2148 SingleOpCodeExpression = TRUE;
2149 }
qhuang8c60a0612008-10-31 04:41:33 +00002150 break;
2151
lgao425737122010-02-25 10:10:59 +00002152 case EFI_IFR_READ_OP:
2153 CurrentExpression = CreateExpression (CurrentForm);
2154 CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
2155 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2156
2157 //
2158 // Make sure CurrentStatement is not NULL.
2159 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2160 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2161 //
2162 ASSERT (CurrentStatement != NULL);
2163 CurrentStatement->ReadExpression = CurrentExpression;
2164
2165 //
2166 // Take a look at next OpCode to see whether current expression consists
2167 // of single OpCode
2168 //
2169 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2170 SingleOpCodeExpression = TRUE;
2171 }
2172 break;
2173
2174 case EFI_IFR_WRITE_OP:
2175 CurrentExpression = CreateExpression (CurrentForm);
2176 CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
2177 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2178
2179 //
2180 // Make sure CurrentStatement is not NULL.
2181 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2182 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
2183 //
2184 ASSERT (CurrentStatement != NULL);
2185 CurrentStatement->WriteExpression = CurrentExpression;
2186
2187 //
2188 // Take a look at next OpCode to see whether current expression consists
2189 // of single OpCode
2190 //
2191 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2192 SingleOpCodeExpression = TRUE;
2193 }
2194 break;
2195
qhuang8c60a0612008-10-31 04:41:33 +00002196 //
2197 // Image
2198 //
2199 case EFI_IFR_IMAGE_OP:
2200 //
2201 // Get ScopeOpcode from top of stack
2202 //
2203 PopScope (&ScopeOpCode);
2204 PushScope (ScopeOpCode);
2205
2206 switch (ScopeOpCode) {
2207 case EFI_IFR_FORM_SET_OP:
2208 ImageId = &FormSet->ImageId;
2209 break;
2210
2211 case EFI_IFR_FORM_OP:
lgao425737122010-02-25 10:10:59 +00002212 case EFI_IFR_FORM_MAP_OP:
qwang12d0720b52009-01-20 01:55:11 +00002213 ASSERT (CurrentForm != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00002214 ImageId = &CurrentForm->ImageId;
2215 break;
2216
2217 case EFI_IFR_ONE_OF_OPTION_OP:
2218 ImageId = &CurrentOption->ImageId;
2219 break;
2220
2221 default:
qwang12bc166db2009-02-02 07:18:59 +00002222 //
2223 // Make sure CurrentStatement is not NULL.
2224 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
2225 // file is wrongly generated by tools such as VFR Compiler.
2226 //
2227 ASSERT (CurrentStatement != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00002228 ImageId = &CurrentStatement->ImageId;
2229 break;
2230 }
2231
qwang12c4105892009-02-06 06:34:43 +00002232 ASSERT (ImageId != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00002233 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
2234 break;
2235
2236 //
2237 // Refresh
2238 //
2239 case EFI_IFR_REFRESH_OP:
qwang12c4105892009-02-06 06:34:43 +00002240 ASSERT (CurrentStatement != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00002241 CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
2242 break;
2243
2244 //
ydong10211cc6e2011-06-08 08:09:47 +00002245 // Refresh guid.
2246 //
2247 case EFI_IFR_REFRESH_ID_OP:
2248 ASSERT (CurrentStatement != NULL);
2249 CopyMem (&CurrentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
2250 break;
2251
2252 //
ydong10b00964a2011-06-08 07:27:39 +00002253 // Modal tag
2254 //
2255 case EFI_IFR_MODAL_TAG_OP:
2256 ASSERT (CurrentForm != NULL);
2257 CurrentForm->ModalForm = TRUE;
2258 break;
2259
2260 //
ydong10f67c4382011-11-16 05:23:38 +00002261 // Lock tag, used by form and statement.
2262 //
2263 case EFI_IFR_LOCKED_OP:
2264 //
2265 // Get ScopeOpcode from top of stack
2266 //
2267 PopScope (&ScopeOpCode);
2268 PushScope (ScopeOpCode);
2269 switch (ScopeOpCode) {
2270 case EFI_IFR_FORM_OP:
2271 case EFI_IFR_FORM_MAP_OP:
2272 ASSERT (CurrentForm != NULL);
2273 CurrentForm->Locked = TRUE;
2274 break;
2275
2276 default:
2277 ASSERT (CurrentStatement != NULL);
2278 CurrentStatement->Locked = TRUE;
2279 }
2280 break;
2281
2282 //
qhuang8c60a0612008-10-31 04:41:33 +00002283 // Vendor specific
2284 //
Eric Dong7c6c0642013-08-12 02:19:56 +00002285 case EFI_IFR_GUID_OP:
2286 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
qhuang8c60a0612008-10-31 04:41:33 +00002287 break;
2288
2289 //
2290 // Scope End
2291 //
2292 case EFI_IFR_END_OP:
2293 Status = PopScope (&ScopeOpCode);
2294 if (EFI_ERROR (Status)) {
2295 ResetScopeStack ();
2296 return Status;
2297 }
2298
2299 switch (ScopeOpCode) {
2300 case EFI_IFR_FORM_SET_OP:
2301 //
2302 // End of FormSet, update FormSet IFR binary length
2303 // to stop parsing substantial OpCodes
2304 //
2305 FormSet->IfrBinaryLength = OpCodeOffset;
2306 break;
2307
2308 case EFI_IFR_FORM_OP:
lgao425737122010-02-25 10:10:59 +00002309 case EFI_IFR_FORM_MAP_OP:
qhuang8c60a0612008-10-31 04:41:33 +00002310 //
2311 // End of Form
2312 //
2313 CurrentForm = NULL;
lgao40c66bc72009-11-12 01:16:12 +00002314 SuppressForQuestion = FALSE;
qhuang8c60a0612008-10-31 04:41:33 +00002315 break;
2316
2317 case EFI_IFR_ONE_OF_OPTION_OP:
2318 //
2319 // End of Option
2320 //
2321 CurrentOption = NULL;
2322 break;
2323
2324 case EFI_IFR_SUBTITLE_OP:
2325 mInScopeSubtitle = FALSE;
2326 break;
2327
2328 case EFI_IFR_NO_SUBMIT_IF_OP:
2329 case EFI_IFR_INCONSISTENT_IF_OP:
2330 //
2331 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
2332 //
2333 break;
2334
2335 case EFI_IFR_SUPPRESS_IF_OP:
2336 if (SuppressForOption) {
ydong1031585af2012-01-31 07:17:42 +00002337 PopConditionalExpression(ExpressOption);
lgao40c66bc72009-11-12 01:16:12 +00002338 } else if (SuppressForQuestion) {
ydong1031585af2012-01-31 07:17:42 +00002339 PopConditionalExpression(ExpressStatement);
lgao40c66bc72009-11-12 01:16:12 +00002340 } else {
ydong1031585af2012-01-31 07:17:42 +00002341 PopConditionalExpression(ExpressForm);
qhuang8c60a0612008-10-31 04:41:33 +00002342 }
2343 break;
2344
2345 case EFI_IFR_GRAY_OUT_IF_OP:
ydong1031585af2012-01-31 07:17:42 +00002346 PopConditionalExpression(ExpressStatement);
qhuang8c60a0612008-10-31 04:41:33 +00002347 break;
2348
2349 case EFI_IFR_DISABLE_IF_OP:
ydong1031585af2012-01-31 07:17:42 +00002350 if (CurrentForm != NULL) {
2351 PopConditionalExpression(ExpressStatement);
2352 }
2353 InScopeDisable = FALSE;
qhuang8c60a0612008-10-31 04:41:33 +00002354 OpCodeDisabled = FALSE;
2355 break;
2356
2357 case EFI_IFR_ONE_OF_OP:
2358 case EFI_IFR_ORDERED_LIST_OP:
2359 SuppressForOption = FALSE;
2360 break;
2361
2362 case EFI_IFR_DEFAULT_OP:
2363 InScopeDefault = FALSE;
2364 break;
2365
lgao425737122010-02-25 10:10:59 +00002366 case EFI_IFR_MAP_OP:
2367 //
2368 // Get current Map Expression List.
2369 //
2370 Status = PopMapExpressionList ((VOID **) &MapExpressionList);
2371 if (Status == EFI_ACCESS_DENIED) {
2372 MapExpressionList = NULL;
2373 }
2374 //
2375 // Get current expression.
2376 //
2377 Status = PopCurrentExpression ((VOID **) &CurrentExpression);
2378 ASSERT_EFI_ERROR (Status);
lgao4771ecec2010-02-27 09:04:11 +00002379 ASSERT (MapScopeDepth > 0);
lgao425737122010-02-25 10:10:59 +00002380 MapScopeDepth --;
2381 break;
2382
qhuang8c60a0612008-10-31 04:41:33 +00002383 default:
2384 if (IsExpressionOpCode (ScopeOpCode)) {
ydong1031585af2012-01-31 07:17:42 +00002385 if (InScopeDisable && CurrentForm == NULL) {
qhuang8c60a0612008-10-31 04:41:33 +00002386 //
lgao40a1147e2009-04-22 03:18:37 +00002387 // This is DisableIf expression for Form, it should be a constant expression
qhuang8c60a0612008-10-31 04:41:33 +00002388 //
xdu2f8a1c222009-10-20 03:01:10 +00002389 ASSERT (CurrentExpression != NULL);
qhuang8c60a0612008-10-31 04:41:33 +00002390 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
2391 if (EFI_ERROR (Status)) {
2392 return Status;
2393 }
qwang12a935a0d2009-02-10 09:40:27 +00002394
qhuang8c60a0612008-10-31 04:41:33 +00002395 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
2396 return EFI_INVALID_PARAMETER;
2397 }
2398
2399 OpCodeDisabled = CurrentExpression->Result.Value.b;
2400 //
lgao425737122010-02-25 10:10:59 +00002401 // DisableIf Expression is only used once and not queued, free it
qhuang8c60a0612008-10-31 04:41:33 +00002402 //
2403 DestroyExpression (CurrentExpression);
2404 }
2405
2406 //
2407 // End of current Expression
2408 //
2409 CurrentExpression = NULL;
2410 }
2411 break;
2412 }
2413 break;
2414
2415 default:
2416 break;
2417 }
2418 }
2419
2420 return EFI_SUCCESS;
2421}