/** @file Parser for IFR binary encoding. Copyright (c) 2007 - 2008, 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. **/ #include "Setup.h" #include "Ui.h" UINT16 mStatementIndex; UINT16 mExpressionOpCodeIndex; BOOLEAN mInScopeSubtitle; BOOLEAN mInScopeSuppress; BOOLEAN mInScopeGrayOut; FORM_EXPRESSION *mSuppressExpression; FORM_EXPRESSION *mGrayOutExpression; EFI_GUID gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID; GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID; /** Initialize Statement header members. @param OpCodeData Pointer of the raw OpCode data. @param FormSet Pointer of the current FormSe. @param Form Pointer of the current Form. @return The Statement. **/ FORM_BROWSER_STATEMENT * CreateStatement ( IN UINT8 *OpCodeData, IN OUT FORM_BROWSER_FORMSET *FormSet, IN OUT FORM_BROWSER_FORM *Form ) { FORM_BROWSER_STATEMENT *Statement; EFI_IFR_STATEMENT_HEADER *StatementHdr; if (Form == NULL) { // // We are currently not in a Form Scope, so just skip this Statement // return NULL; } Statement = &FormSet->StatementBuffer[mStatementIndex]; mStatementIndex++; InitializeListHead (&Statement->DefaultListHead); InitializeListHead (&Statement->OptionListHead); InitializeListHead (&Statement->InconsistentListHead); InitializeListHead (&Statement->NoSubmitListHead); Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE; Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID)); CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID)); if (mInScopeSuppress) { Statement->SuppressExpression = mSuppressExpression; } if (mInScopeGrayOut) { Statement->GrayOutExpression = mGrayOutExpression; } Statement->InSubtitle = mInScopeSubtitle; // // Insert this Statement into current Form // InsertTailList (&Form->StatementListHead, &Statement->Link); return Statement; } EFI_STATUS UpdateCheckBoxStringToken ( IN CONST FORM_BROWSER_FORMSET *FormSet, IN FORM_BROWSER_STATEMENT *Statement ) { CHAR16 Str[MAXIMUM_VALUE_CHARACTERS]; EFI_STRING_ID Id; EFI_STATUS Status; ASSERT (Statement != NULL); ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP); UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1); Status = HiiLibNewString (FormSet->HiiHandle, &Id, Str); if (EFI_ERROR (Status)) { return Status; } Statement->VarStoreInfo.VarName = Id; return EFI_SUCCESS; } BOOLEAN IsNextOpCodeGuidedVarEqName ( UINT8 *OpCodeData ) { // // Get next opcode // OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; if (*OpCodeData == EFI_IFR_GUID_OP) { if (CompareGuid (&mFrameworkHiiCompatibilityGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { // // Specific GUIDed opcodes to support IFR generated from Framework HII VFR // if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) { return TRUE; } } } return FALSE; } /** Initialize Question's members. @param OpCodeData Pointer of the raw OpCode data. @param FormSet Pointer of the current FormSet. @param Form Pointer of the current Form. @return The Question. **/ FORM_BROWSER_STATEMENT * CreateQuestion ( IN UINT8 *OpCodeData, IN OUT FORM_BROWSER_FORMSET *FormSet, IN OUT FORM_BROWSER_FORM *Form ) { FORM_BROWSER_STATEMENT *Statement; EFI_IFR_QUESTION_HEADER *QuestionHdr; LIST_ENTRY *Link; FORMSET_STORAGE *Storage; NAME_VALUE_NODE *NameValueNode; EFI_STATUS Status; Statement = CreateStatement (OpCodeData, FormSet, Form); if (Statement == NULL) { return NULL; } QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID)); CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID)); CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16)); Statement->QuestionFlags = QuestionHdr->Flags; if (Statement->VarStoreId == 0) { // // VarStoreId of zero indicates no variable storage // return Statement; } // // Take a look at next OpCode to see whether it is a GUIDed opcode to support // Framework Compatibility // if (FeaturePcdGet (PcdFrameworkHiiCompatibilitySupport)) { if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) { Status = UpdateCheckBoxStringToken (FormSet, Statement); if (EFI_ERROR (Status)) { return NULL; } } } // // Find Storage for this Question // Link = GetFirstNode (&FormSet->StorageListHead); while (!IsNull (&FormSet->StorageListHead, Link)) { Storage = FORMSET_STORAGE_FROM_LINK (Link); if (Storage->VarStoreId == Statement->VarStoreId) { Statement->Storage = Storage; break; } Link = GetNextNode (&FormSet->StorageListHead, Link); } ASSERT (Statement->Storage != NULL); // // Initialilze varname for Name/Value or EFI Variable // if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) || (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) { Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle); ASSERT (Statement->VariableName != NULL); if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { // // Insert to Name/Value varstore list // NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE)); ASSERT (NameValueNode != NULL); NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE; NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName); ASSERT (NameValueNode->Name != NULL); NameValueNode->Value = AllocateZeroPool (0x10); ASSERT (NameValueNode->Value != NULL); NameValueNode->EditValue = AllocateZeroPool (0x10); ASSERT (NameValueNode->EditValue != NULL); InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link); } } return Statement; } /** Allocate a FORM_EXPRESSION node. @param Form The Form associated with this Expression @return Pointer to a FORM_EXPRESSION data structure. **/ FORM_EXPRESSION * CreateExpression ( IN OUT FORM_BROWSER_FORM *Form ) { FORM_EXPRESSION *Expression; Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION)); Expression->Signature = FORM_EXPRESSION_SIGNATURE; InitializeListHead (&Expression->OpCodeListHead); return Expression; } /** Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List. @param FormSet Pointer of the current FormSet @return Pointer to a FORMSET_STORAGE data structure. **/ FORMSET_STORAGE * CreateStorage ( IN FORM_BROWSER_FORMSET *FormSet ) { FORMSET_STORAGE *Storage; Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE)); Storage->Signature = FORMSET_STORAGE_SIGNATURE; InitializeListHead (&Storage->NameValueListHead); InsertTailList (&FormSet->StorageListHead, &Storage->Link); return Storage; } /** Create ConfigHdr string for a storage. @param FormSet Pointer of the current FormSet @param Storage Pointer of the storage @retval EFI_SUCCESS Initialize ConfigHdr success **/ EFI_STATUS InitializeConfigHdr ( IN FORM_BROWSER_FORMSET *FormSet, IN OUT FORMSET_STORAGE *Storage ) { EFI_STATUS Status; UINTN StrBufferLen; CHAR16 *Name; if (Storage->Type == EFI_HII_VARSTORE_BUFFER) { Name = Storage->Name; } else { Name = NULL; } StrBufferLen = 0; Status = ConstructConfigHdr ( Storage->ConfigHdr, &StrBufferLen, &Storage->Guid, Name, FormSet->DriverHandle ); if (Status == EFI_BUFFER_TOO_SMALL) { Storage->ConfigHdr = AllocateZeroPool (StrBufferLen); Status = ConstructConfigHdr ( Storage->ConfigHdr, &StrBufferLen, &Storage->Guid, Name, FormSet->DriverHandle ); } if (EFI_ERROR (Status)) { return Status; } Storage->ConfigRequest = AllocateCopyPool (StrBufferLen, Storage->ConfigHdr); Storage->SpareStrLen = 0; return EFI_SUCCESS; } /** Initialize Request Element of a Question. ::= '&' | '&'