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