Fixed case in error type
[people/mcb30/basetools.git] / Source / C / GenFv / GenFv.c
1 /*++\r
2 \r
3 Copyright (c) 2007, 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       argc -= 2;\r
221       argv += 2;\r
222       continue; \r
223     }\r
224 \r
225     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--addrfile") == 0)) {\r
226       AddrFileName = argv[1];\r
227       argc -= 2;\r
228       argv += 2;\r
229       continue; \r
230     }\r
231 \r
232     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
233       OutFileName = argv[1];\r
234       argc -= 2;\r
235       argv += 2;\r
236       continue; \r
237     }\r
238 \r
239     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) {\r
240       Status = AsciiStringToUint64 (argv[1], FALSE, &XipBase);\r
241       if (EFI_ERROR (Status)) {\r
242         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
243         return STATUS_ERROR;        \r
244       }\r
245       argc -= 2;\r
246       argv += 2;\r
247       continue; \r
248     }\r
249 \r
250     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--capsule") == 0)) {\r
251       CapsuleFlag = TRUE;\r
252       argc --;\r
253       argv ++;\r
254       continue; \r
255     }\r
256 \r
257     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
258       DumpCapsule = TRUE;\r
259       argc --;\r
260       argv ++;\r
261       continue; \r
262     }\r
263 \r
264     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--map") == 0)) {\r
265       MapFileName = argv[1];\r
266       argc -= 2;\r
267       argv += 2;\r
268       continue; \r
269     }\r
270 \r
271     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
272       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
273       VerboseMsg ("Verbose output Mode Set!");\r
274       argc --;\r
275       argv ++;\r
276       continue;\r
277     }\r
278 \r
279     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
280       SetPrintLevel (KEY_LOG_LEVEL);\r
281       KeyMsg ("Quiet output Mode Set!");\r
282       argc --;\r
283       argv ++;\r
284       continue;\r
285     }\r
286 \r
287     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
288       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
289       if (EFI_ERROR (Status)) {\r
290         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
291         return STATUS_ERROR;\r
292       }\r
293       if (LogLevel > 9) {\r
294         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", LogLevel);\r
295         return STATUS_ERROR;\r
296       }\r
297       SetPrintLevel (LogLevel);\r
298       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
299       argc -= 2;\r
300       argv += 2;\r
301       continue;\r
302     }\r
303 \r
304     //\r
305     // Don't recognize the parameter.\r
306     //\r
307     Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]);\r
308     return STATUS_ERROR;\r
309   }\r
310 \r
311   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
312   \r
313   //\r
314   // check input parameter\r
315   //\r
316   if (InfFileName == NULL) {\r
317     Error (NULL, 0, 1001, "Missing option", "Input File");\r
318     return STATUS_ERROR;\r
319   }\r
320   VerboseMsg ("the input file name is %s", InfFileName);\r
321 \r
322   if (!DumpCapsule && OutFileName == NULL) {\r
323     Error (NULL, 0, 1001, "Missing option", "Output File");\r
324     return STATUS_ERROR;\r
325   }\r
326   if (OutFileName != NULL) {\r
327     VerboseMsg ("the output file name is %s", OutFileName);\r
328   }\r
329   \r
330   //\r
331   // Read boot and runtime address from address file\r
332   //\r
333   if (AddrFileName != NULL) {\r
334     VerboseMsg ("the input address file name is %s", AddrFileName);\r
335     Status = GetFileImage (AddrFileName, &InfFileImage, &InfFileSize);\r
336     if (EFI_ERROR (Status)) {\r
337       return STATUS_ERROR;\r
338     }\r
339 \r
340     AddrMemoryFile.FileImage           = InfFileImage;\r
341     AddrMemoryFile.CurrentFilePointer  = InfFileImage;\r
342     AddrMemoryFile.Eof                 = InfFileImage + InfFileSize;\r
343 \r
344     //\r
345     // Read the boot driver base address for this FV image\r
346     //\r
347     Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, 0, ValueString);\r
348     if (Status == EFI_SUCCESS) {\r
349       //\r
350       // Get the base address\r
351       //\r
352       Status = AsciiStringToUint64 (ValueString, FALSE, &BtBase);\r
353       if (EFI_ERROR (Status)) {\r
354         Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
355         return STATUS_ERROR;\r
356       }\r
357       DebugMsg (NULL, 0, 9, "Boot driver base address", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
358     }\r
359   \r
360     //\r
361     // Read the FV runtime driver base address\r
362     //\r
363     Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_RUNTIME_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, &RtBase);\r
369       if (EFI_ERROR (Status)) {\r
370         Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
371         return STATUS_ERROR;\r
372       }\r
373       DebugMsg (NULL, 0, 9, "Runtime driver base address", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
374     }\r
375     \r
376     //\r
377     // free the allocated memory space for addr file.\r
378     //\r
379     free (InfFileImage);\r
380   }\r
381 \r
382   //\r
383   // Read the INF file image\r
384   //\r
385   Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize);\r
386   if (EFI_ERROR (Status)) {\r
387     return STATUS_ERROR;\r
388   }\r
389   \r
390   if (DumpCapsule) {\r
391     VerboseMsg ("Dump the capsule header information for the input capsule image %s", InfFileName);\r
392     //\r
393     // Dump Capsule Image Header Information\r
394     //\r
395     CapsuleHeader = (EFI_CAPSULE_HEADER *) InfFileImage;\r
396     if (OutFileName == NULL) {\r
397       FpFile = stdout;\r
398     } else {\r
399       FpFile = fopen (OutFileName, "w");\r
400       if (FpFile == NULL) {\r
401         Error (NULL, 0, 0001, "Error opening file", OutFileName);\r
402         return STATUS_ERROR;\r
403       }\r
404     }\r
405     fprintf (FpFile, "Capsule %s Image Header Information\n", InfFileName);\r
406     fprintf (FpFile, "  GUID                  %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", \r
407                     CapsuleHeader->CapsuleGuid.Data1,\r
408                     (UINT32) CapsuleHeader->CapsuleGuid.Data2,\r
409                     (UINT32) CapsuleHeader->CapsuleGuid.Data3,\r
410                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[0],\r
411                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[1],\r
412                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[2],\r
413                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[3],\r
414                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[4],\r
415                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[5],\r
416                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[6],\r
417                     (UINT32) CapsuleHeader->CapsuleGuid.Data4[7]);\r
418     fprintf (FpFile, "  Header size           0x%08X\n", CapsuleHeader->HeaderSize);\r
419     fprintf (FpFile, "  Flags                 0x%08X\n", CapsuleHeader->Flags);\r
420     fprintf (FpFile, "  Capsule image size    0x%08X\n", CapsuleHeader->CapsuleImageSize);\r
421     fclose (FpFile);\r
422   } else if (CapsuleFlag) {\r
423     VerboseMsg ("Create capsule image");\r
424     //\r
425     // Call the GenerateCapImage to generate Capsule Image\r
426     //\r
427     GenerateCapImage (\r
428       InfFileImage, \r
429       InfFileSize,\r
430       OutFileName\r
431       );\r
432   } else {\r
433     VerboseMsg ("Create Fv image and its map file");\r
434     if (XipBase != 0) {\r
435       VerboseMsg ("FvImage Rebase Address is 0x%X", XipBase);\r
436     }\r
437     //\r
438     // Call the GenerateFvImage to generate Fv Image\r
439     //\r
440     GenerateFvImage (\r
441       InfFileImage,\r
442       InfFileSize,\r
443       OutFileName,\r
444       MapFileName,\r
445       XipBase,\r
446       &BtBase,\r
447       &RtBase\r
448       );\r
449   }\r
450 \r
451   //\r
452   // free InfFileImage memory\r
453   //\r
454   if (InfFileImage != NULL) {\r
455     free (InfFileImage);\r
456   }\r
457   \r
458   //\r
459   //  update boot driver address and runtime driver address in address file\r
460   //\r
461   if (AddrFileName != NULL) {\r
462     FpFile = fopen (AddrFileName, "w");\r
463     if (FpFile == NULL) {\r
464       Error (NULL, 0, 0001, "Error opening file", AddrFileName);\r
465       return STATUS_ERROR;\r
466     }\r
467     fprintf (FpFile, OPTIONS_SECTION_STRING);\r
468     fprintf (FpFile, "\n");\r
469     if (BtBase != 0) {\r
470       fprintf (FpFile, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING);\r
471       fprintf (FpFile, " = 0x%x\n", BtBase);\r
472       DebugMsg (NULL, 0, 9, "Updated boot driver base address", "%s = 0x%x", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, BtBase);\r
473     }\r
474     if (RtBase != 0) {\r
475       fprintf (FpFile, EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING);\r
476       fprintf (FpFile, " = 0x%x\n", RtBase);\r
477       DebugMsg (NULL, 0, 9, "Updated runtime driver base address", "%s = 0x%x", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, RtBase);\r
478     }\r
479     fclose (FpFile);\r
480   }\r
481 \r
482   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
483 \r
484   return GetUtilityStatus ();\r
485 }\r