]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
1. Code clean up: add IN/OUT modifier for parameters.
[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 IN 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 UINT8 Width;
814 CHAR8 *AsciiString;
815 UINT16 NumberOfStatement;
816 UINT16 NumberOfExpression;
817 EFI_IMAGE_ID *ImageId;
818 BOOLEAN SuppressForOption;
819 BOOLEAN InScopeOptionSuppress;
820 FORM_EXPRESSION *OptionSuppressExpression;
821 UINT16 DepthOfDisable;
822 BOOLEAN OpCodeDisabled;
823 BOOLEAN SingleOpCodeExpression;
824 BOOLEAN InScopeDefault;
825 EFI_HII_VALUE *Value;
826
827 mInScopeSubtitle = FALSE;
828 SuppressForOption = FALSE;
829 mInScopeSuppress = FALSE;
830 InScopeOptionSuppress = FALSE;
831 mInScopeGrayOut = FALSE;
832 mInScopeDisable = FALSE;
833 DepthOfDisable = 0;
834 OpCodeDisabled = FALSE;
835 SingleOpCodeExpression = FALSE;
836 InScopeDefault = FALSE;
837 CurrentExpression = NULL;
838 CurrentDefault = NULL;
839 CurrentOption = NULL;
840 OptionSuppressExpression = NULL;
841 ImageId = NULL;
842
843 //
844 // Get the number of Statements and Expressions
845 //
846 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
847
848 mStatementIndex = 0;
849 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
850 if (FormSet->StatementBuffer == NULL) {
851 return EFI_OUT_OF_RESOURCES;
852 }
853
854 mExpressionOpCodeIndex = 0;
855 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
856 if (FormSet->ExpressionBuffer == NULL) {
857 return EFI_OUT_OF_RESOURCES;
858 }
859
860 InitializeListHead (&FormSet->StorageListHead);
861 InitializeListHead (&FormSet->DefaultStoreListHead);
862 InitializeListHead (&FormSet->FormListHead);
863
864 CurrentForm = NULL;
865 CurrentStatement = NULL;
866
867 ResetScopeStack ();
868
869 OpCodeOffset = 0;
870 while (OpCodeOffset < FormSet->IfrBinaryLength) {
871 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
872
873 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
874 OpCodeOffset += OpCodeLength;
875 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
876 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
877
878 //
879 // If scope bit set, push onto scope stack
880 //
881 if (Scope != 0) {
882 PushScope (Operand);
883 }
884
885 if (OpCodeDisabled) {
886 //
887 // DisableIf Expression is evaluated to be TRUE, try to find its end.
888 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
889 //
890 if (Operand == EFI_IFR_DISABLE_IF_OP) {
891 DepthOfDisable++;
892 } else if (Operand == EFI_IFR_END_OP) {
893 Status = PopScope (&ScopeOpCode);
894 if (EFI_ERROR (Status)) {
895 return Status;
896 }
897
898 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
899 if (DepthOfDisable == 0) {
900 mInScopeDisable = FALSE;
901 OpCodeDisabled = FALSE;
902 } else {
903 DepthOfDisable--;
904 }
905 }
906 }
907 continue;
908 }
909
910 if (IsExpressionOpCode (Operand)) {
911 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
912 mExpressionOpCodeIndex++;
913
914 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
915 ExpressionOpCode->Operand = Operand;
916 Value = &ExpressionOpCode->Value;
917
918 switch (Operand) {
919 case EFI_IFR_EQ_ID_VAL_OP:
920 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
921
922 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
923 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
924 break;
925
926 case EFI_IFR_EQ_ID_ID_OP:
927 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
928 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
929 break;
930
931 case EFI_IFR_EQ_ID_LIST_OP:
932 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
933 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
934 ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
935 break;
936
937 case EFI_IFR_TO_STRING_OP:
938 case EFI_IFR_FIND_OP:
939 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
940 break;
941
942 case EFI_IFR_STRING_REF1_OP:
943 Value->Type = EFI_IFR_TYPE_STRING;
944 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
945 break;
946
947 case EFI_IFR_RULE_REF_OP:
948 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
949 break;
950
951 case EFI_IFR_SPAN_OP:
952 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
953 break;
954
955 case EFI_IFR_THIS_OP:
956 ASSERT (CurrentStatement != NULL);
957 ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
958 break;
959
960 case EFI_IFR_QUESTION_REF1_OP:
961 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
962 break;
963
964 case EFI_IFR_QUESTION_REF3_OP:
965 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
966 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
967
968 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
969 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
970 }
971 }
972 break;
973
974 //
975 // constant
976 //
977 case EFI_IFR_TRUE_OP:
978 Value->Type = EFI_IFR_TYPE_BOOLEAN;
979 Value->Value.b = TRUE;
980 break;
981
982 case EFI_IFR_FALSE_OP:
983 Value->Type = EFI_IFR_TYPE_BOOLEAN;
984 Value->Value.b = FALSE;
985 break;
986
987 case EFI_IFR_ONE_OP:
988 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
989 Value->Value.u8 = 1;
990 break;
991
992 case EFI_IFR_ZERO_OP:
993 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
994 Value->Value.u8 = 0;
995 break;
996
997 case EFI_IFR_ONES_OP:
998 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
999 Value->Value.u64 = 0xffffffffffffffffULL;
1000 break;
1001
1002 case EFI_IFR_UINT8_OP:
1003 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1004 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
1005 break;
1006
1007 case EFI_IFR_UINT16_OP:
1008 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1009 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
1010 break;
1011
1012 case EFI_IFR_UINT32_OP:
1013 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1014 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
1015 break;
1016
1017 case EFI_IFR_UINT64_OP:
1018 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1019 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
1020 break;
1021
1022 case EFI_IFR_UNDEFINED_OP:
1023 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1024 break;
1025
1026 case EFI_IFR_VERSION_OP:
1027 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1028 Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
1029 break;
1030
1031 default:
1032 break;
1033 }
1034
1035 ASSERT (CurrentExpression != NULL);
1036 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
1037
1038 if (SingleOpCodeExpression) {
1039 //
1040 // There are two cases to indicate the end of an Expression:
1041 // for single OpCode expression: one Expression OpCode
1042 // for expression consists of more than one OpCode: EFI_IFR_END
1043 //
1044 SingleOpCodeExpression = FALSE;
1045
1046 if (mInScopeDisable && CurrentForm == NULL) {
1047 //
1048 // This is DisableIf expression for Form, it should be a constant expression
1049 //
1050 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1051 if (EFI_ERROR (Status)) {
1052 return Status;
1053 }
1054
1055 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1056 return EFI_INVALID_PARAMETER;
1057 }
1058
1059 OpCodeDisabled = CurrentExpression->Result.Value.b;
1060 }
1061
1062 CurrentExpression = NULL;
1063 }
1064
1065 continue;
1066 }
1067
1068 //
1069 // Parse the Opcode
1070 //
1071 switch (Operand) {
1072
1073 case EFI_IFR_FORM_SET_OP:
1074 //
1075 // Check the formset GUID
1076 //
1077 if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1078 return EFI_INVALID_PARAMETER;
1079 }
1080
1081 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1082 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
1083
1084 //
1085 // The formset OpCode contains ClassGuid
1086 //
1087 FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
1088 CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
1089 break;
1090
1091 case EFI_IFR_FORM_OP:
1092 //
1093 // Create a new Form for this FormSet
1094 //
1095 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1096 ASSERT (CurrentForm != NULL);
1097 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1098 InitializeListHead (&CurrentForm->ExpressionListHead);
1099 InitializeListHead (&CurrentForm->StatementListHead);
1100
1101 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1102 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1103
1104 //
1105 // Insert into Form list of this FormSet
1106 //
1107 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1108 break;
1109
1110 //
1111 // Storage
1112 //
1113 case EFI_IFR_VARSTORE_OP:
1114 //
1115 // Create a buffer Storage for this FormSet
1116 //
1117 Storage = CreateStorage (FormSet);
1118 Storage->Type = EFI_HII_VARSTORE_BUFFER;
1119
1120 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1121 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1122 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
1123
1124 Storage->Buffer = AllocateZeroPool (Storage->Size);
1125 Storage->EditBuffer = AllocateZeroPool (Storage->Size);
1126
1127 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
1128 Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
1129 ASSERT (Storage->Name != NULL);
1130 for (Index = 0; AsciiString[Index] != 0; Index++) {
1131 Storage->Name[Index] = (CHAR16) AsciiString[Index];
1132 }
1133
1134 //
1135 // Initialize <ConfigHdr>
1136 //
1137 InitializeConfigHdr (FormSet, Storage);
1138 break;
1139
1140 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1141 //
1142 // Create a name/value Storage for this FormSet
1143 //
1144 Storage = CreateStorage (FormSet);
1145 Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
1146
1147 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1148 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1149
1150 //
1151 // Initialize <ConfigHdr>
1152 //
1153 InitializeConfigHdr (FormSet, Storage);
1154 break;
1155
1156 case EFI_IFR_VARSTORE_EFI_OP:
1157 //
1158 // Create a EFI variable Storage for this FormSet
1159 //
1160 Storage = CreateStorage (FormSet);
1161 Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
1162
1163 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1164 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
1165 CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
1166 break;
1167
1168 //
1169 // DefaultStore
1170 //
1171 case EFI_IFR_DEFAULTSTORE_OP:
1172 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
1173 ASSERT (DefaultStore != NULL);
1174 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1175
1176 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
1177 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1178
1179 //
1180 // Insert to DefaultStore list of this Formset
1181 //
1182 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1183 break;
1184
1185 //
1186 // Statements
1187 //
1188 case EFI_IFR_SUBTITLE_OP:
1189 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1190 ASSERT (CurrentStatement != NULL);
1191
1192 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
1193
1194 if (Scope != 0) {
1195 mInScopeSubtitle = TRUE;
1196 }
1197 break;
1198
1199 case EFI_IFR_TEXT_OP:
1200 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1201 ASSERT (CurrentStatement != NULL);
1202
1203 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1204 break;
1205
1206 case EFI_IFR_RESET_BUTTON_OP:
1207 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1208 ASSERT (CurrentStatement != NULL);
1209 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1210 break;
1211
1212 //
1213 // Questions
1214 //
1215 case EFI_IFR_ACTION_OP:
1216 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1217 ASSERT (CurrentStatement != NULL);
1218 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
1219
1220 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1221 //
1222 // No QuestionConfig present, so no configuration string will be processed
1223 //
1224 CurrentStatement->QuestionConfig = 0;
1225 } else {
1226 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1227 }
1228 break;
1229
1230 case EFI_IFR_REF_OP:
1231 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1232 ASSERT (CurrentStatement != NULL);
1233 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_UNDEFINED;
1234 CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
1235 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1236 CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1237
1238 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1239 CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1240
1241 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1242 CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1243 }
1244 }
1245 }
1246 break;
1247
1248 case EFI_IFR_ONE_OF_OP:
1249 case EFI_IFR_NUMERIC_OP:
1250 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1251 ASSERT(CurrentStatement != NULL);
1252
1253 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1254 Value = &CurrentStatement->HiiValue;
1255
1256 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1257 case EFI_IFR_NUMERIC_SIZE_1:
1258 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1259 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1260 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
1261 CurrentStatement->StorageWidth = sizeof (UINT8);
1262 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1263 break;
1264
1265 case EFI_IFR_NUMERIC_SIZE_2:
1266 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1267 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1268 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
1269 CurrentStatement->StorageWidth = sizeof (UINT16);
1270 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1271 break;
1272
1273 case EFI_IFR_NUMERIC_SIZE_4:
1274 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
1275 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
1276 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
1277 CurrentStatement->StorageWidth = sizeof (UINT32);
1278 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1279 break;
1280
1281 case EFI_IFR_NUMERIC_SIZE_8:
1282 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
1283 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
1284 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
1285 CurrentStatement->StorageWidth = sizeof (UINT64);
1286 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1287 break;
1288
1289 default:
1290 break;
1291 }
1292
1293 InitializeRequestElement (FormSet, CurrentStatement);
1294
1295 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
1296 SuppressForOption = TRUE;
1297 }
1298 break;
1299
1300 case EFI_IFR_ORDERED_LIST_OP:
1301 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1302 ASSERT(CurrentStatement != NULL);
1303
1304 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
1305 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
1306
1307 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
1308
1309 if (Scope != 0) {
1310 SuppressForOption = TRUE;
1311 }
1312 break;
1313
1314 case EFI_IFR_CHECKBOX_OP:
1315 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1316 ASSERT(CurrentStatement != NULL);
1317
1318 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
1319 CurrentStatement->StorageWidth = sizeof (BOOLEAN);
1320 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
1321
1322 InitializeRequestElement (FormSet, CurrentStatement);
1323
1324 break;
1325
1326 case EFI_IFR_STRING_OP:
1327 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1328 ASSERT (CurrentStatement != NULL);
1329 //
1330 // MinSize is the minimum number of characters that can be accepted for this opcode,
1331 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1332 // The characters are stored as Unicode, so the storage width should multiply 2.
1333 //
1334 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
1335 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
1336 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1337 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
1338
1339 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1340 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
1341
1342 InitializeRequestElement (FormSet, CurrentStatement);
1343 break;
1344
1345 case EFI_IFR_PASSWORD_OP:
1346 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1347 ASSERT (CurrentStatement != NULL);
1348 //
1349 // MinSize is the minimum number of characters that can be accepted for this opcode,
1350 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1351 // The characters are stored as Unicode, so the storage width should multiply 2.
1352 //
1353 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
1354 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
1355 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
1356
1357 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
1358 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
1359
1360 InitializeRequestElement (FormSet, CurrentStatement);
1361 break;
1362
1363 case EFI_IFR_DATE_OP:
1364 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1365 ASSERT(CurrentStatement != NULL);
1366
1367 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
1368 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
1369
1370 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
1371 CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);
1372
1373 InitializeRequestElement (FormSet, CurrentStatement);
1374 } else {
1375 //
1376 // Don't assign storage for RTC type of date/time
1377 //
1378 CurrentStatement->Storage = NULL;
1379 CurrentStatement->StorageWidth = 0;
1380 }
1381 break;
1382
1383 case EFI_IFR_TIME_OP:
1384 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1385 ASSERT(CurrentStatement != NULL);
1386
1387 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
1388 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
1389
1390 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
1391 CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);
1392
1393 InitializeRequestElement (FormSet, CurrentStatement);
1394 } else {
1395 //
1396 // Don't assign storage for RTC type of date/time
1397 //
1398 CurrentStatement->Storage = NULL;
1399 CurrentStatement->StorageWidth = 0;
1400 }
1401 break;
1402
1403 //
1404 // Default
1405 //
1406 case EFI_IFR_DEFAULT_OP:
1407 //
1408 // EFI_IFR_DEFAULT appear in scope of a Question,
1409 // It creates a default value for the current question.
1410 // A Question may have more than one Default value which have different default types.
1411 //
1412 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
1413 ASSERT (CurrentDefault != NULL);
1414 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
1415
1416 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
1417 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
1418 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1419 ExtendValueToU64 (&CurrentDefault->Value);
1420
1421 //
1422 // Insert to Default Value list of current Question
1423 //
1424 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
1425
1426 if (Scope != 0) {
1427 InScopeDefault = TRUE;
1428 }
1429 break;
1430
1431 //
1432 // Option
1433 //
1434 case EFI_IFR_ONE_OF_OPTION_OP:
1435 //
1436 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
1437 // It create a selection for use in current Question.
1438 //
1439 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
1440 ASSERT (CurrentOption != NULL);
1441 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
1442
1443 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
1444 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
1445 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
1446 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1447 ExtendValueToU64 (&CurrentOption->Value);
1448
1449 if (InScopeOptionSuppress) {
1450 CurrentOption->SuppressExpression = OptionSuppressExpression;
1451 }
1452
1453 //
1454 // Insert to Option list of current Question
1455 //
1456 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
1457
1458 //
1459 // Now we know the Storage width of nested Ordered List
1460 //
1461 if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) {
1462 Width = 1;
1463 switch (CurrentOption->Value.Type) {
1464 case EFI_IFR_TYPE_NUM_SIZE_8:
1465 Width = 1;
1466 break;
1467
1468 case EFI_IFR_TYPE_NUM_SIZE_16:
1469 Width = 2;
1470 break;
1471
1472 case EFI_IFR_TYPE_NUM_SIZE_32:
1473 Width = 4;
1474 break;
1475
1476 case EFI_IFR_TYPE_NUM_SIZE_64:
1477 Width = 8;
1478 break;
1479
1480 default:
1481 //
1482 // Invalid type for Ordered List
1483 //
1484 break;
1485 }
1486
1487 CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width);
1488 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
1489 CurrentStatement->ValueType = CurrentOption->Value.Type;
1490
1491 InitializeRequestElement (FormSet, CurrentStatement);
1492 }
1493 break;
1494
1495 //
1496 // Conditional
1497 //
1498 case EFI_IFR_NO_SUBMIT_IF_OP:
1499 case EFI_IFR_INCONSISTENT_IF_OP:
1500 //
1501 // Create an Expression node
1502 //
1503 CurrentExpression = CreateExpression (CurrentForm);
1504 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
1505
1506 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
1507 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
1508 InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
1509 } else {
1510 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
1511 InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
1512 }
1513 break;
1514
1515 case EFI_IFR_SUPPRESS_IF_OP:
1516 //
1517 // Question and Option will appear in scope of this OpCode
1518 //
1519 CurrentExpression = CreateExpression (CurrentForm);
1520 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
1521 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1522
1523 if (SuppressForOption) {
1524 InScopeOptionSuppress = TRUE;
1525 OptionSuppressExpression = CurrentExpression;
1526 } else {
1527 mInScopeSuppress = TRUE;
1528 mSuppressExpression = CurrentExpression;
1529 }
1530 break;
1531
1532 case EFI_IFR_GRAY_OUT_IF_OP:
1533 //
1534 // Questions will appear in scope of this OpCode
1535 //
1536 CurrentExpression = CreateExpression (CurrentForm);
1537 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
1538 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1539
1540 mInScopeGrayOut = TRUE;
1541 mGrayOutExpression = CurrentExpression;
1542 break;
1543
1544 case EFI_IFR_DISABLE_IF_OP:
1545 //
1546 // The DisableIf expression should only rely on constant, so it could be
1547 // evaluated at initialization and it will not be queued
1548 //
1549 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
1550 ASSERT (CurrentExpression != NULL);
1551 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
1552 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
1553 InitializeListHead (&CurrentExpression->OpCodeListHead);
1554
1555 if (CurrentForm != NULL) {
1556 //
1557 // This is DisableIf for Question, enqueue it to Form expression list
1558 //
1559 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1560 }
1561
1562 mDisableExpression = CurrentExpression;
1563 mInScopeDisable = TRUE;
1564 OpCodeDisabled = FALSE;
1565
1566 //
1567 // Take a look at next OpCode to see whether current expression consists
1568 // of single OpCode
1569 //
1570 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1571 SingleOpCodeExpression = TRUE;
1572 }
1573 break;
1574
1575 //
1576 // Expression
1577 //
1578 case EFI_IFR_VALUE_OP:
1579 CurrentExpression = CreateExpression (CurrentForm);
1580 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
1581 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1582
1583 if (InScopeDefault) {
1584 //
1585 // Used for default (EFI_IFR_DEFAULT)
1586 //
1587 CurrentDefault->ValueExpression = CurrentExpression;
1588 } else {
1589 //
1590 // If used for a question, then the question will be read-only
1591 //
1592 //
1593 // Make sure CurrentStatement is not NULL.
1594 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1595 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
1596 //
1597 ASSERT (CurrentStatement != NULL);
1598 CurrentStatement->ValueExpression = CurrentExpression;
1599 }
1600 break;
1601
1602 case EFI_IFR_RULE_OP:
1603 CurrentExpression = CreateExpression (CurrentForm);
1604 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
1605
1606 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
1607 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1608 break;
1609
1610 //
1611 // Image
1612 //
1613 case EFI_IFR_IMAGE_OP:
1614 //
1615 // Get ScopeOpcode from top of stack
1616 //
1617 PopScope (&ScopeOpCode);
1618 PushScope (ScopeOpCode);
1619
1620 switch (ScopeOpCode) {
1621 case EFI_IFR_FORM_SET_OP:
1622 ImageId = &FormSet->ImageId;
1623 break;
1624
1625 case EFI_IFR_FORM_OP:
1626 ASSERT (CurrentForm != NULL);
1627 ImageId = &CurrentForm->ImageId;
1628 break;
1629
1630 case EFI_IFR_ONE_OF_OPTION_OP:
1631 ImageId = &CurrentOption->ImageId;
1632 break;
1633
1634 default:
1635 //
1636 // Make sure CurrentStatement is not NULL.
1637 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
1638 // file is wrongly generated by tools such as VFR Compiler.
1639 //
1640 ASSERT (CurrentStatement != NULL);
1641 ImageId = &CurrentStatement->ImageId;
1642 break;
1643 }
1644
1645 ASSERT (ImageId != NULL);
1646 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
1647 break;
1648
1649 //
1650 // Refresh
1651 //
1652 case EFI_IFR_REFRESH_OP:
1653 ASSERT (CurrentStatement != NULL);
1654 CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
1655 break;
1656
1657 //
1658 // Vendor specific
1659 //
1660 case EFI_IFR_GUID_OP:
1661 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
1662 //
1663 // Tiano specific GUIDed opcodes
1664 //
1665 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
1666 case EFI_IFR_EXTEND_OP_LABEL:
1667 //
1668 // just ignore label
1669 //
1670 break;
1671
1672 case EFI_IFR_EXTEND_OP_BANNER:
1673 //
1674 // By SubClass to get Banner Data from Front Page
1675 //
1676 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
1677 CopyMem (
1678 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
1679 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
1680 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
1681 sizeof (EFI_STRING_ID)
1682 );
1683 }
1684 break;
1685
1686 case EFI_IFR_EXTEND_OP_CLASS:
1687 CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
1688 break;
1689
1690 case EFI_IFR_EXTEND_OP_SUBCLASS:
1691 CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
1692 break;
1693
1694 default:
1695 break;
1696 }
1697 }
1698
1699 break;
1700
1701 //
1702 // Scope End
1703 //
1704 case EFI_IFR_END_OP:
1705 Status = PopScope (&ScopeOpCode);
1706 if (EFI_ERROR (Status)) {
1707 ResetScopeStack ();
1708 return Status;
1709 }
1710
1711 switch (ScopeOpCode) {
1712 case EFI_IFR_FORM_SET_OP:
1713 //
1714 // End of FormSet, update FormSet IFR binary length
1715 // to stop parsing substantial OpCodes
1716 //
1717 FormSet->IfrBinaryLength = OpCodeOffset;
1718 break;
1719
1720 case EFI_IFR_FORM_OP:
1721 //
1722 // End of Form
1723 //
1724 CurrentForm = NULL;
1725 break;
1726
1727 case EFI_IFR_ONE_OF_OPTION_OP:
1728 //
1729 // End of Option
1730 //
1731 CurrentOption = NULL;
1732 break;
1733
1734 case EFI_IFR_SUBTITLE_OP:
1735 mInScopeSubtitle = FALSE;
1736 break;
1737
1738 case EFI_IFR_NO_SUBMIT_IF_OP:
1739 case EFI_IFR_INCONSISTENT_IF_OP:
1740 //
1741 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1742 //
1743 break;
1744
1745 case EFI_IFR_SUPPRESS_IF_OP:
1746 if (SuppressForOption) {
1747 InScopeOptionSuppress = FALSE;
1748 } else {
1749 mInScopeSuppress = FALSE;
1750 }
1751 break;
1752
1753 case EFI_IFR_GRAY_OUT_IF_OP:
1754 mInScopeGrayOut = FALSE;
1755 break;
1756
1757 case EFI_IFR_DISABLE_IF_OP:
1758 mInScopeDisable = FALSE;
1759 OpCodeDisabled = FALSE;
1760 break;
1761
1762 case EFI_IFR_ONE_OF_OP:
1763 case EFI_IFR_ORDERED_LIST_OP:
1764 SuppressForOption = FALSE;
1765 break;
1766
1767 case EFI_IFR_DEFAULT_OP:
1768 InScopeDefault = FALSE;
1769 break;
1770
1771 default:
1772 if (IsExpressionOpCode (ScopeOpCode)) {
1773 if (mInScopeDisable && CurrentForm == NULL) {
1774 //
1775 // This is DisableIf expression for Form, it should be a constant expression
1776 //
1777 ASSERT (CurrentExpression != NULL);
1778 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1779 if (EFI_ERROR (Status)) {
1780 return Status;
1781 }
1782
1783 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1784 return EFI_INVALID_PARAMETER;
1785 }
1786
1787 OpCodeDisabled = CurrentExpression->Result.Value.b;
1788 //
1789 // DisableIf Expression is only used once and not quequed, free it
1790 //
1791 DestroyExpression (CurrentExpression);
1792 }
1793
1794 //
1795 // End of current Expression
1796 //
1797 CurrentExpression = NULL;
1798 }
1799 break;
1800 }
1801 break;
1802
1803 default:
1804 break;
1805 }
1806 }
1807
1808 return EFI_SUCCESS;
1809 }