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 ProcessDsc.c 15 16 Abstract: 17 18 Main module for the ProcessDsc utility. 19 20 --*/ 21 22 #include <windows.h> // for GetShortPathName() 23 #include <stdio.h> 24 #include <string.h> 25 #include <ctype.h> 26 #include <stdarg.h> 27 #include <direct.h> // for _mkdir() 28 #include <errno.h> 29 #include <stdlib.h> // for getenv() 30 #include <shlwapi.h> // for PathCanonicalize() 31 #include "DSCFile.h" 32 #include "MultiThread.h" 33 #include "FWVolume.h" 34 #include "Exceptions.h" 35 #include "Common.h" 36 37 #include "EfiUtilityMsgs.h" 38 #include "TianoBind.h" 39 40 #define UTILITY_NAME "ProcessDsc" 41 #define UTILITY_VERSION "v1.0" 42 43 // 44 // Common symbol name definitions. For example, the user can reference 45 // $(BUILD_DIR) in their DSC file and we will expand it for them (usually). 46 // I've defined the equivalents here in case we want to change the name the 47 // user references, in which case we just change the string value here and 48 // our code still works. 49 // 50 #define BUILD_DIR "BUILD_DIR" 51 #define EFI_SOURCE "EFI_SOURCE" 52 #define DEST_DIR "DEST_DIR" 53 #define SOURCE_DIR "SOURCE_DIR" 54 #define LIB_DIR "LIB_DIR" 55 #define BIN_DIR "BIN_DIR" 56 #define OUT_DIR "OUT_DIR" 57 #define INF_FILENAME "INF_FILENAME" 58 #define SOURCE_RELATIVE_PATH "SOURCE_RELATIVE_PATH" 59 #define SOURCE_BASE_NAME "SOURCE_BASE_NAME" 60 #define SOURCE_FILE_NAME "SOURCE_FILE_NAME" // c:\FullPath\File.c 61 #define PROCESSOR "PROCESSOR" 62 #define FV "FV" 63 #define BASE_NAME "BASE_NAME" 64 #define GUID "GUID" 65 #define FILE_GUID "FILE_GUID" 66 #define COMPONENT_TYPE_FILE "FILE" 67 #define BUILD_TYPE "BUILD_TYPE" 68 #define FFS_EXT "FFS_EXT" // FV_EXT is deprecated -- extension of FFS file 69 #define MAKEFILE_NAME "MAKEFILE_NAME" // name of component's output makefile 70 #define PLATFORM "PLATFORM" // for more granularity 71 #define PACKAGE_FILENAME "PACKAGE_FILENAME" 72 #define PACKAGE "PACKAGE" 73 #define PACKAGE_TAG "PACKAGE_TAG" // alternate name to PACKAGE 74 #define SHORT_NAMES "SHORT_NAMES" // for 8.3 names of symbols 75 #define APRIORI "APRIORI" // to add to apriori list 76 #define OPTIONAL_COMPONENT "OPTIONAL" // define as non-zero for optional INF files 77 #define SOURCE_SELECT "SOURCE_SELECT" // say SOURCE_SELECT=smm,common to select INF sources 78 #define NONFFS_FV "NONFFS_FV" // for non-FFS FV such as working & spare block FV 79 #define SKIP_FV_NULL "SKIP_FV_NULL" // define as nonzero to not build components with FV=NULL 80 #define SOURCE_COMPILE_TYPE "SOURCE_COMPILE_TYPE" // to build a source using a custom build section in the DSC file 81 #define SOURCE_FILE_EXTENSION "SOURCE_FILE_EXTENSION" 82 #define COMPILE_SELECT "COMPILE_SELECT" 83 #define SOURCE_OVERRIDE_PATH "SOURCE_OVERRIDE_PATH" // get source files from here first 84 #define MAKEFILE_OUT_SECTION_NAME "makefile.out" 85 #define COMMON_SECTION_NAME "common" // shared files or functionality 86 #define NMAKE_SECTION_NAME "nmake" 87 #define SOURCES_SECTION_NAME "sources" 88 #define COMPONENTS_SECTION_NAME "components" 89 #define INCLUDE_SECTION_NAME "includes" 90 #define DEFINES_SECTION_NAME "defines" 91 #define LIBRARIES_SECTION_NAME "libraries" 92 #define LIBRARIES_PLATFORM_SECTION_NAME "libraries.platform" 93 #define MAKEFILE_SECTION_NAME "makefile" 94 #define COMPONENT_TYPE "component_type" 95 #define PLATFORM_STR "\\platform\\" // to determine EFI_SOURCE 96 #define MAKEFILE_OUT_NAME "makefile.out" // if not specified on command line 97 #define MODULE_MAKEFILE_NAME "module.mak" // record all module makefile targets 98 #define MODULE_NAME_FILE "module.list" // record all module names defined in the dsc file 99 #define GLOBAL_LINK_LIB_NAME "CompilerStub" // Lib added in link option, maybe removed in the future 100 #define MODULE_BASE_NAME_WIDTH 25 // Width for module name output 101 102 // 103 // When a symbol is defined as "NULL", it gets saved in the symbol table as a 0-length 104 // string. Use this macro to detect if a symbol has been defined this way. 105 // 106 #define IS_NULL_SYMBOL_VALUE(var) ((var != NULL) && (strlen (var) == 0)) 107 108 // 109 // Defines for file types 110 // 111 #define FILETYPE_UNKNOWN 0 112 #define FILETYPE_C 1 113 #define FILETYPE_ASM 2 114 #define FILETYPE_S 3 115 #define FILETYPE_VFR 4 116 #define FILETYPE_INC 5 117 #define FILETYPE_H 6 118 #define FILETYPE_I 7 119 120 121 typedef struct { 122 INT8 *Extension; // file extension 123 INT8 *BuiltExtension; 124 INT8 FileFlags; 125 int FileType; 126 } FILETYPE; 127 128 // 129 // Define masks for the FileFlags field 130 // 131 #define FILE_FLAG_INCLUDE 0x01 132 #define FILE_FLAG_SOURCE 0x02 133 134 // 135 // This table describes a from-to list of files. For 136 // example, when a ".c" is built, it results in a ".obj" file. 137 // 138 static const FILETYPE mFileTypes[] = { 139 { 140 ".c", 141 ".obj", 142 FILE_FLAG_SOURCE, 143 FILETYPE_C 144 }, 145 { 146 ".asm", 147 ".obj", 148 FILE_FLAG_SOURCE, 149 FILETYPE_ASM 150 }, 151 { 152 ".s", 153 ".obj", 154 FILE_FLAG_SOURCE, 155 FILETYPE_S 156 }, 157 { 158 ".vfr", 159 ".obj", 160 FILE_FLAG_SOURCE, 161 FILETYPE_VFR 162 }, // actually *.vfr -> *.c -> *.obj 163 { 164 ".h", 165 NULL, 166 FILE_FLAG_INCLUDE, 167 FILETYPE_H 168 }, 169 { 170 ".inc", 171 NULL, 172 FILE_FLAG_INCLUDE, 173 FILETYPE_INC 174 }, 175 { 176 ".i", 177 NULL, 178 FILE_FLAG_INCLUDE, 179 FILETYPE_I 180 }, 181 { 182 NULL, 183 NULL, 184 0, 185 0 186 } 187 }; 188 189 // 190 // Structure to split up a file into its different parts. 191 // 192 typedef struct { 193 INT8 Drive[3]; 194 INT8 *Path; 195 INT8 *BaseName; 196 INT8 *Extension; 197 int ExtensionCode; 198 } FILE_NAME_PARTS; 199 200 // 201 // Maximum length for any line in any file after symbol expansion 202 // 203 #define MAX_EXP_LINE_LEN (MAX_LINE_LEN * 2) 204 205 // 206 // Linked list to keep track of all symbols 207 // 208 typedef struct _SYMBOL { 209 struct _SYMBOL *Next; 210 int Type; // local or global symbol 211 INT8 *Name; 212 INT8 *Value; 213 } SYMBOL; 214 215 // 216 // Module globals for multi-thread build 217 // 218 static BUILD_ITEM **mCurrentBuildList; // build list currently handling 219 static BUILD_ITEM *mCurrentBuildItem; // build item currently handling 220 221 // 222 // Define masks for the build targets 223 // 224 #define BUILD_TARGET_COMPONENTS 0x01 225 #define BUILD_TARGET_LIBRARIES 0x02 226 #define BUILD_TARGET_FVS 0x04 227 #define BUILD_TARGET_ALL 0xff 228 229 230 // 231 // This structure is used to save globals 232 // 233 struct { 234 INT8 *DscFilename; 235 SYMBOL *Symbol; 236 INT8 MakefileName[MAX_PATH]; // output makefile name 237 INT8 XRefFileName[MAX_PATH]; 238 INT8 GuidDatabaseFileName[MAX_PATH]; 239 INT8 ModuleMakefileName[MAX_PATH]; 240 FILE *MakefileFptr; 241 FILE *ModuleMakefileFptr; 242 SYMBOL *ModuleList; 243 SYMBOL *OutdirList; 244 UINT32 Verbose; 245 UINT32 ThreadNumber; 246 UINT32 BuildTarget; 247 BUILD_ITEM *LibraryList; 248 COMPONENTS_ITEM *ComponentsList; 249 } gGlobals; 250 251 // 252 // This gets dumped to the head of makefile.out 253 // 254 static const INT8 *MakefileHeader[] = { 255 "#/*++", 256 "#", 257 "# DO NOT EDIT", 258 "# File auto-generated by build utility", 259 "#", 260 "# Module Name:", 261 "#", 262 "# makefile", 263 "#", 264 "# Abstract:", 265 "#", 266 "# Auto-generated makefile for building of EFI components/libraries", 267 "#", 268 "#--*/", 269 "", 270 NULL 271 }; 272 273 // 274 // Function prototypes 275 // 276 static 277 int 278 ProcessOptions ( 279 int Argc, 280 INT8 *Argv[] 281 ); 282 283 static 284 void 285 Usage ( 286 VOID 287 ); 288 289 static 290 INT8 * 291 StripLine ( 292 INT8 *Line 293 ); 294 295 static 296 STATUS 297 ParseGuidDatabaseFile ( 298 INT8 *FileName 299 ); 300 301 #define DSC_SECTION_TYPE_COMPONENTS 0 302 #define DSC_SECTION_TYPE_LIBRARIES 1 303 #define DSC_SECTION_TYPE_PLATFORM_LIBRARIES 2 304 305 static 306 int 307 ProcessSectionComponents ( 308 DSC_FILE *DscFile, 309 int DscSectionType, 310 int Instance 311 ); 312 static 313 int 314 ProcessComponentFile ( 315 DSC_FILE *DscFile, 316 INT8 *Line, 317 int DscSectionType, 318 int Instance 319 ); 320 static 321 int 322 ProcessIncludeFiles ( 323 DSC_FILE *ComponentFile, 324 FILE *MakeFptr 325 ); 326 static 327 328 int 329 ProcessIncludeFilesSingle ( 330 DSC_FILE *ComponentFile, 331 FILE *MakeFptr, 332 INT8 *SectionName 333 ); 334 335 // 336 // Mode flags for processing source files 337 // 338 #define SOURCE_MODE_BUILD_COMMANDS 0x01 339 #define SOURCE_MODE_SOURCE_FILES 0x02 340 341 static 342 int 343 ProcessSourceFiles ( 344 DSC_FILE *DSCFile, 345 DSC_FILE *ComponentFile, 346 FILE *MakeFptr, 347 UINT32 Mode 348 ); 349 350 static 351 int 352 ProcessSourceFilesSection ( 353 DSC_FILE *DSCFile, 354 DSC_FILE *ComponentFile, 355 FILE *MakeFptr, 356 INT8 *SectionName, 357 UINT32 Mode 358 ); 359 360 static 361 int 362 ProcessObjects ( 363 DSC_FILE *ComponentFile, 364 FILE *MakeFptr 365 ); 366 367 static 368 int 369 ProcessObjectsSingle ( 370 DSC_FILE *ComponentFile, 371 FILE *MakeFptr, 372 INT8 *SectionName 373 ); 374 375 static 376 int 377 ProcessLibs ( 378 DSC_FILE *ComponentFile, 379 FILE *MakeFptr 380 ); 381 382 static 383 int 384 ProcessLibsSingle ( 385 DSC_FILE *ComponentFile, 386 FILE *MakeFptr, 387 INT8 *SectionName 388 ); 389 390 static 391 int 392 ProcessIncludesSection ( 393 DSC_FILE *ComponentFile, 394 FILE *MakeFptr 395 ); 396 397 static 398 int 399 ProcessIncludesSectionSingle ( 400 DSC_FILE *ComponentFile, 401 FILE *MakeFptr, 402 INT8 *SectionName 403 ); 404 405 static 406 int 407 ProcessINFNMakeSection ( 408 DSC_FILE *ComponentFile, 409 FILE *MakeFptr 410 ); 411 412 static 413 int 414 ProcessINFDefinesSection ( 415 DSC_FILE *ComponentFile 416 ); 417 418 static 419 int 420 ProcessINFDefinesSectionSingle ( 421 DSC_FILE *ComponentFile, 422 INT8 *SectionName 423 ); 424 425 static 426 int 427 ProcessSectionLibraries ( 428 DSC_FILE *DscFile, 429 long Offset 430 ); 431 432 static 433 int 434 ProcessDSCDefinesSection ( 435 DSC_FILE *DscFile 436 ); 437 438 static 439 int 440 SetSymbolType ( 441 INT8 *SymbolName, 442 INT8 Type 443 ); 444 445 static 446 int 447 RemoveLocalSymbols ( 448 VOID 449 ); 450 451 static 452 int 453 RemoveFileSymbols ( 454 VOID 455 ); 456 457 static 458 int 459 RemoveSymbol ( 460 INT8 *Name, 461 INT8 SymbolType 462 ); 463 464 static 465 int 466 SetFileExtension ( 467 INT8 *FileName, 468 INT8 *Extension 469 ); 470 471 static 472 int 473 GetSourceFileType ( 474 INT8 *FileName 475 ); 476 477 static 478 int 479 IsIncludeFile ( 480 INT8 *FileName 481 ); 482 483 static 484 int 485 WriteCompileCommands ( 486 DSC_FILE *DscFile, 487 FILE *MakeFptr, 488 INT8 *FileName, 489 INT8 *Processor 490 ); 491 492 static 493 int 494 WriteCommonMakefile ( 495 DSC_FILE *DscFile, 496 FILE *MakeFptr, 497 INT8 *Processor 498 ); 499 500 static 501 int 502 WriteComponentTypeBuildCommands ( 503 DSC_FILE *DscFile, 504 FILE *MakeFptr, 505 INT8 *SectionName 506 ); 507 508 static 509 void 510 StripTrailingSpaces ( 511 INT8 *Str 512 ); 513 514 static 515 void 516 FreeFileParts ( 517 FILE_NAME_PARTS *FP 518 ); 519 520 static 521 FILE_NAME_PARTS * 522 GetFileParts ( 523 INT8 *FileName 524 ); 525 526 static 527 SYMBOL * 528 FreeSymbols ( 529 SYMBOL *Syms 530 ); 531 532 static 533 int 534 GetEfiSource ( 535 VOID 536 ); 537 538 static 539 int 540 CreatePackageFile ( 541 DSC_FILE *DSCFile 542 ); 543 544 static 545 INT8 * 546 BuiltFileExtension ( 547 INT8 *SourceFileName 548 ); 549 550 static 551 void 552 SmartFree ( 553 SMART_FILE *SmartFile 554 ); 555 556 static 557 int 558 AddModuleName ( 559 SYMBOL **SymbolList, 560 INT8 *ModuleName, 561 INT8 *InfName 562 ); 563 564 static 565 void 566 ReplaceSlash ( 567 INT8 *Path 568 ); 569 570 /*****************************************************************************/ 571 int 572 main ( 573 int Argc, 574 INT8 *Argv[] 575 ) 576 /*++ 577 578 Routine Description: 579 580 Main utility entry point. 581 582 Arguments: 583 584 Argc - Standard app entry point args. 585 Argv - Standard app entry point args. 586 587 Returns: 588 589 0 if successful 590 non-zero otherwise 591 592 --*/ 593 { 594 int i; 595 DSC_FILE DSCFile; 596 SECTION *Sect; 597 INT8 Line[MAX_LINE_LEN]; 598 INT8 ExpLine[MAX_LINE_LEN]; 599 INT8 *BuildDir; 600 INT8 *EMsg; 601 FILE *FpModule; 602 SYMBOL *TempSymbol; 603 COMPONENTS_ITEM *TempComponents; 604 605 SetUtilityName (UTILITY_NAME); 606 607 InitExceptions (); 608 609 DSCFileInit (&DSCFile); 610 // 611 // Initialize the firmware volume data 612 // 613 CFVConstructor (); 614 // 615 // Exception handling for this block of code. 616 // 617 TryException (); 618 // 619 // Process command-line options. 620 // 621 if (ProcessOptions (Argc, Argv)) { 622 EMsg = CatchException (); 623 if (EMsg != NULL) { 624 fprintf (stderr, "%s\n", EMsg); 625 } 626 627 return STATUS_ERROR; 628 } 629 // 630 // Parse the GUID database file if specified 631 // 632 if (gGlobals.GuidDatabaseFileName[0] != 0) { 633 ParseGuidDatabaseFile (gGlobals.GuidDatabaseFileName); 634 } 635 // 636 // Set the output cross-reference file if applicable 637 // 638 if (gGlobals.XRefFileName[0]) { 639 CFVSetXRefFileName (gGlobals.XRefFileName); 640 } 641 642 // 643 // Now get the EFI_SOURCE directory which we use everywhere. 644 // 645 if (GetEfiSource ()) { 646 return STATUS_ERROR; 647 } 648 649 // 650 // Pre-process the DSC file to get section info. 651 // 652 if (DSCFileSetFile (&DSCFile, gGlobals.DscFilename) != 0) { 653 goto ProcessingError; 654 } 655 656 // 657 // Set output makefile name for single module build 658 // 659 strcpy (gGlobals.ModuleMakefileName, MODULE_MAKEFILE_NAME); 660 661 // 662 // Try to open all final output makefiles 663 // 664 if ((gGlobals.MakefileFptr = fopen (gGlobals.MakefileName, "w")) == NULL) { 665 Error (NULL, 0, 0, gGlobals.MakefileName, "failed to open output makefile for writing"); 666 goto ProcessingError; 667 } 668 if ((gGlobals.ModuleMakefileFptr = fopen (gGlobals.ModuleMakefileName, "w")) == NULL) { 669 Error (NULL, 0, 0, gGlobals.ModuleMakefileName, "failed to open output makefile for writing"); 670 goto ProcessingError; 671 } 672 673 // 674 // Write the header out to the makefiles 675 // 676 for (i = 0; MakefileHeader[i] != NULL; i++) { 677 fprintf (gGlobals.MakefileFptr, "%s\n", MakefileHeader[i]); 678 fprintf (gGlobals.ModuleMakefileFptr, "%s\n", MakefileHeader[i]); 679 } 680 681 // 682 // Init global potint = NULL 683 // 684 gGlobals.ModuleList = NULL; 685 gGlobals.OutdirList = NULL; 686 687 // 688 // Process the [defines] section in the DSC file to get any defines we need 689 // elsewhere 690 // 691 ProcessDSCDefinesSection (&DSCFile); 692 if (ExceptionThrown ()) { 693 goto ProcessingError; 694 } 695 // 696 // Write out the [makefile.out] section data to the output makefiles 697 // 698 Sect = DSCFileFindSection (&DSCFile, MAKEFILE_OUT_SECTION_NAME); 699 if (Sect != NULL) { 700 while (DSCFileGetLine (&DSCFile, Line, sizeof (Line)) != NULL) { 701 ExpandSymbols (Line, ExpLine, sizeof (ExpLine), 0); 702 // 703 // Write the line to the output makefiles 704 // 705 fprintf (gGlobals.MakefileFptr, ExpLine); 706 fprintf (gGlobals.ModuleMakefileFptr, ExpLine); 707 } 708 } 709 710 // 711 // Add a pseudo target for GLOBAL_LINK_LIB_NAME to avoid single module build 712 // failure when this lib is not used. 713 // 714 fprintf (gGlobals.ModuleMakefileFptr, "%sbuild ::\n\n", GLOBAL_LINK_LIB_NAME); 715 716 fprintf (gGlobals.MakefileFptr, "libraries : \n"); 717 // 718 // Process [libraries] section in the DSC file 719 // 720 Sect = DSCFileFindSection (&DSCFile, LIBRARIES_SECTION_NAME); 721 if (Sect != NULL) { 722 mCurrentBuildList = &gGlobals.LibraryList; 723 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_LIBRARIES, 0); 724 } 725 726 if (ExceptionThrown ()) { 727 goto ProcessingError; 728 } 729 // 730 // Process [libraries.platform] section in the DSC file 731 // 732 Sect = DSCFileFindSection (&DSCFile, LIBRARIES_PLATFORM_SECTION_NAME); 733 if (Sect != NULL) { 734 mCurrentBuildList = &gGlobals.LibraryList; 735 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_PLATFORM_LIBRARIES, 0); 736 } 737 738 fprintf (gGlobals.MakefileFptr, "\n"); 739 if (ExceptionThrown ()) { 740 goto ProcessingError; 741 } 742 743 // 744 // Process [components] section in the DSC file 745 // 746 Sect = DSCFileFindSection (&DSCFile, COMPONENTS_SECTION_NAME); 747 if (Sect != NULL) { 748 fprintf (gGlobals.MakefileFptr, "components_0 : \n"); 749 TempComponents = AddComponentsItem (&gGlobals.ComponentsList); 750 mCurrentBuildList = &TempComponents->BuildList; 751 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, 0); 752 fprintf (gGlobals.MakefileFptr, "\n"); 753 } 754 755 if (ExceptionThrown ()) { 756 goto ProcessingError; 757 } 758 // 759 // Now cycle through all [components.1], [components.2], ....[components.n]. 760 // This is necessary to support building of firmware volumes that may contain 761 // other encapsulated firmware volumes (ala capsules). 762 // 763 i = 1; 764 while (1) { 765 RemoveSymbol (FV, SYM_GLOBAL); 766 sprintf (Line, "%s.%d", COMPONENTS_SECTION_NAME, i); 767 Sect = DSCFileFindSection (&DSCFile, Line); 768 if (Sect != NULL) { 769 fprintf (gGlobals.MakefileFptr, "components_%d : \n", i); 770 TempComponents = AddComponentsItem (&gGlobals.ComponentsList); 771 mCurrentBuildList = &TempComponents->BuildList; 772 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, i); 773 fprintf (gGlobals.MakefileFptr, "\n"); 774 } else { 775 break; 776 } 777 778 if (ExceptionThrown ()) { 779 goto ProcessingError; 780 } 781 782 i++; 783 } 784 785 ProcessingError: 786 EMsg = CatchException (); 787 if (EMsg != NULL) { 788 fprintf (stderr, "%s\n", EMsg); 789 fprintf (stderr, "Processing aborted\n"); 790 } 791 792 TryException (); 793 // 794 // Create the FV files if no fatal errors or errors 795 // 796 if (GetUtilityStatus () < STATUS_ERROR) { 797 CFVWriteInfFiles (&DSCFile, gGlobals.MakefileFptr); 798 } 799 800 // 801 // Write all module name into MODULE_NAME_FILE file. 802 // 803 if ((FpModule = fopen (MODULE_NAME_FILE, "w")) != NULL) { 804 TempSymbol = gGlobals.ModuleList; 805 while (TempSymbol != NULL) { 806 fprintf (FpModule, " %-*s %s \n", MODULE_BASE_NAME_WIDTH, TempSymbol->Name, TempSymbol->Value); 807 TempSymbol = TempSymbol->Next; 808 } 809 fclose (FpModule); 810 FpModule = NULL; 811 } 812 813 // 814 // Close the all the output makefiles 815 // 816 if (gGlobals.MakefileFptr != NULL) { 817 fclose (gGlobals.MakefileFptr); 818 gGlobals.MakefileFptr = NULL; 819 } 820 821 if (gGlobals.ModuleMakefileFptr != NULL) { 822 fclose (gGlobals.ModuleMakefileFptr); 823 gGlobals.ModuleMakefileFptr = NULL; 824 } 825 826 // 827 // Start multi-thread build if ThreadNumber is specified and no error status 828 // 829 if ((gGlobals.ThreadNumber != 0) && (GetUtilityStatus () < STATUS_ERROR)) { 830 BuildDir = GetSymbolValue (BUILD_DIR); 831 if (gGlobals.BuildTarget & BUILD_TARGET_LIBRARIES) { 832 if (StartMultiThreadBuild (&gGlobals.LibraryList, gGlobals.ThreadNumber, BuildDir) != 0) { 833 Error (NULL, 0, 0, NULL, "Multi-thread build libraries failure"); 834 goto Cleanup; 835 } 836 } 837 i = 0; 838 TempComponents = gGlobals.ComponentsList; 839 while (TempComponents != NULL) { 840 if (gGlobals.BuildTarget & BUILD_TARGET_COMPONENTS) { 841 if (StartMultiThreadBuild (&TempComponents->BuildList, gGlobals.ThreadNumber, BuildDir) != 0) { 842 Error (NULL, 0, 0, NULL, "Multi-thread build components %d failure", i); 843 goto Cleanup; 844 } 845 } 846 if (gGlobals.BuildTarget & BUILD_TARGET_FVS) { 847 sprintf (ExpLine, "nmake -nologo -f %s fvs_%d", gGlobals.MakefileName, i); 848 _flushall (); 849 if (system (ExpLine)) { 850 Error (NULL, 0, 0, NULL, "Build FVs for components %d failure", i); 851 goto Cleanup; 852 } 853 } 854 i++; 855 TempComponents = TempComponents->Next; 856 } 857 } 858 859 Cleanup: 860 // 861 // Clean up 862 // 863 FreeBuildList (gGlobals.LibraryList); 864 gGlobals.LibraryList = NULL; 865 FreeComponentsList (gGlobals.ComponentsList); 866 gGlobals.ComponentsList = NULL; 867 FreeSymbols (gGlobals.ModuleList); 868 gGlobals.ModuleList = NULL; 869 FreeSymbols (gGlobals.OutdirList); 870 gGlobals.OutdirList = NULL; 871 FreeSymbols (gGlobals.Symbol); 872 gGlobals.Symbol = NULL; 873 CFVDestructor (); 874 DSCFileDestroy (&DSCFile); 875 876 EMsg = CatchException (); 877 if (EMsg != NULL) { 878 fprintf (stderr, "%s\n", EMsg); 879 fprintf (stderr, "Processing aborted\n"); 880 } 881 882 return GetUtilityStatus (); 883 } 884 885 static 886 int 887 ProcessSectionComponents ( 888 DSC_FILE *DSCFile, 889 int DscSectionType, 890 int Instance 891 ) 892 /*++ 893 894 Routine Description: 895 896 Process the [components] or [libraries] section in the description file. We 897 use this function for both since they're very similar. Here we just 898 read each line from the section, and if it's valid, call a function to 899 do the actual processing of the component description file. 900 901 Arguments: 902 903 DSCFile - structure containing section info on the description file 904 DscSectionType - type of description section 905 906 Returns: 907 908 0 if successful 909 910 --*/ 911 { 912 INT8 Line[MAX_LINE_LEN]; 913 INT8 Line2[MAX_EXP_LINE_LEN]; 914 INT8 *Cptr; 915 916 // 917 // Read lines while they're valid 918 // 919 while (DSCFileGetLine (DSCFile, Line, sizeof (Line)) != NULL) { 920 // 921 // Expand symbols on the line 922 // 923 if (ExpandSymbols (Line, Line2, sizeof (Line2), 0)) { 924 return STATUS_ERROR; 925 } 926 // 927 // Strip the line 928 // 929 Cptr = StripLine (Line2); 930 if (*Cptr) { 931 Message (2, "Processing component line: %s", Line2); 932 if (ProcessComponentFile (DSCFile, Line2, DscSectionType, Instance) != 0) { 933 return STATUS_ERROR; 934 } 935 } 936 } 937 938 return 0; 939 } 940 941 static 942 int 943 ProcessComponentFile ( 944 DSC_FILE *DSCFile, 945 INT8 *ArgLine, 946 int DscSectionType, 947 int Instance 948 ) 949 /*++ 950 951 Routine Description: 952 953 Given a line from the [components] or [libraries] section of the description 954 file, process the line to extract the component's INF filename and 955 parameters. Then open the INF file and process it to create a corresponding 956 makefile. 957 958 Arguments: 959 960 DSCFile The project DSC file info structure. 961 Libs Indicates whether we're processing the [components] 962 section or the [libraries] section. 963 ArgLine The actual line from the DSC file. Looks something like 964 one of the following: 965 966 dxe\drivers\vm\vm.dsc PROCESSOR=IA32 DEST_DIR=$(DEST_DIR)\xxx FV=FV1,FV2 967 $(BUILD_DIR).\FvVariable.ffs COMPONENT_TYPE=FILE 968 .\FvVariable.ffs COMPONENT_TYPE=FILE 969 define VAR1=value1 VAR2=value2 970 971 Returns: 972 973 0 if successful 974 975 --*/ 976 { 977 FILE *MakeFptr; 978 FILE *TempFptr; 979 INT8 *Cptr; 980 INT8 *name; 981 INT8 *End; 982 INT8 *TempCptr; 983 INT8 FileName[MAX_PATH]; 984 INT8 ComponentFilePath[MAX_PATH]; 985 INT8 InLine[MAX_LINE_LEN]; 986 INT8 Line[MAX_LINE_LEN]; 987 INT8 *Processor; 988 INT8 SymType; 989 int Len; 990 int ComponentCreated; 991 int ComponentFilePathAbsolute; 992 int DefineLine; 993 DSC_FILE ComponentFile; 994 INT8 ComponentMakefileName[MAX_PATH]; 995 BOOLEAN IsForFv; 996 997 // 998 // Now remove all local symbols 999 // 1000 RemoveLocalSymbols (); 1001 // 1002 // Null out the file pointer in case we take an exception somewhere 1003 // and we need to close it only if we opened it. 1004 // 1005 MakeFptr = NULL; 1006 ComponentFilePathAbsolute = 0; 1007 ComponentCreated = 0; 1008 // 1009 // Skip preceeding spaces on the line 1010 // 1011 while (isspace (*ArgLine) && (*ArgLine)) { 1012 ArgLine++; 1013 } 1014 // 1015 // Find the end of the component's filename and truncate the line at that 1016 // point. From here on out ArgLine is the name of the component filename. 1017 // 1018 Cptr = ArgLine; 1019 while (!isspace (*Cptr) && *Cptr) { 1020 Cptr++; 1021 } 1022 1023 End = Cptr; 1024 if (*Cptr) { 1025 End++; 1026 *Cptr = 0; 1027 } 1028 // 1029 // Exception-handle processing of this component description file 1030 // 1031 TryException (); 1032 1033 // 1034 // We also allow a component line format for defines of global symbols 1035 // instead of a component filename. In this case, the line looks like: 1036 // defines x=abc y=yyy. Be nice and accept "define" and "defines" in a 1037 // case-insensitive manner. If it's defines, then make the symbols global. 1038 // 1039 if ((_stricmp (ArgLine, "define") == 0) || (_stricmp (ArgLine, "defines") == 0)) { 1040 SymType = SYM_OVERWRITE | SYM_GLOBAL; 1041 DefineLine = 1; 1042 } else { 1043 SymType = SYM_OVERWRITE | SYM_LOCAL; 1044 DefineLine = 0; 1045 } 1046 // 1047 // The rest of the component line from the DSC file should be defines 1048 // 1049 while (*End) { 1050 End = StripLine (End); 1051 if (*End) { 1052 // 1053 // If we're processing a "define abc=1 xyz=2" line, then set symbols 1054 // as globals per the SymType set above. 1055 // 1056 Len = AddSymbol (End, NULL, SymType); 1057 if (Len > 0) { 1058 End += Len; 1059 } else { 1060 Warning (NULL, 0, 0, ArgLine, "unrecognized option in description file"); 1061 break; 1062 } 1063 } 1064 } 1065 1066 // 1067 // If DEBUG_BREAK or EFI_BREAKPOINT is defined, then do a debug breakpoint. 1068 // 1069 if ((GetSymbolValue ("DEBUG_BREAK") != NULL) || (GetSymbolValue ("EFI_BREAKPOINT") != NULL)) { 1070 EFI_BREAKPOINT (); 1071 } 1072 1073 // 1074 // If it's a define line, then we're done 1075 // 1076 if (DefineLine) { 1077 // 1078 // If there is NonFFS_FV, create the FVxxx.inf file 1079 // and include it in makefile.out. Remove the symbol 1080 // in order not to process it again next time 1081 // 1082 Cptr = GetSymbolValue (NONFFS_FV); 1083 if (Cptr != NULL) { 1084 NonFFSFVWriteInfFiles (DSCFile, Cptr); 1085 RemoveSymbol (NONFFS_FV, SYM_GLOBAL); 1086 } 1087 1088 goto ComponentDone; 1089 } 1090 1091 // 1092 // Expand symbols in the component description filename to expand the newly 1093 // added local symbols 1094 // 1095 ExpandSymbols (ArgLine, Line, sizeof (Line), EXPANDMODE_NO_UNDEFS); 1096 1097 // 1098 // If we have "c:\path\filename" 1099 // 1100 ReplaceSlash (Line); 1101 if (IsAbsolutePath (Line)) { 1102 ComponentFilePathAbsolute = 1; 1103 } else if (Line[0] == '.') { 1104 // 1105 // or if the path starts with ".", then it's build-dir relative. 1106 // Prepend $(BUILD_DIR) on the file name 1107 // 1108 sprintf (InLine, "%s\\%s", GetSymbolValue (BUILD_DIR), Line); 1109 strcpy (Line, InLine); 1110 ComponentFilePathAbsolute = 1; 1111 } 1112 1113 // 1114 // Save the path from the component name for later. It may be relative or 1115 // absolute. 1116 // 1117 strcpy (ComponentFilePath, Line); 1118 Cptr = ComponentFilePath + strlen (ComponentFilePath) - 1; 1119 while ((*Cptr != '\\') && (Cptr != ComponentFilePath)) { 1120 Cptr--; 1121 } 1122 // 1123 // Terminate the path. 1124 // 1125 *Cptr = 0; 1126 1127 // 1128 // Typically the given line is a component description filename. However we 1129 // also allow a FV filename (fvvariable.ffs COMPONENT_TYPE=FILE). If the 1130 // component type is "FILE", then add it to the FV list, create a package 1131 // file, and we're done. 1132 // 1133 Cptr = GetSymbolValue (COMPONENT_TYPE); 1134 if ((Cptr != NULL) && (strncmp ( 1135 Cptr, 1136 COMPONENT_TYPE_FILE, 1137 strlen (COMPONENT_TYPE_FILE) 1138 ) == 0)) { 1139 if (ComponentFilePathAbsolute) { 1140 strcpy (InLine, Line); 1141 } else { 1142 sprintf (InLine, "%s\\%s", GetSymbolValue (EFI_SOURCE), Line); 1143 } 1144 CFVAddFVFile ( 1145 InLine, 1146 Cptr, 1147 GetSymbolValue (FV), 1148 Instance, 1149 NULL, 1150 NULL, 1151 GetSymbolValue (APRIORI), 1152 NULL, 1153 NULL 1154 ); 1155 goto ComponentDone; 1156 } 1157 1158 // 1159 // Better have defined processor by this point. 1160 // 1161 Processor = GetSymbolValue (PROCESSOR); 1162 if (Processor == NULL) { 1163 Error (NULL, 0, 0, NULL, "PROCESSOR not defined for component %s", Line); 1164 return STATUS_ERROR; 1165 } 1166 1167 // 1168 // The bin, out, and lib dirs are now = $(BUILD_DIR)/$(PROCESSOR). Set them. 1169 // Don't flag them as file paths (required for short 8.3 filenames) since 1170 // they're defined using the BUILD_DIR macro. 1171 // 1172 sprintf (InLine, "$(BUILD_DIR)\\%s", Processor); 1173 AddSymbol (BIN_DIR, InLine, SYM_LOCAL); 1174 AddSymbol (OUT_DIR, InLine, SYM_LOCAL); 1175 AddSymbol (LIB_DIR, InLine, SYM_LOCAL); 1176 // 1177 // See if it's been destined for an FV. It's possible to not be in an 1178 // FV if they just want to build it. 1179 // 1180 Cptr = GetSymbolValue (FV); 1181 if ((Cptr != NULL) && !IS_NULL_SYMBOL_VALUE (Cptr)) { 1182 IsForFv = TRUE; 1183 } else { 1184 IsForFv = FALSE; 1185 } 1186 // 1187 // As an optimization, if they've defined SKIP_FV_NULL as non-zero, and 1188 // the component is not destined for an FV, then skip it. 1189 // Since libraries are never intended for firmware volumes, we have to 1190 // build all of them. 1191 // 1192 if ((DscSectionType == DSC_SECTION_TYPE_COMPONENTS) && (IsForFv == FALSE)) { 1193 if ((GetSymbolValue (SKIP_FV_NULL) != NULL) && (atoi (GetSymbolValue (SKIP_FV_NULL)) != 0)) { 1194 Message (0, "%s not being built (FV=NULL)", FileName); 1195 goto ComponentDone; 1196 } 1197 } 1198 // 1199 // Prepend EFI_SOURCE to the component description file to get the 1200 // full path. Only do this if the path is not a full path already. 1201 // 1202 if (ComponentFilePathAbsolute == 0) { 1203 name = GetSymbolValue (EFI_SOURCE); 1204 sprintf (FileName, "%s\\%s", name, Line); 1205 } else { 1206 strcpy (FileName, Line); 1207 } 1208 // 1209 // Print a message, depending on verbose level. 1210 // 1211 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { 1212 Message (1, "Processing component %s", FileName); 1213 } else { 1214 Message (1, "Processing library %s", FileName); 1215 } 1216 // 1217 // Open the component's description file and get the sections. If we fail 1218 // to open it, see if they defined "OPTIONAL=1, in which case we'll just 1219 // ignore the component. 1220 // 1221 TempFptr = fopen (FileName, "r"); 1222 if (TempFptr == NULL) { 1223 // 1224 // Better have defined OPTIONAL 1225 // 1226 if (GetSymbolValue (OPTIONAL_COMPONENT) != NULL) { 1227 if (atoi (GetSymbolValue (OPTIONAL_COMPONENT)) != 0) { 1228 Message (0, "Optional component '%s' not found", FileName); 1229 goto ComponentDone; 1230 } 1231 } 1232 1233 ParserError (0, FileName, "failed to open component file"); 1234 return STATUS_ERROR; 1235 } else { 1236 fclose (TempFptr); 1237 } 1238 1239 DSCFileInit (&ComponentFile); 1240 ComponentCreated = 1; 1241 if (DSCFileSetFile (&ComponentFile, FileName)) { 1242 Error (NULL, 0, 0, NULL, "failed to preprocess component file '%s'", FileName); 1243 return STATUS_ERROR; 1244 } 1245 // 1246 // Add a symbol for the INF filename so users can create dependencies 1247 // in makefiles. 1248 // 1249 AddSymbol (INF_FILENAME, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME); 1250 // 1251 // Process the [defines], [defines.$(PROCESSOR)], and [defines.$(PROCESSOR).$(PLATFORM)] 1252 // sections in the INF file 1253 // 1254 ProcessINFDefinesSection (&ComponentFile); 1255 // 1256 // Better have defined FILE_GUID if not a library 1257 // 1258 if ((GetSymbolValue (GUID) == NULL) && 1259 (GetSymbolValue (FILE_GUID) == NULL) && 1260 (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) 1261 ) { 1262 Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing FILE_GUID definition in component file"); 1263 DSCFileDestroy (&ComponentFile); 1264 return STATUS_ERROR; 1265 } 1266 // 1267 // Better have defined base name 1268 // 1269 if (GetSymbolValue (BASE_NAME) == NULL) { 1270 Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing BASE_NAME definition in INF file"); 1271 DSCFileDestroy (&ComponentFile); 1272 return STATUS_ERROR; 1273 } 1274 // 1275 // Better have defined COMPONENT_TYPE, since it's used to find named sections. 1276 // 1277 if (GetSymbolValue (COMPONENT_TYPE) == NULL) { 1278 Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing COMPONENT_TYPE definition in INF file"); 1279 DSCFileDestroy (&ComponentFile); 1280 return STATUS_ERROR; 1281 } 1282 1283 // 1284 // Create the source directory path from the component file's path. If the component 1285 // file's path is absolute, we may have problems here. Try to account for it though. 1286 // 1287 if (ComponentFilePathAbsolute == 0) { 1288 sprintf ( 1289 FileName, 1290 "%s\\%s", 1291 GetSymbolValue (EFI_SOURCE), 1292 ComponentFilePath 1293 ); 1294 } else { 1295 strcpy (FileName, ComponentFilePath); 1296 } 1297 AddSymbol (SOURCE_DIR, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILEPATH); 1298 1299 // 1300 // Create the destination path. 1301 // They may have defined DEST_DIR on the component INF line, so it's already 1302 // been defined, If that's the case, then don't set it to the path of this file. 1303 // 1304 TempCptr = GetSymbolValue (DEST_DIR); 1305 if (TempCptr == NULL) { 1306 if (ComponentFilePathAbsolute == 0) { 1307 // 1308 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\component_path 1309 // 1310 sprintf ( 1311 FileName, 1312 "%s\\%s\\%s", 1313 GetSymbolValue (BUILD_DIR), 1314 Processor, 1315 ComponentFilePath 1316 ); 1317 } else { 1318 // 1319 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\$(BASE_NAME) 1320 // 1321 sprintf ( 1322 FileName, 1323 "%s\\%s\\%s", 1324 GetSymbolValue (BUILD_DIR), 1325 Processor, 1326 GetSymbolValue (BASE_NAME) 1327 ); 1328 } 1329 AddSymbol (DEST_DIR, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILEPATH); 1330 } else { 1331 ReplaceSlash (TempCptr); 1332 } 1333 1334 // 1335 // Create the output directory, then open the output component's makefile 1336 // we're going to create. Allow them to override the makefile name. 1337 // 1338 TempCptr = GetSymbolValue (MAKEFILE_NAME); 1339 if (TempCptr != NULL) { 1340 ExpandSymbols (TempCptr, ComponentMakefileName, sizeof (ComponentMakefileName), EXPANDMODE_NO_UNDEFS); 1341 TempCptr = ComponentMakefileName; 1342 } else { 1343 TempCptr = "makefile"; 1344 } 1345 1346 sprintf (FileName, "%s\\%s", GetSymbolValue (DEST_DIR), TempCptr); 1347 // 1348 // Save it now with path info 1349 // 1350 AddSymbol (MAKEFILE_NAME, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME); 1351 1352 if (MakeFilePath (FileName)) { 1353 return STATUS_ERROR; 1354 } 1355 1356 if ((MakeFptr = fopen (FileName, "w")) == NULL) { 1357 Error (NULL, 0, 0, FileName, "could not create makefile"); 1358 return STATUS_ERROR; 1359 } 1360 // 1361 // At this point we should have all the info we need to create a package 1362 // file if setup to do so. Libraries don't use package files, so 1363 // don't do this for libs. 1364 // 1365 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { 1366 CreatePackageFile (DSCFile); 1367 } 1368 1369 // 1370 // Add a new build item to mCurrentBuildList 1371 // 1372 mCurrentBuildItem = AddBuildItem (mCurrentBuildList, GetSymbolValue (BASE_NAME), Processor, FileName); 1373 // 1374 // ProcessDsc allows duplicate base name libraries. Make sure the duplicate 1375 // base name libraries will be built in the same order as listed in DSC file. 1376 // 1377 AddDependency (*mCurrentBuildList, mCurrentBuildItem, mCurrentBuildItem->BaseName, 1); 1378 1379 // 1380 // Add Module name to the global module list 1381 // 1382 AddModuleName (&gGlobals.ModuleList, GetSymbolValue (BASE_NAME), GetSymbolValue (INF_FILENAME)); 1383 // 1384 // Write an nmake line to makefile.out 1385 // 1386 fprintf (gGlobals.MakefileFptr, " @cd %s\n", Processor); 1387 fprintf (gGlobals.MakefileFptr, " $(MAKE) -f %s all\n", FileName); 1388 fprintf (gGlobals.MakefileFptr, " @cd ..\n"); 1389 1390 // 1391 // Copy the common makefile section from the description file to 1392 // the component's makefile 1393 // 1394 WriteCommonMakefile (DSCFile, MakeFptr, Processor); 1395 // 1396 // Process the component's [nmake.common] and [nmake.$(PROCESSOR)] sections 1397 // 1398 ProcessINFNMakeSection (&ComponentFile, MakeFptr); 1399 // 1400 // Create the SOURCE_FILES macro that includes the names of all source 1401 // files in this component. This macro can then be used elsewhere to 1402 // process all the files making up the component. Required for scanning 1403 // files for string localization. 1404 // Also add source files to mCurrentBuildItem. 1405 // 1406 ProcessSourceFiles (DSCFile, &ComponentFile, MakeFptr, SOURCE_MODE_SOURCE_FILES); 1407 // 1408 // Create the include paths. Process [includes.common] and 1409 // [includes.$(PROCESSOR)] and [includes.$(PROCESSOR).$(PLATFORM)] sections. 1410 // 1411 ProcessIncludesSection (&ComponentFile, MakeFptr); 1412 // 1413 // Process all include source files to create a dependency list that can 1414 // be used in the makefile. 1415 // 1416 ProcessIncludeFiles (&ComponentFile, MakeFptr); 1417 // 1418 // Process the [sources.common], [sources.$(PROCESSOR)], and 1419 // [sources.$(PROCESSOR).$(PLATFORM)] files and emit their build commands 1420 // 1421 ProcessSourceFiles (DSCFile, &ComponentFile, MakeFptr, SOURCE_MODE_BUILD_COMMANDS); 1422 // 1423 // Process sources again to create an OBJECTS macro 1424 // 1425 ProcessObjects (&ComponentFile, MakeFptr); 1426 1427 // 1428 // Add Single Module target : build and clean in top level makefile 1429 // 1430 fprintf (gGlobals.ModuleMakefileFptr, "%sbuild ::", GetSymbolValue (BASE_NAME)); 1431 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { 1432 fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", GLOBAL_LINK_LIB_NAME); 1433 } 1434 1435 // 1436 // Process all the libraries to define "LIBS = x.lib y.lib..." 1437 // Be generous and append ".lib" if they forgot. 1438 // Make a macro definition: LIBS = $(LIBS) xlib.lib ylib.lib... 1439 // Add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ... 1440 // Also add libs dependency to mCurrentBuildItem. 1441 // 1442 ProcessLibs (&ComponentFile, MakeFptr); 1443 1444 fprintf (gGlobals.ModuleMakefileFptr, "\n"); 1445 1446 fprintf (gGlobals.ModuleMakefileFptr, " @cd %s\n", Processor); 1447 fprintf (gGlobals.ModuleMakefileFptr, " $(MAKE) -f %s all\n", FileName); 1448 fprintf (gGlobals.ModuleMakefileFptr, " @cd ..\n\n"); 1449 1450 fprintf (gGlobals.ModuleMakefileFptr, "%sclean ::\n", GetSymbolValue (BASE_NAME)); 1451 fprintf (gGlobals.ModuleMakefileFptr, " $(MAKE) -f %s clean\n\n", FileName); 1452 1453 // 1454 // Emit commands to create the component. These are simply copied from 1455 // the description file to the component's makefile. First look for 1456 // [build.$(PROCESSOR).$(BUILD_TYPE)]. If not found, then look for if 1457 // find a [build.$(PROCESSOR).$(COMPONENT_TYPE)] line. 1458 // 1459 Cptr = GetSymbolValue (BUILD_TYPE); 1460 if (Cptr != NULL) { 1461 sprintf (InLine, "build.%s.%s", Processor, Cptr); 1462 WriteComponentTypeBuildCommands (DSCFile, MakeFptr, InLine); 1463 } else { 1464 sprintf (InLine, "build.%s.%s", Processor, GetSymbolValue (COMPONENT_TYPE)); 1465 WriteComponentTypeBuildCommands (DSCFile, MakeFptr, InLine); 1466 } 1467 // 1468 // Add it to the FV if not a library 1469 // 1470 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { 1471 // 1472 // Create the FV filename and add it to the FV. 1473 // By this point we know it's in FV. 1474 // 1475 Cptr = GetSymbolValue (FILE_GUID); 1476 if (Cptr == NULL) { 1477 Cptr = GetSymbolValue (GUID); 1478 } 1479 1480 sprintf (InLine, "%s-%s", Cptr, GetSymbolValue (BASE_NAME)); 1481 // 1482 // We've deprecated FV_EXT, which should be FFS_EXT, the extension 1483 // of the FFS file generated by GenFFSFile. 1484 // 1485 TempCptr = GetSymbolValue (FFS_EXT); 1486 if (TempCptr == NULL) { 1487 TempCptr = GetSymbolValue ("FV_EXT"); 1488 } 1489 1490 CFVAddFVFile ( 1491 InLine, 1492 GetSymbolValue (COMPONENT_TYPE), 1493 GetSymbolValue (FV), 1494 Instance, 1495 TempCptr, 1496 Processor, 1497 GetSymbolValue (APRIORI), 1498 GetSymbolValue (BASE_NAME), 1499 Cptr 1500 ); 1501 } 1502 // 1503 // Catch any failures and print the name of the component file 1504 // being processed to assist debugging. 1505 // 1506 ComponentDone: 1507 1508 Cptr = CatchException (); 1509 if (Cptr != NULL) { 1510 fprintf (stderr, "%s\n", Cptr); 1511 sprintf (InLine, "Processing of component %s failed", ArgLine); 1512 ThrowException (InLine); 1513 } 1514 1515 if (MakeFptr != NULL) { 1516 fclose (MakeFptr); 1517 } 1518 1519 if (ComponentCreated) { 1520 DSCFileDestroy (&ComponentFile); 1521 } 1522 1523 return STATUS_SUCCESS; 1524 } 1525 1526 static 1527 int 1528 CreatePackageFile ( 1529 DSC_FILE *DSCFile 1530 ) 1531 { 1532 INT8 *Package; 1533 SECTION *TempSect; 1534 INT8 Str[MAX_LINE_LEN]; 1535 INT8 StrExpanded[MAX_LINE_LEN]; 1536 SMART_FILE *PkgFptr; 1537 int Status; 1538 1539 PkgFptr = NULL; 1540 1541 // 1542 // First find out if PACKAGE_FILENAME or PACKAGE is defined. PACKAGE_FILENAME 1543 // is used to specify the exact package file to use. PACKAGE is used to 1544 // specify the package section name. 1545 // 1546 Package = GetSymbolValue (PACKAGE_FILENAME); 1547 if (Package != NULL) { 1548 // 1549 // Use existing file. We're done. 1550 // 1551 return STATUS_SUCCESS; 1552 } 1553 // 1554 // See if PACKAGE or PACKAGE_TAG is defined 1555 // 1556 Package = GetSymbolValue (PACKAGE); 1557 if (Package == NULL) { 1558 Package = GetSymbolValue (PACKAGE_TAG); 1559 } 1560 1561 if (Package == NULL) { 1562 // 1563 // Not defined either. Assume they are not using the package functionality 1564 // of this utility. However define the PACKAGE_FILENAME macro to the 1565 // best-guess value. 1566 // 1567 sprintf ( 1568 Str, 1569 "%s\\%s.pkg", 1570 GetSymbolValue (SOURCE_DIR), 1571 GetSymbolValue (BASE_NAME) 1572 ); 1573 1574 // 1575 // Expand symbols in the package filename 1576 // 1577 ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_NO_UNDEFS); 1578 1579 AddSymbol (PACKAGE_FILENAME, StrExpanded, SYM_LOCAL | SYM_FILENAME); 1580 return STATUS_SUCCESS; 1581 } 1582 // 1583 // Save the position in the DSC file. 1584 // Find the [package.$(COMPONENT_TYPE).$(PACKAGE)] section in the DSC file 1585 // 1586 Status = STATUS_SUCCESS; 1587 DSCFileSavePosition (DSCFile); 1588 sprintf (Str, "%s.%s.%s", PACKAGE, GetSymbolValue (COMPONENT_TYPE), Package); 1589 TempSect = DSCFileFindSection (DSCFile, Str); 1590 if (TempSect != NULL) { 1591 // 1592 // So far so good. Create the name of the package file, then open it up 1593 // for writing. File name is c:\...\oem\platform\nt32\ia32\...\BaseName.pkg. 1594 // 1595 sprintf ( 1596 Str, 1597 "%s\\%s.pkg", 1598 GetSymbolValue (DEST_DIR), 1599 GetSymbolValue (BASE_NAME) 1600 ); 1601 1602 // 1603 // Expand symbols in the package filename 1604 // 1605 ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_NO_UNDEFS); 1606 1607 // 1608 // Try to open the file, then save the file name as the PACKAGE_FILENAME 1609 // symbol for use elsewhere. 1610 // 1611 if ((PkgFptr = SmartOpen (StrExpanded)) == NULL) { 1612 Error (NULL, 0, 0, Str, "could not open package file for writing"); 1613 Status = STATUS_ERROR; 1614 goto Finish; 1615 } 1616 1617 AddSymbol (PACKAGE_FILENAME, StrExpanded, SYM_LOCAL | SYM_FILENAME); 1618 // 1619 // Now read lines in from the DSC file and write them back out to the 1620 // package file (with string substitution). 1621 // 1622 while (DSCFileGetLine (DSCFile, Str, sizeof (Str)) != NULL) { 1623 // 1624 // Expand symbols, then write the line out to the package file 1625 // 1626 ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_RECURSIVE); 1627 SmartWrite (PkgFptr, StrExpanded); 1628 } 1629 } else { 1630 Warning ( 1631 NULL, 1632 0, 1633 0, 1634 NULL, 1635 "cannot locate package section [%s] in DSC file for %s", 1636 Str, 1637 GetSymbolValue (INF_FILENAME) 1638 ); 1639 Status = STATUS_WARNING; 1640 goto Finish; 1641 } 1642 1643 if (PkgFptr != NULL) { 1644 SmartClose (PkgFptr); 1645 } 1646 1647 Finish: 1648 // 1649 // Restore the position in the DSC file 1650 // 1651 DSCFileRestorePosition (DSCFile); 1652 1653 return STATUS_SUCCESS; 1654 } 1655 1656 static 1657 int 1658 ProcessINFDefinesSection ( 1659 DSC_FILE *ComponentFile 1660 ) 1661 /*++ 1662 1663 Routine Description: 1664 1665 Process the [defines.xxx] sections of the component description file. Process 1666 platform first, then processor. In this way, if a platform wants and override, 1667 that one gets parsed first, and later assignments do not overwrite the value. 1668 1669 Arguments: 1670 1671 ComponentFile - section info on the component file being processed 1672 1673 Returns: 1674 1675 1676 --*/ 1677 { 1678 INT8 *Cptr; 1679 INT8 Str[MAX_LINE_LEN]; 1680 1681 // 1682 // Find a [defines.$(PROCESSOR).$(PLATFORM)] section and process it 1683 // 1684 Cptr = GetSymbolValue (PLATFORM); 1685 if (Cptr != NULL) { 1686 sprintf ( 1687 Str, 1688 "%s.%s.%s", 1689 DEFINES_SECTION_NAME, 1690 GetSymbolValue (PROCESSOR), 1691 Cptr 1692 ); 1693 ProcessINFDefinesSectionSingle (ComponentFile, Str); 1694 } 1695 // 1696 // Find a [defines.$(PROCESSOR)] section and process it 1697 // 1698 sprintf (Str, "%s.%s", DEFINES_SECTION_NAME, GetSymbolValue (PROCESSOR)); 1699 ProcessINFDefinesSectionSingle (ComponentFile, Str); 1700 1701 // 1702 // Find a [defines] section and process it 1703 // 1704 if (ProcessINFDefinesSectionSingle (ComponentFile, DEFINES_SECTION_NAME) != STATUS_SUCCESS) { 1705 Error (NULL, 0, 0, NULL, "missing [defines] section in component file %s", GetSymbolValue (INF_FILENAME)); 1706 return STATUS_ERROR; 1707 } 1708 1709 return STATUS_SUCCESS; 1710 } 1711 1712 static 1713 int 1714 ProcessINFDefinesSectionSingle ( 1715 DSC_FILE *ComponentFile, 1716 INT8 *SectionName 1717 ) 1718 { 1719 INT8 *Cptr; 1720 INT8 Str[MAX_LINE_LEN]; 1721 INT8 ExpandedLine[MAX_LINE_LEN]; 1722 SECTION *TempSect; 1723 1724 TempSect = DSCFileFindSection (ComponentFile, SectionName); 1725 if (TempSect != NULL) { 1726 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 1727 ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0); 1728 Cptr = StripLine (ExpandedLine); 1729 // 1730 // Don't process blank lines. 1731 // 1732 if (*Cptr) { 1733 // 1734 // Add without overwriting macros specified on the component line 1735 // in the description file 1736 // 1737 AddSymbol (Cptr, NULL, SYM_LOCAL); 1738 } 1739 } 1740 } else { 1741 return STATUS_WARNING; 1742 } 1743 1744 return STATUS_SUCCESS; 1745 } 1746 1747 static 1748 int 1749 ProcessINFNMakeSection ( 1750 DSC_FILE *ComponentFile, 1751 FILE *MakeFptr 1752 ) 1753 /*++ 1754 1755 Routine Description: 1756 1757 Process the [nmake.common] and [nmake.$(PROCESSOR)] sections of the component 1758 description file and write and copy them to the component's makefile. 1759 1760 Arguments: 1761 1762 ComponentFile - section info on the component file being processed 1763 MakeFptr - file pointer to the component' makefile we're creating 1764 1765 Returns: 1766 1767 Always STATUS_SUCCESS right now, since the sections are optional. 1768 1769 --*/ 1770 { 1771 INT8 *Cptr; 1772 INT8 Str[MAX_LINE_LEN]; 1773 INT8 ExpandedLine[MAX_LINE_LEN]; 1774 SECTION *TempSect; 1775 1776 // 1777 // Copy the [nmake.common] and [nmake.$(PROCESSOR)] sections from the 1778 // component file directly to the output file. 1779 // The line will be stripped and don't print blank lines 1780 // 1781 sprintf (Str, "%s.%s", NMAKE_SECTION_NAME, COMMON_SECTION_NAME); 1782 TempSect = DSCFileFindSection (ComponentFile, Str); 1783 if (TempSect != NULL) { 1784 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 1785 ExpandSymbols ( 1786 Str, 1787 ExpandedLine, 1788 sizeof (ExpandedLine), 1789 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR 1790 ); 1791 Cptr = StripLine (ExpandedLine); 1792 if (*Cptr) { 1793 fprintf (MakeFptr, "%s\n", Cptr); 1794 } 1795 } 1796 1797 fprintf (MakeFptr, "\n"); 1798 } else { 1799 Error (GetSymbolValue (INF_FILENAME), 1, 0, Str, "section not found in component INF file"); 1800 } 1801 1802 sprintf (Str, "%s.%s", NMAKE_SECTION_NAME, GetSymbolValue (PROCESSOR)); 1803 TempSect = DSCFileFindSection (ComponentFile, Str); 1804 if (TempSect != NULL) { 1805 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 1806 ExpandSymbols ( 1807 Str, 1808 ExpandedLine, 1809 sizeof (ExpandedLine), 1810 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR 1811 ); 1812 Cptr = StripLine (ExpandedLine); 1813 if (*Cptr) { 1814 fprintf (MakeFptr, "%s\n", Cptr); 1815 } 1816 } 1817 1818 fprintf (MakeFptr, "\n"); 1819 } 1820 // 1821 // Do the same for [nmake.$(PROCESSOR).$(PLATFORM)] 1822 // 1823 Cptr = GetSymbolValue (PLATFORM); 1824 if (Cptr != NULL) { 1825 sprintf (Str, "%s.%s.%s", NMAKE_SECTION_NAME, GetSymbolValue (PROCESSOR), Cptr); 1826 TempSect = DSCFileFindSection (ComponentFile, Str); 1827 if (TempSect != NULL) { 1828 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 1829 ExpandSymbols ( 1830 Str, 1831 ExpandedLine, 1832 sizeof (ExpandedLine), 1833 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR 1834 ); 1835 Cptr = StripLine (ExpandedLine); 1836 if (*Cptr) { 1837 fprintf (MakeFptr, "%s\n", Cptr); 1838 } 1839 } 1840 1841 fprintf (MakeFptr, "\n"); 1842 } 1843 } 1844 1845 return STATUS_SUCCESS; 1846 } 1847 1848 static 1849 int 1850 ProcessIncludesSection ( 1851 DSC_FILE *ComponentFile, 1852 FILE *MakeFptr 1853 ) 1854 /*++ 1855 1856 Routine Description: 1857 1858 Process the [includes.common], [includes.processor], and 1859 [includes.processor.platform] section of the component description file 1860 and write the appropriate macros to the component's makefile. 1861 1862 Process in reverse order to allow overrides on platform basis. 1863 1864 Arguments: 1865 1866 ComponentFile - section info on the component file being processed 1867 MakeFptr - file pointer to the component' makefile we're creating 1868 1869 Returns: 1870 1871 Always STATUS_SUCCESS right now, since the sections are optional. 1872 1873 --*/ 1874 { 1875 INT8 *Cptr; 1876 INT8 Str[MAX_LINE_LEN]; 1877 INT8 *Processor; 1878 INT8 *OverridePath; 1879 1880 // 1881 // Write a useful comment to the output makefile so the user knows where 1882 // the data came from. 1883 // 1884 fprintf (MakeFptr, "#\n# Tool-generated list of include paths that are created\n"); 1885 fprintf (MakeFptr, "# from the list of include paths in the [includes.*] sections\n"); 1886 fprintf (MakeFptr, "# of the component INF file.\n#\n"); 1887 1888 // 1889 // We use this a lot here, so get the value only once. 1890 // 1891 Processor = GetSymbolValue (PROCESSOR); 1892 // 1893 // If they're using an override source path, then add OverridePath and 1894 // OverridePath\$(PROCESSOR) to the list of include paths. 1895 // 1896 OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH); 1897 if (OverridePath != NULL) { 1898 ReplaceSlash (OverridePath); 1899 fprintf (MakeFptr, "!IF EXIST(%s)\n", OverridePath); 1900 fprintf (MakeFptr, "INC = $(INC) -I %s\n", OverridePath); 1901 fprintf (MakeFptr, "!IF EXIST(%s\\%s)\n", OverridePath, Processor); 1902 fprintf (MakeFptr, "INC = $(INC) -I %s\\%s\n", OverridePath, Processor); 1903 fprintf (MakeFptr, "!ENDIF\n"); 1904 fprintf (MakeFptr, "!ELSE\n"); 1905 fprintf (MakeFptr, "!MESSAGE Warning: include dir %s does not exist\n", OverridePath); 1906 fprintf (MakeFptr, "!ENDIF\n"); 1907 } 1908 // 1909 // Try for an [includes.$(PROCESSOR).$(PLATFORM)] 1910 // 1911 Cptr = GetSymbolValue (PLATFORM); 1912 if (Cptr != NULL) { 1913 sprintf (Str, "%s.%s.%s", INCLUDE_SECTION_NAME, Processor, Cptr); 1914 ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str); 1915 } 1916 // 1917 // Now the [includes.$(PROCESSOR)] section 1918 // 1919 sprintf (Str, "%s.%s", INCLUDE_SECTION_NAME, Processor); 1920 ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str); 1921 1922 // 1923 // Now the [includes.common] section 1924 // 1925 sprintf (Str, "%s.%s", INCLUDE_SECTION_NAME, COMMON_SECTION_NAME); 1926 ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str); 1927 1928 // 1929 // Done 1930 // 1931 fprintf (MakeFptr, "\n"); 1932 return STATUS_SUCCESS; 1933 } 1934 // 1935 // Process one of the [includes.xxx] sections to create a list of all 1936 // the include paths. 1937 // 1938 static 1939 int 1940 ProcessIncludesSectionSingle ( 1941 DSC_FILE *ComponentFile, 1942 FILE *MakeFptr, 1943 INT8 *SectionName 1944 ) 1945 { 1946 INT8 *Cptr; 1947 SECTION *TempSect; 1948 INT8 Str[MAX_LINE_LEN]; 1949 INT8 ExpandedLine[MAX_LINE_LEN]; 1950 INT8 *Processor; 1951 1952 TempSect = DSCFileFindSection (ComponentFile, SectionName); 1953 if (TempSect != NULL) { 1954 // 1955 // Add processor subdirectory on every include path 1956 // 1957 Processor = GetSymbolValue (PROCESSOR); 1958 // 1959 // Copy lines directly 1960 // 1961 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 1962 ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0); 1963 Cptr = StripLine (ExpandedLine); 1964 // 1965 // Don't process blank lines 1966 // 1967 if (*Cptr) { 1968 ReplaceSlash (Cptr); 1969 // 1970 // Strip off trailing slash 1971 // 1972 if (Cptr[strlen (Cptr) - 1] == '\\') { 1973 Cptr[strlen (Cptr) - 1] = 0; 1974 } 1975 // 1976 // Special case of ".". Replace it with source path 1977 // and the rest of the line (for .\$(PROCESSOR)) 1978 // 1979 if (*Cptr == '.') { 1980 // 1981 // Handle case of just a "." 1982 // 1983 if (Cptr[1] == 0) { 1984 fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\n"); 1985 fprintf (MakeFptr, "!IF EXIST($(SOURCE_DIR)\\%s)\n", Processor); 1986 fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\\%s\n", Processor); 1987 fprintf (MakeFptr, "!ENDIF\n"); 1988 } else { 1989 // 1990 // Handle case of ".\path\path\path" or "..\path\path\path" 1991 // 1992 fprintf (MakeFptr, "!IF EXIST($(SOURCE_DIR)\\%s)\n", Cptr); 1993 fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\\%s\n", Cptr); 1994 fprintf (MakeFptr, "!IF EXIST($(SOURCE_DIR)\\%s\\%s)\n", Cptr, Processor); 1995 fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s\n", Cptr, Processor); 1996 fprintf (MakeFptr, "!ENDIF\n"); 1997 fprintf (MakeFptr, "!ELSE\n"); 1998 fprintf (MakeFptr, "!MESSAGE Warning: include dir $(SOURCE_DIR)\\%s does not exist\n", Cptr); 1999 fprintf (MakeFptr, "!ENDIF\n"); 2000 } 2001 } else if ((Cptr[1] != ':') && isalpha (*Cptr)) { 2002 fprintf (MakeFptr, "!IF EXIST($(EFI_SOURCE)\\%s)\n", Cptr); 2003 fprintf (MakeFptr, "INC = $(INC) -I $(EFI_SOURCE)\\%s\n", Cptr); 2004 fprintf (MakeFptr, "!IF EXIST($(EFI_SOURCE)\\%s\\%s)\n", Cptr, Processor); 2005 fprintf (MakeFptr, "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s\n", Cptr, Processor); 2006 fprintf (MakeFptr, "!ENDIF\n"); 2007 fprintf (MakeFptr, "!ELSE\n"); 2008 fprintf (MakeFptr, "!MESSAGE Warning: include dir $(EFI_SOURCE)\\%s does not exist\n", Cptr); 2009 fprintf (MakeFptr, "!ENDIF\n"); 2010 } else { 2011 // 2012 // The line is something like: $(EFI_SOURCE)\dxe\include. Add it to 2013 // the existing $(INC) definition. Add user includes before any 2014 // other existing paths. 2015 // 2016 fprintf (MakeFptr, "!IF EXIST(%s)\n", Cptr); 2017 fprintf (MakeFptr, "INC = $(INC) -I %s\n", Cptr); 2018 fprintf (MakeFptr, "!IF EXIST(%s\\%s)\n", Cptr, Processor); 2019 fprintf (MakeFptr, "INC = $(INC) -I %s\\%s\n", Cptr, Processor); 2020 fprintf (MakeFptr, "!ENDIF\n"); 2021 fprintf (MakeFptr, "!ELSE\n"); 2022 fprintf (MakeFptr, "!MESSAGE Warning: include dir %s does not exist\n", Cptr); 2023 fprintf (MakeFptr, "!ENDIF\n"); 2024 } 2025 } 2026 } 2027 } 2028 2029 return STATUS_SUCCESS; 2030 } 2031 2032 static 2033 int 2034 ProcessSourceFiles ( 2035 DSC_FILE *DSCFile, 2036 DSC_FILE *ComponentFile, 2037 FILE *MakeFptr, 2038 UINT32 Mode 2039 ) 2040 /*++ 2041 2042 Routine Description: 2043 2044 Process the [sources.common], [sources.$(PROCESSOR)], and 2045 [sources.$(PROCESSOR).$(PLATFORM] sections of the component 2046 description file and write the appropriate build commands out to the 2047 component's makefile. If $(SOURCE_SELECT) is defined, then it overrides 2048 the source selections. We use this functionality for SMM. 2049 2050 Arguments: 2051 2052 ComponentFile - section info on the component file being processed 2053 MakeFptr - file pointer to the component' makefile we're creating 2054 DSCFile - section info on the description file we're processing 2055 Mode - to write build commands, or just create a list 2056 of sources. 2057 2058 Returns: 2059 2060 Always STATUS_SUCCESS right now, since the sections are optional. 2061 2062 --*/ 2063 { 2064 INT8 Str[MAX_LINE_LEN]; 2065 INT8 *Processor; 2066 INT8 *Platform; 2067 INT8 *SourceSelect; 2068 INT8 *CStart; 2069 INT8 *CEnd; 2070 INT8 CSave; 2071 INT8 *CopySourceSelect; 2072 2073 if (Mode & SOURCE_MODE_SOURCE_FILES) { 2074 // 2075 // Write a useful comment to the output makefile so the user knows where 2076 // the data came from. 2077 // 2078 fprintf (MakeFptr, "#\n# Tool-generated list of source files that are created\n"); 2079 fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n"); 2080 fprintf (MakeFptr, "# of the component INF file.\n#\n"); 2081 } 2082 2083 // 2084 // We use this a lot here, so get the value only once. 2085 // 2086 Processor = GetSymbolValue (PROCESSOR); 2087 // 2088 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll 2089 // select each [sources.xxx] and [sources.yyy] files and process 2090 // them. 2091 // 2092 SourceSelect = GetSymbolValue (SOURCE_SELECT); 2093 2094 if (SourceSelect != NULL) { 2095 // 2096 // Make a copy of the string and break it up (comma-separated) and 2097 // select each [sources.*] file from the INF. 2098 // 2099 CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1); 2100 if (CopySourceSelect == NULL) { 2101 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 2102 return STATUS_ERROR; 2103 } 2104 2105 strcpy (CopySourceSelect, SourceSelect); 2106 CStart = CopySourceSelect; 2107 CEnd = CStart; 2108 while (*CStart) { 2109 CEnd = CStart + 1; 2110 while (*CEnd && *CEnd != ',') { 2111 CEnd++; 2112 } 2113 2114 CSave = *CEnd; 2115 *CEnd = 0; 2116 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart); 2117 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); 2118 // 2119 // Restore the terminator and advance 2120 // 2121 *CEnd = CSave; 2122 CStart = CEnd; 2123 if (*CStart) { 2124 CStart++; 2125 } 2126 } 2127 2128 free (CopySourceSelect); 2129 2130 } else { 2131 // 2132 // Process all the [sources.common] source files to make them build 2133 // 2134 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME); 2135 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); 2136 // 2137 // Now process the [sources.$(PROCESSOR)] files. 2138 // 2139 sprintf (Str, "sources.%s", Processor); 2140 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); 2141 // 2142 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files. 2143 // 2144 Platform = GetSymbolValue (PLATFORM); 2145 if (Platform != NULL) { 2146 sprintf (Str, "sources.%s.%s", Processor, Platform); 2147 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); 2148 } 2149 } 2150 2151 fprintf (MakeFptr, "\n"); 2152 return STATUS_SUCCESS; 2153 } 2154 2155 /*++ 2156 2157 Routine Description: 2158 Given a source file line from an INF file, parse it to see if there are 2159 any defines on it. If so, then add them to the symbol table. 2160 Also, terminate the line after the file name. 2161 2162 Arguments: 2163 SourceFileLine - a line from a [sources.?] section of the INF file. Likely 2164 something like: 2165 2166 MySourceFile.c BUILT_NAME=$(BUILD_DIR)\MySourceFile.obj 2167 2168 Returns: 2169 Nothing. 2170 2171 --*/ 2172 static 2173 void 2174 AddFileSymbols ( 2175 INT8 *SourceFileLine 2176 ) 2177 { 2178 int Len; 2179 // 2180 // Skip spaces 2181 // 2182 for (; *SourceFileLine && isspace (*SourceFileLine); SourceFileLine++) 2183 ; 2184 for (; *SourceFileLine && !isspace (*SourceFileLine); SourceFileLine++) 2185 ; 2186 if (*SourceFileLine) { 2187 *SourceFileLine = 0; 2188 SourceFileLine++; 2189 // 2190 // AddSymbol() will parse it for us, and return the length. Keep calling 2191 // it until it reports an error or is done. 2192 // 2193 do { 2194 Len = AddSymbol (SourceFileLine, NULL, SYM_FILE); 2195 SourceFileLine += Len; 2196 } while (Len > 0); 2197 } 2198 } 2199 // 2200 // Process a single section of source files in the component INF file 2201 // 2202 static 2203 int 2204 ProcessSourceFilesSection ( 2205 DSC_FILE *DSCFile, 2206 DSC_FILE *ComponentFile, 2207 FILE *MakeFptr, 2208 INT8 *SectionName, 2209 UINT32 Mode 2210 ) 2211 { 2212 INT8 *Cptr; 2213 INT8 FileName[MAX_EXP_LINE_LEN]; 2214 INT8 FilePath[MAX_PATH]; 2215 INT8 TempFileName[MAX_PATH]; 2216 SECTION *TempSect; 2217 INT8 Str[MAX_LINE_LEN]; 2218 INT8 *Processor; 2219 INT8 *OverridePath; 2220 FILE *FPtr; 2221 2222 TempSect = DSCFileFindSection (ComponentFile, SectionName); 2223 if (TempSect != NULL) { 2224 Processor = GetSymbolValue (PROCESSOR); 2225 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 2226 Cptr = StripLine (Str); 2227 // 2228 // Don't process blank lines 2229 // 2230 if (*Cptr) { 2231 // 2232 // Expand symbols in the filename, then parse the line for symbol 2233 // definitions. AddFileSymbols() will null-terminate the line 2234 // after the file name. Save a copy for override purposes, in which 2235 // case we'll need to know the file name and path (in case it's in 2236 // a subdirectory). 2237 // 2238 ExpandSymbols (Cptr, FileName, sizeof (FileName), 0); 2239 AddFileSymbols (FileName); 2240 ReplaceSlash (FileName); 2241 // 2242 // Set the SOURCE_FILE_NAME symbol. What we have now is the name of 2243 // the file, relative to the location of the INF file. So prepend 2244 // $(SOURCE_DIR) to it first. 2245 // 2246 if (IsAbsolutePath (FileName)) { 2247 strcpy (TempFileName, FileName); 2248 } else { 2249 strcpy (TempFileName, "$(SOURCE_DIR)\\"); 2250 strcat (TempFileName, FileName); 2251 } 2252 AddSymbol (SOURCE_FILE_NAME, TempFileName, SYM_FILE | SYM_OVERWRITE); 2253 // 2254 // Extract path information from the source file and set internal 2255 // variable SOURCE_RELATIVE_PATH. Only do this if the path 2256 // contains a backslash. 2257 // 2258 strcpy (FilePath, FileName); 2259 for (Cptr = FilePath + strlen (FilePath) - 1; (Cptr > FilePath) && (*Cptr != '\\'); Cptr--) 2260 ; 2261 if (*Cptr == '\\') { 2262 *(Cptr + 1) = 0; 2263 AddSymbol (SOURCE_RELATIVE_PATH, FilePath, SYM_FILE); 2264 } 2265 // 2266 // Define another internal symbol for the name of the file without 2267 // the path and extension. 2268 // 2269 for (Cptr = FileName + strlen (FileName) - 1; (Cptr > FileName) && (*Cptr != '\\'); Cptr--) 2270 ; 2271 if (*Cptr == '\\') { 2272 Cptr++; 2273 } 2274 2275 strcpy (FilePath, Cptr); 2276 // 2277 // We now have a file name with no path information. Before we do anything else, 2278 // see if OVERRIDE_PATH is set, and if so, see if file $(OVERRIDE_PATH)FileName 2279 // exists. If it does, then recursive call this function to use the override file 2280 // instead of the one from the INF file. 2281 // 2282 if (IsAbsolutePath (FileName)) { 2283 OverridePath = NULL; 2284 } else { 2285 OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH); 2286 } 2287 if (OverridePath != NULL) { 2288 ReplaceSlash (OverridePath); 2289 // 2290 // See if the file exists. If it does, reset the SOURCE_FILE_NAME symbol. 2291 // 2292 strcpy (TempFileName, OverridePath); 2293 strcat (TempFileName, "\\"); 2294 strcat (TempFileName, FileName); 2295 if ((FPtr = fopen (TempFileName, "rb")) != NULL) { 2296 fclose (FPtr); 2297 AddSymbol (SOURCE_FILE_NAME, TempFileName, SYM_FILE | SYM_OVERWRITE); 2298 // 2299 // Print a message. This function is called to create build commands 2300 // for source files, and to create a macro of all source files. Therefore 2301 // do this check so we don't print the override message multiple times. 2302 // 2303 if (Mode & SOURCE_MODE_BUILD_COMMANDS) { 2304 fprintf (stdout, "Override: %s\n", TempFileName); 2305 } 2306 } else { 2307 // 2308 // Set override path to null to use as a flag below 2309 // 2310 OverridePath = NULL; 2311 } 2312 } 2313 2314 // 2315 // Start at the end and work back 2316 // 2317 for (Cptr = FilePath + strlen (FilePath) - 1; (Cptr > FilePath) && (*Cptr != '\\') && (*Cptr != '.'); Cptr--) 2318 ; 2319 if (*Cptr == '.') { 2320 *Cptr = 0; 2321 AddSymbol (SOURCE_FILE_EXTENSION, Cptr + 1, SYM_FILE); 2322 } 2323 2324 AddSymbol (SOURCE_BASE_NAME, FilePath, SYM_FILE); 2325 // 2326 // If we're just creating the SOURCE_FILES macro, then write the 2327 // file name out to the makefile. 2328 // 2329 if (Mode & SOURCE_MODE_SOURCE_FILES) { 2330 // 2331 // If we're processing an override file, then use the file name as-is 2332 // 2333 if (OverridePath != NULL) { 2334 // 2335 // SOURCE_FILES = $(SOURCE_FILES) c:\Path\ThisFile.c 2336 // 2337 fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", TempFileName); 2338 // 2339 // Save the source absolute path 2340 // 2341 if (PathCanonicalize (FilePath, TempFileName)) { 2342 AddSourceFile (mCurrentBuildItem, FilePath); 2343 } 2344 } else if (IsAbsolutePath (FileName)) { 2345 // 2346 // For Absolute path, don't print $(SOURCE_FILE) directory. 2347 // 2348 fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", FileName); 2349 // 2350 // Save the source absolute path 2351 // 2352 if (PathCanonicalize (FilePath, FileName)) { 2353 AddSourceFile (mCurrentBuildItem, FilePath); 2354 } 2355 } else { 2356 // 2357 // SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\ThisFile.c 2358 // 2359 fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\\%s\n", FileName); 2360 // 2361 // Save the source absolute path 2362 // 2363 sprintf (Str, "%s\\%s", GetSymbolValue (SOURCE_DIR), FileName); 2364 if (PathCanonicalize (FilePath, Str)) { 2365 AddSourceFile (mCurrentBuildItem, FilePath); 2366 } 2367 } 2368 } else if (Mode & SOURCE_MODE_BUILD_COMMANDS) { 2369 // 2370 // Write the build commands for this file per the build commands 2371 // for this file type as defined in the description file. 2372 // Also create the directory for it in the build path. 2373 // 2374 WriteCompileCommands (DSCFile, MakeFptr, FileName, Processor); 2375 if (!IsAbsolutePath (FileName)) { 2376 sprintf (Str, "%s\\%s", GetSymbolValue (DEST_DIR), FileName); 2377 MakeFilePath (Str); 2378 // 2379 // Get all output directory for build output files. 2380 // 2381 Cptr = FileName + strlen (FileName) - 1; 2382 for (; (Cptr > FileName) && (*Cptr != '\\'); Cptr--); 2383 if (*Cptr == '\\') { 2384 *Cptr = '\0'; 2385 AddModuleName (&gGlobals.OutdirList, FileName, NULL); 2386 } 2387 } 2388 } 2389 // 2390 // Remove file-level symbols 2391 // 2392 RemoveFileSymbols (); 2393 } 2394 } 2395 } 2396 2397 return STATUS_SUCCESS; 2398 } 2399 // 2400 // Process the INF [sources.*] sections and emit the OBJECTS = ..... 2401 // lines to the component's makefile. 2402 // 2403 static 2404 int 2405 ProcessObjects ( 2406 DSC_FILE *ComponentFile, 2407 FILE *MakeFptr 2408 ) 2409 { 2410 INT8 Str[MAX_LINE_LEN]; 2411 INT8 *Processor; 2412 INT8 *Platform; 2413 INT8 *SourceSelect; 2414 INT8 *CStart; 2415 INT8 *CEnd; 2416 INT8 CSave; 2417 INT8 *CopySourceSelect; 2418 SYMBOL *TempSymbol; 2419 2420 // 2421 // Write a useful comment to the output makefile so the user knows where 2422 // the data came from. 2423 // 2424 fprintf (MakeFptr, "#\n# Tool-generated list of object files that are created\n"); 2425 fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n"); 2426 fprintf (MakeFptr, "# of the component INF file.\n#\n"); 2427 // 2428 // We use this a lot here, so get the value only once. 2429 // 2430 Processor = GetSymbolValue (PROCESSOR); 2431 // 2432 // Now define the OBJECTS variable and assign it to be all the object files we're going 2433 // to create. Afterwards create a pseudo-target objects to let the user quickly just compile 2434 // the source files. This means we need to process all the common objects and 2435 // processor-specific objects again. 2436 // 2437 fprintf (MakeFptr, "OBJECTS = $(OBJECTS) "); 2438 // 2439 // See if they defined SOURCE_SELECT=xxx,yyy in which case well 2440 // select each [sources.xxx] and [sources.yyy] files and process 2441 // them. 2442 // 2443 SourceSelect = GetSymbolValue (SOURCE_SELECT); 2444 2445 if (SourceSelect != NULL) { 2446 // 2447 // Make a copy of the string and break it up (comma-separated) and 2448 // select each [sources.*] file from the INF. 2449 // 2450 CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1); 2451 if (CopySourceSelect == NULL) { 2452 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 2453 return STATUS_ERROR; 2454 } 2455 2456 strcpy (CopySourceSelect, SourceSelect); 2457 CStart = CopySourceSelect; 2458 CEnd = CStart; 2459 while (*CStart) { 2460 CEnd = CStart + 1; 2461 while (*CEnd && *CEnd != ',') { 2462 CEnd++; 2463 } 2464 2465 CSave = *CEnd; 2466 *CEnd = 0; 2467 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart); 2468 ProcessObjectsSingle (ComponentFile, MakeFptr, Str); 2469 // 2470 // Restore the terminator and advance 2471 // 2472 *CEnd = CSave; 2473 CStart = CEnd; 2474 if (*CStart) { 2475 CStart++; 2476 } 2477 } 2478 2479 free (CopySourceSelect); 2480 2481 } else { 2482 // 2483 // Now process all the [sources.common] files and emit build commands for them 2484 // 2485 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME); 2486 if (ProcessObjectsSingle (ComponentFile, MakeFptr, Str) != STATUS_SUCCESS) { 2487 Warning (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "no [%s] section found in component description", Str); 2488 } 2489 // 2490 // Now process any processor-specific source files in [sources.$(PROCESSOR)] 2491 // 2492 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, Processor); 2493 ProcessObjectsSingle (ComponentFile, MakeFptr, Str); 2494 2495 // 2496 // Now process any [sources.$(PROCESSOR).$(PLATFORM)] files 2497 // 2498 Platform = GetSymbolValue (PLATFORM); 2499 if (Platform != NULL) { 2500 sprintf (Str, "sources.%s.%s", Processor, Platform); 2501 ProcessObjectsSingle (ComponentFile, MakeFptr, Str); 2502 } 2503 } 2504 2505 fprintf (MakeFptr, "\n\n"); 2506 2507 // 2508 // Write a useful comment to the output makefile so the user knows where 2509 // the data came from. 2510 // 2511 fprintf (MakeFptr, "#\n# Tool-generated list of dest output dirs that are created\n"); 2512 fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n"); 2513 fprintf (MakeFptr, "# of the component INF file.\n#\n"); 2514 // 2515 // Create output directory list 2516 // for clean target to delete all build output files. 2517 // 2518 fprintf (MakeFptr, "DEST_OUTPUT_DIRS = $(%s) ", DEST_DIR); 2519 2520 TempSymbol = gGlobals.OutdirList; 2521 while (TempSymbol != NULL) { 2522 fprintf (MakeFptr, "\\\n $(%s)\\%s ", 2523 DEST_DIR, TempSymbol->Name); 2524 TempSymbol = TempSymbol->Next; 2525 } 2526 fprintf (MakeFptr, "\n\n"); 2527 2528 // 2529 // clean up for the next module 2530 // 2531 FreeSymbols (gGlobals.OutdirList); 2532 gGlobals.OutdirList = NULL; 2533 2534 return STATUS_SUCCESS; 2535 } 2536 2537 static 2538 INT8 * 2539 BuiltFileExtension ( 2540 INT8 *SourceFileName 2541 ) 2542 { 2543 int i; 2544 INT8 *Cptr; 2545 // 2546 // Find the dot in the filename extension 2547 // 2548 for (Cptr = SourceFileName + strlen (SourceFileName) - 1; 2549 (Cptr > SourceFileName) && (*Cptr != '\\') && (*Cptr != '.'); 2550 Cptr-- 2551 ) { 2552 // 2553 // Do nothing 2554 // 2555 } 2556 2557 if (*Cptr != '.') { 2558 return NULL; 2559 } 2560 // 2561 // Look through our list of known file types and return a pointer to 2562 // its built file extension. 2563 // 2564 for (i = 0; mFileTypes[i].Extension != NULL; i++) { 2565 if (_stricmp (Cptr, mFileTypes[i].Extension) == 0) { 2566 return mFileTypes[i].BuiltExtension; 2567 } 2568 } 2569 2570 return NULL; 2571 } 2572 2573 int 2574 ProcessObjectsSingle ( 2575 DSC_FILE *ComponentFile, 2576 FILE *MakeFptr, 2577 INT8 *SectionName 2578 ) 2579 { 2580 INT8 *Cptr; 2581 INT8 *Cptr2; 2582 INT8 Str[MAX_LINE_LEN]; 2583 INT8 FileName[MAX_EXP_LINE_LEN]; 2584 SECTION *TempSect; 2585 2586 TempSect = DSCFileFindSection (ComponentFile, SectionName); 2587 if (TempSect != NULL) { 2588 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 2589 Cptr = StripLine (Str); 2590 // 2591 // Don't process blank lines 2592 // 2593 if (*Cptr) { 2594 // 2595 // Expand symbols then create the output filename. We'll do a lookup 2596 // on the source file's extension to determine what the extension of 2597 // the built version of the file is. For example, .c -> .obj. 2598 // 2599 if (!IsIncludeFile (Cptr)) { 2600 ExpandSymbols (Cptr, FileName, sizeof (FileName), 0); 2601 ReplaceSlash (FileName); 2602 Cptr2 = BuiltFileExtension (FileName); 2603 if (Cptr2 != NULL) { 2604 SetFileExtension (FileName, Cptr2); 2605 if (!IsAbsolutePath (FileName)) { 2606 fprintf (MakeFptr, "\\\n $(%s)\\%s ", DEST_DIR, FileName); 2607 } else { 2608 fprintf (MakeFptr, "\\\n %s ", FileName); 2609 } 2610 } 2611 } 2612 } 2613 } 2614 } else { 2615 return STATUS_WARNING; 2616 } 2617 2618 return STATUS_SUCCESS; 2619 } 2620 // 2621 // Process all [libraries.*] sections in the component INF file to create a 2622 // macro to the component's output makefile: LIBS = Lib1 Lib2, ... 2623 // 2624 static 2625 int 2626 ProcessLibs ( 2627 DSC_FILE *ComponentFile, 2628 FILE *MakeFptr 2629 ) 2630 { 2631 INT8 Str[MAX_LINE_LEN]; 2632 INT8 *Processor; 2633 INT8 *Platform; 2634 2635 // 2636 // Print a useful comment to the component's makefile so the user knows 2637 // where the data came from. 2638 // 2639 fprintf (MakeFptr, "#\n# Tool-generated list of libraries that are generated\n"); 2640 fprintf (MakeFptr, "# from the list of libraries listed in the [libraries.*] sections\n"); 2641 fprintf (MakeFptr, "# of the component INF file.\n#\n"); 2642 2643 fprintf (MakeFptr, "LIBS = $(LIBS) "); 2644 2645 Processor = GetSymbolValue (PROCESSOR); 2646 // 2647 // Process [libraries.common] files 2648 // 2649 sprintf (Str, "%s.%s", LIBRARIES_SECTION_NAME, COMMON_SECTION_NAME); 2650 ProcessLibsSingle (ComponentFile, MakeFptr, Str); 2651 // 2652 // Process the [libraries.$(PROCESSOR)] libraries to define "LIBS = x.lib y.lib..." 2653 // 2654 sprintf (Str, "%s.%s", LIBRARIES_SECTION_NAME, Processor); 2655 ProcessLibsSingle (ComponentFile, MakeFptr, Str); 2656 // 2657 // Now process any [libraries.$(PROCESSOR).$(PLATFORM)] files 2658 // 2659 Platform = GetSymbolValue (PLATFORM); 2660 if (Platform != NULL) { 2661 sprintf (Str, "%s.%s.%s", LIBRARIES_SECTION_NAME, Processor, Platform); 2662 ProcessLibsSingle (ComponentFile, MakeFptr, Str); 2663 } 2664 // 2665 // Process any [libraries.platform] files 2666 // 2667 ProcessLibsSingle (ComponentFile, MakeFptr, LIBRARIES_PLATFORM_SECTION_NAME); 2668 2669 fprintf (MakeFptr, "\n\n"); 2670 return STATUS_SUCCESS; 2671 } 2672 2673 static 2674 int 2675 ProcessLibsSingle ( 2676 DSC_FILE *ComponentFile, 2677 FILE *MakeFptr, 2678 INT8 *SectionName 2679 ) 2680 { 2681 INT8 *Cptr; 2682 INT8 Str[MAX_LINE_LEN]; 2683 INT8 ExpandedLine[MAX_LINE_LEN]; 2684 SECTION *TempSect; 2685 2686 TempSect = DSCFileFindSection (ComponentFile, SectionName); 2687 if (TempSect != NULL) { 2688 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 2689 ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0); 2690 Cptr = StripLine (ExpandedLine); 2691 // 2692 // Don't process blank lines 2693 // 2694 if (*Cptr) { 2695 if (Cptr[strlen (Cptr) - 4] != '.') { 2696 fprintf (MakeFptr, " \\\n $(LIB_DIR)\\%s.lib", Cptr); 2697 // 2698 // Add lib dependency for single module build 2699 // 2700 fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", Cptr); 2701 } else { 2702 fprintf (MakeFptr, " \\\n $(LIB_DIR)\\%s", Cptr); 2703 // 2704 // Add lib dependency for single module build 2705 // 2706 Cptr[strlen (Cptr) - 4] = 0; 2707 fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", Cptr); 2708 } 2709 // 2710 // Add libs dependency for mCurrentBuildItem 2711 // 2712 AddDependency (*mCurrentBuildList, mCurrentBuildItem, Cptr, 0); 2713 } 2714 } 2715 } 2716 2717 return STATUS_SUCCESS; 2718 } 2719 2720 static 2721 int 2722 ProcessIncludeFiles ( 2723 DSC_FILE *ComponentFile, 2724 FILE *MakeFptr 2725 ) 2726 { 2727 INT8 Str[MAX_LINE_LEN]; 2728 INT8 *Processor; 2729 INT8 *Platform; 2730 INT8 *SourceSelect; 2731 INT8 *CStart; 2732 INT8 *CEnd; 2733 INT8 CSave; 2734 INT8 *CopySourceSelect; 2735 2736 // 2737 // Print a useful comment to the output makefile so the user knows where 2738 // the info came from 2739 // 2740 //fprintf (MakeFptr, "#\n# Tool-generated include dependencies from any include files in the\n"); 2741 //fprintf (MakeFptr, "# [sources.*] sections of the component INF file\n#\n"); 2742 2743 Processor = GetSymbolValue (PROCESSOR); 2744 2745 // 2746 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll 2747 // select each [sources.xxx] and [sources.yyy] files and process 2748 // them. 2749 // 2750 SourceSelect = GetSymbolValue (SOURCE_SELECT); 2751 2752 if (SourceSelect != NULL) { 2753 // 2754 // Make a copy of the string and break it up (comma-separated) and 2755 // select each [sources.*] file from the INF. 2756 // 2757 CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1); 2758 if (CopySourceSelect == NULL) { 2759 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 2760 return STATUS_ERROR; 2761 } 2762 2763 strcpy (CopySourceSelect, SourceSelect); 2764 CStart = CopySourceSelect; 2765 CEnd = CStart; 2766 while (*CStart) { 2767 CEnd = CStart + 1; 2768 while (*CEnd && *CEnd != ',') { 2769 CEnd++; 2770 } 2771 2772 CSave = *CEnd; 2773 *CEnd = 0; 2774 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart); 2775 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); 2776 // 2777 // Restore the terminator and advance 2778 // 2779 *CEnd = CSave; 2780 CStart = CEnd; 2781 if (*CStart) { 2782 CStart++; 2783 } 2784 } 2785 2786 free (CopySourceSelect); 2787 2788 } else { 2789 // 2790 // Find all the include files in the [sources.common] sections. 2791 // 2792 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME); 2793 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); 2794 // 2795 // Now process the [sources.$(PROCESSOR)] files. 2796 // 2797 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, Processor); 2798 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); 2799 // 2800 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files. 2801 // 2802 Platform = GetSymbolValue (PLATFORM); 2803 if (Platform != NULL) { 2804 sprintf (Str, "sources.%s.%s", Processor, Platform); 2805 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); 2806 } 2807 } 2808 2809 fprintf (MakeFptr, "\n"); 2810 return STATUS_SUCCESS; 2811 } 2812 2813 int 2814 ProcessIncludeFilesSingle ( 2815 DSC_FILE *ComponentFile, 2816 FILE *MakeFptr, 2817 INT8 *SectionName 2818 ) 2819 { 2820 INT8 *Cptr; 2821 INT8 FileName[MAX_EXP_LINE_LEN]; 2822 INT8 TempFileName[MAX_PATH]; 2823 SECTION *TempSect; 2824 INT8 Str[MAX_LINE_LEN]; 2825 INT8 *OverridePath; 2826 FILE *FPtr; 2827 2828 TempSect = DSCFileFindSection (ComponentFile, SectionName); 2829 if (TempSect != NULL) { 2830 // 2831 // See if the SOURCE_OVERRIDE_PATH has been set. If it has, and 2832 // they have an include file that is overridden, then add the path 2833 // to it to the list of include paths (prepend). 2834 // 2835 OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH); 2836 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { 2837 Cptr = StripLine (Str); 2838 // 2839 // Don't process blank lines 2840 // 2841 if (*Cptr) { 2842 // 2843 // Expand symbols in the filename, then get its parts 2844 // 2845 ExpandSymbols (Cptr, FileName, sizeof (FileName), 0); 2846 AddFileSymbols (FileName); 2847 ReplaceSlash (FileName); 2848 if (IsIncludeFile (FileName)) { 2849 if ((OverridePath != NULL) && (!IsAbsolutePath (FileName))) { 2850 ReplaceSlash (OverridePath); 2851 strcpy (TempFileName, OverridePath); 2852 strcat (TempFileName, "\\"); 2853 strcat (TempFileName, FileName); 2854 if ((FPtr = fopen (TempFileName, "rb")) != NULL) { 2855 fclose (FPtr); 2856 // 2857 // Null-terminate the file name at the last backslash and add that 2858 // to the beginning of the list of include paths. 2859 // 2860 for (Cptr = TempFileName + strlen (TempFileName) - 1; 2861 (Cptr >= TempFileName) && (*Cptr != '\\'); 2862 Cptr-- 2863 ) 2864 ; 2865 if (Cptr >= TempFileName) { 2866 *Cptr = 0; 2867 } 2868 fprintf (MakeFptr, "!IF EXIST(%s)\n", TempFileName); 2869 fprintf (MakeFptr, "INC = -I %s $(INC)\n", TempFileName); 2870 fprintf (MakeFptr, "!ENDIF\n"); 2871 } 2872 } 2873 // 2874 // If absolute path already, don't prepend source directory 2875 // 2876 // if (IsAbsolutePath (FileName)) { 2877 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) %s\n", FileName); 2878 // } else { 2879 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) $(SOURCE_DIR)\\%s\n", FileName); 2880 // } 2881 } 2882 2883 RemoveFileSymbols (); 2884 } 2885 } 2886 } 2887 2888 return STATUS_SUCCESS; 2889 } 2890 2891 static 2892 void 2893 FreeFileParts ( 2894 FILE_NAME_PARTS *FP 2895 ) 2896 { 2897 if (FP != NULL) { 2898 if (FP->Path != NULL) { 2899 free (FP->Path); 2900 } 2901 2902 if (FP->BaseName != NULL) { 2903 free (FP->BaseName); 2904 } 2905 2906 if (FP->Extension != NULL) { 2907 free (FP->Extension); 2908 } 2909 } 2910 } 2911 2912 static 2913 FILE_NAME_PARTS * 2914 GetFileParts ( 2915 INT8 *FileName 2916 ) 2917 { 2918 FILE_NAME_PARTS *FP; 2919 INT8 *Cptr; 2920 INT8 CopyFileName[MAX_PATH]; 2921 INT8 *FileNamePtr; 2922 2923 strcpy (CopyFileName, FileName); 2924 FP = (FILE_NAME_PARTS *) malloc (sizeof (FILE_NAME_PARTS)); 2925 if (FP == NULL) { 2926 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 2927 return NULL; 2928 } 2929 2930 memset ((INT8 *) FP, 0, sizeof (FILE_NAME_PARTS)); 2931 // 2932 // Get extension code 2933 // 2934 FP->ExtensionCode = GetSourceFileType (CopyFileName); 2935 // 2936 // Get drive if there 2937 // 2938 FileNamePtr = CopyFileName; 2939 if (FileNamePtr[1] == ':') { 2940 FP->Drive[0] = FileNamePtr[0]; 2941 FP->Drive[1] = ':'; 2942 FileNamePtr += 2; 2943 } 2944 // 2945 // Start at the end and work back 2946 // 2947 for (Cptr = FileNamePtr + strlen (FileNamePtr) - 1; (Cptr > FileNamePtr) && (*Cptr != '.'); Cptr--) 2948 ; 2949 2950 if (*Cptr == '.') { 2951 // 2952 // Don't copy the dot 2953 // 2954 FP->Extension = (char *) malloc (strlen (Cptr)); 2955 strcpy (FP->Extension, Cptr + 1); 2956 *Cptr = 0; 2957 Cptr--; 2958 StripTrailingSpaces (FP->Extension); 2959 } else { 2960 // 2961 // Create empty string for extension 2962 // 2963 FP->Extension = (char *) malloc (1); 2964 FP->Extension[0] = 0; 2965 } 2966 // 2967 // Now back up and get the base name (include the preceding '\') 2968 // 2969 for (; (Cptr > FileNamePtr) && (*Cptr != '\\'); Cptr--) 2970 ; 2971 FP->BaseName = (char *) malloc (strlen (Cptr) + 1); 2972 strcpy (FP->BaseName, Cptr); 2973 *Cptr = 0; 2974 Cptr--; 2975 // 2976 // Rest is path 2977 // 2978 if (Cptr >= FileNamePtr) { 2979 Cptr = FileNamePtr; 2980 FP->Path = (char *) malloc (strlen (Cptr) + 1); 2981 strcpy (FP->Path, Cptr); 2982 } else { 2983 FP->Path = (char *) malloc (1); 2984 FP->Path[0] = 0; 2985 } 2986 2987 return FP; 2988 } 2989 2990 /***************************************************************************** 2991 ******************************************************************************/ 2992 static 2993 int 2994 WriteCommonMakefile ( 2995 DSC_FILE *DSCFile, 2996 FILE *MakeFptr, 2997 INT8 *Processor 2998 ) 2999 { 3000 INT8 InLine[MAX_LINE_LEN]; 3001 INT8 OutLine[MAX_EXP_LINE_LEN]; 3002 SECTION *Sect; 3003 INT8 *Sym; 3004 int i; 3005 // 3006 // Don't mess up the original file pointer, since we're processing it at a higher 3007 // level. 3008 // 3009 DSCFileSavePosition (DSCFile); 3010 // 3011 // Write the header to the file 3012 // 3013 for (i = 0; MakefileHeader[i] != NULL; i++) { 3014 fprintf (MakeFptr, "%s\n", MakefileHeader[i]); 3015 } 3016 3017 fprintf (MakeFptr, "#\n# Hard-coded defines output by the tool\n#\n"); 3018 // 3019 // First write the basics to the component's makefile. These includes 3020 // EFI_SOURCE, BIN_DIR, OUT_DIR, LIB_DIR, SOURCE_DIR, DEST_DIR. 3021 // 3022 Sym = GetSymbolValue (EFI_SOURCE); 3023 fprintf (MakeFptr, "%s = %s\n", EFI_SOURCE, Sym); 3024 Sym = GetSymbolValue (BUILD_DIR); 3025 fprintf (MakeFptr, "%s = %s\n", BUILD_DIR, Sym); 3026 Sym = GetSymbolValue (BIN_DIR); 3027 fprintf (MakeFptr, "%s = %s\n", BIN_DIR, Sym); 3028 Sym = GetSymbolValue (OUT_DIR); 3029 fprintf (MakeFptr, "%s = %s\n", OUT_DIR, Sym); 3030 Sym = GetSymbolValue (LIB_DIR); 3031 fprintf (MakeFptr, "%s = %s\n", LIB_DIR, Sym); 3032 Sym = GetSymbolValue (SOURCE_DIR); 3033 fprintf (MakeFptr, "%s = %s\n", SOURCE_DIR, Sym); 3034 Sym = GetSymbolValue (DEST_DIR); 3035 fprintf (MakeFptr, "%s = %s\n", DEST_DIR, Sym); 3036 fprintf (MakeFptr, "\n"); 3037 // 3038 // If there was a [makefile.common] section in the description file, 3039 // copy it (after symbol expansion) to the output file. 3040 // 3041 sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, COMMON_SECTION_NAME); 3042 Sect = DSCFileFindSection (DSCFile, InLine); 3043 if (Sect != NULL) { 3044 // 3045 // fprintf (MakeFptr, "# From the [makefile.common] section of the DSC file\n"); 3046 // Read lines, expand, then dump out 3047 // 3048 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { 3049 // 3050 // Replace symbols 3051 // 3052 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); 3053 fprintf (MakeFptr, OutLine); 3054 } 3055 } 3056 // 3057 // If there was a [makefile.platform] section in the description file, 3058 // copy it (after symbol expansion) to the output file. 3059 // 3060 sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, "Platform"); 3061 Sect = DSCFileFindSection (DSCFile, InLine); 3062 if (Sect != NULL) { 3063 // 3064 // Read lines, expand, then dump out 3065 // 3066 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { 3067 // 3068 // Replace symbols 3069 // 3070 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); 3071 fprintf (MakeFptr, OutLine); 3072 } 3073 } 3074 // 3075 // Do the same for any [makefile.$(PROCESSOR)] 3076 // 3077 sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, Processor); 3078 Sect = DSCFileFindSection (DSCFile, InLine); 3079 if (Sect != NULL) { 3080 // 3081 // Read lines, expand, then dump out 3082 // 3083 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { 3084 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); 3085 fprintf (MakeFptr, OutLine); 3086 } 3087 } 3088 // 3089 // Same thing for [makefile.$(PROCESSOR).$(PLATFORM)] 3090 // 3091 Sym = GetSymbolValue (PLATFORM); 3092 if (Sym != NULL) { 3093 sprintf (InLine, "%s.%s.%s", MAKEFILE_SECTION_NAME, Processor, Sym); 3094 Sect = DSCFileFindSection (DSCFile, InLine); 3095 if (Sect != NULL) { 3096 // 3097 // Read lines, expand, then dump out 3098 // 3099 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { 3100 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); 3101 fprintf (MakeFptr, OutLine); 3102 } 3103 } 3104 } 3105 3106 fprintf (MakeFptr, "\n"); 3107 DSCFileRestorePosition (DSCFile); 3108 return 0; 3109 } 3110 3111 static 3112 int 3113 WriteComponentTypeBuildCommands ( 3114 DSC_FILE *DSCFile, 3115 FILE *MakeFptr, 3116 INT8 *SectionName 3117 ) 3118 /*++ 3119 3120 Routine Description: 3121 3122 Given a section name such as [build.ia32.library], find the section in 3123 the description file and copy the build commands. 3124 3125 Arguments: 3126 3127 DSCFile - section information on the main description file 3128 MakeFptr - file pointer to the makefile we're writing to 3129 SectionName - name of the section we're to copy out to the makefile. 3130 3131 Returns: 3132 3133 Always successful, since the section may be optional. 3134 3135 --*/ 3136 { 3137 SECTION *Sect; 3138 INT8 InLine[MAX_LINE_LEN]; 3139 INT8 OutLine[MAX_EXP_LINE_LEN]; 3140 3141 // 3142 // Don't mess up the original file pointer, since we're processing it at a higher 3143 // level. 3144 // 3145 DSCFileSavePosition (DSCFile); 3146 Sect = DSCFileFindSection (DSCFile, SectionName); 3147 if (Sect != NULL) { 3148 // 3149 // Read lines, expand, then dump out 3150 // 3151 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { 3152 ExpandSymbols ( 3153 InLine, 3154 OutLine, 3155 sizeof(OutLine), 3156 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR 3157 ); 3158 fprintf (MakeFptr, OutLine); 3159 } 3160 } else { 3161 Warning ( 3162 NULL, 3163 0, 3164 0, 3165 GetSymbolValue (INF_FILENAME), 3166 "no [%s] build commands found in DSC file for component", 3167 SectionName 3168 ); 3169 } 3170 3171 DSCFileRestorePosition (DSCFile); 3172 return STATUS_SUCCESS; 3173 } 3174 3175 /***************************************************************************** 3176 3177 ******************************************************************************/ 3178 static 3179 int 3180 WriteCompileCommands ( 3181 DSC_FILE *DscFile, 3182 FILE *MakeFptr, 3183 INT8 *FileName, 3184 INT8 *Processor 3185 ) 3186 { 3187 FILE_NAME_PARTS *File; 3188 SECTION *Sect; 3189 INT8 BuildSectionName[40]; 3190 INT8 InLine[MAX_LINE_LEN]; 3191 INT8 OutLine[MAX_EXP_LINE_LEN]; 3192 INT8 *SourceCompileType; 3193 char *CPtr; 3194 char *CPtr2; 3195 // 3196 // Determine the filename, then chop it up into its parts 3197 // 3198 File = GetFileParts (FileName); 3199 if (File != NULL) { 3200 // 3201 // Don't mess up the original file pointer, since we're processing it at a higher 3202 // level. 3203 // 3204 DSCFileSavePosition (DscFile); 3205 // 3206 // Option 1: SOURCE_COMPILE_TYPE=MyCompileSection 3207 // Find a section of that name from which to get the compile 3208 // commands for this source file. 3209 // Look for [compile.$(PROCESSOR).$(SOURCE_COMPILE_TYPE] 3210 // Option 2: COMPILE_SELECT=.c=MyCCompile,.asm=MyAsm 3211 // Find a [compile.$(PROCESSOR).MyCompile] section from which to 3212 // get the compile commands for this source file. 3213 // Look for [compile.$(PROCESSOR).MyCompile] 3214 // Option 3: Look for standard section types to compile the file by extension. 3215 // Look for [compile.$(PROCESSOR).<extension>] 3216 // 3217 Sect = NULL; 3218 // 3219 // Option 1 - use SOURCE_COMPILE_TYPE variable 3220 // 3221 SourceCompileType = GetSymbolValue (SOURCE_COMPILE_TYPE); 3222 if (SourceCompileType != NULL) { 3223 sprintf (BuildSectionName, "compile.%s.%s", Processor, SourceCompileType); 3224 Sect = DSCFileFindSection (DscFile, BuildSectionName); 3225 } 3226 // 3227 // Option 2 - use COMPILE_SELECT variable 3228 // 3229 if (Sect == NULL) { 3230 SourceCompileType = GetSymbolValue (COMPILE_SELECT); 3231 if (SourceCompileType != NULL) { 3232 // 3233 // Parse the variable, which looks like COMPILE_SELECT=.c=MyCCompiler;.asm=MyAsm; 3234 // to find an entry with a matching file name extension. If you find one, 3235 // then use that name to find the section name. 3236 // 3237 CPtr = SourceCompileType; 3238 while (*CPtr && (Sect == NULL)) { 3239 // 3240 // See if we found a match with this source file name extension. File->Extension 3241 // does not include the dot, so skip the dot in the COMPILE_SELECT variable if there 3242 // is one. 3243 // 3244 if (*CPtr == '.') { 3245 CPtr++; 3246 } 3247 3248 if (_strnicmp (CPtr, File->Extension, strlen (File->Extension)) == 0) { 3249 // 3250 // Found a file name extension match -- extract the name from the variable, for 3251 // example "MyCCompiler" 3252 // 3253 while (*CPtr && (*CPtr != '=')) { 3254 CPtr++; 3255 } 3256 3257 if ((*CPtr != '=') || (CPtr[1] == 0)) { 3258 Error (NULL, 0, 0, SourceCompileType, "malformed COMPILE_SELECT variable"); 3259 break; 3260 } 3261 3262 CPtr++; 3263 sprintf (BuildSectionName, "compile.%s.", Processor); 3264 for (CPtr2 = BuildSectionName + strlen (BuildSectionName); 3265 *CPtr && (*CPtr != ',') && (*CPtr != ';'); 3266 CPtr++ 3267 ) { 3268 *CPtr2 = *CPtr; 3269 CPtr2++; 3270 } 3271 3272 *CPtr2 = 0; 3273 Sect = DSCFileFindSection (DscFile, BuildSectionName); 3274 if (Sect == NULL) { 3275 ParserError ( 3276 0, 3277 BuildSectionName, 3278 "could not find section in DSC file - selected by COMPILE_SELECT variable" 3279 ); 3280 } 3281 } 3282 3283 // 3284 // Skip to next file name extension in the COMPILE_SELECT variable 3285 // 3286 while (*CPtr && (*CPtr != ';') && (*CPtr != ',')) { 3287 CPtr++; 3288 } 3289 3290 if (*CPtr) { 3291 CPtr++; 3292 } 3293 } 3294 } 3295 } 3296 // 3297 // Option 3 - use "Compile.$(PROCESSOR).<Extension>" section 3298 // 3299 if (Sect == NULL) { 3300 sprintf (BuildSectionName, "compile.%s.%s", Processor, File->Extension); 3301 Sect = DSCFileFindSection (DscFile, BuildSectionName); 3302 } 3303 // 3304 // Should have found something by now unless it's an include (.h) file 3305 // 3306 if (Sect != NULL) { 3307 // 3308 // Temporarily add a FILE variable to the global symbol table. Omit the 3309 // extension. 3310 // 3311 sprintf (InLine, "%s%s%s", File->Drive, File->Path, File->BaseName); 3312 AddSymbol ("FILE", InLine, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME); 3313 // 3314 // Read lines, expand (except SOURCE_DIR and DEST_DIR), then dump out 3315 // 3316 while (DSCFileGetLine (DscFile, InLine, sizeof (InLine)) != NULL) { 3317 ExpandSymbols ( 3318 InLine, 3319 OutLine, 3320 sizeof (OutLine), 3321 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR 3322 ); 3323 fprintf (MakeFptr, OutLine); 3324 } 3325 fprintf (MakeFptr, "\n"); 3326 } else { 3327 // 3328 // Be nice and ignore include files 3329 // 3330 if (!IsIncludeFile (FileName)) { 3331 Error ( 3332 NULL, 3333 0, 3334 0, 3335 NULL, 3336 "no compile commands section [%s] found in DSC file for %s", 3337 BuildSectionName, 3338 FileName 3339 ); 3340 } 3341 } 3342 3343 DSCFileRestorePosition (DscFile); 3344 FreeFileParts (File); 3345 } 3346 3347 return STATUS_SUCCESS; 3348 } 3349 3350 /***************************************************************************** 3351 ******************************************************************************/ 3352 static 3353 int 3354 SetFileExtension ( 3355 INT8 *FileName, 3356 INT8 *Extension 3357 ) 3358 { 3359 INT8 *Cptr; 3360 3361 Cptr = FileName + strlen (FileName) - 1; 3362 while ((Cptr > FileName) && (*Cptr != '.')) { 3363 Cptr--; 3364 3365 } 3366 // 3367 // Better be a dot 3368 // 3369 if (*Cptr != '.') { 3370 Message (2, "Missing filename extension: %s", FileName); 3371 return STATUS_WARNING; 3372 } 3373 3374 Cptr++; 3375 if (*Extension == '.') { 3376 Extension++; 3377 } 3378 3379 strcpy (Cptr, Extension); 3380 return STATUS_SUCCESS; 3381 } 3382 3383 /***************************************************************************** 3384 ******************************************************************************/ 3385 int 3386 MakeFilePath ( 3387 INT8 *FileName 3388 ) 3389 { 3390 INT8 *Cptr; 3391 INT8 SavedChar; 3392 INT8 BuildDir[MAX_PATH]; 3393 INT8 CopyFileName[MAX_PATH]; 3394 3395 // 3396 // Expand symbols in the filename 3397 // 3398 if (ExpandSymbols (FileName, CopyFileName, sizeof (CopyFileName), EXPANDMODE_NO_UNDEFS)) { 3399 Error (NULL, 0, 0, NULL, "undefined symbols in file path: %s", FileName); 3400 return STATUS_ERROR; 3401 } 3402 // 3403 // Copy it back 3404 // 3405 strcpy (FileName, CopyFileName); 3406 // 3407 // To avoid creating $(BUILD_DIR) path, see if this path is the same as 3408 // $(BUILD_DIR), and if it is, see if build dir exists and skip over that 3409 // portion if it does 3410 // 3411 Cptr = GetSymbolValue (BUILD_DIR); 3412 if (Cptr != NULL) { 3413 if (_strnicmp (Cptr, FileName, strlen (Cptr)) == 0) { 3414 // 3415 // BUILD_DIR path. See if it exists 3416 // 3417 strcpy (BuildDir, FileName); 3418 BuildDir[strlen (Cptr)] = 0; 3419 if ((_mkdir (BuildDir) != 0) && (errno != EEXIST)) { 3420 Cptr = FileName; 3421 } else { 3422 // 3423 // Already done. Shortcut. Skip to next path so that we don't create 3424 // the BUILD_DIR as well. 3425 // 3426 Cptr = FileName + strlen (Cptr); 3427 if (*Cptr == '\\') { 3428 Cptr++; 3429 } 3430 } 3431 } else { 3432 // 3433 // Not build dir 3434 // 3435 Cptr = FileName; 3436 } 3437 } else { 3438 Cptr = FileName; 3439 } 3440 // 3441 // Create directories until done. Skip over "c:\" in the path if it exists 3442 // 3443 if (*Cptr && (*(Cptr + 1) == ':') && (*(Cptr + 2) == '\\')) { 3444 Cptr += 3; 3445 } 3446 3447 for (;;) { 3448 for (; *Cptr && (*Cptr != '\\'); Cptr++) 3449 ; 3450 if (*Cptr) { 3451 SavedChar = *Cptr; 3452 *Cptr = 0; 3453 if ((_mkdir (FileName) != 0)) { 3454 // 3455 // Error (NULL, 0, 0, FileName, "failed to create directory"); 3456 // return 1; 3457 // 3458 } 3459 3460 *Cptr = SavedChar; 3461 Cptr++; 3462 } else { 3463 break; 3464 } 3465 } 3466 3467 return STATUS_SUCCESS; 3468 } 3469 3470 /***************************************************************************** 3471 ******************************************************************************/ 3472 int 3473 ExpandSymbols ( 3474 INT8 *SourceLine, 3475 INT8 *DestLine, 3476 int LineLen, 3477 int ExpandMode 3478 ) 3479 { 3480 static int NestDepth = 0; 3481 INT8 *FromPtr; 3482 INT8 *ToPtr; 3483 INT8 *SaveStart; 3484 INT8 *Cptr; 3485 INT8 *value; 3486 int Expanded; 3487 int ExpandedCount; 3488 INT8 *LocalDestLine; 3489 STATUS Status; 3490 int LocalLineLen; 3491 3492 NestDepth++; 3493 Status = STATUS_SUCCESS; 3494 LocalDestLine = (INT8 *) malloc (LineLen); 3495 if (LocalDestLine == NULL) { 3496 Error (__FILE__, __LINE__, 0, "application error", "memory allocation failed"); 3497 NestDepth = 0; 3498 return STATUS_ERROR; 3499 } 3500 3501 FromPtr = SourceLine; 3502 ToPtr = LocalDestLine; 3503 // 3504 // Walk the entire line, replacing $(SYMBOL_NAME). 3505 // 3506 LocalLineLen = LineLen; 3507 ExpandedCount = 0; 3508 while (*FromPtr && (LocalLineLen > 0)) { 3509 if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) { 3510 // 3511 // Save the start in case it's undefined, in which case we copy it as-is. 3512 // 3513 SaveStart = FromPtr; 3514 Expanded = 0; 3515 // 3516 // Symbol expansion time. Find the end (no spaces allowed) 3517 // 3518 FromPtr += 2; 3519 for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++) 3520 ; 3521 if (*Cptr) { 3522 // 3523 // Truncate the string at the closing parenthesis for ease-of-use. 3524 // Then copy the string directly to the destination line in case we don't find 3525 // a definition for it. 3526 // 3527 *Cptr = 0; 3528 strcpy (ToPtr, SaveStart); 3529 if ((_stricmp (SOURCE_DIR, FromPtr) == 0) && (ExpandMode & EXPANDMODE_NO_SOURCEDIR)) { 3530 // 3531 // excluded this expansion 3532 // 3533 } else if ((_stricmp (DEST_DIR, FromPtr) == 0) && (ExpandMode & EXPANDMODE_NO_DESTDIR)) { 3534 // 3535 // excluded this expansion 3536 // 3537 } else if ((value = GetSymbolValue (FromPtr)) != NULL) { 3538 strcpy (ToPtr, value); 3539 LocalLineLen -= strlen (value); 3540 ToPtr += strlen (value); 3541 Expanded = 1; 3542 ExpandedCount++; 3543 } else if (ExpandMode & EXPANDMODE_NO_UNDEFS) { 3544 Error (NULL, 0, 0, "undefined symbol", "$(%s)", FromPtr); 3545 Status = STATUS_ERROR; 3546 goto Done; 3547 } 3548 3549 // 3550 // Restore closing parenthesis, and advance to next character 3551 // 3552 *Cptr = ')'; 3553 if (!Expanded) { 3554 FromPtr = SaveStart + 1; 3555 ToPtr++; 3556 } else { 3557 FromPtr = Cptr + 1; 3558 } 3559 } else { 3560 Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on symbol"); 3561 strcpy (ToPtr, FromPtr); 3562 Status = STATUS_WARNING; 3563 goto Done; 3564 } 3565 } else { 3566 *ToPtr = *FromPtr; 3567 FromPtr++; 3568 ToPtr++; 3569 LocalLineLen--; 3570 } 3571 } 3572 3573 if (*FromPtr == 0) { 3574 *ToPtr = 0; 3575 } 3576 3577 // 3578 // If we're in recursive mode, and we expanded at least one string successfully, 3579 // then make a recursive call to try again. 3580 // 3581 if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (ExpandMode & EXPANDMODE_RECURSIVE) && (NestDepth < 2)) { 3582 Status = ExpandSymbols (LocalDestLine, DestLine, LineLen, ExpandMode); 3583 free (LocalDestLine); 3584 NestDepth = 0; 3585 return Status; 3586 } 3587 3588 Done: 3589 if (Status != STATUS_ERROR) { 3590 strcpy (DestLine, LocalDestLine); 3591 } 3592 3593 NestDepth = 0; 3594 free (LocalDestLine); 3595 return Status; 3596 } 3597 3598 INT8 * 3599 GetSymbolValue ( 3600 INT8 *SymbolName 3601 ) 3602 /*++ 3603 3604 Routine Description: 3605 3606 Look up a symbol in our symbol table. 3607 3608 Arguments: 3609 3610 SymbolName - The name of symbol. 3611 3612 Returns: 3613 3614 Pointer to the value of the symbol if found 3615 NULL if the symbol is not found 3616 3617 --*/ 3618 { 3619 SYMBOL *Symbol; 3620 3621 // 3622 // Scan once for file-level symbols 3623 // 3624 Symbol = gGlobals.Symbol; 3625 while (Symbol) { 3626 if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_FILE)) { 3627 return Symbol->Value; 3628 } 3629 3630 Symbol = Symbol->Next; 3631 } 3632 // 3633 // Scan once for local symbols 3634 // 3635 Symbol = gGlobals.Symbol; 3636 while (Symbol) { 3637 if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_LOCAL)) { 3638 return Symbol->Value; 3639 } 3640 3641 Symbol = Symbol->Next; 3642 } 3643 // 3644 // No local value found. Scan for globals. 3645 // 3646 Symbol = gGlobals.Symbol; 3647 while (Symbol) { 3648 if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_GLOBAL)) { 3649 return Symbol->Value; 3650 } 3651 3652 Symbol = Symbol->Next; 3653 } 3654 // 3655 // For backwards-compatibility, if it's "GUID", return FILE_GUID value 3656 // 3657 if (_stricmp (SymbolName, GUID) == 0) { 3658 return GetSymbolValue (FILE_GUID); 3659 } 3660 3661 return NULL; 3662 } 3663 3664 static 3665 int 3666 RemoveLocalSymbols ( 3667 VOID 3668 ) 3669 /*++ 3670 3671 Routine Description: 3672 3673 Remove all local symbols from the symbol table. Local symbols are those 3674 that are defined typically by the component's INF file. 3675 3676 Arguments: 3677 3678 None. 3679 3680 Returns: 3681 3682 Right now, never fails. 3683 3684 --*/ 3685 { 3686 SYMBOL *Sym; 3687 int FoundOne; 3688 3689 do { 3690 FoundOne = 0; 3691 Sym = gGlobals.Symbol; 3692 while (Sym) { 3693 if (Sym->Type & SYM_LOCAL) { 3694 // 3695 // Going to delete it out from under ourselves, so break and restart 3696 // 3697 FoundOne = 1; 3698 RemoveSymbol (Sym->Name, SYM_LOCAL); 3699 break; 3700 } 3701 3702 Sym = Sym->Next; 3703 } 3704 } while (FoundOne); 3705 return STATUS_SUCCESS; 3706 } 3707 3708 static 3709 int 3710 RemoveFileSymbols ( 3711 VOID 3712 ) 3713 /*++ 3714 3715 Routine Description: 3716 3717 Remove all file-level symbols from the symbol table. File-level symbols are 3718 those that are defined on a source file line in an INF file. 3719 3720 Arguments: 3721 3722 None. 3723 3724 Returns: 3725 3726 Right now, never fails. 3727 3728 --*/ 3729 { 3730 SYMBOL *Sym; 3731 int FoundOne; 3732 3733 do { 3734 FoundOne = 0; 3735 Sym = gGlobals.Symbol; 3736 while (Sym) { 3737 if (Sym->Type & SYM_FILE) { 3738 // 3739 // Going to delete it out from under ourselves, so break and restart 3740 // 3741 FoundOne = 1; 3742 RemoveSymbol (Sym->Name, SYM_FILE); 3743 break; 3744 } 3745 3746 Sym = Sym->Next; 3747 } 3748 } while (FoundOne); 3749 return STATUS_SUCCESS; 3750 } 3751 3752 static 3753 STATUS 3754 ParseGuidDatabaseFile ( 3755 INT8 *FileName 3756 ) 3757 /*++ 3758 3759 Routine Description: 3760 This function parses a GUID-to-basename text file (perhaps output by 3761 the GuidChk utility) to define additional symbols. The format of the 3762 file should be: 3763 3764 7BB28B99-61BB-11D5-9A5D-0090273FC14D EFI_DEFAULT_BMP_LOGO_GUID gEfiDefaultBmpLogoGuid 3765 3766 This function parses the line and defines global symbol: 3767 3768 EFI_DEFAULT_BMP_LOGO_GUID=7BB28B99-61BB-11D5-9A5D-0090273FC14D 3769 3770 This symbol (rather than the actual GUID) can then be used in INF files to 3771 fix duplicate GUIDs 3772 3773 Arguments: 3774 FileName - the name of the file to parse. 3775 3776 Returns: 3777 STATUS_ERROR - could not open FileName 3778 STATUS_SUCCESS - we opened the file 3779 3780 --*/ 3781 { 3782 FILE *Fptr; 3783 INT8 Line[100]; 3784 INT8 Guid[100]; 3785 INT8 DefineName[80]; 3786 3787 Fptr = fopen (FileName, "r"); 3788 if (Fptr == NULL) { 3789 Error (NULL, 0, 0, FileName, "failed to open input GUID database input file"); 3790 return STATUS_ERROR; 3791 } 3792 3793 while (fgets (Line, sizeof (Line), Fptr) != NULL) { 3794 // 3795 // Get the GUID string, skip the defined name (EFI_XXX_GUID), and get the 3796 // variable name (gWhateverProtocolGuid) 3797 // 3798 if (sscanf (Line, "%s %s %*s", Guid, DefineName) == 2) { 3799 AddSymbol (DefineName, Guid, SYM_GLOBAL); 3800 } 3801 } 3802 3803 fclose (Fptr); 3804 return STATUS_SUCCESS; 3805 } 3806 3807 /***************************************************************************** 3808 3809 Returns: 3810 0 if successful standard add 3811 length of the parsed string if passed in " name = value " 3812 < 0 on error 3813 3814 ******************************************************************************/ 3815 int 3816 AddSymbol ( 3817 INT8 *Name, 3818 INT8 *Value, 3819 int Mode 3820 ) 3821 { 3822 SYMBOL *Symbol; 3823 SYMBOL *NewSymbol; 3824 int Len; 3825 INT8 *Start; 3826 INT8 *Cptr; 3827 INT8 CSave1; 3828 INT8 *SaveCptr1; 3829 INT8 CSave2; 3830 INT8 *SaveCptr2; 3831 INT8 ShortName[MAX_PATH]; 3832 3833 Len = 0; 3834 SaveCptr1 = NULL; 3835 CSave1 = 0; 3836 SaveCptr2 = NULL; 3837 CSave2 = 0; 3838 3839 ShortName[0] = 0; 3840 // 3841 // Mode better be local or global symbol 3842 // 3843 if ((Mode & (SYM_LOCAL | SYM_GLOBAL | SYM_FILE)) == 0) { 3844 Error (NULL, 0, 0, "APP ERROR", "adding symbol '%s' that is not local, global, nor file level", Name); 3845 return -1; 3846 } 3847 // 3848 // If value pointer is null, then they passed us a line something like: 3849 // varname = value, or simply var = 3850 // 3851 if (Value == NULL) { 3852 Start = Name; 3853 while (*Name && isspace (*Name)) { 3854 Name++; 3855 3856 } 3857 3858 if (!*Name) { 3859 return -1; 3860 } 3861 // 3862 // Find the end of the name. Either space or a '='. 3863 // 3864 for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++) 3865 ; 3866 if (!*Value) { 3867 return -1; 3868 } 3869 // 3870 // Look for the '=' 3871 // 3872 Cptr = Value; 3873 while (*Value && (*Value != '=')) { 3874 Value++; 3875 } 3876 3877 if (!*Value) { 3878 return -1; 3879 } 3880 3881 // 3882 // Now truncate the name 3883 // 3884 CSave1 = *Cptr; 3885 SaveCptr1 = Cptr; 3886 *Cptr = 0; 3887 3888 // 3889 // Skip over the = and then any spaces 3890 // 3891 Value++; 3892 while (*Value && isspace (*Value)) { 3893 Value++; 3894 3895 } 3896 // 3897 // Find end of string, checking for quoted string 3898 // 3899 if (*Value == '\"') { 3900 Value++; 3901 for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++) 3902 ; 3903 } else { 3904 for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++) 3905 ; 3906 } 3907 // 3908 // Null terminate the value string 3909 // 3910 if (*Cptr) { 3911 Len = (int) (Cptr - Start) + 1; 3912 CSave2 = *Cptr; 3913 SaveCptr2 = Cptr; 3914 *Cptr = 0; 3915 } else { 3916 Len = (int) (Cptr - Start); 3917 } 3918 } 3919 3920 // 3921 // If file name or file path, and we're shortening, then print it 3922 // 3923 if ((Mode & (SYM_FILEPATH | SYM_FILENAME)) && (GetSymbolValue (SHORT_NAMES) != NULL)) { 3924 if (GetShortPathName (Value, ShortName, sizeof (ShortName)) > 0) { 3925 // 3926 // fprintf (stdout, "String value '%s' shortened to '%s'\n", 3927 // Value, ShortName); 3928 // 3929 Value = ShortName; 3930 } else { 3931 // 3932 // fprintf (stdout, "WARNING: Failed to get short name for %s\n", Value); 3933 // 3934 } 3935 } 3936 // 3937 // We now have a symbol name and a value. Look for an existing variable of 3938 // the same type (global or local) and overwrite it. 3939 // 3940 Symbol = gGlobals.Symbol; 3941 while (Symbol) { 3942 // 3943 // Check for symbol name match 3944 // 3945 if (_stricmp (Name, Symbol->Name) == 0) { 3946 // 3947 // See if this symbol is of the same type (global or local) as what 3948 // they're requesting 3949 // 3950 if ((Symbol->Type & (SYM_LOCAL | SYM_GLOBAL)) == (Mode & (SYM_LOCAL | SYM_GLOBAL))) { 3951 // 3952 // Did they say we could overwrite it? 3953 // 3954 if (Mode & SYM_OVERWRITE) { 3955 free (Symbol->Value); 3956 Symbol->Value = (INT8 *) malloc (strlen (Value) + 1); 3957 if (Symbol->Value == NULL) { 3958 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 3959 return -1; 3960 } 3961 3962 strcpy (Symbol->Value, Value); 3963 // 3964 // If value == "NULL", then make it a 0-length string 3965 // 3966 if (_stricmp (Symbol->Value, "NULL") == 0) { 3967 Symbol->Value[0] = 0; 3968 } 3969 3970 return Len; 3971 } else { 3972 return STATUS_ERROR; 3973 } 3974 } 3975 } 3976 3977 Symbol = Symbol->Next; 3978 } 3979 // 3980 // Does not exist, create a new one 3981 // 3982 NewSymbol = (SYMBOL *) malloc (sizeof (SYMBOL)); 3983 if (NewSymbol == NULL) { 3984 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 3985 return -1; 3986 } 3987 3988 memset ((INT8 *) NewSymbol, 0, sizeof (SYMBOL)); 3989 NewSymbol->Name = (INT8 *) malloc (strlen (Name) + 1); 3990 NewSymbol->Value = (INT8 *) malloc (strlen (Value) + 1); 3991 // 3992 // Simply use the mode bits as the type. 3993 // 3994 NewSymbol->Type = Mode; 3995 if ((NewSymbol->Name == NULL) || (NewSymbol->Value == NULL)) { 3996 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 3997 return -1; 3998 } 3999 4000 strcpy (NewSymbol->Name, Name); 4001 strcpy (NewSymbol->Value, Value); 4002 // 4003 // Remove trailing spaces 4004 // 4005 Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1; 4006 while (Cptr > NewSymbol->Value) { 4007 if (isspace (*Cptr)) { 4008 *Cptr = 0; 4009 Cptr--; 4010 } else { 4011 break; 4012 } 4013 } 4014 // 4015 // Add it to the head of the list. 4016 // 4017 NewSymbol->Next = gGlobals.Symbol; 4018 gGlobals.Symbol = NewSymbol; 4019 // 4020 // If value == "NULL", then make it a 0-length string 4021 // 4022 if (_stricmp (NewSymbol->Value, "NULL") == 0) { 4023 NewSymbol->Value[0] = 0; 4024 } 4025 // 4026 // Restore the terminator we inserted if they passed in var=value 4027 // 4028 if (SaveCptr1 != NULL) { 4029 *SaveCptr1 = CSave1; 4030 } 4031 if (SaveCptr2 != NULL) { 4032 *SaveCptr2 = CSave2; 4033 } 4034 4035 return Len; 4036 } 4037 4038 /***************************************************************************** 4039 ******************************************************************************/ 4040 static 4041 int 4042 RemoveSymbol ( 4043 INT8 *Name, 4044 INT8 SymbolType 4045 ) 4046 { 4047 SYMBOL *Symbol; 4048 SYMBOL *PrevSymbol; 4049 4050 PrevSymbol = NULL; 4051 Symbol = gGlobals.Symbol; 4052 while (Symbol) { 4053 if ((_stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) { 4054 if (Symbol->Value) { 4055 free (Symbol->Value); 4056 } 4057 4058 free (Symbol->Name); 4059 if (PrevSymbol) { 4060 PrevSymbol->Next = Symbol->Next; 4061 } else { 4062 gGlobals.Symbol = Symbol->Next; 4063 } 4064 4065 free (Symbol); 4066 return STATUS_SUCCESS; 4067 } 4068 4069 PrevSymbol = Symbol; 4070 Symbol = Symbol->Next; 4071 } 4072 4073 return STATUS_WARNING; 4074 } 4075 4076 #if 0 4077 4078 /***************************************************************************** 4079 ******************************************************************************/ 4080 static 4081 void 4082 FreeSections ( 4083 SECTION *Sect 4084 ) 4085 { 4086 SECTION *Next; 4087 4088 while (Sect != NULL) { 4089 Next = Sect->Next; 4090 if (Sect->Name != NULL) { 4091 delete[] Sect->Name; 4092 } 4093 4094 delete Sect; 4095 Sect = Next; 4096 } 4097 } 4098 #endif 4099 4100 /***************************************************************************** 4101 ******************************************************************************/ 4102 static 4103 INT8 * 4104 StripLine ( 4105 INT8 *Line 4106 ) 4107 { 4108 INT8 *Cptr; 4109 int Len; 4110 4111 Cptr = Line; 4112 // 4113 // Look for '#' comments in first character of line 4114 // 4115 if (*Cptr == '#') { 4116 *Cptr = 0; 4117 return Cptr; 4118 } 4119 4120 while (isspace (*Cptr)) { 4121 Cptr++; 4122 } 4123 // 4124 // Hack off newlines 4125 // 4126 Len = strlen (Cptr); 4127 if ((Len > 0) && (Cptr[Len - 1] == '\n')) { 4128 Cptr[Len - 1] = 0; 4129 } 4130 // 4131 // Hack off trailing spaces 4132 // 4133 StripTrailingSpaces (Cptr); 4134 return Cptr; 4135 } 4136 4137 /***************************************************************************** 4138 FUNCTION: ProcessOptions() 4139 4140 DESCRIPTION: Process the command-line options. 4141 ******************************************************************************/ 4142 static 4143 int 4144 ProcessOptions ( 4145 int Argc, 4146 INT8 *Argv[] 4147 ) 4148 /*++ 4149 4150 Routine Description: 4151 4152 Process the command line options to this utility. 4153 4154 Arguments: 4155 4156 Argc - Standard Argc. 4157 Argv[] - Standard Argv. 4158 4159 Returns: 4160 4161 --*/ 4162 { 4163 INT8 *Cptr; 4164 int FreeCwd; 4165 4166 // 4167 // Clear out the options 4168 // 4169 memset ((INT8 *) &gGlobals, 0, sizeof (gGlobals)); 4170 4171 Argc--; 4172 Argv++; 4173 4174 if (Argc == 0) { 4175 Usage (); 4176 return STATUS_ERROR; 4177 } 4178 // 4179 // Now process the arguments 4180 // 4181 while (Argc > 0) { 4182 4183 if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) { 4184 switch (Argv[0][1]) { 4185 // 4186 // -? or -h help option 4187 // 4188 case '?': 4189 case 'h': 4190 case 'H': 4191 Usage (); 4192 return STATUS_ERROR; 4193 4194 // 4195 // /d symbol=name 4196 // 4197 case 'd': 4198 case 'D': 4199 // 4200 // Skip to next arg 4201 // 4202 Argc--; 4203 Argv++; 4204 if (Argc == 0) { 4205 Argv--; 4206 Error (NULL, 0, 0, NULL, "missing symbol definition with %c%c", Argv[0][0], Argv[0][1]); 4207 return STATUS_ERROR; 4208 } else { 4209 if (AddSymbol (Argv[0], NULL, SYM_OVERWRITE | SYM_GLOBAL) <= 0) { 4210 Warning (NULL, 0, 0, Argv[0], "failed to add symbol: %s"); 4211 } 4212 } 4213 break; 4214 4215 // 4216 // output makefile name 4217 // 4218 case 'm': 4219 case 'M': 4220 // 4221 // Skip to next arg 4222 // 4223 Argc--; 4224 Argv++; 4225 if (Argc == 0) { 4226 Argv--; 4227 Error (NULL, 0, 0, Argv[0], "missing output makefile name with option"); 4228 Usage (); 4229 return STATUS_ERROR; 4230 } else { 4231 strcpy (gGlobals.MakefileName, Argv[0]); 4232 } 4233 break; 4234 4235 // 4236 // Print a cross-reference file containing guid/basename/processor 4237 // 4238 case 'x': 4239 case 'X': 4240 // 4241 // Skip to next arg 4242 // 4243 Argc--; 4244 Argv++; 4245 if (Argc == 0) { 4246 Argv--; 4247 Error (NULL, 0, 0, Argv[0], "missing cross-reference output filename with option"); 4248 Usage (); 4249 return STATUS_ERROR; 4250 } else { 4251 strcpy (gGlobals.XRefFileName, Argv[0]); 4252 } 4253 break; 4254 4255 // 4256 // GUID database file to preparse 4257 // 4258 case 'g': 4259 case 'G': 4260 // 4261 // Skip to next arg 4262 // 4263 Argc--; 4264 Argv++; 4265 if (Argc == 0) { 4266 Argv--; 4267 Error (NULL, 0, 0, Argv[0], "missing input GUID database filename with option"); 4268 Usage (); 4269 return STATUS_ERROR; 4270 } else { 4271 strcpy (gGlobals.GuidDatabaseFileName, Argv[0]); 4272 } 4273 break; 4274 4275 // 4276 // Enable multi-thread build and specify the thread number 4277 // 4278 case 'n': 4279 case 'N': 4280 // 4281 // Skip to next arg 4282 // 4283 Argc--; 4284 Argv++; 4285 if (Argc == 0) { 4286 Argv--; 4287 Error (NULL, 0, 0, Argv[0], "missing input thread number with option"); 4288 Usage (); 4289 return STATUS_ERROR; 4290 } else { 4291 gGlobals.ThreadNumber = atoi (Argv[0]); 4292 if (gGlobals.ThreadNumber == 0) { 4293 Argv--; 4294 Error (NULL, 0, 0, Argv[0], "input thread number should not be %s", Argv[1]); 4295 return STATUS_ERROR; 4296 } else if (gGlobals.ThreadNumber > MAXIMUM_WAIT_OBJECTS) { 4297 Argv--; 4298 Error (NULL, 0, 0, Argv[0], "input thread number should not greater than %d", MAXIMUM_WAIT_OBJECTS); 4299 return STATUS_ERROR; 4300 } 4301 } 4302 break; 4303 4304 // 4305 // Specify the multi-thread build target 4306 // 4307 case 't': 4308 case 'T': 4309 // 4310 // Skip to next arg 4311 // 4312 Argc--; 4313 Argv++; 4314 if (Argc == 0) { 4315 Argv--; 4316 Error (NULL, 0, 0, Argv[0], "missing input build target with option"); 4317 Usage (); 4318 return STATUS_ERROR; 4319 } else if (_stricmp (Argv[0], "all") == 0) { 4320 gGlobals.BuildTarget |= BUILD_TARGET_ALL; 4321 } else if (_stricmp (Argv[0], "libraries") == 0) { 4322 gGlobals.BuildTarget |= BUILD_TARGET_LIBRARIES; 4323 } else if (_stricmp (Argv[0], "components") == 0) { 4324 gGlobals.BuildTarget |= BUILD_TARGET_COMPONENTS; 4325 } else { 4326 Argv--; 4327 Error (NULL, 0, 0, Argv[0], "input build target not supported"); 4328 Usage (); 4329 } 4330 break; 4331 4332 case 'v': 4333 case 'V': 4334 gGlobals.Verbose = 1; 4335 break; 4336 4337 default: 4338 Error (NULL, 0, 0, Argv[0], "unrecognized option"); 4339 return STATUS_ERROR; 4340 } 4341 } else { 4342 break; 4343 } 4344 4345 Argc--; 4346 Argv++; 4347 } 4348 // 4349 // Must be at least one arg left 4350 // 4351 if (Argc > 0) { 4352 gGlobals.DscFilename = Argv[0]; 4353 } 4354 4355 if (gGlobals.DscFilename == NULL) { 4356 Error (NULL, 0, 0, NULL, "must specify DSC filename on command line"); 4357 return STATUS_ERROR; 4358 } 4359 // 4360 // Make a global symbol for the DSC filename 4361 // 4362 AddSymbol (DSC_FILENAME, gGlobals.DscFilename, SYM_GLOBAL | SYM_FILENAME); 4363 // 4364 // If no output makefile specified, take the default 4365 // 4366 if (gGlobals.MakefileName[0] == 0) { 4367 strcpy (gGlobals.MakefileName, MAKEFILE_OUT_NAME); 4368 } 4369 // 4370 // Get the current working directory and use it for the build directory. 4371 // Only do this if they have not defined it on the command line. Do the 4372 // same for the bin dir, output dir, and library directory. 4373 // 4374 Cptr = GetSymbolValue (BUILD_DIR); 4375 if (Cptr == NULL) { 4376 Cptr = _getcwd (NULL, 0); 4377 FreeCwd = 1; 4378 AddSymbol (BUILD_DIR, Cptr, SYM_OVERWRITE | SYM_GLOBAL | SYM_FILEPATH); 4379 } else { 4380 ReplaceSlash (Cptr); 4381 FreeCwd = 0; 4382 } 4383 4384 if (FreeCwd) { 4385 free (Cptr); 4386 } 4387 4388 // 4389 // Default build target is all 4390 // 4391 if (gGlobals.BuildTarget == 0) { 4392 gGlobals.BuildTarget = BUILD_TARGET_ALL; 4393 } 4394 4395 return 0; 4396 } 4397 4398 /***************************************************************************** 4399 ******************************************************************************/ 4400 static 4401 SYMBOL * 4402 FreeSymbols ( 4403 SYMBOL *Syms 4404 ) 4405 { 4406 SYMBOL *Next; 4407 while (Syms) { 4408 4409 if (Syms->Name != NULL) { 4410 free (Syms->Name); 4411 } 4412 4413 if (Syms->Value != NULL) { 4414 free (Syms->Value); 4415 } 4416 4417 Next = Syms->Next; 4418 free (Syms); 4419 Syms = Next; 4420 } 4421 4422 return Syms; 4423 } 4424 4425 /***************************************************************************** 4426 ******************************************************************************/ 4427 static 4428 int 4429 GetSourceFileType ( 4430 INT8 *FileName 4431 ) 4432 { 4433 INT8 *Cptr; 4434 int len; 4435 int i; 4436 4437 len = strlen (FileName); 4438 if (len == 0) { 4439 return FILETYPE_UNKNOWN; 4440 4441 } 4442 4443 Cptr = FileName + len - 1; 4444 while ((*Cptr != '.') && (Cptr >= FileName)) { 4445 Cptr--; 4446 4447 } 4448 4449 if (*Cptr == '.') { 4450 4451 for (i = 0; mFileTypes[i].Extension != NULL; i++) { 4452 len = strlen (mFileTypes[i].Extension); 4453 if (_strnicmp (mFileTypes[i].Extension, Cptr, len) == 0) { 4454 if ((*(Cptr + len) == 0) || isspace (*(Cptr + len))) { 4455 return mFileTypes[i].FileType; 4456 } 4457 } 4458 } 4459 } 4460 4461 return FILETYPE_UNKNOWN; 4462 } 4463 // 4464 // Determine if a given file is a standard include file. If we don't know, 4465 // then assume it's not. 4466 // 4467 static 4468 int 4469 IsIncludeFile ( 4470 INT8 *FileName 4471 ) 4472 { 4473 INT8 *Cptr; 4474 int len; 4475 int i; 4476 4477 len = strlen (FileName); 4478 if (len == 0) { 4479 return 0; 4480 } 4481 4482 Cptr = FileName + len - 1; 4483 while ((*Cptr != '.') && (Cptr >= FileName)) { 4484 Cptr--; 4485 } 4486 4487 if (*Cptr == '.') { 4488 // 4489 // Now go through the list of filename extensions and try to find 4490 // a match for this file extension. 4491 // 4492 for (i = 0; mFileTypes[i].Extension != NULL; i++) { 4493 len = strlen (mFileTypes[i].Extension); 4494 if (_strnicmp (mFileTypes[i].Extension, Cptr, len) == 0) { 4495 // 4496 // Make sure that's all there is to the filename extension. 4497 // 4498 if ((*(Cptr + len) == 0) || isspace (*(Cptr + len))) { 4499 return mFileTypes[i].FileFlags & FILE_FLAG_INCLUDE; 4500 } 4501 } 4502 } 4503 } 4504 4505 return 0; 4506 } 4507 4508 /***************************************************************************** 4509 ******************************************************************************/ 4510 static 4511 void 4512 StripTrailingSpaces ( 4513 INT8 *Str 4514 ) 4515 { 4516 INT8 *Cptr; 4517 Cptr = Str + strlen (Str) - 1; 4518 while (Cptr > Str) { 4519 if (isspace (*Cptr)) { 4520 *Cptr = 0; 4521 Cptr--; 4522 } else { 4523 break; 4524 } 4525 } 4526 } 4527 4528 /***************************************************************************** 4529 ******************************************************************************/ 4530 static 4531 int 4532 GetEfiSource ( 4533 VOID 4534 ) 4535 { 4536 INT8 *EfiSource; 4537 4538 // 4539 // Don't set it if the user specified it on the command line. 4540 // 4541 EfiSource = GetSymbolValue (EFI_SOURCE); 4542 if ( EfiSource != NULL) { 4543 ReplaceSlash (EfiSource); 4544 if (EfiSource[strlen (EfiSource) - 1] == '\\') { 4545 EfiSource[strlen (EfiSource) - 1] = 0; 4546 } 4547 return STATUS_SUCCESS; 4548 } 4549 4550 // 4551 // Get the environmental variable setting of EFI_SOURCE. 4552 // 4553 EfiSource = getenv (EFI_SOURCE); 4554 if (EfiSource != NULL) { 4555 ReplaceSlash (EfiSource); 4556 if (EfiSource[strlen (EfiSource) - 1] == '\\') { 4557 EfiSource[strlen (EfiSource) - 1] = 0; 4558 } 4559 AddSymbol (EFI_SOURCE, EfiSource, SYM_GLOBAL | SYM_FILEPATH); 4560 return STATUS_SUCCESS; 4561 } 4562 4563 Error (NULL, 0, 0, NULL, "could not determine EFI_SOURCE"); 4564 return STATUS_ERROR; 4565 } 4566 4567 void 4568 Message ( 4569 UINT32 PrintMask, 4570 INT8 *Fmt, 4571 ... 4572 ) 4573 { 4574 INT8 Line[MAX_LINE_LEN]; 4575 va_list List; 4576 4577 va_start (List, Fmt); 4578 vsprintf (Line, Fmt, List); 4579 if (PrintMask & gGlobals.Verbose) { 4580 fprintf (stdout, "%s\n", Line); 4581 } 4582 4583 va_end (List); 4584 } 4585 4586 static 4587 void 4588 Usage ( 4589 VOID 4590 ) 4591 { 4592 int Index; 4593 const char *Str[] = { 4594 UTILITY_NAME" "UTILITY_VERSION" - Intel Process DSC File Utility", 4595 " Copyright (C), 2004 - 2008 Intel Corporation", 4596 4597 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) ) 4598 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR, 4599 #endif 4600 "", 4601 "Usage:", 4602 " "UTILITY_NAME" [OPTION]... DSCFILE", 4603 "Options:", 4604 " -d var=value to define symbol 'var' to 'value'", 4605 " -v for verbose mode", 4606 " -g filename to preparse GUID listing file", 4607 " -x filename to create a cross-reference file", 4608 " -n threadnumber to build with multi-thread", 4609 " -t target to build the specified target:", 4610 " all, libraries or components", 4611 NULL 4612 }; 4613 for (Index = 0; Str[Index] != NULL; Index++) { 4614 fprintf (stdout, "%s\n", Str[Index]); 4615 } 4616 } 4617 4618 /*++ 4619 4620 Routine Description: 4621 4622 Process the [defines] section in the DSC file. 4623 4624 Arguments: 4625 4626 DscFile - pointer to the DSCFile class that contains the relevant info. 4627 4628 Returns: 4629 4630 0 if not necessarily an absolute path 4631 1 otherwise 4632 4633 --*/ 4634 static 4635 int 4636 ProcessDSCDefinesSection ( 4637 DSC_FILE *DscFile 4638 ) 4639 { 4640 INT8 Line[MAX_LINE_LEN]; 4641 INT8 Line2[MAX_EXP_LINE_LEN]; 4642 INT8 *Cptr; 4643 SECTION *Sect; 4644 4645 // 4646 // Look for a [defines] section and process it 4647 // 4648 Sect = DSCFileFindSection (DscFile, DEFINES_SECTION_NAME); 4649 if (Sect == NULL) { 4650 return STATUS_ERROR; 4651 } 4652 // 4653 // Read lines while they're valid 4654 // 4655 while (DSCFileGetLine (DscFile, Line, sizeof (Line)) != NULL) { 4656 // 4657 // Expand symbols on the line 4658 // 4659 if (ExpandSymbols (Line, Line2, sizeof (Line2), 0)) { 4660 return STATUS_ERROR; 4661 } 4662 // 4663 // Strip the line 4664 // 4665 Cptr = StripLine (Line2); 4666 if (*Cptr) { 4667 // 4668 // Make the assignment 4669 // 4670 AddSymbol (Line2, NULL, SYM_OVERWRITE | SYM_GLOBAL); 4671 } 4672 } 4673 4674 return STATUS_SUCCESS; 4675 } 4676 4677 int 4678 IsAbsolutePath ( 4679 char *FileName 4680 ) 4681 /*++ 4682 4683 Routine Description: 4684 4685 Determine if a given filename contains the full path information. 4686 4687 Arguments: 4688 4689 FileName - the name of the file, with symbol expanded. 4690 4691 Returns: 4692 4693 0 if not necessarily an absolute path 4694 1 otherwise 4695 4696 --*/ 4697 { 4698 // 4699 // If the first character is a-z, and the second character is a colon, then 4700 // it is an absolute path. 4701 // 4702 if (isalpha (FileName[0]) && (FileName[1] == ':')) { 4703 return 1; 4704 } 4705 4706 return 0; 4707 } 4708 4709 SMART_FILE * 4710 SmartOpen ( 4711 char *FileName 4712 ) 4713 { 4714 SMART_FILE *SmartFile; 4715 FILE *Fptr; 4716 int FileSize; 4717 4718 SmartFile = malloc (sizeof (SMART_FILE)); 4719 if (SmartFile == NULL) { 4720 return NULL; 4721 } 4722 memset (SmartFile, 0, sizeof (SMART_FILE)); 4723 4724 SmartFile->FileName = malloc (strlen (FileName) + 1); 4725 if (SmartFile->FileName == NULL){ 4726 SmartFree (SmartFile); 4727 return NULL; 4728 } 4729 strcpy (SmartFile->FileName, FileName); 4730 4731 if ((Fptr = fopen (FileName, "r")) != NULL) { 4732 fseek (Fptr, 0, SEEK_END); 4733 FileSize = ftell (Fptr); 4734 fseek (Fptr, 0, SEEK_SET); 4735 SmartFile->FileContent = malloc (FileSize + 1); 4736 if (SmartFile->FileContent != NULL) { 4737 memset (SmartFile->FileContent, 0, FileSize + 1); 4738 // 4739 // Usually FileLength < FileSize, because in text mode, carriage return-linefeed 4740 // combinations are translated into single linefeeds on input 4741 // 4742 SmartFile->FileLength = fread (SmartFile->FileContent, sizeof(char), FileSize, Fptr); 4743 } 4744 fclose (Fptr); 4745 } 4746 4747 // 4748 // No previous output file content, re-create the file 4749 // 4750 if (SmartFile->FileContent == NULL) { 4751 if ((SmartFile->FilePtr = fopen (FileName, "w")) == NULL) { 4752 SmartFree (SmartFile); 4753 return NULL; 4754 } 4755 } 4756 4757 return SmartFile; 4758 } 4759 4760 int 4761 SmartWrite ( 4762 SMART_FILE *SmartFile, 4763 char *String 4764 ) 4765 { 4766 int StrLen; 4767 4768 if (SmartFile->FilePtr != NULL) { 4769 return fprintf (SmartFile->FilePtr, "%s", String); 4770 } else { 4771 StrLen = strlen (String); 4772 if ((StrLen > SmartFile->FileLength - SmartFile->FilePosition) || 4773 (_strnicmp (&SmartFile->FileContent[SmartFile->FilePosition], String, StrLen) != 0)) { 4774 // 4775 // file changed, need to re-create. 4776 // 4777 if ((SmartFile->FilePtr = fopen (SmartFile->FileName, "w")) == NULL) { 4778 Error (NULL, 0, 0, SmartFile->FileName, "could not open file for writing when SmartWrite"); 4779 return -1; 4780 } else { 4781 SmartFile->FileContent[SmartFile->FilePosition] = 0; 4782 fprintf (SmartFile->FilePtr, "%s%s", SmartFile->FileContent, String); 4783 return StrLen; 4784 } 4785 } else { 4786 SmartFile->FilePosition += StrLen; 4787 return StrLen; 4788 } 4789 } 4790 } 4791 4792 void 4793 SmartClose ( 4794 SMART_FILE *SmartFile 4795 ) 4796 { 4797 if ((SmartFile->FilePtr == NULL) && (SmartFile->FilePosition < SmartFile->FileLength)) { 4798 // 4799 // The new file is smaller than before, re-create it. 4800 // 4801 if ((SmartFile->FilePtr = fopen (SmartFile->FileName, "w")) == NULL) { 4802 Error (NULL, 0, 0, SmartFile->FileName, "could not open file for writing when SmartClose"); 4803 } else { 4804 SmartFile->FileContent[SmartFile->FilePosition] = 0; 4805 fprintf (SmartFile->FilePtr, "%s", SmartFile->FileContent); 4806 } 4807 } 4808 4809 SmartFree(SmartFile); 4810 } 4811 4812 static 4813 void 4814 SmartFree ( 4815 SMART_FILE *SmartFile 4816 ) 4817 { 4818 if (SmartFile == NULL) { 4819 return; 4820 } 4821 4822 if (SmartFile->FileName != NULL ) { 4823 free (SmartFile->FileName); 4824 } 4825 4826 if (SmartFile->FileContent != NULL ) { 4827 free (SmartFile->FileContent); 4828 } 4829 4830 if (SmartFile->FilePtr != NULL ) { 4831 fclose (SmartFile->FilePtr); 4832 } 4833 4834 free (SmartFile); 4835 4836 return; 4837 } 4838 4839 static 4840 int 4841 AddModuleName ( 4842 SYMBOL **SymbolList, 4843 INT8 *ModuleName, 4844 INT8 *InfName 4845 ) 4846 /*++ 4847 4848 Routine Description: 4849 4850 Add module name in the global module list. 4851 For the same module names, it is only added once. 4852 4853 Arguments: 4854 SymbolList : add name into this list 4855 ModuleName : point to one module name char string. 4856 InfName : point to this module inf file name with path. 4857 4858 Returns: 4859 4860 0 : Successfully add input name into the global list. 4861 other value : allocate memory failed. 4862 4863 --*/ 4864 { 4865 SYMBOL *CurrentSymbol; 4866 SYMBOL *LastSymbol; 4867 4868 // 4869 // Get the global module list. 4870 // 4871 CurrentSymbol = *SymbolList; 4872 LastSymbol = *SymbolList; 4873 4874 // 4875 // Search whether this module name has been added into the global list. 4876 // 4877 while (CurrentSymbol != NULL) { 4878 if (_stricmp (CurrentSymbol->Name, ModuleName) == 0) { 4879 if ((CurrentSymbol->Value == NULL) && (InfName == NULL)) { 4880 break; 4881 } else if ((CurrentSymbol->Value != NULL) && (InfName != NULL) && \ 4882 (_stricmp (CurrentSymbol->Value, InfName) == 0)) { 4883 break; 4884 } 4885 } 4886 LastSymbol = CurrentSymbol; 4887 CurrentSymbol = CurrentSymbol->Next; 4888 } 4889 4890 // 4891 // Add new module name in list. 4892 // 4893 if (CurrentSymbol == NULL) { 4894 CurrentSymbol = (SYMBOL *) malloc (sizeof (SYMBOL)); 4895 if (CurrentSymbol == NULL) { 4896 Error (NULL, 0, 0, NULL, "failed to allocate memory"); 4897 return -1; 4898 } 4899 memset ((INT8 *) CurrentSymbol, 0, sizeof (SYMBOL)); 4900 4901 if (ModuleName != NULL) { 4902 CurrentSymbol->Name = (INT8 *) malloc (strlen (ModuleName) + 1); 4903 strcpy (CurrentSymbol->Name, ModuleName); 4904 } 4905 4906 if (InfName != NULL) { 4907 CurrentSymbol->Value = (INT8 *) malloc (strlen (InfName) + 1); 4908 strcpy (CurrentSymbol->Value, InfName); 4909 } 4910 4911 if (LastSymbol == NULL) { 4912 *SymbolList = CurrentSymbol; 4913 } else { 4914 LastSymbol->Next = CurrentSymbol; 4915 } 4916 } 4917 4918 return 0; 4919 } 4920 4921 4922 static 4923 void 4924 ReplaceSlash ( 4925 INT8 *Path 4926 ) 4927 /*++ 4928 4929 Routine Description: 4930 4931 Replace '/' with '\\' 4932 4933 Returns: 4934 4935 --*/ 4936 { 4937 while (*Path) { 4938 if (*Path == '/') { 4939 *Path = '\\'; 4940 } 4941 Path++; 4942 } 4943 } 4944