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