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