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