]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/FCE/IfrParse.c
BaseTools/FCE: Add a tool FCE
[mirror_edk2.git] / BaseTools / Source / C / FCE / IfrParse.c
1 /** @file
2
3 Parser for IFR binary encoding.
4
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "IfrParse.h"
11
12 #ifndef EDKII_IFR_BIT_VARSTORE_GUID
13 #define EDKII_IFR_BIT_VARSTORE_GUID \
14 {0x82DDD68B, 0x9163, 0x4187, {0x9B, 0x27, 0x20, 0xA8, 0xFD, 0x60 ,0xA7, 0x1D}}
15 #endif
16
17 #ifndef EDKII_IFR_NUMERIC_SIZE_BIT
18 #define EDKII_IFR_NUMERIC_SIZE_BIT 0x3F
19 #endif
20
21 UINT16 mStatementIndex;
22 UINT16 mExpressionOpCodeIndex;
23
24 BOOLEAN mInScopeSubtitle;
25 BOOLEAN mInScopeSuppress;
26 BOOLEAN mInScopeGrayOut;
27 BOOLEAN mInScopeDisable;
28 FORM_EXPRESSION *mSuppressExpression;
29 FORM_EXPRESSION *mGrayOutExpression;
30 FORM_EXPRESSION *mDisableExpression;
31
32 extern MULTI_PLATFORM_PARAMETERS mMultiPlatformParam;
33 extern LIST_ENTRY mVarListEntry;
34 extern LIST_ENTRY mFormSetListEntry;
35 extern UINT32 mFormSetOrderParse;
36
37 #define FORM_SET_GUID_PREFIX "Form Set GUID: "
38 #define EFI_GUID_FORMAT "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
39
40 UINT32 mMaxCount = 0x100000;
41 UINT32 mCount = 0;
42 CHAR8 *mStringBuffer = NULL;
43 static EFI_GUID gEdkiiIfrBitVarGuid = EDKII_IFR_BIT_VARSTORE_GUID;
44
45 /**
46 Produces a Null-terminated ASCII string in mStringBuffer based on a Null-terminated
47 ASCII format string and variable argument list.
48
49 @param FormatString A null-terminated ASCII format string.
50 @param ... The variable argument list whose contents are accessed based on the
51 format string specified by FormatString.
52 **/
53 VOID
54 StringPrint (
55 CHAR8 *FormatString,
56 ...
57 )
58 {
59 va_list Marker;
60 INT32 Count;
61
62 va_start (Marker, FormatString);
63 Count = vsprintf (mStringBuffer + mCount, FormatString, Marker);
64 mCount = mCount + Count;
65 va_end (Marker);
66 if (mCount + 0x400 > mMaxCount) {
67 mStringBuffer[mCount] = '\0';
68 fwrite (mStringBuffer, sizeof (CHAR8), mCount, stdout);
69 mCount = 0;
70 }
71 }
72
73 /**
74 Print the information of questions.
75
76 @param FormSet The pointer to the formset.
77 @param FormSet The pointer to the form.
78 @param Question The pointer to the question.
79 @param PrintOrNot Decide whether print or not.
80
81 @return NULL.
82
83 **/
84 static
85 VOID
86 PrintQuestion (
87 IN FORM_BROWSER_FORMSET *FormSet,
88 IN FORM_BROWSER_FORM *Form,
89 IN FORM_BROWSER_STATEMENT *Question,
90 IN BOOLEAN PrintOrNot
91 );
92
93 /**
94 Writes a Unicode string specified by iStringToken and iLanguage to the script file (converted to ASCII).
95
96 @param Package A pointer to the Unicode string.
97
98 @return NULL
99
100 **/
101 static
102 VOID
103 LogUnicodeString (
104 IN CHAR16 *pcString
105 )
106 {
107 UINTN Index;
108
109 if (pcString == NULL) {
110 return;
111 }
112 //
113 // replace the 0x0D to 0x20, because if the pcString has 0D 0A, then after print it,
114 // different editor may have different format
115 //
116 for (Index = 0; pcString[Index] != 0; Index++) {
117 if (pcString[Index] == 0x0D) {
118 pcString[Index] = 0x20;
119 }
120
121 StringPrint("%c", pcString[Index] & 0x00FF);
122 }
123 }
124
125 /**
126 Writes a UQIL Unicode string specified by iStringToken to the script file as an array of 16-bit integers in ASCII.
127
128 @param Package A pointer to the Unicode string.
129
130 @return NULL
131
132 **/
133 static
134 VOID
135 LogUqi (
136 IN CHAR16 *pcString
137 )
138 {
139 UINT16 Index;
140 //
141 // Find the UNICODE string length (in CHAR16)
142 //
143 for (Index = 0; pcString[Index] != 0; Index++);
144 //
145 // Write each word as a hex integer
146 //
147 for (Index = 0; pcString[Index] != 0; Index++) {
148 StringPrint("%04X ", pcString[Index]);
149 }
150 }
151
152 /**
153 Get the question value with bit field from the buffer.
154
155 @param Question The question refer to bit field.
156 @param Buffer The buffer which the question value get from.
157 @param Value Retun the value.
158
159 **/
160 VOID
161 GetBitsQuestionValue(
162 IN FORM_BROWSER_STATEMENT *Question,
163 IN UINT8 *Buffer,
164 OUT UINT32 *Value
165 )
166 {
167 UINT32 PreBits;
168 UINT32 Mask;
169
170 PreBits = Question->BitVarOffset - Question->VarStoreInfo.VarOffset * 8;
171 Mask = (1<< Question->BitStorageWidth) -1;
172
173 *Value = *(UINT32*)Buffer;
174 (*Value) >>= PreBits;
175 (*Value) &= Mask;
176 }
177
178 /**
179 Set the question value with bit field to the buffer.
180
181 @param Question The question refer to bit field.
182 @param Buffer The buffer which the question value set to.
183 @param Value The value need to set.
184
185 **/
186 VOID
187 SetBitsQuestionValue (
188 IN FORM_BROWSER_STATEMENT *Question,
189 IN OUT UINT8 *Buffer,
190 IN UINT32 Value
191 )
192 {
193 UINT32 PreBits;
194 UINT32 Mask;
195 UINT32 TmpValue;
196
197 PreBits = Question->BitVarOffset - Question->VarStoreInfo.VarOffset * 8;
198 Value <<= PreBits;
199 Mask = (1<< Question->BitStorageWidth) -1;
200 Mask <<= PreBits;
201
202 TmpValue = *(UINT32*)(Buffer);
203 TmpValue = (TmpValue & (~Mask)) | Value;
204 CopyMem ((UINT32*)Buffer, &TmpValue, sizeof (UINT32));
205 }
206
207 /**
208 Print the current value of the specified question.
209
210 @param Question The pointer to question
211
212 @return EFI_SUCCESS
213 **/
214 static
215 EFI_STATUS
216 LogIfrValue (
217 IN FORM_BROWSER_FORMSET *FormSet,
218 IN FORM_BROWSER_STATEMENT *Question
219 )
220 {
221 EFI_STATUS Status;
222 FORMSET_STORAGE *VarList;
223 UINT8 *VarBuffer;
224 UINT32 Value;
225
226 VarBuffer = NULL;
227
228 Status = SearchVarStorage (
229 Question,
230 NULL,
231 Question->VarStoreInfo.VarOffset,
232 FormSet->StorageListHead,
233 (CHAR8 **)&VarBuffer,
234 &VarList
235 );
236
237 if (EFI_ERROR (Status)) {
238 StringPrint("\nCouldn't read current variable data.");
239 return EFI_ABORTED;
240 }
241 //
242 // Log the Value
243 //
244 if (
245 (Question->VarStoreInfo.VarOffset > VarList->Size) \
246 && (VarList->Type == EFI_IFR_VARSTORE_OP)
247 ) {
248 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
249 } else if (
250 (Question->VarStoreInfo.VarOffset > VarList->Size) \
251 && (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
252 && VarList->NewEfiVarstore
253 ) {
254 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
255 } else if (
256 (Question->StorageWidth > VarList->Size) \
257 && (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
258 && !VarList->NewEfiVarstore
259 ) {
260 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
261 } else {
262 if (Question->QuestionReferToBitField) {
263 GetBitsQuestionValue (Question, VarBuffer, &Value);
264 VarBuffer = (UINT8*)(&Value);
265 }
266 switch (Question->StorageWidth) {
267
268 case sizeof (UINT8):
269 StringPrint("%02X", (*(UINT8 *)VarBuffer) & 0xFF);
270 break;
271
272 case sizeof (UINT16):
273 StringPrint("%04X", (*(UINT16 *)VarBuffer) & 0xFFFF);
274 break;
275
276 case sizeof (UINT32):
277 StringPrint("%08X", (*(UINT32 *)VarBuffer) & 0xFFFFFFFF);
278 break;
279
280 case sizeof (UINT64):
281 StringPrint("%016llX", *((UINT64 *)VarBuffer));
282 break;
283
284 default:
285 StringPrint("0000 // Width > 16 is not supported -- FAILURE");
286 break;
287 }
288 }
289 return EFI_SUCCESS;
290 }
291
292 /**
293 Print the current value of the STRING question.
294
295 @param Question The pointer to question
296
297 @return EFI_SUCCESS
298 **/
299 static
300 EFI_STATUS
301 LogIfrValueStr (
302 IN FORM_BROWSER_FORMSET *FormSet,
303 IN FORM_BROWSER_STATEMENT *Question
304 )
305 {
306 EFI_STATUS Status;
307 FORMSET_STORAGE *VarList;
308 UINT8 *VarBuffer;
309
310 VarBuffer = NULL;
311 Status = SearchVarStorage (
312 Question,
313 NULL,
314 Question->VarStoreInfo.VarOffset,
315 FormSet->StorageListHead,
316 (CHAR8 **)&VarBuffer,
317 &VarList
318 );
319
320 if (EFI_ERROR (Status)) {
321 StringPrint("\nCouldn't read current variable data.");
322 return EFI_ABORTED;
323 }
324
325 //
326 // Log the Value
327 //
328 if (
329 (Question->VarStoreInfo.VarOffset > VarList->Size) \
330 && (VarList->Type == EFI_IFR_VARSTORE_OP)
331 ) {
332 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
333 } else if (
334 (Question->VarStoreInfo.VarOffset > VarList->Size) \
335 && (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
336 && VarList->NewEfiVarstore
337 ) {
338 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
339 } else if (
340 (Question->StorageWidth > VarList->Size) \
341 && (VarList->Type == EFI_IFR_VARSTORE_EFI_OP) \
342 && !VarList->NewEfiVarstore
343 ) {
344 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
345 } else {
346 StringPrint("\"");
347 LogUnicodeString((CHAR16 *)VarBuffer);
348 StringPrint("\"");
349 }
350 return EFI_SUCCESS;
351 }
352
353 /**
354 Print the current values of an Ordered List question.
355
356 @param Question The pointer to question
357 @param MaxEntries The max number of options
358 @param VarList The dual pointer to the Node of VarList
359
360 @return EFI_SUCCESS
361 **/
362 static
363 EFI_STATUS
364 LogIfrValueList (
365 IN FORM_BROWSER_FORMSET *FormSet,
366 IN FORM_BROWSER_STATEMENT *Question
367 )
368 {
369 EFI_STATUS Status;
370 FORMSET_STORAGE *VarList;
371 UINT8 CurrentEntry;
372 UINT8 *VarBuffer;
373
374 CurrentEntry = 0;
375 VarBuffer = NULL;
376
377 Status = SearchVarStorage (
378 Question,
379 NULL,
380 Question->VarStoreInfo.VarOffset,
381 FormSet->StorageListHead,
382 (CHAR8 **)&VarBuffer,
383 &VarList
384 );
385
386 if (EFI_ERROR (Status)) {
387 StringPrint("\nCouldn't read current variable data.");
388 return EFI_ABORTED;
389 }
390 //
391 // Log the value
392 //
393 if (
394 ((Question->VarStoreInfo.VarOffset + Question->MaxContainers) > VarList->Size) \
395 && (VarList->Type == EFI_IFR_VARSTORE_OP)
396 ) {
397 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
398 } else if (
399 (Question->MaxContainers > VarList->Size) \
400 && (VarList->Type == EFI_IFR_VARSTORE_EFI_OP)
401 ) {
402 StringPrint("0000 // Offset larger than Variable Size -- FAILURE");
403 } else {
404 for (CurrentEntry = 0; CurrentEntry < Question->MaxContainers; CurrentEntry++) {
405
406 switch (Question->StorageWidth/Question->MaxContainers){
407
408 case 1:
409 StringPrint("%02X ", VarBuffer[CurrentEntry]);
410 break;
411
412 case 2:
413 StringPrint("%04X ", *((UINT16 *)VarBuffer + CurrentEntry));
414 break;
415
416 case 4:
417 StringPrint("%08X ", *((UINT32 *)VarBuffer + CurrentEntry));
418 break;
419
420 case 8:
421 StringPrint("%016llX ", *((UINT64 *)VarBuffer + CurrentEntry));
422 break;
423
424 default:
425 StringPrint("%02X ", VarBuffer[CurrentEntry]);
426 }
427 }
428 }
429 return EFI_SUCCESS;
430 }
431
432 /**
433 Compare two Uqi parameters
434
435 @param UqiParm1 The pointer to the first Uqi parameter.
436 @param UqiParm2 The pointer to the second Uqi parameter.
437
438 @retval TRUE If these two Uqi parameters are the same, return TRUE;
439 @return FALSE Otherwise, return FALSE;
440 **/
441 BOOLEAN
442 CompareUqiHeader (
443 IN CONST UQI_HEADER *UqiParm1,
444 IN CONST UQI_HEADER *UqiParm2
445 )
446 {
447 INT32 Index;
448
449 if (UqiParm1->HexNum != UqiParm2->HexNum) {
450 return FALSE;
451 }
452
453 for (Index = UqiParm1->HexNum - 1; Index >= 0; Index--) {
454 if (UqiParm1->Data[Index] != UqiParm2->Data[Index]) {
455 return FALSE;
456 }
457 }
458
459 return TRUE;
460 }
461
462
463 /**
464 Check whether existed a same variable in the LIST_ENTRY.
465
466 @param CurVarList A pointer to a variable node.
467
468 @return Pointer If existed the same variable, return the pointer to the Node.
469 @return NULL Otherwise, return FALSE
470
471 **/
472 static
473 FORMSET_STORAGE *
474 NotSameVariableInVarList (
475 IN LIST_ENTRY *VariableListEntry,
476 IN FORMSET_STORAGE *StorageNode
477 )
478 {
479 FORMSET_STORAGE *CurNode;
480 LIST_ENTRY *Link;
481 LIST_ENTRY *StorageListHead;
482
483 StorageListHead = VariableListEntry;
484 CurNode = NULL;
485
486 //
487 // Find Storage for this Question
488 //
489 Link = GetFirstNode (StorageListHead);
490 while (!IsNull (StorageListHead, Link)) {
491 CurNode = FORMSET_STORAGE_FROM_LINK (Link);
492
493 if (!CompareGuid (&StorageNode->Guid, &CurNode->Guid) \
494 && (CurNode->Name != NULL) \
495 && (StorageNode->Name != NULL) \
496 && !FceStrCmp (StorageNode->Name, CurNode->Name) \
497 && (StorageNode - CurNode != 0)
498 ) {
499 //
500 // If not multi-plaform support mode, take VarStore as the EfiVarStore. So If there are
501 // two variables with same guid same name, but different type, we will take as the same
502 // in general mode
503 //
504 if (mMultiPlatformParam.MultiPlatformOrNot && (CurNode->Type == StorageNode->Type)) {
505 //
506 // If matched, get the address of EFI_IFR_VARSTORE data.
507 //
508 return CurNode;
509 break;
510 } else if (!mMultiPlatformParam.MultiPlatformOrNot) {
511 return CurNode;
512 break;
513 }
514 }
515 Link = GetNextNode (StorageListHead, Link);
516 }
517 return NULL;
518 }
519
520 /**
521 Get the UniString by the offset.
522
523 @param UniPackge A pointer to the beginning of Null-terminated Unicode string Array.
524 @param CurUniPackge A pointer to the current position of Null-terminated Unicode string Array.
525 @param VarDefaultNameId The string ID.
526 @param CurOrDefaultLang Use the current language or the default language.
527 @param VarDefaultName return the name string.
528
529 @return EFI_SUCCESS
530 @return EFI_INVALID_PARAMETER
531 @return EFI_NOT_FOUND
532 **/
533 static
534 EFI_STATUS
535 GetStringByOffset (
536 IN UINT8 *UniPackge,
537 IN UINT8 *CurUniPackge,
538 IN UINT16 VarDefaultNameId,
539 IN BOOLEAN CurOrDefaultLang,
540 IN OUT CHAR16 **VarDefaultName
541 )
542 {
543 UINT8 *HiiStringHeader;
544 UINT32 Offset;
545 UINT32 Count;
546 UINT32 Index;
547 EFI_HII_STRING_BLOCK *Block;
548 VOID *ThisBlock;
549
550 assert ((UniPackge != NULL) && (CurUniPackge != NULL));
551
552 HiiStringHeader = NULL;
553 Offset = 1;
554 Count = 0;
555 Block = NULL;
556 ThisBlock = NULL;
557
558 if (VarDefaultNameId == 0) {
559 return EFI_INVALID_PARAMETER;
560 }
561 if (CurOrDefaultLang) {
562 HiiStringHeader = CurUniPackge;
563 } else {
564 HiiStringHeader = UniPackge + 4;
565 }
566
567 Block = (EFI_HII_STRING_BLOCK *)((UINT8*)HiiStringHeader + ((EFI_HII_STRING_PACKAGE_HDR *)HiiStringHeader)->HdrSize);
568 //
569 // Search the matched String in specificated language package by the Offset
570 //
571 while( Block->BlockType != EFI_HII_SIBT_END ) {
572 switch (Block->BlockType) {
573 case EFI_HII_SIBT_STRING_SCSU:
574 ThisBlock = (VOID *)Block;
575 for (Index = 0 ; ((EFI_HII_SIBT_STRING_SCSU_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
576 Block = (EFI_HII_STRING_BLOCK *)&((EFI_HII_SIBT_STRING_SCSU_BLOCK *)ThisBlock)->StringText[Index + 1];
577 break;
578
579 case EFI_HII_SIBT_STRING_SCSU_FONT:
580 ThisBlock = (VOID *)Block;
581 for (Index = 0 ; ((EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
582 Block = (EFI_HII_STRING_BLOCK *)(((EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK *)ThisBlock) + 1);
583 break;
584
585 case EFI_HII_SIBT_STRINGS_SCSU:
586 ThisBlock = (VOID *)Block;
587 for( Count= ((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ThisBlock)->StringCount, Index = 0 ; Count; Count--, Index++ ) {
588 for ( ; ((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
589 }
590 Block = (EFI_HII_STRING_BLOCK *)&((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ThisBlock)->StringText[Index];
591 break;
592
593 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
594 ThisBlock = (VOID *)Block;
595 for( Count = ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ThisBlock)->StringCount, Index = 0 ; Count; Count--, Index++ ) ;
596 Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ThisBlock)->StringText[Index];
597 break;
598
599 case EFI_HII_SIBT_STRING_UCS2:
600 ThisBlock = (VOID *)Block;
601 if (Offset == VarDefaultNameId) {
602 *VarDefaultName = malloc ((FceStrLen ((CHAR16 *) ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)ThisBlock)->StringText) + 1) * sizeof (CHAR16));
603 if (*VarDefaultName == NULL) {
604 printf ("Fail to allocate memory");
605 return EFI_OUT_OF_RESOURCES;
606 }
607 memset (
608 *VarDefaultName,
609 0,
610 (FceStrLen ((CHAR16 *) ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)ThisBlock)->StringText) + 1) * sizeof (CHAR16)
611 );
612 StrCpy (
613 *VarDefaultName,
614 (CHAR16 *) ((EFI_HII_SIBT_STRING_UCS2_BLOCK *) ThisBlock)->StringText
615 );
616 return EFI_SUCCESS;
617 }
618
619 for (Index = 0 ; ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)ThisBlock)->StringText[Index] != 0 ; Index++) ;
620 Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRING_UCS2_BLOCK *) ThisBlock)->StringText[Index + 1];
621 Offset += 1;
622 break;
623
624 case EFI_HII_SIBT_STRING_UCS2_FONT:
625 ThisBlock = (VOID *)Block;
626 for (Index = 0 ; ((EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK *) ThisBlock)->StringText[Index] != 0 ; Index++) ;
627 Block = (EFI_HII_STRING_BLOCK *)& ((EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK *) ThisBlock)->StringText[Index + 1];
628 break;
629
630 case EFI_HII_SIBT_STRINGS_UCS2:
631 ThisBlock = (VOID *)Block;
632 for( Count = ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *)ThisBlock)->StringCount, Index = 0 ; Count; Count--, Index++ ) {
633 for ( ; ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *) ThisBlock)->StringText[Index] != 0 ; Index++) ;
634 }
635 Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *) ThisBlock)->StringText[Index];
636 break;
637
638 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
639 ThisBlock = (VOID *)Block;
640 for( Count= ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *) ThisBlock)->StringCount, Index = 0 ; Count ; Count--, Index++ ) {
641 for ( ; ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *) ThisBlock)->StringText[Index] != 0 ; Index++) ;
642 }
643 Block = (EFI_HII_STRING_BLOCK *) & ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *)ThisBlock)->StringText[Index];
644 break;
645
646 case EFI_HII_SIBT_DUPLICATE:
647 ThisBlock = (VOID *)Block;
648 Block = (EFI_HII_STRING_BLOCK *)((EFI_HII_SIBT_DUPLICATE_BLOCK *) ThisBlock + 1);
649 break;
650
651 case EFI_HII_SIBT_SKIP2:
652 ThisBlock = (VOID *)Block;
653 Offset += ((EFI_HII_SIBT_SKIP2_BLOCK *) ThisBlock)->SkipCount;
654 Block = (EFI_HII_STRING_BLOCK *)( (EFI_HII_SIBT_SKIP2_BLOCK *) ThisBlock + 1);
655 break;
656
657 case EFI_HII_SIBT_SKIP1:
658 ThisBlock = (VOID *)Block;
659 Offset += ((EFI_HII_SIBT_SKIP1_BLOCK *) ThisBlock)->SkipCount;
660 Block = (EFI_HII_STRING_BLOCK *)((EFI_HII_SIBT_SKIP1_BLOCK *)ThisBlock + 1);
661 break;
662
663 case EFI_HII_SIBT_EXT1:
664 ThisBlock = (VOID *)Block;
665 Block = (EFI_HII_STRING_BLOCK *)((UINT8*)ThisBlock + ((EFI_HII_SIBT_EXT1_BLOCK *) ThisBlock)->Length);
666 break;
667
668 case EFI_HII_SIBT_EXT2:
669 ThisBlock = (VOID *)Block;
670 Block = (EFI_HII_STRING_BLOCK *)((UINT8*)ThisBlock + ((EFI_HII_SIBT_EXT2_BLOCK *) ThisBlock)->Length);
671 break;
672
673 case EFI_HII_SIBT_EXT4:
674 ThisBlock = (VOID *)Block;
675 Block = (EFI_HII_STRING_BLOCK *)((UINT8*)ThisBlock + ((EFI_HII_SIBT_EXT4_BLOCK *)ThisBlock)->Length);
676 break;
677
678 case EFI_HII_SIBT_FONT:
679 ThisBlock = (VOID *)Block;
680 for (Index = 0 ; ((EFI_HII_SIBT_FONT_BLOCK *) ThisBlock)->FontName[Index] != 0 ; Index++) ;
681 Block = (EFI_HII_STRING_BLOCK *)& ((EFI_HII_SIBT_FONT_BLOCK *) ThisBlock)->FontName[Index + 1];
682 break;
683
684 default:
685 StringPrint("Unhandled type = 0x%x\n", Block->BlockType);
686 }
687 }
688
689 return EFI_NOT_FOUND;
690 }
691
692 /**
693 Parse the UniString to get the string information.
694
695 @param CachedStringList A pointer to cached string list
696 @param UniPackge A pointer to a Null-terminated Unicode string Array.
697 @param VarDefaultNameId The string ID.
698 @param Language The language, en-US UQI or eng.
699 @param VarDefaultName return the name string.
700
701 @return EFI_SUCCESS If get the name string successfully
702 @return EFI_NOT_FOUND An error occurred.
703 @return EFI_INVALID_PARAMETER
704
705 **/
706 EFI_STATUS
707 FindDefaultName (
708 IN FORMSET_STRING_LIST *CachedStringList,
709 IN UINT8 *UniPackge,
710 IN UINT16 VarDefaultNameId,
711 IN LANGUAGE Language,
712 IN OUT CHAR16 **VarDefaultName
713 )
714 {
715 CHAR8 *UniPackgeEnd;
716 CHAR8 *UniBin;
717 CHAR8 LangStr[10];
718 BOOLEAN IsFound;
719 EFI_STATUS Status;
720 EFI_STRING_ID Index;
721 STRING_INFO *TempBuffer;
722
723 UniBin = NULL;
724 IsFound = FALSE;
725 Status = EFI_NOT_FOUND;
726
727 UniBin = (CHAR8 *) UniPackge + 4;
728 UniPackgeEnd = (CHAR8 *) UniPackge + *(UINT32 *)UniPackge;
729
730 //
731 //Handle with the invalid usage "STRING_TOKEN(0)"
732 //
733 if (VarDefaultNameId == 0) {
734 *VarDefaultName = L"";
735 return EFI_SUCCESS;
736 }
737
738 if (CachedStringList != NULL) {
739 for (Index = 0; Index < CachedStringList->CachedIdNum; Index ++) {
740 if (VarDefaultNameId == CachedStringList->StringInfoList[Index].StringId) {
741 *VarDefaultName = CachedStringList->StringInfoList[Index].String;
742 return EFI_SUCCESS;
743 }
744 }
745 }
746
747 switch (Language) {
748
749 case UQI:
750 strcpy (LangStr, "uqi");
751 break;
752
753 case EN_US:
754 strcpy (LangStr, "en-US");
755 break;
756
757 case ENG:
758 strcpy (LangStr, "eng");
759 break;
760
761 default:
762 strcpy (LangStr, "en-US");
763 break;
764 }
765 IsFound = FALSE;
766
767 if (((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
768 //
769 // Search the specified language package
770 //
771 while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
772 if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, LangStr) == 0) {
773 IsFound = TRUE;
774 break;
775 }
776 UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
777 }
778 //
779 //If not find the string ID, use the en eng or en-US instead.
780 //
781 if (!IsFound) {
782 UniBin = (CHAR8 *) UniPackge + 4;
783
784 while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
785 if ((strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en") == 0) \
786 || (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en-US") == 0) \
787 || (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "eng") == 0) \
788 ) {
789 IsFound = TRUE;
790 break;
791 }
792 UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
793 }
794 }
795 //
796 //If not still find the string ID, use the first one instead.
797 //
798 Status = GetStringByOffset (
799 UniPackge,
800 (UINT8 *)UniBin,
801 VarDefaultNameId,
802 IsFound,
803 VarDefaultName
804 );
805 if (!EFI_ERROR (Status)) {
806 goto Done;
807 }
808 //
809 //If not find the specified string in UQI package, we use the en en-us eng or uqi insteadly
810 //
811 IsFound = FALSE;
812 UniBin = (CHAR8 *) UniPackge + 4;
813
814 while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
815 if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en") == 0) {
816 IsFound = TRUE;
817 break;
818 }
819 UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
820 }
821 Status = GetStringByOffset (
822 UniPackge,
823 (UINT8 *)UniBin,
824 VarDefaultNameId,
825 IsFound,
826 VarDefaultName
827 );
828 if (!EFI_ERROR (Status)) {
829 goto Done;
830 }
831
832 IsFound = FALSE;
833 UniBin = (CHAR8 *) UniPackge + 4;
834
835 while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
836 if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "en-US") == 0) {
837 IsFound = TRUE;
838 break;
839 }
840 UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
841 }
842 Status = GetStringByOffset (
843 UniPackge,
844 (UINT8 *)UniBin,
845 VarDefaultNameId,
846 IsFound,
847 VarDefaultName
848 );
849 if (!EFI_ERROR (Status)) {
850 goto Done;
851 }
852
853 IsFound = FALSE;
854 UniBin = (CHAR8 *) UniPackge + 4;
855
856 while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
857 if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "eng") == 0) {
858 IsFound = TRUE;
859 break;
860 }
861 UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
862 }
863 Status = GetStringByOffset (
864 UniPackge,
865 (UINT8 *)UniBin,
866 VarDefaultNameId,
867 IsFound,
868 VarDefaultName
869 );
870 if (!EFI_ERROR (Status)) {
871 goto Done;
872 }
873
874 IsFound = FALSE;
875 UniBin = (CHAR8 *) UniPackge + 4;
876
877 while ((UniBin < UniPackgeEnd) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
878 if (strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "uqi") == 0) {
879 IsFound = TRUE;
880 break;
881 }
882 UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
883 }
884 Status = GetStringByOffset (
885 UniPackge,
886 (UINT8 *)UniBin,
887 VarDefaultNameId,
888 IsFound,
889 VarDefaultName
890 );
891 if (!EFI_ERROR (Status)) {
892 goto Done;
893 }
894 }
895
896 Done:
897 if (EFI_ERROR (Status)) {
898 *VarDefaultName = NULL;
899 return EFI_NOT_FOUND;
900 }
901
902 if (CachedStringList != NULL) {
903 if (CachedStringList->CachedIdNum >= CachedStringList->MaxIdNum) {
904 TempBuffer = calloc (sizeof (STRING_INFO), CachedStringList->MaxIdNum + STRING_NUMBER);
905 if (TempBuffer == NULL) {
906 printf ("Fail to allocate memory! \n");
907 free (*VarDefaultName);
908 *VarDefaultName = NULL;
909 return EFI_OUT_OF_RESOURCES;
910 }
911 CopyMem (TempBuffer, CachedStringList->StringInfoList, sizeof (STRING_INFO) * CachedStringList->MaxIdNum);
912 FreePool (CachedStringList->StringInfoList);
913 CachedStringList->StringInfoList = TempBuffer;
914 CachedStringList->MaxIdNum = CachedStringList->MaxIdNum + STRING_NUMBER;
915 }
916 CachedStringList->StringInfoList[CachedStringList->CachedIdNum].StringId = VarDefaultNameId;
917 CachedStringList->StringInfoList[CachedStringList->CachedIdNum].String = *VarDefaultName;
918 CachedStringList->CachedIdNum ++;
919 }
920 return EFI_SUCCESS;
921 }
922
923 /**
924 Get the variable Guid and Name by the variableId and FormSetOrder.
925
926 @param FormSet The pointer to the formset.
927 @param FormSet The pointer to the form.
928 @param ListEntry The pointer to the LIST_ENTRY.
929
930 @return EFI_SUCCESS
931 @return EFI_NOT_FOUND If not find the the variable, or the variable doesn't belong to EfiVarStore or VarStore.
932 **/
933 static
934 EFI_STATUS
935 GetGuidNameByVariableId (
936 IN FORM_BROWSER_FORMSET *FormSet,
937 IN OUT FORM_BROWSER_STATEMENT *Question,
938 IN LIST_ENTRY *ListEntry
939 )
940 {
941 FORMSET_STORAGE *CurNode;
942 LIST_ENTRY *Link;
943 LIST_ENTRY *StorageListHead;
944 EFI_STATUS Status;
945 CHAR16 *EfiVariableName;
946
947 StorageListHead = ListEntry;
948 CurNode = NULL;
949 Status = EFI_SUCCESS;
950 EfiVariableName = NULL;
951
952 Link = GetFirstNode (StorageListHead);
953 while (!IsNull (StorageListHead, Link)) {
954 CurNode = FORMSET_STORAGE_FROM_LINK (Link);
955
956 if ((FormSet->FormSetOrder == CurNode->FormSetOrder) \
957 && (Question->VarStoreId == CurNode->VarStoreId)
958 ) {
959 //
960 // Copy type to question to avoid the case that EfiVarStore and VarStore have the same Guid and name.
961 //
962 Question->Type = CurNode->Type;
963 Question->NewEfiVarstore = CurNode->NewEfiVarstore;
964 Question->Attributes = CurNode->Attributes;
965
966 if (CurNode->Type == EFI_IFR_VARSTORE_EFI_OP) {
967 CopyMem (&Question->Guid, &CurNode->Guid, sizeof (EFI_GUID));
968 //
969 // If the first time to access the old EfiVarStore, need to sync the variable name
970 //
971 if (!CurNode->NewEfiVarstore) {
972 if (CurNode->Buffer == NULL) {
973 CurNode->Buffer = malloc (Question->StorageWidth);
974 }
975 if (CurNode->Name == NULL) {
976 Status = FindDefaultName (
977 &(FormSet->EnUsStringList),
978 FormSet->UnicodeBinary,
979 Question->VarStoreInfo.VarName,
980 EN_US,
981 &EfiVariableName
982 );
983 if (EFI_ERROR(Status)) {
984 return Status;
985 }
986 CurNode->Name = EfiVariableName;
987 }
988 if (CurNode->Size == 0) {
989 CurNode->Size = Question->StorageWidth;
990 }
991 }
992 //
993 // Check whether the Efivariable variable name is valid.
994 //
995 if ((CurNode->Name == NULL) || (FceStrLen (CurNode->Name) == 0)) {
996 StringPrint ("Error. The variable name of question is NULL. Its UQI is: ");
997 StringPrint("Q %04X ", Question->Uqi.HexNum);
998 LogUqi (Question->Uqi.Data);
999 StringPrint ("\n");
1000 return EFI_ABORTED;
1001 }
1002 if (Question->VariableName == NULL) {
1003 Question->VariableName = (CHAR16 *) malloc (2 * (FceStrLen ((CONST CHAR16 *)CurNode->Name) + 1));
1004 if (Question->VariableName == NULL) {
1005 return EFI_ABORTED;
1006 }
1007 }
1008 StrCpy (Question->VariableName, CurNode->Name);
1009
1010 return EFI_SUCCESS;
1011
1012 } else if (CurNode->Type == EFI_IFR_VARSTORE_OP) {
1013 CopyMem (&Question->Guid, &CurNode->Guid, sizeof (EFI_GUID));
1014 if (Question->VariableName == NULL) {
1015 Question->VariableName = (CHAR16 *) malloc (2 * (FceStrLen ((CONST CHAR16 *)CurNode->Name) + 1));
1016 if (Question->VariableName == NULL) {
1017 return EFI_ABORTED;
1018 }
1019 }
1020 //
1021 // Check whether the variable variable name is valid.
1022 //
1023 if ((CurNode->Name == NULL) || (FceStrLen (CurNode->Name) == 0)) {
1024 StringPrint ("Error. The variable name of question is NULL. UQI:");
1025 StringPrint("Q %04X ", Question->Uqi.HexNum);
1026 LogUqi (Question->Uqi.Data);
1027 StringPrint ("\n");
1028 return EFI_ABORTED;
1029 }
1030 StrCpy (Question->VariableName, CurNode->Name);
1031 return EFI_SUCCESS;
1032 }
1033 }
1034 Link = GetNextNode (StorageListHead, Link);
1035 }
1036 return EFI_NOT_FOUND;
1037 }
1038
1039 /**
1040 Search the variable list according to the variable Guid and name, and return the pointer
1041 of that Node.
1042
1043 @param HiiObjList The pointer to the Question
1044 @param VarName The EFI variable name need to be updated to VarList
1045 @param Offset The offset of the variable
1046 @param StorageListHead The pointer to the LIST_ENTRY of Storage
1047 @param Vaue The value in that value offset of the variable
1048 @param VarList The dual pointer of Varlist
1049
1050 @return EFI_SUCCESS
1051 @return EFI_NOT_FOUND
1052 **/
1053 EFI_STATUS
1054 SearchVarStorage (
1055 IN FORM_BROWSER_STATEMENT *Question,
1056 IN CHAR16* VarName,
1057 IN UINT32 Offset,
1058 IN LIST_ENTRY *StorageListHead,
1059 IN OUT CHAR8 **Value,
1060 IN OUT FORMSET_STORAGE **VarList
1061 )
1062 {
1063 FORMSET_STORAGE *CurNode;
1064 LIST_ENTRY *Link;
1065 BOOLEAN FindOrNot;
1066
1067 CurNode = NULL;
1068 FindOrNot = FALSE;
1069 *VarList = NULL;
1070 //
1071 // Find Storage for this Question
1072 //
1073 Link = GetFirstNode (StorageListHead);
1074 while (!IsNull (StorageListHead, Link)) {
1075 CurNode = FORMSET_STORAGE_FROM_LINK (Link);
1076 //
1077 // Deal with the old EfiVarstore before UEFI2.31
1078 //
1079 if (!CompareGuid (&Question->Guid, &CurNode->Guid) \
1080 && (CurNode->Type == EFI_IFR_VARSTORE_EFI_OP) \
1081 && !CurNode->NewEfiVarstore \
1082 && (Question->VariableName != NULL) \
1083 && (CurNode->Name != NULL) \
1084 && !FceStrCmp(Question->VariableName, CurNode->Name)
1085 ) {
1086 //
1087 // If not multi-plaform support mode, take VarStore as the EfiVarStore. So If there are
1088 // two variables with same guid same name, but different type, we will take as the same
1089 // in general mode
1090 //
1091 if (mMultiPlatformParam.MultiPlatformOrNot && (CurNode->Type == Question->Type)) {
1092 //
1093 // check whether exist a old EFI_IFR_VARSTORE_EFI or not.
1094 //
1095 *Value = (CHAR8 *)CurNode->Buffer;
1096 *VarList = CurNode;
1097 FindOrNot = TRUE;
1098 break;
1099 } else if (!mMultiPlatformParam.MultiPlatformOrNot) {
1100 //
1101 // check whether exist a old EFI_IFR_VARSTORE_EFI or not.
1102 //
1103 *Value = (CHAR8 *)CurNode->Buffer;
1104 *VarList = CurNode;
1105 FindOrNot = TRUE;
1106 break;
1107 }
1108 }
1109
1110 if (!CompareGuid (&Question->Guid, &CurNode->Guid) \
1111 && (CurNode->Name != NULL) \
1112 && (Question->VariableName != NULL) \
1113 && !FceStrCmp(Question->VariableName, CurNode->Name)
1114 ) {
1115 //
1116 // If not multi-plaform support mode, take VarStore as the EfiVarStore. So If there are
1117 // two variables with same guid same name, but different type, we will take as the same
1118 // in general mode
1119 //
1120 if (mMultiPlatformParam.MultiPlatformOrNot && (CurNode->Type == Question->Type)) {
1121 //
1122 // If matched, get the address of EFI_IFR_VARSTORE data.
1123 //
1124 *Value = (CHAR8 *)(CurNode->Buffer + Offset);
1125 *VarList = CurNode;
1126 FindOrNot = TRUE;
1127 break;
1128 } else if (!mMultiPlatformParam.MultiPlatformOrNot) {
1129 //
1130 // If matched, get the address of EFI_IFR_VARSTORE data.
1131 //
1132 *Value = (CHAR8 *)(CurNode->Buffer + Offset);
1133 *VarList = CurNode;
1134 FindOrNot = TRUE;
1135 break;
1136 }
1137 }
1138 Link = GetNextNode (StorageListHead, Link);
1139 }
1140 if (!FindOrNot) {
1141 return EFI_NOT_FOUND;
1142 }
1143 return EFI_SUCCESS;
1144 }
1145
1146 /**
1147 Get the string based on the StringId and HII Package List Handle.
1148
1149 @param Token The String's ID.
1150 @param HiiHandle The package list in the HII database to search for
1151 the specified string.
1152
1153 @return The output string.
1154
1155 **/
1156 CHAR16 *
1157 GetToken (
1158 IN EFI_STRING_ID Token,
1159 IN UINT8 *UniPackge
1160 )
1161 {
1162 CHAR16 *VarDefaultName;
1163 EFI_STATUS Status;
1164
1165 Status = EFI_SUCCESS;
1166
1167 if (UniPackge == NULL) {
1168 return NULL;
1169 }
1170
1171 Status = FindDefaultName (
1172 NULL,
1173 UniPackge,
1174 Token,
1175 EN_US,
1176 &VarDefaultName
1177 );
1178 if (EFI_ERROR (Status)) {
1179 return NULL;
1180 }
1181
1182 return VarDefaultName;
1183 }
1184
1185 /**
1186 Initialize Statement header members.
1187
1188 @param OpCodeData Pointer of the raw OpCode data.
1189 @param FormSet Pointer of the current FormSe.
1190 @param Form Pointer of the current Form.
1191
1192 @return The Statement.
1193
1194 **/
1195 FORM_BROWSER_STATEMENT *
1196 CreateStatement (
1197 IN UINT8 *OpCodeData,
1198 IN OUT FORM_BROWSER_FORMSET *FormSet,
1199 IN OUT FORM_BROWSER_FORM *Form
1200 )
1201 {
1202 FORM_BROWSER_STATEMENT *Statement;
1203 EFI_IFR_STATEMENT_HEADER *StatementHdr;
1204
1205 if (Form == NULL) {
1206 //
1207 // We are currently not in a Form Scope, so just skip this Statement
1208 //
1209 return NULL;
1210 }
1211
1212 Statement = &FormSet->StatementBuffer[mStatementIndex];
1213 mStatementIndex++;
1214
1215 InitializeListHead (&Statement->DefaultListHead);
1216 InitializeListHead (&Statement->OptionListHead);
1217 InitializeListHead (&Statement->InconsistentListHead);
1218 InitializeListHead (&Statement->NoSubmitListHead);
1219 InitializeListHead (&Statement->WarningListHead);
1220
1221 Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
1222
1223 Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
1224 Statement->QuestionReferToBitField = FALSE;
1225
1226 StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
1227 CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
1228 CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
1229
1230 if (mInScopeSuppress) {
1231 Statement->SuppressExpression = mSuppressExpression;
1232 }
1233
1234 if (mInScopeGrayOut) {
1235 Statement->GrayOutExpression = mGrayOutExpression;
1236 }
1237
1238
1239 if (mInScopeDisable) {
1240 Statement->DisableExpression = mDisableExpression;
1241 }
1242
1243 Statement->InSubtitle = mInScopeSubtitle;
1244
1245 //
1246 // Insert this Statement into current Form
1247 //
1248 InsertTailList (&Form->StatementListHead, &Statement->Link);
1249
1250 return Statement;
1251 }
1252
1253 /**
1254 Initialize Question's members.
1255
1256 @param OpCodeData Pointer of the raw OpCode data.
1257 @param FormSet Pointer of the current FormSet.
1258 @param Form Pointer of the current Form.
1259
1260 @return The Question.
1261
1262 **/
1263 FORM_BROWSER_STATEMENT *
1264 CreateQuestion (
1265 IN UINT8 *OpCodeData,
1266 IN OUT FORM_BROWSER_FORMSET *FormSet,
1267 IN OUT FORM_BROWSER_FORM *Form
1268 )
1269 {
1270 FORM_BROWSER_STATEMENT *Statement;
1271 EFI_IFR_QUESTION_HEADER *QuestionHdr;
1272 LIST_ENTRY *Link;
1273 FORMSET_STORAGE *Storage;
1274 NAME_VALUE_NODE *NameValueNode;
1275
1276 Statement = CreateStatement (OpCodeData, FormSet, Form);
1277 if (Statement == NULL) {
1278 return NULL;
1279 }
1280
1281 QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
1282 CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
1283 CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
1284 CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
1285
1286 Statement->QuestionFlags = QuestionHdr->Flags;
1287
1288 Statement->FormSetOrder = mFormSetOrderParse;
1289
1290 if (Statement->VarStoreId == 0) {
1291 //
1292 // VarStoreId of zero indicates no variable storage
1293 //
1294 return Statement;
1295 }
1296
1297 //
1298 // Find Storage for this Question
1299 //
1300 Link = GetFirstNode (FormSet->StorageListHead);
1301 while (!IsNull (FormSet->StorageListHead, Link)) {
1302 Storage = FORMSET_STORAGE_FROM_LINK (Link);
1303
1304 if ((Storage->VarStoreId == Statement->VarStoreId)
1305 && (Storage->FormSetOrder == Statement->FormSetOrder)) {
1306 Statement->Storage = Storage;
1307 break;
1308 }
1309
1310 Link = GetNextNode (FormSet->StorageListHead, Link);
1311 }
1312 ASSERT (Statement->Storage != NULL);
1313
1314 if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1315 Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->UnicodeBinary);
1316 ASSERT (Statement->VariableName != NULL);
1317 //
1318 // Insert to Name/Value varstore list
1319 //
1320 NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
1321 ASSERT (NameValueNode != NULL);
1322 NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
1323 NameValueNode->Name = FceAllocateCopyPool (FceStrSize (Statement->VariableName), Statement->VariableName);
1324 ASSERT (NameValueNode->Name != NULL);
1325 NameValueNode->Value = AllocateZeroPool (0x10);
1326 ASSERT (NameValueNode->Value != NULL);
1327 NameValueNode->EditValue = AllocateZeroPool (0x10);
1328 ASSERT (NameValueNode->EditValue != NULL);
1329
1330 InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
1331 }
1332
1333 return Statement;
1334 }
1335
1336
1337 /**
1338 Allocate a FORM_EXPRESSION node.
1339
1340 @param Form The Form associated with this Expression
1341
1342 @return Pointer to a FORM_EXPRESSION data structure.
1343
1344 **/
1345 FORM_EXPRESSION *
1346 CreateExpression (
1347 IN OUT FORM_BROWSER_FORM *Form
1348 )
1349 {
1350 FORM_EXPRESSION *Expression;
1351
1352 Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
1353 ASSERT (Expression != NULL);
1354 Expression->Signature = FORM_EXPRESSION_SIGNATURE;
1355 InitializeListHead (&Expression->OpCodeListHead);
1356
1357 return Expression;
1358 }
1359
1360
1361 /**
1362 Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
1363
1364 @param FormSet Pointer of the current FormSet
1365
1366 @return Pointer to a FORMSET_STORAGE data structure.
1367
1368 **/
1369 FORMSET_STORAGE *
1370 CreateStorage (
1371 IN FORM_BROWSER_FORMSET *FormSet
1372 )
1373 {
1374 FORMSET_STORAGE *Storage;
1375
1376 Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
1377 ASSERT (Storage != NULL);
1378 Storage->Signature = FORMSET_STORAGE_SIGNATURE;
1379 InitializeListHead (&Storage->NameValueListHead);
1380 InsertTailList (FormSet->StorageListHead, &Storage->Link);
1381
1382 return Storage;
1383 }
1384
1385 /**
1386 Free resources of a Expression.
1387
1388 @param FormSet Pointer of the Expression
1389
1390 **/
1391 VOID
1392 DestroyExpression (
1393 IN FORM_EXPRESSION *Expression
1394 )
1395 {
1396 LIST_ENTRY *Link;
1397 EXPRESSION_OPCODE *OpCode;
1398 LIST_ENTRY *SubExpressionLink;
1399 FORM_EXPRESSION *SubExpression;
1400
1401 while (!IsListEmpty (&Expression->OpCodeListHead)) {
1402 Link = GetFirstNode (&Expression->OpCodeListHead);
1403 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
1404 RemoveEntryList (&OpCode->Link);
1405
1406 if (OpCode->ValueList != NULL) {
1407 FreePool (OpCode->ValueList);
1408 }
1409
1410 if (OpCode->ValueName != NULL) {
1411 FreePool (OpCode->ValueName);
1412 }
1413
1414 if (OpCode->MapExpressionList.ForwardLink != NULL) {
1415 while (!IsListEmpty (&OpCode->MapExpressionList)) {
1416 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
1417 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
1418 RemoveEntryList(&SubExpression->Link);
1419 DestroyExpression (SubExpression);
1420 }
1421 }
1422 }
1423
1424 //
1425 // Free this Expression
1426 //
1427 FreePool (Expression);
1428 }
1429
1430
1431 /**
1432 Free resources of a storage.
1433
1434 @param Storage Pointer of the storage
1435
1436 **/
1437 VOID
1438 DestroyStorage (
1439 IN FORMSET_STORAGE *Storage
1440 )
1441 {
1442 LIST_ENTRY *Link;
1443 NAME_VALUE_NODE *NameValueNode;
1444
1445 if (Storage == NULL) {
1446 return;
1447 }
1448
1449 if (Storage->Name != NULL) {
1450 FreePool (Storage->Name);
1451 }
1452 if (Storage->Buffer != NULL) {
1453 FreePool (Storage->Buffer);
1454 }
1455
1456 while (!IsListEmpty (&Storage->NameValueListHead)) {
1457 Link = GetFirstNode (&Storage->NameValueListHead);
1458 NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
1459 RemoveEntryList (&NameValueNode->Link);
1460
1461 if (NameValueNode->Name != NULL) {
1462 FreePool (NameValueNode->Name);
1463 }
1464 if (NameValueNode->Value != NULL) {
1465 FreePool (NameValueNode->Value);
1466 }
1467 if (NameValueNode->EditValue != NULL) {
1468 FreePool (NameValueNode->EditValue);
1469 }
1470 FreePool (NameValueNode);
1471 }
1472
1473 FreePool (Storage);
1474 Storage = NULL;
1475 }
1476
1477 /**
1478 Free resources allocated for all Storage in an LIST_ENTRY.
1479
1480 @param FormSet Pointer of the FormSet
1481
1482 **/
1483 VOID
1484 DestroyAllStorage (
1485 IN LIST_ENTRY *StorageEntryListHead
1486 )
1487 {
1488 LIST_ENTRY *Link;
1489 FORMSET_STORAGE *Storage;
1490 //
1491 // Parse Fromset one by one
1492 //
1493 if (StorageEntryListHead->ForwardLink != NULL) {
1494 while (!IsListEmpty (StorageEntryListHead)) {
1495 Link = GetFirstNode (StorageEntryListHead);
1496 Storage = FORMSET_STORAGE_FROM_LINK (Link);
1497 RemoveEntryList (&Storage->Link);
1498
1499 DestroyStorage (Storage);
1500 }
1501 }
1502 StorageEntryListHead = NULL;
1503 }
1504
1505 /**
1506 Free resources of a Statement.
1507
1508 @param FormSet Pointer of the FormSet
1509 @param Statement Pointer of the Statement
1510
1511 **/
1512 VOID
1513 DestroyStatement (
1514 IN FORM_BROWSER_FORMSET *FormSet,
1515 IN OUT FORM_BROWSER_STATEMENT *Statement
1516 )
1517 {
1518 LIST_ENTRY *Link;
1519 QUESTION_DEFAULT *Default;
1520 QUESTION_OPTION *Option;
1521 FORM_EXPRESSION *Expression;
1522
1523 //
1524 // Free Default value List
1525 //
1526 while (!IsListEmpty (&Statement->DefaultListHead)) {
1527 Link = GetFirstNode (&Statement->DefaultListHead);
1528 Default = QUESTION_DEFAULT_FROM_LINK (Link);
1529 RemoveEntryList (&Default->Link);
1530
1531 if (Default->Value.Buffer != NULL) {
1532 FreePool(Default->Value.Buffer);
1533 }
1534 FreePool (Default);
1535 }
1536
1537 //
1538 // Free Options List
1539 //
1540 while (!IsListEmpty (&Statement->OptionListHead)) {
1541 Link = GetFirstNode (&Statement->OptionListHead);
1542 Option = QUESTION_OPTION_FROM_LINK (Link);
1543 RemoveEntryList (&Option->Link);
1544
1545 FreePool (Option);
1546 }
1547
1548 //
1549 // Free Inconsistent List
1550 //
1551 while (!IsListEmpty (&Statement->InconsistentListHead)) {
1552 Link = GetFirstNode (&Statement->InconsistentListHead);
1553 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1554 RemoveEntryList (&Expression->Link);
1555
1556 DestroyExpression (Expression);
1557 }
1558
1559 //
1560 // Free NoSubmit List
1561 //
1562 while (!IsListEmpty (&Statement->NoSubmitListHead)) {
1563 Link = GetFirstNode (&Statement->NoSubmitListHead);
1564 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1565 RemoveEntryList (&Expression->Link);
1566
1567 DestroyExpression (Expression);
1568 }
1569
1570 //
1571 // Free WarningIf List
1572 //
1573 while (!IsListEmpty (&Statement->WarningListHead)) {
1574 Link = GetFirstNode (&Statement->WarningListHead);
1575 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1576 RemoveEntryList (&Expression->Link);
1577
1578 DestroyExpression (Expression);
1579 }
1580 if (Statement->VariableName != NULL) {
1581 FreePool (Statement->VariableName);
1582 }
1583 if (Statement->BufferValue != NULL) {
1584 FreePool (Statement->BufferValue);
1585 }
1586 }
1587
1588 /**
1589 Free resources of a Form.
1590
1591 @param FormSet Pointer of the FormSet
1592 @param Form Pointer of the Form.
1593
1594 **/
1595 VOID
1596 DestroyForm (
1597 IN FORM_BROWSER_FORMSET *FormSet,
1598 IN OUT FORM_BROWSER_FORM *Form
1599 )
1600 {
1601 LIST_ENTRY *Link;
1602 FORM_EXPRESSION *Expression;
1603 FORM_BROWSER_STATEMENT *Statement;
1604
1605 //
1606 // Free Form Expressions
1607 //
1608 while (!IsListEmpty (&Form->ExpressionListHead)) {
1609 Link = GetFirstNode (&Form->ExpressionListHead);
1610 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1611 RemoveEntryList (&Expression->Link);
1612
1613 DestroyExpression (Expression);
1614 }
1615
1616 //
1617 // Free Statements/Questions
1618 //
1619 while (!IsListEmpty (&Form->StatementListHead)) {
1620 Link = GetFirstNode (&Form->StatementListHead);
1621 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
1622 RemoveEntryList (&Statement->Link);
1623
1624 DestroyStatement (FormSet, Statement);
1625 }
1626
1627 //
1628 // Free this Form
1629 //
1630 FreePool (Form);
1631 }
1632
1633
1634 /**
1635 Free resources allocated for a FormSet.
1636
1637 @param FormSet Pointer of the FormSet
1638
1639 **/
1640 VOID
1641 DestroyFormSet (
1642 IN FORM_BROWSER_FORMSET *FormSet
1643 )
1644 {
1645 LIST_ENTRY *Link;
1646 FORMSET_DEFAULTSTORE *DefaultStore;
1647 FORM_EXPRESSION *Expression;
1648 FORM_BROWSER_FORM *Form;
1649 UINT16 Index;
1650
1651 //
1652 // Free FormSet Default Store
1653 //
1654 if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
1655 while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
1656 Link = GetFirstNode (&FormSet->DefaultStoreListHead);
1657 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
1658 RemoveEntryList (&DefaultStore->Link);
1659
1660 FreePool (DefaultStore);
1661 }
1662 }
1663
1664 //
1665 // Free Formset Expressions
1666 //
1667 while (!IsListEmpty (&FormSet->ExpressionListHead)) {
1668 Link = GetFirstNode (&FormSet->ExpressionListHead);
1669 Expression = FORM_EXPRESSION_FROM_LINK (Link);
1670 RemoveEntryList (&Expression->Link);
1671
1672 DestroyExpression (Expression);
1673 }
1674
1675 //
1676 // Free Forms
1677 //
1678 if (FormSet->FormListHead.ForwardLink != NULL) {
1679 while (!IsListEmpty (&FormSet->FormListHead)) {
1680 Link = GetFirstNode (&FormSet->FormListHead);
1681 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
1682 RemoveEntryList (&Form->Link);
1683
1684 DestroyForm (FormSet, Form);
1685 }
1686 }
1687
1688 if (FormSet->StatementBuffer != NULL) {
1689 FreePool (FormSet->StatementBuffer);
1690 }
1691 if (FormSet->ExpressionBuffer != NULL) {
1692 FreePool (FormSet->ExpressionBuffer);
1693 }
1694 if (FormSet->EnUsStringList.StringInfoList != NULL) {
1695 for (Index = 0; Index < FormSet->EnUsStringList.CachedIdNum; Index ++) {
1696 FreePool (FormSet->EnUsStringList.StringInfoList[Index].String);
1697 }
1698 FreePool (FormSet->EnUsStringList.StringInfoList);
1699 }
1700 if (FormSet->UqiStringList.StringInfoList != NULL) {
1701 for (Index = 0; Index < FormSet->UqiStringList.CachedIdNum; Index ++) {
1702 FreePool (FormSet->UqiStringList.StringInfoList[Index].String);
1703 }
1704 FreePool (FormSet->UqiStringList.StringInfoList);
1705 }
1706
1707 FreePool (FormSet);
1708 }
1709
1710 /**
1711 Free resources allocated for all FormSet in an LIST_ENTRY.
1712
1713 @param FormSet Pointer of the FormSet
1714
1715 **/
1716 VOID
1717 DestroyAllFormSet (
1718 IN LIST_ENTRY *FormSetEntryListHead
1719 )
1720 {
1721 LIST_ENTRY *Link;
1722 FORM_BROWSER_FORMSET *FormSet;
1723 //
1724 // Parse Fromset one by one
1725 //
1726 if (FormSetEntryListHead->ForwardLink != NULL) {
1727 while (!IsListEmpty (FormSetEntryListHead)) {
1728 Link = GetFirstNode (FormSetEntryListHead);
1729 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
1730 RemoveEntryList (&FormSet->Link);
1731 DestroyFormSet (FormSet);
1732 }
1733 }
1734 }
1735
1736 /**
1737 Tell whether this Operand is an Expression OpCode or not
1738
1739 @param Operand Operand of an IFR OpCode.
1740
1741 @retval TRUE This is an Expression OpCode.
1742 @retval FALSE Not an Expression OpCode.
1743
1744 **/
1745 BOOLEAN
1746 IsExpressionOpCode (
1747 IN UINT8 Operand
1748 )
1749 {
1750 if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
1751 ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) ||
1752 ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
1753 (Operand == EFI_IFR_CATENATE_OP) ||
1754 (Operand == EFI_IFR_TO_LOWER_OP) ||
1755 (Operand == EFI_IFR_TO_UPPER_OP) ||
1756 (Operand == EFI_IFR_MAP_OP) ||
1757 (Operand == EFI_IFR_VERSION_OP) ||
1758 (Operand == EFI_IFR_SECURITY_OP)) {
1759 return TRUE;
1760 } else {
1761 return FALSE;
1762 }
1763 }
1764
1765
1766 /**
1767 Calculate number of Statemens(Questions) and Expression OpCodes.
1768
1769 @param FormSet The FormSet to be counted.
1770 @param NumberOfStatement Number of Statemens(Questions)
1771 @param NumberOfExpression Number of Expression OpCodes
1772
1773 **/
1774 VOID
1775 CountOpCodes (
1776 IN FORM_BROWSER_FORMSET *FormSet,
1777 IN OUT UINT16 *NumberOfStatement,
1778 IN OUT UINT16 *NumberOfExpression
1779 )
1780 {
1781 UINT16 StatementCount;
1782 UINT16 ExpressionCount;
1783 UINT8 *OpCodeData;
1784 UINTN Offset;
1785 UINTN OpCodeLen;
1786
1787 Offset = 0;
1788 StatementCount = 0;
1789 ExpressionCount = 0;
1790
1791 while (Offset < FormSet->IfrBinaryLength) {
1792 OpCodeData = FormSet->IfrBinaryData + Offset;
1793 OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1794 Offset += OpCodeLen;
1795
1796 if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
1797 ExpressionCount++;
1798 } else {
1799 StatementCount++;
1800 }
1801 }
1802
1803 *NumberOfStatement = StatementCount;
1804 *NumberOfExpression = ExpressionCount;
1805 }
1806
1807
1808
1809 /**
1810 Parse opcodes in the formset IFR binary.
1811
1812 @param FormSet Pointer of the FormSet data structure.
1813
1814 @retval EFI_SUCCESS Opcode parse success.
1815 @retval Other Opcode parse fail.
1816
1817 **/
1818 EFI_STATUS
1819 ParseOpCodes (
1820 IN FORM_BROWSER_FORMSET *FormSet
1821 )
1822 {
1823 EFI_STATUS Status;
1824 UINT16 Index;
1825 FORM_BROWSER_FORM *CurrentForm;
1826 FORM_BROWSER_STATEMENT *CurrentStatement;
1827 EXPRESSION_OPCODE *ExpressionOpCode;
1828 FORM_EXPRESSION *CurrentExpression;
1829 UINT8 Operand;
1830 UINT8 Scope;
1831 UINTN OpCodeOffset;
1832 UINTN OpCodeLength;
1833 UINT8 *OpCodeData;
1834 UINT8 ScopeOpCode;
1835 FORMSET_STORAGE *Storage;
1836 FORMSET_STORAGE *TempStorage;
1837 FORMSET_DEFAULTSTORE *DefaultStore;
1838 QUESTION_DEFAULT *CurrentDefault;
1839 QUESTION_OPTION *CurrentOption;
1840 UINT8 Width;
1841 CHAR8 *AsciiString;
1842 UINT16 NumberOfStatement;
1843 UINT16 NumberOfExpression;
1844 BOOLEAN SuppressForQuestion;
1845 BOOLEAN SuppressForOption;
1846 BOOLEAN InScopeOptionSuppress;
1847 FORM_EXPRESSION *OptionSuppressExpression;
1848 BOOLEAN InScopeFormSuppress;
1849 FORM_EXPRESSION *FormSuppressExpression;
1850 UINT16 DepthOfDisable;
1851 BOOLEAN OpCodeDisabled;
1852 BOOLEAN SingleOpCodeExpression;
1853 BOOLEAN InScopeDefault;
1854 EFI_HII_VALUE *Value;
1855 UINT8 MapScopeDepth;
1856 LIST_ENTRY *Link;
1857 FORMSET_STORAGE *VarStorage;
1858 LIST_ENTRY *MapExpressionList;
1859 EFI_VARSTORE_ID TempVarstoreId;
1860 BOOLEAN ConstantFlag;
1861 FORMSET_DEFAULTSTORE *PreDefaultStore;
1862 LIST_ENTRY *DefaultLink;
1863 BOOLEAN HaveInserted;
1864 BOOLEAN BitFieldStorage;
1865 UINT16 TotalBits;
1866
1867 mInScopeSubtitle = FALSE;
1868 SuppressForQuestion = FALSE;
1869 SuppressForOption = FALSE;
1870 InScopeFormSuppress = FALSE;
1871 mInScopeSuppress = FALSE;
1872 InScopeOptionSuppress = FALSE;
1873 mInScopeGrayOut = FALSE;
1874 mInScopeDisable = FALSE;
1875 DepthOfDisable = 0;
1876 OpCodeDisabled = FALSE;
1877 SingleOpCodeExpression = FALSE;
1878 InScopeDefault = FALSE;
1879 CurrentExpression = NULL;
1880 CurrentDefault = NULL;
1881 CurrentOption = NULL;
1882 OptionSuppressExpression = NULL;
1883 FormSuppressExpression = NULL;
1884 MapScopeDepth = 0;
1885 Link = NULL;
1886 VarStorage = NULL;
1887 MapExpressionList = NULL;
1888 TempVarstoreId = 0;
1889 ConstantFlag = TRUE;
1890 BitFieldStorage = FALSE;
1891
1892 //
1893 // Get the number of Statements and Expressions
1894 //
1895 CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
1896
1897 mStatementIndex = 0;
1898 FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
1899 if (FormSet->StatementBuffer == NULL) {
1900 return EFI_OUT_OF_RESOURCES;
1901 }
1902
1903 mExpressionOpCodeIndex = 0;
1904 FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
1905 if (FormSet->ExpressionBuffer == NULL) {
1906 return EFI_OUT_OF_RESOURCES;
1907 }
1908
1909 FormSet->StorageListHead = &mVarListEntry;
1910 InitializeListHead (&FormSet->DefaultStoreListHead);
1911 InitializeListHead (&FormSet->FormListHead);
1912 InitializeListHead (&FormSet->ExpressionListHead);
1913 ResetCurrentExpressionStack ();
1914 ResetMapExpressionListStack ();
1915
1916 CurrentForm = NULL;
1917 CurrentStatement = NULL;
1918
1919 ResetScopeStack ();
1920
1921 OpCodeOffset = 0;
1922 while (OpCodeOffset < FormSet->IfrBinaryLength) {
1923 OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
1924
1925 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
1926 OpCodeOffset += OpCodeLength;
1927 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
1928 Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
1929
1930 //
1931 // If scope bit set, push onto scope stack
1932 //
1933 if (Scope != 0) {
1934 PushScope (Operand);
1935 }
1936
1937 if (OpCodeDisabled) {
1938 //
1939 // DisableIf Expression is evaluated to be TRUE, try to find its end.
1940 // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
1941 //
1942 if (Operand == EFI_IFR_DISABLE_IF_OP) {
1943 DepthOfDisable++;
1944 } else if (Operand == EFI_IFR_END_OP) {
1945 Status = PopScope (&ScopeOpCode);
1946 if (EFI_ERROR (Status)) {
1947 return Status;
1948 }
1949
1950 if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
1951 if (DepthOfDisable == 0) {
1952 mInScopeDisable = FALSE;
1953 OpCodeDisabled = FALSE;
1954 } else {
1955 DepthOfDisable--;
1956 }
1957 }
1958 }
1959 continue;
1960 }
1961
1962 if (IsExpressionOpCode (Operand)) {
1963 ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
1964 mExpressionOpCodeIndex++;
1965
1966 ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
1967 ExpressionOpCode->Operand = Operand;
1968 Value = &ExpressionOpCode->Value;
1969
1970 switch (Operand) {
1971 case EFI_IFR_EQ_ID_VAL_OP:
1972 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1973
1974 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1975 CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
1976 break;
1977
1978 case EFI_IFR_EQ_ID_ID_OP:
1979 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
1980 CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
1981 break;
1982
1983 case EFI_IFR_EQ_ID_VAL_LIST_OP:
1984 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
1985 CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
1986 ExpressionOpCode->ValueList = FceAllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
1987 break;
1988
1989 case EFI_IFR_TO_STRING_OP:
1990 case EFI_IFR_FIND_OP:
1991 ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
1992 break;
1993
1994 case EFI_IFR_STRING_REF1_OP:
1995 Value->Type = EFI_IFR_TYPE_STRING;
1996 CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
1997 break;
1998
1999 case EFI_IFR_RULE_REF_OP:
2000 ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
2001 break;
2002
2003 case EFI_IFR_SPAN_OP:
2004 ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
2005 break;
2006
2007 case EFI_IFR_THIS_OP:
2008 ASSERT (CurrentStatement != NULL);
2009 ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
2010 break;
2011
2012 case EFI_IFR_SECURITY_OP:
2013 CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
2014 break;
2015
2016 case EFI_IFR_GET_OP:
2017 case EFI_IFR_SET_OP:
2018 CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
2019 if (TempVarstoreId != 0) {
2020 if (FormSet->StorageListHead->ForwardLink != NULL) {
2021 Link = GetFirstNode (FormSet->StorageListHead);
2022 while (!IsNull (FormSet->StorageListHead, Link)) {
2023 VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
2024 if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
2025 ExpressionOpCode->VarStorage = VarStorage;
2026 break;
2027 }
2028 Link = GetNextNode (FormSet->StorageListHead, Link);
2029 }
2030 }
2031 if (ExpressionOpCode->VarStorage == NULL) {
2032 //
2033 // VarStorage is not found.
2034 //
2035 return EFI_INVALID_PARAMETER;
2036 }
2037 }
2038 ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;
2039 switch (ExpressionOpCode->ValueType) {
2040 case EFI_IFR_TYPE_BOOLEAN:
2041 case EFI_IFR_TYPE_NUM_SIZE_8:
2042 ExpressionOpCode->ValueWidth = 1;
2043 break;
2044
2045 case EFI_IFR_TYPE_NUM_SIZE_16:
2046 case EFI_IFR_TYPE_STRING:
2047 ExpressionOpCode->ValueWidth = 2;
2048 break;
2049
2050 case EFI_IFR_TYPE_NUM_SIZE_32:
2051 ExpressionOpCode->ValueWidth = 4;
2052 break;
2053
2054 case EFI_IFR_TYPE_NUM_SIZE_64:
2055 ExpressionOpCode->ValueWidth = 8;
2056 break;
2057
2058 case EFI_IFR_TYPE_DATE:
2059 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_DATE);
2060 break;
2061
2062 case EFI_IFR_TYPE_TIME:
2063 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_TIME);
2064 break;
2065
2066 case EFI_IFR_TYPE_REF:
2067 ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);
2068 break;
2069
2070 case EFI_IFR_TYPE_OTHER:
2071 case EFI_IFR_TYPE_UNDEFINED:
2072 case EFI_IFR_TYPE_ACTION:
2073 case EFI_IFR_TYPE_BUFFER:
2074 default:
2075 //
2076 // Invalid value type for Get/Set opcode.
2077 //
2078 return EFI_INVALID_PARAMETER;
2079 }
2080 CopyMem (&ExpressionOpCode->VarStoreInfo.VarName, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName, sizeof (EFI_STRING_ID));
2081 CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));
2082 if ((ExpressionOpCode->VarStorage != NULL) &&
2083 ((ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE)
2084 || ((ExpressionOpCode->VarStorage->Type == EFI_IFR_VARSTORE_EFI_OP) && !ExpressionOpCode->VarStorage->NewEfiVarstore))
2085 ) {
2086 ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->UnicodeBinary);
2087 if (ExpressionOpCode->ValueName == NULL) {
2088 //
2089 // String ID is invalid.
2090 //
2091 return EFI_INVALID_PARAMETER;
2092 }
2093 }
2094 break;
2095
2096 case EFI_IFR_QUESTION_REF1_OP:
2097 CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
2098 break;
2099
2100 case EFI_IFR_QUESTION_REF3_OP:
2101 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
2102 CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
2103
2104 if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
2105 CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
2106 }
2107 }
2108 break;
2109
2110 //
2111 // constant
2112 //
2113 case EFI_IFR_TRUE_OP:
2114 Value->Type = EFI_IFR_TYPE_BOOLEAN;
2115 Value->Value.b = TRUE;
2116 break;
2117
2118 case EFI_IFR_FALSE_OP:
2119 Value->Type = EFI_IFR_TYPE_BOOLEAN;
2120 Value->Value.b = FALSE;
2121 break;
2122
2123 case EFI_IFR_ONE_OP:
2124 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
2125 Value->Value.u8 = 1;
2126 break;
2127
2128 case EFI_IFR_ZERO_OP:
2129 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
2130 Value->Value.u8 = 0;
2131 break;
2132
2133 case EFI_IFR_ONES_OP:
2134 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2135 Value->Value.u64 = 0xffffffffffffffffULL;
2136 break;
2137
2138 case EFI_IFR_UINT8_OP:
2139 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
2140 Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
2141 break;
2142
2143 case EFI_IFR_UINT16_OP:
2144 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
2145 CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
2146 break;
2147
2148 case EFI_IFR_UINT32_OP:
2149 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
2150 CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
2151 break;
2152
2153 case EFI_IFR_UINT64_OP:
2154 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2155 CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
2156 break;
2157
2158 case EFI_IFR_UNDEFINED_OP:
2159 Value->Type = EFI_IFR_TYPE_UNDEFINED;
2160 break;
2161
2162 case EFI_IFR_VERSION_OP:
2163 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
2164 break;
2165
2166 default:
2167 break;
2168 }
2169 //
2170 // Create sub expression nested in MAP opcode
2171 //
2172 if ((CurrentExpression == NULL) && (MapScopeDepth > 0)) {
2173 CurrentExpression = CreateExpression (CurrentForm);
2174 ASSERT (MapExpressionList != NULL);
2175 InsertTailList (MapExpressionList, &CurrentExpression->Link);
2176 if (Scope == 0) {
2177 SingleOpCodeExpression = TRUE;
2178 }
2179 }
2180 ASSERT (CurrentExpression != NULL);
2181 InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
2182 if (Operand == EFI_IFR_MAP_OP) {
2183 //
2184 // Store current Map Expression List.
2185 //
2186 if (MapExpressionList != NULL) {
2187 PushMapExpressionList (MapExpressionList);
2188 }
2189 //
2190 // Initialize new Map Expression List.
2191 //
2192 MapExpressionList = &ExpressionOpCode->MapExpressionList;
2193 InitializeListHead (MapExpressionList);
2194 //
2195 // Store current expression.
2196 //
2197 PushCurrentExpression (CurrentExpression);
2198 CurrentExpression = NULL;
2199 MapScopeDepth ++;
2200 } else if (SingleOpCodeExpression) {
2201 //
2202 // There are two cases to indicate the end of an Expression:
2203 // for single OpCode expression: one Expression OpCode
2204 // for expression consists of more than one OpCode: EFI_IFR_END
2205 //
2206 SingleOpCodeExpression = FALSE;
2207
2208 if (mInScopeDisable && (CurrentForm == NULL)) {
2209 //
2210 // This is DisableIf expression for Form, it should be a constant expression
2211 //
2212 ConstantFlag = TRUE;
2213 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression, &ConstantFlag);
2214 if (EFI_ERROR (Status)) {
2215 return Status;
2216 }
2217
2218 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
2219 return EFI_INVALID_PARAMETER;
2220 }
2221 if (!ConstantFlag) {
2222 StringPrint ("WARNING. The DisableIf expression for Form should be a constant expression.\n");
2223 }
2224 OpCodeDisabled = CurrentExpression->Result.Value.b;
2225 }
2226
2227 CurrentExpression = NULL;
2228 }
2229
2230 continue;
2231 }
2232
2233 //
2234 // Parse the Opcode
2235 //
2236 switch (Operand) {
2237
2238 case EFI_IFR_FORM_SET_OP:
2239
2240 CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
2241 CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
2242 CopyMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
2243
2244 if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
2245 //
2246 // The formset OpCode contains ClassGuid
2247 //
2248 FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
2249 CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
2250 }
2251 FormSet->FormSetOrder = ++mFormSetOrderParse;
2252 break;
2253
2254 case EFI_IFR_FORM_OP:
2255 case EFI_IFR_FORM_MAP_OP:
2256 //
2257 // Create a new Form for this FormSet
2258 //
2259 CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
2260 ASSERT (CurrentForm != NULL);
2261 CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
2262 InitializeListHead (&CurrentForm->ExpressionListHead);
2263 InitializeListHead (&CurrentForm->StatementListHead);
2264
2265 CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
2266 CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
2267 CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
2268
2269 if (InScopeFormSuppress) {
2270 //
2271 // Form is inside of suppressif
2272 //
2273 CurrentForm->SuppressExpression = FormSuppressExpression;
2274 }
2275
2276 if (Scope != 0) {
2277 //
2278 // Enter scope of a Form, suppressif will be used for Question or Option
2279 //
2280 SuppressForQuestion = TRUE;
2281 }
2282
2283 //
2284 // Insert into Form list of this FormSet
2285 //
2286 InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
2287 break;
2288 //
2289 // Storage
2290 //
2291 case EFI_IFR_VARSTORE_OP:
2292 //
2293 // Create a buffer Storage for this FormSet
2294 //
2295
2296 Storage = CreateStorage (FormSet);
2297 Storage->Type = EFI_IFR_VARSTORE_OP;
2298
2299 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
2300 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
2301 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
2302
2303 Storage->Buffer = AllocateZeroPool (Storage->Size);
2304
2305 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
2306 Storage->Name = AllocateZeroPool ((strlen (AsciiString) + 1) * 2);
2307 ASSERT (Storage->Name != NULL);
2308 for (Index = 0; AsciiString[Index] != 0; Index++) {
2309 Storage->Name[Index] = (CHAR16) AsciiString[Index];
2310 }
2311 Storage->FormSetOrder = mFormSetOrderParse;
2312
2313 //
2314 // If not existed the same variable in StorageList, insert the new one. Or else, use the old one.
2315 // If these two variales have the same Guid name but different size, report an error.
2316 //
2317 if ((TempStorage = NotSameVariableInVarList (FormSet->StorageListHead, Storage)) != NULL) {
2318 if (Storage->Size != TempStorage->Size) {
2319 StringPrint ("Error. Two modules found with VarStore variables with same name %S and GUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x, but with different sizes %d and %d.\n",
2320 Storage->Name,
2321 Storage->Guid.Data1,
2322 Storage->Guid.Data2,
2323 Storage->Guid.Data3,
2324 Storage->Guid.Data4[0],
2325 Storage->Guid.Data4[1],
2326 Storage->Guid.Data4[2],
2327 Storage->Guid.Data4[3],
2328 Storage->Guid.Data4[4],
2329 Storage->Guid.Data4[5],
2330 Storage->Guid.Data4[6],
2331 Storage->Guid.Data4[7],
2332 Storage->Size,
2333 TempStorage->Size
2334 );
2335 return EFI_ABORTED;
2336 }
2337 //
2338 // Update the VarStoreId for current question to get the variable guid and name information
2339 //
2340 TempStorage->VarStoreId = Storage->VarStoreId;
2341 TempStorage->FormSetOrder = Storage->FormSetOrder;
2342 RemoveEntryList (&Storage->Link);
2343 DestroyStorage(Storage);
2344 }
2345 break;
2346
2347 case EFI_IFR_VARSTORE_NAME_VALUE_OP:
2348 //
2349 // Create a name/value Storage for this FormSet
2350 //
2351 Storage = CreateStorage (FormSet);
2352 Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
2353
2354 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
2355 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
2356
2357 Storage->FormSetOrder = mFormSetOrderParse;
2358 break;
2359
2360 case EFI_IFR_VARSTORE_EFI_OP:
2361 //
2362 // Create a EFI variable Storage for this FormSet
2363 //
2364 Storage = CreateStorage (FormSet);
2365 Storage->Type = EFI_IFR_VARSTORE_EFI_OP;
2366 CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
2367 CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
2368 CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
2369 //
2370 // Check whether the EfiVarStore before UEFI2.31 or not
2371 //
2372 Storage->Size = sizeof (EFI_IFR_VARSTORE_EFI_OLD);
2373 if (((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Header.Length == sizeof (EFI_IFR_VARSTORE_EFI_OLD)) {
2374 Storage->NewEfiVarstore = FALSE;
2375 Storage->Size = 0;
2376 Storage->Buffer = NULL;
2377 Storage->Name = NULL;
2378 Storage->Size = 0;
2379 } else {
2380 //
2381 // EfiVarStore structure for UEFI2.31
2382 //
2383 Storage->NewEfiVarstore = TRUE;
2384 CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size, sizeof (UINT16));
2385
2386 Storage->Buffer = AllocateZeroPool (Storage->Size);
2387 AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;
2388 Storage->Name = AllocateZeroPool ((strlen (AsciiString) + 1) * 2);
2389 ASSERT (Storage->Name != NULL);
2390 for (Index = 0; AsciiString[Index] != 0; Index++) {
2391 Storage->Name[Index] = (CHAR16) AsciiString[Index];
2392 }
2393 }
2394 Storage->FormSetOrder = mFormSetOrderParse;
2395 //
2396 // If not existed the same variable in StorageList, insert the new one. Or else, use the old one.
2397 // If these two variales have the same Guid name but different size, report an error.
2398 //
2399 if ((TempStorage = NotSameVariableInVarList (FormSet->StorageListHead, Storage)) != NULL) {
2400 if (Storage->Size != TempStorage->Size) {
2401 StringPrint ("Error. Two modules found with EfiVarStore variables with same name %S and GUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x, but different sizes %d and %d.\n",
2402 Storage->Name,
2403 Storage->Guid.Data1,
2404 Storage->Guid.Data2,
2405 Storage->Guid.Data3,
2406 Storage->Guid.Data4[0],
2407 Storage->Guid.Data4[1],
2408 Storage->Guid.Data4[2],
2409 Storage->Guid.Data4[3],
2410 Storage->Guid.Data4[4],
2411 Storage->Guid.Data4[5],
2412 Storage->Guid.Data4[6],
2413 Storage->Guid.Data4[7],
2414 Storage->Size,
2415 TempStorage->Size
2416 );
2417 return EFI_ABORTED;
2418 }
2419 //
2420 // Update the VarStoreId for current question to get the variable guid and name information
2421 //
2422 TempStorage->VarStoreId = Storage->VarStoreId;
2423 TempStorage->FormSetOrder = Storage->FormSetOrder;
2424 RemoveEntryList (&Storage->Link);
2425 DestroyStorage( Storage);
2426 }
2427 break;
2428
2429 //
2430 // DefaultStore
2431 //
2432 case EFI_IFR_DEFAULTSTORE_OP:
2433 HaveInserted = FALSE;
2434 DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
2435 ASSERT (DefaultStore != NULL);
2436 DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
2437
2438 CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
2439 CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
2440
2441 //
2442 // Insert it to the DefaultStore list of this Formset with ascending order.
2443 //
2444 if (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
2445 DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
2446 while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
2447 PreDefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
2448 DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
2449 if (DefaultStore->DefaultId < PreDefaultStore->DefaultId) {
2450 InsertTailList (&PreDefaultStore->Link, &DefaultStore->Link);
2451 HaveInserted = TRUE;
2452 break;
2453 }
2454 }
2455 }
2456 if (!HaveInserted) {
2457 InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
2458 }
2459 break;
2460
2461 //
2462 // Statements
2463 //
2464 case EFI_IFR_SUBTITLE_OP:
2465 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
2466 ASSERT (CurrentStatement != NULL);
2467
2468 CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
2469
2470 if (Scope != 0) {
2471 mInScopeSubtitle = TRUE;
2472 }
2473 break;
2474
2475 case EFI_IFR_TEXT_OP:
2476 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
2477 ASSERT (CurrentStatement != NULL);
2478
2479 CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
2480 break;
2481
2482 case EFI_IFR_RESET_BUTTON_OP:
2483 CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
2484 ASSERT (CurrentStatement != NULL);
2485 CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
2486 break;
2487
2488 //
2489 // Questions
2490 //
2491 case EFI_IFR_ACTION_OP:
2492 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2493 ASSERT (CurrentStatement != NULL);
2494 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
2495 //
2496 // No need to deal with the EFI_IFR_ACTION
2497 //
2498 break;
2499
2500 case EFI_IFR_REF_OP:
2501 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2502 ASSERT (CurrentStatement != NULL);
2503 Value = &CurrentStatement->HiiValue;
2504 Value->Type = EFI_IFR_TYPE_REF;
2505 if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
2506 CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
2507
2508 if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
2509 CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
2510
2511 if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
2512 CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
2513
2514 if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
2515 CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
2516 }
2517 }
2518 }
2519 }
2520 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
2521 break;
2522
2523 case EFI_IFR_ONE_OF_OP:
2524 case EFI_IFR_NUMERIC_OP:
2525 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2526 ASSERT(CurrentStatement != NULL);
2527
2528 CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
2529 Value = &CurrentStatement->HiiValue;
2530
2531 if (BitFieldStorage) {
2532 //
2533 // Get the bit var store info (bit/byte offset, bit/byte offset)
2534 //
2535 CurrentStatement->QuestionReferToBitField = TRUE;
2536 CurrentStatement->BitStorageWidth = CurrentStatement->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
2537 CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;
2538 CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;
2539 TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;
2540 CurrentStatement->StorageWidth = (TotalBits % 8 == 0? TotalBits / 8: TotalBits / 8 + 1);
2541 //
2542 // Get the Minimum/Maximum/Step value(Note: bit field type has been stored as UINT32 type)
2543 //
2544 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue;
2545 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue;
2546 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step;
2547 } else {
2548 switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
2549 case EFI_IFR_NUMERIC_SIZE_1:
2550 CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
2551 CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
2552 CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
2553 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
2554 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
2555 break;
2556
2557 case EFI_IFR_NUMERIC_SIZE_2:
2558 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
2559 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
2560 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
2561 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
2562 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
2563 break;
2564
2565 case EFI_IFR_NUMERIC_SIZE_4:
2566 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
2567 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
2568 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
2569 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
2570 Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
2571 break;
2572
2573 case EFI_IFR_NUMERIC_SIZE_8:
2574 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
2575 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
2576 CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
2577 CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
2578 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2579 break;
2580
2581 default:
2582 break;
2583 }
2584 }
2585 if ((Operand == EFI_IFR_ONE_OF_OP) && (Scope != 0)) {
2586 SuppressForOption = TRUE;
2587 }
2588 //
2589 // Get the UQI information
2590 //
2591 PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
2592 //
2593 // Exchange the Guid and name information between VarList and Question List
2594 //
2595 Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
2596 //
2597 // Remove the question which isn't stored by EfiVarStore or VarStore
2598 //
2599 if (EFI_ERROR (Status)) {
2600 RemoveEntryList (&CurrentStatement->Link);
2601 DestroyStatement (FormSet, CurrentStatement);
2602 }
2603 break;
2604
2605 case EFI_IFR_ORDERED_LIST_OP:
2606 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2607 ASSERT(CurrentStatement != NULL);
2608
2609 CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
2610 CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
2611
2612 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
2613 CurrentStatement->BufferValue = NULL;
2614 if (Scope != 0) {
2615 SuppressForOption = TRUE;
2616 }
2617 //
2618 // Get the UQI information
2619 //
2620 PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
2621 //
2622 // Exchange the Guid and name information between VarList and Question List
2623 //
2624 Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
2625 //
2626 // Remove the question which isn't stored by EfiVarStore or VarStore
2627 //
2628 if (EFI_ERROR (Status)) {
2629 RemoveEntryList (&CurrentStatement->Link);
2630 DestroyStatement (FormSet, CurrentStatement);
2631 }
2632
2633 break;
2634
2635 case EFI_IFR_CHECKBOX_OP:
2636 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2637 ASSERT(CurrentStatement != NULL);
2638
2639 CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
2640 CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
2641 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
2642
2643 if (BitFieldStorage) {
2644 //
2645 // Get the bit var store info (bit/byte offset, bit/byte width)
2646 //
2647 CurrentStatement->QuestionReferToBitField = TRUE;
2648 CurrentStatement->BitStorageWidth = 1;
2649 CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;
2650 CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;
2651 TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;
2652 CurrentStatement->StorageWidth = (TotalBits % 8 == 0? TotalBits / 8: TotalBits / 8 + 1);
2653 }
2654 //
2655 // Get the UQI information
2656 //
2657 PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
2658 //
2659 // Exchange the Guid and name information between VarList and Question List
2660 //
2661 Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
2662 //
2663 // Remove the question which isn't stored by EfiVarStore or VarStore
2664 //
2665 if (EFI_ERROR (Status)) {
2666 RemoveEntryList (&CurrentStatement->Link);
2667 DestroyStatement (FormSet, CurrentStatement);
2668 }
2669
2670 break;
2671
2672 case EFI_IFR_STRING_OP:
2673 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2674 ASSERT (CurrentStatement != NULL);
2675 //
2676 // MinSize is the minimum number of characters that can be accepted for this opcode,
2677 // MaxSize is the maximum number of characters that can be accepted for this opcode.
2678 // The characters are stored as Unicode, so the storage width should multiply 2.
2679 //
2680 CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
2681 CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
2682 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2683 CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
2684
2685 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2686 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
2687 //
2688 // Get the UQI information
2689 //
2690 PrintQuestion(FormSet, CurrentForm, CurrentStatement, FALSE);
2691 //
2692 // Exchange the Guid and name information between VarList and Question List
2693 //
2694 Status = GetGuidNameByVariableId (FormSet, CurrentStatement, FormSet->StorageListHead);
2695 //
2696 // Remove the question which isn't stored by EfiVarStore or VarStore
2697 //
2698 if (EFI_ERROR (Status)) {
2699 RemoveEntryList (&CurrentStatement->Link);
2700 DestroyStatement (FormSet, CurrentStatement);
2701 }
2702
2703 break;
2704
2705 case EFI_IFR_PASSWORD_OP:
2706 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2707 ASSERT (CurrentStatement != NULL);
2708 //
2709 // MinSize is the minimum number of characters that can be accepted for this opcode,
2710 // MaxSize is the maximum number of characters that can be accepted for this opcode.
2711 // The characters are stored as Unicode, so the storage width should multiply 2.
2712 //
2713 CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
2714 CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
2715 CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
2716
2717 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
2718 CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
2719 break;
2720
2721 case EFI_IFR_DATE_OP:
2722 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2723 ASSERT(CurrentStatement != NULL);
2724
2725 CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
2726 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
2727
2728 if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
2729 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
2730 } else {
2731 //
2732 // Don't assign storage for RTC type of date/time
2733 //
2734 CurrentStatement->Storage = NULL;
2735 CurrentStatement->StorageWidth = 0;
2736 }
2737 break;
2738
2739 case EFI_IFR_TIME_OP:
2740 CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
2741 ASSERT(CurrentStatement != NULL);
2742
2743 CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
2744 CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
2745
2746 if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
2747 CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
2748 } else {
2749 //
2750 // Don't assign storage for RTC type of date/time
2751 //
2752 CurrentStatement->Storage = NULL;
2753 CurrentStatement->StorageWidth = 0;
2754 }
2755 break;
2756
2757 //
2758 // Default
2759 //
2760 case EFI_IFR_DEFAULT_OP:
2761 //
2762 // EFI_IFR_DEFAULT appear in scope of a Question,
2763 // It creates a default value for the current question.
2764 // A Question may have more than one Default value which have different default types.
2765 //
2766 CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
2767 ASSERT (CurrentDefault != NULL);
2768 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2769
2770 CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
2771 CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
2772 if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {
2773 CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF(EFI_IFR_DEFAULT, Value));
2774 CurrentDefault->Value.Buffer = FceAllocateCopyPool(CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *)OpCodeData)->Value);
2775 ASSERT(CurrentDefault->Value.Buffer != NULL);
2776 } else {
2777 CopyMem(&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *)OpCodeData)->Value, OpCodeLength - OFFSET_OF(EFI_IFR_DEFAULT, Value));
2778 ExtendValueToU64(&CurrentDefault->Value);
2779 }
2780
2781 //
2782 // Insert to Default Value list of current Question
2783 //
2784 InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
2785
2786 if (Scope != 0) {
2787 InScopeDefault = TRUE;
2788 }
2789 break;
2790
2791 //
2792 // Option
2793 //
2794 case EFI_IFR_ONE_OF_OPTION_OP:
2795 ASSERT (CurrentStatement != NULL);
2796 if (CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP &&
2797 ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0)) {
2798 //
2799 // It's keep the default value for ordered list opcode.
2800 //
2801 CurrentDefault = AllocateZeroPool(sizeof (QUESTION_DEFAULT));
2802 ASSERT(CurrentDefault != NULL);
2803 CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
2804
2805 CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;
2806 if ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
2807 CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
2808 } else {
2809 CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
2810 }
2811
2812 CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value));
2813 CurrentDefault->Value.Buffer = FceAllocateCopyPool(CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value);
2814 ASSERT(CurrentDefault->Value.Buffer != NULL);
2815
2816 //
2817 // Insert to Default Value list of current Question
2818 //
2819 InsertTailList(&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
2820 break;
2821 }
2822 //
2823 // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
2824 // It create a selection for use in current Question.
2825 //
2826 CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
2827 ASSERT (CurrentOption != NULL);
2828 CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
2829
2830 CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
2831 CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
2832 CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
2833 CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
2834 ExtendValueToU64 (&CurrentOption->Value);
2835
2836 if (InScopeOptionSuppress) {
2837 CurrentOption->SuppressExpression = OptionSuppressExpression;
2838 }
2839
2840 //
2841 // Insert to Option list of current Question
2842 //
2843 InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
2844
2845 //
2846 // Now we know the Storage width of nested Ordered List
2847 //
2848 if ((CurrentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (CurrentStatement->BufferValue == NULL)) {
2849 Width = 1;
2850 switch (CurrentOption->Value.Type) {
2851 case EFI_IFR_TYPE_NUM_SIZE_8:
2852 Width = 1;
2853 break;
2854
2855 case EFI_IFR_TYPE_NUM_SIZE_16:
2856 Width = 2;
2857 break;
2858
2859 case EFI_IFR_TYPE_NUM_SIZE_32:
2860 Width = 4;
2861 break;
2862
2863 case EFI_IFR_TYPE_NUM_SIZE_64:
2864 Width = 8;
2865 break;
2866
2867 default:
2868 //
2869 // Invalid type for Ordered List
2870 //
2871 break;
2872 }
2873
2874 CurrentStatement->StorageWidth = (UINT16) (CurrentStatement->MaxContainers * Width);
2875 CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
2876 CurrentStatement->ValueType = CurrentOption->Value.Type;
2877 if (CurrentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
2878 CurrentStatement->HiiValue.Buffer = CurrentStatement->BufferValue;
2879 CurrentStatement->HiiValue.BufferLen = CurrentStatement->StorageWidth;
2880 }
2881 }
2882 break;
2883
2884 //
2885 // Conditional
2886 //
2887 case EFI_IFR_NO_SUBMIT_IF_OP:
2888 case EFI_IFR_INCONSISTENT_IF_OP:
2889 //
2890 // Create an Expression node
2891 //
2892 CurrentExpression = CreateExpression (CurrentForm);
2893 CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
2894
2895 if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
2896 CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
2897 InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
2898 } else {
2899 CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
2900 InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
2901 }
2902 //
2903 // Take a look at next OpCode to see whether current expression consists
2904 // of single OpCode
2905 //
2906 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2907 SingleOpCodeExpression = TRUE;
2908 }
2909 break;
2910
2911 case EFI_IFR_WARNING_IF_OP:
2912 //
2913 // Create an Expression node
2914 //
2915 CurrentExpression = CreateExpression (CurrentForm);
2916 CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));
2917 CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;
2918 CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF;
2919 InsertTailList (&CurrentStatement->WarningListHead, &CurrentExpression->Link);
2920
2921 //
2922 // Take a look at next OpCode to see whether current expression consists
2923 // of single OpCode
2924 //
2925 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2926 SingleOpCodeExpression = TRUE;
2927 }
2928 break;
2929
2930 case EFI_IFR_SUPPRESS_IF_OP:
2931 //
2932 // Question and Option will appear in scope of this OpCode
2933 //
2934 CurrentExpression = CreateExpression (CurrentForm);
2935 CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
2936
2937 if (CurrentForm == NULL) {
2938 InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);
2939 } else {
2940 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2941 }
2942
2943 if (SuppressForOption) {
2944 InScopeOptionSuppress = TRUE;
2945 OptionSuppressExpression = CurrentExpression;
2946 } else if (SuppressForQuestion) {
2947 mInScopeSuppress = TRUE;
2948 mSuppressExpression = CurrentExpression;
2949 } else {
2950 InScopeFormSuppress = TRUE;
2951 FormSuppressExpression = CurrentExpression;
2952 }
2953 //
2954 // Take a look at next OpCode to see whether current expression consists
2955 // of single OpCode
2956 //
2957 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2958 SingleOpCodeExpression = TRUE;
2959 }
2960 break;
2961
2962 case EFI_IFR_GRAY_OUT_IF_OP:
2963 //
2964 // Questions will appear in scope of this OpCode
2965 //
2966 CurrentExpression = CreateExpression (CurrentForm);
2967 CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
2968 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2969
2970 mInScopeGrayOut = TRUE;
2971 mGrayOutExpression = CurrentExpression;
2972
2973 //
2974 // Take a look at next OpCode to see whether current expression consists
2975 // of single OpCode
2976 //
2977 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
2978 SingleOpCodeExpression = TRUE;
2979 }
2980 break;
2981
2982 case EFI_IFR_DISABLE_IF_OP:
2983 //
2984 // The DisableIf expression should only rely on constant, so it could be
2985 // evaluated at initialization and it will not be queued
2986 //
2987 CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
2988 ASSERT (CurrentExpression != NULL);
2989 CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
2990 CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
2991 InitializeListHead (&CurrentExpression->OpCodeListHead);
2992
2993 if (CurrentForm != NULL) {
2994 //
2995 // This is DisableIf for Question, enqueue it to Form expression list
2996 //
2997 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
2998 }
2999
3000 mDisableExpression = CurrentExpression;
3001 mInScopeDisable = TRUE;
3002 OpCodeDisabled = FALSE;
3003
3004 //
3005 // Take a look at next OpCode to see whether current expression consists
3006 // of single OpCode
3007 //
3008 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
3009 SingleOpCodeExpression = TRUE;
3010 }
3011 break;
3012
3013 //
3014 // Expression
3015 //
3016 case EFI_IFR_VALUE_OP:
3017 CurrentExpression = CreateExpression (CurrentForm);
3018 CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
3019 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
3020
3021 if (InScopeDefault) {
3022 //
3023 // Used for default (EFI_IFR_DEFAULT)
3024 //
3025 CurrentDefault->ValueExpression = CurrentExpression;
3026 } else {
3027 //
3028 // If used for a question, then the question will be read-only
3029 //
3030 //
3031 // Make sure CurrentStatement is not NULL.
3032 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
3033 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
3034 //
3035 ASSERT (CurrentStatement != NULL);
3036 CurrentStatement->ValueExpression = CurrentExpression;
3037 }
3038
3039 //
3040 // Take a look at next OpCode to see whether current expression consists
3041 // of single OpCode
3042 //
3043 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
3044 SingleOpCodeExpression = TRUE;
3045 }
3046 break;
3047
3048 case EFI_IFR_RULE_OP:
3049 CurrentExpression = CreateExpression (CurrentForm);
3050 CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
3051
3052 CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
3053 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
3054
3055 //
3056 // Take a look at next OpCode to see whether current expression consists
3057 // of single OpCode
3058 //
3059 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
3060 SingleOpCodeExpression = TRUE;
3061 }
3062 break;
3063
3064 case EFI_IFR_READ_OP:
3065 CurrentExpression = CreateExpression (CurrentForm);
3066 CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
3067 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
3068
3069 //
3070 // Make sure CurrentStatement is not NULL.
3071 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
3072 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
3073 //
3074 ASSERT (CurrentStatement != NULL);
3075 CurrentStatement->ReadExpression = CurrentExpression;
3076
3077 //
3078 // Take a look at next OpCode to see whether current expression consists
3079 // of single OpCode
3080 //
3081 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
3082 SingleOpCodeExpression = TRUE;
3083 }
3084 break;
3085
3086 case EFI_IFR_WRITE_OP:
3087 CurrentExpression = CreateExpression (CurrentForm);
3088 CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
3089 InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
3090
3091 //
3092 // Make sure CurrentStatement is not NULL.
3093 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
3094 // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
3095 //
3096 ASSERT (CurrentStatement != NULL);
3097 CurrentStatement->WriteExpression = CurrentExpression;
3098
3099 //
3100 // Take a look at next OpCode to see whether current expression consists
3101 // of single OpCode
3102 //
3103 if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
3104 SingleOpCodeExpression = TRUE;
3105 }
3106 break;
3107
3108 //
3109 // Image
3110 //
3111 case EFI_IFR_IMAGE_OP:
3112 //
3113 // Get ScopeOpcode from top of stack
3114 //
3115 PopScope (&ScopeOpCode);
3116 PushScope (ScopeOpCode);
3117
3118 switch (ScopeOpCode) {
3119 case EFI_IFR_FORM_SET_OP:
3120 break;
3121
3122 case EFI_IFR_FORM_OP:
3123 case EFI_IFR_FORM_MAP_OP:
3124 ASSERT (CurrentForm != NULL);
3125 break;
3126
3127 case EFI_IFR_ONE_OF_OPTION_OP:
3128 break;
3129
3130 default:
3131 //
3132 // Make sure CurrentStatement is not NULL.
3133 // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
3134 // file is wrongly generated by tools such as VFR Compiler.
3135 //
3136 ASSERT (CurrentStatement != NULL);
3137 break;
3138 }
3139 break;
3140
3141 //
3142 // Refresh
3143 //
3144 case EFI_IFR_REFRESH_OP:
3145 break;
3146
3147 //
3148 // Refresh guid.
3149 //
3150 case EFI_IFR_REFRESH_ID_OP:
3151 break;
3152
3153 //
3154 // Modal tag
3155 //
3156 case EFI_IFR_MODAL_TAG_OP:
3157 break;
3158
3159 //
3160 // Vendor specific
3161 //
3162 case EFI_IFR_GUID_OP:
3163 if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarGuid)==0) {
3164 Scope = 0;
3165 BitFieldStorage = TRUE;
3166 }
3167 break;
3168
3169 //
3170 // Scope End
3171 //
3172 case EFI_IFR_END_OP:
3173 BitFieldStorage = FALSE;
3174 Status = PopScope (&ScopeOpCode);
3175 if (EFI_ERROR (Status)) {
3176 ResetScopeStack ();
3177 return Status;
3178 }
3179
3180 switch (ScopeOpCode) {
3181 case EFI_IFR_FORM_SET_OP:
3182 //
3183 // End of FormSet, update FormSet IFR binary length
3184 // to stop parsing substantial OpCodes
3185 //
3186 FormSet->IfrBinaryLength = OpCodeOffset;
3187 break;
3188
3189 case EFI_IFR_FORM_OP:
3190 case EFI_IFR_FORM_MAP_OP:
3191 //
3192 // End of Form
3193 //
3194 CurrentForm = NULL;
3195 SuppressForQuestion = FALSE;
3196 break;
3197
3198 case EFI_IFR_ONE_OF_OPTION_OP:
3199 //
3200 // End of Option
3201 //
3202 CurrentOption = NULL;
3203 break;
3204
3205 case EFI_IFR_SUBTITLE_OP:
3206 mInScopeSubtitle = FALSE;
3207 break;
3208
3209 case EFI_IFR_NO_SUBMIT_IF_OP:
3210 case EFI_IFR_INCONSISTENT_IF_OP:
3211 case EFI_IFR_WARNING_IF_OP:
3212 //
3213 // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
3214 //
3215 break;
3216
3217 case EFI_IFR_SUPPRESS_IF_OP:
3218 if (SuppressForOption) {
3219 InScopeOptionSuppress = FALSE;
3220 } else if (SuppressForQuestion) {
3221 mInScopeSuppress = FALSE;
3222 } else {
3223 InScopeFormSuppress = FALSE;
3224 }
3225 break;
3226
3227 case EFI_IFR_GRAY_OUT_IF_OP:
3228 mInScopeGrayOut = FALSE;
3229 break;
3230
3231 case EFI_IFR_DISABLE_IF_OP:
3232 mInScopeDisable = FALSE;
3233 OpCodeDisabled = FALSE;
3234 break;
3235
3236 case EFI_IFR_ONE_OF_OP:
3237 case EFI_IFR_ORDERED_LIST_OP:
3238 SuppressForOption = FALSE;
3239 break;
3240
3241 case EFI_IFR_DEFAULT_OP:
3242 InScopeDefault = FALSE;
3243 break;
3244
3245 case EFI_IFR_MAP_OP:
3246 //
3247 // Get current Map Expression List.
3248 //
3249 Status = PopMapExpressionList ((VOID **) &MapExpressionList);
3250 if (Status == EFI_ACCESS_DENIED) {
3251 MapExpressionList = NULL;
3252 }
3253 //
3254 // Get current expression.
3255 //
3256 Status = PopCurrentExpression ((VOID **) &CurrentExpression);
3257 ASSERT (!EFI_ERROR (Status));
3258 ASSERT (MapScopeDepth > 0);
3259 MapScopeDepth --;
3260 break;
3261
3262 default:
3263 if (IsExpressionOpCode (ScopeOpCode)) {
3264 if (mInScopeDisable && (CurrentForm == NULL)) {
3265 //
3266 // This is DisableIf expression for Form, it should be a constant expression
3267 //
3268 ASSERT (CurrentExpression != NULL);
3269 ConstantFlag = TRUE;
3270 Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression, &ConstantFlag);
3271 if (EFI_ERROR (Status)) {
3272 return Status;
3273 }
3274 if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
3275 return EFI_INVALID_PARAMETER;
3276 }
3277 if (!ConstantFlag) {
3278 StringPrint ("WARNING. The DisableIf expression for Form should be a constant expression.\n");
3279 }
3280 OpCodeDisabled = CurrentExpression->Result.Value.b;
3281 //
3282 // DisableIf Expression is only used once and not queued, free it
3283 //
3284 DestroyExpression (CurrentExpression);
3285 }
3286
3287 //
3288 // End of current Expression
3289 //
3290 CurrentExpression = NULL;
3291 }
3292 break;
3293 }
3294 break;
3295
3296 default:
3297 break;
3298 }
3299 }
3300
3301 return EFI_SUCCESS;
3302 }
3303
3304 /**
3305 Search an Option of a Question by its value.
3306
3307 @param Question The Question
3308 @param OptionValue Value for Option to be searched.
3309
3310 @retval Pointer Pointer to the found Option.
3311 @retval NULL Option not found.
3312
3313 **/
3314 QUESTION_OPTION *
3315 ValueToOption (
3316 IN FORM_BROWSER_FORMSET *FormSet,
3317 IN FORM_BROWSER_STATEMENT *Question,
3318 IN EFI_HII_VALUE *OptionValue
3319 )
3320 {
3321 LIST_ENTRY *Link;
3322 QUESTION_OPTION *Option;
3323
3324 Link = GetFirstNode (&Question->OptionListHead);
3325 while (!IsNull (&Question->OptionListHead, Link)) {
3326 Option = QUESTION_OPTION_FROM_LINK (Link);
3327
3328 if (CompareHiiValue (&Option->Value, OptionValue, FormSet) == 0) {
3329 return Option;
3330 }
3331
3332 Link = GetNextNode (&Question->OptionListHead, Link);
3333 }
3334
3335 return NULL;
3336 }
3337
3338 /**
3339 Set value of a data element in an Array by its Index.
3340
3341 @param Array The data array.
3342 @param Type Type of the data in this array.
3343 @param Index Zero based index for data in this array.
3344 @param Value The value to be set.
3345
3346 **/
3347 VOID
3348 SetArrayData (
3349 IN VOID *Array,
3350 IN UINT8 Type,
3351 IN UINTN Index,
3352 IN UINT64 Value
3353 )
3354 {
3355
3356 ASSERT (Array != NULL);
3357
3358 switch (Type) {
3359 case EFI_IFR_TYPE_NUM_SIZE_8:
3360 *(((UINT8 *) Array) + Index) = (UINT8) Value;
3361 break;
3362
3363 case EFI_IFR_TYPE_NUM_SIZE_16:
3364 *(((UINT16 *) Array) + Index) = (UINT16) Value;
3365 break;
3366
3367 case EFI_IFR_TYPE_NUM_SIZE_32:
3368 *(((UINT32 *) Array) + Index) = (UINT32) Value;
3369 break;
3370
3371 case EFI_IFR_TYPE_NUM_SIZE_64:
3372 *(((UINT64 *) Array) + Index) = (UINT64) Value;
3373 break;
3374
3375 default:
3376 break;
3377 }
3378 }
3379
3380 /**
3381 Reset Question of five kinds to its default value.
3382
3383 @param FormSet The form set.
3384 @param Form The form.
3385 @param Question The question.
3386 @param DefaultId The default Id.
3387 @param DefaultId The platform Id.
3388
3389 @retval EFI_SUCCESS Question is reset to default value.
3390
3391 **/
3392 EFI_STATUS
3393 GetQuestionDefault (
3394 IN FORM_BROWSER_FORMSET *FormSet,
3395 IN FORM_BROWSER_FORM *Form,
3396 IN FORM_BROWSER_STATEMENT *Question,
3397 IN UINT16 DefaultId,
3398 IN UINT64 PlatformId
3399 )
3400 {
3401 EFI_STATUS Status;
3402 LIST_ENTRY *Link;
3403 QUESTION_DEFAULT *Default;
3404 QUESTION_OPTION *Option;
3405 EFI_HII_VALUE *HiiValue;
3406 UINT8 Index;
3407 FORMSET_STORAGE *VarList;
3408 UINT8 *VarBuffer;
3409 BOOLEAN ConstantFlag;
3410 UINT16 OriginalDefaultId;
3411 FORMSET_DEFAULTSTORE *DefaultStore;
3412 LIST_ENTRY *DefaultLink;
3413 CHAR16 *VarDefaultName;
3414
3415 VarDefaultName = NULL;
3416 Status = EFI_SUCCESS;
3417 ConstantFlag = TRUE;
3418 OriginalDefaultId = DefaultId;
3419 DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
3420
3421 //
3422 // Statement don't have storage, skip them
3423 //
3424 if (Question->QuestionId == 0) {
3425 return EFI_NOT_FOUND;
3426 }
3427 //
3428 // Return if no any kinds of
3429 //
3430 if ((Question->Operand != EFI_IFR_CHECKBOX_OP)
3431 && (Question->Operand != EFI_IFR_ONE_OF_OP)
3432 && (Question->Operand != EFI_IFR_ORDERED_LIST_OP)
3433 && (Question->Operand != EFI_IFR_NUMERIC_OP)
3434 && (Question->Operand != EFI_IFR_STRING_OP)
3435 ) {
3436 return EFI_ABORTED;
3437 }
3438 //
3439 // Search the variable for this question (Compatible with the old EfiVarStore before UEFI2.31)
3440 //
3441
3442 //
3443 //VarStoreInfoDepending on the type of variable store selected,
3444 //this contains either a 16-bit Buffer Storage offset (VarOffset)
3445 //or a Name/Value or EFI Variable name (VarName).
3446 //
3447 Status = SearchVarStorage (
3448 Question,
3449 NULL,
3450 Question->VarStoreInfo.VarOffset,
3451 FormSet->StorageListHead,
3452 (CHAR8 **)&VarBuffer,
3453 &VarList
3454 );
3455 if (EFI_ERROR(Status)) {
3456 return Status;
3457 }
3458 //
3459 // There are three ways to specify default value for a Question:
3460 // 1, use nested EFI_IFR_DEFAULT
3461 // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3462 // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3463 //
3464 ReGetDefault:
3465 HiiValue = &Question->HiiValue;
3466 //
3467 // EFI_IFR_DEFAULT has highest priority
3468 //
3469 if (!IsListEmpty (&Question->DefaultListHead)) {
3470 Link = GetFirstNode (&Question->DefaultListHead);
3471 while (!IsNull (&Question->DefaultListHead, Link)) {
3472 Default = QUESTION_DEFAULT_FROM_LINK (Link);
3473
3474 if (Default->DefaultId == DefaultId) {
3475 if (Default->ValueExpression != NULL) {
3476 //
3477 // Default is provided by an Expression, evaluate it
3478 //
3479 Status = EvaluateExpression (FormSet, Form, Default->ValueExpression, &ConstantFlag);
3480 if (EFI_ERROR (Status)) {
3481 return Status;
3482 }
3483
3484 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
3485 if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {
3486 CopyMem(Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);
3487 Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;
3488 } else {
3489 CopyMem(Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);
3490 Question->HiiValue.BufferLen = Question->StorageWidth;
3491 }
3492 FreePool(Default->ValueExpression->Result.Buffer);
3493 }
3494 HiiValue->Type = Default->ValueExpression->Result.Type;
3495 CopyMem(&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
3496 } else {
3497 //
3498 // Default value is embedded in EFI_IFR_DEFAULT
3499 //
3500 if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
3501 CopyMem(HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);
3502 } else {
3503 CopyMem(HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
3504 }
3505 }
3506 if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
3507 CopyMem(VarBuffer, HiiValue->Buffer, HiiValue->BufferLen);
3508 } else if (HiiValue->Type == EFI_IFR_TYPE_STRING){
3509 Status = FindDefaultName (
3510 &(FormSet->EnUsStringList),
3511 FormSet->UnicodeBinary,
3512 HiiValue->Value.string,
3513 EN_US,
3514 &VarDefaultName
3515 );
3516 if (VarDefaultName == NULL) {
3517 return EFI_NOT_FOUND;
3518 }
3519 if (Question->StorageWidth > FceStrSize(VarDefaultName)) {
3520 ZeroMem (VarBuffer, Question->StorageWidth);
3521 CopyMem (VarBuffer, VarDefaultName, FceStrSize(VarDefaultName));
3522 } else {
3523 CopyMem (VarBuffer, VarDefaultName, Question->StorageWidth);
3524 }
3525 } else {
3526 if (Question->QuestionReferToBitField) {
3527 SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
3528 } else {
3529 CopyMem(VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
3530 }
3531 }
3532 return EFI_SUCCESS;
3533 }
3534 if (Default->DefaultId == DefaultId) {
3535 return EFI_SUCCESS;
3536 }
3537 Link = GetNextNode (&Question->DefaultListHead, Link);
3538 }
3539 }
3540
3541 if (HiiValue->Buffer == NULL) {
3542 ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
3543 }
3544
3545 //
3546 // EFI_ONE_OF_OPTION
3547 //
3548 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
3549 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
3550 //
3551 // OneOfOption could only provide Standard and Manufacturing default
3552 //
3553 Link = GetFirstNode (&Question->OptionListHead);
3554 while (!IsNull (&Question->OptionListHead, Link)) {
3555 Option = QUESTION_OPTION_FROM_LINK (Link);
3556
3557 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
3558 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
3559 ) {
3560 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
3561 if (Question->QuestionReferToBitField) {
3562 SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
3563 } else {
3564 CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
3565 }
3566 return EFI_SUCCESS;
3567 }
3568
3569 Link = GetNextNode (&Question->OptionListHead, Link);
3570 }
3571 }
3572 }
3573
3574 //
3575 // EFI_IFR_CHECKBOX - lowest priority
3576 //
3577 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
3578 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
3579 //
3580 // Checkbox could only provide Standard and Manufacturing default
3581 //
3582 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
3583 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
3584 ) {
3585 HiiValue->Value.b = TRUE;
3586 if (Question->QuestionReferToBitField) {
3587 SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
3588 } else {
3589 CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
3590 }
3591 return EFI_SUCCESS;
3592 }
3593 }
3594 }
3595
3596 //
3597 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
3598 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
3599 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
3600 //
3601 while (!IsNull(&FormSet->DefaultStoreListHead, DefaultLink)) {
3602 DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
3603 DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead,DefaultLink);
3604 DefaultId = DefaultStore->DefaultId;
3605 if (DefaultId == OriginalDefaultId) {
3606 continue;
3607 }
3608 goto ReGetDefault;
3609 }
3610
3611 //
3612 // For Questions without default
3613 //
3614 Status = EFI_NOT_FOUND;
3615 switch (Question->Operand) {
3616 case EFI_IFR_CHECKBOX_OP:
3617 HiiValue->Value.b = FALSE;
3618 if (Question->QuestionReferToBitField) {
3619 SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
3620 } else {
3621 CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
3622 }
3623 break;
3624
3625 case EFI_IFR_NUMERIC_OP:
3626 //
3627 // Take minimum value as numeric default value
3628 //
3629 if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {
3630 HiiValue->Value.u64 = Question->Minimum;
3631 if (Question->QuestionReferToBitField) {
3632 SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
3633 } else {
3634 CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
3635 }
3636 return EFI_SUCCESS;
3637 }
3638 break;
3639
3640 case EFI_IFR_ONE_OF_OP:
3641 //
3642 // Take first oneof option as oneof's default value
3643 //
3644 if (ValueToOption (FormSet, Question, HiiValue) == NULL) {
3645 Link = GetFirstNode (&Question->OptionListHead);
3646 if (!IsNull (&Question->OptionListHead, Link)) {
3647 Option = QUESTION_OPTION_FROM_LINK (Link);
3648 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
3649 if (Question->QuestionReferToBitField) {
3650 SetBitsQuestionValue(Question, VarBuffer, HiiValue->Value.u32);
3651 } else {
3652 CopyMem (VarBuffer, &HiiValue->Value.u64, Question->StorageWidth);
3653 }
3654 return EFI_SUCCESS;
3655 }
3656 }
3657 break;
3658
3659 case EFI_IFR_ORDERED_LIST_OP:
3660 //
3661 // Take option sequence in IFR as ordered list's default value
3662 //
3663 Index = 0;
3664 Link = GetFirstNode (&Question->OptionListHead);
3665 while (!IsNull (&Question->OptionListHead, Link)) {
3666 Option = QUESTION_OPTION_FROM_LINK (Link);
3667
3668 SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);
3669 SetArrayData (VarBuffer, Question->ValueType, Index, Option->Value.Value.u64);
3670
3671 Index++;
3672 if (Index >= Question->MaxContainers) {
3673 break;
3674 }
3675
3676 Link = GetNextNode (&Question->OptionListHead, Link);
3677 }
3678 break;
3679
3680 default:
3681 break;
3682 }
3683
3684 return EFI_SUCCESS;
3685 }
3686
3687 /**
3688 Set the value to the variable of platformId question.
3689
3690 @param PlatformId The form set.
3691
3692 @retval EFI_SUCCESS Set successfully.
3693
3694 **/
3695 EFI_STATUS
3696 AssignThePlatformId (
3697 IN UINT64 PlatformId
3698 )
3699 {
3700 EFI_STATUS Status;
3701 FORMSET_STORAGE *VarList;
3702 UINT8 *VarBuffer;
3703
3704 Status = EFI_SUCCESS;
3705 VarBuffer = NULL;
3706 //
3707 // Set the Storage
3708 //
3709 Status = SearchVarStorage (
3710 &mMultiPlatformParam.PlatformIdQuestion,
3711 NULL,
3712 mMultiPlatformParam.PlatformIdQuestion.VarStoreInfo.VarOffset,
3713 &mVarListEntry,
3714 (CHAR8 **)&VarBuffer,
3715 &VarList
3716 );
3717 if (EFI_ERROR(Status)) {
3718 return Status;
3719 }
3720 CopyMem (VarBuffer, &PlatformId, mMultiPlatformParam.PlatformIdWidth);
3721 //
3722 // Set the HIIvalue of this questions
3723 //
3724 CopyMem (&mMultiPlatformParam.Question->HiiValue.Value.u64, &PlatformId, mMultiPlatformParam.PlatformIdWidth);
3725
3726 switch (mMultiPlatformParam.PlatformIdWidth) {
3727 case sizeof (UINT8):
3728 mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
3729 break;
3730
3731 case sizeof (UINT16):
3732 mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_16;
3733 break;
3734
3735 case sizeof (UINT32):
3736 mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_32;
3737 break;
3738
3739 case sizeof (UINT64):
3740 mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_64;
3741 break;
3742
3743 default:
3744 mMultiPlatformParam.Question->HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_64;
3745 }
3746 return EFI_SUCCESS;
3747 }
3748 /**
3749 Reset Questions to their default value in a Form, Formset or System.
3750
3751 @param FormSet FormSet data structure.
3752 @param Form Form data structure.
3753 @param DefaultId The default Id
3754 @param PlatformId The platform Id
3755 @param SettingScope Setting Scope for Default action.
3756
3757 @retval EFI_SUCCESS The function completed successfully.
3758 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3759
3760 **/
3761 EFI_STATUS
3762 ExtractDefault (
3763 IN FORM_BROWSER_FORMSET *FormSet,
3764 IN FORM_BROWSER_FORM *Form,
3765 IN UINT16 DefaultId,
3766 IN UINT64 PlatformId,
3767 IN BROWSER_SETTING_SCOPE SettingScope
3768 )
3769 {
3770 EFI_STATUS Status;
3771 LIST_ENTRY *FormLink;
3772 LIST_ENTRY *Link;
3773 LIST_ENTRY *FormSetEntryListHead;
3774 FORM_BROWSER_STATEMENT *Question;
3775 //
3776 // Check the supported setting level.
3777 //
3778 if (SettingScope >= MaxLevel) {
3779 return EFI_UNSUPPORTED;
3780 }
3781
3782 if (SettingScope == FormLevel) {
3783 //
3784 // Extract Form default
3785 //
3786 Link = GetFirstNode (&Form->StatementListHead);
3787 while (!IsNull (&Form->StatementListHead, Link)) {
3788 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
3789 Link = GetNextNode (&Form->StatementListHead, Link);
3790 //
3791 // Re-set the platformId before calcuate the platformId of every question to avoid over-written.
3792 //
3793 if (mMultiPlatformParam.MultiPlatformOrNot) {
3794 Status = AssignThePlatformId (PlatformId);
3795 if (EFI_ERROR (Status)) {
3796 StringPrint ("Error. Failed to assign the platformId.\n");
3797 return Status;
3798 }
3799 }
3800 //
3801 // Reset Question to its default value, and store the default to variable
3802 //
3803 Status = GetQuestionDefault (FormSet, Form, Question, DefaultId, PlatformId);
3804 if (EFI_ERROR (Status)) {
3805 continue;
3806 }
3807 }
3808 } else if (SettingScope == FormSetLevel) {
3809 FormLink = GetFirstNode (&FormSet->FormListHead);
3810 while (!IsNull (&FormSet->FormListHead, FormLink)) {
3811 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
3812 ExtractDefault (FormSet, Form, DefaultId, PlatformId, FormLevel);
3813 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
3814 }
3815 } else if (SettingScope == SystemLevel) {
3816 //
3817 // Parse Fromset one by one
3818 //
3819 FormSetEntryListHead = &mFormSetListEntry;
3820
3821 FormLink = GetFirstNode (FormSetEntryListHead);
3822 while (!IsNull (FormSetEntryListHead, FormLink)) {
3823 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormLink);
3824 ExtractDefault (FormSet, NULL, DefaultId, PlatformId, FormSetLevel);
3825 FormLink = GetNextNode (FormSetEntryListHead, FormLink);
3826 }
3827 }
3828
3829 return EFI_SUCCESS;
3830 }
3831
3832 /**
3833 Check whether existed the UQI in Current Unicode String.
3834
3835 @param UniPackge A pointer to a Null-terminated Unicode string Array.
3836
3837 @return TRUE If find the uqi, return TRUE
3838 @return FALSE Otherwise, return FALSE
3839
3840 **/
3841 static
3842 BOOLEAN
3843 IsUqiOrNot (
3844 IN UINT8 *UniPackge
3845 )
3846 {
3847 CHAR8 *UniBin;
3848 UINTN UniLength;
3849 UINTN Index;
3850 BOOLEAN FindIt;
3851
3852 UniBin = (CHAR8 *) UniPackge + 4;
3853 Index = 4;
3854 FindIt = FALSE;
3855 UniLength = *(UINT32 *) UniPackge;
3856
3857 if (((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS) {
3858 //
3859 // Search the uqi language
3860 //
3861 while ((Index < UniLength) && ((EFI_HII_PACKAGE_HEADER *)UniBin)->Type == EFI_HII_PACKAGE_STRINGS){
3862 if (!strcmp (((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Language, "uqi")) {
3863 FindIt = TRUE;
3864 break;
3865 }
3866 Index = Index + ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
3867 UniBin += ((EFI_HII_STRING_PACKAGE_HDR *)UniBin)->Header.Length;
3868 }
3869 }
3870 return FindIt;
3871 }
3872
3873 /**
3874 Returns Length of UQI string (in CHAR16) (not including null termination).
3875
3876 @param UniPackge A pointer to a UQI string.
3877
3878 @return Number Length of UQIL string (in words) or 0
3879
3880 **/
3881 static
3882 UINT16
3883 GetUqiNum (
3884 IN CHAR16 *UniString
3885 )
3886 {
3887 UINT16 Number;
3888
3889 if (UniString == NULL) {
3890 return 0;
3891 }
3892 for (Number = 0; UniString[Number] != 0; Number++) {
3893 ;
3894 }
3895 return Number;
3896 }
3897
3898 /**
3899 Print the formset title information.
3900
3901 @param FormSet The pointer to the formset.
3902
3903 @return NULL.
3904
3905 **/
3906 static
3907 VOID
3908 StringPrintormSetTitle (
3909 IN FORM_BROWSER_FORMSET *FormSet
3910 )
3911 {
3912 CHAR16 *VarDefaultName;
3913 EFI_STATUS Status;
3914
3915 VarDefaultName = NULL;
3916
3917 StringPrint("\n\n// Form Set: ");
3918
3919 Status = FindDefaultName (
3920 &(FormSet->EnUsStringList),
3921 FormSet->UnicodeBinary,
3922 FormSet->FormSetTitle,
3923 EN_US,
3924 &VarDefaultName
3925 );
3926 assert (!EFI_ERROR (Status));
3927 LogUnicodeString (VarDefaultName);
3928
3929 StringPrint("\n// %s",FORM_SET_GUID_PREFIX);
3930 StringPrint(
3931 EFI_GUID_FORMAT,
3932 FormSet->Guid.Data1, FormSet->Guid.Data2,
3933 FormSet->Guid.Data3, FormSet->Guid.Data4[0],
3934 FormSet->Guid.Data4[1],FormSet->Guid.Data4[2],
3935 FormSet->Guid.Data4[3],FormSet->Guid.Data4[4],
3936 FormSet->Guid.Data4[5],FormSet->Guid.Data4[6],
3937 FormSet->Guid.Data4[7]);
3938 StringPrint("\n");
3939
3940 if (&(FormSet->EnUsStringList) == NULL && VarDefaultName != NULL && FormSet->FormSetTitle != 0) {
3941 free (VarDefaultName);
3942 VarDefaultName = NULL;
3943 }
3944 }
3945
3946 /**
3947 Print the formset title information.
3948
3949 @param FormSet The pointer to the formset.
3950 @param Question The pointer to the question of ONE_OF.
3951
3952 @return NULL.
3953
3954 **/
3955 static
3956 EFI_STATUS
3957 PrintOneOfOptions (
3958 IN FORM_BROWSER_FORMSET *FormSet,
3959 IN FORM_BROWSER_STATEMENT *Question
3960 )
3961 {
3962 LIST_ENTRY *Link;
3963 QUESTION_OPTION *Option;
3964 CHAR16 *VarDefaultName;
3965 EFI_STATUS Status;
3966
3967 Status = EFI_SUCCESS;
3968 VarDefaultName = NULL;
3969
3970 if ((Question->Operand != EFI_IFR_ONE_OF_OP)
3971 && (Question->Operand != EFI_IFR_ORDERED_LIST_OP)
3972 ) {
3973 return EFI_ABORTED;
3974 }
3975
3976 Link = GetFirstNode (&Question->OptionListHead);
3977 while (!IsNull (&Question->OptionListHead, Link)) {
3978 Option = QUESTION_OPTION_FROM_LINK (Link);
3979 if (Question->QuestionReferToBitField) {
3980 StringPrint("// %08X = ", Option->Value.Value.u32);
3981 } else {
3982 switch(Option->Value.Type) {
3983
3984 case EFI_IFR_TYPE_NUM_SIZE_8:
3985 StringPrint("// %02X = ", Option->Value.Value.u8);
3986 break;
3987
3988 case EFI_IFR_TYPE_NUM_SIZE_16:
3989 StringPrint("// %04X = ", Option->Value.Value.u16);
3990 break;
3991
3992 case EFI_IFR_TYPE_NUM_SIZE_32:
3993 StringPrint("// %08X = ", Option->Value.Value.u32);
3994 break;
3995
3996 case EFI_IFR_TYPE_NUM_SIZE_64:
3997 StringPrint("// %016llX = ", Option->Value.Value.u64);
3998 break;
3999
4000 case EFI_IFR_TYPE_BOOLEAN:
4001 StringPrint("// %X = ", Option->Value.Value.b);
4002 break;
4003
4004 case EFI_IFR_TYPE_STRING:
4005 StringPrint("// %X = ", Option->Value.Value.string);
4006 break;
4007
4008 default:
4009 break;
4010 }
4011 }
4012 Status = FindDefaultName (
4013 &(FormSet->EnUsStringList),
4014 FormSet->UnicodeBinary,
4015 Option->Text,
4016 EN_US,
4017 &VarDefaultName
4018 );
4019
4020 LogUnicodeString (VarDefaultName);
4021 StringPrint("\n");
4022 if (&(FormSet->EnUsStringList) == NULL && VarDefaultName != NULL && Option->Text != 0) {
4023 free (VarDefaultName);
4024 VarDefaultName = NULL;
4025 }
4026 Link = GetNextNode (&Question->OptionListHead, Link);
4027 }
4028 return Status;
4029 }
4030
4031 /**
4032 Print the form title information.
4033
4034 @param FormSet The pointer to the formset.
4035 @param FormSet The pointer to the form.
4036
4037 @return NULL.
4038
4039 **/
4040 static
4041 VOID
4042 StringPrintormTitle (
4043 IN FORM_BROWSER_FORMSET *FormSet,
4044 IN FORM_BROWSER_FORM *Form
4045 )
4046 {
4047 CHAR16 *VarDefaultName;
4048 EFI_STATUS Status;
4049
4050 VarDefaultName = NULL;
4051
4052 StringPrint("\n// Form: ");
4053 Status = FindDefaultName (
4054 &(FormSet->EnUsStringList),
4055 FormSet->UnicodeBinary,
4056 Form->FormTitle,
4057 EN_US,
4058 &VarDefaultName
4059 );
4060 assert (!EFI_ERROR (Status));
4061
4062 LogUnicodeString (VarDefaultName);
4063 StringPrint("\n");
4064
4065 if (&(FormSet->EnUsStringList) == NULL && VarDefaultName != NULL && Form->FormTitle != 0) {
4066 free (VarDefaultName);
4067 VarDefaultName = NULL;
4068 }
4069
4070 }
4071
4072 /**
4073 Print the information of questions.
4074
4075 @param FormSet The pointer to the formset.
4076 @param FormSet The pointer to the form.
4077 @param Question The pointer to the question.
4078 @param PrintOrNot Decide whether print or not.
4079
4080 @return NULL.
4081
4082 **/
4083 static
4084 VOID
4085 PrintQuestion (
4086 IN FORM_BROWSER_FORMSET *FormSet,
4087 IN FORM_BROWSER_FORM *Form,
4088 IN FORM_BROWSER_STATEMENT *Question,
4089 IN BOOLEAN PrintOrNot
4090 )
4091 {
4092 EFI_STATUS Status;
4093 CHAR16 *VarDefaultName;
4094 UINT16 UqiStringLength;
4095 BOOLEAN HaveUQIlanguage;
4096
4097 Status = EFI_SUCCESS;
4098 VarDefaultName = NULL;
4099 UqiStringLength = 0;
4100
4101 HaveUQIlanguage = IsUqiOrNot (FormSet->UnicodeBinary);
4102
4103 switch (Question->Operand) {
4104
4105 case EFI_IFR_SUBTITLE_OP:
4106 if (PrintOrNot) {
4107 Status = FindDefaultName (
4108 &(FormSet->EnUsStringList),
4109 FormSet->UnicodeBinary,
4110 Question->Prompt,
4111 EN_US,
4112 &VarDefaultName
4113 );
4114 assert (!EFI_ERROR (Status));
4115 if ((VarDefaultName != NULL) && (FceStrCmp (VarDefaultName, L"") != 0)) {
4116 StringPrint("// Subtitle: ");
4117 StringPrint("// ");
4118 LogUnicodeString (VarDefaultName);
4119 StringPrint("\n");
4120 }
4121 }
4122 break;
4123
4124 case EFI_IFR_ONE_OF_OP:
4125
4126 if( HaveUQIlanguage ) {
4127 Status = FindDefaultName (
4128 &(FormSet->UqiStringList),
4129 FormSet->UnicodeBinary,
4130 Question->Prompt,
4131 UQI,
4132 &VarDefaultName
4133 );
4134 assert (!EFI_ERROR (Status));
4135
4136 UqiStringLength = GetUqiNum (VarDefaultName);
4137 if (PrintOrNot) {
4138 if (UqiStringLength > 0) {
4139 StringPrint("\nQ %04X ", UqiStringLength);
4140 LogUqi(VarDefaultName);
4141 } else {
4142 StringPrint("\n// [No UQI] ");
4143 }
4144 }
4145 } else {
4146 Status = FindDefaultName (
4147 &(FormSet->EnUsStringList),
4148 FormSet->UnicodeBinary,
4149 Question->Prompt,
4150 EN_US,
4151 &VarDefaultName
4152 );
4153 assert (!EFI_ERROR (Status));
4154 UqiStringLength = GetUqiNum (VarDefaultName);
4155
4156 if (PrintOrNot) {
4157 if (UqiStringLength > 0) {
4158 StringPrint("\nQ %04X ", UqiStringLength);
4159 LogUqi(VarDefaultName);
4160 } else {
4161 StringPrint("\n// [No UQI] ");
4162 }
4163 }
4164 }
4165 //
4166 //Record the UQi to the Question
4167 //
4168 Question->Uqi.HexNum = UqiStringLength;
4169 Question->Uqi.Data = VarDefaultName;
4170 Question->Uqi.Type = ONE_OF;
4171
4172 if (PrintOrNot) {
4173 StringPrint("ONE_OF ");
4174
4175 LogIfrValue (
4176 FormSet,
4177 Question
4178 );
4179 StringPrint(" // ");
4180 Status = FindDefaultName (
4181 &(FormSet->EnUsStringList),
4182 FormSet->UnicodeBinary,
4183 Question->Prompt,
4184 EN_US,
4185 &VarDefaultName
4186 );
4187 assert (!EFI_ERROR (Status));
4188 LogUnicodeString (VarDefaultName);
4189 StringPrint("\n");
4190 //
4191 // Print ONE_OF_OPTION
4192 //
4193 PrintOneOfOptions (FormSet, Question);
4194 }
4195 break;
4196
4197 case EFI_IFR_CHECKBOX_OP:
4198
4199 if( HaveUQIlanguage ) {
4200 Status = FindDefaultName (
4201 &(FormSet->UqiStringList),
4202 FormSet->UnicodeBinary,
4203 Question->Prompt,
4204 UQI,
4205 &VarDefaultName
4206 );
4207 assert (!EFI_ERROR (Status));
4208
4209 UqiStringLength = GetUqiNum (VarDefaultName);
4210 if (PrintOrNot) {
4211 if (UqiStringLength > 0) {
4212 StringPrint("\nQ %04X ", UqiStringLength);
4213 LogUqi(VarDefaultName);
4214 } else {
4215 StringPrint("\n// [No UQI] ");
4216 }
4217 }
4218 } else {
4219 Status = FindDefaultName (
4220 &(FormSet->EnUsStringList),
4221 FormSet->UnicodeBinary,
4222 Question->Prompt,
4223 EN_US,
4224 &VarDefaultName
4225 );
4226 assert (!EFI_ERROR (Status));
4227
4228 UqiStringLength = GetUqiNum (VarDefaultName);
4229
4230 if (PrintOrNot) {
4231 if (UqiStringLength > 0) {
4232 StringPrint("\nQ %04X ", UqiStringLength);
4233 LogUqi(VarDefaultName);
4234 } else {
4235 StringPrint("\n// [No UQI] ");
4236 }
4237 }
4238 }
4239 //
4240 //Record the UQi to the HiiObjList
4241 //
4242 Question->Uqi.HexNum = UqiStringLength;
4243 Question->Uqi.Data = VarDefaultName;
4244 Question->Uqi.Type = CHECKBOX;
4245 if (PrintOrNot) {
4246 StringPrint("CHECKBOX ");
4247 LogIfrValue (
4248 FormSet,
4249 Question
4250 );
4251 StringPrint(" // ");
4252 Status = FindDefaultName (
4253 &(FormSet->EnUsStringList),
4254 FormSet->UnicodeBinary,
4255 Question->Prompt,
4256 EN_US,
4257 &VarDefaultName
4258 );
4259 assert (!EFI_ERROR (Status));
4260 LogUnicodeString (VarDefaultName);
4261 StringPrint("\n");
4262 StringPrint("// 0 = Unchecked\n");
4263 StringPrint("// 1 = Checked\n");
4264 }
4265 break;
4266
4267 case EFI_IFR_STRING_OP:
4268 if( HaveUQIlanguage ) {
4269 Status = FindDefaultName (
4270 &(FormSet->UqiStringList),
4271 FormSet->UnicodeBinary,
4272 Question->Prompt,
4273 UQI,
4274 &VarDefaultName
4275 );
4276 assert (!EFI_ERROR (Status));
4277
4278 UqiStringLength = GetUqiNum (VarDefaultName);
4279 if (PrintOrNot) {
4280 if (UqiStringLength > 0) {
4281 StringPrint("\nQ %04X ", UqiStringLength);
4282 LogUqi(VarDefaultName);
4283 } else {
4284 StringPrint("\n// [No UQI] ");
4285 }
4286 }
4287 } else {
4288 Status = FindDefaultName (
4289 &(FormSet->EnUsStringList),
4290 FormSet->UnicodeBinary,
4291 Question->Prompt,
4292 EN_US,
4293 &VarDefaultName
4294 );
4295 assert (!EFI_ERROR (Status));
4296
4297 UqiStringLength = GetUqiNum (VarDefaultName);
4298
4299 if (PrintOrNot) {
4300 if (UqiStringLength > 0) {
4301 StringPrint("\nQ %04X ", UqiStringLength);
4302 LogUqi(VarDefaultName);
4303 } else {
4304 StringPrint("\n// [No UQI] ");
4305 }
4306 }
4307 }
4308 //
4309 //Record the UQi to the HiiObjList
4310 //
4311 Question->Uqi.HexNum = UqiStringLength;
4312 Question->Uqi.Data = VarDefaultName;
4313 Question->Uqi.Type = STRING;
4314 if (PrintOrNot) {
4315 StringPrint("STRING ");
4316 LogIfrValueStr (
4317 FormSet,
4318 Question
4319 );
4320 StringPrint(" // ");
4321 Status = FindDefaultName (
4322 &(FormSet->EnUsStringList),
4323 FormSet->UnicodeBinary,
4324 Question->Prompt,
4325 EN_US,
4326 &VarDefaultName
4327 );
4328 assert (!EFI_ERROR (Status));
4329 LogUnicodeString (VarDefaultName);
4330 StringPrint("\n");
4331 }
4332 break;
4333
4334 case EFI_IFR_NUMERIC_OP:
4335
4336 if( HaveUQIlanguage ) {
4337 Status = FindDefaultName (
4338 &(FormSet->UqiStringList),
4339 FormSet->UnicodeBinary,
4340 Question->Prompt,
4341 UQI,
4342 &VarDefaultName
4343 );
4344 assert (!EFI_ERROR (Status));
4345
4346 UqiStringLength = GetUqiNum (VarDefaultName);
4347 if (PrintOrNot) {
4348 if (UqiStringLength > 0) {
4349 StringPrint("\nQ %04X ", UqiStringLength);
4350 LogUqi(VarDefaultName);
4351 } else {
4352 StringPrint("\n// [No UQI] ");
4353 }
4354 }
4355 } else {
4356 Status = FindDefaultName (
4357 &(FormSet->EnUsStringList),
4358 FormSet->UnicodeBinary,
4359 Question->Prompt,
4360 EN_US,
4361 &VarDefaultName
4362 );
4363 assert (!EFI_ERROR (Status));
4364
4365 UqiStringLength = GetUqiNum (VarDefaultName);
4366 if (PrintOrNot) {
4367 if (UqiStringLength > 0) {
4368 StringPrint("\nQ %04X ", UqiStringLength);
4369 LogUqi(VarDefaultName);
4370 } else {
4371 StringPrint("\n// [No UQI] ");
4372 }
4373 }
4374 }
4375 //
4376 //Record the UQi to the HiiObjList
4377 //
4378 Question->Uqi.HexNum = UqiStringLength;
4379 Question->Uqi.Data = VarDefaultName;
4380 Question->Uqi.Type = NUMERIC;
4381 if (PrintOrNot) {
4382 StringPrint("NUMERIC ");
4383 LogIfrValue (
4384 FormSet,
4385 Question
4386 );
4387 StringPrint(" // ");
4388 Status = FindDefaultName (
4389 &(FormSet->EnUsStringList),
4390 FormSet->UnicodeBinary,
4391 Question->Prompt,
4392 EN_US,
4393 &VarDefaultName
4394 );
4395 assert (!EFI_ERROR (Status));
4396 LogUnicodeString (VarDefaultName);
4397 StringPrint("\n");
4398
4399 if (Question->QuestionReferToBitField) {
4400 StringPrint("// Minimum = %08llX \n", Question->Minimum);
4401 StringPrint("// Maximum = %08llX \n", Question->Maximum);
4402 StringPrint("// Step = %08llX \n", Question->Step);
4403 } else {
4404 switch (Question->StorageWidth) {
4405
4406 case sizeof (UINT8):
4407 StringPrint("// Minimum = %02llX \n", Question->Minimum);
4408 StringPrint("// Maximum = %02llX \n", Question->Maximum);
4409 StringPrint("// Step = %02llX \n", Question->Step);
4410 break;
4411
4412 case sizeof (UINT16):
4413 StringPrint("// Minimum = %04llX \n", Question->Minimum);
4414 StringPrint("// Maximum = %04llX \n", Question->Maximum);
4415 StringPrint("// Step = %04llX \n", Question->Step);
4416 break;
4417
4418 case sizeof (UINT32):
4419 StringPrint("// Minimum = %08llX \n", Question->Minimum);
4420 StringPrint("// Maximum = %08llX \n", Question->Maximum);
4421 StringPrint("// Step = %08llX \n", Question->Step);
4422 break;
4423
4424 case sizeof (UINT64):
4425 StringPrint("// Minimum = %016llX \n", Question->Minimum);
4426 StringPrint("// Maximum = %016llX \n", Question->Maximum);
4427 StringPrint("// Step = %016llX \n", Question->Step);
4428 break;
4429
4430 default:
4431 StringPrint("0000 // Width > 16 is not supported -- FAILURE");
4432 break;
4433 }
4434 }
4435 }
4436 break;
4437
4438 case EFI_IFR_ORDERED_LIST_OP:
4439
4440 if( HaveUQIlanguage ) {
4441 Status = FindDefaultName (
4442 &(FormSet->UqiStringList),
4443 FormSet->UnicodeBinary,
4444 Question->Prompt,
4445 UQI,
4446 &VarDefaultName
4447 );
4448 assert (!EFI_ERROR (Status));
4449 UqiStringLength = GetUqiNum (VarDefaultName);
4450
4451 if (PrintOrNot) {
4452 if (UqiStringLength > 0) {
4453 StringPrint("\nQ %04X ", UqiStringLength);
4454 LogUqi(VarDefaultName);
4455 } else {
4456 StringPrint("\n// [No UQI] ");
4457 }
4458 }
4459 } else {
4460 Status = FindDefaultName (
4461 &(FormSet->EnUsStringList),
4462 FormSet->UnicodeBinary,
4463 Question->Prompt,
4464 EN_US,
4465 &VarDefaultName
4466 );
4467
4468 assert (!EFI_ERROR (Status));
4469
4470 UqiStringLength = GetUqiNum (VarDefaultName);
4471 if (PrintOrNot) {
4472 if (UqiStringLength > 0) {
4473 StringPrint("\nQ %04X ", UqiStringLength);
4474 LogUqi(VarDefaultName);
4475 } else {
4476 StringPrint("\n// [No UQI] ");
4477 }
4478 }
4479 }
4480 //
4481 //Record the UQi to the HiiObjList
4482 //
4483 Question->Uqi.HexNum = UqiStringLength;
4484 Question->Uqi.Data = VarDefaultName;
4485 Question->Uqi.Type = ORDERED_LIST;
4486
4487 if (PrintOrNot) {
4488 StringPrint("ORDERED_LIST %04X ", Question->MaxContainers);
4489
4490 LogIfrValueList (
4491 FormSet,
4492 Question
4493 );
4494 StringPrint(" // ");
4495 Status = FindDefaultName (
4496 &(FormSet->EnUsStringList),
4497 FormSet->UnicodeBinary,
4498 Question->Prompt,
4499 EN_US,
4500 &VarDefaultName
4501 );
4502 assert (!EFI_ERROR (Status));
4503 LogUnicodeString (VarDefaultName);
4504 StringPrint("\n");
4505 }
4506 //
4507 // Print ONE_OF_OPTION
4508 //
4509 PrintOneOfOptions (FormSet, Question);
4510 break;
4511
4512 default:
4513 break;
4514 }
4515
4516 if (&(FormSet->EnUsStringList) == NULL &&VarDefaultName != NULL && Question->Prompt != 0) {
4517 free (VarDefaultName);
4518 VarDefaultName = NULL;
4519 }
4520
4521 if (PrintOrNot && Question->Storage) {
4522 StringPrint("// size = 0x%x", Question->StorageWidth);
4523 StringPrint("\n// offset = 0x%x", Question->VarStoreInfo.VarOffset);
4524 StringPrint("\n// name = ");
4525 LogUnicodeString(Question->VariableName);
4526 StringPrint("\n// guid = ");
4527 StringPrint(
4528 EFI_GUID_FORMAT,
4529 Question->Guid.Data1, Question->Guid.Data2,
4530 Question->Guid.Data3, Question->Guid.Data4[0],
4531 Question->Guid.Data4[1],Question->Guid.Data4[2],
4532 Question->Guid.Data4[3],Question->Guid.Data4[4],
4533 Question->Guid.Data4[5],Question->Guid.Data4[6],
4534 Question->Guid.Data4[7]
4535 );
4536 StringPrint("\n// attribute = 0x%x", Question->Attributes);
4537 StringPrint("\n// help = ");
4538 Status = FindDefaultName (
4539 &(FormSet->EnUsStringList),
4540 FormSet->UnicodeBinary,
4541 Question->Help,
4542 EN_US,
4543 &VarDefaultName
4544 );
4545 assert (!EFI_ERROR (Status));
4546 LogUnicodeString (VarDefaultName);
4547 StringPrint("\n");
4548 if (&(FormSet->EnUsStringList) == NULL &&VarDefaultName != NULL && Question->Help != 0) {
4549 free (VarDefaultName);
4550 VarDefaultName = NULL;
4551 }
4552 }
4553
4554 }
4555
4556 /**
4557 Check whether current Formset or Form is NULL. If no valid questions, return FASLE.
4558
4559 @param FormSet The pointer to the formset.
4560 @param FormSet The pointer to the form.
4561 @param IsFormSet FormSet or Form.
4562
4563 @retval TRUE
4564 @return FALSE
4565 **/
4566 BOOLEAN
4567 CheckFormSetOrFormNull (
4568 IN FORM_BROWSER_FORMSET *FormSet,
4569 IN FORM_BROWSER_FORM *Form,
4570 IN BOOLEAN IsFormSet
4571 )
4572 {
4573 LIST_ENTRY *FormLink;
4574 FORM_BROWSER_STATEMENT *Question;
4575 LIST_ENTRY *QuestionLink;
4576
4577 FormLink = NULL;
4578 Question = NULL;
4579 QuestionLink = NULL;
4580
4581 //
4582 // Parse all forms in formset
4583 //
4584 if (IsFormSet) {
4585 FormLink = GetFirstNode (&FormSet->FormListHead);
4586
4587 while (!IsNull (&FormSet->FormListHead, FormLink)) {
4588 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
4589 //
4590 // Parse five kinds of Questions in Form
4591 //
4592 QuestionLink = GetFirstNode (&Form->StatementListHead);
4593
4594 while (!IsNull (&Form->StatementListHead, QuestionLink)) {
4595 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
4596 //
4597 // Parse five kinds of Questions in Form
4598 //
4599 if ((Question->Operand == EFI_IFR_ONE_OF_OP)
4600 || (Question->Operand == EFI_IFR_NUMERIC_OP)
4601 || (Question->Operand == EFI_IFR_CHECKBOX_OP)
4602 || (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
4603 || (Question->Operand == EFI_IFR_STRING_OP)
4604 ) {
4605 if (mMultiPlatformParam.MultiPlatformOrNot) {
4606 //
4607 // Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode
4608 //
4609 if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) {
4610 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4611 continue;
4612 }
4613 if (Question->Type == EFI_IFR_VARSTORE_EFI_OP
4614 && Question->NewEfiVarstore
4615 && ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {
4616 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4617 continue;
4618 }
4619 }
4620 //
4621 //If invalid variable type, skip it.
4622 //
4623 if ((Question->Type != EFI_IFR_VARSTORE_EFI_OP)
4624 && (Question->Type != EFI_IFR_VARSTORE_OP)) {
4625 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4626 continue;
4627 }
4628 return TRUE;
4629 }
4630 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4631 }
4632
4633 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
4634 }
4635 } else {
4636 //
4637 // Parse five kinds of Questions in Form
4638 //
4639 QuestionLink = GetFirstNode (&Form->StatementListHead);
4640
4641 while (!IsNull (&Form->StatementListHead, QuestionLink)) {
4642 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
4643 //
4644 // Parse five kinds of Questions in Form
4645 //
4646 if ((Question->Operand == EFI_IFR_ONE_OF_OP)
4647 || (Question->Operand == EFI_IFR_NUMERIC_OP)
4648 || (Question->Operand == EFI_IFR_CHECKBOX_OP)
4649 || (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
4650 || (Question->Operand == EFI_IFR_STRING_OP)
4651 ) {
4652 if (mMultiPlatformParam.MultiPlatformOrNot) {
4653 //
4654 // Only compare the valid EFI_IFR_VARSTORE_EFI_OP in multi-platform mode
4655 //
4656 if (Question->Type != EFI_IFR_VARSTORE_EFI_OP) {
4657 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4658 continue;
4659 }
4660 if ((Question->Type == EFI_IFR_VARSTORE_EFI_OP)
4661 && Question->NewEfiVarstore
4662 && ((Question->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {
4663 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4664 continue;
4665 }
4666 }
4667 //
4668 //If invalid variable type, skip it.
4669 //
4670 if ((Question->Type != EFI_IFR_VARSTORE_EFI_OP)
4671 && (Question->Type != EFI_IFR_VARSTORE_OP)) {
4672 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4673 continue;
4674 }
4675 return TRUE;
4676 }
4677 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4678 }
4679 }
4680 return FALSE;
4681 }
4682
4683 /**
4684 Print all ONE_OF ORDER_LIST NUMERIC STRING and CHECKBOX in all fromsets.
4685
4686 @param Formset The pointer to the entry of the fromset list
4687 @param Formset The pointer to the entry of the storage list
4688
4689 @retval EFI_SUCCESS It was complete successfully
4690 @return EFI_ABORTED An error occurred
4691 **/
4692 EFI_STATUS
4693 PrintInfoInAllFormset (
4694 IN LIST_ENTRY *FormSetEntryListHead,
4695 IN LIST_ENTRY *StorageEntryListHead
4696 )
4697 {
4698 EFI_STATUS Status;
4699 FORM_BROWSER_FORMSET *FormSet;
4700 LIST_ENTRY *FormSetLink;
4701 LIST_ENTRY *FormLink;
4702 FORM_BROWSER_FORM *Form;
4703 FORM_BROWSER_STATEMENT *Question;
4704 LIST_ENTRY *QuestionLink;
4705 FORMSET_STORAGE *Storage;
4706 CHAR8 *VarBuffer;
4707 LIST_ENTRY *TempStorageLink;
4708 UINT32 Index;
4709 BOOLEAN Skip;
4710 BOOLEAN ConstantFlag;
4711
4712 Status = EFI_SUCCESS;
4713 FormSet = NULL;
4714 FormSetLink = NULL;
4715 FormLink = NULL;
4716 Form = NULL;
4717 Question = NULL;
4718 QuestionLink = NULL;
4719 Storage = NULL;
4720 VarBuffer = NULL;
4721 TempStorageLink = NULL;
4722 Index = 0;
4723 Skip = FALSE;
4724 ConstantFlag = TRUE;
4725 //
4726 // Print platformId, defaultId and platformIdUqi
4727 //
4728 if (mMultiPlatformParam.MultiPlatformOrNot) {
4729 StringPrint("\n\n// FCEKEY DEFAULT_ID:");
4730 TempStorageLink = GetFirstNode (StorageEntryListHead);
4731 Storage = FORMSET_STORAGE_FROM_LINK (TempStorageLink);
4732 for (Index = 0; Index <= Storage->DefaultPlatformIdNum; Index++) {
4733 StringPrint (" %4d", Storage->DefaultId[Index]);
4734 }
4735 StringPrint("\n\n//FCEKEY PLATFORM_ID:");
4736 for (Index = 0; Index <= Storage->DefaultPlatformIdNum; Index++) {
4737 StringPrint (" %4lld", Storage->PlatformId[Index]);
4738 }
4739 if (mMultiPlatformParam.Uqi.Data != NULL) {
4740 StringPrint("\n\n//FCEKEY PLATFORM_UQI:");
4741 StringPrint(" %04X ", mMultiPlatformParam.Uqi.HexNum);
4742 LogUqi(mMultiPlatformParam.Uqi.Data);
4743 }
4744 }
4745 FormSetLink = GetFirstNode (FormSetEntryListHead);
4746 while (!IsNull (FormSetEntryListHead, FormSetLink)) {
4747 FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
4748 //
4749 //Assign the new storage list
4750 //
4751 FormSet->StorageListHead = StorageEntryListHead;
4752
4753 if (CheckFormSetOrFormNull (FormSet, NULL, TRUE)) {
4754 StringPrintormSetTitle (FormSet);
4755 } else {
4756 FormSetLink = GetNextNode (FormSetEntryListHead, FormSetLink);
4757 continue;
4758 }
4759 //
4760 // Parse all forms in formset
4761 //
4762 FormLink = GetFirstNode (&FormSet->FormListHead);
4763
4764 while (!IsNull (&FormSet->FormListHead, FormLink)) {
4765 Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
4766
4767 if (CheckFormSetOrFormNull (NULL, Form, FALSE)) {
4768 StringPrintormTitle(FormSet,Form);
4769 } else {
4770 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
4771 continue;
4772 }
4773 //
4774 // Parse five kinds of Questions in Form
4775 //
4776 QuestionLink = GetFirstNode (&Form->StatementListHead);
4777
4778 while (!IsNull (&Form->StatementListHead, QuestionLink)) {
4779 Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
4780 //
4781 // Parse five kinds of Questions in Form
4782 //
4783 if ((Question->Operand == EFI_IFR_ONE_OF_OP)
4784 || (Question->Operand == EFI_IFR_NUMERIC_OP)
4785 || (Question->Operand == EFI_IFR_CHECKBOX_OP)
4786 || (Question->Operand == EFI_IFR_ORDERED_LIST_OP)
4787 || (Question->Operand == EFI_IFR_SUBTITLE_OP)
4788 || (Question->Operand == EFI_IFR_STRING_OP)
4789 ) {
4790 Skip = FALSE;
4791
4792 //
4793 //Only output the questions stored by EFI_IFR_VARSTORE_EFI_OP.
4794 //
4795 if (mMultiPlatformParam.MultiPlatformOrNot
4796 && (Question->Operand != EFI_IFR_SUBTITLE_OP)
4797 ) {
4798 Status = SearchVarStorage (
4799 Question,
4800 NULL,
4801 Question->VarStoreInfo.VarOffset,
4802 StorageEntryListHead,
4803 (CHAR8 **)&VarBuffer,
4804 &Storage
4805 );
4806
4807 if (EFI_ERROR (Status)) {
4808 Skip = TRUE;
4809 }
4810 }
4811 //
4812 // If Question is constant expression and "disabledIf True", don't output it.
4813 //
4814 ConstantFlag = TRUE;
4815 if (!Skip && (Question->DisableExpression != NULL)) {
4816 Status = EvaluateExpression (FormSet, Form, Question->DisableExpression, &ConstantFlag);
4817 if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b && ConstantFlag) {
4818 Skip = TRUE;
4819 }
4820 }
4821
4822 if (!Skip) {
4823 PrintQuestion(FormSet, Form, Question, TRUE);
4824 }
4825 }
4826 QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
4827 }
4828
4829 FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
4830 }
4831 FormSetLink = GetNextNode (FormSetEntryListHead, FormSetLink);
4832 }
4833
4834 return EFI_SUCCESS;
4835 }
4836