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 641