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