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