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