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