]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/UefiVfrCompile/VfrCompiler.cpp
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / UefiVfrCompile / VfrCompiler.cpp
1 /*++
2
3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 VfrCompiler.cpp
15
16 Abstract:
17
18 --*/
19
20 #include "stdio.h"
21 #include "string.h"
22 #include "process.h"
23 #include "VfrCompiler.h"
24
25
26 VOID
27 CVfrCompiler::SET_RUN_STATUS (
28 IN COMPILER_RUN_STATUS Status
29 )
30 {
31 mRunStatus = Status;
32 }
33
34 BOOLEAN
35 CVfrCompiler::IS_RUN_STATUS (
36 IN COMPILER_RUN_STATUS Status
37 )
38 {
39 return mRunStatus == Status;
40 }
41
42 VOID
43 CVfrCompiler::OptionInitialization (
44 IN INT32 Argc,
45 IN INT8 **Argv
46 )
47 {
48 INT32 Index;
49
50 mOptions.VfrFileName[0] = '\0';
51 mOptions.RecordListFile[0] = '\0';
52 mOptions.CreateRecordListFile = FALSE;
53 mOptions.CreateIfrPkgFile = FALSE;
54 mOptions.PkgOutputFileName[0] = '\0';
55 mOptions.COutputFileName[0] = '\0';
56 mOptions.OutputDirectory[0] = '\0';
57 mOptions.PreprocessorOutputFileName[0] = '\0';
58 mOptions.VfrBaseFileName[0] = '\0';
59 mOptions.IncludePaths = NULL;
60 mOptions.SkipCPreprocessor = FALSE;
61 mOptions.CPreprocessorOptions = NULL;
62
63 for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) {
64 if ((_stricmp(Argv[Index], "-?") == 0) || (_stricmp(Argv[Index], "-h") == 0)) {
65 Usage ();
66 SET_RUN_STATUS (STATUS_DEAD);
67 return;
68 } else if (_stricmp(Argv[Index], "-l") == 0) {
69 mOptions.CreateRecordListFile = TRUE;
70 gCIfrRecordInfoDB.TurnOn ();
71 } else if (_stricmp(Argv[Index], "-i") == 0) {
72 Index++;
73 if ((Index >= Argc) || (Argv[Index][0] == '-')) {
74 printf ("%s -i - missing path argument\n", UTILITY_NAME);
75 goto Fail;
76 }
77
78 AppendIncludePath(Argv[Index]);
79 } else if (_stricmp(Argv[Index], "-od") == 0) {
80 Index++;
81 if ((Index >= Argc) || (Argv[Index][0] == '-')) {
82 printf ("%s -od - missing output directory name\n", UTILITY_NAME);
83 goto Fail;
84 }
85 strcpy (mOptions.OutputDirectory, Argv[Index]);
86 strcat (mOptions.OutputDirectory, "\\");
87 } else if (_stricmp(Argv[Index], "-ibin") == 0) {
88 mOptions.CreateIfrPkgFile = TRUE;
89 } else if (_stricmp(Argv[Index], "-nostrings") == 0) {
90 } else if (_stricmp(Argv[Index], "-nopp") == 0) {
91 mOptions.SkipCPreprocessor = TRUE;
92 } else if (_stricmp(Argv[Index], "-ppflag") == 0) {
93 Index++;
94 if ((Index >= Argc) || (Argv[Index][0] == '-')) {
95 printf ("%s -od - missing C-preprocessor argument\n", UTILITY_NAME);
96 goto Fail;
97 }
98
99 AppendCPreprocessorOptions (Argv[Index]);
100 } else {
101 printf ("%s unrecognized option %s\n", UTILITY_NAME, Argv[Index]);
102 Usage ();
103 goto Fail;
104 }
105 }
106
107 if (Index != Argc - 1) {
108 printf ("%s must specify VFR file name\n", UTILITY_NAME);
109 Usage ();
110 goto Fail;
111 } else {
112 strcpy (mOptions.VfrFileName, Argv[Index]);
113 }
114
115 if (SetBaseFileName() != 0) {
116 goto Fail;
117 }
118 if (SetPkgOutputFileName () != 0) {
119 goto Fail;
120 }
121 if (SetCOutputFileName() != 0) {
122 goto Fail;
123 }
124 if (SetPreprocessorOutputFileName () != 0) {
125 goto Fail;
126 }
127 if (SetRecordListFileName () != 0) {
128 goto Fail;
129 }
130 return;
131
132 Fail:
133 SET_RUN_STATUS (STATUS_FAILED);
134
135 mOptions.VfrFileName[0] = '\0';
136 mOptions.RecordListFile[0] = '\0';
137 mOptions.CreateRecordListFile = FALSE;
138 mOptions.CreateIfrPkgFile = FALSE;
139 mOptions.PkgOutputFileName[0] = '\0';
140 mOptions.COutputFileName[0] = '\0';
141 mOptions.OutputDirectory[0] = '\0';
142 mOptions.PreprocessorOutputFileName[0] = '\0';
143 mOptions.VfrBaseFileName[0] = '\0';
144 if (mOptions.IncludePaths != NULL) {
145 delete mOptions.IncludePaths;
146 mOptions.IncludePaths = NULL;
147 }
148 if (mOptions.CPreprocessorOptions != NULL) {
149 delete mOptions.CPreprocessorOptions;
150 mOptions.CPreprocessorOptions = NULL;
151 }
152 }
153
154 VOID
155 CVfrCompiler::AppendIncludePath (
156 IN INT8 *PathStr
157 )
158 {
159 UINT32 Len = 0;
160 INT8 *IncludePaths = NULL;
161
162 Len = strlen (" -I ") + strlen (PathStr) + 1;
163 if (mOptions.IncludePaths != NULL) {
164 Len += strlen (mOptions.IncludePaths);
165 }
166 IncludePaths = new INT8[Len];
167 if (IncludePaths == NULL) {
168 printf ("%s memory allocation failure\n", UTILITY_NAME);
169 return;
170 }
171 IncludePaths[0] = '\0';
172 if (mOptions.IncludePaths != NULL) {
173 strcat (IncludePaths, mOptions.IncludePaths);
174 }
175 strcat (IncludePaths, " -I ");
176 strcat (IncludePaths, PathStr);
177 if (mOptions.IncludePaths != NULL) {
178 delete mOptions.IncludePaths;
179 }
180 mOptions.IncludePaths = IncludePaths;
181 }
182
183 VOID
184 CVfrCompiler::AppendCPreprocessorOptions (
185 IN INT8 *Options
186 )
187 {
188 UINT32 Len = 0;
189 INT8 *Opt = NULL;
190
191 Len = strlen (Options) + strlen (" ") + 1;
192 if (mOptions.CPreprocessorOptions != NULL) {
193 Len += strlen (mOptions.CPreprocessorOptions);
194 }
195 Opt = new INT8[Len];
196 if (Opt == NULL) {
197 printf ("%s memory allocation failure\n", UTILITY_NAME);
198 return;
199 }
200 Opt[0] = 0;
201 if (mOptions.CPreprocessorOptions != NULL) {
202 strcat (Opt, mOptions.CPreprocessorOptions);
203 }
204 strcat (Opt, " ");
205 strcat (Opt, Options);
206 if (mOptions.CPreprocessorOptions != NULL) {
207 delete mOptions.CPreprocessorOptions;
208 }
209 mOptions.CPreprocessorOptions = Opt;
210 }
211
212 INT8
213 CVfrCompiler::SetBaseFileName (
214 VOID
215 )
216 {
217 INT8 *pFileName, *pPath, *pExt;
218
219 if (mOptions.VfrFileName[0] == '\0') {
220 return -1;
221 }
222
223 pFileName = mOptions.VfrFileName;
224 while (
225 ((pPath = strchr (pFileName, '\\')) != NULL) ||
226 ((pPath = strchr (pFileName, '/')) != NULL)
227 )
228 {
229 pFileName = pPath + 1;
230 }
231
232 if (pFileName == NULL) {
233 return -1;
234 }
235
236 if ((pExt = strchr (pFileName, '.')) == NULL) {
237 return -1;
238 }
239
240 strncpy (mOptions.VfrBaseFileName, pFileName, pExt - pFileName);
241 mOptions.VfrBaseFileName[pExt - pFileName] = '\0';
242
243 return 0;
244 }
245
246 INT8
247 CVfrCompiler::SetPkgOutputFileName (
248 VOID
249 )
250 {
251 if (mOptions.VfrBaseFileName[0] == '\0') {
252 return -1;
253 }
254
255 strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory);
256 strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName);
257 strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION);
258
259 return 0;
260 }
261
262 INT8
263 CVfrCompiler::SetCOutputFileName (
264 VOID
265 )
266 {
267 if (mOptions.VfrBaseFileName[0] == '\0') {
268 return -1;
269 }
270
271 strcpy (mOptions.COutputFileName, mOptions.OutputDirectory);
272 strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName);
273 strcat (mOptions.COutputFileName, ".c");
274
275 return 0;
276 }
277
278 INT8
279 CVfrCompiler::SetPreprocessorOutputFileName (
280 VOID
281 )
282 {
283 if (mOptions.VfrBaseFileName[0] == '\0') {
284 return -1;
285 }
286
287 strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory);
288 strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName);
289 strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);
290
291 return 0;
292 }
293
294 INT8
295 CVfrCompiler::SetRecordListFileName (
296 VOID
297 )
298 {
299 if (mOptions.VfrBaseFileName[0] == '\0') {
300 return -1;
301 }
302
303 strcpy (mOptions.RecordListFile, mOptions.OutputDirectory);
304 strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName);
305 strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION);
306
307 return 0;
308 }
309
310 CVfrCompiler::CVfrCompiler (
311 IN INT32 Argc,
312 IN INT8 **Argv
313 )
314 {
315 mPreProcessCmd = PREPROCESSOR_COMMAND;
316 mPreProcessOpt = PREPROCESSOR_OPTIONS;
317
318 OptionInitialization(Argc, Argv);
319
320 if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) {
321 return;
322 }
323
324 SET_RUN_STATUS(STATUS_INITIALIZED);
325 }
326
327 CVfrCompiler::~CVfrCompiler (
328 VOID
329 )
330 {
331 if (mOptions.IncludePaths != NULL) {
332 delete mOptions.IncludePaths;
333 mOptions.IncludePaths = NULL;
334 }
335
336 if (mOptions.CPreprocessorOptions != NULL) {
337 delete mOptions.CPreprocessorOptions;
338 mOptions.CPreprocessorOptions = NULL;
339 }
340
341 SET_RUN_STATUS(STATUS_DEAD);
342 }
343
344 VOID
345 CVfrCompiler::Usage (
346 VOID
347 )
348 {
349 int Index;
350 const char *Str[] = {
351 UTILITY_NAME" "UTILITY_VERSION" - Intel UEFI VFR Compiler Utility",
352 " Copyright (C), 2004 - 2008 Intel Corporation",
353 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
354 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
355 #endif
356 "",
357 "Usage:",
358 " "UTILITY_NAME" [OPTION] VFRFILE",
359 "Description:",
360 " Compile VFRFILE.",
361 "Options:",
362 " -? or -h print this help",
363 " -l create an output IFR listing file",
364 " -i IncPath add IncPath to the search path for VFR included files",
365 " -od OutputDir deposit all output files to directory OutputDir (default=cwd)",
366 " -ibin create an IFR HII pack file",
367 " -ppflag CFlags pass Flags as C-preprocessor-flag",
368 " -v or -version print version information",
369 NULL
370 };
371
372 for (Index = 0; Str[Index] != NULL; Index++) {
373 fprintf (stdout, "%s\n", Str[Index]);
374 }
375 }
376
377
378 VOID
379 CVfrCompiler::PreProcess (
380 VOID
381 )
382 {
383 FILE *pVfrFile = NULL;
384 UINT32 CmdLen = 0;
385 INT8 *PreProcessCmd = NULL;
386
387 if (!IS_RUN_STATUS(STATUS_INITIALIZED)) {
388 goto Fail;
389 }
390
391 if (mOptions.SkipCPreprocessor == TRUE) {
392 goto Out;
393 }
394
395 if ((pVfrFile = fopen (mOptions.VfrFileName, "r")) == NULL) {
396 printf ("%s could not open input VFR file - %s\n", UTILITY_NAME, mOptions.VfrFileName);
397 goto Fail;
398 }
399 fclose (pVfrFile);
400
401 CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) +
402 strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName);
403 if (mOptions.CPreprocessorOptions != NULL) {
404 CmdLen += strlen (mOptions.CPreprocessorOptions);
405 }
406 if (mOptions.IncludePaths != NULL) {
407 CmdLen += strlen (mOptions.IncludePaths);
408 }
409
410 PreProcessCmd = new INT8[CmdLen + 10];
411 if (PreProcessCmd == NULL) {
412 printf ("%s could not allocate memory\n", UTILITY_NAME);
413 goto Fail;
414 }
415 strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " ");
416 strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " ");
417 if (mOptions.IncludePaths != NULL) {
418 strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " ");
419 }
420 if (mOptions.CPreprocessorOptions != NULL) {
421 strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " ");
422 }
423 strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > ");
424 strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName);
425
426 if (system (PreProcessCmd) != 0) {
427 printf ("%s failed to spawn C preprocessor on VFR file \n\t - %s\n", UTILITY_NAME, PreProcessCmd);
428 goto Fail;
429 }
430
431 delete PreProcessCmd;
432
433 Out:
434 SET_RUN_STATUS (STATUS_PREPROCESSED);
435 return;
436
437 Fail:
438 if (!IS_RUN_STATUS(STATUS_DEAD)) {
439 SET_RUN_STATUS (STATUS_FAILED);
440 }
441 delete PreProcessCmd;
442 }
443
444 extern UINT8 VfrParserStart (IN FILE *);
445
446 VOID
447 CVfrCompiler::Compile (
448 VOID
449 )
450 {
451 FILE *pInFile = NULL;
452 INT8 *InFileName = NULL;
453
454 if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) {
455 goto Fail;
456 }
457
458 InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
459
460 gCVfrErrorHandle.SetInputFile (InFileName);
461
462 if ((pInFile = fopen (InFileName, "r")) == NULL) {
463 printf ("%s failed to open input file - %s\n", UTILITY_NAME, InFileName);
464 goto Fail;
465 }
466
467 if (VfrParserStart (pInFile) != 0) {
468 goto Fail;
469 }
470
471 fclose (pInFile);
472
473 if (gCFormPkg.HavePendingUnassigned () == TRUE) {
474 gCFormPkg.PendingAssignPrintAll ();
475 goto Fail;
476 }
477
478 SET_RUN_STATUS (STATUS_COMPILEED);
479 return;
480
481 Fail:
482 if (!IS_RUN_STATUS(STATUS_DEAD)) {
483 printf ("%s compile error!\n", UTILITY_NAME);
484 SET_RUN_STATUS (STATUS_FAILED);
485 }
486 if (pInFile != NULL) {
487 fclose (pInFile);
488 }
489 }
490
491 VOID
492 CVfrCompiler::GenBinary (
493 VOID
494 )
495 {
496 FILE *pFile = NULL;
497
498 if (!IS_RUN_STATUS(STATUS_COMPILEED)) {
499 goto Fail;
500 }
501
502 if (mOptions.CreateIfrPkgFile == TRUE) {
503 if ((pFile = fopen (mOptions.PkgOutputFileName, "wb")) == NULL) {
504 printf ("can not open %s\n", mOptions.PkgOutputFileName);
505 goto Fail;
506 }
507 if (gCFormPkg.BuildPkg (pFile) != VFR_RETURN_SUCCESS) {
508 fclose (pFile);
509 goto Fail;
510 }
511 fclose (pFile);
512 }
513
514 SET_RUN_STATUS (STATUS_GENBINARY);
515 return;
516
517 Fail:
518 if (!IS_RUN_STATUS(STATUS_DEAD)) {
519 SET_RUN_STATUS (STATUS_FAILED);
520 }
521 }
522
523 static const char *gSourceFileHeader[] = {
524 "//",
525 "// DO NOT EDIT -- auto-generated file",
526 "//",
527 "// This file is generated by the vfrcompiler utility",
528 "//",
529 NULL
530 };
531
532 VOID
533 CVfrCompiler::GenCFile (
534 VOID
535 )
536 {
537 FILE *pFile;
538 UINT32 Index;
539
540 if (!IS_RUN_STATUS(STATUS_GENBINARY)) {
541 goto Fail;
542 }
543
544 if ((pFile = fopen (mOptions.COutputFileName, "w")) == NULL) {
545 printf ("failed to open output C file - %s\n", mOptions.COutputFileName);
546 goto Fail;
547 }
548
549 for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) {
550 fprintf (pFile, "%s\n", gSourceFileHeader[Index]);
551 }
552
553 gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName);
554
555 if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile) != VFR_RETURN_SUCCESS) {
556 fclose (pFile);
557 goto Fail;
558 }
559 fclose (pFile);
560
561 SET_RUN_STATUS (STATUS_FINISHED);
562 return;
563
564 Fail:
565 if (!IS_RUN_STATUS(STATUS_DEAD)) {
566 SET_RUN_STATUS (STATUS_FAILED);
567 }
568 }
569
570 VOID
571 CVfrCompiler::GenRecordListFile (
572 VOID
573 )
574 {
575 INT8 *InFileName = NULL;
576 FILE *pInFile = NULL;
577 FILE *pOutFile = NULL;
578 INT8 LineBuf[MAX_LINE_LEN];
579 UINT32 LineNo;
580
581 InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;
582
583 if (mOptions.CreateRecordListFile == TRUE) {
584 if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) {
585 return;
586 }
587
588 if ((pInFile = fopen (InFileName, "r")) == NULL) {
589 printf ("%s failed to open input VFR preprocessor output file - %s\n", UTILITY_NAME, InFileName);
590 return;
591 }
592
593 if ((pOutFile = fopen (mOptions.RecordListFile, "w")) == NULL) {
594 printf ("%s failed to open record list file for writing - %s\n", UTILITY_NAME, mOptions.RecordListFile);
595 goto Err1;
596 }
597
598 fprintf (pOutFile, "//\n// VFR compiler version " UTILITY_VERSION "\n//\n");
599 LineNo = 0;
600 while (!feof (pInFile)) {
601 if (fgets (LineBuf, MAX_LINE_LEN, pInFile) != NULL) {
602 fprintf (pOutFile, "%s", LineBuf);
603 LineNo++;
604 gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo);
605 }
606 }
607
608 fclose (pOutFile);
609 fclose (pInFile);
610 }
611
612 return;
613
614 Err1:
615 fclose (pInFile);
616 }
617
618 INT32
619 main (
620 IN INT32 Argc,
621 IN INT8 **Argv
622 )
623 {
624 COMPILER_RUN_STATUS Status;
625 CVfrCompiler Compiler(Argc, Argv);
626
627 Compiler.PreProcess();
628 Compiler.Compile();
629 Compiler.GenBinary();
630 Compiler.GenCFile();
631 Compiler.GenRecordListFile ();
632
633 Status = Compiler.RunStatus ();
634 if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) {
635 return 2;
636 }
637
638 return 0;
639 }
640