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