/*++ Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. Module Name: IfrParse.c Abstract: Routines for parsing and managing HII IFR packs. --*/ #include #include #include #include "Tiano.h" #include "EfiUtilityMsgs.h" #include "EfiInternalFormRepresentation.h" #include "Hii.h" #include "IfrParse.h" #include "HiiPack.h" typedef struct _VARIABLE_STORE_ENTRY { struct _VARIABLE_STORE_ENTRY *Next; CHAR8 VarName[MAX_VARIABLE_NAME]; char *VarBuffer; int VarBufferSize; EFI_HII_VARIABLE_PACK *VarPack; int VarPackSize; } VARIABLE_STORE_ENTRY; typedef STATUS (*IFR_PARSE_FUNCTION) (IFR_PARSE_CONTEXT * Context); typedef struct { INT8 *Name; INT32 Size; IFR_PARSE_FUNCTION Parse; } IFR_PARSE_TABLE_ENTRY; static STATUS IfrParse01 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse02 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse03 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse05 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse06 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse07 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse08 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse09 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse0A ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse0B ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse0C ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse0D ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse0E ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse0F ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse10 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse11 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse12 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse13 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse14 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse15 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse16 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse17 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse18 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse19 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse1A ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse1B ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse1C ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse1D ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse1E ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse1F ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse20 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse21 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse22 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse23 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse24 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse25 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse26 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse27 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse28 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse29 ( IFR_PARSE_CONTEXT *Context ); static STATUS IfrParse2A ( IFR_PARSE_CONTEXT *Context ); static const IFR_PARSE_TABLE_ENTRY mIfrParseTable[] = { { 0, 0, NULL }, // invalid { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM), IfrParse01 }, { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE), IfrParse02 }, { "EFI_IFR_TEXT", -6, IfrParse03 }, // sizeof (EFI_IFR_TEXT) }, { "unused 0x04 opcode", 0, NULL }, // EFI_IFR_GRAPHIC_OP { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF), IfrParse05 }, { "EFI_IFR_CHECK_BOX", sizeof (EFI_IFR_CHECK_BOX), IfrParse06 }, { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC), IfrParse07 }, { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD), IfrParse08 }, { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION), IfrParse09 }, { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS), IfrParse0A }, { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM), IfrParse0B }, { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN), IfrParse0C }, { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET), IfrParse0D }, { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET), IfrParse0E }, { "EFI_IFR_REF", sizeof (EFI_IFR_REF), IfrParse0F }, { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF), IfrParse10 }, { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT), IfrParse11 }, { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL), IfrParse12 }, { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID), IfrParse13 }, { "EFI_IFR_EQ_ID_LIST", -(int) (sizeof (EFI_IFR_EQ_ID_LIST)), IfrParse14 }, { "EFI_IFR_AND", sizeof (EFI_IFR_AND), IfrParse15 }, { "EFI_IFR_OR", sizeof (EFI_IFR_OR), IfrParse16 }, { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT), IfrParse17 }, { "EFI_IFR_END_IF", sizeof (EFI_IFR_END_IF), IfrParse18 }, { "EFI_IFR_GRAYOUT", sizeof (EFI_IFR_GRAYOUT), IfrParse19 }, { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3, IfrParse1A }, { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3, IfrParse1B }, { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING), IfrParse1C }, { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL), IfrParse1D }, { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS), IfrParse1E }, { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS), IfrParse1F }, { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER), IfrParse20 }, { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY), IfrParse21 }, { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL), IfrParse22 }, { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST), IfrParse23 }, { "EFI_IFR_VARSTORE_OP", -(int) (sizeof (EFI_IFR_VARSTORE)), IfrParse24 }, { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT), IfrParse25 }, { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), IfrParse26 }, { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE), IfrParse27 }, { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE), IfrParse28 }, { "EFI_IFR_GT", sizeof (EFI_IFR_GT), IfrParse29 }, { "EFI_IFR_GE", sizeof (EFI_IFR_GE), IfrParse2A }, }; #define PARSE_TABLE_ENTRIES (sizeof (mIfrParseTable) / sizeof (mIfrParseTable[0])) static STATUS GetVarStoreInfo ( IFR_PARSE_CONTEXT *Context, UINT16 VarId, EFI_GUID **VarStoreGuid, char **VarStoreName ); static void FreeVarStores ( VOID ); static STATUS CreateVarStore ( EFI_GUID *VarGuid, CHAR8 *VarName, int VarStoreSize ); static STATUS SetDefaults ( IFR_PARSE_CONTEXT *Context, UINT32 MfgDefaults ); // // Globals // static IFR_PARSE_CONTEXT *mParseContext = NULL; static VARIABLE_STORE_ENTRY *mVariableStores = NULL; static int BreakOnOpcodeTag = 0; static int OpcodeTag = 1; /*****************************************************************************/ STATUS IfrParseCheck ( char *Buffer, long BufferSize ) /*++ Routine Description: Check a buffer to ensure that is is parseable IFR Arguments: Buffer - pointer to raw IFR bytes BufferSize - size of IFR pointed to by Buffer Returns: STATUS_SUCCESS if successful STATUS_ERROR otherwise --*/ { char *Start; char *End; char *Pos; EFI_IFR_OP_HEADER *OpHeader; char *FileName; FileName = ""; // // Walk the list of IFR statements in the IFR pack // Start = Buffer; Pos = Buffer; End = Start + BufferSize; while ((Pos >= Start) && (Pos < End)) { OpHeader = (EFI_IFR_OP_HEADER *) Pos; // // Check range on size // if (Pos + OpHeader->Length > End) { Error (NULL, 0, 0, FileName, "invalid IFR opcode size at offset 0x%X", (int) Pos - (int) Start); return STATUS_ERROR; } if (OpHeader->Length == 0) { Error (NULL, 0, 0, FileName, "IFR opcode size=0 at offset 0x%X", (int) Pos - (int) Start); return STATUS_ERROR; } // // See if it's the END_FORMSET opcode // if (OpHeader->OpCode == EFI_IFR_END_FORM_SET_OP) { break; } // // Advance to next IFR statement/opcode // Pos += OpHeader->Length; } return STATUS_SUCCESS; } STATUS IfrParseInit ( VOID ) /*++ Routine Description: Initialize this module for IFR pack parsing Arguments: Returns: STATUS_SUCCESS always --*/ { return STATUS_SUCCESS; } STATUS IfrParseEnd ( VOID ) /*++ Routine Description: Free up memory allocated during IFR pack parsing done by this module Arguments: None Returns: STATUS_SUCCESS always --*/ { IFR_PARSE_CONTEXT *NextContext; IFR_PARSE_ENTRY *NextEntry; // // Free up the memory from our parse contexts // while (mParseContext != NULL) { while (mParseContext->Ifr != NULL) { NextEntry = mParseContext->Ifr->Next; // // We pointed directly into the user buffer, rather than make // a copy, so don't free up the bytes. // free (mParseContext->Ifr); mParseContext->Ifr = NextEntry; } NextContext = mParseContext->Next; free (mParseContext->PackHeader); free (mParseContext); mParseContext = NextContext; } return STATUS_SUCCESS; } static void FreeVarStores ( VOID ) /*++ Routine Description: GC_TODO: Add function description Arguments: None Returns: GC_TODO: add return values --*/ { VARIABLE_STORE_ENTRY *NextVarStore; // // Free up memory from our variable stores // while (mVariableStores != NULL) { if (mVariableStores->VarPack != NULL) { free (mVariableStores->VarPack); } NextVarStore = mVariableStores->Next; free (mVariableStores); mVariableStores = NextVarStore; } } /****************************************************************************** FUNCTION: IfrParsePack() DESCRIPTION: Given a pointer to an IFR pack, parse it to create a linked list of opcodes and relevant data required for later dumping. *******************************************************************************/ STATUS IfrParsePack ( int Handle, EFI_HII_IFR_PACK *PackHeader, EFI_GUID *PackageGuid ) /*++ Routine Description: Given a pointer to an IFR pack, parse it to create a linked list of opcodes and relevant data required for later dumping. Arguments: Handle - the handle number associated with this IFR pack. It can be used later to retrieve more info on the particular pack PackHeader - pointer to IFR pack to parse PackageGuid - on input, it comes from the HII data table entry for this pack. On output, we'll return the IFR formset GUID. Returns: STATUS_SUCCESS always --*/ { EFI_IFR_OP_HEADER *OpHeader; IFR_PARSE_CONTEXT *Context; IFR_PARSE_CONTEXT *TempContext; IFR_PARSE_ENTRY *IfrEntry; // // Initialize our context // Context = (IFR_PARSE_CONTEXT *) malloc (sizeof (IFR_PARSE_CONTEXT)); if (Context == NULL) { Error (NULL, 0, 0, "memory allocation failure", NULL); return STATUS_ERROR; } memset ((void *) Context, 0, sizeof (IFR_PARSE_CONTEXT)); // // Cache a copy of the input pack so the caller can free their copy // Context->PackHeader = (EFI_HII_IFR_PACK *) malloc (PackHeader->Header.Length); if (Context->PackHeader == NULL) { Error (NULL, 0, 0, "memory allocation failure", NULL); free (Context); return STATUS_ERROR; } memcpy (Context->PackHeader, PackHeader, PackHeader->Header.Length); Context->IfrBufferStart = (char *) (Context->PackHeader + 1); Context->CurrentPos = Context->IfrBufferStart; Context->IfrBufferLen = PackHeader->Header.Length - sizeof (EFI_HII_IFR_PACK); Context->Handle = Handle; Context->FormsetGuid = &Context->NullGuid; Context->PackageGuid = *PackageGuid; // // Add it to the end of our list // if (mParseContext == NULL) { mParseContext = Context; } else { TempContext = mParseContext; while (TempContext->Next != NULL) { TempContext = TempContext->Next; } TempContext->Next = Context; } // // Walk the opcodes in the pack // while ( (Context->CurrentPos >= Context->IfrBufferStart) && (Context->CurrentPos < Context->IfrBufferStart + Context->IfrBufferLen) ) { OpHeader = (EFI_IFR_OP_HEADER *) Context->CurrentPos; // // Allocate a new IFR entry to put in our linked list, then // point directly to the caller's raw data. // IfrEntry = (IFR_PARSE_ENTRY *) malloc (sizeof (IFR_PARSE_ENTRY)); if (IfrEntry == NULL) { Error (NULL, 0, 0, "memory allocation failure", NULL); free (Context->PackHeader); free (Context); return STATUS_ERROR; } memset ((void *) IfrEntry, 0, sizeof (IFR_PARSE_ENTRY)); IfrEntry->Tag = ++OpcodeTag; if (OpcodeTag == BreakOnOpcodeTag) { EFI_BREAKPOINT (); } IfrEntry->RawIfrHeader = (EFI_IFR_OP_HEADER *) (Context->CurrentPos); // // Add this entry to our linked list. If it's not the first, then // forward the variable store settings from the previous entry. // if (Context->LastIfr != NULL) { IfrEntry->VarStoreGuid1 = Context->LastIfr->VarStoreGuid1; IfrEntry->VarStoreName1 = Context->LastIfr->VarStoreName1; IfrEntry->VarStoreGuid2 = Context->LastIfr->VarStoreGuid2; IfrEntry->VarStoreName2 = Context->LastIfr->VarStoreName2; Context->LastIfr->Next = IfrEntry; } else { Context->Ifr = IfrEntry; } Context->LastIfr = IfrEntry; // // Switch on the opcode to parse it // if (OpHeader->OpCode < PARSE_TABLE_ENTRIES) { if (mIfrParseTable[OpHeader->OpCode].Parse != NULL) { mIfrParseTable[OpHeader->OpCode].Parse (Context); } } else { Error ( NULL, 0, 0, "invalid opcode found in IFR", "offset=0x%X opcode=0x%02X", (int) OpHeader - (int) Context->PackHeader, (int) OpHeader->OpCode ); free (IfrEntry); free (Context->PackHeader); free (Context); return STATUS_ERROR; } // // If it's the END_FORMSET opcode, then we're done // if (OpHeader->OpCode == EFI_IFR_END_FORM_SET_OP) { break; } // // Advance to next IFR statement/opcode // if (OpHeader->Length == 0) { Error (NULL, 0, 0, "0-length IFR opcode encountered", NULL); free (IfrEntry); free (Context->PackHeader); free (Context); return STATUS_ERROR; } Context->CurrentPos += OpHeader->Length; } // // Return the form GUID. // *PackageGuid = *Context->FormsetGuid; return STATUS_SUCCESS; } /****************************************************************************** FUNCTION: GetVarStoreInfo() DESCRIPTION: IFR contains VARSTORE opcodes to specify where variable data for following opcodes is supposed to be stored. One VARSTORE statement allows you to specify the variable store GUID and a key, and another VARSTORE (select) allows you to specify the key of a VARSTORE statement. Given the key from a VARSTORE_SELECT statement, go find the corresponding VARSTORE statement with a matching key and return the varstore GUID and name. If key == 0, then the variable store is FormsetGuid."Setup" *******************************************************************************/ static STATUS GetVarStoreInfo ( IFR_PARSE_CONTEXT *Context, UINT16 VarId, EFI_GUID **VarStoreGuid, char **VarStoreName ) /*++ Routine Description: Get variable store information from an IFR pack for a given variable store ID. Arguments: Context - pointer to IFR parse context VarId - variable store ID referenced by IFR being parsed VarStoreGuid - outgoing GUID of the variable store corresponding to VarId VarStoreName - outgoing variable name of variable store corresponding to VarId Returns: STATUS_SUCCESS - variable store with matching VarId found, and outoing GUID/Name are valid STATUS_ERROR - otherwise --*/ { IFR_PARSE_ENTRY *Ptr; EFI_IFR_VARSTORE *VarStore; if (Context == NULL) { return STATUS_ERROR; } // // Walk the entire IFR form and find a variable store opcode that // has a matching variable store ID. // for (Ptr = Context->Ifr; Ptr != NULL; Ptr = Ptr->Next) { if (Ptr->RawIfrHeader->OpCode == EFI_IFR_FORM_SET_OP) { if (VarId == 0) { *VarStoreGuid = &((EFI_IFR_FORM_SET *) (Ptr->RawIfrHeader))->Guid; *VarStoreName = DEFAULT_VARIABLE_NAME; return STATUS_SUCCESS; } } else if (Ptr->RawIfrHeader->OpCode == EFI_IFR_VARSTORE_OP) { // // See if it's a variable ID match // VarStore = (EFI_IFR_VARSTORE *) Ptr->RawIfrHeader; if (VarStore->VarId == VarId) { *VarStoreGuid = &VarStore->Guid; *VarStoreName = (char *) (VarStore + 1); return STATUS_SUCCESS; } } } return STATUS_ERROR; } STATUS IfrSetDefaults ( int MfgDefaults ) /*++ Routine Description: Go through all the IFR forms we've parsed so far and create and set variable defaults. Arguments: MfgDefaults - non-zero if manufacturing defaults are desired Returns: STATUS_SUCCESS - always --*/ { IFR_PARSE_CONTEXT *Context; // // First free up any variable stores we've created so far. // FreeVarStores (); for (Context = mParseContext; Context != NULL; Context = Context->Next) { // // Call our internal function to handle it // SetDefaults (Context, MfgDefaults); } return STATUS_SUCCESS; } /******************************************************************************/ STATUS IfrGetIfrPack ( int Handle, EFI_HII_IFR_PACK **PackHeader, EFI_GUID *FormsetGuid ) /*++ Routine Description: GC_TODO: Add function description Arguments: Handle - GC_TODO: add argument description PackHeader - GC_TODO: add argument description FormsetGuid - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { IFR_PARSE_CONTEXT *Context; for (Context = mParseContext; Context != NULL; Context = Context->Next) { if (Context->Handle == Handle) { *PackHeader = Context->PackHeader; memcpy (FormsetGuid, Context->FormsetGuid, sizeof (EFI_GUID)); return STATUS_SUCCESS; } } return STATUS_ERROR; } STATUS IfrReferencesVarPack ( int IfrHandle, EFI_HII_VARIABLE_PACK *VarPack ) /*++ Routine Description: Given an HII handle number (which corrresponds to a handle number passed in to IfrParsePack()), see if the IFR references the specified variable pack. Arguments: IfrHandle - handle number for the IFR pack to check (passed to IfrParsePack()) VarPack - variable pack to check to see if the IFR references Returns: STATUS_SUCCESS if the IFR on the given handle references the variable pack STATUS_WARNING the IFR does not reference the variable pack STATUS_ERROR invalid IFR handle --*/ { IFR_PARSE_CONTEXT *Context; char VarName[MAX_VARIABLE_NAME]; IFR_PARSE_ENTRY *ParseEntry; for (Context = mParseContext; Context != NULL; Context = Context->Next) { if (Context->Handle == IfrHandle) { // // Create an ASCII version of the variable name, since that's what is // referenced in IFR. // sprintf (VarName, "%S", (CHAR16 *) (VarPack + 1)); // // Walk all the opcodes and see if the IFR references this variable pack // for (ParseEntry = Context->Ifr; ParseEntry != NULL; ParseEntry = ParseEntry->Next) { // // Check for Name.Guid match for primary IFR variable store // if ((strcmp (VarName, ParseEntry->VarStoreName1) == 0) && (memcmp (&VarPack->VariableGuid, ParseEntry->VarStoreGuid1, sizeof (EFI_GUID)) == 0) ) { return STATUS_SUCCESS; } // // Check for Name.Guid match for secondary IFR variable store // if ((ParseEntry->VarStoreName2 != NULL) && (strcmp (VarName, ParseEntry->VarStoreName2) == 0) && (memcmp (&VarPack->VariableGuid, ParseEntry->VarStoreGuid2, sizeof (EFI_GUID)) == 0) ) { return STATUS_SUCCESS; } } return STATUS_WARNING; } } return STATUS_ERROR; } STATUS IfrGetVarPack ( int VarIndex, EFI_HII_VARIABLE_PACK **VarPack ) /*++ Routine Description: Get the variable defaults. It is expected that the caller called IfrSetDefaults() previously to walk all the IFR forms we know about and create and initialize default values. Arguments: VarIndex - a 0-based index into all the variable stores we know about VarPack - outgoing pointer to a variable pack Returns: STATUS_ERROR - VarIndex exceeds the number of variable packs we know of STATUS_SUCCESS - otherwise --*/ { VARIABLE_STORE_ENTRY *Entry; // // Initialize outgoing parameters // *VarPack = NULL; for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) { if (VarIndex == 0) { *VarPack = Entry->VarPack; return STATUS_SUCCESS; } VarIndex--; } return STATUS_ERROR; } static STATUS SetVariableValue ( EFI_GUID *VarGuid, char *VarName, int VarOffset, int VarSize, void *VarValue ) /*++ Routine Description: Given a variable GUID.Name, offset, size, and value, set the bytes in the variable to the provided value. Arguments: VarGuid - GUID of variable to set VarName - name of variable to set VarOffset - byte offset into the variable store VarSize - size of the value in the variable store (in bytes) VarValue - pointer to buffer containing the value to set Returns: --*/ { VARIABLE_STORE_ENTRY *Entry; char *Src; char *Dest; // // Go through our list of variable stores to find the match // for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) { if (memcmp (VarGuid, &Entry->VarPack->VariableGuid, sizeof (EFI_GUID)) == 0) { if (strcmp (VarName, Entry->VarName) == 0) { // // Found match -- check offset. If it's beyond the size of the variable store // buffer, then return a warning. Note that date-time can be beyond the // end of the varstore, which is ok. // if (VarOffset + VarSize <= Entry->VarBufferSize) { // // Stuff the data // Dest = Entry->VarBuffer + VarOffset; Src = (char *) VarValue; while (VarSize > 0) { *Dest = *Src; Src++; Dest++; VarSize--; } return STATUS_SUCCESS; } return STATUS_WARNING; } } } return STATUS_ERROR; } static STATUS SetDefaults ( IFR_PARSE_CONTEXT *Context, UINT32 MfgDefaults ) /*++ Routine Description: Set variable defaults by walking a single IFR form. Arguments: Context - Pointer to the IFR context. MfgDefaults - Number of Mfg defaults Returns: EFI_INVALID_PARAMETER - arguments to function are invalid STATUS_SUCCESS - function executed successfully --*/ { int Size; int CachedVarOffset; int CachedVarSize; int OrderedList; IFR_PARSE_ENTRY *SavedParseEntry; EFI_IFR_CHECK_BOX *IfrCheckBox; EFI_IFR_ONE_OF_OPTION *IfrOneOfOption; EFI_IFR_NUMERIC *IfrNumeric; STATUS Status; char ZeroByte; // // Walk the opcodes to set default values and stuff them into the variable stores // if (Context == NULL) { return EFI_INVALID_PARAMETER; } Status = STATUS_SUCCESS; Context->CurrentIfr = Context->Ifr; SavedParseEntry = NULL; OrderedList = 0; CachedVarOffset = 0; CachedVarSize = 0; ZeroByte = 0; while (Context->CurrentIfr != NULL) { if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_FORM_SET_OP) { // // Formset opcode -- create a variable pack // Status = CreateVarStore ( &((EFI_IFR_FORM_SET *) (Context->CurrentIfr->RawIfrHeader))->Guid, DEFAULT_VARIABLE_NAME, ((EFI_IFR_FORM_SET *) (Context->CurrentIfr->RawIfrHeader))->NvDataSize ); } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_VARSTORE_OP) { // // Variable store opcode -- create a variable pack // Status = CreateVarStore ( &((EFI_IFR_VARSTORE *) (Context->CurrentIfr->RawIfrHeader))->Guid, (char *) Context->CurrentIfr->RawIfrHeader + sizeof (EFI_IFR_VARSTORE), ((EFI_IFR_VARSTORE *) (Context->CurrentIfr->RawIfrHeader))->Size ); } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ONE_OF_OP) { // // Need this parse context later when we find the default ONE_OF_OPTION. // Clear out the variable store first, so that we're covered if someone // has two one-of opcode that operate on the same data. // So "last one wins" is the behavior. // OrderedList = 0; SavedParseEntry = Context->CurrentIfr; CachedVarOffset = ((EFI_IFR_ONE_OF *) Context->CurrentIfr->RawIfrHeader)->QuestionId; CachedVarSize = ((EFI_IFR_ONE_OF *) Context->CurrentIfr->RawIfrHeader)->Width; } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ORDERED_LIST_OP) { // // Need this parse context later as we parse the ONE_OF_OP's in the ordered list // OrderedList = 1; SavedParseEntry = Context->CurrentIfr; CachedVarOffset = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->QuestionId; CachedVarSize = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->MaxEntries; while (CachedVarSize > 0) { Status = SetVariableValue ( SavedParseEntry->VarStoreGuid1, // GUID of variable store to write SavedParseEntry->VarStoreName1, // name of variable store to write CachedVarOffset, // offset into variable store 1, // variable data size (void *) &ZeroByte ); // // variable value // CachedVarSize--; CachedVarOffset++; } CachedVarOffset = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->QuestionId; CachedVarSize = 1; // // ((EFI_IFR_ORDERED_LIST *)Context->CurrentIfr->RawIfrHeader)->Width; // } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ONE_OF_OPTION_OP) { IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) Context->CurrentIfr->RawIfrHeader; // // If we're in an ordered list, then copy the value to the data store // if (OrderedList) { Status = SetVariableValue ( SavedParseEntry->VarStoreGuid1, // GUID of variable store to write SavedParseEntry->VarStoreName1, // name of variable store to write CachedVarOffset, // offset into variable store 1, // variable data size (void *) &IfrOneOfOption->Value ); // // variable value // // Advance the offset for the next ordered list item // CachedVarOffset += CachedVarSize; } else { // // ONE-OF list. See if the default flag is set (provided we're not doing mfg defaults) // if (!MfgDefaults) { if (IfrOneOfOption->Flags & EFI_IFR_FLAG_DEFAULT) { Status = SetVariableValue ( SavedParseEntry->VarStoreGuid1, // GUID of variable store to write SavedParseEntry->VarStoreName1, // name of variable store to write CachedVarOffset, // offset into variable store CachedVarSize, // variable data size &IfrOneOfOption->Value ); // // variable value // } } else { if (IfrOneOfOption->Flags & EFI_IFR_FLAG_MANUFACTURING) { Status = SetVariableValue ( SavedParseEntry->VarStoreGuid1, // GUID of variable store to write SavedParseEntry->VarStoreName1, // name of variable store to write CachedVarOffset, // offset into variable store CachedVarSize, // variable data size &IfrOneOfOption->Value ); // // variable value // } } } } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_CHECKBOX_OP) { // // If we're saving defaults, and the default flag is set, or we're saving // manufacturing defaults and the manufacturing flag is set, then save a 1. // By default the varstore buffer is cleared, so we don't need to save a 0 ever. // IfrCheckBox = (EFI_IFR_CHECK_BOX *) Context->CurrentIfr->RawIfrHeader; if (((MfgDefaults == 0) && (IfrCheckBox->Flags & EFI_IFR_FLAG_DEFAULT)) || ((MfgDefaults != 0) && (IfrCheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING)) ) { Size = 1; Status = SetVariableValue ( Context->CurrentIfr->VarStoreGuid1, // GUID of variable store to write Context->CurrentIfr->VarStoreName1, // name of variable store to write IfrCheckBox->QuestionId, // offset into variable store IfrCheckBox->Width, // variable data size (void *) &Size ); // // variable value // } } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_NUMERIC_OP) { IfrNumeric = (EFI_IFR_NUMERIC *) Context->CurrentIfr->RawIfrHeader; Status = SetVariableValue ( Context->CurrentIfr->VarStoreGuid1, // GUID of variable store to write Context->CurrentIfr->VarStoreName1, // name of variable store to write IfrNumeric->QuestionId, // offset into variable store IfrNumeric->Width, // variable data size (void *) &IfrNumeric->Default ); // // variable value // } Context->CurrentIfr = Context->CurrentIfr->Next; } return STATUS_SUCCESS; } static STATUS CreateVarStore ( EFI_GUID *VarGuid, CHAR8 *VarName, int VarStoreSize ) /*++ Routine Description: Given a variable GUID.Name and the size of the variable store, allocate storage for maintaining the variable value. Arguments: VarGuid - GUID for a variable VarName - Name of the variable VarStoreSize - size of the variable store Returns: STATUS_ERROR - problem with storage allocation STATUS_SUCCESS - function executed successfully --*/ { VARIABLE_STORE_ENTRY *Entry; VARIABLE_STORE_ENTRY *TempEntry; int PackSize; int VarNameLen; // // If the variable store size is zero, then do nothing. This could be valid // if variable steering is used in the IFR such that FormsetGUID."Setup" variable // store is never used. // // OPEN: What about a form that only has a time/date question? Then if some other // function called SetDefaults(), attempting to set time/date would result in an // error in the SetVarValue() function. // if (VarStoreSize == 0) { return STATUS_SUCCESS; } // // Go through our list of variable stores and see if we've already created one // for this Guid.Name. If so, check the size and return. Otherwise create // one and add it to the list. // for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) { if (memcmp (VarGuid, &Entry->VarPack->VariableGuid, sizeof (EFI_GUID)) == 0) { if (strcmp (VarName, Entry->VarName) == 0) { // // Already have one. Check size. // if (Entry->VarBufferSize != VarStoreSize) { Error (NULL, 0, 0, "mismatched variable store size between two formsets", VarName); return STATUS_ERROR; } return STATUS_SUCCESS; } } } // // Create a new one. // Entry = (VARIABLE_STORE_ENTRY *) malloc (sizeof (VARIABLE_STORE_ENTRY)); if (Entry == NULL) { Error (NULL, 0, 0, "memory allocation failure", NULL); return STATUS_ERROR; } memset ((void *) Entry, 0, sizeof (VARIABLE_STORE_ENTRY)); // // Compute size of the varpack // VarNameLen = strlen (VarName) + 1; PackSize = sizeof (EFI_HII_VARIABLE_PACK) + VarNameLen * sizeof (CHAR16) + VarStoreSize; Entry->VarPack = (EFI_HII_VARIABLE_PACK *) malloc (PackSize); if (Entry->VarPack == NULL) { Error (NULL, 0, 0, "memory allocation failure", NULL); free (Entry); return STATUS_ERROR; } Entry->VarPack->Header.Length = PackSize; Entry->VarPack->Header.Type = EFI_HII_VARIABLE; Entry->VarPack->VariableNameLength = VarNameLen * sizeof (CHAR16); Entry->VarName[MAX_VARIABLE_NAME - 1] = 0; strncpy (Entry->VarName, VarName, MAX_VARIABLE_NAME - 1); #ifdef USE_VC8 swprintf ((CHAR16 *) (Entry->VarPack + 1), (strlen (VarName) + 1) * sizeof (CHAR16), L"%S", VarName); #else swprintf ((CHAR16 *) (Entry->VarPack + 1), L"%S", VarName); #endif memcpy (&Entry->VarPack->VariableGuid, VarGuid, sizeof (EFI_GUID)); // // Point VarBuffer into the allocated buffer (for convenience) // Entry->VarBuffer = (char *) Entry->VarPack + sizeof (EFI_HII_VARIABLE_PACK) + VarNameLen * sizeof (CHAR16); memset ((void *) Entry->VarBuffer, 0, VarStoreSize); Entry->VarBufferSize = VarStoreSize; // // Add this new varstore to our list // if (mVariableStores == NULL) { mVariableStores = Entry; } else { for (TempEntry = mVariableStores; TempEntry->Next != NULL; TempEntry = TempEntry->Next) ; TempEntry->Next = Entry; } return STATUS_SUCCESS; } /******************************************************************************/ /*++ Routine Description: The following IfrParseXX() functions are used to parse an IFR opcode numbered XX via a dispatch table. Arguments: Context - IFR parsing context into which pertinent data for the current opcode can be saved. Context->LastIfr->RawIfrHeader points to the raw IFR bytes currently being parsed. Returns: STATUS_SUCCESS - always --*/ /*******************************************************************************/ static STATUS IfrParse01 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse02 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse03 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } // // Parse the IFR EFI_IFR_ONE_OF opcode. // static STATUS IfrParse05 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse06 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse07 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse08 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse09 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse0A ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse0B ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse0C ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse0D ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse0E ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { EFI_IFR_FORM_SET *Op; Op = (EFI_IFR_FORM_SET *) Context->LastIfr->RawIfrHeader; Context->LastIfr->VarStoreGuid1 = &Op->Guid; Context->LastIfr->VarStoreName1 = "Setup"; Context->FormsetGuid = &Op->Guid; return STATUS_SUCCESS; } static STATUS IfrParse0F ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse10 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse11 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse12 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse13 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse14 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse15 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse16 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse17 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse18 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse19 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse1A ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse1B ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse1C ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse1D ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse1E ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse1F ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse20 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse21 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse22 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse23 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } // // EFI_IFR_VARSTORE // static STATUS IfrParse24 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { EFI_IFR_VARSTORE *Op; Op = (EFI_IFR_VARSTORE *) Context->LastIfr->RawIfrHeader; return STATUS_SUCCESS; } // // VARSTORE_SELECT // static STATUS IfrParse25 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { STATUS Status; EFI_IFR_VARSTORE_SELECT *Op; Op = (EFI_IFR_VARSTORE_SELECT *) Context->LastIfr->RawIfrHeader; Status = GetVarStoreInfo (Context, Op->VarId, &Context->LastIfr->VarStoreGuid1, &Context->LastIfr->VarStoreName1); // // VARSTORE_SELECT sets both // Context->LastIfr->VarStoreGuid2 = Context->LastIfr->VarStoreGuid1; Context->LastIfr->VarStoreName2 = Context->LastIfr->VarStoreName1; return Status; } // // VARSTORE_SELECT_PAIR // static STATUS IfrParse26 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { STATUS Status; EFI_IFR_VARSTORE_SELECT_PAIR *Op; Op = (EFI_IFR_VARSTORE_SELECT_PAIR *) Context->LastIfr->RawIfrHeader; Status = GetVarStoreInfo (Context, Op->VarId, &Context->LastIfr->VarStoreGuid1, &Context->LastIfr->VarStoreName1); Status = GetVarStoreInfo ( Context, Op->SecondaryVarId, &Context->LastIfr->VarStoreGuid2, &Context->LastIfr->VarStoreName2 ); return Status; } // // TRUE // static STATUS IfrParse27 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } // // FALSe // static STATUS IfrParse28 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse29 ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; } static STATUS IfrParse2A ( IFR_PARSE_CONTEXT *Context ) /*++ Routine Description: GC_TODO: Add function description Arguments: Context - GC_TODO: add argument description Returns: GC_TODO: add return values --*/ { return STATUS_SUCCESS; }