1 /** @file
2 
3   VfrCompiler main class and main function.
4 
5 Copyright (c) 2004 - 2016, 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                   = NULL;
72   mOptions.RecordListFile                = NULL;
73   mOptions.CreateRecordListFile          = FALSE;
74   mOptions.CreateIfrPkgFile              = FALSE;
75   mOptions.PkgOutputFileName             = NULL;
76   mOptions.COutputFileName               = NULL;
77   mOptions.OutputDirectory               = NULL;
78   mOptions.PreprocessorOutputFileName    = NULL;
79   mOptions.VfrBaseFileName               = NULL;
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   mOptions.AutoDefault                   = FALSE;
87   mOptions.CheckDefault                  = FALSE;
88   memset (&mOptions.OverrideClassGuid, 0, sizeof (EFI_GUID));
89 
90   if (Argc == 1) {
91     Usage ();
92     SET_RUN_STATUS (STATUS_DEAD);
93     return;
94   }
95 
96   for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) {
97     if ((stricmp(Argv[Index], "-h") == 0) || (stricmp(Argv[Index], "--help") == 0)) {
98       Usage ();
99       SET_RUN_STATUS (STATUS_DEAD);
100       return;
101     } else if (stricmp(Argv[Index], "--version") == 0) {
102       Version ();
103       SET_RUN_STATUS (STATUS_DEAD);
104       return;
105     } else if (stricmp(Argv[Index], "-l") == 0) {
106       mOptions.CreateRecordListFile = TRUE;
107       gCIfrRecordInfoDB.TurnOn ();
108     } else if (stricmp(Argv[Index], "-i") == 0) {
109       Index++;
110       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
111         DebugError (NULL, 0, 1001, "Missing option", "-i missing path argument");
112         goto Fail;
113       }
114 
115       AppendIncludePath(Argv[Index]);
116     } else if (stricmp(Argv[Index], "-o") == 0 || stricmp(Argv[Index], "--output-directory") == 0 || stricmp(Argv[Index], "-od") == 0) {
117       Index++;
118       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
119         DebugError (NULL, 0, 1001, "Missing option", "-o missing output directory name");
120         goto Fail;
121       }
122       if (strlen (Argv[Index]) > MAX_PATH - 1) {
123         DebugError (NULL, 0, 1003, "Invalid option value", "Output directory name %s is too long", Argv[Index]);
124         goto Fail;
125       }
126 
127       mOptions.OutputDirectory = (CHAR8 *) malloc (strlen (Argv[Index]) + strlen ("\\") + 1);
128       if (mOptions.OutputDirectory == NULL) {
129         DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
130         goto Fail;
131       }
132       strcpy (mOptions.OutputDirectory, Argv[Index]);
133 
134       CHAR8 lastChar = mOptions.OutputDirectory[strlen(mOptions.OutputDirectory) - 1];
135       if ((lastChar != '/') && (lastChar != '\\')) {
136         if (strchr(mOptions.OutputDirectory, '/') != NULL) {
137           strcat (mOptions.OutputDirectory, "/");
138         } else {
139           strcat (mOptions.OutputDirectory, "\\");
140         }
141       }
142       DebugMsg (NULL, 0, 9, (CHAR8 *) "Output Directory", (CHAR8 *) "%s", mOptions.OutputDirectory);
143     } else if (stricmp(Argv[Index], "-b") == 0 || stricmp(Argv[Index], "--create-ifr-package") == 0 || stricmp(Argv[Index], "-ibin") == 0) {
144       mOptions.CreateIfrPkgFile = TRUE;
145     } else if (stricmp(Argv[Index], "-n") == 0 || stricmp(Argv[Index], "--no-pre-processing") == 0 || stricmp(Argv[Index], "-nopp") == 0) {
146       mOptions.SkipCPreprocessor = TRUE;
147     } else if (stricmp(Argv[Index], "-f") == 0 || stricmp(Argv[Index], "--pre-processing-flag") == 0 || stricmp(Argv[Index], "-ppflag") == 0) {
148       Index++;
149       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
150         DebugError (NULL, 0, 1001, "Missing option", "-od - missing C-preprocessor argument");
151         goto Fail;
152       }
153 
154       AppendCPreprocessorOptions (Argv[Index]);
155     } else if (stricmp(Argv[Index], "-c") == 0 || stricmp(Argv[Index], "--compatible-framework") == 0) {
156       mOptions.CompatibleMode = TRUE;
157     } else if (stricmp(Argv[Index], "-s") == 0|| stricmp(Argv[Index], "--string-db") == 0) {
158       Index++;
159       if ((Index >= Argc) || (Argv[Index][0] == '-')) {
160         DebugError (NULL, 0, 1001, "Missing option", "-s missing input string file name");
161         goto Fail;
162       }
163       gCVfrStringDB.SetStringFileName(Argv[Index]);
164       DebugMsg (NULL, 0, 9, (CHAR8 *) "Input string file path", (CHAR8 *) "%s", Argv[Index]);
165     } else if ((stricmp (Argv[Index], "-g") == 0) || (stricmp (Argv[Index], "--guid") == 0)) {
166       Index++;
167       Status = StringToGuid (Argv[Index], &mOptions.OverrideClassGuid);
168       if (EFI_ERROR (Status)) {
169         DebugError (NULL, 0, 1000, "Invalid format:", "%s", Argv[Index]);
170         goto Fail;
171       }
172       mOptions.HasOverrideClassGuid = TRUE;
173     } else if (stricmp(Argv[Index], "-w") == 0 || stricmp(Argv[Index], "--warning-as-error") == 0) {
174       mOptions.WarningAsError = TRUE;
175     } else if (stricmp(Argv[Index], "-a") == 0 ||stricmp(Argv[Index], "--autodefault") == 0) {
176       mOptions.AutoDefault = TRUE;
177     } else if (stricmp(Argv[Index], "-d") == 0 ||stricmp(Argv[Index], "--checkdefault") == 0) {
178       mOptions.CheckDefault = TRUE;
179     } else {
180       DebugError (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]);
181       goto Fail;
182     }
183   }
184 
185   if (Index != Argc - 1) {
186     DebugError (NULL, 0, 1001, "Missing option", "VFR file name is not specified.");
187     goto Fail;
188   } else {
189     if (strlen (Argv[Index]) > MAX_PATH) {
190       DebugError (NULL, 0, 1003, "Invalid option value", "VFR file name %s is too long.", Argv[Index]);
191       goto Fail;
192     }
193     mOptions.VfrFileName = (CHAR8 *) malloc (strlen (Argv[Index]) + 1);
194     if (mOptions.VfrFileName == NULL) {
195       DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
196       goto Fail;
197     }
198     strcpy (mOptions.VfrFileName, Argv[Index]);
199 
200     if (mOptions.OutputDirectory == NULL) {
201       mOptions.OutputDirectory = (CHAR8 *) malloc (1);
202       if (mOptions.OutputDirectory == NULL) {
203         DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
204         goto Fail;
205       }
206       mOptions.OutputDirectory[0] = '\0';
207     }
208   }
209 
210   if (SetBaseFileName() != 0) {
211     goto Fail;
212   }
213   if (SetPkgOutputFileName () != 0) {
214     goto Fail;
215   }
216   if (SetCOutputFileName() != 0) {
217     goto Fail;
218   }
219   if (SetPreprocessorOutputFileName () != 0) {
220     goto Fail;
221   }
222   if (SetRecordListFileName () != 0) {
223     goto Fail;
224   }
225   return;
226 
227 Fail:
228   SET_RUN_STATUS (STATUS_DEAD);
229 
230   mOptions.CreateRecordListFile          = FALSE;
231   mOptions.CreateIfrPkgFile              = FALSE;
232 
233   if (mOptions.VfrFileName != NULL) {
234     free (mOptions.VfrFileName);
235     mOptions.VfrFileName                 = NULL;
236   }
237   if (mOptions.VfrBaseFileName != NULL) {
238     free (mOptions.VfrBaseFileName);
239     mOptions.VfrBaseFileName             = NULL;
240   }
241   if (mOptions.OutputDirectory != NULL) {
242     free (mOptions.OutputDirectory);
243     mOptions.OutputDirectory             = NULL;
244   }
245   if (mOptions.PkgOutputFileName != NULL) {
246     free (mOptions.PkgOutputFileName);
247     mOptions.PkgOutputFileName           = NULL;
248   }
249   if (mOptions.COutputFileName != NULL) {
250     free (mOptions.COutputFileName);
251     mOptions.COutputFileName             = NULL;
252   }
253   if (mOptions.PreprocessorOutputFileName != NULL) {
254     free (mOptions.PreprocessorOutputFileName);
255     mOptions.PreprocessorOutputFileName  = NULL;
256   }
257   if (mOptions.RecordListFile != NULL) {
258     free (mOptions.RecordListFile);
259     mOptions.RecordListFile              = NULL;
260   }
261   if (mOptions.IncludePaths != NULL) {
262     delete mOptions.IncludePaths;
263     mOptions.IncludePaths                = NULL;
264   }
265   if (mOptions.CPreprocessorOptions != NULL) {
266     delete mOptions.CPreprocessorOptions;
267     mOptions.CPreprocessorOptions        = NULL;
268   }
269 }
270 
271 VOID
AppendIncludePath(IN CHAR8 * PathStr)272 CVfrCompiler::AppendIncludePath (
273   IN CHAR8      *PathStr
274   )
275 {
276   UINT32  Len           = 0;
277   CHAR8   *IncludePaths = NULL;
278 
279   Len = strlen (" -I ") + strlen (PathStr) + 1;
280   if (mOptions.IncludePaths != NULL) {
281     Len += strlen (mOptions.IncludePaths);
282   }
283   IncludePaths = new CHAR8[Len];
284   if (IncludePaths == NULL) {
285     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
286     return;
287   }
288   IncludePaths[0] = '\0';
289   if (mOptions.IncludePaths != NULL) {
290     strcat (IncludePaths, mOptions.IncludePaths);
291   }
292   strcat (IncludePaths, " -I ");
293   strcat (IncludePaths, PathStr);
294   if (mOptions.IncludePaths != NULL) {
295     delete mOptions.IncludePaths;
296   }
297   mOptions.IncludePaths = IncludePaths;
298 }
299 
300 VOID
AppendCPreprocessorOptions(IN CHAR8 * Options)301 CVfrCompiler::AppendCPreprocessorOptions (
302   IN CHAR8      *Options
303   )
304 {
305   UINT32  Len           = 0;
306   CHAR8   *Opt          = NULL;
307 
308   Len = strlen (Options) + strlen (" ") + 1;
309   if (mOptions.CPreprocessorOptions != NULL) {
310     Len += strlen (mOptions.CPreprocessorOptions);
311   }
312   Opt = new CHAR8[Len];
313   if (Opt == NULL) {
314     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
315     return;
316   }
317   Opt[0] = 0;
318   if (mOptions.CPreprocessorOptions != NULL) {
319     strcat (Opt, mOptions.CPreprocessorOptions);
320   }
321   strcat (Opt, " ");
322   strcat (Opt, Options);
323   if (mOptions.CPreprocessorOptions != NULL) {
324     delete mOptions.CPreprocessorOptions;
325   }
326   mOptions.CPreprocessorOptions = Opt;
327 }
328 
329 INT8
SetBaseFileName(VOID)330 CVfrCompiler::SetBaseFileName (
331   VOID
332   )
333 {
334   CHAR8         *pFileName, *pPath, *pExt;
335 
336   if (mOptions.VfrFileName == NULL) {
337     return -1;
338   }
339 
340   pFileName = mOptions.VfrFileName;
341   while (
342     ((pPath = strchr (pFileName, '\\')) != NULL) ||
343     ((pPath = strchr (pFileName, '/')) != NULL)
344     )
345   {
346     pFileName = pPath + 1;
347   }
348 
349   if (pFileName == NULL) {
350     return -1;
351   }
352 
353   if ((pExt = strchr (pFileName, '.')) == NULL) {
354     return -1;
355   }
356 
357   *pExt = '\0';
358   if (strlen (pFileName) > MAX_PATH - 1) {
359     *pExt = '.';
360     return -1;
361   }
362 
363   mOptions.VfrBaseFileName = (CHAR8 *) malloc (strlen (pFileName) + 1);
364   if (mOptions.VfrBaseFileName == NULL) {
365     *pExt = '.';
366     return -1;
367   }
368 
369   strcpy (mOptions.VfrBaseFileName, pFileName);
370   *pExt = '.';
371 
372   return 0;
373 }
374 
375 INT8
SetPkgOutputFileName(VOID)376 CVfrCompiler::SetPkgOutputFileName (
377   VOID
378   )
379 {
380   INTN Length;
381 
382   if (mOptions.VfrBaseFileName == NULL) {
383     return -1;
384   }
385 
386   Length = strlen (mOptions.OutputDirectory) +
387            strlen (mOptions.VfrBaseFileName) +
388            strlen (VFR_PACKAGE_FILENAME_EXTENSION) +
389            1;
390   if (Length > MAX_PATH) {
391     return -1;
392   }
393 
394   mOptions.PkgOutputFileName = (CHAR8 *) malloc (Length);
395   if (mOptions.PkgOutputFileName == NULL) {
396     return -1;
397   }
398 
399   strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory);
400   strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName);
401   strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION);
402 
403   return 0;
404 }
405 
406 INT8
SetCOutputFileName(VOID)407 CVfrCompiler::SetCOutputFileName (
408   VOID
409   )
410 {
411   INTN Length;
412 
413   if (mOptions.VfrBaseFileName == NULL) {
414     return -1;
415   }
416 
417   Length = strlen (mOptions.OutputDirectory) +
418            strlen (mOptions.VfrBaseFileName) +
419            strlen (".c") +
420            1;
421   if (Length > MAX_PATH) {
422     return -1;
423   }
424 
425   mOptions.COutputFileName = (CHAR8 *) malloc (Length);
426   if (mOptions.COutputFileName == NULL) {
427     return -1;
428   }
429 
430   strcpy (mOptions.COutputFileName, mOptions.OutputDirectory);
431   strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName);
432   strcat (mOptions.COutputFileName, ".c");
433 
434   return 0;
435 }
436 
437 INT8
SetPreprocessorOutputFileName(VOID)438 CVfrCompiler::SetPreprocessorOutputFileName (
439   VOID
440   )
441 {
442   INTN Length;
443 
444   if (mOptions.VfrBaseFileName == NULL) {
445     return -1;
446   }
447 
448   Length = strlen (mOptions.OutputDirectory) +
449            strlen (mOptions.VfrBaseFileName) +
450            strlen (VFR_PREPROCESS_FILENAME_EXTENSION) +
451            1;
452   if (Length > MAX_PATH) {
453     return -1;
454   }
455 
456   mOptions.PreprocessorOutputFileName = (CHAR8 *) malloc (Length);
457   if (mOptions.PreprocessorOutputFileName == NULL) {
458     return -1;
459   }
460 
461   strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory);
462   strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName);
463   strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);
464 
465   return 0;
466 }
467 
468 INT8
SetRecordListFileName(VOID)469 CVfrCompiler::SetRecordListFileName (
470   VOID
471   )
472 {
473   INTN Length;
474 
475   if (mOptions.VfrBaseFileName == NULL) {
476     return -1;
477   }
478 
479   Length = strlen (mOptions.OutputDirectory) +
480            strlen (mOptions.VfrBaseFileName) +
481            strlen (VFR_RECORDLIST_FILENAME_EXTENSION) +
482            1;
483   if (Length > MAX_PATH) {
484     return -1;
485   }
486 
487   mOptions.RecordListFile = (CHAR8 *) malloc (Length);
488   if (mOptions.RecordListFile == NULL) {
489     return -1;
490   }
491 
492   strcpy (mOptions.RecordListFile, mOptions.OutputDirectory);
493   strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName);
494   strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION);
495 
496   return 0;
497 }
498 
CVfrCompiler(IN INT32 Argc,IN CHAR8 ** Argv)499 CVfrCompiler::CVfrCompiler (
500   IN INT32      Argc,
501   IN CHAR8      **Argv
502   )
503 {
504   mPreProcessCmd = (CHAR8 *) PREPROCESSOR_COMMAND;
505   mPreProcessOpt = (CHAR8 *) PREPROCESSOR_OPTIONS;
506 
507   SET_RUN_STATUS (STATUS_STARTED);
508 
509   OptionInitialization(Argc, Argv);
510 
511   if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) {
512     return;
513   }
514 
515   SET_RUN_STATUS(STATUS_INITIALIZED);
516 }
517 
~CVfrCompiler(VOID)518 CVfrCompiler::~CVfrCompiler (
519   VOID
520   )
521 {
522   if (mOptions.VfrFileName != NULL) {
523     free (mOptions.VfrFileName);
524     mOptions.VfrFileName = NULL;
525   }
526 
527   if (mOptions.VfrBaseFileName != NULL) {
528     free (mOptions.VfrBaseFileName);
529     mOptions.VfrBaseFileName = NULL;
530   }
531 
532   if (mOptions.OutputDirectory != NULL) {
533     free (mOptions.OutputDirectory);
534     mOptions.OutputDirectory = NULL;
535   }
536 
537   if (mOptions.PkgOutputFileName != NULL) {
538     free (mOptions.PkgOutputFileName);
539     mOptions.PkgOutputFileName = NULL;
540   }
541 
542   if (mOptions.COutputFileName != NULL) {
543     free (mOptions.COutputFileName);
544     mOptions.COutputFileName = NULL;
545   }
546 
547   if (mOptions.PreprocessorOutputFileName != NULL) {
548     free (mOptions.PreprocessorOutputFileName);
549     mOptions.PreprocessorOutputFileName = NULL;
550   }
551 
552   if (mOptions.RecordListFile != NULL) {
553     free (mOptions.RecordListFile);
554     mOptions.RecordListFile = NULL;
555   }
556 
557   if (mOptions.IncludePaths != NULL) {
558     delete mOptions.IncludePaths;
559     mOptions.IncludePaths = NULL;
560   }
561 
562   if (mOptions.CPreprocessorOptions != NULL) {
563     delete mOptions.CPreprocessorOptions;
564     mOptions.CPreprocessorOptions = NULL;
565   }
566 
567   SET_RUN_STATUS(STATUS_DEAD);
568 }
569 
570 VOID
Usage(VOID)571 CVfrCompiler::Usage (
572   VOID
573   )
574 {
575   UINT32 Index;
576   CONST  CHAR8 *Help[] = {
577     " ",
578     "VfrCompile version " VFR_COMPILER_VERSION "Build " __BUILD_VERSION,
579     "Copyright (c) 2004-2016 Intel Corporation. All rights reserved.",
580     " ",
581     "Usage: VfrCompile [options] VfrFile",
582     " ",
583     "Options:",
584     "  -h, --help     prints this help",
585     "  --version      prints version info",
586     "  -l             create an output IFR listing file",
587     "  -o DIR, --output-directory DIR",
588     "                 deposit all output files to directory OutputDir",
589     "                 default is current directory",
590     "  -b, --create-ifr-package",
591     "                 create an IFR HII pack file",
592     "  -n, --no-pre-processing",
593     "                 do not preprocessing input file",
594     "  -c, --compatible-framework",
595     "                 compatible framework vfr file",
596     "  -s, --string-db",
597     "                 input uni string package file",
598     "  -g, --guid",
599     "                 override class guid input",
600     "                 format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
601     "  -w  --warning-as-error",
602     "                 treat warning as an error",
603     "  -a  --autodefaut    generate default value for question opcode if some default is missing",
604     "  -d  --checkdefault  check the default information in a question opcode",
605     NULL
606     };
607   for (Index = 0; Help[Index] != NULL; Index++) {
608     fprintf (stdout, "%s\n", Help[Index]);
609   }
610 }
611 
612 VOID
Version(VOID)613 CVfrCompiler::Version (
614   VOID
615   )
616 {
617   UINT32 Index;
618   CONST  CHAR8 *Help[] = {
619     "VfrCompile version " VFR_COMPILER_VERSION "Build " __BUILD_VERSION,
620     NULL
621     };
622   for (Index = 0; Help[Index] != NULL; Index++) {
623     fprintf (stdout, "%s\n", Help[Index]);
624   }
625 }
626 
627 VOID
PreProcess(VOID)628 CVfrCompiler::PreProcess (
629   VOID
630   )
631 {
632   FILE    *pVfrFile      = NULL;
633   UINT32  CmdLen         = 0;
634   CHAR8   *PreProcessCmd = NULL;
635 
636   if (!IS_RUN_STATUS(STATUS_INITIALIZED)) {
637     goto Fail;
638   }
639 
640   if (mOptions.SkipCPreprocessor == TRUE) {
641     goto Out;
642   }
643 
644   if ((pVfrFile = fopen (LongFilePath (mOptions.VfrFileName), "r")) == NULL) {
645     DebugError (NULL, 0, 0001, "Error opening the input VFR file", mOptions.VfrFileName);
646     goto Fail;
647   }
648   fclose (pVfrFile);
649 
650   CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) +
651   	       strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName);
652   if (mOptions.CPreprocessorOptions != NULL) {
653     CmdLen += strlen (mOptions.CPreprocessorOptions);
654   }
655   if (mOptions.IncludePaths != NULL) {
656     CmdLen += strlen (mOptions.IncludePaths);
657   }
658 
659   PreProcessCmd = new CHAR8[CmdLen + 10];
660   if (PreProcessCmd == NULL) {
661     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);
662     goto Fail;
663   }
664   strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " ");
665   strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " ");
666   if (mOptions.IncludePaths != NULL) {
667     strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " ");
668   }
669   if (mOptions.CPreprocessorOptions != NULL) {
670     strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " ");
671   }
672   strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > ");
673   strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName);
674 
675   if (system (PreProcessCmd) != 0) {
676     DebugError (NULL, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd);
677     goto Fail;
678   }
679 
680   delete[] PreProcessCmd;
681 
682 Out:
683   SET_RUN_STATUS (STATUS_PREPROCESSED);
684   return;
685 
686 Fail:
687   if (!IS_RUN_STATUS(STATUS_DEAD)) {
688     SET_RUN_STATUS (STATUS_FAILED);
689   }
690   delete[] PreProcessCmd;
691 }
692 
693 extern UINT8 VfrParserStart (IN FILE *, IN INPUT_INFO_TO_SYNTAX *);
694 
695 VOID
Compile(VOID)696 CVfrCompiler::Compile (
697   VOID
698   )
699 {
700   FILE  *pInFile    = NULL;
701   CHAR8 *InFileName = NULL;
702   INPUT_INFO_TO_SYNTAX InputInfo;
703 
704   if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) {
705     goto Fail;
706   }
707 
708   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
709 
710   gCVfrErrorHandle.SetInputFile (InFileName);
711   gCVfrErrorHandle.SetWarningAsError(mOptions.WarningAsError);
712 
713   if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) {
714     DebugError (NULL, 0, 0001, "Error opening the input file", InFileName);
715     goto Fail;
716   }
717 
718   InputInfo.CompatibleMode = mOptions.CompatibleMode;
719   if (mOptions.HasOverrideClassGuid) {
720     InputInfo.OverrideClassGuid = &mOptions.OverrideClassGuid;
721   } else {
722     InputInfo.OverrideClassGuid = NULL;
723   }
724 
725   if (VfrParserStart (pInFile, &InputInfo) != 0) {
726     goto Fail;
727   }
728 
729   fclose (pInFile);
730 
731   if (gCFormPkg.HavePendingUnassigned () == TRUE) {
732     gCFormPkg.PendingAssignPrintAll ();
733     goto Fail;
734   }
735 
736   SET_RUN_STATUS (STATUS_COMPILEED);
737   return;
738 
739 Fail:
740   if (!IS_RUN_STATUS(STATUS_DEAD)) {
741     DebugError (NULL, 0, 0003, "Error parsing", "compile error in file %s", InFileName);
742     SET_RUN_STATUS (STATUS_FAILED);
743   }
744   if (pInFile != NULL) {
745     fclose (pInFile);
746   }
747 }
748 
749 VOID
AdjustBin(VOID)750 CVfrCompiler::AdjustBin (
751   VOID
752   )
753 {
754   EFI_VFR_RETURN_CODE Status;
755 
756   if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
757     return;
758   }
759 
760   if (gNeedAdjustOpcode) {
761     //
762     // When parsing the Vfr, has created some opcodes, now need to update the record info.
763     //
764     gCIfrRecordInfoDB.IfrUpdateRecordInfoForDynamicOpcode (FALSE);
765   }
766 
767   //
768   // Check whether need to check default info for question or auto add default for question.
769   //
770   if (mOptions.AutoDefault || mOptions.CheckDefault) {
771     gCIfrRecordInfoDB.IfrCheckAddDefaultRecord (mOptions.AutoDefault, mOptions.CheckDefault);
772   }
773 
774   //
775   // Check Binary Code consistent between Form and IfrRecord
776   //
777 
778   //
779   // Get Package Data and IfrRecord Data
780   //
781   gCFormPkg.BuildPkg (gCBuffer);
782   gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer);
783 
784   //
785   // Compare Form and Record data
786   //
787   if (gCBuffer.Buffer != NULL && gRBuffer.Buffer != NULL) {
788     UINT32 Index;
789     if (gCBuffer.Size != gRBuffer.Size) {
790       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);
791     }
792     for (Index = 0; Index < gCBuffer.Size; Index ++) {
793       if (gCBuffer.Buffer[Index] != gRBuffer.Buffer[Index]) {
794         break;
795       }
796     }
797     if (Index != gCBuffer.Size) {
798       DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions.VfrFileName, Index);
799     }
800     DebugMsg (NULL, 0, 9, (CHAR8 *) "IFR Buffer", (CHAR8 *) "Form Buffer same to Record Buffer and Size is 0x%X", Index);
801   } else if (gCBuffer.Buffer == NULL && gRBuffer.Buffer == NULL) {
802     //ok
803   } else {
804     DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions.VfrFileName);
805   }
806 
807   //
808   // For UEFI mode, not do OpCode Adjust
809   //
810   if (mOptions.CompatibleMode) {
811     //
812     // Adjust Opcode to be compatible with framework vfr
813     //
814     Status = gCIfrRecordInfoDB.IfrRecordAdjust ();
815     if (Status != VFR_RETURN_SUCCESS) {
816       //
817       // Record List Adjust Failed
818       //
819       SET_RUN_STATUS (STATUS_FAILED);
820       return;
821     }
822     //
823     // Re get the IfrRecord Buffer.
824     //
825     gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer);
826   }
827 
828   return;
829 }
830 
831 VOID
GenBinary(VOID)832 CVfrCompiler::GenBinary (
833   VOID
834   )
835 {
836   FILE                    *pFile = NULL;
837 
838   if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
839     goto Fail;
840   }
841 
842   if (mOptions.CreateIfrPkgFile == TRUE) {
843     if ((pFile = fopen (LongFilePath (mOptions.PkgOutputFileName), "wb")) == NULL) {
844       DebugError (NULL, 0, 0001, "Error opening file", mOptions.PkgOutputFileName);
845       goto Fail;
846     }
847     if (gCFormPkg.BuildPkg (pFile, &gRBuffer) != VFR_RETURN_SUCCESS) {
848       fclose (pFile);
849       goto Fail;
850     }
851     fclose (pFile);
852   }
853 
854   SET_RUN_STATUS (STATUS_GENBINARY);
855 
856   return;
857 
858 Fail:
859   if (!IS_RUN_STATUS(STATUS_DEAD)) {
860     SET_RUN_STATUS (STATUS_FAILED);
861   }
862 }
863 
864 static const char *gSourceFileHeader[] = {
865   "//",
866   "//  DO NOT EDIT -- auto-generated file",
867   "//",
868   "//  This file is generated by the vfrcompiler utility",
869   "//",
870   NULL
871 };
872 
873 VOID
GenCFile(VOID)874 CVfrCompiler::GenCFile (
875   VOID
876   )
877 {
878   FILE                    *pFile;
879   UINT32                  Index;
880 
881   if (!IS_RUN_STATUS(STATUS_GENBINARY)) {
882     goto Fail;
883   }
884 
885   if (!mOptions.CreateIfrPkgFile || mOptions.CompatibleMode) {
886     if ((pFile = fopen (LongFilePath (mOptions.COutputFileName), "w")) == NULL) {
887       DebugError (NULL, 0, 0001, "Error opening output C file", mOptions.COutputFileName);
888       goto Fail;
889     }
890 
891     for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) {
892       fprintf (pFile, "%s\n", gSourceFileHeader[Index]);
893     }
894 
895     if (mOptions.CompatibleMode) {
896       gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName);
897     }
898 
899     if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile, &gRBuffer) != VFR_RETURN_SUCCESS) {
900       fclose (pFile);
901       goto Fail;
902     }
903     fclose (pFile);
904   }
905 
906   SET_RUN_STATUS (STATUS_FINISHED);
907   return;
908 
909 Fail:
910   if (!IS_RUN_STATUS(STATUS_DEAD)) {
911     SET_RUN_STATUS (STATUS_FAILED);
912   }
913 }
914 
915 VOID
GenRecordListFile(VOID)916 CVfrCompiler::GenRecordListFile (
917   VOID
918   )
919 {
920   CHAR8  *InFileName = NULL;
921   FILE   *pInFile    = NULL;
922   FILE   *pOutFile   = NULL;
923   CHAR8  LineBuf[MAX_VFR_LINE_LEN];
924   UINT32 LineNo;
925 
926   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
927 
928   if (mOptions.CreateRecordListFile == TRUE) {
929     if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) {
930       return;
931     }
932 
933     if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) {
934       DebugError (NULL, 0, 0001, "Error opening the input VFR preprocessor output file", InFileName);
935       return;
936     }
937 
938     if ((pOutFile = fopen (LongFilePath (mOptions.RecordListFile), "w")) == NULL) {
939       DebugError (NULL, 0, 0001, "Error opening the record list file", mOptions.RecordListFile);
940       goto Err1;
941     }
942 
943     fprintf (pOutFile, "//\n//  VFR compiler version " VFR_COMPILER_VERSION __BUILD_VERSION "\n//\n");
944     LineNo = 0;
945     while (!feof (pInFile)) {
946       if (fgets (LineBuf, MAX_VFR_LINE_LEN, pInFile) != NULL) {
947         fprintf (pOutFile, "%s", LineBuf);
948         LineNo++;
949         gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo);
950       }
951     }
952 
953     fprintf (pOutFile, "\n//\n// All Opcode Record List \n//\n");
954     gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, 0);
955     gCVfrVarDataTypeDB.Dump(pOutFile);
956 
957     fclose (pOutFile);
958     fclose (pInFile);
959   }
960 
961   return;
962 
963 Err1:
964   fclose (pInFile);
965 }
966 
967 int
main(IN int Argc,IN char ** Argv)968 main (
969   IN int             Argc,
970   IN char            **Argv
971   )
972 {
973   COMPILER_RUN_STATUS  Status;
974 
975   SetPrintLevel(WARNING_LOG_LEVEL);
976   CVfrCompiler         Compiler(Argc, Argv);
977 
978   Compiler.PreProcess();
979   Compiler.Compile();
980   Compiler.AdjustBin();
981   Compiler.GenBinary();
982   Compiler.GenCFile();
983   Compiler.GenRecordListFile ();
984 
985   Status = Compiler.RunStatus ();
986   if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) {
987     return 2;
988   }
989 
990   if (gCBuffer.Buffer != NULL) {
991     delete gCBuffer.Buffer;
992   }
993 
994   if (gRBuffer.Buffer != NULL) {
995     delete gRBuffer.Buffer;
996   }
997 
998   return GetUtilityStatus ();
999 }
1000 
1001 
1002