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