• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 
3   VfrCompiler main class and main function.
4 
5 Copyright (c) 2004 - 2014, 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 "stdlib.h"
18 #include "string.h"
19 #include "VfrCompiler.h"
20 #include "CommonLib.h"
21 #include "EfiUtilityMsgs.h"
22 
23 PACKAGE_DATA  gCBuffer;
24 PACKAGE_DATA  gRBuffer;
25 CVfrStringDB  gCVfrStringDB;
26 
27 VOID
DebugError(IN CHAR8 * FileName,IN UINT32 LineNumber,IN UINT32 MessageCode,IN CONST CHAR8 * Text,IN CONST CHAR8 * MsgFmt,...)28 CVfrCompiler::DebugError (
29   IN CHAR8         *FileName,
30   IN UINT32        LineNumber,
31   IN UINT32        MessageCode,
32   IN CONST CHAR8   *Text,
33   IN CONST CHAR8   *MsgFmt,
34   ...
35   )
36 {
37   va_list List;
38   va_start (List, MsgFmt);
39   PrintMessage ((CHAR8 *) "ERROR", FileName, LineNumber, MessageCode, (CHAR8 *) Text, (CHAR8 *) MsgFmt, List);
40   va_end (List);
41 }
42 
43 VOID
SET_RUN_STATUS(IN COMPILER_RUN_STATUS Status)44 CVfrCompiler::SET_RUN_STATUS (
45   IN COMPILER_RUN_STATUS Status
46   )
47 {
48   mRunStatus = Status;
49 }
50 
51 BOOLEAN
IS_RUN_STATUS(IN COMPILER_RUN_STATUS Status)52 CVfrCompiler::IS_RUN_STATUS (
53   IN COMPILER_RUN_STATUS Status
54   )
55 {
56   return mRunStatus == Status;
57 }
58 
59 VOID
OptionInitialization(IN INT32 Argc,IN CHAR8 ** Argv)60 CVfrCompiler::OptionInitialization (
61   IN INT32      Argc,
62   IN CHAR8      **Argv
63   )
64 {
65   INT32         Index;
66   EFI_STATUS    Status;
67 
68   Status = EFI_SUCCESS;
69   SetUtilityName ((CHAR8*) PROGRAM_NAME);
70 
71   mOptions.VfrFileName[0]                = '\0';
72   mOptions.RecordListFile[0]             = '\0';
73   mOptions.CreateRecordListFile          = FALSE;
74   mOptions.CreateIfrPkgFile              = FALSE;
75   mOptions.PkgOutputFileName[0]          = '\0';
76   mOptions.COutputFileName[0]            = '\0';
77   mOptions.OutputDirectory[0]            = '\0';
78   mOptions.PreprocessorOutputFileName[0] = '\0';
79   mOptions.VfrBaseFileName[0]            = '\0';
80   mOptions.IncludePaths                  = NULL;
81   mOptions.SkipCPreprocessor             = TRUE;
82   mOptions.CPreprocessorOptions          = NULL;
83   mOptions.CompatibleMode                = FALSE;
84   mOptions.HasOverrideClassGuid          = FALSE;
85   mOptions.WarningAsError                = FALSE;
86   memset (&mOptions.OverrideClassGuid, 0, sizeof (EFI_GUID));
87 
88   if (Argc == 1) {
89     Usage ();
90     SET_RUN_STATUS (STATUS_DEAD);
91     return;
92   }
93 
94   for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) {
95     if ((stricmp(Argv[Index], "-h") == 0) || (stricmp(Argv[Index], "--help") == 0)) {
96       Usage ();
97       SET_RUN_STATUS (STATUS_DEAD);
98       return;
99     } else if (stricmp(Argv[Index], "--version") == 0) {
100       Version ();
101       SET_RUN_STATUS (STATUS_DEAD);
102       return;
103     } else if (stricmp(Argv[Index], "-l") == 0) {
104       mOptions.CreateRecordListFile = TRUE;
105       gCIfrRecordInfoDB.TurnOn ();
106     } else if (stricmp(Argv[Index], "-i") == 0) {
107       Index++;
108       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
109         DebugError (NULL, 0, 1001, "Missing option", "-i missing path argument");
110         goto Fail;
111       }
112 
113       AppendIncludePath(Argv[Index]);
114     } else if (stricmp(Argv[Index], "-o") == 0 || stricmp(Argv[Index], "--output-directory") == 0 || stricmp(Argv[Index], "-od") == 0) {
115       Index++;
116       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
117         DebugError (NULL, 0, 1001, "Missing option", "-o missing output directory name");
118         goto Fail;
119       }
120       strcpy (mOptions.OutputDirectory, Argv[Index]);
121 
122       CHAR8 lastChar = mOptions.OutputDirectory[strlen(mOptions.OutputDirectory) - 1];
123       if ((lastChar != '/') && (lastChar != '\\')) {
124         if (strchr(mOptions.OutputDirectory, '/') != NULL) {
125           strcat (mOptions.OutputDirectory, "/");
126         } else {
127           strcat (mOptions.OutputDirectory, "\\");
128         }
129       }
130       DebugMsg (NULL, 0, 9, (CHAR8 *) "Output Directory", mOptions.OutputDirectory);
131     } else if (stricmp(Argv[Index], "-b") == 0 || stricmp(Argv[Index], "--create-ifr-package") == 0 || stricmp(Argv[Index], "-ibin") == 0) {
132       mOptions.CreateIfrPkgFile = TRUE;
133     } else if (stricmp(Argv[Index], "-n") == 0 || stricmp(Argv[Index], "--no-pre-processing") == 0 || stricmp(Argv[Index], "-nopp") == 0) {
134       mOptions.SkipCPreprocessor = TRUE;
135     } else if (stricmp(Argv[Index], "-f") == 0 || stricmp(Argv[Index], "--pre-processing-flag") == 0 || stricmp(Argv[Index], "-ppflag") == 0) {
136       Index++;
137       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
138         DebugError (NULL, 0, 1001, "Missing option", "-od - missing C-preprocessor argument");
139         goto Fail;
140       }
141 
142       AppendCPreprocessorOptions (Argv[Index]);
143     } else if (stricmp(Argv[Index], "-c") == 0 || stricmp(Argv[Index], "--compatible-framework") == 0) {
144       mOptions.CompatibleMode = TRUE;
145     } else if (stricmp(Argv[Index], "-s") == 0|| stricmp(Argv[Index], "--string-db") == 0) {
146       Index++;
147       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
148         DebugError (NULL, 0, 1001, "Missing option", "-s missing input string file name");
149         goto Fail;
150       }
151       gCVfrStringDB.SetStringFileName(Argv[Index]);
152       DebugMsg (NULL, 0, 9, (CHAR8 *) "Input string file path", Argv[Index]);
153     } else if ((stricmp (Argv[Index], "-g") == 0) || (stricmp (Argv[Index], "--guid") == 0)) {
154       Index++;
155       Status = StringToGuid (Argv[Index], &mOptions.OverrideClassGuid);
156       if (EFI_ERROR (Status)) {
157         DebugError (NULL, 0, 1000, "Invalid format:", "%s", Argv[Index]);
158         goto Fail;
159       }
160       mOptions.HasOverrideClassGuid = TRUE;
161     } else if (stricmp(Argv[Index], "-w") == 0 || stricmp(Argv[Index], "--warning-as-error") == 0) {
162       mOptions.WarningAsError = TRUE;
163     } else {
164       DebugError (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]);
165       goto Fail;
166     }
167   }
168 
169   if (Index != Argc - 1) {
170     DebugError (NULL, 0, 1001, "Missing option", "VFR file name is not specified.");
171     goto Fail;
172   } else {
173     strcpy (mOptions.VfrFileName, Argv[Index]);
174   }
175 
176   if (SetBaseFileName() != 0) {
177     goto Fail;
178   }
179   if (SetPkgOutputFileName () != 0) {
180     goto Fail;
181   }
182   if (SetCOutputFileName() != 0) {
183     goto Fail;
184   }
185   if (SetPreprocessorOutputFileName () != 0) {
186     goto Fail;
187   }
188   if (SetRecordListFileName () != 0) {
189     goto Fail;
190   }
191   return;
192 
193 Fail:
194   SET_RUN_STATUS (STATUS_DEAD);
195 
196   mOptions.VfrFileName[0]                = '\0';
197   mOptions.RecordListFile[0]             = '\0';
198   mOptions.CreateRecordListFile          = FALSE;
199   mOptions.CreateIfrPkgFile              = FALSE;
200   mOptions.PkgOutputFileName[0]          = '\0';
201   mOptions.COutputFileName[0]            = '\0';
202   mOptions.OutputDirectory[0]            = '\0';
203   mOptions.PreprocessorOutputFileName[0] = '\0';
204   mOptions.VfrBaseFileName[0]            = '\0';
205   if (mOptions.IncludePaths != NULL) {
206     delete mOptions.IncludePaths;
207     mOptions.IncludePaths                = NULL;
208   }
209   if (mOptions.CPreprocessorOptions != NULL) {
210     delete mOptions.CPreprocessorOptions;
211     mOptions.CPreprocessorOptions        = NULL;
212   }
213 }
214 
215 VOID
AppendIncludePath(IN CHAR8 * PathStr)216 CVfrCompiler::AppendIncludePath (
217   IN CHAR8      *PathStr
218   )
219 {
220   UINT32  Len           = 0;
221   CHAR8   *IncludePaths = NULL;
222 
223   Len = strlen (" -I ") + strlen (PathStr) + 1;
224   if (mOptions.IncludePaths != NULL) {
225     Len += strlen (mOptions.IncludePaths);
226   }
227   IncludePaths = new CHAR8[Len];
228   if (IncludePaths == NULL) {
229     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
230     return;
231   }
232   IncludePaths[0] = '\0';
233   if (mOptions.IncludePaths != NULL) {
234     strcat (IncludePaths, mOptions.IncludePaths);
235   }
236   strcat (IncludePaths, " -I ");
237   strcat (IncludePaths, PathStr);
238   if (mOptions.IncludePaths != NULL) {
239     delete mOptions.IncludePaths;
240   }
241   mOptions.IncludePaths = IncludePaths;
242 }
243 
244 VOID
AppendCPreprocessorOptions(IN CHAR8 * Options)245 CVfrCompiler::AppendCPreprocessorOptions (
246   IN CHAR8      *Options
247   )
248 {
249   UINT32  Len           = 0;
250   CHAR8   *Opt          = NULL;
251 
252   Len = strlen (Options) + strlen (" ") + 1;
253   if (mOptions.CPreprocessorOptions != NULL) {
254     Len += strlen (mOptions.CPreprocessorOptions);
255   }
256   Opt = new CHAR8[Len];
257   if (Opt == NULL) {
258     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
259     return;
260   }
261   Opt[0] = 0;
262   if (mOptions.CPreprocessorOptions != NULL) {
263     strcat (Opt, mOptions.CPreprocessorOptions);
264   }
265   strcat (Opt, " ");
266   strcat (Opt, Options);
267   if (mOptions.CPreprocessorOptions != NULL) {
268     delete mOptions.CPreprocessorOptions;
269   }
270   mOptions.CPreprocessorOptions = Opt;
271 }
272 
273 INT8
SetBaseFileName(VOID)274 CVfrCompiler::SetBaseFileName (
275   VOID
276   )
277 {
278   CHAR8         *pFileName, *pPath, *pExt;
279 
280   if (mOptions.VfrFileName[0] == '\0') {
281     return -1;
282   }
283 
284   pFileName = mOptions.VfrFileName;
285   while (
286     ((pPath = strchr (pFileName, '\\')) != NULL) ||
287     ((pPath = strchr (pFileName, '/')) != NULL)
288     )
289   {
290     pFileName = pPath + 1;
291   }
292 
293   if (pFileName == NULL) {
294     return -1;
295   }
296 
297   if ((pExt = strchr (pFileName, '.')) == NULL) {
298     return -1;
299   }
300 
301   strncpy (mOptions.VfrBaseFileName, pFileName, pExt - pFileName);
302   mOptions.VfrBaseFileName[pExt - pFileName] = '\0';
303 
304   return 0;
305 }
306 
307 INT8
SetPkgOutputFileName(VOID)308 CVfrCompiler::SetPkgOutputFileName (
309   VOID
310   )
311 {
312   if (mOptions.VfrBaseFileName[0] == '\0') {
313     return -1;
314   }
315 
316   strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory);
317   strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName);
318   strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION);
319 
320   return 0;
321 }
322 
323 INT8
SetCOutputFileName(VOID)324 CVfrCompiler::SetCOutputFileName (
325   VOID
326   )
327 {
328   if (mOptions.VfrBaseFileName[0] == '\0') {
329     return -1;
330   }
331 
332   strcpy (mOptions.COutputFileName, mOptions.OutputDirectory);
333   strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName);
334   strcat (mOptions.COutputFileName, ".c");
335 
336   return 0;
337 }
338 
339 INT8
SetPreprocessorOutputFileName(VOID)340 CVfrCompiler::SetPreprocessorOutputFileName (
341   VOID
342   )
343 {
344   if (mOptions.VfrBaseFileName[0] == '\0') {
345     return -1;
346   }
347 
348   strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory);
349   strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName);
350   strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);
351 
352   return 0;
353 }
354 
355 INT8
SetRecordListFileName(VOID)356 CVfrCompiler::SetRecordListFileName (
357   VOID
358   )
359 {
360   if (mOptions.VfrBaseFileName[0] == '\0') {
361     return -1;
362   }
363 
364   strcpy (mOptions.RecordListFile, mOptions.OutputDirectory);
365   strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName);
366   strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION);
367 
368   return 0;
369 }
370 
CVfrCompiler(IN INT32 Argc,IN CHAR8 ** Argv)371 CVfrCompiler::CVfrCompiler (
372   IN INT32      Argc,
373   IN CHAR8      **Argv
374   )
375 {
376   mPreProcessCmd = (CHAR8 *) PREPROCESSOR_COMMAND;
377   mPreProcessOpt = (CHAR8 *) PREPROCESSOR_OPTIONS;
378 
379   SET_RUN_STATUS (STATUS_STARTED);
380 
381   OptionInitialization(Argc, Argv);
382 
383   if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) {
384     return;
385   }
386 
387   SET_RUN_STATUS(STATUS_INITIALIZED);
388 }
389 
~CVfrCompiler(VOID)390 CVfrCompiler::~CVfrCompiler (
391   VOID
392   )
393 {
394   if (mOptions.IncludePaths != NULL) {
395     delete mOptions.IncludePaths;
396     mOptions.IncludePaths = NULL;
397   }
398 
399   if (mOptions.CPreprocessorOptions != NULL) {
400     delete mOptions.CPreprocessorOptions;
401     mOptions.CPreprocessorOptions = NULL;
402   }
403 
404   SET_RUN_STATUS(STATUS_DEAD);
405 }
406 
407 VOID
Usage(VOID)408 CVfrCompiler::Usage (
409   VOID
410   )
411 {
412   UINT32 Index;
413   CONST  CHAR8 *Help[] = {
414     " ",
415     "VfrCompile version " VFR_COMPILER_VERSION __BUILD_VERSION,
416     "Copyright (c) 2004-2014 Intel Corporation. All rights reserved.",
417     " ",
418     "Usage: VfrCompile [options] VfrFile",
419     " ",
420     "Options:",
421     "  -h, --help     prints this help",
422     "  --version      prints version info",
423     "  -l             create an output IFR listing file",
424     "  -o DIR, --output-directory DIR",
425     "                 deposit all output files to directory OutputDir",
426     "                 default is current directory",
427     "  -b, --create-ifr-package",
428     "                 create an IFR HII pack file",
429     "  -n, --no-pre-processing",
430     "                 do not preprocessing input file",
431     "  -c, --compatible-framework",
432     "                 compatible framework vfr file",
433     "  -s, --string-db",
434     "                 input uni string package file",
435     "  -g, --guid",
436     "                 override class guid input",
437     "                 format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
438     "  -w  --warning-as-error",
439     "                 treat warning as an error",
440     NULL
441     };
442   for (Index = 0; Help[Index] != NULL; Index++) {
443     fprintf (stdout, "%s\n", Help[Index]);
444   }
445 }
446 
447 VOID
Version(VOID)448 CVfrCompiler::Version (
449   VOID
450   )
451 {
452   UINT32 Index;
453   CONST  CHAR8 *Help[] = {
454     "VfrCompile version " VFR_COMPILER_VERSION __BUILD_VERSION,
455     NULL
456     };
457   for (Index = 0; Help[Index] != NULL; Index++) {
458     fprintf (stdout, "%s\n", Help[Index]);
459   }
460 }
461 
462 VOID
PreProcess(VOID)463 CVfrCompiler::PreProcess (
464   VOID
465   )
466 {
467   FILE    *pVfrFile      = NULL;
468   UINT32  CmdLen         = 0;
469   CHAR8   *PreProcessCmd = NULL;
470 
471   if (!IS_RUN_STATUS(STATUS_INITIALIZED)) {
472     goto Fail;
473   }
474 
475   if (mOptions.SkipCPreprocessor == TRUE) {
476     goto Out;
477   }
478 
479   if ((pVfrFile = fopen (LongFilePath (mOptions.VfrFileName), "r")) == NULL) {
480     DebugError (NULL, 0, 0001, "Error opening the input VFR file", mOptions.VfrFileName);
481     goto Fail;
482   }
483   fclose (pVfrFile);
484 
485   CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) +
486   	       strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName);
487   if (mOptions.CPreprocessorOptions != NULL) {
488     CmdLen += strlen (mOptions.CPreprocessorOptions);
489   }
490   if (mOptions.IncludePaths != NULL) {
491     CmdLen += strlen (mOptions.IncludePaths);
492   }
493 
494   PreProcessCmd = new CHAR8[CmdLen + 10];
495   if (PreProcessCmd == NULL) {
496     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
497     goto Fail;
498   }
499   strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " ");
500   strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " ");
501   if (mOptions.IncludePaths != NULL) {
502     strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " ");
503   }
504   if (mOptions.CPreprocessorOptions != NULL) {
505     strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " ");
506   }
507   strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > ");
508   strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName);
509 
510   if (system (PreProcessCmd) != 0) {
511     DebugError (NULL, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd);
512     goto Fail;
513   }
514 
515   delete PreProcessCmd;
516 
517 Out:
518   SET_RUN_STATUS (STATUS_PREPROCESSED);
519   return;
520 
521 Fail:
522   if (!IS_RUN_STATUS(STATUS_DEAD)) {
523     SET_RUN_STATUS (STATUS_FAILED);
524   }
525   delete PreProcessCmd;
526 }
527 
528 extern UINT8 VfrParserStart (IN FILE *, IN INPUT_INFO_TO_SYNTAX *);
529 
530 VOID
Compile(VOID)531 CVfrCompiler::Compile (
532   VOID
533   )
534 {
535   FILE  *pInFile    = NULL;
536   CHAR8 *InFileName = NULL;
537   INPUT_INFO_TO_SYNTAX InputInfo;
538 
539   if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) {
540     goto Fail;
541   }
542 
543   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
544 
545   gCVfrErrorHandle.SetInputFile (InFileName);
546   gCVfrErrorHandle.SetWarningAsError(mOptions.WarningAsError);
547 
548   if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) {
549     DebugError (NULL, 0, 0001, "Error opening the input file", InFileName);
550     goto Fail;
551   }
552 
553   InputInfo.CompatibleMode = mOptions.CompatibleMode;
554   if (mOptions.HasOverrideClassGuid) {
555     InputInfo.OverrideClassGuid = &mOptions.OverrideClassGuid;
556   } else {
557     InputInfo.OverrideClassGuid = NULL;
558   }
559 
560   if (VfrParserStart (pInFile, &InputInfo) != 0) {
561     goto Fail;
562   }
563 
564   fclose (pInFile);
565 
566   if (gCFormPkg.HavePendingUnassigned () == TRUE) {
567     gCFormPkg.PendingAssignPrintAll ();
568     goto Fail;
569   }
570 
571   SET_RUN_STATUS (STATUS_COMPILEED);
572   return;
573 
574 Fail:
575   if (!IS_RUN_STATUS(STATUS_DEAD)) {
576     DebugError (NULL, 0, 0003, "Error parsing", "compile error in file %s", InFileName);
577     SET_RUN_STATUS (STATUS_FAILED);
578   }
579   if (pInFile != NULL) {
580     fclose (pInFile);
581   }
582 }
583 
584 VOID
UpdateInfoForDynamicOpcode(VOID)585 CVfrCompiler::UpdateInfoForDynamicOpcode (
586   VOID
587   )
588 {
589   SIfrRecord          *pRecord;
590 
591   if (!gNeedAdjustOpcode) {
592     return;
593   }
594 
595   //
596   // Base on the original offset info to update the record list.
597   //
598   if (!gCIfrRecordInfoDB.IfrAdjustDynamicOpcodeInRecords()) {
599     DebugError (NULL, 0, 1001, "Error parsing vfr file", "Can find the offset in the record.");
600   }
601 
602   //
603   // Base on the opcode binary length to recalculate the offset for each opcode.
604   //
605   gCIfrRecordInfoDB.IfrAdjustOffsetForRecord();
606 
607   //
608   // Base on the offset to find the binary address.
609   //
610   pRecord = gCIfrRecordInfoDB.GetRecordInfoFromOffset(gAdjustOpcodeOffset);
611   while (pRecord != NULL) {
612     pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset);
613     if (pRecord->mIfrBinBuf == NULL) {
614       DebugError (NULL, 0, 0001, "Error parsing vfr file", " 0x%X. offset not allocated.", pRecord->mOffset);
615     }
616     pRecord = pRecord->mNext;
617   }
618 }
619 
620 VOID
AdjustBin(VOID)621 CVfrCompiler::AdjustBin (
622   VOID
623   )
624 {
625   EFI_VFR_RETURN_CODE Status;
626 
627   if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
628     return;
629   }
630 
631   UpdateInfoForDynamicOpcode ();
632 
633   //
634   // Check Binary Code consistent between Form and IfrRecord
635   //
636 
637   //
638   // Get Package Data and IfrRecord Data
639   //
640   gCFormPkg.BuildPkg (gCBuffer);
641   gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer);
642 
643   //
644   // Compare Form and Record data
645   //
646   if (gCBuffer.Buffer != NULL && gRBuffer.Buffer != NULL) {
647     UINT32 Index;
648     if (gCBuffer.Size != gRBuffer.Size) {
649       DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. FormBinary Size 0x%X is not same to RecordBuffer Size 0x%X", mOptions.VfrFileName, gCBuffer.Size, gRBuffer.Size);
650     }
651     for (Index = 0; Index < gCBuffer.Size; Index ++) {
652       if (gCBuffer.Buffer[Index] != gRBuffer.Buffer[Index]) {
653         break;
654       }
655     }
656     if (Index != gCBuffer.Size) {
657       DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions.VfrFileName, Index);
658     }
659     DebugMsg (NULL, 0, 9, (CHAR8 *) "IFR Buffer", (CHAR8 *) "Form Buffer same to Record Buffer and Size is 0x%X", Index);
660   } else if (gCBuffer.Buffer == NULL && gRBuffer.Buffer == NULL) {
661     //ok
662   } else {
663     DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions.VfrFileName);
664   }
665 
666   //
667   // For UEFI mode, not do OpCode Adjust
668   //
669   if (mOptions.CompatibleMode) {
670     //
671     // Adjust Opcode to be compatible with framework vfr
672     //
673     Status = gCIfrRecordInfoDB.IfrRecordAdjust ();
674     if (Status != VFR_RETURN_SUCCESS) {
675       //
676       // Record List Adjust Failed
677       //
678       SET_RUN_STATUS (STATUS_FAILED);
679       return;
680     }
681     //
682     // Re get the IfrRecord Buffer.
683     //
684     gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer);
685   }
686 
687   return;
688 }
689 
690 VOID
GenBinary(VOID)691 CVfrCompiler::GenBinary (
692   VOID
693   )
694 {
695   FILE                    *pFile = NULL;
696 
697   if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
698     goto Fail;
699   }
700 
701   if (mOptions.CreateIfrPkgFile == TRUE) {
702     if ((pFile = fopen (LongFilePath (mOptions.PkgOutputFileName), "wb")) == NULL) {
703       DebugError (NULL, 0, 0001, "Error opening file", mOptions.PkgOutputFileName);
704       goto Fail;
705     }
706     if (gCFormPkg.BuildPkg (pFile, &gRBuffer) != VFR_RETURN_SUCCESS) {
707       fclose (pFile);
708       goto Fail;
709     }
710     fclose (pFile);
711   }
712 
713   SET_RUN_STATUS (STATUS_GENBINARY);
714 
715   return;
716 
717 Fail:
718   if (!IS_RUN_STATUS(STATUS_DEAD)) {
719     SET_RUN_STATUS (STATUS_FAILED);
720   }
721 }
722 
723 static const char *gSourceFileHeader[] = {
724   "//",
725   "//  DO NOT EDIT -- auto-generated file",
726   "//",
727   "//  This file is generated by the vfrcompiler utility",
728   "//",
729   NULL
730 };
731 
732 VOID
GenCFile(VOID)733 CVfrCompiler::GenCFile (
734   VOID
735   )
736 {
737   FILE                    *pFile;
738   UINT32                  Index;
739 
740   if (!IS_RUN_STATUS(STATUS_GENBINARY)) {
741     goto Fail;
742   }
743 
744   if (!mOptions.CreateIfrPkgFile || mOptions.CompatibleMode) {
745     if ((pFile = fopen (LongFilePath (mOptions.COutputFileName), "w")) == NULL) {
746       DebugError (NULL, 0, 0001, "Error opening output C file", mOptions.COutputFileName);
747       goto Fail;
748     }
749 
750     for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) {
751       fprintf (pFile, "%s\n", gSourceFileHeader[Index]);
752     }
753 
754     if (mOptions.CompatibleMode) {
755       gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName);
756     }
757 
758     if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile, &gRBuffer) != VFR_RETURN_SUCCESS) {
759       fclose (pFile);
760       goto Fail;
761     }
762     fclose (pFile);
763   }
764 
765   SET_RUN_STATUS (STATUS_FINISHED);
766   return;
767 
768 Fail:
769   if (!IS_RUN_STATUS(STATUS_DEAD)) {
770     SET_RUN_STATUS (STATUS_FAILED);
771   }
772 }
773 
774 VOID
GenRecordListFile(VOID)775 CVfrCompiler::GenRecordListFile (
776   VOID
777   )
778 {
779   CHAR8  *InFileName = NULL;
780   FILE   *pInFile    = NULL;
781   FILE   *pOutFile   = NULL;
782   CHAR8  LineBuf[MAX_VFR_LINE_LEN];
783   UINT32 LineNo;
784 
785   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
786 
787   if (mOptions.CreateRecordListFile == TRUE) {
788     if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) {
789       return;
790     }
791 
792     if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) {
793       DebugError (NULL, 0, 0001, "Error opening the input VFR preprocessor output file", InFileName);
794       return;
795     }
796 
797     if ((pOutFile = fopen (LongFilePath (mOptions.RecordListFile), "w")) == NULL) {
798       DebugError (NULL, 0, 0001, "Error opening the record list file", mOptions.RecordListFile);
799       goto Err1;
800     }
801 
802     fprintf (pOutFile, "//\n//  VFR compiler version " VFR_COMPILER_VERSION __BUILD_VERSION "\n//\n");
803     LineNo = 0;
804     while (!feof (pInFile)) {
805       if (fgets (LineBuf, MAX_VFR_LINE_LEN, pInFile) != NULL) {
806         fprintf (pOutFile, "%s", LineBuf);
807         LineNo++;
808         gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo);
809       }
810     }
811 
812     fprintf (pOutFile, "\n//\n// All Opcode Record List \n//\n");
813     gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, 0);
814     gCVfrVarDataTypeDB.Dump(pOutFile);
815 
816     fclose (pOutFile);
817     fclose (pInFile);
818   }
819 
820   return;
821 
822 Err1:
823   fclose (pInFile);
824 }
825 
826 int
main(IN int Argc,IN char ** Argv)827 main (
828   IN int             Argc,
829   IN char            **Argv
830   )
831 {
832   COMPILER_RUN_STATUS  Status;
833 
834   SetPrintLevel(WARNING_LOG_LEVEL);
835   CVfrCompiler         Compiler(Argc, Argv);
836 
837   Compiler.PreProcess();
838   Compiler.Compile();
839   Compiler.AdjustBin();
840   Compiler.GenBinary();
841   Compiler.GenCFile();
842   Compiler.GenRecordListFile ();
843 
844   Status = Compiler.RunStatus ();
845   if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) {
846     return 2;
847   }
848 
849   if (gCBuffer.Buffer != NULL) {
850     delete gCBuffer.Buffer;
851   }
852 
853   if (gRBuffer.Buffer != NULL) {
854     delete gRBuffer.Buffer;
855   }
856 
857   return GetUtilityStatus ();
858 }
859 
860 
861