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