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