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