72889955b5c9304b48291e5c2821c603fb35660f
[people/mcb30/basetools.git] / Source / C / GenFv / GenFv.c
1 /** @file\r
2 \r
3 Copyright (c) 2007 - 2008, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   GenFv.c\r
15 \r
16 Abstract:\r
17 \r
18   This contains all code necessary to build the GenFvImage.exe utility.       \r
19   This utility relies heavily on the GenFvImage Lib.  Definitions for both\r
20   can be found in the Tiano Firmware Volume Generation Utility \r
21   Specification, review draft.\r
22 \r
23 **/\r
24 \r
25 //\r
26 // File included in build\r
27 //\r
28 #include <stdio.h>\r
29 #include <string.h>\r
30 #include <stdlib.h>\r
31 #include "GenFvInternalLib.h"\r
32 \r
33 //\r
34 // Utility Name\r
35 //\r
36 #define UTILITY_NAME  "GenFv"\r
37 \r
38 //\r
39 // Utility version information\r
40 //\r
41 #define UTILITY_MAJOR_VERSION 0\r
42 #define UTILITY_MINOR_VERSION 1\r
43 \r
44 STATIC\r
45 VOID \r
46 Version (\r
47   VOID\r
48 )\r
49 /*++\r
50 \r
51 Routine Description:\r
52 \r
53   Displays the standard utility information to SDTOUT\r
54 \r
55 Arguments:\r
56 \r
57   None\r
58 \r
59 Returns:\r
60 \r
61   None\r
62 \r
63 --*/\r
64 {\r
65   fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
66 }\r
67 \r
68 STATIC\r
69 VOID \r
70 Usage (\r
71   VOID\r
72   )\r
73 /*++\r
74 \r
75 Routine Description:\r
76 \r
77   Displays the utility usage syntax to STDOUT\r
78 \r
79 Arguments:\r
80 \r
81   None\r
82 \r
83 Returns:\r
84 \r
85   None\r
86 \r
87 --*/\r
88 {\r
89   //\r
90   // Summary usage\r
91   //\r
92   fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME);\r
93   \r
94   //\r
95   // Copyright declaration\r
96   // \r
97   fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
98 \r
99   //\r
100   // Details Option\r
101   //\r
102   fprintf (stdout, "Options:\n");\r
103   fprintf (stdout, "  -o FileName, --outputfile FileName\n\\r
104                         File is the FvImage or CapImage to be created.\n");\r
105   fprintf (stdout, "  -i FileName, --inputfile FileName\n\\r
106                         File is the input FV.inf or Cap.inf to specify\n\\r
107                         how to construct FvImage or CapImage.\n");\r
108   fprintf (stdout, "  -r Address, --baseaddr Address\n\\r
109                         Address is the rebase start address for drivers that\n\\r
110                         run in Flash. It supports DEC or HEX digital format.\n");\r
111   fprintf (stdout, "  -a AddressFile, --addrfile AddressFile\n\\r
112                         AddressFile is one file used to record boot driver base\n\\r
113                         address and runtime driver base address. And this tool\n\\r
114                         will update these two addresses after it relocates all\n\\r
115                         boot drivers and runtime drivers in this fv iamge to\n\\r
116                         the preferred loaded memory address.\n");\r
117   fprintf (stdout, "  -m logfile, --map logfile\n\\r
118                         Logfile is the output fv map file name. if it is not\n\\r
119                         given, the FvName.map will be the default map file name\n"); \r
120   fprintf (stdout, "  -c, --capsule         Create Capsule Image.\n");\r
121   fprintf (stdout, "  -p, --dump            Dump Capsule Image header.\n");\r
122   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");\r
123   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");\r
124   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");\r
125   fprintf (stdout, "  --version             Show program's version number and exit.\n");\r
126   fprintf (stdout, "  -h, --help            Show this help message and exit.\n");\r
127 }\r
128 \r
129 int\r
130 main (\r
131   IN INTN   argc,\r
132   IN CHAR8  **argv\r
133   )\r
134 /*++\r
135 \r
136 Routine Description:\r
137 \r
138   This utility uses GenFvImage.Lib to build a firmware volume image.\r
139 \r
140 Arguments:\r
141 \r
142   FvInfFileName      The name of an FV image description file or Capsule Image.\r
143 \r
144   Arguments come in pair in any order.\r
145     -I FvInfFileName \r
146 \r
147 Returns:\r
148 \r
149   EFI_SUCCESS            No error conditions detected.\r
150   EFI_INVALID_PARAMETER  One or more of the input parameters is invalid.\r
151   EFI_OUT_OF_RESOURCES   A resource required by the utility was unavailable.  \r
152                          Most commonly this will be memory allocation \r
153                          or file creation.\r
154   EFI_LOAD_ERROR         GenFvImage.lib could not be loaded.\r
155   EFI_ABORTED            Error executing the GenFvImage lib.\r
156 \r
157 --*/\r
158 {\r
159   EFI_STATUS            Status;\r
160   CHAR8                 *InfFileName;\r
161   CHAR8                 *AddrFileName;\r
162   CHAR8                 *MapFileName;\r
163   CHAR8                 *InfFileImage;\r
164   UINTN                 InfFileSize;\r
165   CHAR8                 *OutFileName;\r
166   CHAR8                 ValueString[_MAX_PATH];\r
167   EFI_PHYSICAL_ADDRESS  XipBase;\r
168   EFI_PHYSICAL_ADDRESS  BtBase;\r
169   EFI_PHYSICAL_ADDRESS  RtBase;\r
170   BOOLEAN               CapsuleFlag;\r
171   BOOLEAN               DumpCapsule;\r
172   MEMORY_FILE           AddrMemoryFile;\r
173   FILE                  *FpFile;\r
174   EFI_CAPSULE_HEADER    *CapsuleHeader;\r
175   UINT64                LogLevel;\r
176 \r
177   InfFileName   = NULL;\r
178   AddrFileName  = NULL;\r
179   InfFileImage  = NULL;\r
180   OutFileName   = NULL;\r
181   MapFileName   = NULL;\r
182   XipBase       = 0;\r
183   BtBase        = 0;\r
184   RtBase        = 0;\r
185   InfFileSize   = 0;\r
186   CapsuleFlag   = FALSE;\r
187   DumpCapsule   = FALSE;\r
188   FpFile        = NULL;\r
189   CapsuleHeader = NULL;\r
190   LogLevel      = 0;\r
191 \r
192   SetUtilityName (UTILITY_NAME);\r
193 \r
194   if (argc == 1) {\r
195     Error (NULL, 0, 1001, "Missing options", "No input options specified.");\r
196     Usage ();\r
197     return STATUS_ERROR;\r
198   }\r
199 \r
200   //\r
201   // Parse command line\r
202   //\r
203   argc --;\r
204   argv ++;\r
205 \r
206   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
207     Version ();\r
208     Usage ();\r
209     return STATUS_SUCCESS;    \r
210   }\r
211 \r
212   if (stricmp (argv[0], "--version") == 0) {\r
213     Version ();\r
214     return STATUS_SUCCESS;    \r
215   }\r
216 \r
217   while (argc > 0) {\r
218     if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--inputfile") == 0)) {\r
219       InfFileName = argv[1];\r
220       if (InfFileName == NULL) {\r
221         Error (NULL, 0, 1003, "Invalid option value", "Input file can't be null");\r
222         return STATUS_ERROR;\r
223       }\r
224       argc -= 2;\r
225       argv += 2;\r
226       continue; \r
227     }\r
228 \r
229     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--addrfile") == 0)) {\r
230       AddrFileName = argv[1];\r
231       if (AddrFileName == NULL) {\r
232         Error (NULL, 0, 1003, "Invalid option value", "Address file can't be null");\r
233         return STATUS_ERROR;\r
234       }\r
235       argc -= 2;\r
236       argv += 2;\r
237       continue; \r
238     }\r
239 \r
240     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
241       OutFileName = argv[1];\r
242       if (OutFileName == NULL) {\r
243         Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null");\r
244         return STATUS_ERROR;\r
245       }\r
246       argc -= 2;\r
247       argv += 2;\r
248       continue; \r
249     }\r
250 \r
251     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) {\r
252       Status = AsciiStringToUint64 (argv[1], FALSE, &XipBase);\r
253       if (EFI_ERROR (Status)) {\r
254         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
255         return STATUS_ERROR;        \r
256       }\r
257       argc -= 2;\r
258       argv += 2;\r
259       continue; \r
260     }\r
261 \r
262     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--capsule") == 0)) {\r
263       CapsuleFlag = TRUE;\r
264       argc --;\r
265       argv ++;\r
266       continue; \r
267     }\r
268 \r
269     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
270       DumpCapsule = TRUE;\r
271       argc --;\r
272       argv ++;\r
273       continue; \r
274     }\r
275 \r
276     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--map") == 0)) {\r
277       MapFileName = argv[1];\r
278       if (MapFileName == NULL) {\r
279         Error (NULL, 0, 1003, "Invalid option value", "Map file can't be null");\r
280         return STATUS_ERROR;\r
281       }\r
282       argc -= 2;\r
283       argv += 2;\r
284       continue; \r
285     }\r
286 \r
287     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
288       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
289       VerboseMsg ("Verbose output Mode Set!");\r
290       argc --;\r
291       argv ++;\r
292       continue;\r
293     }\r
294 \r
295     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
296       SetPrintLevel (KEY_LOG_LEVEL);\r
297       KeyMsg ("Quiet output Mode Set!");\r
298       argc --;\r
299       argv ++;\r
300       continue;\r
301     }\r
302 \r
303     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
304       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
305       if (EFI_ERROR (Status)) {\r
306         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
307         return STATUS_ERROR;\r
308       }\r
309       if (LogLevel > 9) {\r
310         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", LogLevel);\r
311         return STATUS_ERROR;\r
312       }\r
313       SetPrintLevel (LogLevel);\r
314       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
315       argc -= 2;\r
316       argv += 2;\r
317       continue;\r
318     }\r
319 \r
320     //\r
321     // Don't recognize the parameter.\r
322     //\r
323     Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]);\r
324     return STATUS_ERROR;\r
325   }\r
326 \r
327   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
328   \r
329   //\r
330   // check input parameter\r
331   //\r
332   if (InfFileName == NULL) {\r
333     Error (NULL, 0, 1001, "Missing option", "Input File");\r
334     return STATUS_ERROR;\r
335   }\r
336   VerboseMsg ("the input file name is %s", InfFileName);\r
337 \r
338   if (!DumpCapsule && OutFileName == NULL) {\r
339     Error (NULL, 0, 1001, "Missing option", "Output File");\r
340     return STATUS_ERROR;\r
341   }\r
342   if (OutFileName != NULL) {\r
343     VerboseMsg ("the output file name is %s", OutFileName);\r
344   }\r
345   \r
346   //\r
347   // Read boot and runtime address from address file\r
348   //\r
349   if (AddrFileName != NULL) {\r
350     VerboseMsg ("the input address file name is %s", AddrFileName);\r
351     Status = GetFileImage (AddrFileName, &InfFileImage, &InfFileSize);\r
352     if (EFI_ERROR (Status)) {\r
353       return STATUS_ERROR;\r
354     }\r
355 \r
356     AddrMemoryFile.FileImage           = InfFileImage;\r
357     AddrMemoryFile.CurrentFilePointer  = InfFileImage;\r
358     AddrMemoryFile.Eof                 = InfFileImage + InfFileSize;\r
359 \r
360     //\r
361     // Read the boot driver base address for this FV image\r
362     //\r
363     Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, 0, ValueString);\r
364     if (Status == EFI_SUCCESS) {\r
365       //\r
366       // Get the base address\r
367       //\r
368       Status = AsciiStringToUint64 (ValueString, FALSE, &BtBase);\r
369       if (EFI_ERROR (Status)) {\r
370         Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
371         return STATUS_ERROR;\r
372       }\r
373       DebugMsg (NULL, 0, 9, "Boot driver base address", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
374     }\r
375   \r
376     //\r
377     // Read the FV runtime driver base address\r
378     //\r
379     Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, 0, ValueString);\r
380     if (Status == EFI_SUCCESS) {\r
381       //\r
382       // Get the base address\r
383       //\r
384       Status = AsciiStringToUint64 (ValueString, FALSE, &RtBase);\r
385       if (EFI_ERROR (Status)) {\r
386         Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
387         return STATUS_ERROR;\r
388       }\r
389       DebugMsg (NULL, 0, 9, "Runtime driver base address", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
390     }\r
391     \r
392     //\r
393     // free the allocated memory space for addr file.\r
394     //\r
395     free (InfFileImage);\r
396   }\r
397 \r
398   //\r
399   // Read the INF file image\r
400   //\r
401   Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize);\r
402   if (EFI_ERROR (Status)) {\r
403     return STATUS_ERROR;\r
404   }\r
405   \r
406   if (DumpCapsule) {\r
407     VerboseMsg ("Dump the capsule header information for the input capsule image %s", InfFileName);\r
408     //\r
409     // Dump Capsule Image Header Information\r
410     //\r
411     CapsuleHeader = (EFI_CAPSULE_HEADER *) InfFileImage;\r
412     if (OutFileName == NULL) {\r
413       FpFile = stdout;\r
414     } else {\r
415       FpFile = fopen (OutFileName, "w");\r
416       if (FpFile == NULL) {\r
417         Error (NULL, 0, 0001, "Error opening file", OutFileName);\r
418         return STATUS_ERROR;\r
419       }\r
420     }\r
421     fprintf (FpFile, "Capsule %s Image Header Information\n", InfFileName);\r
422     fprintf (FpFile, "  GUID                  %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", \r
423                     CapsuleHeader->CapsuleGuid.Data1,\r
424                     (UINT32) CapsuleHeader->CapsuleGuid.Data2,\r
425                     (UINT32) CapsuleHeader->CapsuleGuid.Data3,\r
426                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[0],\r
427                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[1],\r
428                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[2],\r
429                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[3],\r
430                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[4],\r
431                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[5],\r
432                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[6],\r
433                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[7]);\r
434     fprintf (FpFile, "  Header size           0x%08X\n", CapsuleHeader->HeaderSize);\r
435     fprintf (FpFile, "  Flags                 0x%08X\n", CapsuleHeader->Flags);\r
436     fprintf (FpFile, "  Capsule image size    0x%08X\n", CapsuleHeader->CapsuleImageSize);\r
437     fclose (FpFile);\r
438   } else if (CapsuleFlag) {\r
439     VerboseMsg ("Create capsule image");\r
440     //\r
441     // Call the GenerateCapImage to generate Capsule Image\r
442     //\r
443     GenerateCapImage (\r
444       InfFileImage, \r
445       InfFileSize,\r
446       OutFileName\r
447       );\r
448   } else {\r
449     VerboseMsg ("Create Fv image and its map file");\r
450     if (XipBase != 0) {\r
451       VerboseMsg ("FvImage Rebase Address is 0x%X", XipBase);\r
452     }\r
453     //\r
454     // Call the GenerateFvImage to generate Fv Image\r
455     //\r
456     GenerateFvImage (\r
457       InfFileImage,\r
458       InfFileSize,\r
459       OutFileName,\r
460       MapFileName,\r
461       XipBase,\r
462       &BtBase,\r
463       &RtBase\r
464       );\r
465   }\r
466 \r
467   //\r
468   // free InfFileImage memory\r
469   //\r
470   if (InfFileImage != NULL) {\r
471     free (InfFileImage);\r
472   }\r
473   \r
474   //\r
475   //  update boot driver address and runtime driver address in address file\r
476   //\r
477   if (AddrFileName != NULL) {\r
478     FpFile = fopen (AddrFileName, "w");\r
479     if (FpFile == NULL) {\r
480       Error (NULL, 0, 0001, "Error opening file", AddrFileName);\r
481       return STATUS_ERROR;\r
482     }\r
483     fprintf (FpFile, OPTIONS_SECTION_STRING);\r
484     fprintf (FpFile, "\n");\r
485     if (BtBase != 0) {\r
486       fprintf (FpFile, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING);\r
487       fprintf (FpFile, " = 0x%x\n", BtBase);\r
488       DebugMsg (NULL, 0, 9, "Updated boot driver base address", "%s = 0x%x", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, BtBase);\r
489     }\r
490     if (RtBase != 0) {\r
491       fprintf (FpFile, EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING);\r
492       fprintf (FpFile, " = 0x%x\n", RtBase);\r
493       DebugMsg (NULL, 0, 9, "Updated runtime driver base address", "%s = 0x%x", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, RtBase);\r
494     }\r
495     fclose (FpFile);\r
496   }\r
497 \r
498   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
499 \r
500   return GetUtilityStatus ();\r
501 }\r