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