1 /** @file
2
3 VfrCompiler error handler.
4
5 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "stdio.h"
17 #include "string.h"
18 #include "stdlib.h"
19 #include "VfrError.h"
20 #include "EfiUtilityMsgs.h"
21
22 static SVFR_ERROR_HANDLE VFR_ERROR_HANDLE_TABLE [] = {
23 { VFR_RETURN_SUCCESS, NULL },
24 { VFR_RETURN_ERROR_SKIPED, NULL },
25 { VFR_RETURN_FATAL_ERROR, ": fatal error!!" },
26
27 { VFR_RETURN_MISMATCHED, ": unexpected token" },
28 { VFR_RETURN_INVALID_PARAMETER, ": invalid parameter" },
29 { VFR_RETURN_OUT_FOR_RESOURCES, ": system out of memory" },
30 { VFR_RETURN_UNSUPPORTED, ": unsupported" },
31 { VFR_RETURN_REDEFINED, ": already defined" },
32 { VFR_RETURN_FORMID_REDEFINED, ": form id already defined" },
33 { VFR_RETURN_QUESTIONID_REDEFINED, ": question id already defined" },
34 { VFR_RETURN_VARSTOREID_REDEFINED, ": varstore id already defined" },
35 { VFR_RETURN_UNDEFINED, ": undefined" },
36 { VFR_RETURN_VAR_NOTDEFINED_BY_QUESTION, ": some variable has not defined by a question"},
37 { 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."},
38 { VFR_RETURN_GET_EFIVARSTORE_ERROR, ": get efi varstore error"},
39 { VFR_RETURN_EFIVARSTORE_USE_ERROR, ": can not use the efi varstore like this" },
40 { VFR_RETURN_EFIVARSTORE_SIZE_ERROR, ": unsupport efi varstore size should be <= 8 bytes" },
41 { VFR_RETURN_GET_NVVARSTORE_ERROR, ": get name value varstore error" },
42 { VFR_RETURN_QVAR_REUSE, ": variable reused by more than one question" },
43 { VFR_RETURN_FLAGS_UNSUPPORTED, ": flags unsupported" },
44 { 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" },
45 { VFR_RETURN_DATA_STRING_ERROR, ": data field string error or not support"},
46 { VFR_RETURN_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"},
47 { VFR_RETURN_CONSTANT_ONLY, ": only constant is allowed in the expression"},
48 { VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR, ": Varstore name is defined by more than one varstores, it can't be referred as varstore, only varstore strucure name could be used."},
49 { VFR_RETURN_CODEUNDEFINED, ": undefined Error Code" }
50 };
51
52 static SVFR_WARNING_HANDLE VFR_WARNING_HANDLE_TABLE [] = {
53 { VFR_WARNING_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"},
54 { VFR_WARNING_STRING_TO_UINT_OVERFLOW, ": String to UINT* Overflow"},
55 { VFR_WARNING_ACTION_WITH_TEXT_TWO, ": Action opcode should not have TextTwo part"},
56 { VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, ": Not recommend to use obsoleted framework opcode"},
57 { VFR_WARNING_CODEUNDEFINED, ": undefined Warning Code" }
58 };
59
CVfrErrorHandle(VOID)60 CVfrErrorHandle::CVfrErrorHandle (
61 VOID
62 )
63 {
64 mInputFileName = NULL;
65 mScopeRecordListHead = NULL;
66 mScopeRecordListTail = NULL;
67 mVfrErrorHandleTable = VFR_ERROR_HANDLE_TABLE;
68 mVfrWarningHandleTable = VFR_WARNING_HANDLE_TABLE;
69 }
70
~CVfrErrorHandle(VOID)71 CVfrErrorHandle::~CVfrErrorHandle (
72 VOID
73 )
74 {
75 SVfrFileScopeRecord *pNode = NULL;
76
77 if (mInputFileName != NULL) {
78 delete mInputFileName;
79 }
80
81 while (mScopeRecordListHead != NULL) {
82 pNode = mScopeRecordListHead;
83 mScopeRecordListHead = mScopeRecordListHead->mNext;
84 delete pNode;
85 }
86
87 mScopeRecordListHead = NULL;
88 mScopeRecordListTail = NULL;
89 mVfrErrorHandleTable = NULL;
90 mVfrWarningHandleTable = NULL;
91 }
92
93 VOID
SetWarningAsError(IN BOOLEAN WarningAsError)94 CVfrErrorHandle::SetWarningAsError (
95 IN BOOLEAN WarningAsError
96 )
97 {
98 mWarningAsError = WarningAsError;
99 }
100
101 VOID
SetInputFile(IN CHAR8 * InputFile)102 CVfrErrorHandle::SetInputFile (
103 IN CHAR8 *InputFile
104 )
105 {
106 if (InputFile != NULL) {
107 mInputFileName = new CHAR8[strlen(InputFile) + 1];
108 strcpy (mInputFileName, InputFile);
109 }
110 }
111
SVfrFileScopeRecord(IN CHAR8 * Record,IN UINT32 LineNum)112 SVfrFileScopeRecord::SVfrFileScopeRecord (
113 IN CHAR8 *Record,
114 IN UINT32 LineNum
115 )
116 {
117 UINT32 Index;
118 CHAR8 *FileName = NULL;
119 CHAR8 *Str = NULL;
120
121 mWholeScopeLine = LineNum;
122 mNext = NULL;
123
124 Str = strchr (Record, ' ');
125 mScopeLineStart = atoi (++Str);
126
127 Str = strchr (Str, '\"');
128 FileName = ++Str;
129
130 while((Str = strstr (FileName, "\\\\")) != NULL) {
131 FileName = Str + 2;
132 }
133 if ((mFileName = new CHAR8[strlen(FileName)]) != NULL) {
134 for (Index = 0; FileName[Index] != '\"'; Index++) {
135 mFileName[Index] = FileName[Index];
136 }
137 mFileName[Index] = '\0';
138 }
139
140 return;
141 }
142
~SVfrFileScopeRecord(VOID)143 SVfrFileScopeRecord::~SVfrFileScopeRecord (
144 VOID
145 )
146 {
147 if (mFileName != NULL) {
148 delete mFileName;
149 }
150 }
151
152 VOID
ParseFileScopeRecord(IN CHAR8 * Record,IN UINT32 WholeScopeLine)153 CVfrErrorHandle::ParseFileScopeRecord (
154 IN CHAR8 *Record,
155 IN UINT32 WholeScopeLine
156 )
157 {
158 SVfrFileScopeRecord *pNode = NULL;
159
160 if (Record == NULL) {
161 return;
162 }
163
164 if ((pNode = new SVfrFileScopeRecord(Record, WholeScopeLine)) == NULL) {
165 return;
166 }
167
168 if (mScopeRecordListHead == NULL) {
169 mScopeRecordListTail = mScopeRecordListHead = pNode;
170 } else {
171 mScopeRecordListTail->mNext = pNode;
172 mScopeRecordListTail = pNode;
173 }
174 }
175
176 VOID
GetFileNameLineNum(IN UINT32 LineNum,OUT CHAR8 ** FileName,OUT UINT32 * FileLine)177 CVfrErrorHandle::GetFileNameLineNum (
178 IN UINT32 LineNum,
179 OUT CHAR8 **FileName,
180 OUT UINT32 *FileLine
181 )
182 {
183 SVfrFileScopeRecord *pNode = NULL;
184
185 if ((FileName == NULL) || (FileLine == NULL)) {
186 return;
187 }
188
189 *FileName = NULL;
190 *FileLine = 0xFFFFFFFF;
191
192 //
193 // Some errors occur before scope record list been built.
194 //
195 if (mScopeRecordListHead == NULL) {
196 *FileLine = LineNum;
197 *FileName = mInputFileName;
198 return ;
199 }
200
201 for (pNode = mScopeRecordListHead; pNode->mNext != NULL; pNode = pNode->mNext) {
202 if ((LineNum > pNode->mWholeScopeLine) && (pNode->mNext->mWholeScopeLine > LineNum)) {
203 *FileName = pNode->mFileName;
204 *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1;
205 return ;
206 }
207 }
208
209 *FileName = pNode->mFileName;
210 *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1;
211 }
212
213 VOID
PrintMsg(IN UINT32 LineNum,IN CHAR8 * TokName,IN CONST CHAR8 * MsgType,IN CONST CHAR8 * ErrorMsg)214 CVfrErrorHandle::PrintMsg (
215 IN UINT32 LineNum,
216 IN CHAR8 *TokName,
217 IN CONST CHAR8 *MsgType,
218 IN CONST CHAR8 *ErrorMsg
219 )
220 {
221 CHAR8 *FileName = NULL;
222 UINT32 FileLine;
223
224 if (strncmp ("Warning", MsgType, strlen ("Warning")) == 0) {
225 VerboseMsg ((CHAR8 *) ErrorMsg);
226 return;
227 }
228 GetFileNameLineNum (LineNum, &FileName, &FileLine);
229 Error (FileName, FileLine, 0x3000, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) ErrorMsg);
230 }
231
232 UINT8
HandleError(IN EFI_VFR_RETURN_CODE ErrorCode,IN UINT32 LineNum,IN CHAR8 * TokName)233 CVfrErrorHandle::HandleError (
234 IN EFI_VFR_RETURN_CODE ErrorCode,
235 IN UINT32 LineNum,
236 IN CHAR8 *TokName
237 )
238 {
239 UINT32 Index;
240 CHAR8 *FileName = NULL;
241 UINT32 FileLine;
242 CONST CHAR8 *ErrorMsg = NULL;
243
244 if (mVfrErrorHandleTable == NULL) {
245 return 1;
246 }
247
248 for (Index = 0; mVfrErrorHandleTable[Index].mErrorCode != VFR_RETURN_CODEUNDEFINED; Index++) {
249 if (ErrorCode == mVfrErrorHandleTable[Index].mErrorCode) {
250 ErrorMsg = mVfrErrorHandleTable[Index].mErrorMsg;
251 break;
252 }
253 }
254
255 if (ErrorMsg != NULL) {
256 GetFileNameLineNum (LineNum, &FileName, &FileLine);
257 Error (FileName, FileLine, 0x3000, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) ErrorMsg);
258 return 1;
259 } else {
260 return 0;
261 }
262 }
263
264 UINT8
HandleWarning(IN EFI_VFR_WARNING_CODE WarningCode,IN UINT32 LineNum,IN CHAR8 * TokName)265 CVfrErrorHandle::HandleWarning (
266 IN EFI_VFR_WARNING_CODE WarningCode,
267 IN UINT32 LineNum,
268 IN CHAR8 *TokName
269 )
270 {
271 UINT32 Index;
272 CHAR8 *FileName = NULL;
273 UINT32 FileLine;
274 CONST CHAR8 *WarningMsg = NULL;
275
276 if (mVfrWarningHandleTable == NULL) {
277 return 1;
278 }
279
280 GetFileNameLineNum (LineNum, &FileName, &FileLine);
281
282 if (mWarningAsError) {
283 Error (FileName, FileLine, 0x2220, (CHAR8 *) "warning treated as error", NULL);
284 }
285
286 for (Index = 0; mVfrWarningHandleTable[Index].mWarningCode != VFR_WARNING_CODEUNDEFINED; Index++) {
287 if (WarningCode == mVfrWarningHandleTable[Index].mWarningCode) {
288 WarningMsg = mVfrWarningHandleTable[Index].mWarningMsg;
289 break;
290 }
291 }
292
293 if (WarningMsg != NULL) {
294 Warning (FileName, FileLine, 0, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) WarningMsg);
295 return 1;
296 } else {
297 return 0;
298 }
299 }
300
301 CVfrErrorHandle gCVfrErrorHandle;
302