]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
Add more check to avoid code enter into wrong state.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / IfrParse.c
CommitLineData
c60a0616 1/** @file\r
2Parser for IFR binary encoding.\r
3\r
d228526f 4Copyright (c) 2007 - 2010, Intel Corporation\r
c60a0616 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
c60a0616 16\r
17UINT16 mStatementIndex;\r
18UINT16 mExpressionOpCodeIndex;\r
19\r
20BOOLEAN mInScopeSubtitle;\r
21BOOLEAN mInScopeSuppress;\r
22BOOLEAN mInScopeGrayOut;\r
0a1147ed 23BOOLEAN mInScopeDisable;\r
c60a0616 24FORM_EXPRESSION *mSuppressExpression;\r
25FORM_EXPRESSION *mGrayOutExpression;\r
0a1147ed 26FORM_EXPRESSION *mDisableExpression;\r
c60a0616 27\r
c60a0616 28/**\r
29 Initialize Statement header members.\r
30\r
31 @param OpCodeData Pointer of the raw OpCode data.\r
32 @param FormSet Pointer of the current FormSe.\r
33 @param Form Pointer of the current Form.\r
34\r
35 @return The Statement.\r
36\r
37**/\r
38FORM_BROWSER_STATEMENT *\r
39CreateStatement (\r
40 IN UINT8 *OpCodeData,\r
41 IN OUT FORM_BROWSER_FORMSET *FormSet,\r
42 IN OUT FORM_BROWSER_FORM *Form\r
43 )\r
44{\r
45 FORM_BROWSER_STATEMENT *Statement;\r
46 EFI_IFR_STATEMENT_HEADER *StatementHdr;\r
47\r
48 if (Form == NULL) {\r
49 //\r
50 // We are currently not in a Form Scope, so just skip this Statement\r
51 //\r
52 return NULL;\r
53 }\r
54\r
55 Statement = &FormSet->StatementBuffer[mStatementIndex];\r
56 mStatementIndex++;\r
57\r
58 InitializeListHead (&Statement->DefaultListHead);\r
59 InitializeListHead (&Statement->OptionListHead);\r
60 InitializeListHead (&Statement->InconsistentListHead);\r
61 InitializeListHead (&Statement->NoSubmitListHead);\r
62\r
63 Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;\r
64\r
65 Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
66\r
67 StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
68 CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));\r
69 CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));\r
70\r
71 if (mInScopeSuppress) {\r
72 Statement->SuppressExpression = mSuppressExpression;\r
73 }\r
74\r
75 if (mInScopeGrayOut) {\r
76 Statement->GrayOutExpression = mGrayOutExpression;\r
77 }\r
78\r
0a1147ed
LG
79\r
80 if (mInScopeDisable) {\r
81 Statement->DisableExpression = mDisableExpression;\r
82 }\r
83\r
c60a0616 84 Statement->InSubtitle = mInScopeSubtitle;\r
85\r
86 //\r
87 // Insert this Statement into current Form\r
88 //\r
89 InsertTailList (&Form->StatementListHead, &Statement->Link);\r
90\r
91 return Statement;\r
92}\r
93\r
7064c0a5 94/**\r
95 Convert a numeric value to a Unicode String and insert it to String Package.\r
96 This string is used as the Unicode Name for the EFI Variable. This is to support\r
97 the deprecated vareqval opcode.\r
8b0fc5c1 98\r
7064c0a5 99 @param FormSet The FormSet.\r
100 @param Statement The numeric question whose VarStoreInfo.VarName is the\r
101 numeric value which is used to produce the Unicode Name\r
102 for the EFI Variable.\r
8b0fc5c1 103\r
7064c0a5 104 If the Statement is NULL, the ASSERT.\r
105 If the opcode is not Numeric, then ASSERT.\r
8b0fc5c1 106\r
7064c0a5 107 @retval EFI_SUCCESS The funtion always succeeds.\r
108**/\r
c60a0616 109EFI_STATUS\r
110UpdateCheckBoxStringToken (\r
111 IN CONST FORM_BROWSER_FORMSET *FormSet,\r
112 IN FORM_BROWSER_STATEMENT *Statement\r
113 )\r
114{\r
115 CHAR16 Str[MAXIMUM_VALUE_CHARACTERS];\r
116 EFI_STRING_ID Id;\r
c60a0616 117\r
118 ASSERT (Statement != NULL);\r
119 ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP);\r
8b0fc5c1 120\r
c60a0616 121 UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1);\r
c60a0616 122\r
cb7d01c0 123 Id = HiiSetString (FormSet->HiiHandle, 0, Str, NULL);\r
124 if (Id == 0) {\r
125 return EFI_OUT_OF_RESOURCES;\r
c60a0616 126 }\r
127\r
128 Statement->VarStoreInfo.VarName = Id;\r
8b0fc5c1 129\r
c60a0616 130 return EFI_SUCCESS;\r
131}\r
132\r
7064c0a5 133/**\r
134 Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME.\r
8b0fc5c1 135\r
7064c0a5 136 @param OpCodeData The current opcode.\r
8b0fc5c1 137\r
7064c0a5 138 @retval TRUE Yes.\r
139 @retval FALSE No.\r
140**/\r
c60a0616 141BOOLEAN\r
142IsNextOpCodeGuidedVarEqName (\r
8b0fc5c1 143 IN UINT8 *OpCodeData\r
c60a0616 144 )\r
145{\r
146 //\r
147 // Get next opcode\r
148 //\r
149 OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
150 if (*OpCodeData == EFI_IFR_GUID_OP) {\r
5c526736 151 if (CompareGuid (&gEfiIfrFrameworkGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
c60a0616 152 //\r
8b0fc5c1 153 // Specific GUIDed opcodes to support IFR generated from Framework HII VFR\r
c60a0616 154 //\r
155 if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) {\r
156 return TRUE;\r
157 }\r
158 }\r
159 }\r
160\r
161 return FALSE;\r
162}\r
163\r
164/**\r
165 Initialize Question's members.\r
166\r
167 @param OpCodeData Pointer of the raw OpCode data.\r
168 @param FormSet Pointer of the current FormSet.\r
169 @param Form Pointer of the current Form.\r
170\r
171 @return The Question.\r
172\r
173**/\r
174FORM_BROWSER_STATEMENT *\r
175CreateQuestion (\r
176 IN UINT8 *OpCodeData,\r
177 IN OUT FORM_BROWSER_FORMSET *FormSet,\r
178 IN OUT FORM_BROWSER_FORM *Form\r
179 )\r
180{\r
181 FORM_BROWSER_STATEMENT *Statement;\r
182 EFI_IFR_QUESTION_HEADER *QuestionHdr;\r
183 LIST_ENTRY *Link;\r
184 FORMSET_STORAGE *Storage;\r
185 NAME_VALUE_NODE *NameValueNode;\r
186 EFI_STATUS Status;\r
187\r
188 Statement = CreateStatement (OpCodeData, FormSet, Form);\r
189 if (Statement == NULL) {\r
190 return NULL;\r
191 }\r
192\r
193 QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
194 CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));\r
195 CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
196 CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));\r
197\r
198 Statement->QuestionFlags = QuestionHdr->Flags;\r
199\r
200 if (Statement->VarStoreId == 0) {\r
201 //\r
202 // VarStoreId of zero indicates no variable storage\r
203 //\r
204 return Statement;\r
205 }\r
206\r
207 //\r
208 // Take a look at next OpCode to see whether it is a GUIDed opcode to support\r
209 // Framework Compatibility\r
210 //\r
f806dd27 211 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
c60a0616 212 if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {\r
213 Status = UpdateCheckBoxStringToken (FormSet, Statement);\r
214 if (EFI_ERROR (Status)) {\r
215 return NULL;\r
216 }\r
217 }\r
218 }\r
219\r
220 //\r
221 // Find Storage for this Question\r
222 //\r
223 Link = GetFirstNode (&FormSet->StorageListHead);\r
224 while (!IsNull (&FormSet->StorageListHead, Link)) {\r
225 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
226\r
227 if (Storage->VarStoreId == Statement->VarStoreId) {\r
228 Statement->Storage = Storage;\r
229 break;\r
230 }\r
231\r
232 Link = GetNextNode (&FormSet->StorageListHead, Link);\r
233 }\r
234 ASSERT (Statement->Storage != NULL);\r
235\r
236 //\r
237 // Initialilze varname for Name/Value or EFI Variable\r
238 //\r
239 if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||\r
240 (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
241 Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);\r
242 ASSERT (Statement->VariableName != NULL);\r
243\r
244 if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
245 //\r
246 // Insert to Name/Value varstore list\r
247 //\r
248 NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));\r
249 ASSERT (NameValueNode != NULL);\r
250 NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;\r
251 NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);\r
252 ASSERT (NameValueNode->Name != NULL);\r
253 NameValueNode->Value = AllocateZeroPool (0x10);\r
254 ASSERT (NameValueNode->Value != NULL);\r
255 NameValueNode->EditValue = AllocateZeroPool (0x10);\r
256 ASSERT (NameValueNode->EditValue != NULL);\r
257\r
258 InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);\r
259 }\r
260 }\r
261\r
262 return Statement;\r
263}\r
264\r
265\r
266/**\r
267 Allocate a FORM_EXPRESSION node.\r
268\r
269 @param Form The Form associated with this Expression\r
270\r
271 @return Pointer to a FORM_EXPRESSION data structure.\r
272\r
273**/\r
274FORM_EXPRESSION *\r
275CreateExpression (\r
276 IN OUT FORM_BROWSER_FORM *Form\r
277 )\r
278{\r
279 FORM_EXPRESSION *Expression;\r
280\r
281 Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));\r
1ac628ee 282 ASSERT (Expression != NULL);\r
c60a0616 283 Expression->Signature = FORM_EXPRESSION_SIGNATURE;\r
284 InitializeListHead (&Expression->OpCodeListHead);\r
285\r
286 return Expression;\r
287}\r
288\r
289\r
290/**\r
291 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.\r
292\r
293 @param FormSet Pointer of the current FormSet\r
294\r
295 @return Pointer to a FORMSET_STORAGE data structure.\r
296\r
297**/\r
298FORMSET_STORAGE *\r
299CreateStorage (\r
300 IN FORM_BROWSER_FORMSET *FormSet\r
301 )\r
302{\r
303 FORMSET_STORAGE *Storage;\r
304\r
305 Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));\r
1ac628ee 306 ASSERT (Storage != NULL);\r
c60a0616 307 Storage->Signature = FORMSET_STORAGE_SIGNATURE;\r
308 InitializeListHead (&Storage->NameValueListHead);\r
309 InsertTailList (&FormSet->StorageListHead, &Storage->Link);\r
310\r
311 return Storage;\r
312}\r
313\r
314\r
315/**\r
316 Create ConfigHdr string for a storage.\r
317\r
318 @param FormSet Pointer of the current FormSet\r
319 @param Storage Pointer of the storage\r
320\r
321 @retval EFI_SUCCESS Initialize ConfigHdr success\r
322\r
323**/\r
324EFI_STATUS\r
325InitializeConfigHdr (\r
326 IN FORM_BROWSER_FORMSET *FormSet,\r
327 IN OUT FORMSET_STORAGE *Storage\r
328 )\r
329{\r
c60a0616 330 CHAR16 *Name;\r
8b0fc5c1 331\r
c60a0616 332 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
333 Name = Storage->Name;\r
334 } else {\r
335 Name = NULL;\r
336 }\r
8b0fc5c1 337\r
7e3bcccb
LG
338 Storage->ConfigHdr = HiiConstructConfigHdr (\r
339 &Storage->Guid,\r
340 Name,\r
341 FormSet->DriverHandle\r
342 );\r
8b0fc5c1 343\r
7e3bcccb
LG
344 if (Storage->ConfigHdr == NULL) {\r
345 return EFI_NOT_FOUND;\r
c60a0616 346 }\r
347\r
7e3bcccb 348 Storage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);\r
c60a0616 349 Storage->SpareStrLen = 0;\r
350\r
351 return EFI_SUCCESS;\r
352}\r
353\r
354\r
355/**\r
356 Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>\r
357\r
358 @param FormSet Pointer of the current FormSet.\r
359 @param Question The Question to be initialized.\r
360\r
361 @retval EFI_SUCCESS Function success.\r
362 @retval EFI_INVALID_PARAMETER No storage associated with the Question.\r
363\r
364**/\r
365EFI_STATUS\r
366InitializeRequestElement (\r
367 IN OUT FORM_BROWSER_FORMSET *FormSet,\r
368 IN OUT FORM_BROWSER_STATEMENT *Question\r
369 )\r
370{\r
371 FORMSET_STORAGE *Storage;\r
372 UINTN StrLen;\r
373 UINTN StringSize;\r
374 CHAR16 *NewStr;\r
375 CHAR16 RequestElement[30];\r
376\r
377 Storage = Question->Storage;\r
378 if (Storage == NULL) {\r
379 return EFI_INVALID_PARAMETER;\r
380 }\r
381\r
382 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
383 //\r
384 // <ConfigRequest> is unnecessary for EFI variable storage,\r
385 // GetVariable()/SetVariable() will be used to retrieve/save values\r
386 //\r
387 return EFI_SUCCESS;\r
388 }\r
389\r
390 //\r
391 // Prepare <RequestElement>\r
392 //\r
393 if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
394 StrLen = UnicodeSPrint (\r
395 RequestElement,\r
396 30 * sizeof (CHAR16),\r
397 L"&OFFSET=%x&WIDTH=%x",\r
398 Question->VarStoreInfo.VarOffset,\r
399 Question->StorageWidth\r
400 );\r
401 Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);\r
402 } else {\r
403 StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);\r
404 }\r
405\r
406 if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
407 //\r
408 // Password with CALLBACK flag is stored in encoded format,\r
409 // so don't need to append it to <ConfigRequest>\r
410 //\r
411 return EFI_SUCCESS;\r
412 }\r
413\r
414 //\r
415 // Append <RequestElement> to <ConfigRequest>\r
416 //\r
417 if (StrLen > Storage->SpareStrLen) {\r
418 //\r
419 // Old String buffer is not sufficient for RequestElement, allocate a new one\r
420 //\r
421 StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);\r
422 NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
1ac628ee 423 ASSERT (NewStr != NULL);\r
c60a0616 424 if (Storage->ConfigRequest != NULL) {\r
425 CopyMem (NewStr, Storage->ConfigRequest, StringSize);\r
f4113e1f 426 FreePool (Storage->ConfigRequest);\r
c60a0616 427 }\r
428 Storage->ConfigRequest = NewStr;\r
429 Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
430 }\r
431\r
432 StrCat (Storage->ConfigRequest, RequestElement);\r
433 Storage->ElementCount++;\r
434 Storage->SpareStrLen -= StrLen;\r
435\r
436 return EFI_SUCCESS;\r
437}\r
438\r
439\r
440/**\r
441 Free resources of a Expression.\r
442\r
443 @param FormSet Pointer of the Expression\r
444\r
445**/\r
446VOID\r
447DestroyExpression (\r
448 IN FORM_EXPRESSION *Expression\r
449 )\r
450{\r
451 LIST_ENTRY *Link;\r
452 EXPRESSION_OPCODE *OpCode;\r
453\r
454 while (!IsListEmpty (&Expression->OpCodeListHead)) {\r
455 Link = GetFirstNode (&Expression->OpCodeListHead);\r
456 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
457 RemoveEntryList (&OpCode->Link);\r
458\r
459 if (OpCode->ValueList != NULL) {\r
460 FreePool (OpCode->ValueList);\r
461 }\r
462 }\r
463\r
464 //\r
465 // Free this Expression\r
466 //\r
f4113e1f 467 FreePool (Expression);\r
c60a0616 468}\r
469\r
470\r
471/**\r
472 Free resources of a storage.\r
473\r
474 @param Storage Pointer of the storage\r
475\r
476**/\r
477VOID\r
478DestroyStorage (\r
479 IN FORMSET_STORAGE *Storage\r
480 )\r
481{\r
482 LIST_ENTRY *Link;\r
483 NAME_VALUE_NODE *NameValueNode;\r
484\r
485 if (Storage == NULL) {\r
486 return;\r
487 }\r
488\r
489 if (Storage->Name != NULL) {\r
490 FreePool (Storage->Name);\r
491 }\r
492 if (Storage->Buffer != NULL) {\r
493 FreePool (Storage->Buffer);\r
494 }\r
495 if (Storage->EditBuffer != NULL) {\r
496 FreePool (Storage->EditBuffer);\r
497 }\r
498\r
499 while (!IsListEmpty (&Storage->NameValueListHead)) {\r
500 Link = GetFirstNode (&Storage->NameValueListHead);\r
501 NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);\r
502 RemoveEntryList (&NameValueNode->Link);\r
503\r
504 if (NameValueNode->Name != NULL) {\r
505 FreePool (NameValueNode->Name);\r
506 }\r
507 if (NameValueNode->Value != NULL) {\r
508 FreePool (NameValueNode->Value);\r
509 }\r
510 if (NameValueNode->EditValue != NULL) {\r
511 FreePool (NameValueNode->EditValue);\r
512 }\r
513 FreePool (NameValueNode);\r
514 }\r
515\r
516 if (Storage->ConfigHdr != NULL) {\r
517 FreePool (Storage->ConfigHdr);\r
518 }\r
519 if (Storage->ConfigRequest != NULL) {\r
520 FreePool (Storage->ConfigRequest);\r
521 }\r
522\r
523 FreePool (Storage);\r
524}\r
525\r
526\r
527/**\r
528 Free resources of a Statement.\r
529\r
530 @param Statement Pointer of the Statement\r
531\r
532**/\r
533VOID\r
534DestroyStatement (\r
535 IN OUT FORM_BROWSER_STATEMENT *Statement\r
536 )\r
537{\r
538 LIST_ENTRY *Link;\r
539 QUESTION_DEFAULT *Default;\r
540 QUESTION_OPTION *Option;\r
541 FORM_EXPRESSION *Expression;\r
542\r
543 //\r
544 // Free Default value List\r
545 //\r
546 while (!IsListEmpty (&Statement->DefaultListHead)) {\r
547 Link = GetFirstNode (&Statement->DefaultListHead);\r
548 Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
549 RemoveEntryList (&Default->Link);\r
550\r
f4113e1f 551 FreePool (Default);\r
c60a0616 552 }\r
553\r
554 //\r
555 // Free Options List\r
556 //\r
557 while (!IsListEmpty (&Statement->OptionListHead)) {\r
558 Link = GetFirstNode (&Statement->OptionListHead);\r
559 Option = QUESTION_OPTION_FROM_LINK (Link);\r
560 RemoveEntryList (&Option->Link);\r
561\r
f4113e1f 562 FreePool (Option);\r
c60a0616 563 }\r
564\r
565 //\r
566 // Free Inconsistent List\r
567 //\r
568 while (!IsListEmpty (&Statement->InconsistentListHead)) {\r
569 Link = GetFirstNode (&Statement->InconsistentListHead);\r
570 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
571 RemoveEntryList (&Expression->Link);\r
572\r
573 DestroyExpression (Expression);\r
574 }\r
575\r
576 //\r
577 // Free NoSubmit List\r
578 //\r
579 while (!IsListEmpty (&Statement->NoSubmitListHead)) {\r
580 Link = GetFirstNode (&Statement->NoSubmitListHead);\r
581 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
582 RemoveEntryList (&Expression->Link);\r
583\r
584 DestroyExpression (Expression);\r
585 }\r
586\r
587 if (Statement->VariableName != NULL) {\r
588 FreePool (Statement->VariableName);\r
589 }\r
590 if (Statement->BlockName != NULL) {\r
591 FreePool (Statement->BlockName);\r
592 }\r
b86b413a
LG
593 if (Statement->BufferValue != NULL) {\r
594 FreePool (Statement->BufferValue);\r
595 }\r
c60a0616 596}\r
597\r
598\r
599/**\r
600 Free resources of a Form.\r
601\r
602 @param Form Pointer of the Form.\r
603\r
604**/\r
605VOID\r
606DestroyForm (\r
607 IN OUT FORM_BROWSER_FORM *Form\r
608 )\r
609{\r
610 LIST_ENTRY *Link;\r
611 FORM_EXPRESSION *Expression;\r
612 FORM_BROWSER_STATEMENT *Statement;\r
613\r
614 //\r
615 // Free Form Expressions\r
616 //\r
617 while (!IsListEmpty (&Form->ExpressionListHead)) {\r
618 Link = GetFirstNode (&Form->ExpressionListHead);\r
619 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
620 RemoveEntryList (&Expression->Link);\r
621\r
622 DestroyExpression (Expression);\r
623 }\r
624\r
625 //\r
626 // Free Statements/Questions\r
627 //\r
628 while (!IsListEmpty (&Form->StatementListHead)) {\r
629 Link = GetFirstNode (&Form->StatementListHead);\r
630 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
631 RemoveEntryList (&Statement->Link);\r
632\r
633 DestroyStatement (Statement);\r
634 }\r
635\r
636 //\r
637 // Free this Form\r
638 //\r
f4113e1f 639 FreePool (Form);\r
c60a0616 640}\r
641\r
642\r
643/**\r
644 Free resources allocated for a FormSet.\r
645\r
646 @param FormSet Pointer of the FormSet\r
647\r
648**/\r
649VOID\r
650DestroyFormSet (\r
651 IN OUT FORM_BROWSER_FORMSET *FormSet\r
652 )\r
653{\r
654 LIST_ENTRY *Link;\r
655 FORMSET_STORAGE *Storage;\r
656 FORMSET_DEFAULTSTORE *DefaultStore;\r
0c66bc76 657 FORM_EXPRESSION *Expression;\r
c60a0616 658 FORM_BROWSER_FORM *Form;\r
659\r
4c8358c7 660 if (FormSet->IfrBinaryData == NULL) {\r
661 //\r
662 // Uninitialized FormSet\r
663 //\r
664 FreePool (FormSet);\r
665 return;\r
666 }\r
667\r
c60a0616 668 //\r
669 // Free IFR binary buffer\r
670 //\r
671 FreePool (FormSet->IfrBinaryData);\r
672\r
673 //\r
674 // Free FormSet Storage\r
675 //\r
676 if (FormSet->StorageListHead.ForwardLink != NULL) {\r
677 while (!IsListEmpty (&FormSet->StorageListHead)) {\r
678 Link = GetFirstNode (&FormSet->StorageListHead);\r
679 Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
680 RemoveEntryList (&Storage->Link);\r
681\r
682 DestroyStorage (Storage);\r
683 }\r
684 }\r
685\r
686 //\r
687 // Free FormSet Default Store\r
688 //\r
689 if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {\r
690 while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {\r
691 Link = GetFirstNode (&FormSet->DefaultStoreListHead);\r
692 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);\r
693 RemoveEntryList (&DefaultStore->Link);\r
694\r
f4113e1f 695 FreePool (DefaultStore);\r
c60a0616 696 }\r
697 }\r
698\r
0c66bc76
LG
699 //\r
700 // Free Formset Expressions\r
701 //\r
702 while (!IsListEmpty (&FormSet->ExpressionListHead)) {\r
703 Link = GetFirstNode (&FormSet->ExpressionListHead);\r
704 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
705 RemoveEntryList (&Expression->Link);\r
706\r
707 DestroyExpression (Expression);\r
708 }\r
709\r
c60a0616 710 //\r
711 // Free Forms\r
712 //\r
713 if (FormSet->FormListHead.ForwardLink != NULL) {\r
714 while (!IsListEmpty (&FormSet->FormListHead)) {\r
715 Link = GetFirstNode (&FormSet->FormListHead);\r
716 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
717 RemoveEntryList (&Form->Link);\r
718\r
719 DestroyForm (Form);\r
720 }\r
721 }\r
722\r
723 if (FormSet->StatementBuffer != NULL) {\r
724 FreePool (FormSet->StatementBuffer);\r
725 }\r
726 if (FormSet->ExpressionBuffer != NULL) {\r
727 FreePool (FormSet->ExpressionBuffer);\r
728 }\r
729\r
730 FreePool (FormSet);\r
731}\r
732\r
733\r
734/**\r
735 Tell whether this Operand is an Expression OpCode or not\r
736\r
737 @param Operand Operand of an IFR OpCode.\r
738\r
739 @retval TRUE This is an Expression OpCode.\r
740 @retval FALSE Not an Expression OpCode.\r
741\r
742**/\r
743BOOLEAN\r
744IsExpressionOpCode (\r
745 IN UINT8 Operand\r
746 )\r
747{\r
748 if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||\r
749 ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||\r
750 (Operand == EFI_IFR_CATENATE_OP) ||\r
751 (Operand == EFI_IFR_TO_LOWER_OP) ||\r
752 (Operand == EFI_IFR_TO_UPPER_OP) ||\r
cbf73e50 753 (Operand == EFI_IFR_VERSION_OP) ||\r
754 (Operand == EFI_IFR_SECURITY_OP)) {\r
c60a0616 755 return TRUE;\r
756 } else {\r
757 return FALSE;\r
758 }\r
759}\r
760\r
761\r
762/**\r
763 Calculate number of Statemens(Questions) and Expression OpCodes.\r
764\r
765 @param FormSet The FormSet to be counted.\r
766 @param NumberOfStatement Number of Statemens(Questions)\r
767 @param NumberOfExpression Number of Expression OpCodes\r
768\r
769**/\r
770VOID\r
771CountOpCodes (\r
772 IN FORM_BROWSER_FORMSET *FormSet,\r
773 IN OUT UINT16 *NumberOfStatement,\r
774 IN OUT UINT16 *NumberOfExpression\r
775 )\r
776{\r
777 UINT16 StatementCount;\r
778 UINT16 ExpressionCount;\r
779 UINT8 *OpCodeData;\r
780 UINTN Offset;\r
781 UINTN OpCodeLen;\r
782\r
783 Offset = 0;\r
784 StatementCount = 0;\r
785 ExpressionCount = 0;\r
786\r
787 while (Offset < FormSet->IfrBinaryLength) {\r
788 OpCodeData = FormSet->IfrBinaryData + Offset;\r
789 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
790 Offset += OpCodeLen;\r
791\r
792 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {\r
793 ExpressionCount++;\r
794 } else {\r
795 StatementCount++;\r
796 }\r
797 }\r
798\r
799 *NumberOfStatement = StatementCount;\r
800 *NumberOfExpression = ExpressionCount;\r
801}\r
802\r
803\r
804\r
805/**\r
806 Parse opcodes in the formset IFR binary.\r
807\r
808 @param FormSet Pointer of the FormSet data structure.\r
809\r
810 @retval EFI_SUCCESS Opcode parse success.\r
811 @retval Other Opcode parse fail.\r
812\r
813**/\r
814EFI_STATUS\r
815ParseOpCodes (\r
816 IN FORM_BROWSER_FORMSET *FormSet\r
817 )\r
818{\r
819 EFI_STATUS Status;\r
820 UINT16 Index;\r
821 FORM_BROWSER_FORM *CurrentForm;\r
822 FORM_BROWSER_STATEMENT *CurrentStatement;\r
823 EXPRESSION_OPCODE *ExpressionOpCode;\r
824 FORM_EXPRESSION *CurrentExpression;\r
825 UINT8 Operand;\r
826 UINT8 Scope;\r
827 UINTN OpCodeOffset;\r
828 UINTN OpCodeLength;\r
829 UINT8 *OpCodeData;\r
830 UINT8 ScopeOpCode;\r
831 FORMSET_STORAGE *Storage;\r
832 FORMSET_DEFAULTSTORE *DefaultStore;\r
833 QUESTION_DEFAULT *CurrentDefault;\r
834 QUESTION_OPTION *CurrentOption;\r
d02847d3 835 UINT8 Width;\r
c60a0616 836 CHAR8 *AsciiString;\r
837 UINT16 NumberOfStatement;\r
838 UINT16 NumberOfExpression;\r
839 EFI_IMAGE_ID *ImageId;\r
0c66bc76 840 BOOLEAN SuppressForQuestion;\r
c60a0616 841 BOOLEAN SuppressForOption;\r
842 BOOLEAN InScopeOptionSuppress;\r
843 FORM_EXPRESSION *OptionSuppressExpression;\r
0c66bc76
LG
844 BOOLEAN InScopeFormSuppress;\r
845 FORM_EXPRESSION *FormSuppressExpression;\r
c60a0616 846 UINT16 DepthOfDisable;\r
847 BOOLEAN OpCodeDisabled;\r
848 BOOLEAN SingleOpCodeExpression;\r
849 BOOLEAN InScopeDefault;\r
850 EFI_HII_VALUE *Value;\r
851\r
852 mInScopeSubtitle = FALSE;\r
0c66bc76 853 SuppressForQuestion = FALSE;\r
c60a0616 854 SuppressForOption = FALSE;\r
0c66bc76 855 InScopeFormSuppress = FALSE;\r
c60a0616 856 mInScopeSuppress = FALSE;\r
857 InScopeOptionSuppress = FALSE;\r
858 mInScopeGrayOut = FALSE;\r
0a1147ed 859 mInScopeDisable = FALSE;\r
c60a0616 860 DepthOfDisable = 0;\r
861 OpCodeDisabled = FALSE;\r
862 SingleOpCodeExpression = FALSE;\r
863 InScopeDefault = FALSE;\r
864 CurrentExpression = NULL;\r
865 CurrentDefault = NULL;\r
866 CurrentOption = NULL;\r
867 OptionSuppressExpression = NULL;\r
0c66bc76 868 FormSuppressExpression = NULL;\r
c410589e 869 ImageId = NULL;\r
c60a0616 870\r
871 //\r
872 // Get the number of Statements and Expressions\r
873 //\r
874 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);\r
875\r
876 mStatementIndex = 0;\r
877 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));\r
878 if (FormSet->StatementBuffer == NULL) {\r
879 return EFI_OUT_OF_RESOURCES;\r
880 }\r
881\r
882 mExpressionOpCodeIndex = 0;\r
883 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));\r
884 if (FormSet->ExpressionBuffer == NULL) {\r
885 return EFI_OUT_OF_RESOURCES;\r
886 }\r
887\r
888 InitializeListHead (&FormSet->StorageListHead);\r
889 InitializeListHead (&FormSet->DefaultStoreListHead);\r
890 InitializeListHead (&FormSet->FormListHead);\r
891\r
892 CurrentForm = NULL;\r
893 CurrentStatement = NULL;\r
894\r
895 ResetScopeStack ();\r
896\r
897 OpCodeOffset = 0;\r
898 while (OpCodeOffset < FormSet->IfrBinaryLength) {\r
899 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;\r
900\r
901 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
902 OpCodeOffset += OpCodeLength;\r
903 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
904 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;\r
905\r
906 //\r
907 // If scope bit set, push onto scope stack\r
908 //\r
909 if (Scope != 0) {\r
910 PushScope (Operand);\r
911 }\r
912\r
913 if (OpCodeDisabled) {\r
914 //\r
915 // DisableIf Expression is evaluated to be TRUE, try to find its end.\r
916 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END\r
917 //\r
918 if (Operand == EFI_IFR_DISABLE_IF_OP) {\r
919 DepthOfDisable++;\r
920 } else if (Operand == EFI_IFR_END_OP) {\r
921 Status = PopScope (&ScopeOpCode);\r
922 if (EFI_ERROR (Status)) {\r
923 return Status;\r
924 }\r
925\r
926 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {\r
927 if (DepthOfDisable == 0) {\r
0a1147ed 928 mInScopeDisable = FALSE;\r
c60a0616 929 OpCodeDisabled = FALSE;\r
930 } else {\r
931 DepthOfDisable--;\r
932 }\r
933 }\r
934 }\r
935 continue;\r
936 }\r
937\r
938 if (IsExpressionOpCode (Operand)) {\r
939 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];\r
940 mExpressionOpCodeIndex++;\r
941\r
942 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;\r
943 ExpressionOpCode->Operand = Operand;\r
944 Value = &ExpressionOpCode->Value;\r
945\r
946 switch (Operand) {\r
947 case EFI_IFR_EQ_ID_VAL_OP:\r
948 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
949\r
950 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
951 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));\r
952 break;\r
953\r
954 case EFI_IFR_EQ_ID_ID_OP:\r
955 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));\r
956 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));\r
957 break;\r
958\r
959 case EFI_IFR_EQ_ID_LIST_OP:\r
2654f642 960 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
961 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));\r
962 ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);\r
c60a0616 963 break;\r
964\r
965 case EFI_IFR_TO_STRING_OP:\r
966 case EFI_IFR_FIND_OP:\r
967 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;\r
968 break;\r
969\r
970 case EFI_IFR_STRING_REF1_OP:\r
971 Value->Type = EFI_IFR_TYPE_STRING;\r
972 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));\r
973 break;\r
974\r
975 case EFI_IFR_RULE_REF_OP:\r
976 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;\r
977 break;\r
978\r
979 case EFI_IFR_SPAN_OP:\r
980 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;\r
981 break;\r
982\r
983 case EFI_IFR_THIS_OP:\r
d0720b57 984 ASSERT (CurrentStatement != NULL);\r
c60a0616 985 ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;\r
986 break;\r
987\r
cbf73e50 988 case EFI_IFR_SECURITY_OP:\r
989 CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));\r
990 break;\r
991\r
c60a0616 992 case EFI_IFR_QUESTION_REF1_OP:\r
2654f642 993 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
c60a0616 994 break;\r
995\r
996 case EFI_IFR_QUESTION_REF3_OP:\r
997 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {\r
998 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
999\r
1000 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {\r
1001 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
1002 }\r
1003 }\r
1004 break;\r
1005\r
1006 //\r
1007 // constant\r
1008 //\r
1009 case EFI_IFR_TRUE_OP:\r
1010 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1011 Value->Value.b = TRUE;\r
1012 break;\r
1013\r
1014 case EFI_IFR_FALSE_OP:\r
1015 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1016 Value->Value.b = FALSE;\r
1017 break;\r
1018\r
1019 case EFI_IFR_ONE_OP:\r
1020 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1021 Value->Value.u8 = 1;\r
1022 break;\r
1023\r
1024 case EFI_IFR_ZERO_OP:\r
1025 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1026 Value->Value.u8 = 0;\r
1027 break;\r
1028\r
1029 case EFI_IFR_ONES_OP:\r
1030 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1031 Value->Value.u64 = 0xffffffffffffffffULL;\r
1032 break;\r
1033\r
1034 case EFI_IFR_UINT8_OP:\r
1035 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1036 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;\r
1037 break;\r
1038\r
1039 case EFI_IFR_UINT16_OP:\r
1040 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
1041 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));\r
1042 break;\r
1043\r
1044 case EFI_IFR_UINT32_OP:\r
1045 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
1046 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));\r
1047 break;\r
1048\r
1049 case EFI_IFR_UINT64_OP:\r
1050 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1051 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));\r
1052 break;\r
1053\r
1054 case EFI_IFR_UNDEFINED_OP:\r
d02847d3 1055 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
c60a0616 1056 break;\r
1057\r
1058 case EFI_IFR_VERSION_OP:\r
1059 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
1060 Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;\r
1061 break;\r
1062\r
1063 default:\r
1064 break;\r
1065 }\r
1066\r
f8a1c229 1067 ASSERT (CurrentExpression != NULL);\r
c60a0616 1068 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);\r
1069\r
1070 if (SingleOpCodeExpression) {\r
1071 //\r
1072 // There are two cases to indicate the end of an Expression:\r
1073 // for single OpCode expression: one Expression OpCode\r
1074 // for expression consists of more than one OpCode: EFI_IFR_END\r
1075 //\r
1076 SingleOpCodeExpression = FALSE;\r
1077\r
0a1147ed 1078 if (mInScopeDisable && CurrentForm == NULL) {\r
c60a0616 1079 //\r
0a1147ed 1080 // This is DisableIf expression for Form, it should be a constant expression\r
c60a0616 1081 //\r
1082 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);\r
1083 if (EFI_ERROR (Status)) {\r
1084 return Status;\r
1085 }\r
c410589e 1086\r
c60a0616 1087 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1088 return EFI_INVALID_PARAMETER;\r
1089 }\r
1090\r
1091 OpCodeDisabled = CurrentExpression->Result.Value.b;\r
1092 }\r
1093\r
1094 CurrentExpression = NULL;\r
1095 }\r
1096\r
1097 continue;\r
1098 }\r
1099\r
1100 //\r
1101 // Parse the Opcode\r
1102 //\r
1103 switch (Operand) {\r
1104\r
1105 case EFI_IFR_FORM_SET_OP:\r
1106 //\r
f8a1c229 1107 // Check the formset GUID\r
c60a0616 1108 //\r
1109 if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {\r
1110 return EFI_INVALID_PARAMETER;\r
1111 }\r
1112\r
1113 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));\r
1114 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));\r
0a1147ed 1115\r
d228526f
LG
1116 if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
1117 //\r
1118 // The formset OpCode contains ClassGuid\r
1119 //\r
1120 FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
1121 CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));\r
1122 }\r
0c66bc76
LG
1123\r
1124 InitializeListHead (&FormSet->ExpressionListHead);\r
c60a0616 1125 break;\r
1126\r
1127 case EFI_IFR_FORM_OP:\r
1128 //\r
1129 // Create a new Form for this FormSet\r
1130 //\r
1131 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));\r
1ac628ee 1132 ASSERT (CurrentForm != NULL);\r
c60a0616 1133 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;\r
1134 InitializeListHead (&CurrentForm->ExpressionListHead);\r
1135 InitializeListHead (&CurrentForm->StatementListHead);\r
1136\r
1137 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));\r
1138 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));\r
1139\r
0c66bc76
LG
1140 if (InScopeFormSuppress) {\r
1141 //\r
1142 // Form is inside of suppressif\r
1143 //\r
1144 CurrentForm->SuppressExpression = FormSuppressExpression;\r
1145 }\r
1146\r
1147 if (Scope != 0) {\r
1148 //\r
1149 // Enter scope of a Form, suppressif will be used for Question or Option\r
1150 //\r
1151 SuppressForQuestion = TRUE;\r
1152 }\r
1153\r
c60a0616 1154 //\r
1155 // Insert into Form list of this FormSet\r
1156 //\r
1157 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);\r
1158 break;\r
1159\r
1160 //\r
1161 // Storage\r
1162 //\r
1163 case EFI_IFR_VARSTORE_OP:\r
1164 //\r
1165 // Create a buffer Storage for this FormSet\r
1166 //\r
1167 Storage = CreateStorage (FormSet);\r
1168 Storage->Type = EFI_HII_VARSTORE_BUFFER;\r
1169\r
1170 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
1171 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
1172 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));\r
1173\r
1174 Storage->Buffer = AllocateZeroPool (Storage->Size);\r
1175 Storage->EditBuffer = AllocateZeroPool (Storage->Size);\r
1176\r
1177 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
1178 Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);\r
1179 ASSERT (Storage->Name != NULL);\r
1180 for (Index = 0; AsciiString[Index] != 0; Index++) {\r
1181 Storage->Name[Index] = (CHAR16) AsciiString[Index];\r
1182 }\r
1183\r
1184 //\r
1185 // Initialize <ConfigHdr>\r
1186 //\r
1187 InitializeConfigHdr (FormSet, Storage);\r
1188 break;\r
1189\r
1190 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
1191 //\r
1192 // Create a name/value Storage for this FormSet\r
1193 //\r
1194 Storage = CreateStorage (FormSet);\r
1195 Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
1196\r
1197 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
1198 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
1199\r
1200 //\r
1201 // Initialize <ConfigHdr>\r
1202 //\r
1203 InitializeConfigHdr (FormSet, Storage);\r
1204 break;\r
1205\r
1206 case EFI_IFR_VARSTORE_EFI_OP:\r
1207 //\r
1208 // Create a EFI variable Storage for this FormSet\r
1209 //\r
1210 Storage = CreateStorage (FormSet);\r
1211 Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;\r
1212\r
1213 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
1214 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
1215 CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));\r
1216 break;\r
1217\r
1218 //\r
1219 // DefaultStore\r
1220 //\r
1221 case EFI_IFR_DEFAULTSTORE_OP:\r
1222 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));\r
1ac628ee 1223 ASSERT (DefaultStore != NULL);\r
c60a0616 1224 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;\r
1225\r
1226 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));\r
1227 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));\r
1228\r
1229 //\r
1230 // Insert to DefaultStore list of this Formset\r
1231 //\r
1232 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);\r
1233 break;\r
1234\r
1235 //\r
1236 // Statements\r
1237 //\r
1238 case EFI_IFR_SUBTITLE_OP:\r
1239 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
bc166db3 1240 ASSERT (CurrentStatement != NULL);\r
8b0fc5c1 1241\r
c60a0616 1242 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;\r
1243\r
1244 if (Scope != 0) {\r
1245 mInScopeSubtitle = TRUE;\r
1246 }\r
1247 break;\r
1248\r
1249 case EFI_IFR_TEXT_OP:\r
1250 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
bc166db3 1251 ASSERT (CurrentStatement != NULL);\r
c60a0616 1252\r
1253 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));\r
1254 break;\r
1255\r
f8a1c229 1256 case EFI_IFR_RESET_BUTTON_OP:\r
1257 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
1258 ASSERT (CurrentStatement != NULL);\r
1259 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));\r
1260 break;\r
1261\r
c60a0616 1262 //\r
1263 // Questions\r
1264 //\r
1265 case EFI_IFR_ACTION_OP:\r
1266 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
bc166db3 1267 ASSERT (CurrentStatement != NULL);\r
d02847d3 1268 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;\r
c60a0616 1269\r
1270 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {\r
1271 //\r
1272 // No QuestionConfig present, so no configuration string will be processed\r
1273 //\r
1274 CurrentStatement->QuestionConfig = 0;\r
1275 } else {\r
1276 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));\r
1277 }\r
1278 break;\r
1279\r
c60a0616 1280 case EFI_IFR_REF_OP:\r
1281 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
b347c1bc 1282 ASSERT (CurrentStatement != NULL);\r
d02847d3 1283 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_UNDEFINED;\r
c60a0616 1284 CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));\r
1285 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {\r
1286 CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
1287\r
1288 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {\r
1289 CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));\r
1290\r
1291 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {\r
1292 CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
1293 }\r
1294 }\r
1295 }\r
1296 break;\r
1297\r
1298 case EFI_IFR_ONE_OF_OP:\r
1299 case EFI_IFR_NUMERIC_OP:\r
1300 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
945e3aed 1301 ASSERT(CurrentStatement != NULL);\r
8b0fc5c1 1302\r
c60a0616 1303 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;\r
1304 Value = &CurrentStatement->HiiValue;\r
1305\r
1306 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1307 case EFI_IFR_NUMERIC_SIZE_1:\r
1308 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;\r
1309 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;\r
1310 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;\r
1311 CurrentStatement->StorageWidth = sizeof (UINT8);\r
1312 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1313 break;\r
1314\r
1315 case EFI_IFR_NUMERIC_SIZE_2:\r
1316 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));\r
1317 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));\r
1318 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));\r
1319 CurrentStatement->StorageWidth = sizeof (UINT16);\r
1320 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
1321 break;\r
1322\r
1323 case EFI_IFR_NUMERIC_SIZE_4:\r
1324 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));\r
1325 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));\r
1326 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));\r
1327 CurrentStatement->StorageWidth = sizeof (UINT32);\r
1328 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
1329 break;\r
1330\r
1331 case EFI_IFR_NUMERIC_SIZE_8:\r
1332 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));\r
1333 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));\r
1334 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));\r
1335 CurrentStatement->StorageWidth = sizeof (UINT64);\r
1336 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1337 break;\r
1338\r
1339 default:\r
1340 break;\r
1341 }\r
1342\r
1343 InitializeRequestElement (FormSet, CurrentStatement);\r
1344\r
1345 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {\r
1346 SuppressForOption = TRUE;\r
1347 }\r
1348 break;\r
1349\r
1350 case EFI_IFR_ORDERED_LIST_OP:\r
1351 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
b347c1bc 1352 ASSERT(CurrentStatement != NULL);\r
8b0fc5c1 1353\r
c60a0616 1354 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;\r
1355 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
c60a0616 1356\r
d02847d3 1357 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;\r
b86b413a 1358 CurrentStatement->BufferValue = NULL;\r
c60a0616 1359\r
1360 if (Scope != 0) {\r
1361 SuppressForOption = TRUE;\r
1362 }\r
1363 break;\r
1364\r
1365 case EFI_IFR_CHECKBOX_OP:\r
1366 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
b347c1bc 1367 ASSERT(CurrentStatement != NULL);\r
8b0fc5c1 1368\r
c60a0616 1369 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;\r
1370 CurrentStatement->StorageWidth = sizeof (BOOLEAN);\r
1371 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;\r
1372\r
1373 InitializeRequestElement (FormSet, CurrentStatement);\r
1374\r
1375 break;\r
1376\r
1377 case EFI_IFR_STRING_OP:\r
1378 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
b347c1bc 1379 ASSERT (CurrentStatement != NULL);\r
c60a0616 1380 //\r
1381 // MinSize is the minimum number of characters that can be accepted for this opcode,\r
1382 // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
1383 // The characters are stored as Unicode, so the storage width should multiply 2.\r
1384 //\r
1385 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;\r
1386 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;\r
1387 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));\r
1388 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;\r
1389\r
1390 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;\r
1391 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));\r
1392\r
1393 InitializeRequestElement (FormSet, CurrentStatement);\r
1394 break;\r
1395\r
1396 case EFI_IFR_PASSWORD_OP:\r
1397 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
b347c1bc 1398 ASSERT (CurrentStatement != NULL);\r
c60a0616 1399 //\r
1400 // MinSize is the minimum number of characters that can be accepted for this opcode,\r
1401 // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
1402 // The characters are stored as Unicode, so the storage width should multiply 2.\r
1403 //\r
1404 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));\r
1405 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));\r
1406 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));\r
1407\r
1408 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;\r
1409 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));\r
1410\r
1411 InitializeRequestElement (FormSet, CurrentStatement);\r
1412 break;\r
1413\r
1414 case EFI_IFR_DATE_OP:\r
1415 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
b347c1bc 1416 ASSERT(CurrentStatement != NULL);\r
8b0fc5c1 1417\r
c60a0616 1418 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;\r
1419 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;\r
1420\r
1421 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {\r
1422 CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);\r
1423\r
1424 InitializeRequestElement (FormSet, CurrentStatement);\r
1425 } else {\r
1426 //\r
1427 // Don't assign storage for RTC type of date/time\r
1428 //\r
1429 CurrentStatement->Storage = NULL;\r
1430 CurrentStatement->StorageWidth = 0;\r
1431 }\r
1432 break;\r
1433\r
1434 case EFI_IFR_TIME_OP:\r
1435 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
b347c1bc 1436 ASSERT(CurrentStatement != NULL);\r
8b0fc5c1 1437\r
c60a0616 1438 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;\r
1439 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;\r
1440\r
1441 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {\r
1442 CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);\r
1443\r
1444 InitializeRequestElement (FormSet, CurrentStatement);\r
1445 } else {\r
1446 //\r
1447 // Don't assign storage for RTC type of date/time\r
1448 //\r
1449 CurrentStatement->Storage = NULL;\r
1450 CurrentStatement->StorageWidth = 0;\r
1451 }\r
1452 break;\r
1453\r
1454 //\r
1455 // Default\r
1456 //\r
1457 case EFI_IFR_DEFAULT_OP:\r
1458 //\r
1459 // EFI_IFR_DEFAULT appear in scope of a Question,\r
1460 // It creates a default value for the current question.\r
1461 // A Question may have more than one Default value which have different default types.\r
1462 //\r
1463 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));\r
1ac628ee 1464 ASSERT (CurrentDefault != NULL);\r
c60a0616 1465 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;\r
1466\r
1467 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;\r
1468 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));\r
1469 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
1470 ExtendValueToU64 (&CurrentDefault->Value);\r
1471\r
1472 //\r
1473 // Insert to Default Value list of current Question\r
1474 //\r
1475 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);\r
1476\r
1477 if (Scope != 0) {\r
1478 InScopeDefault = TRUE;\r
1479 }\r
1480 break;\r
1481\r
1482 //\r
1483 // Option\r
1484 //\r
1485 case EFI_IFR_ONE_OF_OPTION_OP:\r
1486 //\r
1487 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.\r
1488 // It create a selection for use in current Question.\r
1489 //\r
1490 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));\r
1ac628ee 1491 ASSERT (CurrentOption != NULL);\r
c60a0616 1492 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;\r
1493\r
1494 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;\r
1495 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;\r
1496 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));\r
1497 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
1498 ExtendValueToU64 (&CurrentOption->Value);\r
1499\r
1500 if (InScopeOptionSuppress) {\r
1501 CurrentOption->SuppressExpression = OptionSuppressExpression;\r
1502 }\r
1503\r
1504 //\r
1505 // Insert to Option list of current Question\r
1506 //\r
1507 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);\r
d02847d3 1508\r
1509 //\r
1510 // Now we know the Storage width of nested Ordered List\r
1511 //\r
1b2bf3ca 1512 ASSERT (CurrentStatement != NULL);\r
d02847d3 1513 if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) {\r
1514 Width = 1;\r
1515 switch (CurrentOption->Value.Type) {\r
1516 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1517 Width = 1;\r
1518 break;\r
1519\r
1520 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1521 Width = 2;\r
1522 break;\r
1523\r
1524 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1525 Width = 4;\r
1526 break;\r
1527\r
1528 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1529 Width = 8;\r
1530 break;\r
1531\r
1532 default:\r
1533 //\r
1534 // Invalid type for Ordered List\r
1535 //\r
1536 break;\r
1537 }\r
1538\r
1539 CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width);\r
1540 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);\r
1541 CurrentStatement->ValueType = CurrentOption->Value.Type;\r
1542\r
1543 InitializeRequestElement (FormSet, CurrentStatement);\r
1544 }\r
c60a0616 1545 break;\r
1546\r
1547 //\r
1548 // Conditional\r
1549 //\r
1550 case EFI_IFR_NO_SUBMIT_IF_OP:\r
1551 case EFI_IFR_INCONSISTENT_IF_OP:\r
1552 //\r
1553 // Create an Expression node\r
1554 //\r
1555 CurrentExpression = CreateExpression (CurrentForm);\r
1556 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));\r
1557\r
1558 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {\r
1559 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;\r
1560 InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);\r
1561 } else {\r
1562 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;\r
1563 InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);\r
1564 }\r
0c66bc76
LG
1565\r
1566 //\r
1567 // Take a look at next OpCode to see whether current expression consists\r
1568 // of single OpCode\r
1569 //\r
1570 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
1571 SingleOpCodeExpression = TRUE;\r
1572 }\r
c60a0616 1573 break;\r
1574\r
1575 case EFI_IFR_SUPPRESS_IF_OP:\r
1576 //\r
1577 // Question and Option will appear in scope of this OpCode\r
1578 //\r
1579 CurrentExpression = CreateExpression (CurrentForm);\r
1580 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;\r
0c66bc76
LG
1581\r
1582 if (CurrentForm == NULL) {\r
1583 InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);\r
1584 } else {\r
1585 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
1586 }\r
c60a0616 1587\r
1588 if (SuppressForOption) {\r
1589 InScopeOptionSuppress = TRUE;\r
1590 OptionSuppressExpression = CurrentExpression;\r
0c66bc76 1591 } else if (SuppressForQuestion) {\r
c60a0616 1592 mInScopeSuppress = TRUE;\r
1593 mSuppressExpression = CurrentExpression;\r
0c66bc76
LG
1594 } else {\r
1595 InScopeFormSuppress = TRUE;\r
1596 FormSuppressExpression = CurrentExpression;\r
1597 }\r
1598\r
1599 //\r
1600 // Take a look at next OpCode to see whether current expression consists\r
1601 // of single OpCode\r
1602 //\r
1603 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
1604 SingleOpCodeExpression = TRUE;\r
c60a0616 1605 }\r
1606 break;\r
1607\r
1608 case EFI_IFR_GRAY_OUT_IF_OP:\r
1609 //\r
1610 // Questions will appear in scope of this OpCode\r
1611 //\r
1612 CurrentExpression = CreateExpression (CurrentForm);\r
1613 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;\r
1614 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
1615\r
1616 mInScopeGrayOut = TRUE;\r
1617 mGrayOutExpression = CurrentExpression;\r
0c66bc76
LG
1618\r
1619 //\r
1620 // Take a look at next OpCode to see whether current expression consists\r
1621 // of single OpCode\r
1622 //\r
1623 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
1624 SingleOpCodeExpression = TRUE;\r
1625 }\r
c60a0616 1626 break;\r
1627\r
1628 case EFI_IFR_DISABLE_IF_OP:\r
1629 //\r
1630 // The DisableIf expression should only rely on constant, so it could be\r
1631 // evaluated at initialization and it will not be queued\r
1632 //\r
1633 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));\r
1ac628ee 1634 ASSERT (CurrentExpression != NULL);\r
c60a0616 1635 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;\r
1636 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;\r
1637 InitializeListHead (&CurrentExpression->OpCodeListHead);\r
1638\r
0a1147ed
LG
1639 if (CurrentForm != NULL) {\r
1640 //\r
1641 // This is DisableIf for Question, enqueue it to Form expression list\r
1642 //\r
1643 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
1644 }\r
1645\r
1646 mDisableExpression = CurrentExpression;\r
1647 mInScopeDisable = TRUE;\r
1648 OpCodeDisabled = FALSE;\r
c60a0616 1649\r
1650 //\r
1651 // Take a look at next OpCode to see whether current expression consists\r
1652 // of single OpCode\r
1653 //\r
1654 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
1655 SingleOpCodeExpression = TRUE;\r
1656 }\r
1657 break;\r
1658\r
1659 //\r
1660 // Expression\r
1661 //\r
1662 case EFI_IFR_VALUE_OP:\r
1663 CurrentExpression = CreateExpression (CurrentForm);\r
1664 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;\r
1665 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
1666\r
1667 if (InScopeDefault) {\r
1668 //\r
1669 // Used for default (EFI_IFR_DEFAULT)\r
1670 //\r
1671 CurrentDefault->ValueExpression = CurrentExpression;\r
1672 } else {\r
1673 //\r
1674 // If used for a question, then the question will be read-only\r
1675 //\r
bc166db3 1676 //\r
1677 // Make sure CurrentStatement is not NULL.\r
1678 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
1679 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.\r
1680 //\r
1681 ASSERT (CurrentStatement != NULL);\r
c60a0616 1682 CurrentStatement->ValueExpression = CurrentExpression;\r
1683 }\r
0c66bc76
LG
1684\r
1685 //\r
1686 // Take a look at next OpCode to see whether current expression consists\r
1687 // of single OpCode\r
1688 //\r
1689 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
1690 SingleOpCodeExpression = TRUE;\r
1691 }\r
c60a0616 1692 break;\r
1693\r
1694 case EFI_IFR_RULE_OP:\r
1695 CurrentExpression = CreateExpression (CurrentForm);\r
1696 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;\r
1697\r
1698 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;\r
1699 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
0c66bc76
LG
1700\r
1701 //\r
1702 // Take a look at next OpCode to see whether current expression consists\r
1703 // of single OpCode\r
1704 //\r
1705 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
1706 SingleOpCodeExpression = TRUE;\r
1707 }\r
c60a0616 1708 break;\r
1709\r
1710 //\r
1711 // Image\r
1712 //\r
1713 case EFI_IFR_IMAGE_OP:\r
1714 //\r
1715 // Get ScopeOpcode from top of stack\r
1716 //\r
1717 PopScope (&ScopeOpCode);\r
1718 PushScope (ScopeOpCode);\r
1719\r
1720 switch (ScopeOpCode) {\r
1721 case EFI_IFR_FORM_SET_OP:\r
1722 ImageId = &FormSet->ImageId;\r
1723 break;\r
1724\r
1725 case EFI_IFR_FORM_OP:\r
d0720b57 1726 ASSERT (CurrentForm != NULL);\r
c60a0616 1727 ImageId = &CurrentForm->ImageId;\r
1728 break;\r
1729\r
1730 case EFI_IFR_ONE_OF_OPTION_OP:\r
1731 ImageId = &CurrentOption->ImageId;\r
1732 break;\r
1733\r
1734 default:\r
bc166db3 1735 //\r
1736 // Make sure CurrentStatement is not NULL.\r
1737 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
1738 // file is wrongly generated by tools such as VFR Compiler.\r
1739 //\r
1740 ASSERT (CurrentStatement != NULL);\r
c60a0616 1741 ImageId = &CurrentStatement->ImageId;\r
1742 break;\r
1743 }\r
1744\r
c410589e 1745 ASSERT (ImageId != NULL);\r
c60a0616 1746 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));\r
1747 break;\r
1748\r
1749 //\r
1750 // Refresh\r
1751 //\r
1752 case EFI_IFR_REFRESH_OP:\r
c410589e 1753 ASSERT (CurrentStatement != NULL);\r
c60a0616 1754 CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;\r
1755 break;\r
1756\r
1757 //\r
1758 // Vendor specific\r
1759 //\r
1760 case EFI_IFR_GUID_OP:\r
5c526736 1761 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
c60a0616 1762 //\r
1763 // Tiano specific GUIDed opcodes\r
1764 //\r
1765 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
1766 case EFI_IFR_EXTEND_OP_LABEL:\r
1767 //\r
1768 // just ignore label\r
1769 //\r
1770 break;\r
1771\r
1772 case EFI_IFR_EXTEND_OP_BANNER:\r
0a1147ed 1773 //\r
b9e388d2 1774 // By SubClass to get Banner Data from Front Page\r
0a1147ed 1775 //\r
c60a0616 1776 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
1777 CopyMem (\r
0a1147ed 1778 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][\r
c60a0616 1779 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],\r
1780 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,\r
1781 sizeof (EFI_STRING_ID)\r
1782 );\r
1783 }\r
1784 break;\r
1785\r
1786 case EFI_IFR_EXTEND_OP_CLASS:\r
1787 CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));\r
1788 break;\r
1789\r
1790 case EFI_IFR_EXTEND_OP_SUBCLASS:\r
1791 CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));\r
1792 break;\r
1793\r
1794 default:\r
1795 break;\r
1796 }\r
1797 }\r
1798\r
1799 break;\r
1800\r
1801 //\r
1802 // Scope End\r
1803 //\r
1804 case EFI_IFR_END_OP:\r
1805 Status = PopScope (&ScopeOpCode);\r
1806 if (EFI_ERROR (Status)) {\r
1807 ResetScopeStack ();\r
1808 return Status;\r
1809 }\r
1810\r
1811 switch (ScopeOpCode) {\r
1812 case EFI_IFR_FORM_SET_OP:\r
1813 //\r
1814 // End of FormSet, update FormSet IFR binary length\r
1815 // to stop parsing substantial OpCodes\r
1816 //\r
1817 FormSet->IfrBinaryLength = OpCodeOffset;\r
1818 break;\r
1819\r
1820 case EFI_IFR_FORM_OP:\r
1821 //\r
1822 // End of Form\r
1823 //\r
1824 CurrentForm = NULL;\r
0c66bc76 1825 SuppressForQuestion = FALSE;\r
c60a0616 1826 break;\r
1827\r
1828 case EFI_IFR_ONE_OF_OPTION_OP:\r
1829 //\r
1830 // End of Option\r
1831 //\r
1832 CurrentOption = NULL;\r
1833 break;\r
1834\r
1835 case EFI_IFR_SUBTITLE_OP:\r
1836 mInScopeSubtitle = FALSE;\r
1837 break;\r
1838\r
1839 case EFI_IFR_NO_SUBMIT_IF_OP:\r
1840 case EFI_IFR_INCONSISTENT_IF_OP:\r
1841 //\r
1842 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF\r
1843 //\r
1844 break;\r
1845\r
1846 case EFI_IFR_SUPPRESS_IF_OP:\r
1847 if (SuppressForOption) {\r
1848 InScopeOptionSuppress = FALSE;\r
0c66bc76 1849 } else if (SuppressForQuestion) {\r
c60a0616 1850 mInScopeSuppress = FALSE;\r
0c66bc76
LG
1851 } else {\r
1852 InScopeFormSuppress = FALSE;\r
c60a0616 1853 }\r
1854 break;\r
1855\r
1856 case EFI_IFR_GRAY_OUT_IF_OP:\r
1857 mInScopeGrayOut = FALSE;\r
1858 break;\r
1859\r
1860 case EFI_IFR_DISABLE_IF_OP:\r
0a1147ed 1861 mInScopeDisable = FALSE;\r
c60a0616 1862 OpCodeDisabled = FALSE;\r
1863 break;\r
1864\r
1865 case EFI_IFR_ONE_OF_OP:\r
1866 case EFI_IFR_ORDERED_LIST_OP:\r
1867 SuppressForOption = FALSE;\r
1868 break;\r
1869\r
1870 case EFI_IFR_DEFAULT_OP:\r
1871 InScopeDefault = FALSE;\r
1872 break;\r
1873\r
1874 default:\r
1875 if (IsExpressionOpCode (ScopeOpCode)) {\r
0a1147ed 1876 if (mInScopeDisable && CurrentForm == NULL) {\r
c60a0616 1877 //\r
0a1147ed 1878 // This is DisableIf expression for Form, it should be a constant expression\r
c60a0616 1879 //\r
f8a1c229 1880 ASSERT (CurrentExpression != NULL);\r
c60a0616 1881 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);\r
1882 if (EFI_ERROR (Status)) {\r
1883 return Status;\r
1884 }\r
a935a0d8 1885\r
c60a0616 1886 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1887 return EFI_INVALID_PARAMETER;\r
1888 }\r
1889\r
1890 OpCodeDisabled = CurrentExpression->Result.Value.b;\r
1891 //\r
1892 // DisableIf Expression is only used once and not quequed, free it\r
1893 //\r
1894 DestroyExpression (CurrentExpression);\r
1895 }\r
1896\r
1897 //\r
1898 // End of current Expression\r
1899 //\r
1900 CurrentExpression = NULL;\r
1901 }\r
1902 break;\r
1903 }\r
1904 break;\r
1905\r
1906 default:\r
1907 break;\r
1908 }\r
1909 }\r
1910\r
1911 return EFI_SUCCESS;\r
1912}\r