| /** @file | |
| The definition of CFormPkg's member function | |
| Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR> | |
| 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 "stdio.h" | |
| #include "VfrFormPkg.h" | |
| /* | |
| * The definition of CFormPkg's member function | |
| */ | |
| SPendingAssign::SPendingAssign ( | |
| IN CHAR8 *Key, | |
| IN VOID *Addr, | |
| IN UINT32 Len, | |
| IN UINT32 LineNo, | |
| IN CONST CHAR8 *Msg | |
| ) | |
| { | |
| mKey = NULL; | |
| mAddr = Addr; | |
| mLen = Len; | |
| mFlag = PENDING; | |
| mLineNo = LineNo; | |
| mMsg = NULL; | |
| mNext = NULL; | |
| if (Key != NULL) { | |
| mKey = new CHAR8[strlen (Key) + 1]; | |
| if (mKey != NULL) { | |
| strcpy (mKey, Key); | |
| } | |
| } | |
| if (Msg != NULL) { | |
| mMsg = new CHAR8[strlen (Msg) + 1]; | |
| if (mMsg != NULL) { | |
| strcpy (mMsg, Msg); | |
| } | |
| } | |
| } | |
| SPendingAssign::~SPendingAssign ( | |
| VOID | |
| ) | |
| { | |
| if (mKey != NULL) { | |
| delete mKey; | |
| } | |
| mAddr = NULL; | |
| mLen = 0; | |
| mLineNo = 0; | |
| if (mMsg != NULL) { | |
| delete mMsg; | |
| } | |
| mNext = NULL; | |
| } | |
| VOID | |
| SPendingAssign::SetAddrAndLen ( | |
| IN VOID *Addr, | |
| IN UINT32 LineNo | |
| ) | |
| { | |
| mAddr = Addr; | |
| mLineNo = LineNo; | |
| } | |
| VOID | |
| SPendingAssign::AssignValue ( | |
| IN VOID *Addr, | |
| IN UINT32 Len | |
| ) | |
| { | |
| memcpy (mAddr, Addr, (mLen < Len ? mLen : Len)); | |
| mFlag = ASSIGNED; | |
| } | |
| CHAR8 * | |
| SPendingAssign::GetKey ( | |
| VOID | |
| ) | |
| { | |
| return mKey; | |
| } | |
| CFormPkg::CFormPkg ( | |
| IN UINT32 BufferSize = 4096 | |
| ) | |
| { | |
| CHAR8 *BufferStart; | |
| CHAR8 *BufferEnd; | |
| SBufferNode *Node; | |
| mPkgLength = 0; | |
| mBufferNodeQueueHead = NULL; | |
| mCurrBufferNode = NULL; | |
| Node = new SBufferNode; | |
| if (Node == NULL) { | |
| return ; | |
| } | |
| BufferStart = new CHAR8[BufferSize]; | |
| if (BufferStart == NULL) { | |
| return; | |
| } | |
| BufferEnd = BufferStart + BufferSize; | |
| memset (BufferStart, 0, BufferSize); | |
| Node->mBufferStart = BufferStart; | |
| Node->mBufferEnd = BufferEnd; | |
| Node->mBufferFree = BufferStart; | |
| Node->mNext = NULL; | |
| mBufferSize = BufferSize; | |
| mBufferNodeQueueHead = Node; | |
| mBufferNodeQueueTail = Node; | |
| mCurrBufferNode = Node; | |
| } | |
| CFormPkg::~CFormPkg () | |
| { | |
| SBufferNode *pBNode; | |
| SPendingAssign *pPNode; | |
| while (mBufferNodeQueueHead != NULL) { | |
| pBNode = mBufferNodeQueueHead; | |
| mBufferNodeQueueHead = mBufferNodeQueueHead->mNext; | |
| if (pBNode->mBufferStart != NULL) { | |
| delete pBNode->mBufferStart; | |
| delete pBNode; | |
| } | |
| } | |
| mBufferNodeQueueTail = NULL; | |
| mCurrBufferNode = NULL; | |
| while (PendingAssignList != NULL) { | |
| pPNode = PendingAssignList; | |
| PendingAssignList = PendingAssignList->mNext; | |
| delete pPNode; | |
| } | |
| PendingAssignList = NULL; | |
| } | |
| CHAR8 * | |
| CFormPkg::IfrBinBufferGet ( | |
| IN UINT32 Len | |
| ) | |
| { | |
| CHAR8 *BinBuffer = NULL; | |
| if ((Len == 0) || (Len > mBufferSize)) { | |
| return NULL; | |
| } | |
| if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) { | |
| BinBuffer = mCurrBufferNode->mBufferFree; | |
| mCurrBufferNode->mBufferFree += Len; | |
| } else { | |
| SBufferNode *Node; | |
| Node = new SBufferNode; | |
| if (Node == NULL) { | |
| return NULL; | |
| } | |
| Node->mBufferStart = new CHAR8[mBufferSize]; | |
| if (Node->mBufferStart == NULL) { | |
| delete Node; | |
| return NULL; | |
| } else { | |
| memset (Node->mBufferStart, 0, mBufferSize); | |
| Node->mBufferEnd = Node->mBufferStart + mBufferSize; | |
| Node->mBufferFree = Node->mBufferStart; | |
| Node->mNext = NULL; | |
| } | |
| if (mBufferNodeQueueTail == NULL) { | |
| mBufferNodeQueueHead = mBufferNodeQueueTail = Node; | |
| } else { | |
| mBufferNodeQueueTail->mNext = Node; | |
| mBufferNodeQueueTail = Node; | |
| } | |
| mCurrBufferNode = Node; | |
| // | |
| // Now try again. | |
| // | |
| BinBuffer = mCurrBufferNode->mBufferFree; | |
| mCurrBufferNode->mBufferFree += Len; | |
| } | |
| mPkgLength += Len; | |
| return BinBuffer; | |
| } | |
| inline | |
| UINT32 | |
| CFormPkg::GetPkgLength ( | |
| VOID | |
| ) | |
| { | |
| return mPkgLength; | |
| } | |
| VOID | |
| CFormPkg::Open ( | |
| VOID | |
| ) | |
| { | |
| mReadBufferNode = mBufferNodeQueueHead; | |
| mReadBufferOffset = 0; | |
| } | |
| VOID | |
| CFormPkg::Close ( | |
| VOID | |
| ) | |
| { | |
| mReadBufferNode = NULL; | |
| mReadBufferOffset = 0; | |
| } | |
| UINT32 | |
| CFormPkg::Read ( | |
| IN CHAR8 *Buffer, | |
| IN UINT32 Size | |
| ) | |
| { | |
| UINT32 Index; | |
| if ((Size == 0) || (Buffer == NULL)) { | |
| return 0; | |
| } | |
| if (mReadBufferNode == NULL) { | |
| return 0; | |
| } | |
| for (Index = 0; Index < Size; Index++) { | |
| if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) { | |
| Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++]; | |
| } else { | |
| if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) { | |
| return Index; | |
| } else { | |
| mReadBufferOffset = 0; | |
| Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++]; | |
| } | |
| } | |
| } | |
| return Size; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CFormPkg::BuildPkgHdr ( | |
| OUT EFI_HII_PACKAGE_HEADER **PkgHdr | |
| ) | |
| { | |
| if (PkgHdr == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM; | |
| (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CFormPkg::BuildPkg ( | |
| OUT PACKAGE_DATA &TBuffer | |
| ) | |
| { | |
| CHAR8 *Temp; | |
| UINT32 Size; | |
| CHAR8 Buffer[1024]; | |
| if (TBuffer.Buffer != NULL) { | |
| delete TBuffer.Buffer; | |
| } | |
| TBuffer.Size = mPkgLength; | |
| TBuffer.Buffer = NULL; | |
| if (TBuffer.Size != 0) { | |
| TBuffer.Buffer = new CHAR8[TBuffer.Size]; | |
| } else { | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| Temp = TBuffer.Buffer; | |
| Open (); | |
| while ((Size = Read (Buffer, 1024)) != 0) { | |
| memcpy (Temp, Buffer, Size); | |
| Temp += Size; | |
| } | |
| Close (); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CFormPkg::BuildPkg ( | |
| IN FILE *Output, | |
| IN PACKAGE_DATA *PkgData | |
| ) | |
| { | |
| EFI_VFR_RETURN_CODE Ret; | |
| CHAR8 Buffer[1024]; | |
| UINT32 Size; | |
| EFI_HII_PACKAGE_HEADER *PkgHdr; | |
| if (Output == NULL) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) { | |
| return Ret; | |
| } | |
| fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output); | |
| delete PkgHdr; | |
| if (PkgData == NULL) { | |
| Open (); | |
| while ((Size = Read (Buffer, 1024)) != 0) { | |
| fwrite (Buffer, Size, 1, Output); | |
| } | |
| Close (); | |
| } else { | |
| fwrite (PkgData->Buffer, PkgData->Size, 1, Output); | |
| } | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| VOID | |
| CFormPkg::_WRITE_PKG_LINE ( | |
| IN FILE *pFile, | |
| IN UINT32 LineBytes, | |
| IN CONST CHAR8 *LineHeader, | |
| IN CHAR8 *BlkBuf, | |
| IN UINT32 BlkSize | |
| ) | |
| { | |
| UINT32 Index; | |
| if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { | |
| return; | |
| } | |
| for (Index = 0; Index < BlkSize; Index++) { | |
| if ((Index % LineBytes) == 0) { | |
| fprintf (pFile, "\n%s", LineHeader); | |
| } | |
| fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); | |
| } | |
| } | |
| VOID | |
| CFormPkg::_WRITE_PKG_END ( | |
| IN FILE *pFile, | |
| IN UINT32 LineBytes, | |
| IN CONST CHAR8 *LineHeader, | |
| IN CHAR8 *BlkBuf, | |
| IN UINT32 BlkSize | |
| ) | |
| { | |
| UINT32 Index; | |
| if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { | |
| return; | |
| } | |
| for (Index = 0; Index < BlkSize - 1; Index++) { | |
| if ((Index % LineBytes) == 0) { | |
| fprintf (pFile, "\n%s", LineHeader); | |
| } | |
| fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); | |
| } | |
| if ((Index % LineBytes) == 0) { | |
| fprintf (pFile, "\n%s", LineHeader); | |
| } | |
| fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]); | |
| } | |
| #define BYTES_PRE_LINE 0x10 | |
| EFI_VFR_RETURN_CODE | |
| CFormPkg::GenCFile ( | |
| IN CHAR8 *BaseName, | |
| IN FILE *pFile, | |
| IN PACKAGE_DATA *PkgData | |
| ) | |
| { | |
| EFI_VFR_RETURN_CODE Ret; | |
| CHAR8 Buffer[BYTES_PRE_LINE * 8]; | |
| EFI_HII_PACKAGE_HEADER *PkgHdr; | |
| UINT32 PkgLength = 0; | |
| UINT32 ReadSize = 0; | |
| if ((BaseName == NULL) || (pFile == NULL)) { | |
| return VFR_RETURN_FATAL_ERROR; | |
| } | |
| fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName); | |
| if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) { | |
| return Ret; | |
| } | |
| // | |
| // For framework vfr file, the extension framework header will be added. | |
| // | |
| if (VfrCompatibleMode) { | |
| fprintf (pFile, " // FRAMEWORK PACKAGE HEADER Length\n"); | |
| PkgLength = PkgHdr->Length + sizeof (UINT32) + 2; | |
| _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32)); | |
| fprintf (pFile, "\n\n // FRAMEWORK PACKAGE HEADER Type\n"); | |
| PkgLength = 3; | |
| _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT16)); | |
| } else { | |
| fprintf (pFile, " // ARRAY LENGTH\n"); | |
| PkgLength = PkgHdr->Length + sizeof (UINT32); | |
| _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32)); | |
| } | |
| fprintf (pFile, "\n\n // PACKAGE HEADER\n"); | |
| _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER)); | |
| PkgLength = sizeof (EFI_HII_PACKAGE_HEADER); | |
| fprintf (pFile, "\n\n // PACKAGE DATA\n"); | |
| if (PkgData == NULL) { | |
| Open (); | |
| while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) { | |
| PkgLength += ReadSize; | |
| if (PkgLength < PkgHdr->Length) { | |
| _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize); | |
| } else { | |
| _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize); | |
| } | |
| } | |
| Close (); | |
| } else { | |
| if (PkgData->Size % BYTES_PRE_LINE != 0) { | |
| PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE); | |
| _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength); | |
| _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE); | |
| } else { | |
| PkgLength = PkgData->Size - BYTES_PRE_LINE; | |
| _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength); | |
| _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE); | |
| } | |
| } | |
| delete PkgHdr; | |
| fprintf (pFile, "\n};\n"); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CFormPkg::AssignPending ( | |
| IN CHAR8 *Key, | |
| IN VOID *ValAddr, | |
| IN UINT32 ValLen, | |
| IN UINT32 LineNo, | |
| IN CONST CHAR8 *Msg | |
| ) | |
| { | |
| SPendingAssign *pNew; | |
| pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg); | |
| if (pNew == NULL) { | |
| return VFR_RETURN_OUT_FOR_RESOURCES; | |
| } | |
| pNew->mNext = PendingAssignList; | |
| PendingAssignList = pNew; | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| VOID | |
| CFormPkg::DoPendingAssign ( | |
| IN CHAR8 *Key, | |
| IN VOID *ValAddr, | |
| IN UINT32 ValLen | |
| ) | |
| { | |
| SPendingAssign *pNode; | |
| if ((Key == NULL) || (ValAddr == NULL)) { | |
| return; | |
| } | |
| for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { | |
| if (strcmp (pNode->mKey, Key) == 0) { | |
| pNode->AssignValue (ValAddr, ValLen); | |
| } | |
| } | |
| } | |
| bool | |
| CFormPkg::HavePendingUnassigned ( | |
| VOID | |
| ) | |
| { | |
| SPendingAssign *pNode; | |
| for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mFlag == PENDING) { | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| VOID | |
| CFormPkg::PendingAssignPrintAll ( | |
| VOID | |
| ) | |
| { | |
| SPendingAssign *pNode; | |
| for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mFlag == PENDING) { | |
| gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg); | |
| } | |
| } | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CFormPkg::DeclarePendingQuestion ( | |
| IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB, | |
| IN CVfrDataStorage &lCVfrDataStorage, | |
| IN CVfrQuestionDB &lCVfrQuestionDB, | |
| IN EFI_GUID *LocalFormSetGuid, | |
| IN UINT32 LineNo | |
| ) | |
| { | |
| SPendingAssign *pNode; | |
| CHAR8 *VarStr; | |
| UINT32 ArrayIdx; | |
| CHAR8 FName[MAX_NAME_LEN]; | |
| CHAR8 *SName; | |
| CHAR8 *NewStr; | |
| EFI_VFR_RETURN_CODE ReturnCode; | |
| EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; | |
| // | |
| // Declare all questions as Numeric in DisableIf True | |
| // | |
| // DisableIf | |
| CIfrDisableIf DIObj; | |
| DIObj.SetLineNo (LineNo); | |
| //TrueOpcode | |
| CIfrTrue TObj (LineNo); | |
| // Declare Numeric qeustion for each undefined question. | |
| for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mFlag == PENDING) { | |
| CIfrNumeric CNObj; | |
| EFI_VARSTORE_INFO Info; | |
| EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; | |
| CNObj.SetLineNo (LineNo); | |
| CNObj.SetPrompt (0x0); | |
| CNObj.SetHelp (0x0); | |
| // | |
| // Register this question, assume it is normal question, not date or time question | |
| // | |
| VarStr = pNode->mKey; | |
| ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId); | |
| if (ReturnCode != VFR_RETURN_SUCCESS) { | |
| gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); | |
| return ReturnCode; | |
| } | |
| #ifdef VFREXP_DEBUG | |
| printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId); | |
| #endif | |
| // | |
| // Get Question Info, framework vfr VarName == StructName | |
| // | |
| ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx); | |
| if (ReturnCode != VFR_RETURN_SUCCESS) { | |
| gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable"); | |
| return ReturnCode; | |
| } | |
| // | |
| // Get VarStoreType | |
| // | |
| ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType); | |
| if (ReturnCode == VFR_RETURN_UNDEFINED) { | |
| lCVfrDataStorage.DeclareBufferVarStore ( | |
| FName, | |
| LocalFormSetGuid, | |
| &lCVfrVarDataTypeDB, | |
| FName, | |
| EFI_VARSTORE_ID_INVALID, | |
| FALSE | |
| ); | |
| ReturnCode = lCVfrDataStorage.GetVarStoreType (FName, VarStoreType); | |
| } | |
| if (ReturnCode != VFR_RETURN_SUCCESS) { | |
| gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined"); | |
| return ReturnCode; | |
| } | |
| ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId); | |
| if (ReturnCode != VFR_RETURN_SUCCESS) { | |
| gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined"); | |
| return ReturnCode; | |
| } | |
| if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) { | |
| ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx); | |
| } else { | |
| if (VarStoreType == EFI_VFR_VARSTORE_EFI) { | |
| ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info); | |
| } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER) { | |
| VarStr = pNode->mKey; | |
| //convert VarStr with store name to VarStr with structure name | |
| ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (FName, &SName); | |
| if (ReturnCode == VFR_RETURN_SUCCESS) { | |
| NewStr = new CHAR8[strlen (VarStr) + strlen (SName) + 1]; | |
| NewStr[0] = '\0'; | |
| strcpy (NewStr, SName); | |
| strcat (NewStr, VarStr + strlen (FName)); | |
| ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize); | |
| delete NewStr; | |
| } | |
| } else { | |
| ReturnCode = VFR_RETURN_UNSUPPORTED; | |
| } | |
| } | |
| if (ReturnCode != VFR_RETURN_SUCCESS) { | |
| gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); | |
| return ReturnCode; | |
| } | |
| CNObj.SetQuestionId (QId); | |
| CNObj.SetVarStoreInfo (&Info); | |
| // | |
| // Numeric doesn't support BOOLEAN data type. | |
| // BOOLEAN type has the same data size to UINT8. | |
| // | |
| if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) { | |
| Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8; | |
| } | |
| CNObj.SetFlags (0, Info.mVarType); | |
| // | |
| // Use maximum value not to limit the vaild value for the undefined question. | |
| // | |
| switch (Info.mVarType) { | |
| case EFI_IFR_TYPE_NUM_SIZE_64: | |
| CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_32: | |
| CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_16: | |
| CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_8: | |
| CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0); | |
| break; | |
| default: | |
| break; | |
| } | |
| // | |
| // For undefined Efi VarStore type question | |
| // Append the extended guided opcode to contain VarName | |
| // | |
| if (VarStoreType == EFI_VFR_VARSTORE_EFI || VfrCompatibleMode) { | |
| CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName); | |
| CVNObj.SetLineNo (LineNo); | |
| } | |
| // | |
| // End for Numeric | |
| // | |
| CIfrEnd CEObj; | |
| CEObj.SetLineNo (LineNo); | |
| } | |
| } | |
| // | |
| // End for DisableIf | |
| // | |
| CIfrEnd SEObj; | |
| SEObj.SetLineNo (LineNo); | |
| return VFR_RETURN_SUCCESS; | |
| } | |
| CFormPkg gCFormPkg; | |
| SIfrRecord::SIfrRecord ( | |
| VOID | |
| ) | |
| { | |
| mIfrBinBuf = NULL; | |
| mBinBufLen = 0; | |
| mLineNo = 0xFFFFFFFF; | |
| mOffset = 0xFFFFFFFF; | |
| mNext = NULL; | |
| } | |
| SIfrRecord::~SIfrRecord ( | |
| VOID | |
| ) | |
| { | |
| if (mIfrBinBuf != NULL) { | |
| //delete mIfrBinBuf; | |
| mIfrBinBuf = NULL; | |
| } | |
| mLineNo = 0xFFFFFFFF; | |
| mOffset = 0xFFFFFFFF; | |
| mBinBufLen = 0; | |
| mNext = NULL; | |
| } | |
| CIfrRecordInfoDB::CIfrRecordInfoDB ( | |
| VOID | |
| ) | |
| { | |
| mSwitch = TRUE; | |
| mRecordCount = EFI_IFR_RECORDINFO_IDX_START; | |
| mIfrRecordListHead = NULL; | |
| mIfrRecordListTail = NULL; | |
| } | |
| CIfrRecordInfoDB::~CIfrRecordInfoDB ( | |
| VOID | |
| ) | |
| { | |
| SIfrRecord *pNode; | |
| while (mIfrRecordListHead != NULL) { | |
| pNode = mIfrRecordListHead; | |
| mIfrRecordListHead = mIfrRecordListHead->mNext; | |
| delete pNode; | |
| } | |
| } | |
| SIfrRecord * | |
| CIfrRecordInfoDB::GetRecordInfoFromIdx ( | |
| IN UINT32 RecordIdx | |
| ) | |
| { | |
| UINT32 Idx; | |
| SIfrRecord *pNode = NULL; | |
| if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) { | |
| return NULL; | |
| } | |
| for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead; | |
| (Idx != RecordIdx) && (pNode != NULL); | |
| Idx++, pNode = pNode->mNext) | |
| ; | |
| return pNode; | |
| } | |
| UINT32 | |
| CIfrRecordInfoDB::IfrRecordRegister ( | |
| IN UINT32 LineNo, | |
| IN CHAR8 *IfrBinBuf, | |
| IN UINT8 BinBufLen, | |
| IN UINT32 Offset | |
| ) | |
| { | |
| SIfrRecord *pNew; | |
| if (mSwitch == FALSE) { | |
| return EFI_IFR_RECORDINFO_IDX_INVALUD; | |
| } | |
| if ((pNew = new SIfrRecord) == NULL) { | |
| return EFI_IFR_RECORDINFO_IDX_INVALUD; | |
| } | |
| if (mIfrRecordListHead == NULL) { | |
| mIfrRecordListHead = pNew; | |
| mIfrRecordListTail = pNew; | |
| } else { | |
| mIfrRecordListTail->mNext = pNew; | |
| mIfrRecordListTail = pNew; | |
| } | |
| mRecordCount++; | |
| return mRecordCount; | |
| } | |
| VOID | |
| CIfrRecordInfoDB::IfrRecordInfoUpdate ( | |
| IN UINT32 RecordIdx, | |
| IN UINT32 LineNo, | |
| IN CHAR8 *BinBuf, | |
| IN UINT8 BinBufLen, | |
| IN UINT32 Offset | |
| ) | |
| { | |
| SIfrRecord *pNode; | |
| SIfrRecord *Prev; | |
| if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) { | |
| return; | |
| } | |
| if (LineNo == 0) { | |
| // | |
| // Line number is not specified explicitly, try to use line number of previous opcode | |
| // | |
| Prev = GetRecordInfoFromIdx (RecordIdx - 1); | |
| if (Prev != NULL) { | |
| LineNo = Prev->mLineNo; | |
| } | |
| } | |
| pNode->mLineNo = LineNo; | |
| pNode->mOffset = Offset; | |
| pNode->mBinBufLen = BinBufLen; | |
| pNode->mIfrBinBuf = BinBuf; | |
| } | |
| VOID | |
| CIfrRecordInfoDB::IfrRecordOutput ( | |
| OUT PACKAGE_DATA &TBuffer | |
| ) | |
| { | |
| CHAR8 *Temp; | |
| SIfrRecord *pNode; | |
| if (TBuffer.Buffer != NULL) { | |
| delete TBuffer.Buffer; | |
| } | |
| TBuffer.Size = 0; | |
| TBuffer.Buffer = NULL; | |
| if (mSwitch == FALSE) { | |
| return; | |
| } | |
| for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { | |
| TBuffer.Size += pNode->mBinBufLen; | |
| } | |
| if (TBuffer.Size != 0) { | |
| TBuffer.Buffer = new CHAR8[TBuffer.Size]; | |
| } else { | |
| return; | |
| } | |
| Temp = TBuffer.Buffer; | |
| for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mIfrBinBuf != NULL) { | |
| memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen); | |
| Temp += pNode->mBinBufLen; | |
| } | |
| } | |
| return; | |
| } | |
| VOID | |
| CIfrRecordInfoDB::IfrRecordOutput ( | |
| IN FILE *File, | |
| IN UINT32 LineNo | |
| ) | |
| { | |
| SIfrRecord *pNode; | |
| UINT8 Index; | |
| UINT32 TotalSize; | |
| if (mSwitch == FALSE) { | |
| return; | |
| } | |
| if (File == NULL) { | |
| return; | |
| } | |
| TotalSize = 0; | |
| for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { | |
| if (pNode->mLineNo == LineNo || LineNo == 0) { | |
| fprintf (File, ">%08X: ", pNode->mOffset); | |
| TotalSize += pNode->mBinBufLen; | |
| if (pNode->mIfrBinBuf != NULL) { | |
| for (Index = 0; Index < pNode->mBinBufLen; Index++) { | |
| fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index])); | |
| } | |
| } | |
| fprintf (File, "\n"); | |
| } | |
| } | |
| if (LineNo == 0) { | |
| fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize); | |
| } | |
| } | |
| // | |
| // for framework vfr file | |
| // adjust opcode sequence for uefi IFR format | |
| // adjust inconsistent and varstore into the right position. | |
| // | |
| BOOLEAN | |
| CIfrRecordInfoDB::CheckQuestionOpCode ( | |
| IN UINT8 OpCode | |
| ) | |
| { | |
| switch (OpCode) { | |
| case EFI_IFR_CHECKBOX_OP: | |
| case EFI_IFR_NUMERIC_OP: | |
| case EFI_IFR_PASSWORD_OP: | |
| case EFI_IFR_ONE_OF_OP: | |
| case EFI_IFR_ACTION_OP: | |
| case EFI_IFR_STRING_OP: | |
| case EFI_IFR_DATE_OP: | |
| case EFI_IFR_TIME_OP: | |
| case EFI_IFR_ORDERED_LIST_OP: | |
| return TRUE; | |
| default: | |
| return FALSE; | |
| } | |
| } | |
| BOOLEAN | |
| CIfrRecordInfoDB::CheckIdOpCode ( | |
| IN UINT8 OpCode | |
| ) | |
| { | |
| switch (OpCode) { | |
| case EFI_IFR_EQ_ID_VAL_OP: | |
| case EFI_IFR_EQ_ID_ID_OP: | |
| case EFI_IFR_EQ_ID_LIST_OP: | |
| case EFI_IFR_QUESTION_REF1_OP: | |
| return TRUE; | |
| default: | |
| return FALSE; | |
| } | |
| } | |
| EFI_QUESTION_ID | |
| CIfrRecordInfoDB::GetOpcodeQuestionId ( | |
| IN EFI_IFR_OP_HEADER *OpHead | |
| ) | |
| { | |
| EFI_IFR_QUESTION_HEADER *QuestionHead; | |
| QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1); | |
| return QuestionHead->QuestionId; | |
| } | |
| EFI_VFR_RETURN_CODE | |
| CIfrRecordInfoDB::IfrRecordAdjust ( | |
| VOID | |
| ) | |
| { | |
| SIfrRecord *pNode, *preNode; | |
| SIfrRecord *uNode, *tNode; | |
| EFI_IFR_OP_HEADER *OpHead, *tOpHead; | |
| EFI_QUESTION_ID QuestionId; | |
| UINT32 StackCount; | |
| UINT32 QuestionScope; | |
| UINT32 OpcodeOffset; | |
| CHAR8 ErrorMsg[MAX_STRING_LEN] = {0, }; | |
| EFI_VFR_RETURN_CODE Status; | |
| // | |
| // Init local variable | |
| // | |
| Status = VFR_RETURN_SUCCESS; | |
| pNode = mIfrRecordListHead; | |
| preNode = pNode; | |
| QuestionScope = 0; | |
| while (pNode != NULL) { | |
| OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf; | |
| // | |
| // make sure the inconsistent opcode in question scope | |
| // | |
| if (QuestionScope > 0) { | |
| QuestionScope += OpHead->Scope; | |
| if (OpHead->OpCode == EFI_IFR_END_OP) { | |
| QuestionScope --; | |
| } | |
| } | |
| if (CheckQuestionOpCode (OpHead->OpCode)) { | |
| QuestionScope = 1; | |
| } | |
| // | |
| // for the inconsistent opcode not in question scope, adjust it | |
| // | |
| if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) { | |
| // | |
| // for inconsistent opcode not in question scope | |
| // | |
| // | |
| // Count inconsistent opcode Scope | |
| // | |
| StackCount = OpHead->Scope; | |
| QuestionId = EFI_QUESTION_ID_INVALID; | |
| tNode = pNode; | |
| while (tNode != NULL && StackCount > 0) { | |
| tNode = tNode->mNext; | |
| tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf; | |
| // | |
| // Calculate Scope Number | |
| // | |
| StackCount += tOpHead->Scope; | |
| if (tOpHead->OpCode == EFI_IFR_END_OP) { | |
| StackCount --; | |
| } | |
| // | |
| // by IdEqual opcode to get QuestionId | |
| // | |
| if (QuestionId == EFI_QUESTION_ID_INVALID && | |
| CheckIdOpCode (tOpHead->OpCode)) { | |
| QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1); | |
| } | |
| } | |
| if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) { | |
| // | |
| // report error; not found | |
| // | |
| sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId); | |
| gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg); | |
| Status = VFR_RETURN_MISMATCHED; | |
| break; | |
| } | |
| // | |
| // extract inconsistent opcode list | |
| // pNode is Incosistent opcode, tNode is End Opcode | |
| // | |
| // | |
| // insert inconsistent opcode list into the right question scope by questionid | |
| // | |
| for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) { | |
| tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf; | |
| if (CheckQuestionOpCode (tOpHead->OpCode) && | |
| (QuestionId == GetOpcodeQuestionId (tOpHead))) { | |
| break; | |
| } | |
| } | |
| // | |
| // insert inconsistent opcode list and check LATE_CHECK flag | |
| // | |
| if (uNode != NULL) { | |
| if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) { | |
| // | |
| // if LATE_CHECK flag is set, change inconsistent to nosumbit | |
| // | |
| OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP; | |
| } | |
| // | |
| // skip the default storage for Date and Time | |
| // | |
| if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) { | |
| uNode = uNode->mNext; | |
| } | |
| preNode->mNext = tNode->mNext; | |
| tNode->mNext = uNode->mNext; | |
| uNode->mNext = pNode; | |
| // | |
| // reset pNode to head list, scan the whole list again. | |
| // | |
| pNode = mIfrRecordListHead; | |
| preNode = pNode; | |
| QuestionScope = 0; | |
| continue; | |
| } else { | |
| // | |
| // not found matched question id, report error | |
| // | |
| sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId); | |
| gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg); | |
| Status = VFR_RETURN_MISMATCHED; | |
| break; | |
| } | |
| } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP || | |
| OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) { | |
| // | |
| // for new added group of varstore opcode | |
| // | |
| tNode = pNode; | |
| while (tNode->mNext != NULL) { | |
| tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf; | |
| if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP && | |
| tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) { | |
| break; | |
| } | |
| tNode = tNode->mNext; | |
| } | |
| if (tNode->mNext == NULL) { | |
| // | |
| // invalid IfrCode, IfrCode end by EndOpCode | |
| // | |
| gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end"); | |
| Status = VFR_RETURN_MISMATCHED; | |
| break; | |
| } | |
| if (tOpHead->OpCode != EFI_IFR_END_OP) { | |
| // | |
| // not new added varstore, which are not needed to be adjust. | |
| // | |
| preNode = tNode; | |
| pNode = tNode->mNext; | |
| continue; | |
| } else { | |
| // | |
| // move new added varstore opcode to the position befor form opcode | |
| // varstore opcode between pNode and tNode | |
| // | |
| // | |
| // search form opcode from begin | |
| // | |
| for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) { | |
| tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf; | |
| if (tOpHead->OpCode == EFI_IFR_FORM_OP) { | |
| break; | |
| } | |
| } | |
| // | |
| // Insert varstore opcode beform form opcode if form opcode is found | |
| // | |
| if (uNode->mNext != NULL) { | |
| preNode->mNext = tNode->mNext; | |
| tNode->mNext = uNode->mNext; | |
| uNode->mNext = pNode; | |
| // | |
| // reset pNode to head list, scan the whole list again. | |
| // | |
| pNode = mIfrRecordListHead; | |
| preNode = pNode; | |
| QuestionScope = 0; | |
| continue; | |
| } else { | |
| // | |
| // not found form, continue scan IfrRecord list | |
| // | |
| preNode = tNode; | |
| pNode = tNode->mNext; | |
| continue; | |
| } | |
| } | |
| } | |
| // | |
| // next node | |
| // | |
| preNode = pNode; | |
| pNode = pNode->mNext; | |
| } | |
| // | |
| // Update Ifr Opcode Offset | |
| // | |
| if (Status == VFR_RETURN_SUCCESS) { | |
| OpcodeOffset = 0; | |
| for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { | |
| pNode->mOffset = OpcodeOffset; | |
| OpcodeOffset += pNode->mBinBufLen; | |
| } | |
| } | |
| return Status; | |
| } | |
| CIfrRecordInfoDB gCIfrRecordInfoDB; | |
| VOID | |
| CIfrObj::_EMIT_PENDING_OBJ ( | |
| VOID | |
| ) | |
| { | |
| CHAR8 *ObjBinBuf = NULL; | |
| // | |
| // do nothing | |
| // | |
| if (!mDelayEmit || !gCreateOp) { | |
| return; | |
| } | |
| mPkgOffset = gCFormPkg.GetPkgLength (); | |
| // | |
| // update data buffer to package data | |
| // | |
| ObjBinBuf = gCFormPkg.IfrBinBufferGet (mObjBinLen); | |
| if (ObjBinBuf != NULL) { | |
| memcpy (ObjBinBuf, mObjBinBuf, mObjBinLen); | |
| } | |
| // | |
| // update bin buffer to package data buffer | |
| // | |
| if (mObjBinBuf != NULL) { | |
| delete mObjBinBuf; | |
| mObjBinBuf = ObjBinBuf; | |
| } | |
| mDelayEmit = FALSE; | |
| } | |
| /* | |
| * The definition of CIfrObj's member function | |
| */ | |
| static struct { | |
| UINT8 mSize; | |
| UINT8 mScope; | |
| } gOpcodeSizesScopeTable[] = { | |
| { 0, 0 }, // EFI_IFR_INVALID - 0x00 | |
| { sizeof (EFI_IFR_FORM), 1 }, // EFI_IFR_FORM_OP | |
| { sizeof (EFI_IFR_SUBTITLE), 1 }, // EFI_IFR_SUBTITLE_OP | |
| { sizeof (EFI_IFR_TEXT), 0 }, // EFI_IFR_TEXT_OP | |
| { sizeof (EFI_IFR_IMAGE), 0 }, // EFI_IFR_IMAGE_OP | |
| { sizeof (EFI_IFR_ONE_OF), 1 }, // EFI_IFR_ONE_OF_OP - 0x05 | |
| { sizeof (EFI_IFR_CHECKBOX), 1}, // EFI_IFR_CHECKBOX_OP | |
| { sizeof (EFI_IFR_NUMERIC), 1 }, // EFI_IFR_NUMERIC_OP | |
| { sizeof (EFI_IFR_PASSWORD), 1 }, // EFI_IFR_PASSWORD_OP | |
| { sizeof (EFI_IFR_ONE_OF_OPTION), 0 }, // EFI_IFR_ONE_OF_OPTION_OP | |
| { sizeof (EFI_IFR_SUPPRESS_IF), 1 }, // EFI_IFR_SUPPRESS_IF - 0x0A | |
| { sizeof (EFI_IFR_LOCKED), 0 }, // EFI_IFR_LOCKED_OP | |
| { sizeof (EFI_IFR_ACTION), 1 }, // EFI_IFR_ACTION_OP | |
| { sizeof (EFI_IFR_RESET_BUTTON), 1 }, // EFI_IFR_RESET_BUTTON_OP | |
| { sizeof (EFI_IFR_FORM_SET), 1 }, // EFI_IFR_FORM_SET_OP -0xE | |
| { sizeof (EFI_IFR_REF), 0 }, // EFI_IFR_REF_OP | |
| { sizeof (EFI_IFR_NO_SUBMIT_IF), 1}, // EFI_IFR_NO_SUBMIT_IF_OP -0x10 | |
| { sizeof (EFI_IFR_INCONSISTENT_IF), 1 }, // EFI_IFR_INCONSISTENT_IF_OP | |
| { sizeof (EFI_IFR_EQ_ID_VAL), 0 }, // EFI_IFR_EQ_ID_VAL_OP | |
| { sizeof (EFI_IFR_EQ_ID_ID), 0 }, // EFI_IFR_EQ_ID_ID_OP | |
| { sizeof (EFI_IFR_EQ_ID_VAL_LIST), 0 }, // EFI_IFR_EQ_ID_LIST_OP - 0x14 | |
| { sizeof (EFI_IFR_AND), 0 }, // EFI_IFR_AND_OP | |
| { sizeof (EFI_IFR_OR), 0 }, // EFI_IFR_OR_OP | |
| { sizeof (EFI_IFR_NOT), 0 }, // EFI_IFR_NOT_OP | |
| { sizeof (EFI_IFR_RULE), 1 }, // EFI_IFR_RULE_OP | |
| { sizeof (EFI_IFR_GRAY_OUT_IF), 1 }, // EFI_IFR_GRAYOUT_IF_OP - 0x19 | |
| { sizeof (EFI_IFR_DATE), 1 }, // EFI_IFR_DATE_OP | |
| { sizeof (EFI_IFR_TIME), 1 }, // EFI_IFR_TIME_OP | |
| { sizeof (EFI_IFR_STRING), 1 }, // EFI_IFR_STRING_OP | |
| { sizeof (EFI_IFR_REFRESH), 0 }, // EFI_IFR_REFRESH_OP | |
| { sizeof (EFI_IFR_DISABLE_IF), 1 }, // EFI_IFR_DISABLE_IF_OP - 0x1E | |
| { 0, 0 }, // 0x1F | |
| { sizeof (EFI_IFR_TO_LOWER), 0 }, // EFI_IFR_TO_LOWER_OP - 0x20 | |
| { sizeof (EFI_IFR_TO_UPPER), 0 }, // EFI_IFR_TO_UPPER_OP - 0x21 | |
| { sizeof (EFI_IFR_MAP), 1 }, // EFI_IFR_MAP - 0x22 | |
| { sizeof (EFI_IFR_ORDERED_LIST), 1 }, // EFI_IFR_ORDERED_LIST_OP - 0x23 | |
| { sizeof (EFI_IFR_VARSTORE), 0 }, // EFI_IFR_VARSTORE_OP | |
| { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP | |
| { sizeof (EFI_IFR_VARSTORE_EFI), 0 }, // EFI_IFR_VARSTORE_EFI_OP | |
| { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 }, // EFI_IFR_VARSTORE_DEVICE_OP | |
| { sizeof (EFI_IFR_VERSION), 0 }, // EFI_IFR_VERSION_OP - 0x28 | |
| { sizeof (EFI_IFR_END), 0 }, // EFI_IFR_END_OP | |
| { sizeof (EFI_IFR_MATCH), 0 }, // EFI_IFR_MATCH_OP - 0x2A | |
| { sizeof (EFI_IFR_GET), 0 }, // EFI_IFR_GET - 0x2B | |
| { sizeof (EFI_IFR_SET), 0 }, // EFI_IFR_SET - 0x2C | |
| { sizeof (EFI_IFR_READ), 0 }, // EFI_IFR_READ - 0x2D | |
| { sizeof (EFI_IFR_WRITE), 0 }, // EFI_IFR_WRITE - 0x2E | |
| { sizeof (EFI_IFR_EQUAL), 0 }, // EFI_IFR_EQUAL_OP - 0x2F | |
| { sizeof (EFI_IFR_NOT_EQUAL), 0 }, // EFI_IFR_NOT_EQUAL_OP | |
| { sizeof (EFI_IFR_GREATER_THAN), 0 }, // EFI_IFR_GREATER_THAN_OP | |
| { sizeof (EFI_IFR_GREATER_EQUAL), 0 }, // EFI_IFR_GREATER_EQUAL_OP | |
| { sizeof (EFI_IFR_LESS_THAN), 0 }, // EFI_IFR_LESS_THAN_OP | |
| { sizeof (EFI_IFR_LESS_EQUAL), 0 }, // EFI_IFR_LESS_EQUAL_OP - 0x34 | |
| { sizeof (EFI_IFR_BITWISE_AND), 0 }, // EFI_IFR_BITWISE_AND_OP | |
| { sizeof (EFI_IFR_BITWISE_OR), 0 }, // EFI_IFR_BITWISE_OR_OP | |
| { sizeof (EFI_IFR_BITWISE_NOT), 0 }, // EFI_IFR_BITWISE_NOT_OP | |
| { sizeof (EFI_IFR_SHIFT_LEFT), 0 }, // EFI_IFR_SHIFT_LEFT_OP | |
| { sizeof (EFI_IFR_SHIFT_RIGHT), 0 }, // EFI_IFR_SHIFT_RIGHT_OP | |
| { sizeof (EFI_IFR_ADD), 0 }, // EFI_IFR_ADD_OP - 0x3A | |
| { sizeof (EFI_IFR_SUBTRACT), 0 }, // EFI_IFR_SUBTRACT_OP | |
| { sizeof (EFI_IFR_MULTIPLY), 0 }, // EFI_IFR_MULTIPLY_OP | |
| { sizeof (EFI_IFR_DIVIDE), 0 }, // EFI_IFR_DIVIDE_OP | |
| { sizeof (EFI_IFR_MODULO), 0 }, // EFI_IFR_MODULO_OP - 0x3E | |
| { sizeof (EFI_IFR_RULE_REF), 0 }, // EFI_IFR_RULE_REF_OP | |
| { sizeof (EFI_IFR_QUESTION_REF1), 0 }, // EFI_IFR_QUESTION_REF1_OP | |
| { sizeof (EFI_IFR_QUESTION_REF2), 0 }, // EFI_IFR_QUESTION_REF2_OP - 0x41 | |
| { sizeof (EFI_IFR_UINT8), 0}, // EFI_IFR_UINT8 | |
| { sizeof (EFI_IFR_UINT16), 0}, // EFI_IFR_UINT16 | |
| { sizeof (EFI_IFR_UINT32), 0}, // EFI_IFR_UINT32 | |
| { sizeof (EFI_IFR_UINT64), 0}, // EFI_IFR_UTNT64 | |
| { sizeof (EFI_IFR_TRUE), 0 }, // EFI_IFR_TRUE_OP - 0x46 | |
| { sizeof (EFI_IFR_FALSE), 0 }, // EFI_IFR_FALSE_OP | |
| { sizeof (EFI_IFR_TO_UINT), 0 }, // EFI_IFR_TO_UINT_OP | |
| { sizeof (EFI_IFR_TO_STRING), 0 }, // EFI_IFR_TO_STRING_OP | |
| { sizeof (EFI_IFR_TO_BOOLEAN), 0 }, // EFI_IFR_TO_BOOLEAN_OP | |
| { sizeof (EFI_IFR_MID), 0 }, // EFI_IFR_MID_OP | |
| { sizeof (EFI_IFR_FIND), 0 }, // EFI_IFR_FIND_OP | |
| { sizeof (EFI_IFR_TOKEN), 0 }, // EFI_IFR_TOKEN_OP | |
| { sizeof (EFI_IFR_STRING_REF1), 0 }, // EFI_IFR_STRING_REF1_OP - 0x4E | |
| { sizeof (EFI_IFR_STRING_REF2), 0 }, // EFI_IFR_STRING_REF2_OP | |
| { sizeof (EFI_IFR_CONDITIONAL), 0 }, // EFI_IFR_CONDITIONAL_OP | |
| { sizeof (EFI_IFR_QUESTION_REF3), 0 }, // EFI_IFR_QUESTION_REF3_OP | |
| { sizeof (EFI_IFR_ZERO), 0 }, // EFI_IFR_ZERO_OP | |
| { sizeof (EFI_IFR_ONE), 0 }, // EFI_IFR_ONE_OP | |
| { sizeof (EFI_IFR_ONES), 0 }, // EFI_IFR_ONES_OP | |
| { sizeof (EFI_IFR_UNDEFINED), 0 }, // EFI_IFR_UNDEFINED_OP | |
| { sizeof (EFI_IFR_LENGTH), 0 }, // EFI_IFR_LENGTH_OP | |
| { sizeof (EFI_IFR_DUP), 0 }, // EFI_IFR_DUP_OP - 0x57 | |
| { sizeof (EFI_IFR_THIS), 0 }, // EFI_IFR_THIS_OP | |
| { sizeof (EFI_IFR_SPAN), 0 }, // EFI_IFR_SPAN_OP | |
| { sizeof (EFI_IFR_VALUE), 1 }, // EFI_IFR_VALUE_OP | |
| { sizeof (EFI_IFR_DEFAULT), 0 }, // EFI_IFR_DEFAULT_OP | |
| { sizeof (EFI_IFR_DEFAULTSTORE), 0 }, // EFI_IFR_DEFAULTSTORE_OP - 0x5C | |
| { sizeof (EFI_IFR_FORM_MAP), 1}, // EFI_IFR_FORM_MAP_OP - 0x5D | |
| { sizeof (EFI_IFR_CATENATE), 0 }, // EFI_IFR_CATENATE_OP | |
| { sizeof (EFI_IFR_GUID), 0 }, // EFI_IFR_GUID_OP | |
| { sizeof (EFI_IFR_SECURITY), 0 }, // EFI_IFR_SECURITY_OP - 0x60 | |
| { sizeof (EFI_IFR_MODAL), 0}, // EFI_IFR_MODAL_OP - 0x61 | |
| { sizeof (EFI_IFR_REFRESH_ID), 0}, // EFI_IFR_REFRESH_ID_OP - 0x62 | |
| }; | |
| #ifdef CIFROBJ_DEUBG | |
| static struct { | |
| CHAR8 *mIfrName; | |
| } gIfrObjPrintDebugTable[] = { | |
| "EFI_IFR_INVALID", "EFI_IFR_FORM", "EFI_IFR_SUBTITLE", "EFI_IFR_TEXT", "EFI_IFR_IMAGE", "EFI_IFR_ONE_OF", | |
| "EFI_IFR_CHECKBOX", "EFI_IFR_NUMERIC", "EFI_IFR_PASSWORD", "EFI_IFR_ONE_OF_OPTION", "EFI_IFR_SUPPRESS_IF", "EFI_IFR_LOCKED", | |
| "EFI_IFR_ACTION", "EFI_IFR_RESET_BUTTON", "EFI_IFR_FORM_SET", "EFI_IFR_REF", "EFI_IFR_NO_SUBMIT_IF", "EFI_IFR_INCONSISTENT_IF", | |
| "EFI_IFR_EQ_ID_VAL", "EFI_IFR_EQ_ID_ID", "EFI_IFR_EQ_ID_LIST", "EFI_IFR_AND", "EFI_IFR_OR", "EFI_IFR_NOT", | |
| "EFI_IFR_RULE", "EFI_IFR_GRAY_OUT_IF", "EFI_IFR_DATE", "EFI_IFR_TIME", "EFI_IFR_STRING", "EFI_IFR_REFRESH", | |
| "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID", "EFI_IFR_TO_LOWER", "EFI_IFR_TO_UPPER", "EFI_IFR_MAP", "EFI_IFR_ORDERED_LIST", | |
| "EFI_IFR_VARSTORE", "EFI_IFR_VARSTORE_NAME_VALUE", "EFI_IFR_VARSTORE_EFI", "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION", "EFI_IFR_END", | |
| "EFI_IFR_MATCH", "EFI_IFR_GET", "EFI_IFR_SET", "EFI_IFR_READ", "EFI_IFR_WRITE", "EFI_IFR_EQUAL", | |
| "EFI_IFR_NOT_EQUAL", "EFI_IFR_GREATER_THAN", "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN", "EFI_IFR_LESS_EQUAL", "EFI_IFR_BITWISE_AND", | |
| "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT", "EFI_IFR_SHIFT_LEFT", "EFI_IFR_SHIFT_RIGHT", "EFI_IFR_ADD", "EFI_IFR_SUBTRACT", | |
| "EFI_IFR_MULTIPLY", "EFI_IFR_DIVIDE", "EFI_IFR_MODULO", "EFI_IFR_RULE_REF", "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2", | |
| "EFI_IFR_UINT8", "EFI_IFR_UINT16", "EFI_IFR_UINT32", "EFI_IFR_UINT64", "EFI_IFR_TRUE", "EFI_IFR_FALSE", | |
| "EFI_IFR_TO_UINT", "EFI_IFR_TO_STRING", "EFI_IFR_TO_BOOLEAN", "EFI_IFR_MID", "EFI_IFR_FIND", "EFI_IFR_TOKEN", | |
| "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2", "EFI_IFR_CONDITIONAL", "EFI_IFR_QUESTION_REF3", "EFI_IFR_ZERO", "EFI_IFR_ONE", | |
| "EFI_IFR_ONES", "EFI_IFR_UNDEFINED", "EFI_IFR_LENGTH", "EFI_IFR_DUP", "EFI_IFR_THIS", "EFI_IFR_SPAN", | |
| "EFI_IFR_VALUE", "EFI_IFR_DEFAULT", "EFI_IFR_DEFAULTSTORE", "EFI_IFR_FORM_MAP", "EFI_IFR_CATENATE", "EFI_IFR_GUID", | |
| "EFI_IFR_SECURITY", "EFI_IFR_MODAL", "EFI_IFR_REFRESH_ID", | |
| }; | |
| VOID | |
| CIFROBJ_DEBUG_PRINT ( | |
| IN UINT8 OpCode | |
| ) | |
| { | |
| printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName); | |
| } | |
| #else | |
| #define CIFROBJ_DEBUG_PRINT(OpCode) | |
| #endif | |
| BOOLEAN gCreateOp = TRUE; | |
| CIfrObj::CIfrObj ( | |
| IN UINT8 OpCode, | |
| OUT CHAR8 **IfrObj, | |
| IN UINT8 ObjBinLen, | |
| IN BOOLEAN DelayEmit | |
| ) | |
| { | |
| mDelayEmit = DelayEmit; | |
| mPkgOffset = gCFormPkg.GetPkgLength (); | |
| mObjBinLen = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen; | |
| mObjBinBuf = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH]; | |
| mRecordIdx = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD; | |
| if (IfrObj != NULL) { | |
| *IfrObj = mObjBinBuf; | |
| } | |
| CIFROBJ_DEBUG_PRINT (OpCode); | |
| } | |
| CIfrObj::~CIfrObj ( | |
| VOID | |
| ) | |
| { | |
| if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) { | |
| _EMIT_PENDING_OBJ (); | |
| } | |
| gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset); | |
| } | |
| /* | |
| * The definition of CIfrObj's member function | |
| */ | |
| UINT8 gScopeCount = 0; | |
| CIfrOpHeader::CIfrOpHeader ( | |
| IN UINT8 OpCode, | |
| IN VOID *StartAddr, | |
| IN UINT8 Length | |
| ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr) | |
| { | |
| mHeader->OpCode = OpCode; | |
| mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length; | |
| mHeader->Scope = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0; | |
| } | |
| CIfrOpHeader::CIfrOpHeader ( | |
| IN CIfrOpHeader &OpHdr | |
| ) | |
| { | |
| mHeader = OpHdr.mHeader; | |
| } | |
| UINT32 CIfrFormId::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, }; |