]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
Add the support of GUID opcode which enable SetupBrowser to support IFR generated...
[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);
103 ASSERT (Statement->Operand == EFI_IFR_CHECKBOX_OP);
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)) {
189 if ((*OpCodeData == EFI_IFR_CHECKBOX_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {
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)) ||
690 (Operand == EFI_IFR_CATENATE_OP)
691 ) {
692 return TRUE;
693 } else {
694 return FALSE;
695 }
696}
697
698
699/**
700 Calculate number of Statemens(Questions) and Expression OpCodes.
701
702 @param FormSet The FormSet to be counted.
703 @param NumberOfStatement Number of Statemens(Questions)
704 @param NumberOfExpression Number of Expression OpCodes
705
93e3992d 706**/
707VOID
708CountOpCodes (
709 IN FORM_BROWSER_FORMSET *FormSet,
710 IN OUT UINT16 *NumberOfStatement,
711 IN OUT UINT16 *NumberOfExpression
712 )
713{
714 UINT16 StatementCount;
715 UINT16 ExpressionCount;
716 UINT8 *OpCodeData;
717 UINTN Offset;
718 UINTN OpCodeLen;
719
720 Offset = 0;
721 StatementCount = 0;
722 ExpressionCount = 0;
723
724 while (Offset < FormSet->IfrBinaryLength) {
725 OpCodeData = FormSet->IfrBinaryData + Offset;
726 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
727 Offset += OpCodeLen;
728
729 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
730 ExpressionCount++;
731 } else {
732 StatementCount++;
733 }
734 }
735
736 *NumberOfStatement = StatementCount;
737 *NumberOfExpression = ExpressionCount;
738}
739
740
f511d656 741
93e3992d 742/**
743 Parse opcodes in the formset IFR binary.
744
745 @param FormSet Pointer of the FormSet data structure.
746
747 @retval EFI_SUCCESS Opcode parse success.
748 @retval Other Opcode parse fail.
749
750**/
751EFI_STATUS
752ParseOpCodes (
753 IN FORM_BROWSER_FORMSET *FormSet
754 )
755{
756 EFI_STATUS Status;
757 UINT16 Index;
758 FORM_BROWSER_FORM *CurrentForm;
759 FORM_BROWSER_STATEMENT *CurrentStatement;
760 EXPRESSION_OPCODE *ExpressionOpCode;
761 FORM_EXPRESSION *CurrentExpression;
762 UINT8 Operand;
763 UINT8 Scope;
764 UINTN OpCodeOffset;
765 UINTN OpCodeLength;
766 UINT8 *OpCodeData;
767 UINT8 ScopeOpCode;
768 FORMSET_STORAGE *Storage;
769 FORMSET_DEFAULTSTORE *DefaultStore;
770 QUESTION_DEFAULT *CurrentDefault;
771 QUESTION_OPTION *CurrentOption;
772 CHAR8 *AsciiString;
773 UINT16 NumberOfStatement;
774 UINT16 NumberOfExpression;
775 EFI_IMAGE_ID *ImageId;
776 BOOLEAN SuppressForOption;
777 BOOLEAN InScopeOptionSuppress;
778 FORM_EXPRESSION *OptionSuppressExpression;
779 BOOLEAN InScopeDisable;
780 UINT16 DepthOfDisable;
781 BOOLEAN OpCodeDisabled;
782 BOOLEAN SingleOpCodeExpression;
783 BOOLEAN InScopeDefault;
784 EFI_HII_VALUE *Value;
785
786 mInScopeSubtitle = FALSE;
787 SuppressForOption = FALSE;
788 mInScopeSuppress = FALSE;
789 InScopeOptionSuppress = FALSE;
790 mInScopeGrayOut = FALSE;
791 InScopeDisable = FALSE;
792 DepthOfDisable = 0;
793 OpCodeDisabled = FALSE;
794 SingleOpCodeExpression = FALSE;
795 InScopeDefault = FALSE;
796 CurrentExpression = NULL;
797 CurrentDefault = NULL;
798 CurrentOption = NULL;
799 OptionSuppressExpression = NULL;
800
801 //
802 // Get the number of Statements and Expressions
803 //
804 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
805
806 mStatementIndex = 0;
807 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
808 if (FormSet->StatementBuffer == NULL) {
809 return EFI_OUT_OF_RESOURCES;
810 }
811
812 mExpressionOpCodeIndex = 0;
813 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
814 if (FormSet->ExpressionBuffer == NULL) {
815 return EFI_OUT_OF_RESOURCES;
816 }
817
818 InitializeListHead (&FormSet->StorageListHead);
819 InitializeListHead (&FormSet->DefaultStoreListHead);
820 InitializeListHead (&FormSet->FormListHead);
821
822 CurrentForm = NULL;
823 CurrentStatement = NULL;
824
825 ResetScopeStack ();
826
827 OpCodeOffset = 0;
828 while (OpCodeOffset < FormSet->IfrBinaryLength) {
829 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
830
831 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
832 OpCodeOffset += OpCodeLength;
833 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
834 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
835
836 //
837 // If scope bit set, push onto scope stack
838 //
7936fb6a 839 if (Scope != 0) {
93e3992d 840 PushScope (Operand);
841 }
842
843 if (OpCodeDisabled) {
844 //
845 // DisableIf Expression is evaluated to be TRUE, try to find its end.
846 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
847 //
848 if (Operand == EFI_IFR_DISABLE_IF_OP) {
849 DepthOfDisable++;
850 } else if (Operand == EFI_IFR_END_OP) {
851 Status = PopScope (&ScopeOpCode);
852 if (EFI_ERROR (Status)) {
853 return Status;
854 }
855
856 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
857 if (DepthOfDisable == 0) {
858 InScopeDisable = FALSE;
859 OpCodeDisabled = FALSE;
860 } else {
861 DepthOfDisable--;
862 }
863 }
864 }
865 continue;
866 }
867
868 if (IsExpressionOpCode (Operand)) {
869 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
870 mExpressionOpCodeIndex++;
871
872 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
873 ExpressionOpCode->Operand = Operand;
874 Value = &ExpressionOpCode->Value;
875
876 switch (Operand) {
877 case EFI_IFR_EQ_ID_VAL_OP:
878 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
879
880 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
881 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
882 break;
883
884 case EFI_IFR_EQ_ID_ID_OP:
885 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
886 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
887 break;
888
889 case EFI_IFR_EQ_ID_LIST_OP:
890 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
891 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
892 ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ValueList);
893 break;
894
895 case EFI_IFR_TO_STRING_OP:
896 case EFI_IFR_FIND_OP:
897 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
898 break;
899
900 case EFI_IFR_STRING_REF1_OP:
901 Value->Type = EFI_IFR_TYPE_STRING;
902 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
903 break;
904
905 case EFI_IFR_RULE_REF_OP:
906 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
907 break;
908
909 case EFI_IFR_SPAN_OP:
910 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
911 break;
912
913 case EFI_IFR_THIS_OP:
914 ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
915 break;
916
917 case EFI_IFR_QUESTION_REF1_OP:
918 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
919 break;
920
921 case EFI_IFR_QUESTION_REF3_OP:
922 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
923 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
924
925 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
926 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
927 }
928 }
929 break;
930
931 //
932 // constant
933 //
934 case EFI_IFR_TRUE_OP:
935 Value->Type = EFI_IFR_TYPE_BOOLEAN;
936 Value->Value.b = TRUE;
937 break;
938
939 case EFI_IFR_FALSE_OP:
940 Value->Type = EFI_IFR_TYPE_BOOLEAN;
941 Value->Value.b = FALSE;
942 break;
943
944 case EFI_IFR_ONE_OP:
945 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
946 Value->Value.u8 = 1;
947 break;
948
949 case EFI_IFR_ZERO_OP:
950 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
951 Value->Value.u8 = 0;
952 break;
953
954 case EFI_IFR_ONES_OP:
955 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
ee17f9c1 956 Value->Value.u64 = 0xffffffffffffffffULL;
93e3992d 957 break;
958
959 case EFI_IFR_UINT8_OP:
960 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
961 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
962 break;
963
964 case EFI_IFR_UINT16_OP:
965 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
966 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
967 break;
968
969 case EFI_IFR_UINT32_OP:
970 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
971 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
972 break;
973
974 case EFI_IFR_UINT64_OP:
975 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
976 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
977 break;
978
979 case EFI_IFR_UNDEFINED_OP:
980 Value->Type = EFI_IFR_TYPE_OTHER;
981 break;
982
983 case EFI_IFR_VERSION_OP:
984 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
985 Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
986 break;
987
988 default:
989 break;
990 }
991
992 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
993
994 if (SingleOpCodeExpression) {
995 //
996 // There are two cases to indicate the end of an Expression:
997 // for single OpCode expression: one Expression OpCode
998 // for expression consists of more than one OpCode: EFI_IFR_END
999 //
1000 SingleOpCodeExpression = FALSE;
1001
1002 if (InScopeDisable) {
1003 //
1004 // Evaluate DisableIf expression
1005 //
1006 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1007 if (EFI_ERROR (Status)) {
1008 return Status;
1009 }
1010 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1011 return EFI_INVALID_PARAMETER;
1012 }
1013
1014 OpCodeDisabled = CurrentExpression->Result.Value.b;
1015 }
1016
1017 CurrentExpression = NULL;
1018 }
1019
1020 continue;
1021 }
1022
1023 //
1024 // Parse the Opcode
1025 //
1026 switch (Operand) {
1027
1028 case EFI_IFR_FORM_SET_OP:
1029 //
1030 // check the formset GUID
1031 //
1032 if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
1033 return EFI_INVALID_PARAMETER;
1034 }
1035
1036 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
1037 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
1038 break;
1039
1040 case EFI_IFR_FORM_OP:
1041 //
1042 // Create a new Form for this FormSet
1043 //
1044 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
1045 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
1046 InitializeListHead (&CurrentForm->ExpressionListHead);
1047 InitializeListHead (&CurrentForm->StatementListHead);
1048
1049 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
1050 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
1051
1052 //
1053 // Insert into Form list of this FormSet
1054 //
1055 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
1056 break;
1057
1058 //
1059 // Storage
1060 //
1061 case EFI_IFR_VARSTORE_OP:
1062 //
1063 // Create a buffer Storage for this FormSet
1064 //
1065 Storage = CreateStorage (FormSet);
1066 Storage->Type = EFI_HII_VARSTORE_BUFFER;
1067
1068 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1069 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1070 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
1071
1072 Storage->Buffer = AllocateZeroPool (Storage->Size);
1073 Storage->EditBuffer = AllocateZeroPool (Storage->Size);
1074
1075 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
1076 Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
1077 ASSERT (Storage->Name != NULL);
1078 for (Index = 0; AsciiString[Index] != 0; Index++) {
1079 Storage->Name[Index] = (CHAR16) AsciiString[Index];
1080 }
1081
1082 //
1083 // Initialize <ConfigHdr>
1084 //
1085 InitializeConfigHdr (FormSet, Storage);
1086 break;
1087
1088 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
1089 //
1090 // Create a name/value Storage for this FormSet
1091 //
1092 Storage = CreateStorage (FormSet);
1093 Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
1094
1095 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1096 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
1097
1098 //
1099 // Initialize <ConfigHdr>
1100 //
1101 InitializeConfigHdr (FormSet, Storage);
1102 break;
1103
1104 case EFI_IFR_VARSTORE_EFI_OP:
1105 //
1106 // Create a EFI variable Storage for this FormSet
1107 //
1108 Storage = CreateStorage (FormSet);
1109 Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
1110
1111 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
1112 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
1113 CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
1114 break;
1115
1116 //
1117 // DefaultStore
1118 //
1119 case EFI_IFR_DEFAULTSTORE_OP:
1120 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
1121 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
1122
1123 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
1124 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
1125
1126 //
1127 // Insert to DefaultStore list of this Formset
1128 //
1129 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
1130 break;
1131
1132 //
1133 // Statements
1134 //
1135 case EFI_IFR_SUBTITLE_OP:
1136 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1137 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
1138
7936fb6a 1139 if (Scope != 0) {
93e3992d 1140 mInScopeSubtitle = TRUE;
1141 }
1142 break;
1143
1144 case EFI_IFR_TEXT_OP:
1145 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
1146
1147 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
1148 break;
1149
1150 //
1151 // Questions
1152 //
1153 case EFI_IFR_ACTION_OP:
1154 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1155
1156 if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
1157 //
1158 // No QuestionConfig present, so no configuration string will be processed
1159 //
1160 CurrentStatement->QuestionConfig = 0;
1161 } else {
1162 CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
1163 }
1164 break;
1165
1166 case EFI_IFR_RESET_BUTTON_OP:
1167 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1168
1169 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
1170 break;
1171
1172 case EFI_IFR_REF_OP:
1173 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1174
1175 CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
1176 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
1177 CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1178
1179 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
1180 CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
1181
1182 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
1183 CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
1184 }
1185 }
1186 }
1187 break;
1188
1189 case EFI_IFR_ONE_OF_OP:
1190 case EFI_IFR_NUMERIC_OP:
1191 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1192
1193 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
1194 Value = &CurrentStatement->HiiValue;
1195
1196 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
1197 case EFI_IFR_NUMERIC_SIZE_1:
1198 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
1199 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
1200 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
1201 CurrentStatement->StorageWidth = sizeof (UINT8);
1202 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1203 break;
1204
1205 case EFI_IFR_NUMERIC_SIZE_2:
1206 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
1207 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
1208 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
1209 CurrentStatement->StorageWidth = sizeof (UINT16);
1210 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1211 break;
1212
1213 case EFI_IFR_NUMERIC_SIZE_4:
1214 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
1215 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
1216 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
1217 CurrentStatement->StorageWidth = sizeof (UINT32);
1218 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
1219 break;
1220
1221 case EFI_IFR_NUMERIC_SIZE_8:
1222 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
1223 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
1224 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
1225 CurrentStatement->StorageWidth = sizeof (UINT64);
1226 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1227 break;
1228
1229 default:
1230 break;
1231 }
1232
1233 InitializeRequestElement (FormSet, CurrentStatement);
1234
7936fb6a 1235 if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
93e3992d 1236 SuppressForOption = TRUE;
1237 }
1238 break;
1239
1240 case EFI_IFR_ORDERED_LIST_OP:
1241 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1242
1243 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
1244 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
1245 CurrentStatement->StorageWidth = (UINT16)(CurrentStatement->MaxContainers * sizeof (UINT8));
1246 InitializeRequestElement (FormSet, CurrentStatement);
1247
1248 //
1249 // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
1250 // has to use FormBrowser2.Callback() to retrieve the uncommited data for
1251 // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
1252 //
1253 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;
1254 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
1255
7936fb6a 1256 if (Scope != 0) {
93e3992d 1257 SuppressForOption = TRUE;
1258 }
1259 break;
1260
1261 case EFI_IFR_CHECKBOX_OP:
1262 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1263
1264 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
1265 CurrentStatement->StorageWidth = sizeof (BOOLEAN);
1266 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
1267
1268 InitializeRequestElement (FormSet, CurrentStatement);
f511d656 1269
93e3992d 1270 break;
1271
1272 case EFI_IFR_STRING_OP:
1273 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1274
1275 //
1276 // MinSize is the minimum number of characters that can be accepted for this opcode,
1277 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1278 // The characters are stored as Unicode, so the storage width should multiply 2.
1279 //
1280 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
1281 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
813acf3a 1282 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
93e3992d 1283 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
1284
1285 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
813acf3a 1286 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
93e3992d 1287
1288 InitializeRequestElement (FormSet, CurrentStatement);
1289 break;
1290
1291 case EFI_IFR_PASSWORD_OP:
1292 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1293
1294 //
1295 // MinSize is the minimum number of characters that can be accepted for this opcode,
1296 // MaxSize is the maximum number of characters that can be accepted for this opcode.
1297 // The characters are stored as Unicode, so the storage width should multiply 2.
1298 //
1299 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
1300 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
813acf3a 1301 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
93e3992d 1302
1303 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
813acf3a 1304 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
93e3992d 1305
1306 InitializeRequestElement (FormSet, CurrentStatement);
1307 break;
1308
1309 case EFI_IFR_DATE_OP:
1310 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1311
1312 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
1313 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
1314
1315 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
1316 CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);
1317
1318 InitializeRequestElement (FormSet, CurrentStatement);
1319 } else {
1320 //
1321 // Don't assign storage for RTC type of date/time
1322 //
1323 CurrentStatement->Storage = NULL;
1324 CurrentStatement->StorageWidth = 0;
1325 }
1326 break;
1327
1328 case EFI_IFR_TIME_OP:
1329 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
1330
1331 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
1332 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
1333
1334 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
1335 CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);
1336
1337 InitializeRequestElement (FormSet, CurrentStatement);
1338 } else {
1339 //
1340 // Don't assign storage for RTC type of date/time
1341 //
1342 CurrentStatement->Storage = NULL;
1343 CurrentStatement->StorageWidth = 0;
1344 }
1345 break;
1346
1347 //
1348 // Default
1349 //
1350 case EFI_IFR_DEFAULT_OP:
1351 //
1352 // EFI_IFR_DEFAULT appear in scope of a Question,
1353 // It creates a default value for the current question.
1354 // A Question may have more than one Default value which have different default types.
1355 //
1356 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
1357 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
1358
1359 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
1360 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
1361 CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1362 ExtendValueToU64 (&CurrentDefault->Value);
1363
1364 //
1365 // Insert to Default Value list of current Question
1366 //
1367 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
1368
7936fb6a 1369 if (Scope != 0) {
93e3992d 1370 InScopeDefault = TRUE;
1371 }
1372 break;
1373
1374 //
1375 // Option
1376 //
1377 case EFI_IFR_ONE_OF_OPTION_OP:
1378 //
1379 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
1380 // It create a selection for use in current Question.
1381 //
1382 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
1383 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
1384
1385 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
1386 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
1387 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
1388 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
1389 ExtendValueToU64 (&CurrentOption->Value);
1390
1391 if (InScopeOptionSuppress) {
1392 CurrentOption->SuppressExpression = OptionSuppressExpression;
1393 }
1394
1395 //
1396 // Insert to Option list of current Question
1397 //
1398 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
1399 break;
1400
1401 //
1402 // Conditional
1403 //
1404 case EFI_IFR_NO_SUBMIT_IF_OP:
1405 case EFI_IFR_INCONSISTENT_IF_OP:
1406 //
1407 // Create an Expression node
1408 //
1409 CurrentExpression = CreateExpression (CurrentForm);
1410 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
1411
1412 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
1413 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
1414 InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
1415 } else {
1416 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
1417 InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
1418 }
1419 break;
1420
1421 case EFI_IFR_SUPPRESS_IF_OP:
1422 //
1423 // Question and Option will appear in scope of this OpCode
1424 //
1425 CurrentExpression = CreateExpression (CurrentForm);
1426 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
1427 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1428
1429 if (SuppressForOption) {
1430 InScopeOptionSuppress = TRUE;
1431 OptionSuppressExpression = CurrentExpression;
1432 } else {
1433 mInScopeSuppress = TRUE;
1434 mSuppressExpression = CurrentExpression;
1435 }
1436 break;
1437
1438 case EFI_IFR_GRAY_OUT_IF_OP:
1439 //
1440 // Questions will appear in scope of this OpCode
1441 //
1442 CurrentExpression = CreateExpression (CurrentForm);
1443 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
1444 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1445
1446 mInScopeGrayOut = TRUE;
1447 mGrayOutExpression = CurrentExpression;
1448 break;
1449
1450 case EFI_IFR_DISABLE_IF_OP:
1451 //
1452 // The DisableIf expression should only rely on constant, so it could be
1453 // evaluated at initialization and it will not be queued
1454 //
1455 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
1456 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
1457 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
1458 InitializeListHead (&CurrentExpression->OpCodeListHead);
1459
1460 InScopeDisable = TRUE;
1461 OpCodeDisabled = FALSE;
1462
1463 //
1464 // Take a look at next OpCode to see whether current expression consists
1465 // of single OpCode
1466 //
1467 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
1468 SingleOpCodeExpression = TRUE;
1469 }
1470 break;
1471
1472 //
1473 // Expression
1474 //
1475 case EFI_IFR_VALUE_OP:
1476 CurrentExpression = CreateExpression (CurrentForm);
1477 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
1478 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1479
1480 if (InScopeDefault) {
1481 //
1482 // Used for default (EFI_IFR_DEFAULT)
1483 //
1484 CurrentDefault->ValueExpression = CurrentExpression;
1485 } else {
1486 //
1487 // If used for a question, then the question will be read-only
1488 //
1489 CurrentStatement->ValueExpression = CurrentExpression;
1490 }
1491 break;
1492
1493 case EFI_IFR_RULE_OP:
1494 CurrentExpression = CreateExpression (CurrentForm);
1495 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
1496
1497 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
1498 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
1499 break;
1500
1501 //
1502 // Image
1503 //
1504 case EFI_IFR_IMAGE_OP:
1505 //
1506 // Get ScopeOpcode from top of stack
1507 //
1508 PopScope (&ScopeOpCode);
1509 PushScope (ScopeOpCode);
1510
1511 switch (ScopeOpCode) {
1512 case EFI_IFR_FORM_SET_OP:
1513 ImageId = &FormSet->ImageId;
1514 break;
1515
1516 case EFI_IFR_FORM_OP:
1517 ImageId = &CurrentForm->ImageId;
1518 break;
1519
1520 case EFI_IFR_ONE_OF_OPTION_OP:
1521 ImageId = &CurrentOption->ImageId;
1522 break;
1523
1524 default:
1525 ImageId = &CurrentStatement->ImageId;
1526 break;
1527 }
1528
1529 CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
1530 break;
1531
1532 //
1533 // Refresh
1534 //
1535 case EFI_IFR_REFRESH_OP:
1536 CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
1537 break;
1538
1539 //
1540 // Vendor specific
1541 //
1542 case EFI_IFR_GUID_OP:
1543 if (CompareGuid (&gTianoHiiIfrGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
1544 //
1545 // Tiano specific GUIDed opcodes
1546 //
1547 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
1548 case EFI_IFR_EXTEND_OP_LABEL:
1549 //
1550 // just ignore label
1551 //
1552 break;
1553
1554 case EFI_IFR_EXTEND_OP_BANNER:
1555 if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
1556 CopyMem (
1557 &BannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
1558 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
1559 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
1560 sizeof (EFI_STRING_ID)
1561 );
1562 }
1563 break;
1564
1565 case EFI_IFR_EXTEND_OP_CLASS:
1566 CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
1567 break;
1568
1569 case EFI_IFR_EXTEND_OP_SUBCLASS:
1570 CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
1571 break;
1572
1573 default:
1574 break;
1575 }
1576 }
f511d656 1577
93e3992d 1578 break;
1579
1580 //
1581 // Scope End
1582 //
1583 case EFI_IFR_END_OP:
1584 Status = PopScope (&ScopeOpCode);
1585 if (EFI_ERROR (Status)) {
1586 ResetScopeStack ();
1587 return Status;
1588 }
1589
1590 switch (ScopeOpCode) {
1591 case EFI_IFR_FORM_SET_OP:
1592 //
1593 // End of FormSet, update FormSet IFR binary length
1594 // to stop parsing substantial OpCodes
1595 //
1596 FormSet->IfrBinaryLength = OpCodeOffset;
1597 break;
1598
1599 case EFI_IFR_FORM_OP:
1600 //
1601 // End of Form
1602 //
1603 CurrentForm = NULL;
1604 break;
1605
1606 case EFI_IFR_ONE_OF_OPTION_OP:
1607 //
1608 // End of Option
1609 //
1610 CurrentOption = NULL;
1611 break;
1612
1613 case EFI_IFR_SUBTITLE_OP:
1614 mInScopeSubtitle = FALSE;
1615 break;
1616
1617 case EFI_IFR_NO_SUBMIT_IF_OP:
1618 case EFI_IFR_INCONSISTENT_IF_OP:
1619 //
1620 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
1621 //
1622 break;
1623
1624 case EFI_IFR_SUPPRESS_IF_OP:
1625 if (SuppressForOption) {
1626 InScopeOptionSuppress = FALSE;
1627 } else {
1628 mInScopeSuppress = FALSE;
1629 }
1630 break;
1631
1632 case EFI_IFR_GRAY_OUT_IF_OP:
1633 mInScopeGrayOut = FALSE;
1634 break;
1635
1636 case EFI_IFR_DISABLE_IF_OP:
1637 InScopeDisable = FALSE;
1638 OpCodeDisabled = FALSE;
1639 break;
1640
1641 case EFI_IFR_ONE_OF_OP:
1642 case EFI_IFR_ORDERED_LIST_OP:
1643 SuppressForOption = FALSE;
1644 break;
1645
1646 case EFI_IFR_DEFAULT_OP:
1647 InScopeDefault = FALSE;
1648 break;
1649
1650 default:
1651 if (IsExpressionOpCode (ScopeOpCode)) {
1652 if (InScopeDisable) {
1653 //
1654 // Evaluate DisableIf expression
1655 //
1656 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
1657 if (EFI_ERROR (Status)) {
1658 return Status;
1659 }
1660 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
1661 return EFI_INVALID_PARAMETER;
1662 }
1663
1664 OpCodeDisabled = CurrentExpression->Result.Value.b;
1665 //
1666 // DisableIf Expression is only used once and not quequed, free it
1667 //
1668 DestroyExpression (CurrentExpression);
1669 }
1670
1671 //
1672 // End of current Expression
1673 //
1674 CurrentExpression = NULL;
1675 }
1676 break;
1677 }
1678 break;
1679
1680 default:
1681 break;
1682 }
1683 }
1684
1685 return EFI_SUCCESS;
1686}