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