/** @file | |
The definition of CFormPkg's member function | |
Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "stdio.h" | |
#include "assert.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 | |
) | |
{ | |
memmove (mAddr, Addr, (mLen < Len ? mLen : Len)); | |
mFlag = ASSIGNED; | |
} | |
CHAR8 * | |
SPendingAssign::GetKey ( | |
VOID | |
) | |
{ | |
return mKey; | |
} | |
CFormPkg::CFormPkg ( | |
IN UINT32 BufferSize | |
) | |
{ | |
CHAR8 *BufferStart; | |
CHAR8 *BufferEnd; | |
SBufferNode *Node; | |
mPkgLength = 0; | |
mBufferSize = 0; | |
mBufferNodeQueueHead = NULL; | |
mBufferNodeQueueTail = NULL; | |
mCurrBufferNode = NULL; | |
mReadBufferNode = NULL; | |
mReadBufferOffset = 0; | |
PendingAssignList = NULL; | |
Node = new SBufferNode; | |
if (Node == NULL) { | |
return ; | |
} | |
BufferStart = new CHAR8[BufferSize]; | |
if (BufferStart == NULL) { | |
delete Node; | |
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; | |
} | |
SBufferNode * | |
CFormPkg::CreateNewNode ( | |
VOID | |
) | |
{ | |
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; | |
} | |
return Node; | |
} | |
CHAR8 * | |
CFormPkg::IfrBinBufferGet ( | |
IN UINT32 Len | |
) | |
{ | |
CHAR8 *BinBuffer = NULL; | |
SBufferNode *Node = NULL; | |
if ((Len == 0) || (Len > mBufferSize)) { | |
return NULL; | |
} | |
if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) { | |
BinBuffer = mCurrBufferNode->mBufferFree; | |
mCurrBufferNode->mBufferFree += Len; | |
} else { | |
Node = CreateNewNode (); | |
if (Node == NULL) { | |
return 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; | |
Index --; | |
} | |
} | |
} | |
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 | |
UINT32 gAdjustOpcodeOffset = 0; | |
BOOLEAN gNeedAdjustOpcode = FALSE; | |
UINT32 gAdjustOpcodeLen = 0; | |
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; | |
} | |
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); | |
} | |
} | |
} | |
SBufferNode * | |
CFormPkg::GetBinBufferNodeForAddr ( | |
IN CHAR8 *BinBuffAddr | |
) | |
{ | |
SBufferNode *TmpNode; | |
TmpNode = mBufferNodeQueueHead; | |
while (TmpNode != NULL) { | |
if (TmpNode->mBufferStart <= BinBuffAddr && TmpNode->mBufferFree >= BinBuffAddr) { | |
return TmpNode; | |
} | |
TmpNode = TmpNode->mNext; | |
} | |
return NULL; | |
} | |
SBufferNode * | |
CFormPkg::GetNodeBefore( | |
IN SBufferNode *CurrentNode | |
) | |
{ | |
SBufferNode *FirstNode = mBufferNodeQueueHead; | |
SBufferNode *LastNode = mBufferNodeQueueHead; | |
while (FirstNode != NULL) { | |
if (FirstNode == CurrentNode) { | |
break; | |
} | |
LastNode = FirstNode; | |
FirstNode = FirstNode->mNext; | |
} | |
if (FirstNode == NULL) { | |
LastNode = NULL; | |
} | |
return LastNode; | |
} | |
EFI_VFR_RETURN_CODE | |
CFormPkg::InsertNodeBefore( | |
IN SBufferNode *CurrentNode, | |
IN SBufferNode *NewNode | |
) | |
{ | |
SBufferNode *LastNode = GetNodeBefore (CurrentNode); | |
if (LastNode == NULL) { | |
return VFR_RETURN_MISMATCHED; | |
} | |
NewNode->mNext = LastNode->mNext; | |
LastNode->mNext = NewNode; | |
return VFR_RETURN_SUCCESS; | |
} | |
CHAR8 * | |
CFormPkg::GetBufAddrBaseOnOffset ( | |
IN UINT32 Offset | |
) | |
{ | |
SBufferNode *TmpNode; | |
UINT32 TotalBufLen; | |
UINT32 CurrentBufLen; | |
TotalBufLen = 0; | |
for (TmpNode = mBufferNodeQueueHead; TmpNode != NULL; TmpNode = TmpNode->mNext) { | |
CurrentBufLen = TmpNode->mBufferFree - TmpNode->mBufferStart; | |
if (Offset >= TotalBufLen && Offset < TotalBufLen + CurrentBufLen) { | |
return TmpNode->mBufferStart + (Offset - TotalBufLen); | |
} | |
TotalBufLen += CurrentBufLen; | |
} | |
return NULL; | |
} | |
EFI_VFR_RETURN_CODE | |
CFormPkg::AdjustDynamicInsertOpcode ( | |
IN CHAR8 *InserPositionAddr, | |
IN CHAR8 *InsertOpcodeAddr, | |
IN BOOLEAN CreateOpcodeAfterParsingVfr | |
) | |
{ | |
SBufferNode *InserPositionNode; | |
SBufferNode *InsertOpcodeNode; | |
SBufferNode *NewRestoreNodeBegin; | |
SBufferNode *NewRestoreNodeEnd; | |
SBufferNode *NewLastEndNode; | |
SBufferNode *TmpNode; | |
UINT32 NeedRestoreCodeLen; | |
NewRestoreNodeEnd = NULL; | |
InserPositionNode = GetBinBufferNodeForAddr(InserPositionAddr); | |
InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr); | |
assert (InserPositionNode != NULL); | |
assert (InsertOpcodeNode != NULL); | |
if (InserPositionNode == InsertOpcodeNode) { | |
// | |
// Create New Node to save the restore opcode. | |
// | |
NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr; | |
gAdjustOpcodeLen = NeedRestoreCodeLen; | |
NewRestoreNodeBegin = CreateNewNode (); | |
if (NewRestoreNodeBegin == NULL) { | |
return VFR_RETURN_OUT_FOR_RESOURCES; | |
} | |
memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen); | |
NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen; | |
// | |
// Override the restore buffer data. | |
// | |
memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr); | |
InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen; | |
memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen); | |
} else { | |
// | |
// Create New Node to save the restore opcode. | |
// | |
NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr; | |
gAdjustOpcodeLen = NeedRestoreCodeLen; | |
NewRestoreNodeBegin = CreateNewNode (); | |
if (NewRestoreNodeBegin == NULL) { | |
return VFR_RETURN_OUT_FOR_RESOURCES; | |
} | |
memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen); | |
NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen; | |
// | |
// Override the restore buffer data. | |
// | |
InserPositionNode->mBufferFree -= NeedRestoreCodeLen; | |
// | |
// Link the restore data to new node. | |
// | |
NewRestoreNodeBegin->mNext = InserPositionNode->mNext; | |
// | |
// Count the Adjust opcode len. | |
// | |
TmpNode = InserPositionNode->mNext; | |
while (TmpNode != InsertOpcodeNode) { | |
gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart; | |
TmpNode = TmpNode->mNext; | |
} | |
// | |
// Create New Node to save the last node of restore opcode. | |
// | |
NeedRestoreCodeLen = InsertOpcodeAddr - InsertOpcodeNode->mBufferStart; | |
gAdjustOpcodeLen += NeedRestoreCodeLen; | |
if (NeedRestoreCodeLen > 0) { | |
NewRestoreNodeEnd = CreateNewNode (); | |
if (NewRestoreNodeEnd == NULL) { | |
return VFR_RETURN_OUT_FOR_RESOURCES; | |
} | |
memcpy (NewRestoreNodeEnd->mBufferFree, InsertOpcodeNode->mBufferStart, NeedRestoreCodeLen); | |
NewRestoreNodeEnd->mBufferFree += NeedRestoreCodeLen; | |
// | |
// Override the restore buffer data. | |
// | |
memmove (InsertOpcodeNode->mBufferStart, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr); | |
InsertOpcodeNode->mBufferFree -= InsertOpcodeAddr - InsertOpcodeNode->mBufferStart; | |
// | |
// Insert the last restore data node. | |
// | |
TmpNode = GetNodeBefore (InsertOpcodeNode); | |
assert (TmpNode != NULL); | |
if (TmpNode == InserPositionNode) { | |
NewRestoreNodeBegin->mNext = NewRestoreNodeEnd; | |
} else { | |
TmpNode->mNext = NewRestoreNodeEnd; | |
} | |
// | |
// Connect the dynamic opcode node to the node after InserPositionNode. | |
// | |
InserPositionNode->mNext = InsertOpcodeNode; | |
} | |
} | |
if (CreateOpcodeAfterParsingVfr) { | |
// | |
// Th new opcodes were created after Parsing Vfr file, | |
// so the content in mBufferNodeQueueTail must be the new created opcodes. | |
// So connet the NewRestoreNodeBegin to the tail and update the tail node. | |
// | |
mBufferNodeQueueTail->mNext = NewRestoreNodeBegin; | |
if (NewRestoreNodeEnd != NULL) { | |
mBufferNodeQueueTail = NewRestoreNodeEnd; | |
} else { | |
mBufferNodeQueueTail = NewRestoreNodeBegin; | |
} | |
} else { | |
if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) { | |
// | |
// End form set opcode all in the mBufferNodeQueueTail node. | |
// | |
NewLastEndNode = CreateNewNode (); | |
if (NewLastEndNode == NULL) { | |
return VFR_RETURN_OUT_FOR_RESOURCES; | |
} | |
NewLastEndNode->mBufferStart[0] = 0x29; | |
NewLastEndNode->mBufferStart[1] = 0x02; | |
NewLastEndNode->mBufferFree += 2; | |
mBufferNodeQueueTail->mBufferFree -= 2; | |
mBufferNodeQueueTail->mNext = NewRestoreNodeBegin; | |
if (NewRestoreNodeEnd != NULL) { | |
NewRestoreNodeEnd->mNext = NewLastEndNode; | |
} else { | |
NewRestoreNodeBegin->mNext = NewLastEndNode; | |
} | |
mBufferNodeQueueTail = NewLastEndNode; | |
} else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) { | |
TmpNode = GetNodeBefore(mBufferNodeQueueTail); | |
assert (TmpNode != NULL); | |
TmpNode->mNext = NewRestoreNodeBegin; | |
if (NewRestoreNodeEnd != NULL) { | |
NewRestoreNodeEnd->mNext = mBufferNodeQueueTail; | |
} else { | |
NewRestoreNodeBegin->mNext = mBufferNodeQueueTail; | |
} | |
} | |
} | |
mCurrBufferNode = mBufferNodeQueueTail; | |
return VFR_RETURN_SUCCESS; | |
} | |
EFI_VFR_RETURN_CODE | |
CFormPkg::DeclarePendingQuestion ( | |
IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB, | |
IN CVfrDataStorage &lCVfrDataStorage, | |
IN CVfrQuestionDB &lCVfrQuestionDB, | |
IN EFI_GUID *LocalFormSetGuid, | |
IN UINT32 LineNo, | |
OUT CHAR8 **InsertOpcodeAddr | |
) | |
{ | |
SPendingAssign *pNode; | |
CHAR8 *VarStr; | |
UINT32 ArrayIdx; | |
CHAR8 FName[MAX_NAME_LEN]; | |
CHAR8 *SName; | |
CHAR8 *NewStr; | |
UINT32 ShrinkSize = 0; | |
EFI_VFR_RETURN_CODE ReturnCode; | |
EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; | |
UINT8 LFlags; | |
UINT32 MaxValue; | |
CIfrGuid *GuidObj = NULL; | |
// | |
// Declare all questions as Numeric in DisableIf True | |
// | |
// DisableIf | |
CIfrDisableIf DIObj; | |
DIObj.SetLineNo (LineNo); | |
*InsertOpcodeAddr = DIObj.GetObjBinAddr<CHAR8>(); | |
//TrueOpcode | |
CIfrTrue TObj (LineNo); | |
// Declare Numeric qeustion for each undefined question. | |
for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { | |
if (pNode->mFlag == PENDING) { | |
EFI_VARSTORE_INFO Info; | |
EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; | |
// | |
// 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.GetVarStoreId (FName, &Info.mVarStoreId); | |
if (ReturnCode != VFR_RETURN_SUCCESS) { | |
gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined"); | |
return ReturnCode; | |
} | |
VarStoreType = lCVfrDataStorage.GetVarStoreType (Info.mVarStoreId); | |
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 || VarStoreType == EFI_VFR_VARSTORE_BUFFER_BITS) { | |
VarStr = pNode->mKey; | |
//convert VarStr with store name to VarStr with structure name | |
ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (Info.mVarStoreId, &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, Info.mIsBitVar); | |
delete[] NewStr; | |
} | |
} else { | |
ReturnCode = VFR_RETURN_UNSUPPORTED; | |
} | |
} | |
if (ReturnCode != VFR_RETURN_SUCCESS) { | |
gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); | |
return ReturnCode; | |
} | |
// | |
// If the storage is bit fields, create Guid opcode to wrap the numeric opcode. | |
// | |
if (Info.mIsBitVar) { | |
GuidObj = new CIfrGuid(0); | |
GuidObj->SetGuid (&gEdkiiIfrBitVarGuid); | |
GuidObj->SetLineNo(LineNo); | |
} | |
CIfrNumeric CNObj; | |
CNObj.SetLineNo (LineNo); | |
CNObj.SetPrompt (0x0); | |
CNObj.SetHelp (0x0); | |
CNObj.SetQuestionId (QId); | |
CNObj.SetVarStoreInfo (&Info); | |
// | |
// Set Min/Max/Step Data and flags for the question with bit fields.Min/Max/Step Data are saved as UINT32 type for bit question. | |
// | |
if (Info.mIsBitVar) { | |
MaxValue = (1 << Info.mVarTotalSize) -1; | |
CNObj.SetMinMaxStepData ((UINT32) 0, MaxValue, (UINT32) 0); | |
ShrinkSize = 12; | |
LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & Info.mVarTotalSize); | |
CNObj.SetFlagsForBitField (0, LFlags); | |
} else { | |
// | |
// 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 valid value for the undefined question. | |
// | |
switch (Info.mVarType) { | |
case EFI_IFR_TYPE_NUM_SIZE_64: | |
CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0); | |
ShrinkSize = 0; | |
break; | |
case EFI_IFR_TYPE_NUM_SIZE_32: | |
CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0); | |
ShrinkSize = 12; | |
break; | |
case EFI_IFR_TYPE_NUM_SIZE_16: | |
CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0); | |
ShrinkSize = 18; | |
break; | |
case EFI_IFR_TYPE_NUM_SIZE_8: | |
CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0); | |
ShrinkSize = 21; | |
break; | |
default: | |
break; | |
} | |
} | |
CNObj.ShrinkBinSize (ShrinkSize); | |
// | |
// For undefined Efi VarStore type question | |
// Append the extended guided opcode to contain VarName | |
// | |
if (VarStoreType == EFI_VFR_VARSTORE_EFI) { | |
CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName); | |
CVNObj.SetLineNo (LineNo); | |
} | |
// | |
// End for Numeric | |
// | |
CIfrEnd CEObj; | |
CEObj.SetLineNo (LineNo); | |
// | |
// End for Guided opcode | |
// | |
if (GuidObj != NULL) { | |
CIfrEnd CEObjGuid; | |
CEObjGuid.SetLineNo (LineNo); | |
GuidObj->SetScope(1); | |
delete GuidObj; | |
GuidObj = NULL; | |
} | |
} | |
} | |
// | |
// 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; | |
mAllDefaultTypeCount = 0; | |
for (UINT8 i = 0; i < EFI_HII_MAX_SUPPORT_DEFAULT_TYPE; i++) { | |
mAllDefaultIdArray[i] = 0xffff; | |
} | |
} | |
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: | |
case EFI_IFR_REF_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_VAL_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; | |
} | |
SIfrRecord * | |
CIfrRecordInfoDB::GetRecordInfoFromOffset ( | |
IN UINT32 Offset | |
) | |
{ | |
SIfrRecord *pNode = NULL; | |
for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { | |
if (pNode->mOffset == Offset) { | |
return pNode; | |
} | |
} | |
return pNode; | |
} | |
/** | |
Add just the op code position. | |
Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode, | |
so pDynamicOpcodeNodes is before mIfrRecordListTail. | |
From | |
|mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail| | |
To | |
|mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail| | |
Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file, | |
so new records are appennded to the end of OriginalIfrRecordListTail. | |
From | |
|mIfrRecordListHead + ...+ pAdjustNode + ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes| | |
To | |
|mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + ... + OriginalIfrRecordListTail| | |
@param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file. | |
**/ | |
BOOLEAN | |
CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords ( | |
IN BOOLEAN CreateOpcodeAfterParsingVfr | |
) | |
{ | |
UINT32 OpcodeOffset; | |
SIfrRecord *pNode, *pPreNode; | |
SIfrRecord *pAdjustNode, *pNodeBeforeAdjust; | |
SIfrRecord *pNodeBeforeDynamic; | |
pPreNode = NULL; | |
pAdjustNode = NULL; | |
pNodeBeforeDynamic = NULL; | |
OpcodeOffset = 0; | |
// | |
// Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode, | |
// and the node before pDynamicOpcodeNode. | |
// | |
for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) { | |
if (OpcodeOffset == gAdjustOpcodeOffset) { | |
pAdjustNode = pNode; | |
pNodeBeforeAdjust = pPreNode; | |
} else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) { | |
pNodeBeforeDynamic = pPreNode; | |
} | |
if (pNode->mNext != NULL) { | |
pPreNode = pNode; | |
} | |
OpcodeOffset += pNode->mBinBufLen; | |
} | |
// | |
// Check the nodes whether exist. | |
// | |
if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL || pNodeBeforeAdjust == NULL) { | |
return FALSE; | |
} | |
// | |
// Adjust the node. pPreNode save the Node before mIfrRecordListTail | |
// | |
pNodeBeforeAdjust->mNext = pNodeBeforeDynamic->mNext; | |
if (CreateOpcodeAfterParsingVfr) { | |
// | |
// mIfrRecordListTail is the end of pDynamicNode (Case2). | |
// | |
mIfrRecordListTail->mNext = pAdjustNode; | |
mIfrRecordListTail = pNodeBeforeDynamic; | |
mIfrRecordListTail->mNext = NULL; | |
} else { | |
// | |
//pPreNode is the end of pDynamicNode(Case1). | |
// | |
pPreNode->mNext = pAdjustNode; | |
pNodeBeforeDynamic->mNext = mIfrRecordListTail; | |
} | |
return TRUE; | |
} | |
/** | |
Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record. | |
@param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file. | |
**/ | |
VOID | |
CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode ( | |
IN BOOLEAN CreateOpcodeAfterParsingVfr | |
) | |
{ | |
SIfrRecord *pRecord; | |
// | |
// Base on the original offset info to update the record list. | |
// | |
if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr)) { | |
gCVfrErrorHandle.PrintMsg (0, (CHAR8 *)"Error", (CHAR8 *)"Can not find the adjust offset in the record."); | |
} | |
// | |
// Base on the opcode binary length to recalculate the offset for each opcode. | |
// | |
IfrAdjustOffsetForRecord(); | |
// | |
// Base on the offset to find the binary address. | |
// | |
pRecord = GetRecordInfoFromOffset(gAdjustOpcodeOffset); | |
while (pRecord != NULL) { | |
pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset); | |
pRecord = pRecord->mNext; | |
} | |
} | |
VOID | |
CIfrRecordInfoDB::IfrAdjustOffsetForRecord ( | |
VOID | |
) | |
{ | |
UINT32 OpcodeOffset; | |
SIfrRecord *pNode; | |
OpcodeOffset = 0; | |
for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { | |
pNode->mOffset = OpcodeOffset; | |
OpcodeOffset += pNode->mBinBufLen; | |
} | |
} | |
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; | |
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 Inconsistent 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) { | |
IfrAdjustOffsetForRecord (); | |
} | |
return Status; | |
} | |
/** | |
When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not | |
given by expression, should save the default info for the Buffer VarStore. | |
@param DefaultId The default id. | |
@param pQuestionNode Point to the question opcode node. | |
@param Value The default value. | |
**/ | |
VOID | |
CIfrRecordInfoDB::IfrAddDefaultToBufferConfig ( | |
IN UINT16 DefaultId, | |
IN SIfrRecord *pQuestionNode, | |
IN EFI_IFR_TYPE_VALUE Value | |
) | |
{ | |
CHAR8 *VarStoreName = NULL; | |
EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; | |
EFI_GUID *VarGuid = NULL; | |
EFI_VARSTORE_INFO VarInfo; | |
EFI_IFR_QUESTION_HEADER *QuestionHead; | |
EFI_IFR_OP_HEADER *pQuestionOpHead; | |
pQuestionOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf; | |
QuestionHead = (EFI_IFR_QUESTION_HEADER *) (pQuestionOpHead + 1); | |
// | |
// Get the Var Store name and type. | |
// | |
gCVfrDataStorage.GetVarStoreName (QuestionHead->VarStoreId, &VarStoreName); | |
VarGuid= gCVfrDataStorage.GetVarStoreGuid (QuestionHead->VarStoreId); | |
VarStoreType = gCVfrDataStorage.GetVarStoreType (QuestionHead->VarStoreId); | |
// | |
// Only for Buffer storage need to save the default info in the storage. | |
// Other type storage, just return. | |
// | |
if (VarStoreType != EFI_VFR_VARSTORE_BUFFER) { | |
return; | |
} else { | |
VarInfo.mInfo.mVarOffset = QuestionHead->VarStoreInfo.VarOffset; | |
VarInfo.mVarStoreId = QuestionHead->VarStoreId; | |
} | |
// | |
// Get the buffer storage info about this question. | |
// | |
gCVfrDataStorage.GetBufferVarStoreFieldInfo (&VarInfo); | |
// | |
// Add action. | |
// | |
gCVfrDefaultStore.BufferVarStoreAltConfigAdd ( | |
DefaultId, | |
VarInfo, | |
VarStoreName, | |
VarGuid, | |
VarInfo.mVarType, | |
Value | |
); | |
} | |
/** | |
Record the number and default id of all defaultstore opcode. | |
**/ | |
VOID | |
CIfrRecordInfoDB::IfrGetDefaultStoreInfo ( | |
VOID | |
) | |
{ | |
SIfrRecord *pNode; | |
EFI_IFR_OP_HEADER *pOpHead; | |
EFI_IFR_DEFAULTSTORE *DefaultStore; | |
pNode = mIfrRecordListHead; | |
mAllDefaultTypeCount = 0; | |
while (pNode != NULL) { | |
pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf; | |
if (pOpHead->OpCode == EFI_IFR_DEFAULTSTORE_OP){ | |
DefaultStore = (EFI_IFR_DEFAULTSTORE *) pNode->mIfrBinBuf; | |
mAllDefaultIdArray[mAllDefaultTypeCount++] = DefaultStore->DefaultId; | |
} | |
pNode = pNode->mNext; | |
} | |
} | |
/** | |
Create new default opcode record. | |
@param Size The new default opcode size. | |
@param DefaultId The new default id. | |
@param Type The new default type. | |
@param LineNo The line number of the new record. | |
@param Value The new default value. | |
**/ | |
VOID | |
CIfrRecordInfoDB::IfrCreateDefaultRecord( | |
IN UINT8 Size, | |
IN UINT16 DefaultId, | |
IN UINT8 Type, | |
IN UINT32 LineNo, | |
IN EFI_IFR_TYPE_VALUE Value | |
) | |
{ | |
CIfrDefault *DObj; | |
CIfrDefault2 *DObj2; | |
DObj = NULL; | |
DObj2 = NULL; | |
if (Type == EFI_IFR_TYPE_OTHER) { | |
DObj2 = new CIfrDefault2 (Size); | |
DObj2->SetDefaultId(DefaultId); | |
DObj2->SetType(Type); | |
DObj2->SetLineNo(LineNo); | |
DObj2->SetScope (1); | |
delete DObj2; | |
} else { | |
DObj = new CIfrDefault (Size); | |
DObj->SetDefaultId(DefaultId); | |
DObj->SetType(Type); | |
DObj->SetLineNo(LineNo); | |
DObj->SetValue (Value); | |
delete DObj; | |
} | |
} | |
/** | |
Create new default opcode for question base on the QuestionDefaultInfo. | |
@param pQuestionNode Point to the question opcode Node. | |
@param QuestionDefaultInfo Point to the QuestionDefaultInfo for current question. | |
**/ | |
VOID | |
CIfrRecordInfoDB::IfrCreateDefaultForQuestion ( | |
IN SIfrRecord *pQuestionNode, | |
IN QuestionDefaultRecord *QuestionDefaultInfo | |
) | |
{ | |
EFI_IFR_OP_HEADER *pOpHead; | |
EFI_IFR_DEFAULT *Default; | |
SIfrRecord *pSNode; | |
SIfrRecord *pENode; | |
SIfrRecord *pDefaultNode; | |
CIfrObj *Obj; | |
CHAR8 *ObjBinBuf; | |
UINT8 ScopeCount; | |
UINT8 OpcodeNumber; | |
UINT8 OpcodeCount; | |
UINT8 DefaultSize; | |
EFI_IFR_ONE_OF_OPTION *DefaultOptionOpcode; | |
EFI_IFR_TYPE_VALUE CheckBoxDefaultValue; | |
CheckBoxDefaultValue.b = 1; | |
pOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf; | |
ScopeCount = 0; | |
OpcodeCount = 0; | |
Obj = NULL; | |
// | |
// Record the offset of node which need to be adjust, will move the new created default opcode to this offset. | |
// | |
gAdjustOpcodeOffset = pQuestionNode->mNext->mOffset; | |
// | |
// Case 1: | |
// For oneof, the default with smallest default id is given by the option flag. | |
// So create the missing defaults base on the oneof option value(mDefaultValueRecord). | |
// | |
if (pOpHead->OpCode == EFI_IFR_ONE_OF_OP && !QuestionDefaultInfo->mIsDefaultOpcode) { | |
DefaultOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)QuestionDefaultInfo->mDefaultValueRecord->mIfrBinBuf; | |
DefaultSize = QuestionDefaultInfo->mDefaultValueRecord->mBinBufLen - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value); | |
DefaultSize += OFFSET_OF (EFI_IFR_DEFAULT, Value); | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], DefaultOptionOpcode->Type, pQuestionNode->mLineNo, DefaultOptionOpcode->Value); | |
// | |
// Save the new created default in the buffer storage. | |
// | |
IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, DefaultOptionOpcode->Value); | |
} | |
} | |
return; | |
} | |
// | |
// Case2: | |
// For checkbox, the default with smallest default id is given by the question flag. | |
// And create the missing defaults with true value. | |
// | |
if (pOpHead-> OpCode == EFI_IFR_CHECKBOX_OP && !QuestionDefaultInfo->mIsDefaultOpcode) { | |
DefaultSize = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (BOOLEAN); | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], EFI_IFR_TYPE_BOOLEAN, pQuestionNode->mLineNo, CheckBoxDefaultValue); | |
// | |
// Save the new created default. | |
// | |
IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, CheckBoxDefaultValue); | |
} | |
} | |
return; | |
} | |
// | |
// Case3: | |
// The default with smallest default id is given by the default opcode. | |
// So create the missing defaults base on the value in the default opcode. | |
// | |
// | |
// pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo. | |
// | |
pDefaultNode = QuestionDefaultInfo->mDefaultValueRecord; | |
Default = (EFI_IFR_DEFAULT *)pDefaultNode->mIfrBinBuf; | |
// | |
// Record the offset of node which need to be adjust, will move the new created default opcode to this offset. | |
// | |
gAdjustOpcodeOffset = pDefaultNode->mNext->mOffset; | |
if (Default->Type == EFI_IFR_TYPE_OTHER) { | |
// | |
// EFI_IFR_DEFAULT_2 opcode. | |
// | |
// Point to the first expression opcode. | |
// | |
pSNode = pDefaultNode->mNext; | |
pENode = NULL; | |
ScopeCount++; | |
// | |
// Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2) | |
// | |
while (pSNode != NULL && pSNode->mNext != NULL && ScopeCount != 0) { | |
pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf; | |
if (pOpHead->Scope == 1) { | |
ScopeCount++; | |
} | |
if (pOpHead->OpCode == EFI_IFR_END_OP) { | |
ScopeCount--; | |
} | |
pENode = pSNode; | |
pSNode = pSNode->mNext; | |
OpcodeCount++; | |
} | |
assert (pSNode); | |
assert (pENode); | |
// | |
// Record the offset of node which need to be adjust, will move the new created default opcode to this offset. | |
// | |
gAdjustOpcodeOffset = pSNode->mOffset; | |
// | |
// Create new default opcode node for missing default. | |
// | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
OpcodeNumber = OpcodeCount; | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pENode->mLineNo, Default->Value); | |
// | |
// Point to the first expression opcode node. | |
// | |
pSNode = pDefaultNode->mNext; | |
// | |
// Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode. | |
// | |
while (pSNode != NULL && pSNode->mNext != NULL && OpcodeNumber-- != 0) { | |
pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf; | |
Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE); | |
assert (Obj != NULL); | |
Obj->SetLineNo (pSNode->mLineNo); | |
ObjBinBuf = Obj->GetObjBinAddr<CHAR8>(); | |
memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen); | |
delete Obj; | |
pSNode = pSNode->mNext; | |
} | |
} | |
} | |
} else { | |
// | |
// EFI_IFR_DEFAULT opcode. | |
// | |
// Create new default opcode node for missing default. | |
// | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pDefaultNode->mLineNo, Default->Value); | |
// | |
// Save the new created default in the buffer storage.. | |
// | |
IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, Default->Value); | |
} | |
} | |
} | |
} | |
/** | |
Parse the default information in a question, get the QuestionDefaultInfo. | |
@param pQuestionNode Point to the question record Node. | |
@param QuestionDefaultInfo On return, point to the QuestionDefaultInfo. | |
**/ | |
VOID | |
CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion( | |
IN SIfrRecord *pQuestionNode, | |
OUT QuestionDefaultRecord *QuestionDefaultInfo | |
) | |
{ | |
SIfrRecord *pSNode; | |
EFI_IFR_ONE_OF_OPTION *OneofOptionOpcode; | |
EFI_IFR_OP_HEADER *pSOpHead; | |
EFI_IFR_CHECKBOX *CheckBoxOpcode; | |
EFI_IFR_DEFAULT *DefaultOpcode; | |
BOOLEAN IsOneOfOpcode; | |
UINT16 SmallestDefaultId; | |
UINT8 ScopeCount; | |
SmallestDefaultId = 0xffff; | |
IsOneOfOpcode = FALSE; | |
ScopeCount = 0; | |
pSNode = pQuestionNode; | |
// | |
// Parse all the opcodes in the Question. | |
// | |
while (pSNode != NULL) { | |
pSOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf; | |
// | |
// For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP. | |
// Scopes may be nested within other scopes. | |
// When finishing parsing a question, the scope count must be zero. | |
// | |
if (pSOpHead->Scope == 1) { | |
ScopeCount++; | |
} | |
if (pSOpHead->OpCode == EFI_IFR_END_OP) { | |
ScopeCount--; | |
} | |
// | |
// Check whether finishing parsing a question. | |
// | |
if (ScopeCount == 0) { | |
break; | |
} | |
// | |
// Record the default information in the question. | |
// | |
switch (pSOpHead->OpCode) { | |
case EFI_IFR_ONE_OF_OP: | |
IsOneOfOpcode = TRUE; | |
break; | |
case EFI_IFR_CHECKBOX_OP: | |
// | |
// The default info of check box may be given by flag. | |
// So need to check the flag of check box. | |
// | |
CheckBoxOpcode = (EFI_IFR_CHECKBOX *)pSNode->mIfrBinBuf; | |
if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0) { | |
// | |
// Check whether need to update the smallest default id. | |
// | |
if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) { | |
SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; | |
} | |
// | |
// Update the QuestionDefaultInfo. | |
// | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
QuestionDefaultInfo->mDefaultNumber ++; | |
QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; | |
} | |
break; | |
} | |
} | |
} | |
if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0) { | |
// | |
// Check whether need to update the smallest default id. | |
// | |
if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) { | |
SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING; | |
} | |
// | |
// Update the QuestionDefaultInfo. | |
// | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
QuestionDefaultInfo->mDefaultNumber ++; | |
QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; | |
} | |
break; | |
} | |
} | |
} | |
break; | |
case EFI_IFR_ONE_OF_OPTION_OP: | |
if (!IsOneOfOpcode) { | |
// | |
// Only check the option in oneof. | |
// | |
break; | |
} | |
OneofOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)pSNode->mIfrBinBuf; | |
if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT) != 0) { | |
// | |
// The option is used as the standard default. | |
// Check whether need to update the smallest default id and QuestionDefaultInfo. | |
// | |
if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) { | |
SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; | |
QuestionDefaultInfo->mDefaultValueRecord = pSNode; | |
} | |
// | |
// Update the IsDefaultIdExist array in QuestionDefaultInfo. | |
// | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
QuestionDefaultInfo->mDefaultNumber ++; | |
QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; | |
} | |
break; | |
} | |
} | |
} | |
if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0) { | |
// | |
// This option is used as the manufacture default. | |
// Check whether need to update the smallest default id and QuestionDefaultInfo. | |
// | |
if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) { | |
SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING; | |
QuestionDefaultInfo->mDefaultValueRecord = pSNode; | |
} | |
// | |
// Update the QuestionDefaultInfo. | |
// | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { | |
if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
QuestionDefaultInfo->mDefaultNumber ++; | |
QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; | |
} | |
break; | |
} | |
} | |
} | |
break; | |
case EFI_IFR_DEFAULT_OP: | |
DefaultOpcode = (EFI_IFR_DEFAULT *) pSNode->mIfrBinBuf; | |
// | |
// Check whether need to update the smallest default id and QuestionDefaultInfo. | |
// | |
if (SmallestDefaultId >= DefaultOpcode->DefaultId ) { | |
SmallestDefaultId = DefaultOpcode->DefaultId; | |
QuestionDefaultInfo->mDefaultValueRecord= pSNode; | |
QuestionDefaultInfo->mIsDefaultOpcode= TRUE; | |
} | |
// | |
// Update the QuestionDefaultInfo. | |
// | |
for (UINT8 i = 0; i < mAllDefaultTypeCount; i++){ | |
if (mAllDefaultIdArray[i] == ((EFI_IFR_DEFAULT *)pSNode->mIfrBinBuf)->DefaultId) { | |
if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { | |
QuestionDefaultInfo->mDefaultNumber ++; | |
QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; | |
} | |
break; | |
} | |
} | |
break; | |
default: | |
break; | |
} | |
// | |
// Parse next opcode in this question. | |
// | |
pSNode = pSNode->mNext; | |
} | |
} | |
/** | |
Check or add default for question if need. | |
This function will check the default info for question. | |
If the question has default, but the default number < defaultstore opcode number. | |
will do following two action : | |
1. if (AutoDefault) will add default for question to support all kinds of defaults. | |
2. if (CheckDefault) will generate an error to tell user the question misses some default value. | |
We assume that the two options can not be TRUE at same time. | |
If they are TRUE at same time, only do the action corresponding to AutoDefault option. | |
@param AutoDefault Add default for question if needed | |
@param CheckDefault Check the default info, if missing default, generates an error. | |
**/ | |
VOID | |
CIfrRecordInfoDB::IfrCheckAddDefaultRecord ( | |
BOOLEAN AutoDefault, | |
BOOLEAN CheckDefault | |
) | |
{ | |
SIfrRecord *pNode; | |
SIfrRecord *pTailNode; | |
SIfrRecord *pStartAdjustNode; | |
EFI_IFR_OP_HEADER *pOpHead; | |
QuestionDefaultRecord QuestionDefaultInfo; | |
UINT8 MissingDefaultCount; | |
CHAR8 Msg[MAX_STRING_LEN] = {0, }; | |
pNode = mIfrRecordListHead; | |
// | |
// Record the number and default id of all defaultstore opcode. | |
// | |
IfrGetDefaultStoreInfo (); | |
while (pNode != NULL) { | |
pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf; | |
// | |
// Check whether is question opcode. | |
// | |
if (CheckQuestionOpCode (pOpHead->OpCode)) { | |
// | |
// Initialize some local variables here, because they vary with question. | |
// Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail. | |
// | |
memset (&QuestionDefaultInfo, 0, sizeof (QuestionDefaultRecord)); | |
pTailNode = mIfrRecordListTail; | |
// | |
// Get the QuestionDefaultInfo for current question. | |
// | |
IfrParseDefaulInfoInQuestion (pNode, &QuestionDefaultInfo); | |
if (QuestionDefaultInfo.mDefaultNumber != mAllDefaultTypeCount && QuestionDefaultInfo.mDefaultNumber != 0) { | |
if (AutoDefault) { | |
// | |
// Create default for question which misses default. | |
// | |
IfrCreateDefaultForQuestion (pNode, &QuestionDefaultInfo); | |
// | |
// Adjust the buffer content. | |
// pStartAdjustNode->mIfrBinBuf points to the insert position. | |
// pTailNode->mNext->mIfrBinBuf points to the inset opcodes. | |
// | |
pStartAdjustNode =GetRecordInfoFromOffset (gAdjustOpcodeOffset); | |
gCFormPkg.AdjustDynamicInsertOpcode (pStartAdjustNode->mIfrBinBuf, pTailNode->mNext->mIfrBinBuf, TRUE); | |
// | |
// Update the record info. | |
// | |
IfrUpdateRecordInfoForDynamicOpcode (TRUE); | |
} else if (CheckDefault) { | |
// | |
// Generate an error for question which misses default. | |
// | |
MissingDefaultCount = mAllDefaultTypeCount - QuestionDefaultInfo.mDefaultNumber; | |
sprintf (Msg, "The question misses %d default, the question's opcode is %d", MissingDefaultCount, pOpHead->OpCode); | |
gCVfrErrorHandle.PrintMsg (pNode->mLineNo, NULL, "Error", Msg); | |
} | |
} | |
} | |
// | |
// parse next opcode. | |
// | |
pNode = pNode->mNext; | |
} | |
} | |
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) { | |
memmove (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_TAG), 0}, // EFI_IFR_MODAL_TAG_OP - 0x61 | |
{ sizeof (EFI_IFR_REFRESH_ID), 0}, // EFI_IFR_REFRESH_ID_OP - 0x62 | |
{ sizeof (EFI_IFR_WARNING_IF), 1}, // EFI_IFR_WARNING_IF_OP - 0x63 | |
{ sizeof (EFI_IFR_MATCH2), 0 }, // EFI_IFR_MATCH2_OP - 0x64 | |
}; | |
#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_TAG", "EFI_IFR_REFRESH_ID", "EFI_IFR_WARNING_IF", "EFI_IFR_MATCH2", | |
}; | |
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; | |
mLineNo = 0; | |
assert (mObjBinBuf != NULL); | |
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, }; |