3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Routines for parsing and managing HII IFR packs.
27 #include "EfiUtilityMsgs.h"
28 #include "EfiInternalFormRepresentation.h"
33 typedef struct _VARIABLE_STORE_ENTRY
{
34 struct _VARIABLE_STORE_ENTRY
*Next
;
35 CHAR8 VarName
[MAX_VARIABLE_NAME
];
38 EFI_HII_VARIABLE_PACK
*VarPack
;
40 } VARIABLE_STORE_ENTRY
;
42 typedef STATUS (*IFR_PARSE_FUNCTION
) (IFR_PARSE_CONTEXT
* Context
);
47 IFR_PARSE_FUNCTION Parse
;
48 } IFR_PARSE_TABLE_ENTRY
;
53 IFR_PARSE_CONTEXT
*Context
58 IFR_PARSE_CONTEXT
*Context
63 IFR_PARSE_CONTEXT
*Context
68 IFR_PARSE_CONTEXT
*Context
73 IFR_PARSE_CONTEXT
*Context
78 IFR_PARSE_CONTEXT
*Context
83 IFR_PARSE_CONTEXT
*Context
88 IFR_PARSE_CONTEXT
*Context
93 IFR_PARSE_CONTEXT
*Context
98 IFR_PARSE_CONTEXT
*Context
103 IFR_PARSE_CONTEXT
*Context
108 IFR_PARSE_CONTEXT
*Context
113 IFR_PARSE_CONTEXT
*Context
118 IFR_PARSE_CONTEXT
*Context
123 IFR_PARSE_CONTEXT
*Context
128 IFR_PARSE_CONTEXT
*Context
133 IFR_PARSE_CONTEXT
*Context
138 IFR_PARSE_CONTEXT
*Context
143 IFR_PARSE_CONTEXT
*Context
148 IFR_PARSE_CONTEXT
*Context
153 IFR_PARSE_CONTEXT
*Context
158 IFR_PARSE_CONTEXT
*Context
163 IFR_PARSE_CONTEXT
*Context
168 IFR_PARSE_CONTEXT
*Context
173 IFR_PARSE_CONTEXT
*Context
178 IFR_PARSE_CONTEXT
*Context
183 IFR_PARSE_CONTEXT
*Context
188 IFR_PARSE_CONTEXT
*Context
193 IFR_PARSE_CONTEXT
*Context
198 IFR_PARSE_CONTEXT
*Context
203 IFR_PARSE_CONTEXT
*Context
208 IFR_PARSE_CONTEXT
*Context
213 IFR_PARSE_CONTEXT
*Context
218 IFR_PARSE_CONTEXT
*Context
223 IFR_PARSE_CONTEXT
*Context
228 IFR_PARSE_CONTEXT
*Context
233 IFR_PARSE_CONTEXT
*Context
238 IFR_PARSE_CONTEXT
*Context
243 IFR_PARSE_CONTEXT
*Context
248 IFR_PARSE_CONTEXT
*Context
253 IFR_PARSE_CONTEXT
*Context
256 static const IFR_PARSE_TABLE_ENTRY mIfrParseTable
[] = {
264 sizeof (EFI_IFR_FORM
),
269 sizeof (EFI_IFR_SUBTITLE
),
276 }, // sizeof (EFI_IFR_TEXT) },
278 "unused 0x04 opcode",
281 }, // EFI_IFR_GRAPHIC_OP
284 sizeof (EFI_IFR_ONE_OF
),
289 sizeof (EFI_IFR_CHECK_BOX
),
294 sizeof (EFI_IFR_NUMERIC
),
299 sizeof (EFI_IFR_PASSWORD
),
303 "EFI_IFR_ONE_OF_OPTION",
304 sizeof (EFI_IFR_ONE_OF_OPTION
),
309 sizeof (EFI_IFR_SUPPRESS
),
314 sizeof (EFI_IFR_END_FORM
),
319 sizeof (EFI_IFR_HIDDEN
),
323 "EFI_IFR_END_FORM_SET",
324 sizeof (EFI_IFR_END_FORM_SET
),
329 sizeof (EFI_IFR_FORM_SET
),
334 sizeof (EFI_IFR_REF
),
338 "EFI_IFR_END_ONE_OF",
339 sizeof (EFI_IFR_END_ONE_OF
),
343 "EFI_IFR_INCONSISTENT",
344 sizeof (EFI_IFR_INCONSISTENT
),
349 sizeof (EFI_IFR_EQ_ID_VAL
),
354 sizeof (EFI_IFR_EQ_ID_ID
),
358 "EFI_IFR_EQ_ID_LIST",
359 -(int) (sizeof (EFI_IFR_EQ_ID_LIST
)),
364 sizeof (EFI_IFR_AND
),
374 sizeof (EFI_IFR_NOT
),
379 sizeof (EFI_IFR_END_IF
),
384 sizeof (EFI_IFR_GRAYOUT
),
389 sizeof (EFI_IFR_DATE
) / 3,
394 sizeof (EFI_IFR_TIME
) / 3,
399 sizeof (EFI_IFR_STRING
),
404 sizeof (EFI_IFR_LABEL
),
408 "EFI_IFR_SAVE_DEFAULTS",
409 sizeof (EFI_IFR_SAVE_DEFAULTS
),
413 "EFI_IFR_RESTORE_DEFAULTS",
414 sizeof (EFI_IFR_RESTORE_DEFAULTS
),
419 sizeof (EFI_IFR_BANNER
),
424 sizeof (EFI_IFR_INVENTORY
),
428 "EFI_IFR_EQ_VAR_VAL_OP",
429 sizeof (EFI_IFR_EQ_VAR_VAL
),
433 "EFI_IFR_ORDERED_LIST_OP",
434 sizeof (EFI_IFR_ORDERED_LIST
),
438 "EFI_IFR_VARSTORE_OP",
439 -(int) (sizeof (EFI_IFR_VARSTORE
)),
443 "EFI_IFR_VARSTORE_SELECT_OP",
444 sizeof (EFI_IFR_VARSTORE_SELECT
),
448 "EFI_IFR_VARSTORE_SELECT_PAIR_OP",
449 sizeof (EFI_IFR_VARSTORE_SELECT_PAIR
),
454 sizeof (EFI_IFR_TRUE
),
459 sizeof (EFI_IFR_FALSE
),
473 #define PARSE_TABLE_ENTRIES (sizeof (mIfrParseTable) / sizeof (mIfrParseTable[0]))
478 IFR_PARSE_CONTEXT
*Context
,
480 EFI_GUID
**VarStoreGuid
,
501 IFR_PARSE_CONTEXT
*Context
,
508 static IFR_PARSE_CONTEXT
*mParseContext
= NULL
;
509 static VARIABLE_STORE_ENTRY
*mVariableStores
= NULL
;
510 static int BreakOnOpcodeTag
= 0;
511 static int OpcodeTag
= 1;
513 /*****************************************************************************/
523 Check a buffer to ensure that is is parseable IFR
527 Buffer - pointer to raw IFR bytes
528 BufferSize - size of IFR pointed to by Buffer
532 STATUS_SUCCESS if successful
533 STATUS_ERROR otherwise
542 EFI_IFR_OP_HEADER
*OpHeader
;
546 // Walk the list of IFR statements in the IFR pack
550 End
= Start
+ BufferSize
;
551 while ((Pos
>= Start
) && (Pos
< End
)) {
552 OpHeader
= (EFI_IFR_OP_HEADER
*) Pos
;
554 // Check range on size
556 if (Pos
+ OpHeader
->Length
> End
) {
557 Error (NULL
, 0, 0, FileName
, "invalid IFR opcode size at offset 0x%X", (int) Pos
- (int) Start
);
561 if (OpHeader
->Length
== 0) {
562 Error (NULL
, 0, 0, FileName
, "IFR opcode size=0 at offset 0x%X", (int) Pos
- (int) Start
);
566 // See if it's the END_FORMSET opcode
568 if (OpHeader
->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
572 // Advance to next IFR statement/opcode
574 Pos
+= OpHeader
->Length
;
577 return STATUS_SUCCESS
;
588 Initialize this module for IFR pack parsing
594 STATUS_SUCCESS always
598 return STATUS_SUCCESS
;
609 Free up memory allocated during IFR pack parsing done by this module
616 STATUS_SUCCESS always
620 IFR_PARSE_CONTEXT
*NextContext
;
621 IFR_PARSE_ENTRY
*NextEntry
;
623 // Free up the memory from our parse contexts
625 while (mParseContext
!= NULL
) {
626 while (mParseContext
->Ifr
!= NULL
) {
627 NextEntry
= mParseContext
->Ifr
->Next
;
629 // We pointed directly into the user buffer, rather than make
630 // a copy, so don't free up the bytes.
632 free (mParseContext
->Ifr
);
633 mParseContext
->Ifr
= NextEntry
;
636 NextContext
= mParseContext
->Next
;
637 free (mParseContext
->PackHeader
);
638 free (mParseContext
);
639 mParseContext
= NextContext
;
642 return STATUS_SUCCESS
;
654 GC_TODO: Add function description
662 GC_TODO: add return values
666 VARIABLE_STORE_ENTRY
*NextVarStore
;
668 // Free up memory from our variable stores
670 while (mVariableStores
!= NULL
) {
671 if (mVariableStores
->VarPack
!= NULL
) {
672 free (mVariableStores
->VarPack
);
675 NextVarStore
= mVariableStores
->Next
;
676 free (mVariableStores
);
677 mVariableStores
= NextVarStore
;
681 /******************************************************************************
682 FUNCTION: IfrParsePack()
684 DESCRIPTION: Given a pointer to an IFR pack, parse it to create a linked
685 list of opcodes and relevant data required for later dumping.
688 *******************************************************************************/
692 EFI_HII_IFR_PACK
*PackHeader
,
693 EFI_GUID
*PackageGuid
699 Given a pointer to an IFR pack, parse it to create a linked
700 list of opcodes and relevant data required for later dumping.
704 Handle - the handle number associated with this IFR pack. It
705 can be used later to retrieve more info on the particular
707 PackHeader - pointer to IFR pack to parse
708 PackageGuid - on input, it comes from the HII data table entry for this pack.
709 On output, we'll return the IFR formset GUID.
713 STATUS_SUCCESS always
717 EFI_IFR_OP_HEADER
*OpHeader
;
718 IFR_PARSE_CONTEXT
*Context
;
719 IFR_PARSE_CONTEXT
*TempContext
;
720 IFR_PARSE_ENTRY
*IfrEntry
;
722 // Initialize our context
724 Context
= (IFR_PARSE_CONTEXT
*) malloc (sizeof (IFR_PARSE_CONTEXT
));
725 if (Context
== NULL
) {
726 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
730 memset ((void *) Context
, 0, sizeof (IFR_PARSE_CONTEXT
));
732 // Cache a copy of the input pack so the caller can free their copy
734 Context
->PackHeader
= (EFI_HII_IFR_PACK
*) malloc (PackHeader
->Header
.Length
);
735 if (Context
->PackHeader
== NULL
) {
736 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
741 memcpy (Context
->PackHeader
, PackHeader
, PackHeader
->Header
.Length
);
742 Context
->IfrBufferStart
= (char *) (Context
->PackHeader
+ 1);
743 Context
->CurrentPos
= Context
->IfrBufferStart
;
744 Context
->IfrBufferLen
= PackHeader
->Header
.Length
- sizeof (EFI_HII_IFR_PACK
);
745 Context
->Handle
= Handle
;
746 Context
->FormsetGuid
= &Context
->NullGuid
;
747 Context
->PackageGuid
= *PackageGuid
;
749 // Add it to the end of our list
751 if (mParseContext
== NULL
) {
752 mParseContext
= Context
;
754 TempContext
= mParseContext
;
755 while (TempContext
->Next
!= NULL
) {
756 TempContext
= TempContext
->Next
;
759 TempContext
->Next
= Context
;
762 // Walk the opcodes in the pack
766 (Context
->CurrentPos
>= Context
->IfrBufferStart
) &&
767 (Context
->CurrentPos
< Context
->IfrBufferStart
+ Context
->IfrBufferLen
)
769 OpHeader
= (EFI_IFR_OP_HEADER
*) Context
->CurrentPos
;
771 // Allocate a new IFR entry to put in our linked list, then
772 // point directly to the caller's raw data.
774 IfrEntry
= (IFR_PARSE_ENTRY
*) malloc (sizeof (IFR_PARSE_ENTRY
));
775 if (IfrEntry
== NULL
) {
776 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
777 free (Context
->PackHeader
);
782 memset ((void *) IfrEntry
, 0, sizeof (IFR_PARSE_ENTRY
));
783 IfrEntry
->Tag
= ++OpcodeTag
;
784 if (OpcodeTag
== BreakOnOpcodeTag
) {
788 IfrEntry
->RawIfrHeader
= (EFI_IFR_OP_HEADER
*) (Context
->CurrentPos
);
790 // Add this entry to our linked list. If it's not the first, then
791 // forward the variable store settings from the previous entry.
793 if (Context
->LastIfr
!= NULL
) {
794 IfrEntry
->VarStoreGuid1
= Context
->LastIfr
->VarStoreGuid1
;
795 IfrEntry
->VarStoreName1
= Context
->LastIfr
->VarStoreName1
;
796 IfrEntry
->VarStoreGuid2
= Context
->LastIfr
->VarStoreGuid2
;
797 IfrEntry
->VarStoreName2
= Context
->LastIfr
->VarStoreName2
;
798 Context
->LastIfr
->Next
= IfrEntry
;
800 Context
->Ifr
= IfrEntry
;
803 Context
->LastIfr
= IfrEntry
;
805 // Switch on the opcode to parse it
807 if (OpHeader
->OpCode
< PARSE_TABLE_ENTRIES
) {
808 if (mIfrParseTable
[OpHeader
->OpCode
].Parse
!= NULL
) {
809 mIfrParseTable
[OpHeader
->OpCode
].Parse (Context
);
816 "invalid opcode found in IFR",
817 "offset=0x%X opcode=0x%02X",
818 (int) OpHeader
- (int) Context
->PackHeader
,
819 (int) OpHeader
->OpCode
822 free (Context
->PackHeader
);
827 // If it's the END_FORMSET opcode, then we're done
829 if (OpHeader
->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
833 // Advance to next IFR statement/opcode
835 if (OpHeader
->Length
== 0) {
836 Error (NULL
, 0, 0, "0-length IFR opcode encountered", NULL
);
838 free (Context
->PackHeader
);
843 Context
->CurrentPos
+= OpHeader
->Length
;
846 // Return the form GUID.
848 *PackageGuid
= *Context
->FormsetGuid
;
849 return STATUS_SUCCESS
;
852 /******************************************************************************
853 FUNCTION: GetVarStoreInfo()
855 DESCRIPTION: IFR contains VARSTORE opcodes to specify where variable data
856 for following opcodes is supposed to be stored. One VARSTORE statement
857 allows you to specify the variable store GUID and a key, and another
858 VARSTORE (select) allows you to specify the key of a VARSTORE statement.
859 Given the key from a VARSTORE_SELECT statement, go find the corresponding
860 VARSTORE statement with a matching key and return the varstore GUID and
861 name. If key == 0, then the variable store is FormsetGuid."Setup"
862 *******************************************************************************/
866 IFR_PARSE_CONTEXT
*Context
,
868 EFI_GUID
**VarStoreGuid
,
875 Get variable store information from an IFR pack for a given variable store ID.
879 Context - pointer to IFR parse context
880 VarId - variable store ID referenced by IFR being parsed
881 VarStoreGuid - outgoing GUID of the variable store corresponding to VarId
882 VarStoreName - outgoing variable name of variable store corresponding to VarId
886 STATUS_SUCCESS - variable store with matching VarId found, and outoing GUID/Name are valid
887 STATUS_ERROR - otherwise
891 IFR_PARSE_ENTRY
*Ptr
;
892 EFI_IFR_VARSTORE
*VarStore
;
893 if (Context
== NULL
) {
898 // Walk the entire IFR form and find a variable store opcode that
899 // has a matching variable store ID.
901 for (Ptr
= Context
->Ifr
; Ptr
!= NULL
; Ptr
= Ptr
->Next
) {
902 if (Ptr
->RawIfrHeader
->OpCode
== EFI_IFR_FORM_SET_OP
) {
904 *VarStoreGuid
= &((EFI_IFR_FORM_SET
*) (Ptr
->RawIfrHeader
))->Guid
;
905 *VarStoreName
= DEFAULT_VARIABLE_NAME
;
906 return STATUS_SUCCESS
;
908 } else if (Ptr
->RawIfrHeader
->OpCode
== EFI_IFR_VARSTORE_OP
) {
910 // See if it's a variable ID match
912 VarStore
= (EFI_IFR_VARSTORE
*) Ptr
->RawIfrHeader
;
913 if (VarStore
->VarId
== VarId
) {
914 *VarStoreGuid
= &VarStore
->Guid
;
915 *VarStoreName
= (char *) (VarStore
+ 1);
916 return STATUS_SUCCESS
;
932 Go through all the IFR forms we've parsed so far and create and set variable
937 MfgDefaults - non-zero if manufacturing defaults are desired
941 STATUS_SUCCESS - always
945 IFR_PARSE_CONTEXT
*Context
;
947 // First free up any variable stores we've created so far.
950 for (Context
= mParseContext
; Context
!= NULL
; Context
= Context
->Next
) {
952 // Call our internal function to handle it
954 SetDefaults (Context
, MfgDefaults
);
957 return STATUS_SUCCESS
;
961 /******************************************************************************/
965 EFI_HII_IFR_PACK
**PackHeader
,
966 EFI_GUID
*FormsetGuid
972 GC_TODO: Add function description
976 Handle - GC_TODO: add argument description
977 PackHeader - GC_TODO: add argument description
978 FormsetGuid - GC_TODO: add argument description
982 GC_TODO: add return values
986 IFR_PARSE_CONTEXT
*Context
;
988 for (Context
= mParseContext
; Context
!= NULL
; Context
= Context
->Next
) {
989 if (Context
->Handle
== Handle
) {
990 *PackHeader
= Context
->PackHeader
;
991 memcpy (FormsetGuid
, Context
->FormsetGuid
, sizeof (EFI_GUID
));
992 return STATUS_SUCCESS
;
1000 IfrReferencesVarPack (
1002 EFI_HII_VARIABLE_PACK
*VarPack
1006 Routine Description:
1008 Given an HII handle number (which corrresponds to a handle number passed
1009 in to IfrParsePack()), see if the IFR references the specified variable
1014 IfrHandle - handle number for the IFR pack to check (passed to IfrParsePack())
1015 VarPack - variable pack to check to see if the IFR references
1019 STATUS_SUCCESS if the IFR on the given handle references the variable pack
1020 STATUS_WARNING the IFR does not reference the variable pack
1021 STATUS_ERROR invalid IFR handle
1025 IFR_PARSE_CONTEXT
*Context
;
1026 char VarName
[MAX_VARIABLE_NAME
];
1027 IFR_PARSE_ENTRY
*ParseEntry
;
1029 for (Context
= mParseContext
; Context
!= NULL
; Context
= Context
->Next
) {
1030 if (Context
->Handle
== IfrHandle
) {
1032 // Create an ASCII version of the variable name, since that's what is
1033 // referenced in IFR.
1035 sprintf (VarName
, "%S", (CHAR16
*) (VarPack
+ 1));
1037 // Walk all the opcodes and see if the IFR references this variable pack
1039 for (ParseEntry
= Context
->Ifr
; ParseEntry
!= NULL
; ParseEntry
= ParseEntry
->Next
) {
1041 // Check for Name.Guid match for primary IFR variable store
1043 if ((strcmp (VarName
, ParseEntry
->VarStoreName1
) == 0) &&
1044 (memcmp (&VarPack
->VariableGuid
, ParseEntry
->VarStoreGuid1
, sizeof (EFI_GUID
)) == 0)
1046 return STATUS_SUCCESS
;
1049 // Check for Name.Guid match for secondary IFR variable store
1051 if ((ParseEntry
->VarStoreName2
!= NULL
) &&
1052 (strcmp (VarName
, ParseEntry
->VarStoreName2
) == 0) &&
1053 (memcmp (&VarPack
->VariableGuid
, ParseEntry
->VarStoreGuid2
, sizeof (EFI_GUID
)) == 0)
1055 return STATUS_SUCCESS
;
1059 return STATUS_WARNING
;
1063 return STATUS_ERROR
;
1069 EFI_HII_VARIABLE_PACK
**VarPack
1073 Routine Description:
1075 Get the variable defaults. It is expected that the caller
1076 called IfrSetDefaults() previously to walk all the IFR forms we know about
1077 and create and initialize default values.
1081 VarIndex - a 0-based index into all the variable stores we know about
1082 VarPack - outgoing pointer to a variable pack
1086 STATUS_ERROR - VarIndex exceeds the number of variable packs we know of
1087 STATUS_SUCCESS - otherwise
1091 VARIABLE_STORE_ENTRY
*Entry
;
1093 // Initialize outgoing parameters
1096 for (Entry
= mVariableStores
; Entry
!= NULL
; Entry
= Entry
->Next
) {
1097 if (VarIndex
== 0) {
1098 *VarPack
= Entry
->VarPack
;
1099 return STATUS_SUCCESS
;
1105 return STATUS_ERROR
;
1119 Routine Description:
1121 Given a variable GUID.Name, offset, size, and value, set the bytes in
1122 the variable to the provided value.
1125 VarGuid - GUID of variable to set
1126 VarName - name of variable to set
1127 VarOffset - byte offset into the variable store
1128 VarSize - size of the value in the variable store (in bytes)
1129 VarValue - pointer to buffer containing the value to set
1136 VARIABLE_STORE_ENTRY
*Entry
;
1140 // Go through our list of variable stores to find the match
1142 for (Entry
= mVariableStores
; Entry
!= NULL
; Entry
= Entry
->Next
) {
1143 if (memcmp (VarGuid
, &Entry
->VarPack
->VariableGuid
, sizeof (EFI_GUID
)) == 0) {
1144 if (strcmp (VarName
, Entry
->VarName
) == 0) {
1146 // Found match -- check offset. If it's beyond the size of the variable store
1147 // buffer, then return a warning. Note that date-time can be beyond the
1148 // end of the varstore, which is ok.
1150 if (VarOffset
+ VarSize
<= Entry
->VarBufferSize
) {
1154 Dest
= Entry
->VarBuffer
+ VarOffset
;
1155 Src
= (char *) VarValue
;
1156 while (VarSize
> 0) {
1163 return STATUS_SUCCESS
;
1166 return STATUS_WARNING
;
1171 return STATUS_ERROR
;
1177 IFR_PARSE_CONTEXT
*Context
,
1182 Routine Description:
1184 Set variable defaults by walking a single IFR form.
1188 Context - Pointer to the IFR context.
1189 MfgDefaults - Number of Mfg defaults
1193 EFI_INVALID_PARAMETER - arguments to function are invalid
1194 STATUS_SUCCESS - function executed successfully
1199 int CachedVarOffset
;
1202 IFR_PARSE_ENTRY
*SavedParseEntry
;
1203 EFI_IFR_CHECK_BOX
*IfrCheckBox
;
1204 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1205 EFI_IFR_NUMERIC
*IfrNumeric
;
1210 // Walk the opcodes to set default values and stuff them into the variable stores
1213 if (Context
== NULL
) {
1214 return EFI_INVALID_PARAMETER
;
1216 Status
= STATUS_SUCCESS
;
1217 Context
->CurrentIfr
= Context
->Ifr
;
1218 SavedParseEntry
= NULL
;
1220 CachedVarOffset
= 0;
1224 while (Context
->CurrentIfr
!= NULL
) {
1225 if (Context
->CurrentIfr
->RawIfrHeader
->OpCode
== EFI_IFR_FORM_SET_OP
) {
1227 // Formset opcode -- create a variable pack
1229 Status
= CreateVarStore (
1230 &((EFI_IFR_FORM_SET
*) (Context
->CurrentIfr
->RawIfrHeader
))->Guid
,
1231 DEFAULT_VARIABLE_NAME
,
1232 ((EFI_IFR_FORM_SET
*) (Context
->CurrentIfr
->RawIfrHeader
))->NvDataSize
1234 } else if (Context
->CurrentIfr
->RawIfrHeader
->OpCode
== EFI_IFR_VARSTORE_OP
) {
1236 // Variable store opcode -- create a variable pack
1238 Status
= CreateVarStore (
1239 &((EFI_IFR_VARSTORE
*) (Context
->CurrentIfr
->RawIfrHeader
))->Guid
,
1240 (char *) Context
->CurrentIfr
->RawIfrHeader
+ sizeof (EFI_IFR_VARSTORE
),
1241 ((EFI_IFR_VARSTORE
*) (Context
->CurrentIfr
->RawIfrHeader
))->Size
1243 } else if (Context
->CurrentIfr
->RawIfrHeader
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1245 // Need this parse context later when we find the default ONE_OF_OPTION.
1246 // Clear out the variable store first, so that we're covered if someone
1247 // has two one-of opcode that operate on the same data.
1248 // So "last one wins" is the behavior.
1251 SavedParseEntry
= Context
->CurrentIfr
;
1252 CachedVarOffset
= ((EFI_IFR_ONE_OF
*) Context
->CurrentIfr
->RawIfrHeader
)->QuestionId
;
1253 CachedVarSize
= ((EFI_IFR_ONE_OF
*) Context
->CurrentIfr
->RawIfrHeader
)->Width
;
1254 } else if (Context
->CurrentIfr
->RawIfrHeader
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1256 // Need this parse context later as we parse the ONE_OF_OP's in the ordered list
1259 SavedParseEntry
= Context
->CurrentIfr
;
1260 CachedVarOffset
= ((EFI_IFR_ORDERED_LIST
*) Context
->CurrentIfr
->RawIfrHeader
)->QuestionId
;
1261 CachedVarSize
= ((EFI_IFR_ORDERED_LIST
*) Context
->CurrentIfr
->RawIfrHeader
)->MaxEntries
;
1263 while (CachedVarSize
> 0) {
1264 Status
= SetVariableValue (
1265 SavedParseEntry
->VarStoreGuid1
, // GUID of variable store to write
1266 SavedParseEntry
->VarStoreName1
, // name of variable store to write
1267 CachedVarOffset
, // offset into variable store
1268 1, // variable data size
1278 CachedVarOffset
= ((EFI_IFR_ORDERED_LIST
*) Context
->CurrentIfr
->RawIfrHeader
)->QuestionId
;
1281 // ((EFI_IFR_ORDERED_LIST *)Context->CurrentIfr->RawIfrHeader)->Width;
1283 } else if (Context
->CurrentIfr
->RawIfrHeader
->OpCode
== EFI_IFR_ONE_OF_OPTION_OP
) {
1284 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) Context
->CurrentIfr
->RawIfrHeader
;
1286 // If we're in an ordered list, then copy the value to the data store
1289 Status
= SetVariableValue (
1290 SavedParseEntry
->VarStoreGuid1
, // GUID of variable store to write
1291 SavedParseEntry
->VarStoreName1
, // name of variable store to write
1292 CachedVarOffset
, // offset into variable store
1293 1, // variable data size
1294 (void *) &IfrOneOfOption
->Value
1299 // Advance the offset for the next ordered list item
1301 CachedVarOffset
+= CachedVarSize
;
1304 // ONE-OF list. See if the default flag is set (provided we're not doing mfg defaults)
1307 if (IfrOneOfOption
->Flags
& EFI_IFR_FLAG_DEFAULT
) {
1308 Status
= SetVariableValue (
1309 SavedParseEntry
->VarStoreGuid1
, // GUID of variable store to write
1310 SavedParseEntry
->VarStoreName1
, // name of variable store to write
1311 CachedVarOffset
, // offset into variable store
1312 CachedVarSize
, // variable data size
1313 &IfrOneOfOption
->Value
1320 if (IfrOneOfOption
->Flags
& EFI_IFR_FLAG_MANUFACTURING
) {
1321 Status
= SetVariableValue (
1322 SavedParseEntry
->VarStoreGuid1
, // GUID of variable store to write
1323 SavedParseEntry
->VarStoreName1
, // name of variable store to write
1324 CachedVarOffset
, // offset into variable store
1325 CachedVarSize
, // variable data size
1326 &IfrOneOfOption
->Value
1334 } else if (Context
->CurrentIfr
->RawIfrHeader
->OpCode
== EFI_IFR_CHECKBOX_OP
) {
1336 // If we're saving defaults, and the default flag is set, or we're saving
1337 // manufacturing defaults and the manufacturing flag is set, then save a 1.
1338 // By default the varstore buffer is cleared, so we don't need to save a 0 ever.
1340 IfrCheckBox
= (EFI_IFR_CHECK_BOX
*) Context
->CurrentIfr
->RawIfrHeader
;
1341 if (((MfgDefaults
== 0) && (IfrCheckBox
->Flags
& EFI_IFR_FLAG_DEFAULT
)) ||
1342 ((MfgDefaults
!= 0) && (IfrCheckBox
->Flags
& EFI_IFR_FLAG_MANUFACTURING
))
1345 Status
= SetVariableValue (
1346 Context
->CurrentIfr
->VarStoreGuid1
, // GUID of variable store to write
1347 Context
->CurrentIfr
->VarStoreName1
, // name of variable store to write
1348 IfrCheckBox
->QuestionId
, // offset into variable store
1349 IfrCheckBox
->Width
, // variable data size
1356 } else if (Context
->CurrentIfr
->RawIfrHeader
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1357 IfrNumeric
= (EFI_IFR_NUMERIC
*) Context
->CurrentIfr
->RawIfrHeader
;
1358 Status
= SetVariableValue (
1359 Context
->CurrentIfr
->VarStoreGuid1
, // GUID of variable store to write
1360 Context
->CurrentIfr
->VarStoreName1
, // name of variable store to write
1361 IfrNumeric
->QuestionId
, // offset into variable store
1362 IfrNumeric
->Width
, // variable data size
1363 (void *) &IfrNumeric
->Default
1370 Context
->CurrentIfr
= Context
->CurrentIfr
->Next
;
1373 return STATUS_SUCCESS
;
1385 Routine Description:
1387 Given a variable GUID.Name and the size of the variable store, allocate
1388 storage for maintaining the variable value.
1392 VarGuid - GUID for a variable
1393 VarName - Name of the variable
1394 VarStoreSize - size of the variable store
1398 STATUS_ERROR - problem with storage allocation
1399 STATUS_SUCCESS - function executed successfully
1403 VARIABLE_STORE_ENTRY
*Entry
;
1405 VARIABLE_STORE_ENTRY
*TempEntry
;
1409 // If the variable store size is zero, then do nothing. This could be valid
1410 // if variable steering is used in the IFR such that FormsetGUID."Setup" variable
1411 // store is never used.
1413 // OPEN: What about a form that only has a time/date question? Then if some other
1414 // function called SetDefaults(), attempting to set time/date would result in an
1415 // error in the SetVarValue() function.
1417 if (VarStoreSize
== 0) {
1418 return STATUS_SUCCESS
;
1421 // Go through our list of variable stores and see if we've already created one
1422 // for this Guid.Name. If so, check the size and return. Otherwise create
1423 // one and add it to the list.
1425 for (Entry
= mVariableStores
; Entry
!= NULL
; Entry
= Entry
->Next
) {
1426 if (memcmp (VarGuid
, &Entry
->VarPack
->VariableGuid
, sizeof (EFI_GUID
)) == 0) {
1427 if (strcmp (VarName
, Entry
->VarName
) == 0) {
1429 // Already have one. Check size.
1431 if (Entry
->VarBufferSize
!= VarStoreSize
) {
1432 Error (NULL
, 0, 0, "mismatched variable store size between two formsets", VarName
);
1433 return STATUS_ERROR
;
1436 return STATUS_SUCCESS
;
1441 // Create a new one.
1443 Entry
= (VARIABLE_STORE_ENTRY
*) malloc (sizeof (VARIABLE_STORE_ENTRY
));
1444 if (Entry
== NULL
) {
1445 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
1446 return STATUS_ERROR
;
1449 memset ((void *) Entry
, 0, sizeof (VARIABLE_STORE_ENTRY
));
1451 // Compute size of the varpack
1453 VarNameLen
= strlen (VarName
) + 1;
1454 PackSize
= sizeof (EFI_HII_VARIABLE_PACK
) + VarNameLen
* sizeof (CHAR16
) + VarStoreSize
;
1455 Entry
->VarPack
= (EFI_HII_VARIABLE_PACK
*) malloc (PackSize
);
1456 if (Entry
->VarPack
== NULL
) {
1457 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
1459 return STATUS_ERROR
;
1462 Entry
->VarPack
->Header
.Length
= PackSize
;
1463 Entry
->VarPack
->Header
.Type
= EFI_HII_VARIABLE
;
1464 Entry
->VarPack
->VariableNameLength
= VarNameLen
* sizeof (CHAR16
);
1465 Entry
->VarName
[MAX_VARIABLE_NAME
- 1] = 0;
1466 strncpy (Entry
->VarName
, VarName
, MAX_VARIABLE_NAME
- 1);
1468 swprintf ((CHAR16
*) (Entry
->VarPack
+ 1), (strlen (VarName
) + 1) * sizeof (CHAR16
), L
"%S", VarName
);
1470 swprintf ((CHAR16
*) (Entry
->VarPack
+ 1), L
"%S", VarName
);
1472 memcpy (&Entry
->VarPack
->VariableGuid
, VarGuid
, sizeof (EFI_GUID
));
1474 // Point VarBuffer into the allocated buffer (for convenience)
1476 Entry
->VarBuffer
= (char *) Entry
->VarPack
+ sizeof (EFI_HII_VARIABLE_PACK
) + VarNameLen
* sizeof (CHAR16
);
1477 memset ((void *) Entry
->VarBuffer
, 0, VarStoreSize
);
1478 Entry
->VarBufferSize
= VarStoreSize
;
1480 // Add this new varstore to our list
1482 if (mVariableStores
== NULL
) {
1483 mVariableStores
= Entry
;
1485 for (TempEntry
= mVariableStores
; TempEntry
->Next
!= NULL
; TempEntry
= TempEntry
->Next
)
1487 TempEntry
->Next
= Entry
;
1489 return STATUS_SUCCESS
;
1492 /******************************************************************************/
1496 Routine Description:
1498 The following IfrParseXX() functions are used to parse an IFR opcode numbered
1499 XX via a dispatch table.
1503 Context - IFR parsing context into which pertinent data for the
1504 current opcode can be saved. Context->LastIfr->RawIfrHeader points to
1505 the raw IFR bytes currently being parsed.
1509 STATUS_SUCCESS - always
1513 /*******************************************************************************/
1517 IFR_PARSE_CONTEXT
*Context
1521 Routine Description:
1523 GC_TODO: Add function description
1527 Context - GC_TODO: add argument description
1531 GC_TODO: add return values
1535 return STATUS_SUCCESS
;
1541 IFR_PARSE_CONTEXT
*Context
1545 Routine Description:
1547 GC_TODO: Add function description
1551 Context - GC_TODO: add argument description
1555 GC_TODO: add return values
1559 return STATUS_SUCCESS
;
1565 IFR_PARSE_CONTEXT
*Context
1569 Routine Description:
1571 GC_TODO: Add function description
1575 Context - GC_TODO: add argument description
1579 GC_TODO: add return values
1583 return STATUS_SUCCESS
;
1586 // Parse the IFR EFI_IFR_ONE_OF opcode.
1591 IFR_PARSE_CONTEXT
*Context
1595 Routine Description:
1597 GC_TODO: Add function description
1601 Context - GC_TODO: add argument description
1605 GC_TODO: add return values
1609 return STATUS_SUCCESS
;
1615 IFR_PARSE_CONTEXT
*Context
1619 Routine Description:
1621 GC_TODO: Add function description
1625 Context - GC_TODO: add argument description
1629 GC_TODO: add return values
1633 return STATUS_SUCCESS
;
1639 IFR_PARSE_CONTEXT
*Context
1643 Routine Description:
1645 GC_TODO: Add function description
1649 Context - GC_TODO: add argument description
1653 GC_TODO: add return values
1657 return STATUS_SUCCESS
;
1663 IFR_PARSE_CONTEXT
*Context
1667 Routine Description:
1669 GC_TODO: Add function description
1673 Context - GC_TODO: add argument description
1677 GC_TODO: add return values
1681 return STATUS_SUCCESS
;
1687 IFR_PARSE_CONTEXT
*Context
1691 Routine Description:
1693 GC_TODO: Add function description
1697 Context - GC_TODO: add argument description
1701 GC_TODO: add return values
1705 return STATUS_SUCCESS
;
1711 IFR_PARSE_CONTEXT
*Context
1715 Routine Description:
1717 GC_TODO: Add function description
1721 Context - GC_TODO: add argument description
1725 GC_TODO: add return values
1729 return STATUS_SUCCESS
;
1735 IFR_PARSE_CONTEXT
*Context
1739 Routine Description:
1741 GC_TODO: Add function description
1745 Context - GC_TODO: add argument description
1749 GC_TODO: add return values
1753 return STATUS_SUCCESS
;
1759 IFR_PARSE_CONTEXT
*Context
1763 Routine Description:
1765 GC_TODO: Add function description
1769 Context - GC_TODO: add argument description
1773 GC_TODO: add return values
1777 return STATUS_SUCCESS
;
1783 IFR_PARSE_CONTEXT
*Context
1787 Routine Description:
1789 GC_TODO: Add function description
1793 Context - GC_TODO: add argument description
1797 GC_TODO: add return values
1801 return STATUS_SUCCESS
;
1807 IFR_PARSE_CONTEXT
*Context
1811 Routine Description:
1813 GC_TODO: Add function description
1817 Context - GC_TODO: add argument description
1821 GC_TODO: add return values
1825 EFI_IFR_FORM_SET
*Op
;
1826 Op
= (EFI_IFR_FORM_SET
*) Context
->LastIfr
->RawIfrHeader
;
1827 Context
->LastIfr
->VarStoreGuid1
= &Op
->Guid
;
1828 Context
->LastIfr
->VarStoreName1
= "Setup";
1829 Context
->FormsetGuid
= &Op
->Guid
;
1830 return STATUS_SUCCESS
;
1836 IFR_PARSE_CONTEXT
*Context
1840 Routine Description:
1842 GC_TODO: Add function description
1846 Context - GC_TODO: add argument description
1850 GC_TODO: add return values
1854 return STATUS_SUCCESS
;
1860 IFR_PARSE_CONTEXT
*Context
1864 Routine Description:
1866 GC_TODO: Add function description
1870 Context - GC_TODO: add argument description
1874 GC_TODO: add return values
1878 return STATUS_SUCCESS
;
1884 IFR_PARSE_CONTEXT
*Context
1888 Routine Description:
1890 GC_TODO: Add function description
1894 Context - GC_TODO: add argument description
1898 GC_TODO: add return values
1902 return STATUS_SUCCESS
;
1908 IFR_PARSE_CONTEXT
*Context
1912 Routine Description:
1914 GC_TODO: Add function description
1918 Context - GC_TODO: add argument description
1922 GC_TODO: add return values
1926 return STATUS_SUCCESS
;
1932 IFR_PARSE_CONTEXT
*Context
1936 Routine Description:
1938 GC_TODO: Add function description
1942 Context - GC_TODO: add argument description
1946 GC_TODO: add return values
1950 return STATUS_SUCCESS
;
1956 IFR_PARSE_CONTEXT
*Context
1960 Routine Description:
1962 GC_TODO: Add function description
1966 Context - GC_TODO: add argument description
1970 GC_TODO: add return values
1974 return STATUS_SUCCESS
;
1980 IFR_PARSE_CONTEXT
*Context
1984 Routine Description:
1986 GC_TODO: Add function description
1990 Context - GC_TODO: add argument description
1994 GC_TODO: add return values
1998 return STATUS_SUCCESS
;
2004 IFR_PARSE_CONTEXT
*Context
2008 Routine Description:
2010 GC_TODO: Add function description
2014 Context - GC_TODO: add argument description
2018 GC_TODO: add return values
2022 return STATUS_SUCCESS
;
2028 IFR_PARSE_CONTEXT
*Context
2032 Routine Description:
2034 GC_TODO: Add function description
2038 Context - GC_TODO: add argument description
2042 GC_TODO: add return values
2046 return STATUS_SUCCESS
;
2052 IFR_PARSE_CONTEXT
*Context
2056 Routine Description:
2058 GC_TODO: Add function description
2062 Context - GC_TODO: add argument description
2066 GC_TODO: add return values
2070 return STATUS_SUCCESS
;
2076 IFR_PARSE_CONTEXT
*Context
2080 Routine Description:
2082 GC_TODO: Add function description
2086 Context - GC_TODO: add argument description
2090 GC_TODO: add return values
2094 return STATUS_SUCCESS
;
2100 IFR_PARSE_CONTEXT
*Context
2104 Routine Description:
2106 GC_TODO: Add function description
2110 Context - GC_TODO: add argument description
2114 GC_TODO: add return values
2118 return STATUS_SUCCESS
;
2124 IFR_PARSE_CONTEXT
*Context
2128 Routine Description:
2130 GC_TODO: Add function description
2134 Context - GC_TODO: add argument description
2138 GC_TODO: add return values
2142 return STATUS_SUCCESS
;
2148 IFR_PARSE_CONTEXT
*Context
2152 Routine Description:
2154 GC_TODO: Add function description
2158 Context - GC_TODO: add argument description
2162 GC_TODO: add return values
2166 return STATUS_SUCCESS
;
2172 IFR_PARSE_CONTEXT
*Context
2176 Routine Description:
2178 GC_TODO: Add function description
2182 Context - GC_TODO: add argument description
2186 GC_TODO: add return values
2190 return STATUS_SUCCESS
;
2196 IFR_PARSE_CONTEXT
*Context
2200 Routine Description:
2202 GC_TODO: Add function description
2206 Context - GC_TODO: add argument description
2210 GC_TODO: add return values
2214 return STATUS_SUCCESS
;
2220 IFR_PARSE_CONTEXT
*Context
2224 Routine Description:
2226 GC_TODO: Add function description
2230 Context - GC_TODO: add argument description
2234 GC_TODO: add return values
2238 return STATUS_SUCCESS
;
2244 IFR_PARSE_CONTEXT
*Context
2248 Routine Description:
2250 GC_TODO: Add function description
2254 Context - GC_TODO: add argument description
2258 GC_TODO: add return values
2262 return STATUS_SUCCESS
;
2268 IFR_PARSE_CONTEXT
*Context
2272 Routine Description:
2274 GC_TODO: Add function description
2278 Context - GC_TODO: add argument description
2282 GC_TODO: add return values
2286 return STATUS_SUCCESS
;
2292 IFR_PARSE_CONTEXT
*Context
2296 Routine Description:
2298 GC_TODO: Add function description
2302 Context - GC_TODO: add argument description
2306 GC_TODO: add return values
2310 return STATUS_SUCCESS
;
2316 IFR_PARSE_CONTEXT
*Context
2320 Routine Description:
2322 GC_TODO: Add function description
2326 Context - GC_TODO: add argument description
2330 GC_TODO: add return values
2334 return STATUS_SUCCESS
;
2342 IFR_PARSE_CONTEXT
*Context
2346 Routine Description:
2348 GC_TODO: Add function description
2352 Context - GC_TODO: add argument description
2356 GC_TODO: add return values
2360 EFI_IFR_VARSTORE
*Op
;
2361 Op
= (EFI_IFR_VARSTORE
*) Context
->LastIfr
->RawIfrHeader
;
2362 return STATUS_SUCCESS
;
2370 IFR_PARSE_CONTEXT
*Context
2374 Routine Description:
2376 GC_TODO: Add function description
2380 Context - GC_TODO: add argument description
2384 GC_TODO: add return values
2389 EFI_IFR_VARSTORE_SELECT
*Op
;
2390 Op
= (EFI_IFR_VARSTORE_SELECT
*) Context
->LastIfr
->RawIfrHeader
;
2391 Status
= GetVarStoreInfo (Context
, Op
->VarId
, &Context
->LastIfr
->VarStoreGuid1
, &Context
->LastIfr
->VarStoreName1
);
2393 // VARSTORE_SELECT sets both
2395 Context
->LastIfr
->VarStoreGuid2
= Context
->LastIfr
->VarStoreGuid1
;
2396 Context
->LastIfr
->VarStoreName2
= Context
->LastIfr
->VarStoreName1
;
2400 // VARSTORE_SELECT_PAIR
2405 IFR_PARSE_CONTEXT
*Context
2409 Routine Description:
2411 GC_TODO: Add function description
2415 Context - GC_TODO: add argument description
2419 GC_TODO: add return values
2424 EFI_IFR_VARSTORE_SELECT_PAIR
*Op
;
2426 Op
= (EFI_IFR_VARSTORE_SELECT_PAIR
*) Context
->LastIfr
->RawIfrHeader
;
2427 Status
= GetVarStoreInfo (Context
, Op
->VarId
, &Context
->LastIfr
->VarStoreGuid1
, &Context
->LastIfr
->VarStoreName1
);
2428 Status
= GetVarStoreInfo (
2431 &Context
->LastIfr
->VarStoreGuid2
,
2432 &Context
->LastIfr
->VarStoreName2
2442 IFR_PARSE_CONTEXT
*Context
2446 Routine Description:
2448 GC_TODO: Add function description
2452 Context - GC_TODO: add argument description
2456 GC_TODO: add return values
2460 return STATUS_SUCCESS
;
2468 IFR_PARSE_CONTEXT
*Context
2472 Routine Description:
2474 GC_TODO: Add function description
2478 Context - GC_TODO: add argument description
2482 GC_TODO: add return values
2486 return STATUS_SUCCESS
;
2491 IFR_PARSE_CONTEXT
*Context
2495 Routine Description:
2497 GC_TODO: Add function description
2501 Context - GC_TODO: add argument description
2505 GC_TODO: add return values
2509 return STATUS_SUCCESS
;
2514 IFR_PARSE_CONTEXT
*Context
2518 Routine Description:
2520 GC_TODO: Add function description
2524 Context - GC_TODO: add argument description
2528 GC_TODO: add return values
2532 return STATUS_SUCCESS
;