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