3 VfrCompiler main class and main function.
5 Copyright (c) 2004 - 2010, 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 (
30 IN UINT32 MessageCode
,
32 IN CONST CHAR8
*MsgFmt
,
37 va_start (List
, MsgFmt
);
38 PrintMessage ((CHAR8
*) "ERROR", FileName
, LineNumber
, MessageCode
, (CHAR8
*) Text
, (CHAR8
*) MsgFmt
, List
);
43 CVfrCompiler::SET_RUN_STATUS (
44 IN COMPILER_RUN_STATUS Status
51 CVfrCompiler::IS_RUN_STATUS (
52 IN COMPILER_RUN_STATUS Status
55 return mRunStatus
== Status
;
59 CVfrCompiler::OptionInitialization (
66 SetUtilityName ((CHAR8
*) PROGRAM_NAME
);
68 mOptions
.VfrFileName
[0] = '\0';
69 mOptions
.RecordListFile
[0] = '\0';
70 mOptions
.CreateRecordListFile
= FALSE
;
71 mOptions
.CreateIfrPkgFile
= FALSE
;
72 mOptions
.PkgOutputFileName
[0] = '\0';
73 mOptions
.COutputFileName
[0] = '\0';
74 mOptions
.OutputDirectory
[0] = '\0';
75 mOptions
.PreprocessorOutputFileName
[0] = '\0';
76 mOptions
.VfrBaseFileName
[0] = '\0';
77 mOptions
.IncludePaths
= NULL
;
78 mOptions
.SkipCPreprocessor
= TRUE
;
79 mOptions
.CPreprocessorOptions
= NULL
;
80 mOptions
.CompatibleMode
= FALSE
;
84 SET_RUN_STATUS (STATUS_DEAD
);
88 for (Index
= 1; (Index
< Argc
) && (Argv
[Index
][0] == '-'); Index
++) {
89 if ((stricmp(Argv
[Index
], "-h") == 0) || (stricmp(Argv
[Index
], "--help") == 0)) {
91 SET_RUN_STATUS (STATUS_DEAD
);
93 } else if (stricmp(Argv
[Index
], "-l") == 0) {
94 mOptions
.CreateRecordListFile
= TRUE
;
95 gCIfrRecordInfoDB
.TurnOn ();
96 } else if (stricmp(Argv
[Index
], "-i") == 0) {
98 if ((Index
>= Argc
) || (Argv
[Index
][0] == '-')) {
99 DebugError (NULL
, 0, 1001, "Missing option", "-i missing path argument");
103 AppendIncludePath(Argv
[Index
]);
104 } else if (stricmp(Argv
[Index
], "-o") == 0 || stricmp(Argv
[Index
], "--output-directory") == 0 || stricmp(Argv
[Index
], "-od") == 0) {
106 if ((Index
>= Argc
) || (Argv
[Index
][0] == '-')) {
107 DebugError (NULL
, 0, 1001, "Missing option", "-o missing output directory name");
110 strcpy (mOptions
.OutputDirectory
, Argv
[Index
]);
112 CHAR8 lastChar
= mOptions
.OutputDirectory
[strlen(mOptions
.OutputDirectory
) - 1];
113 if ((lastChar
!= '/') && (lastChar
!= '\\')) {
114 if (strchr(mOptions
.OutputDirectory
, '/') != NULL
) {
115 strcat (mOptions
.OutputDirectory
, "/");
117 strcat (mOptions
.OutputDirectory
, "\\");
120 DebugMsg (NULL
, 0, 9, (CHAR8
*) "Output Directory", mOptions
.OutputDirectory
);
121 } else if (stricmp(Argv
[Index
], "-b") == 0 || stricmp(Argv
[Index
], "--create-ifr-package") == 0 || stricmp(Argv
[Index
], "-ibin") == 0) {
122 mOptions
.CreateIfrPkgFile
= TRUE
;
123 } else if (stricmp(Argv
[Index
], "-n") == 0 || stricmp(Argv
[Index
], "--no-pre-processing") == 0 || stricmp(Argv
[Index
], "-nopp") == 0) {
124 mOptions
.SkipCPreprocessor
= TRUE
;
125 } else if (stricmp(Argv
[Index
], "-f") == 0 || stricmp(Argv
[Index
], "--pre-processing-flag") == 0 || stricmp(Argv
[Index
], "-ppflag") == 0) {
127 if ((Index
>= Argc
) || (Argv
[Index
][0] == '-')) {
128 DebugError (NULL
, 0, 1001, "Missing option", "-od - missing C-preprocessor argument");
132 AppendCPreprocessorOptions (Argv
[Index
]);
133 } else if (stricmp(Argv
[Index
], "-c") == 0 || stricmp(Argv
[Index
], "--compatible-framework") == 0) {
134 mOptions
.CompatibleMode
= TRUE
;
136 DebugError (NULL
, 0, 1000, "Unknown option", "unrecognized option %s", Argv
[Index
]);
141 if (Index
!= Argc
- 1) {
142 DebugError (NULL
, 0, 1001, "Missing option", "VFR file name is not specified.");
145 strcpy (mOptions
.VfrFileName
, Argv
[Index
]);
148 if (SetBaseFileName() != 0) {
151 if (SetPkgOutputFileName () != 0) {
154 if (SetCOutputFileName() != 0) {
157 if (SetPreprocessorOutputFileName () != 0) {
160 if (SetRecordListFileName () != 0) {
166 SET_RUN_STATUS (STATUS_DEAD
);
168 mOptions
.VfrFileName
[0] = '\0';
169 mOptions
.RecordListFile
[0] = '\0';
170 mOptions
.CreateRecordListFile
= FALSE
;
171 mOptions
.CreateIfrPkgFile
= FALSE
;
172 mOptions
.PkgOutputFileName
[0] = '\0';
173 mOptions
.COutputFileName
[0] = '\0';
174 mOptions
.OutputDirectory
[0] = '\0';
175 mOptions
.PreprocessorOutputFileName
[0] = '\0';
176 mOptions
.VfrBaseFileName
[0] = '\0';
177 if (mOptions
.IncludePaths
!= NULL
) {
178 delete mOptions
.IncludePaths
;
179 mOptions
.IncludePaths
= NULL
;
181 if (mOptions
.CPreprocessorOptions
!= NULL
) {
182 delete mOptions
.CPreprocessorOptions
;
183 mOptions
.CPreprocessorOptions
= NULL
;
188 CVfrCompiler::AppendIncludePath (
193 CHAR8
*IncludePaths
= NULL
;
195 Len
= strlen (" -I ") + strlen (PathStr
) + 1;
196 if (mOptions
.IncludePaths
!= NULL
) {
197 Len
+= strlen (mOptions
.IncludePaths
);
199 IncludePaths
= new CHAR8
[Len
];
200 if (IncludePaths
== NULL
) {
201 DebugError (NULL
, 0, 4001, "Resource: memory can't be allocated", NULL
);
204 IncludePaths
[0] = '\0';
205 if (mOptions
.IncludePaths
!= NULL
) {
206 strcat (IncludePaths
, mOptions
.IncludePaths
);
208 strcat (IncludePaths
, " -I ");
209 strcat (IncludePaths
, PathStr
);
210 if (mOptions
.IncludePaths
!= NULL
) {
211 delete mOptions
.IncludePaths
;
213 mOptions
.IncludePaths
= IncludePaths
;
217 CVfrCompiler::AppendCPreprocessorOptions (
224 Len
= strlen (Options
) + strlen (" ") + 1;
225 if (mOptions
.CPreprocessorOptions
!= NULL
) {
226 Len
+= strlen (mOptions
.CPreprocessorOptions
);
228 Opt
= new CHAR8
[Len
];
230 DebugError (NULL
, 0, 4001, "Resource: memory can't be allocated", NULL
);
234 if (mOptions
.CPreprocessorOptions
!= NULL
) {
235 strcat (Opt
, mOptions
.CPreprocessorOptions
);
238 strcat (Opt
, Options
);
239 if (mOptions
.CPreprocessorOptions
!= NULL
) {
240 delete mOptions
.CPreprocessorOptions
;
242 mOptions
.CPreprocessorOptions
= Opt
;
246 CVfrCompiler::SetBaseFileName (
250 CHAR8
*pFileName
, *pPath
, *pExt
;
252 if (mOptions
.VfrFileName
[0] == '\0') {
256 pFileName
= mOptions
.VfrFileName
;
258 ((pPath
= strchr (pFileName
, '\\')) != NULL
) ||
259 ((pPath
= strchr (pFileName
, '/')) != NULL
)
262 pFileName
= pPath
+ 1;
265 if (pFileName
== NULL
) {
269 if ((pExt
= strchr (pFileName
, '.')) == NULL
) {
273 strncpy (mOptions
.VfrBaseFileName
, pFileName
, pExt
- pFileName
);
274 mOptions
.VfrBaseFileName
[pExt
- pFileName
] = '\0';
280 CVfrCompiler::SetPkgOutputFileName (
284 if (mOptions
.VfrBaseFileName
[0] == '\0') {
288 strcpy (mOptions
.PkgOutputFileName
, mOptions
.OutputDirectory
);
289 strcat (mOptions
.PkgOutputFileName
, mOptions
.VfrBaseFileName
);
290 strcat (mOptions
.PkgOutputFileName
, VFR_PACKAGE_FILENAME_EXTENSION
);
296 CVfrCompiler::SetCOutputFileName (
300 if (mOptions
.VfrBaseFileName
[0] == '\0') {
304 strcpy (mOptions
.COutputFileName
, mOptions
.OutputDirectory
);
305 strcat (mOptions
.COutputFileName
, mOptions
.VfrBaseFileName
);
306 strcat (mOptions
.COutputFileName
, ".c");
312 CVfrCompiler::SetPreprocessorOutputFileName (
316 if (mOptions
.VfrBaseFileName
[0] == '\0') {
320 strcpy (mOptions
.PreprocessorOutputFileName
, mOptions
.OutputDirectory
);
321 strcat (mOptions
.PreprocessorOutputFileName
, mOptions
.VfrBaseFileName
);
322 strcat (mOptions
.PreprocessorOutputFileName
, VFR_PREPROCESS_FILENAME_EXTENSION
);
328 CVfrCompiler::SetRecordListFileName (
332 if (mOptions
.VfrBaseFileName
[0] == '\0') {
336 strcpy (mOptions
.RecordListFile
, mOptions
.OutputDirectory
);
337 strcat (mOptions
.RecordListFile
, mOptions
.VfrBaseFileName
);
338 strcat (mOptions
.RecordListFile
, VFR_RECORDLIST_FILENAME_EXTENSION
);
343 CVfrCompiler::CVfrCompiler (
348 mPreProcessCmd
= (CHAR8
*) PREPROCESSOR_COMMAND
;
349 mPreProcessOpt
= (CHAR8
*) PREPROCESSOR_OPTIONS
;
351 OptionInitialization(Argc
, Argv
);
353 if ((IS_RUN_STATUS(STATUS_FAILED
)) || (IS_RUN_STATUS(STATUS_DEAD
))) {
357 SET_RUN_STATUS(STATUS_INITIALIZED
);
360 CVfrCompiler::~CVfrCompiler (
364 if (mOptions
.IncludePaths
!= NULL
) {
365 delete mOptions
.IncludePaths
;
366 mOptions
.IncludePaths
= NULL
;
369 if (mOptions
.CPreprocessorOptions
!= NULL
) {
370 delete mOptions
.CPreprocessorOptions
;
371 mOptions
.CPreprocessorOptions
= NULL
;
374 SET_RUN_STATUS(STATUS_DEAD
);
378 CVfrCompiler::Usage (
383 CONST CHAR8
*Help
[] = {
385 "VfrCompile version " VFR_COMPILER_VERSION VFR_COMPILER_UPDATE_TIME
,
386 "Copyright (c) 2004-2010 Intel Corporation. All rights reserved.",
388 "Usage: VfrCompile [options] VfrFile",
391 " -h, --help prints this help",
392 " -l create an output IFR listing file",
393 " -o DIR, --output-directory DIR",
394 " deposit all output files to directory OutputDir",
395 " default is current directory",
396 " -b, --create-ifr-package",
397 " create an IFR HII pack file",
398 " -n, --no-pre-processing",
399 " do not preprocessing input file",
400 " -c, --compatible-framework",
401 " compatible framework vfr file",
404 for (Index
= 0; Help
[Index
] != NULL
; Index
++) {
405 fprintf (stdout
, "%s\n", Help
[Index
]);
410 CVfrCompiler::PreProcess (
414 FILE *pVfrFile
= NULL
;
416 CHAR8
*PreProcessCmd
= NULL
;
418 if (!IS_RUN_STATUS(STATUS_INITIALIZED
)) {
422 if (mOptions
.SkipCPreprocessor
== TRUE
) {
426 if ((pVfrFile
= fopen (mOptions
.VfrFileName
, "r")) == NULL
) {
427 DebugError (NULL
, 0, 0001, "Error opening the input VFR file", mOptions
.VfrFileName
);
432 CmdLen
= strlen (mPreProcessCmd
) + strlen (mPreProcessOpt
) +
433 strlen (mOptions
.VfrFileName
) + strlen (mOptions
.PreprocessorOutputFileName
);
434 if (mOptions
.CPreprocessorOptions
!= NULL
) {
435 CmdLen
+= strlen (mOptions
.CPreprocessorOptions
);
437 if (mOptions
.IncludePaths
!= NULL
) {
438 CmdLen
+= strlen (mOptions
.IncludePaths
);
441 PreProcessCmd
= new CHAR8
[CmdLen
+ 10];
442 if (PreProcessCmd
== NULL
) {
443 DebugError (NULL
, 0, 4001, "Resource: memory can't be allocated", NULL
);
446 strcpy (PreProcessCmd
, mPreProcessCmd
), strcat (PreProcessCmd
, " ");
447 strcat (PreProcessCmd
, mPreProcessOpt
), strcat (PreProcessCmd
, " ");
448 if (mOptions
.IncludePaths
!= NULL
) {
449 strcat (PreProcessCmd
, mOptions
.IncludePaths
), strcat (PreProcessCmd
, " ");
451 if (mOptions
.CPreprocessorOptions
!= NULL
) {
452 strcat (PreProcessCmd
, mOptions
.CPreprocessorOptions
), strcat (PreProcessCmd
, " ");
454 strcat (PreProcessCmd
, mOptions
.VfrFileName
), strcat (PreProcessCmd
, " > ");
455 strcat (PreProcessCmd
, mOptions
.PreprocessorOutputFileName
);
457 if (system (PreProcessCmd
) != 0) {
458 DebugError (NULL
, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd
);
462 delete PreProcessCmd
;
465 SET_RUN_STATUS (STATUS_PREPROCESSED
);
469 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
470 SET_RUN_STATUS (STATUS_FAILED
);
472 delete PreProcessCmd
;
475 extern UINT8
VfrParserStart (IN
FILE *, IN BOOLEAN
);
478 CVfrCompiler::Compile (
482 FILE *pInFile
= NULL
;
483 CHAR8
*InFileName
= NULL
;
485 if (!IS_RUN_STATUS(STATUS_PREPROCESSED
)) {
489 InFileName
= (mOptions
.SkipCPreprocessor
== TRUE
) ? mOptions
.VfrFileName
: mOptions
.PreprocessorOutputFileName
;
491 gCVfrErrorHandle
.SetInputFile (InFileName
);
493 if ((pInFile
= fopen (InFileName
, "r")) == NULL
) {
494 DebugError (NULL
, 0, 0001, "Error opening the input file", InFileName
);
498 if (VfrParserStart (pInFile
, mOptions
.CompatibleMode
) != 0) {
504 if (gCFormPkg
.HavePendingUnassigned () == TRUE
) {
505 gCFormPkg
.PendingAssignPrintAll ();
509 SET_RUN_STATUS (STATUS_COMPILEED
);
513 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
514 DebugError (NULL
, 0, 0003, "Error parsing", "compile error in file %s", InFileName
);
515 SET_RUN_STATUS (STATUS_FAILED
);
517 if (pInFile
!= NULL
) {
523 CVfrCompiler::AdjustBin (
527 EFI_VFR_RETURN_CODE Status
;
529 // Check Binary Code consistent between Form and IfrRecord
533 // Get Package Data and IfrRecord Data
535 gCFormPkg
.BuildPkg (gCBuffer
);
536 gCIfrRecordInfoDB
.IfrRecordOutput (gRBuffer
);
539 // Compare Form and Record data
541 if (gCBuffer
.Buffer
!= NULL
&& gRBuffer
.Buffer
!= NULL
) {
543 if (gCBuffer
.Size
!= gRBuffer
.Size
) {
544 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
);
546 for (Index
= 0; Index
< gCBuffer
.Size
; Index
++) {
547 if (gCBuffer
.Buffer
[Index
] != gRBuffer
.Buffer
[Index
]) {
551 if (Index
!= gCBuffer
.Size
) {
552 DebugError (NULL
, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions
.VfrFileName
, Index
);
554 DebugMsg (NULL
, 0, 9, (CHAR8
*) "IFR Buffer", (CHAR8
*) "Form Buffer same to Record Buffer and Size is 0x%X", Index
);
555 } else if (gCBuffer
.Buffer
== NULL
&& gRBuffer
.Buffer
== NULL
) {
558 DebugError (NULL
, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions
.VfrFileName
);
562 // For UEFI mode, not do OpCode Adjust
564 if (mOptions
.CompatibleMode
) {
566 // Adjust Opcode to be compatible with framework vfr
568 Status
= gCIfrRecordInfoDB
.IfrRecordAdjust ();
569 if (Status
!= VFR_RETURN_SUCCESS
) {
571 // Record List Adjust Failed
573 SET_RUN_STATUS (STATUS_FAILED
);
577 // Re get the IfrRecord Buffer.
579 gCIfrRecordInfoDB
.IfrRecordOutput (gRBuffer
);
586 CVfrCompiler::GenBinary (
592 if (!IS_RUN_STATUS(STATUS_COMPILEED
)) {
596 if (mOptions
.CreateIfrPkgFile
== TRUE
) {
597 if ((pFile
= fopen (mOptions
.PkgOutputFileName
, "wb")) == NULL
) {
598 DebugError (NULL
, 0, 0001, "Error opening file", mOptions
.PkgOutputFileName
);
601 if (gCFormPkg
.BuildPkg (pFile
, &gRBuffer
) != VFR_RETURN_SUCCESS
) {
608 SET_RUN_STATUS (STATUS_GENBINARY
);
613 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
614 SET_RUN_STATUS (STATUS_FAILED
);
618 static const char *gSourceFileHeader
[] = {
620 "// DO NOT EDIT -- auto-generated file",
622 "// This file is generated by the vfrcompiler utility",
628 CVfrCompiler::GenCFile (
635 if (!IS_RUN_STATUS(STATUS_GENBINARY
)) {
639 if (!mOptions
.CreateIfrPkgFile
|| mOptions
.CompatibleMode
) {
640 if ((pFile
= fopen (mOptions
.COutputFileName
, "w")) == NULL
) {
641 DebugError (NULL
, 0, 0001, "Error opening output C file", mOptions
.COutputFileName
);
645 for (Index
= 0; gSourceFileHeader
[Index
] != NULL
; Index
++) {
646 fprintf (pFile
, "%s\n", gSourceFileHeader
[Index
]);
649 if (mOptions
.CompatibleMode
) {
650 gCVfrBufferConfig
.OutputCFile (pFile
, mOptions
.VfrBaseFileName
);
653 if (gCFormPkg
.GenCFile (mOptions
.VfrBaseFileName
, pFile
, &gRBuffer
) != VFR_RETURN_SUCCESS
) {
660 SET_RUN_STATUS (STATUS_FINISHED
);
664 if (!IS_RUN_STATUS(STATUS_DEAD
)) {
665 SET_RUN_STATUS (STATUS_FAILED
);
670 CVfrCompiler::GenRecordListFile (
674 CHAR8
*InFileName
= NULL
;
675 FILE *pInFile
= NULL
;
676 FILE *pOutFile
= NULL
;
677 CHAR8 LineBuf
[MAX_VFR_LINE_LEN
];
680 InFileName
= (mOptions
.SkipCPreprocessor
== TRUE
) ? mOptions
.VfrFileName
: mOptions
.PreprocessorOutputFileName
;
682 if (mOptions
.CreateRecordListFile
== TRUE
) {
683 if ((InFileName
[0] == '\0') || (mOptions
.RecordListFile
[0] == '\0')) {
687 if ((pInFile
= fopen (InFileName
, "r")) == NULL
) {
688 DebugError (NULL
, 0, 0001, "Error opening the input VFR preprocessor output file", InFileName
);
692 if ((pOutFile
= fopen (mOptions
.RecordListFile
, "w")) == NULL
) {
693 DebugError (NULL
, 0, 0001, "Error opening the record list file", mOptions
.RecordListFile
);
697 fprintf (pOutFile
, "//\n// VFR compiler version " VFR_COMPILER_VERSION
"\n//\n");
699 while (!feof (pInFile
)) {
700 if (fgets (LineBuf
, MAX_VFR_LINE_LEN
, pInFile
) != NULL
) {
701 fprintf (pOutFile
, "%s", LineBuf
);
703 gCIfrRecordInfoDB
.IfrRecordOutput (pOutFile
, LineNo
);
707 fprintf (pOutFile
, "\n//\n// All Opcode Record List \n//\n");
708 gCIfrRecordInfoDB
.IfrRecordOutput (pOutFile
, 0);
709 gCVfrVarDataTypeDB
.Dump(pOutFile
);
727 COMPILER_RUN_STATUS Status
;
728 CVfrCompiler
Compiler(Argc
, Argv
);
730 Compiler
.PreProcess();
732 Compiler
.AdjustBin();
733 Compiler
.GenBinary();
735 Compiler
.GenRecordListFile ();
737 Status
= Compiler
.RunStatus ();
738 if ((Status
== STATUS_DEAD
) || (Status
== STATUS_FAILED
)) {
742 if (gCBuffer
.Buffer
!= NULL
) {
743 delete gCBuffer
.Buffer
;
746 if (gRBuffer
.Buffer
!= NULL
) {
747 delete gRBuffer
.Buffer
;
750 return GetUtilityStatus ();