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