]> git.proxmox.com Git - mirror_edk2.git/blame - 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
CommitLineData
93e3992d 1/** @file
7936fb6a 2Parser for IFR binary encoding.
3
813acf3a 4Copyright (c) 2007 - 2008, Intel Corporation
93e3992d 5All rights reserved. This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
93e3992d 13**/
14
15#include "Setup.h"
16#include "Ui.h"
93e3992d 17
18UINT16 mStatementIndex;
19UINT16 mExpressionOpCodeIndex;
20
21BOOLEAN mInScopeSubtitle;
22BOOLEAN mInScopeSuppress;
23BOOLEAN mInScopeGrayOut;
24FORM_EXPRESSION *mSuppressExpression;
25FORM_EXPRESSION *mGrayOutExpression;
26
27EFI_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**/
40FORM_BROWSER_STATEMENT *
41CreateStatement (
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**/
102FORM_BROWSER_STATEMENT *
103CreateQuestion (
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**/
188FORM_EXPRESSION *
189CreateExpression (
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**/
211FORMSET_STORAGE *
212CreateStorage (
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**/
236EFI_STATUS
237InitializeConfigHdr (
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**/
292EFI_STATUS
293InitializeRequestElement (
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
7936fb6a 333 if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
93e3992d 334 //
335 // Password with CALLBACK flag is stored in encoded format,
c56f5124 336 // so don't need to append it to <ConfigRequest>
93e3992d 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 //
c7b616cf 348 StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);
93e3992d 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/**
7936fb6a 367 Free resources of a Expression.
93e3992d 368
369 @param FormSet Pointer of the Expression
370
93e3992d 371**/
372VOID
373DestroyExpression (
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/**
7936fb6a 396 Free resources of a storage.
93e3992d 397
398 @param Storage Pointer of the storage
399
93e3992d 400**/
401VOID
402DestroyStorage (
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/**
7936fb6a 436 Free resources of a Statement.
93e3992d 437
438 @param Statement Pointer of the Statement
439
93e3992d 440**/
441VOID
442DestroyStatement (
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/**
7936fb6a 501 Free resources of a Form.
93e3992d 502
7936fb6a 503 @param Form Pointer of the Form.
93e3992d 504
505**/
506VOID
507DestroyForm (
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/**
7936fb6a 545 Free resources allocated for a FormSet.
93e3992d 546
547 @param FormSet Pointer of the FormSet
548
93e3992d 549**/
550VOID
551DestroyFormSet (
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**/
620BOOLEAN
621IsExpressionOpCode (
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
93e3992d 643**/
644VOID
645CountOpCodes (
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**/
687EFI_STATUS
688ParseOpCodes (
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 //
7936fb6a 775 if (Scope != 0) {
93e3992d 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;
ee17f9c1 892 Value->Value.u64 = 0xffffffffffffffffULL;
93e3992d 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
7936fb6a 1075 if (Scope != 0) {
93e3992d 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
7936fb6a 1171 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
93e3992d 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
7936fb6a 1192 if (Scope != 0) {
93e3992d 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;
813acf3a 1217 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
93e3992d 1218 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
1219
1220 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
813acf3a 1221 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
93e3992d 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));
813acf3a 1236 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
93e3992d 1237
1238 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
813acf3a 1239 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
93e3992d 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
7936fb6a 1304 if (Scope != 0) {
93e3992d 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}