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