1 /*++ 2 3 Copyright (c) 2006 - 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 13 Module Name: 14 15 GenAprioriFile.c 16 17 Abstract: 18 19 Given an input file containing a list of GUIDs (or Guided file names), 20 convert the file to an Apriori file consumable by the dispatcher. 21 22 --*/ 23 24 #include <stdio.h> 25 #include <string.h> 26 #include <ctype.h> 27 28 #include "EfiCommon.h" 29 #include "ParseInf.h" 30 #include "CommonLib.h" // for compare guid 31 #include "EfiUtilityMsgs.h" 32 33 #define MAX_LINE_LEN 200 34 #define MAX_PATH 200 35 36 // 37 // typedef unsigned int STATUS; 38 // #define STATUS_SUCCESS 0 39 // #define STATUS_WARNING 1 40 // #define STATUS_ERROR 2 41 // 42 #define UTILITY_NAME "GenAprioriFile" 43 #define UTILITY_VERSION "v1.0" 44 // 45 // Here's all our globals. 46 // 47 static struct { 48 FILE *BinFptr; // output dependencies to this file 49 INT8 *AprioriFileName; 50 INT8 *OutputFileName; 51 BOOLEAN Intelligent; 52 BOOLEAN Verbose; 53 BOOLEAN NullTerminate; 54 } mGlobals; 55 56 static 57 STATUS 58 ProcessArgs ( 59 int Argc, 60 char *Argv[] 61 ); 62 63 static 64 BOOLEAN 65 IsCommentLine ( 66 INT8 *Line 67 ); 68 69 static 70 void 71 Usage ( 72 VOID 73 ); 74 75 int 76 main ( 77 int Argc, 78 char *Argv[] 79 ) 80 /*++ 81 82 Routine Description: 83 84 Call the routine to parse the command-line options, then process the 85 Apriori list file and generate the GUID file. 86 87 Arguments: 88 89 Standard C main() argc and argv. 90 91 Returns: 92 93 0 if successful 94 nonzero otherwise 95 96 --*/ 97 // GC_TODO: Argc - add argument and description to function comment 98 // GC_TODO: ] - add argument and description to function comment 99 { 100 STATUS Status; 101 FILE *AprioriFptr; 102 FILE *BinFptr; 103 INT8 Line[MAX_LINE_LEN]; 104 EFI_GUID Guid; 105 EFI_GUID GuidIn; 106 EFI_GUID ZeroGuid; 107 UINT32 LineCounter; 108 // 109 // Initialize the error printing routines 110 // 111 SetUtilityName (UTILITY_NAME); 112 // 113 // Clear our globals 114 // 115 memset ((char *) &mGlobals, 0, sizeof (mGlobals)); 116 memset ((char *) &ZeroGuid, 0, sizeof (ZeroGuid)); 117 AprioriFptr = NULL; 118 BinFptr = NULL; 119 120 // 121 // Process the command-line arguments 122 // 123 Status = ProcessArgs (Argc, Argv); 124 if (Status != STATUS_SUCCESS) { 125 return Status; 126 } 127 // 128 // If arguments were ok, then open the Apriori file and process it. 129 // 130 if ((AprioriFptr = fopen (mGlobals.AprioriFileName, "r")) == NULL) { 131 Error (NULL, 0, 0, mGlobals.AprioriFileName, "failed to open file for reading"); 132 goto FinishUp; 133 } 134 // 135 // If -i intelligent option specified, then attempt to read and 136 // existing output file and see if we'd be creating an identical file. 137 // 138 if (mGlobals.Intelligent) { 139 if ((BinFptr = fopen (mGlobals.OutputFileName, "rb")) == NULL) { 140 if (mGlobals.Verbose) { 141 DebugMsg (NULL, 0, 0, "Creating new apriori file -- no existing file", NULL); 142 } 143 144 goto CreateFile; 145 } 146 // 147 // Read lines from the input file until done. Convert each to a guid, then 148 // read a guid from the input file and compare them. 149 // 150 while (fgets (Line, sizeof (Line), AprioriFptr) != NULL) { 151 152 if (IsCommentLine (Line)) { 153 continue; 154 } 155 // 156 // Convert to a guid 157 // 158 if (StringToGuid (Line, &Guid) != EFI_SUCCESS) { 159 if (mGlobals.Verbose) { 160 DebugMsg (NULL, 0, 0, "failed to read GUID from input text file -- creating new file", NULL); 161 } 162 163 goto CreateFile; 164 } 165 // 166 // Read guid from input file, then compare 167 // 168 if (fread (&GuidIn, sizeof (GuidIn), 1, BinFptr) != 1) { 169 if (mGlobals.Verbose) { 170 DebugMsg (NULL, 0, 0, "failed to read GUID from input binary file -- creating new file", NULL); 171 } 172 173 goto CreateFile; 174 } 175 176 if (CompareGuid (&Guid, &GuidIn) != 0) { 177 if (mGlobals.Verbose) { 178 DebugMsg (NULL, 0, 0, "GUID comparison failed -- creating new file", NULL); 179 } 180 181 goto CreateFile; 182 } 183 } 184 // 185 // May be one more NULL guid in the binary file 186 // 187 if (mGlobals.NullTerminate) { 188 if (fread (&GuidIn, sizeof (GuidIn), 1, BinFptr) != 1) { 189 if (mGlobals.Verbose) { 190 DebugMsg (NULL, 0, 0, "failed to read NULL GUID from input binary file -- creating new file", NULL); 191 } 192 193 goto CreateFile; 194 } 195 196 if (CompareGuid (&GuidIn, &ZeroGuid) != 0) { 197 if (mGlobals.Verbose) { 198 DebugMsg (NULL, 0, 0, "NULL GUID comparison failed -- creating new file", NULL); 199 } 200 201 goto CreateFile; 202 } 203 } 204 // 205 // Make sure we're at the end of both files. 206 // 207 if ((fgets (Line, sizeof (Line), AprioriFptr) != NULL) || (fread (&GuidIn, 1, 1, BinFptr) != 0)) { 208 if (mGlobals.Verbose) { 209 DebugMsg (NULL, 0, 0, "file sizes different, -i test failed -- creating new file", NULL); 210 } 211 212 goto CreateFile; 213 } 214 215 if (mGlobals.Verbose) { 216 DebugMsg (NULL, 0, 0, "existing file would be unchanged -- keeping existing apriori file", NULL); 217 } 218 219 goto FinishUp; 220 } 221 222 CreateFile: 223 // 224 // Rewind the Apriori file in case -i was specified. Also 225 // try to close the output file for the case where we prescanned 226 // it (again, because of -i). 227 // 228 rewind (AprioriFptr); 229 if (BinFptr != NULL) { 230 fclose (BinFptr); 231 } 232 // 233 // Open the output file 234 // 235 if ((BinFptr = fopen (mGlobals.OutputFileName, "wb")) == NULL) { 236 Error (NULL, 0, 0, mGlobals.OutputFileName, "could not open input file"); 237 goto FinishUp; 238 } 239 // 240 // Read lines until we're done 241 // 242 LineCounter = 0; 243 while (fgets (Line, sizeof (Line), AprioriFptr) != NULL) { 244 LineCounter++; 245 if (IsCommentLine (Line)) { 246 continue; 247 } 248 // 249 // Convert to a GUID 250 // 251 if (StringToGuid (Line, &Guid) != EFI_SUCCESS) { 252 Error (mGlobals.AprioriFileName, LineCounter, 0, "failed to convert GUID", NULL); 253 goto FinishUp; 254 } 255 // 256 // Write the guid to the output file 257 // 258 if (fwrite (&Guid, sizeof (Guid), 1, BinFptr) != 1) { 259 Error (NULL, 0, 0, mGlobals.OutputFileName, "failed to write GUID to output file"); 260 goto FinishUp; 261 } 262 } 263 // 264 // Write a null guid out to terminate the list 265 // 266 if (mGlobals.NullTerminate) { 267 memset ((void *) &Guid, 0, sizeof (Guid)); 268 if (fwrite (&Guid, sizeof (Guid), 1, BinFptr) != 1) { 269 Error (NULL, 0, 0, mGlobals.OutputFileName, "failed to write NULL termination GUID to output file"); 270 } 271 } 272 273 FinishUp: 274 275 if (AprioriFptr != NULL) { 276 fclose (AprioriFptr); 277 } 278 279 if (BinFptr != NULL) { 280 fclose (BinFptr); 281 } 282 283 return GetUtilityStatus (); 284 } 285 286 static 287 BOOLEAN 288 IsCommentLine ( 289 INT8 *Line 290 ) 291 /*++ 292 293 Routine Description: 294 295 GC_TODO: Add function description 296 297 Arguments: 298 299 Line - GC_TODO: add argument description 300 301 Returns: 302 303 GC_TODO: add return values 304 305 --*/ 306 { 307 for (; isspace (*Line) && *Line; Line++) 308 ; 309 310 // 311 // Allow # or // comments 312 // 313 if ((*Line == '#') || ((*Line == '/') && (*(Line + 1) == '/')) || (*Line == '\n') || (*Line == 0)) { 314 return TRUE; 315 } 316 317 return FALSE; 318 } 319 // 320 // Process the command-line arguments 321 // 322 static 323 STATUS 324 ProcessArgs ( 325 int Argc, 326 char *Argv[] 327 ) 328 /*++ 329 330 Routine Description: 331 332 GC_TODO: Add function description 333 334 Arguments: 335 336 Argc - GC_TODO: add argument description 337 ] - GC_TODO: add argument description 338 339 Returns: 340 341 GC_TODO: add return values 342 343 --*/ 344 { 345 // 346 // Skip program name 347 // 348 Argc--; 349 Argv++; 350 351 // 352 // Process until no more args 353 // 354 while (Argc) { 355 // 356 // -f AprioriFile 357 // 358 if (_stricmp (Argv[0], "-f") == 0) { 359 // 360 // check for one more arg 361 // 362 if (Argc > 1) { 363 mGlobals.AprioriFileName = Argv[1]; 364 } else { 365 Error (NULL, 0, 0, NULL, "missing filename with %s", Argv[0]); 366 Usage (); 367 return STATUS_ERROR; 368 } 369 370 Argc--; 371 Argv++; 372 } else if (_stricmp (Argv[0], "-i") == 0) { 373 // 374 // intelligent creation of output file. That is to say, if 375 // there's already a file there, and it's the same as what 376 // we'd create, then don't re-create. This is to support 377 // incremental builds (that is to say, running nmake a second time 378 // does nothing). 379 // 380 mGlobals.Intelligent = TRUE; 381 } else if (_stricmp (Argv[0], "-v") == 0) { 382 mGlobals.Verbose = TRUE; 383 } else if (_stricmp (Argv[0], "-null") == 0) { 384 mGlobals.NullTerminate = TRUE; 385 } else if (_stricmp (Argv[0], "-o") == 0) { 386 // 387 // -o OutputFileName 388 // check for one more arg 389 // 390 if (Argc > 1) { 391 mGlobals.OutputFileName = Argv[1]; 392 } else { 393 Error (NULL, 0, 0, NULL, "missing filename argument with %s", Argv[0]); 394 Usage (); 395 return STATUS_ERROR; 396 } 397 398 Argc--; 399 Argv++; 400 } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) { 401 Usage (); 402 return STATUS_ERROR; 403 } else { 404 Error (NULL, 0, 0, Argv[0], "unrecognized option"); 405 Usage (); 406 return STATUS_ERROR; 407 } 408 409 Argc--; 410 Argv++; 411 } 412 // 413 // Had to specify the apriori input file and output file names 414 // 415 if (mGlobals.AprioriFileName == NULL) { 416 Error (NULL, 0, 0, "must specify -f AprioriFile", NULL); 417 Usage (); 418 return STATUS_ERROR; 419 } 420 421 if (mGlobals.OutputFileName == NULL) { 422 Error (NULL, 0, 0, "must specify -o OutputFile", NULL); 423 Usage (); 424 return STATUS_ERROR; 425 } 426 427 return STATUS_SUCCESS; 428 } 429 430 static 431 void 432 Usage ( 433 VOID 434 ) 435 /*++ 436 437 Routine Description: 438 439 Print usage information for this utility. 440 441 Arguments: 442 443 None. 444 445 Returns: 446 447 Nothing. 448 449 --*/ 450 { 451 int Index; 452 const char *Str[] = { 453 UTILITY_NAME" "UTILITY_VERSION" - Intel Generate Apriori File Utility", 454 " Copyright (C), 2006 - 2008 Intel Corporation", 455 456 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) ) 457 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR, 458 #endif 459 "", 460 "Usage:", 461 " "UTILITY_NAME" [OPTION]...", 462 "Description:", 463 " Generate an Apriori file consumable by the DXE or PEI dispatcher.", 464 "Options:", 465 " -h or -? for this help information", 466 " -f AprioriFile parse the GUID'ed files in AprioriFile (required)", 467 " -o OutputFile write output to OutputFile (required)", 468 " -i for intelligent re-creation of OutputFile", 469 " -null to terminate the output file with a NULL GUID", 470 " -v verbose option", 471 NULL 472 }; 473 for (Index = 0; Str[Index] != NULL; Index++) { 474 fprintf (stdout, "%s\n", Str[Index]); 475 } 476 } 477