/** @file VfrCompiler error handler. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "stdio.h" #include "string.h" #include "stdlib.h" #include "VfrError.h" #include "EfiUtilityMsgs.h" static SVFR_ERROR_HANDLE VFR_ERROR_HANDLE_TABLE [] = { { VFR_RETURN_SUCCESS, NULL }, { VFR_RETURN_ERROR_SKIPED, NULL }, { VFR_RETURN_FATAL_ERROR, ": fatal error!!" }, { VFR_RETURN_MISMATCHED, ": unexpected token" }, { VFR_RETURN_INVALID_PARAMETER, ": invalid parameter" }, { VFR_RETURN_OUT_FOR_RESOURCES, ": system out of memory" }, { VFR_RETURN_UNSUPPORTED, ": unsupported" }, { VFR_RETURN_REDEFINED, ": already defined" }, { VFR_RETURN_FORMID_REDEFINED, ": form id already defined" }, { VFR_RETURN_QUESTIONID_REDEFINED, ": question id already defined" }, { VFR_RETURN_VARSTOREID_REDEFINED, ": varstore id already defined" }, { VFR_RETURN_UNDEFINED, ": undefined" }, { VFR_RETURN_VAR_NOTDEFINED_BY_QUESTION, ": some variable has not defined by a question"}, { VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR, ": Data Structure is defined by more than one varstores, it can't be referred as varstore, only varstore name could be used."}, { VFR_RETURN_GET_EFIVARSTORE_ERROR, ": get efi varstore error"}, { VFR_RETURN_EFIVARSTORE_USE_ERROR, ": can not use the efi varstore like this" }, { VFR_RETURN_EFIVARSTORE_SIZE_ERROR, ": unsupport efi varstore size should be <= 8 bytes" }, { VFR_RETURN_GET_NVVARSTORE_ERROR, ": get name value varstore error" }, { VFR_RETURN_QVAR_REUSE, ": variable reused by more than one question" }, { VFR_RETURN_FLAGS_UNSUPPORTED, ": flags unsupported" }, { VFR_RETURN_ERROR_ARRARY_NUM, ": array number error, the valid value is in (0 ~ MAX_INDEX-1) for UEFI vfr and in (1 ~ MAX_INDEX) for Framework Vfr" }, { VFR_RETURN_DATA_STRING_ERROR, ": data field string error or not support"}, { VFR_RETURN_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"}, { VFR_RETURN_CONSTANT_ONLY, ": only constant is allowed in the expression"}, { VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR, ": Varstore name is defined by more than one varstores, it can't be referred as varstore, only varstore structure name could be used."}, { VFR_RETURN_BIT_WIDTH_ERROR, ": bit width must be <= sizeof (type) * 8 and the max width can not > 32" }, { VFR_RETURN_STRING_TO_UINT_OVERFLOW, ": String to UINT* Overflow"}, { VFR_RETURN_CODEUNDEFINED, ": undefined Error Code" } }; static SVFR_WARNING_HANDLE VFR_WARNING_HANDLE_TABLE [] = { { VFR_WARNING_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"}, { VFR_WARNING_ACTION_WITH_TEXT_TWO, ": Action opcode should not have TextTwo part"}, { VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, ": Not recommend to use obsoleted framework opcode"}, { VFR_WARNING_CODEUNDEFINED, ": undefined Warning Code" } }; CVfrErrorHandle::CVfrErrorHandle ( VOID ) { mInputFileName = NULL; mScopeRecordListHead = NULL; mScopeRecordListTail = NULL; mVfrErrorHandleTable = VFR_ERROR_HANDLE_TABLE; mVfrWarningHandleTable = VFR_WARNING_HANDLE_TABLE; mWarningAsError = FALSE; } CVfrErrorHandle::~CVfrErrorHandle ( VOID ) { SVfrFileScopeRecord *pNode = NULL; if (mInputFileName != NULL) { delete[] mInputFileName; } while (mScopeRecordListHead != NULL) { pNode = mScopeRecordListHead; mScopeRecordListHead = mScopeRecordListHead->mNext; delete pNode; } mScopeRecordListHead = NULL; mScopeRecordListTail = NULL; mVfrErrorHandleTable = NULL; mVfrWarningHandleTable = NULL; } VOID CVfrErrorHandle::SetWarningAsError ( IN BOOLEAN WarningAsError ) { mWarningAsError = WarningAsError; } VOID CVfrErrorHandle::SetInputFile ( IN CHAR8 *InputFile ) { if (InputFile != NULL) { mInputFileName = new CHAR8[strlen(InputFile) + 1]; strcpy (mInputFileName, InputFile); } } SVfrFileScopeRecord::SVfrFileScopeRecord ( IN CHAR8 *Record, IN UINT32 LineNum ) { UINT32 Index; CHAR8 *FileName = NULL; CHAR8 *Str = NULL; mWholeScopeLine = LineNum; mNext = NULL; Str = strchr (Record, ' '); mScopeLineStart = atoi (++Str); Str = strchr (Str, '\"'); FileName = ++Str; while((Str = strstr (FileName, "\\\\")) != NULL) { FileName = Str + 2; } if ((mFileName = new CHAR8[strlen(FileName)]) != NULL) { for (Index = 0; FileName[Index] != '\"'; Index++) { mFileName[Index] = FileName[Index]; } mFileName[Index] = '\0'; } return; } SVfrFileScopeRecord::~SVfrFileScopeRecord ( VOID ) { if (mFileName != NULL) { delete[] mFileName; } } VOID CVfrErrorHandle::ParseFileScopeRecord ( IN CHAR8 *Record, IN UINT32 WholeScopeLine ) { SVfrFileScopeRecord *pNode = NULL; if (Record == NULL) { return; } if ((pNode = new SVfrFileScopeRecord(Record, WholeScopeLine)) == NULL) { return; } if (mScopeRecordListHead == NULL) { mScopeRecordListTail = mScopeRecordListHead = pNode; } else { mScopeRecordListTail->mNext = pNode; mScopeRecordListTail = pNode; } } VOID CVfrErrorHandle::GetFileNameLineNum ( IN UINT32 LineNum, OUT CHAR8 **FileName, OUT UINT32 *FileLine ) { SVfrFileScopeRecord *pNode = NULL; if ((FileName == NULL) || (FileLine == NULL)) { return; } *FileName = NULL; *FileLine = 0xFFFFFFFF; // // Some errors occur before scope record list been built. // if (mScopeRecordListHead == NULL) { *FileLine = LineNum; *FileName = mInputFileName; return ; } for (pNode = mScopeRecordListHead; pNode->mNext != NULL; pNode = pNode->mNext) { if ((LineNum > pNode->mWholeScopeLine) && (pNode->mNext->mWholeScopeLine > LineNum)) { *FileName = pNode->mFileName; *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1; return ; } } *FileName = pNode->mFileName; *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1; } VOID CVfrErrorHandle::PrintMsg ( IN UINT32 LineNum, IN CHAR8 *TokName, IN CONST CHAR8 *MsgType, IN CONST CHAR8 *ErrorMsg ) { CHAR8 *FileName = NULL; UINT32 FileLine; if (strncmp ("Warning", MsgType, strlen ("Warning")) == 0) { VerboseMsg ((CHAR8 *) ErrorMsg); return; } GetFileNameLineNum (LineNum, &FileName, &FileLine); Error (FileName, FileLine, 0x3000, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) ErrorMsg); } UINT8 CVfrErrorHandle::HandleError ( IN EFI_VFR_RETURN_CODE ErrorCode, IN UINT32 LineNum, IN CHAR8 *TokName ) { UINT32 Index; CHAR8 *FileName = NULL; UINT32 FileLine; CONST CHAR8 *ErrorMsg = NULL; if (mVfrErrorHandleTable == NULL) { return 1; } for (Index = 0; mVfrErrorHandleTable[Index].mErrorCode != VFR_RETURN_CODEUNDEFINED; Index++) { if (ErrorCode == mVfrErrorHandleTable[Index].mErrorCode) { ErrorMsg = mVfrErrorHandleTable[Index].mErrorMsg; break; } } if (ErrorMsg != NULL) { GetFileNameLineNum (LineNum, &FileName, &FileLine); Error (FileName, FileLine, 0x3000, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) ErrorMsg); return 1; } else { return 0; } } UINT8 CVfrErrorHandle::HandleWarning ( IN EFI_VFR_WARNING_CODE WarningCode, IN UINT32 LineNum, IN CHAR8 *TokName ) { UINT32 Index; CHAR8 *FileName = NULL; UINT32 FileLine; CONST CHAR8 *WarningMsg = NULL; if (mVfrWarningHandleTable == NULL) { return 1; } GetFileNameLineNum (LineNum, &FileName, &FileLine); if (mWarningAsError) { Error (FileName, FileLine, 0x2220, (CHAR8 *) "warning treated as error", NULL); } for (Index = 0; mVfrWarningHandleTable[Index].mWarningCode != VFR_WARNING_CODEUNDEFINED; Index++) { if (WarningCode == mVfrWarningHandleTable[Index].mWarningCode) { WarningMsg = mVfrWarningHandleTable[Index].mWarningMsg; break; } } if (WarningMsg != NULL) { Warning (FileName, FileLine, 0, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) WarningMsg); return 1; } else { return 0; } } CVfrErrorHandle gCVfrErrorHandle;