3 VfrCompiler main class and main function.
5 Copyright (c) 2004 - 2008, Intel Corporation
6 All rights reserved. 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
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.
19 #include "VfrCompiler.h"
20 #include "CommonLib.h"
21 #include "EfiUtilityMsgs.h"
23 PACKAGE_DATA gCBuffer
;
24 PACKAGE_DATA gRBuffer
;
27 CVfrCompiler::DebugError () {
28 Error (NULL
, 0, 0001, "Error parsing vfr file", " %s", mOptions
.VfrFileName
);
33 CVfrCompiler::SET_RUN_STATUS (
34 IN COMPILER_RUN_STATUS Status
41 CVfrCompiler::IS_RUN_STATUS (
42 IN COMPILER_RUN_STATUS Status
45 return mRunStatus
== Status
;
49 CVfrCompiler::OptionInitialization (
56 SetUtilityName (PROGRAM_NAME
);
58 mOptions
.VfrFileName
[0] = '\0';
59 mOptions
.RecordListFile
[0] = '\0';
60 mOptions
.CreateRecordListFile
= FALSE
;
61 mOptions
.CreateIfrPkgFile
= FALSE
;
62 mOptions
.PkgOutputFileName
[0] = '\0';
63 mOptions
.COutputFileName
[0] = '\0';
64 mOptions
.OutputDirectory
[0] = '\0';
65 mOptions
.PreprocessorOutputFileName
[0] = '\0';
66 mOptions
.VfrBaseFileName
[0] = '\0';
67 mOptions
.IncludePaths
= NULL
;
68 mOptions
.SkipCPreprocessor
= TRUE
;
69 mOptions
.CPreprocessorOptions
= NULL
;
70 mOptions
.CompatibleMode
= FALSE
;
74 SET_RUN_STATUS (STATUS_DEAD
);
78 for (Index
= 1; (Index
< Argc
) && (Argv
[Index
][0] == '-'); Index
++) {
79 if ((stricmp(Argv
[Index
], "-h") == 0) || (stricmp(Argv
[Index
], "--help") == 0)) {
81 SET_RUN_STATUS (STATUS_DEAD
);
83 } else if (stricmp(Argv
[Index
], "-l") == 0) {
84 mOptions
.CreateRecordListFile
= TRUE
;
85 gCIfrRecordInfoDB
.TurnOn ();
86 } else if (stricmp(Argv
[Index
], "-i") == 0) {
87 Error (NULL
, 0, 1000, "Unknown option", "unrecognized option %s", Argv
[Index
]);
90 if ((Index
>= Argc
) || (Argv
[Index
][0] == '-')) {
91 Error (NULL
, 0, 1001, "Missing option", "-i missing path argument");
95 AppendIncludePath(Argv
[Index
]);
96 } else if (stricmp(Argv
[Index
], "-o") == 0 || stricmp(Argv
[Index
], "--output-directory") == 0 || stricmp(Argv
[Index
], "-od") == 0) {
98 if ((Index
>= Argc
) || (Argv
[Index
][0] == '-')) {
99 Error (NULL
, 0, 1001, "Missing option", "-o missing output directory name");
102 strcpy (mOptions
.OutputDirectory
, Argv
[Index
]);
104 CHAR8 lastChar
= mOptions
.OutputDirectory
[strlen(mOptions
.OutputDirectory
) - 1];
105 if ((lastChar
!= '/') && (lastChar
!= '\\')) {
106 if (strchr(mOptions
.OutputDirectory
, '/') != NULL
) {
107 strcat (mOptions
.OutputDirectory
, "/");
109 strcat (mOptions
.OutputDirectory
, "\\");
112 DebugMsg (NULL
, 0, 9, "Output Directory", mOptions
.OutputDirectory
);
113 } else if (stricmp(Argv
[Index
], "-b") == 0 || stricmp(Argv
[Index
], "--create-ifr-package") == 0 || stricmp(Argv
[Index
], "-ibin") == 0) {
114 mOptions
.CreateIfrPkgFile
= TRUE
;
115 } else if (stricmp(Argv
[Index
], "-n") == 0 || stricmp(Argv
[Index
], "--no-pre-processing") == 0 || stricmp(Argv
[Index
], "-nopp") == 0) {
116 mOptions
.SkipCPreprocessor
= TRUE
;
117 } else if (stricmp(Argv
[Index
], "-f") == 0 || stricmp(Argv
[Index
], "--pre-processing-flag") == 0 || stricmp(Argv
[Index
], "-ppflag") == 0) {
118 Error (NULL
, 0, 1000, "Unknown option", "unrecognized option %s", Argv
[Index
]);
121 if ((Index
>= Argc
) || (Argv
[Index
][0] == '-')) {
122 Error (NULL
, 0, 1001, "Missing option", "-od - missing C-preprocessor argument");
126 AppendCPreprocessorOptions (Argv
[Index
]);
127 } else if (stricmp(Argv
[Index
], "-c") == 0 || stricmp(Argv
[Index
], "--compatible-framework") == 0) {
128 mOptions
.CompatibleMode
= TRUE
;
130 Error (NULL
, 0, 1000, "Unknown option", "unrecognized option %s", Argv
[Index
]);
135 if (Index
!= Argc
- 1) {
136 Error (NULL
, 0, 1001, "Missing option", "VFR file name is not specified.");
139 strcpy (mOptions
.VfrFileName
, Argv
[Index
]);
142 if (SetBaseFileName() != 0) {
145 if (SetPkgOutputFileName () != 0) {
148 if (SetCOutputFileName() != 0) {
151 if (SetPreprocessorOutputFileName () != 0) {
154 if (SetRecordListFileName () != 0) {
160 SET_RUN_STATUS (STATUS_DEAD
);
162 mOptions
.VfrFileName
[0] = '\0';
163 mOptions
.RecordListFile
[0] = '\0';
164 mOptions
.CreateRecordListFile
= FALSE
;
165 mOptions
.CreateIfrPkgFile
= FALSE
;
166 mOptions
.PkgOutputFileName
[0] = '\0';
167 mOptions
.COutputFileName
[0] = '\0';
168 mOptions
.OutputDirectory
[0] = '\0';
169 mOptions
.PreprocessorOutputFileName
[0] = '\0';
170 mOptions
.VfrBaseFileName
[0] = '\0';
171 if (mOptions
.IncludePaths
!= NULL
) {
172 delete mOptions
.IncludePaths
;
173 mOptions
.IncludePaths
= NULL
;
175 if (mOptions
.CPreprocessorOptions
!= NULL
) {
176 delete mOptions
.CPreprocessorOptions
;
177 mOptions
.CPreprocessorOptions
= NULL
;
182 CVfrCompiler::AppendIncludePath (
187 CHAR8
*IncludePaths
= NULL
;
189 Len
= strlen (" -I ") + strlen (PathStr
) + 1;
190 if (mOptions
.IncludePaths
!= NULL
) {
191 Len
+= strlen (mOptions
.IncludePaths
);
193 IncludePaths
= new CHAR8
[Len
];
194 if (IncludePaths
== NULL
) {
195 Error (NULL
, 0, 4001, "Resource: memory can't be allocated", NULL
);
198 IncludePaths
[0] = '\0';
199 if (mOptions
.IncludePaths
!= NULL
) {
200 strcat (IncludePaths
, mOptions
.IncludePaths
);
202 strcat (IncludePaths
, " -I ");
203 strcat (IncludePaths
, PathStr
);
204 if (mOptions
.IncludePaths
!= NULL
) {
205 delete mOptions
.IncludePaths
;
207 mOptions
.IncludePaths
= IncludePaths
;
211 CVfrCompiler::AppendCPreprocessorOptions (
218 Len
= strlen (Options
) + strlen (" ") + 1;
219 if (mOptions
.CPreprocessorOptions
!= NULL
) {
220 Len
+= strlen (mOptions
.CPreprocessorOptions
);
222 Opt
= new CHAR8
[Len
];
224 Error (NULL
, 0, 4001, "Resource: memory can't be allocated", NULL
);
228 if (mOptions
.CPreprocessorOptions
!= NULL
) {
229 strcat (Opt
, mOptions
.CPreprocessorOptions
);
232 strcat (Opt
, Options
);
233 if (mOptions
.CPreprocessorOptions
!= NULL
) {
234 delete mOptions
.CPreprocessorOptions
;
236 mOptions
.CPreprocessorOptions
= Opt
;
240 CVfrCompiler::SetBaseFileName (
244 CHAR8
*pFileName
, *pPath
, *pExt
;
246 if (mOptions
.VfrFileName
[0] == '\0') {
250 pFileName
= mOptions
.VfrFileName
;
252 ((pPath
= strchr (pFileName
, '\\')) != NULL
) ||
253 ((pPath
= strchr (pFileName
, '/')) != NULL
)
256 pFileName
= pPath
+ 1;
259 if (pFileName
== NULL
) {
263 if ((pExt
= strchr (pFileName
, '.')) == NULL
) {
267 strncpy (mOptions
.VfrBaseFileName
, pFileName
, pExt
- pFileName
);
268 mOptions
.VfrBaseFileName
[pExt
- pFileName
] = '\0';
274 CVfrCompiler::SetPkgOutputFileName (
278 if (mOptions
.VfrBaseFileName
[0] == '\0') {
282 strcpy (mOptions
.PkgOutputFileName
, mOptions
.OutputDirectory
);
283 strcat (mOptions
.PkgOutputFileName
, mOptions
.VfrBaseFileName
);
284 strcat (mOptions
.PkgOutputFileName
, VFR_PACKAGE_FILENAME_EXTENSION
);
290 CVfrCompiler::SetCOutputFileName (
294 if (mOptions
.VfrBaseFileName
[0] == '\0') {
298 strcpy (mOptions
.COutputFileName
, mOptions
.OutputDirectory
);
299 strcat (mOptions
.COutputFileName
, mOptions
.VfrBaseFileName
);
300 strcat (mOptions
.COutputFileName
, ".c");
306 CVfrCompiler::SetPreprocessorOutputFileName (
310 if (mOptions
.VfrBaseFileName
[0] == '\0') {
314 strcpy (mOptions
.PreprocessorOutputFileName
, mOptions
.OutputDirectory
);
315 strcat (mOptions
.PreprocessorOutputFileName
, mOptions
.VfrBaseFileName
);
316 strcat (mOptions
.PreprocessorOutputFileName
, VFR_PREPROCESS_FILENAME_EXTENSION
);
322 CVfrCompiler::SetRecordListFileName (
326 if (mOptions
.VfrBaseFileName
[0] == '\0') {
330 strcpy (mOptions
.RecordListFile
, mOptions
.OutputDirectory
);
331 strcat (mOptions
.RecordListFile
, mOptions
.VfrBaseFileName
);
332 strcat (mOptions
.RecordListFile
, VFR_RECORDLIST_FILENAME_EXTENSION
);
337 CVfrCompiler::CVfrCompiler (
342 mPreProcessCmd
= PREPROCESSOR_COMMAND
;
343 mPreProcessOpt
= PREPROCESSOR_OPTIONS
;
345 OptionInitialization(Argc
, Argv
);
347 if ((IS_RUN_STATUS(STATUS_FAILED
)) || (IS_RUN_STATUS(STATUS_DEAD
))) {
351 SET_RUN_STATUS(STATUS_INITIALIZED
);
354 CVfrCompiler::~CVfrCompiler (
358 if (mOptions
.IncludePaths
!= NULL
) {
359 delete mOptions
.IncludePaths
;
360 mOptions
.IncludePaths
= NULL
;
363 if (mOptions
.CPreprocessorOptions
!= NULL
) {
364 delete mOptions
.CPreprocessorOptions
;
365 mOptions
.CPreprocessorOptions
= NULL
;
368 SET_RUN_STATUS(STATUS_DEAD
);
372 CVfrCompiler::Usage (
377 CONST CHAR8
*Help
[] = {
379 "VfrCompile version " VFR_COMPILER_VERSION VFR_COMPILER_UPDATE_TIME
,
381 "Usage: VfrCompile [options] VfrFile",
384 " -h, --help prints this help",
385 " -l create an output IFR listing file",
386 " -o DIR, --output-directory DIR",
387 " deposit all output files to directory OutputDir",
388 " default is current directory",
389 " -b, --create-ifr-package",
390 " create an IFR HII pack file",
391 " -n, --no-pre-processing",
392 " do not preprocessing input file",
393 " -c, --compatible-framework",
394 " compatible framework vfr file",
397 for (Index
= 0; Help
[Index
] != NULL
; Index
++) {
398 fprintf (stdout
, "%s\n", Help
[Index
]);
403 CVfrCompiler::PreProcess (
407 FILE *pVfrFile
= NULL
;
409 CHAR8
*PreProcessCmd
= NULL
;
411 if (!IS_RUN_STATUS(STATUS_INITIALIZED
)) {
415 if (mOptions
.SkipCPreprocessor
== TRUE
) {
419 if ((pVfrFile
= fopen (mOptions
.VfrFileName
, "r")) == NULL
) {
420 Error (NULL
, 0, 0001, "Error opening the input VFR file", mOptions
.VfrFileName
);
425 CmdLen
= strlen (mPreProcessCmd
) + strlen (mPreProcessOpt
) +
426 strlen (mOptions
.VfrFileName
) + strlen (mOptions
.PreprocessorOutputFileName
);
427 if (mOptions
.CPreprocessorOptions
!= NULL
) {
428 CmdLen
+= strlen (mOptions
.CPreprocessorOptions
);
430 if (mOptions
.IncludePaths
!= NULL
) {
431 CmdLen
+= strlen (mOptions
.IncludePaths
);
434 PreProcessCmd
= new CHAR8
[CmdLen
+ 10];
435 if (PreProcessCmd
== NULL
) {
436 Error (NULL
, 0, 4001, "Resource: memory can't be allocated", NULL
);
439 strcpy (PreProcessCmd
, mPreProcessCmd
), strcat (PreProcessCmd
, " ");
440 strcat (PreProcessCmd
, mPreProcessOpt
), strcat (PreProcessCmd
, " ");
441 if (mOptions
.IncludePaths
!= NULL
) {
442 strcat (PreProcessCmd
, mOptions
.IncludePaths
), strcat (PreProcessCmd
, " ");
444 if (mOptions
.CPreprocessorOptions
!= NULL
) {
445 strcat (PreProcessCmd
, mOptions
.CPreprocessorOptions
), strcat (PreProcessCmd
, " ");
447 strcat (PreProcessCmd
, mOptions
.VfrFileName
), strcat (PreProcessCmd
, " > ");
448 strcat (PreProcessCmd
, mOptions
.PreprocessorOutputFileName
);
450 if (system (PreProcessCmd
) != 0) {
451 Error (NULL
, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd
);
455 delete PreProcessCmd
;
458 SET_RUN_STATUS (STATUS_PREPROCESSED
);
462 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
463 SET_RUN_STATUS (STATUS_FAILED
);
465 delete PreProcessCmd
;
468 extern UINT8
VfrParserStart (IN
FILE *, IN BOOLEAN
);
471 CVfrCompiler::Compile (
475 FILE *pInFile
= NULL
;
476 CHAR8
*InFileName
= NULL
;
478 if (!IS_RUN_STATUS(STATUS_PREPROCESSED
)) {
482 InFileName
= (mOptions
.SkipCPreprocessor
== TRUE
) ? mOptions
.VfrFileName
: mOptions
.PreprocessorOutputFileName
;
484 gCVfrErrorHandle
.SetInputFile (InFileName
);
486 if ((pInFile
= fopen (InFileName
, "r")) == NULL
) {
487 Error (NULL
, 0, 0001, "Error opening the input file", InFileName
);
491 if (VfrParserStart (pInFile
, mOptions
.CompatibleMode
) != 0) {
497 if (gCFormPkg
.HavePendingUnassigned () == TRUE
) {
498 gCFormPkg
.PendingAssignPrintAll ();
502 SET_RUN_STATUS (STATUS_COMPILEED
);
506 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
507 Error (NULL
, 0, 0003, "Error parsing", "compile error in file %s", InFileName
);
508 SET_RUN_STATUS (STATUS_FAILED
);
510 if (pInFile
!= NULL
) {
516 CVfrCompiler::AdjustBin (
520 EFI_VFR_RETURN_CODE Status
;
522 // Check Binary Code consistent between Form and IfrRecord
526 // Get Package Data and IfrRecord Data
528 gCFormPkg
.BuildPkg (gCBuffer
);
529 gCIfrRecordInfoDB
.IfrRecordOutput (gRBuffer
);
532 // Compare Form and Record data
534 if (gCBuffer
.Buffer
!= NULL
&& gRBuffer
.Buffer
!= NULL
) {
536 if (gCBuffer
.Size
!= gRBuffer
.Size
) {
537 Error (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
);
539 for (Index
= 0; Index
< gCBuffer
.Size
; Index
++) {
540 if (gCBuffer
.Buffer
[Index
] != gRBuffer
.Buffer
[Index
]) {
544 if (Index
!= gCBuffer
.Size
) {
545 Error (NULL
, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions
.VfrFileName
, Index
);
547 DebugMsg (NULL
, 0, 9, "IFR Buffer", "Form Buffer same to Record Buffer and Size is 0x%X", Index
);
548 } else if (gCBuffer
.Buffer
== NULL
&& gRBuffer
.Buffer
== NULL
) {
551 Error (NULL
, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions
.VfrFileName
);
555 // For UEFI mode, not do OpCode Adjust
557 if (mOptions
.CompatibleMode
) {
559 // Adjust Opcode to be compatible with framework vfr
561 Status
= gCIfrRecordInfoDB
.IfrRecordAdjust ();
562 if (Status
!= VFR_RETURN_SUCCESS
) {
564 // Record List Adjust Failed
566 SET_RUN_STATUS (STATUS_FAILED
);
570 // Re get the IfrRecord Buffer.
572 gCIfrRecordInfoDB
.IfrRecordOutput (gRBuffer
);
579 CVfrCompiler::GenBinary (
585 if (!IS_RUN_STATUS(STATUS_COMPILEED
)) {
589 if (mOptions
.CreateIfrPkgFile
== TRUE
) {
590 if ((pFile
= fopen (mOptions
.PkgOutputFileName
, "wb")) == NULL
) {
591 Error (NULL
, 0, 0001, "Error opening file", mOptions
.PkgOutputFileName
);
594 if (gCFormPkg
.BuildPkg (pFile
, &gRBuffer
) != VFR_RETURN_SUCCESS
) {
601 SET_RUN_STATUS (STATUS_GENBINARY
);
606 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
607 SET_RUN_STATUS (STATUS_FAILED
);
611 static const char *gSourceFileHeader
[] = {
613 "// DO NOT EDIT -- auto-generated file",
615 "// This file is generated by the vfrcompiler utility",
621 CVfrCompiler::GenCFile (
628 if (!IS_RUN_STATUS(STATUS_GENBINARY
)) {
632 if ((pFile
= fopen (mOptions
.COutputFileName
, "w")) == NULL
) {
633 Error (NULL
, 0, 0001, "Error opening output C file", mOptions
.COutputFileName
);
637 for (Index
= 0; gSourceFileHeader
[Index
] != NULL
; Index
++) {
638 fprintf (pFile
, "%s\n", gSourceFileHeader
[Index
]);
641 gCVfrBufferConfig
.OutputCFile (pFile
, mOptions
.VfrBaseFileName
);
643 if (gCFormPkg
.GenCFile (mOptions
.VfrBaseFileName
, pFile
, &gRBuffer
) != VFR_RETURN_SUCCESS
) {
649 SET_RUN_STATUS (STATUS_FINISHED
);
653 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
654 SET_RUN_STATUS (STATUS_FAILED
);
659 CVfrCompiler::GenRecordListFile (
663 CHAR8
*InFileName
= NULL
;
664 FILE *pInFile
= NULL
;
665 FILE *pOutFile
= NULL
;
666 CHAR8 LineBuf
[MAX_VFR_LINE_LEN
];
669 InFileName
= (mOptions
.SkipCPreprocessor
== TRUE
) ? mOptions
.VfrFileName
: mOptions
.PreprocessorOutputFileName
;
671 if (mOptions
.CreateRecordListFile
== TRUE
) {
672 if ((InFileName
[0] == '\0') || (mOptions
.RecordListFile
[0] == '\0')) {
676 if ((pInFile
= fopen (InFileName
, "r")) == NULL
) {
677 Error (NULL
, 0, 0001, "Error opening the input VFR preprocessor output file", InFileName
);
681 if ((pOutFile
= fopen (mOptions
.RecordListFile
, "w")) == NULL
) {
682 Error (NULL
, 0, 0001, "Error opening the record list file", mOptions
.RecordListFile
);
686 fprintf (pOutFile
, "//\n// VFR compiler version " VFR_COMPILER_VERSION
"\n//\n");
688 while (!feof (pInFile
)) {
689 if (fgets (LineBuf
, MAX_VFR_LINE_LEN
, pInFile
) != NULL
) {
690 fprintf (pOutFile
, "%s", LineBuf
);
692 gCIfrRecordInfoDB
.IfrRecordOutput (pOutFile
, LineNo
);
696 fprintf (pOutFile
, "\n//\n// All Opcode Record List \n//\n");
697 gCIfrRecordInfoDB
.IfrRecordOutput (pOutFile
, 0);
698 gCVfrVarDataTypeDB
.Dump(pOutFile
);
716 COMPILER_RUN_STATUS Status
;
717 CVfrCompiler
Compiler(Argc
, Argv
);
719 Compiler
.PreProcess();
721 Compiler
.AdjustBin();
722 Compiler
.GenBinary();
724 Compiler
.GenRecordListFile ();
726 Status
= Compiler
.RunStatus ();
727 if ((Status
== STATUS_DEAD
) || (Status
== STATUS_FAILED
)) {
731 if (gCBuffer
.Buffer
!= NULL
) {
732 delete gCBuffer
.Buffer
;
735 if (gRBuffer
.Buffer
!= NULL
) {
736 delete gRBuffer
.Buffer
;
739 return GetUtilityStatus ();