3 Copyright (c) 2004-2005 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
18 Utility for flash management in the Intel Platform Innovation Framework
19 for EFI build environment.
34 #include "EfiUtilityMsgs.h"
35 #include "Microcode.h"
36 #include "FlashDefFile.h"
39 #define UTILITY_NAME "FlashMap"
41 typedef struct _STRING_LIST
{
42 struct _STRING_LIST
*Next
;
47 // Keep our globals in one of these structures
50 char *CIncludeFileName
;
52 char *FlashDeviceImage
;
55 char *ImageOutFileName
;
57 char *AsmIncludeFileName
;
58 char *FlashDefinitionFileName
;
59 char *StringReplaceInFileName
;
60 char *StringReplaceOutFileName
;
61 char *DiscoverFDImageName
;
62 char MicrocodePadByteValue
;
63 unsigned int MicrocodeAlignment
;
64 STRING_LIST
*MCIFileNames
;
65 STRING_LIST
*LastMCIFileNames
;
66 unsigned int BaseAddress
;
69 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
70 #define DEFAULT_MC_ALIGNMENT 16
83 STRING_LIST
*FileNames
,
84 unsigned int Alignment
,
102 Parse the command line arguments and then call worker functions to do the work
105 argc - number of elements in argv
106 argv - array of command-line arguments
109 STATUS_SUCCESS - no problems encountered while processing
110 STATUS_WARNING - warnings, but no errors, were encountered while processing
111 STATUS_ERROR - errors were encountered while processing
117 SetUtilityName (UTILITY_NAME
);
118 Status
= ProcessCommandLine (argc
, argv
);
119 if (Status
!= STATUS_SUCCESS
) {
123 // Check for discovery of an FD (command line option)
125 if (mGlobals
.DiscoverFDImageName
!= NULL
) {
126 Status
= FDDiscover (mGlobals
.DiscoverFDImageName
, mGlobals
.BaseAddress
);
130 // If they're doing microcode file parsing, then do that
132 if (mGlobals
.MCIFileName
!= NULL
) {
133 MicrocodeConstructor ();
134 MicrocodeParseFile (mGlobals
.MCIFileName
, mGlobals
.MCOFileName
);
135 MicrocodeDestructor ();
138 // If they're doing microcode file merging, then do that now
140 if (mGlobals
.MCIFileNames
!= NULL
) {
141 MergeMicrocodeFiles (
142 mGlobals
.MCOFileName
,
143 mGlobals
.MCIFileNames
,
144 mGlobals
.MicrocodeAlignment
,
145 mGlobals
.MicrocodePadByteValue
149 // If using a flash definition file, then process that and return
151 if (mGlobals
.FlashDefinitionFileName
!= NULL
) {
153 SymbolsConstructor ();
154 Status
= FDFParseFile (mGlobals
.FlashDefinitionFileName
);
155 if (GetUtilityStatus () != STATUS_ERROR
) {
157 // If they want us to do a string-replace on a file, then add the symbol definitions to
158 // the symbol table, and then do the string replace.
160 if (mGlobals
.StringReplaceInFileName
!= NULL
) {
161 Status
= FDFCreateSymbols (mGlobals
.FlashDevice
);
162 Status
= SymbolsFileStringsReplace (mGlobals
.StringReplaceInFileName
, mGlobals
.StringReplaceOutFileName
);
165 // If they want us to create a .h defines file or .c flashmap data file, then do so now
167 if (mGlobals
.CIncludeFileName
!= NULL
) {
168 Status
= FDFCreateCIncludeFile (mGlobals
.FlashDevice
, mGlobals
.CIncludeFileName
);
170 if (mGlobals
.AsmIncludeFileName
!= NULL
) {
171 Status
= FDFCreateAsmIncludeFile (mGlobals
.FlashDevice
, mGlobals
.AsmIncludeFileName
);
174 // If they want us to create an image, do that now
176 if (mGlobals
.ImageOutFileName
!= NULL
) {
177 Status
= FDFCreateImage (mGlobals
.FlashDevice
, mGlobals
.FlashDeviceImage
, mGlobals
.ImageOutFileName
);
180 // If they want to create an output DSC file, do that now
182 if (mGlobals
.DscFileName
!= NULL
) {
183 Status
= FDFCreateDscFile (mGlobals
.FlashDevice
, mGlobals
.DscFileName
);
186 SymbolsDestructor ();
193 while (mGlobals
.MCIFileNames
!= NULL
) {
194 mGlobals
.LastMCIFileNames
= mGlobals
.MCIFileNames
->Next
;
195 _free (mGlobals
.MCIFileNames
);
196 mGlobals
.MCIFileNames
= mGlobals
.LastMCIFileNames
;
198 return GetUtilityStatus ();
203 MergeMicrocodeFiles (
205 STRING_LIST
*FileNames
,
206 unsigned int Alignment
,
213 Merge binary microcode files into a single file, taking into consideration
214 the alignment and pad value.
218 OutFileName - name of the output file to create
219 FileNames - linked list of input microcode files to merge
220 Alignment - alignment for each microcode file in the output image
221 PadByteValue - value to use when padding to meet alignment requirements
225 STATUS_SUCCESS - merge completed successfully or with acceptable warnings
226 STATUS_ERROR - merge failed, output file not created
238 // Open the output file
240 if ((OutFptr
= fopen (OutFileName
, "wb")) == NULL
) {
241 Error (NULL
, 0, 0, OutFileName
, "failed to open output file for writing");
245 // Walk the list of files
247 Status
= STATUS_ERROR
;
251 while (FileNames
!= NULL
) {
253 // Open the file, determine the size, then read it in and write
256 if ((InFptr
= fopen (FileNames
->Str
, "rb")) == NULL
) {
257 Error (NULL
, 0, 0, FileNames
->Str
, "failed to open input file for reading");
260 fseek (InFptr
, 0, SEEK_END
);
261 FileSize
= ftell (InFptr
);
262 fseek (InFptr
, 0, SEEK_SET
);
264 Buffer
= (char *) _malloc (FileSize
);
265 if (Buffer
== NULL
) {
266 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
269 if (fread (Buffer
, FileSize
, 1, InFptr
) != 1) {
270 Error (NULL
, 0, 0, FileNames
->Str
, "failed to read file contents");
276 if (Alignment
!= 0) {
277 while ((TotalFileSize
% Alignment
) != 0) {
278 if (fwrite (&PadByteValue
, 1, 1, OutFptr
) != 1) {
279 Error (NULL
, 0, 0, OutFileName
, "failed to write pad bytes to output file");
285 TotalFileSize
+= FileSize
;
286 if (fwrite (Buffer
, FileSize
, 1, OutFptr
) != 1) {
287 Error (NULL
, 0, 0, OutFileName
, "failed to write to output file");
293 Warning (NULL
, 0, 0, FileNames
->Str
, "0-size file encountered");
297 FileNames
= FileNames
->Next
;
299 Status
= STATUS_SUCCESS
;
302 if (InFptr
!= NULL
) {
305 if (Buffer
!= NULL
) {
308 if (Status
== STATUS_ERROR
) {
309 remove (OutFileName
);
323 Process the command line arguments
326 argc - Standard C entry point arguments
327 argv[] - Standard C entry point arguments
330 STATUS_SUCCESS - no problems encountered while processing
331 STATUS_WARNING - warnings, but no errors, were encountered while processing
332 STATUS_ERROR - errors were encountered while processing
340 // Skip program name arg, process others
349 // Clear out our globals, then start walking the arguments
351 memset ((void *) &mGlobals
, 0, sizeof (mGlobals
));
352 mGlobals
.MicrocodePadByteValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
353 mGlobals
.MicrocodeAlignment
= DEFAULT_MC_ALIGNMENT
;
356 if (strcmp (argv
[0], "-?") == 0) {
359 } else if (strcmp (argv
[0], "-hfile") == 0) {
363 // Used to specify an output C #include file to create that contains
364 // #define statements for all the flashmap region offsets and sizes.
365 // Check for additional argument.
368 Error (NULL
, 0, 0, argv
[0], "option requires an output file name");
373 mGlobals
.CIncludeFileName
= argv
[0];
375 } else if (strcmp (argv
[0], "-flashdevice") == 0) {
377 // -flashdevice FLASH_DEVICE_NAME
379 // Used to select which flash device definition to operate on.
380 // Check for additional argument
383 Error (NULL
, 0, 0, argv
[0], "option requires a flash device name to use");
388 mGlobals
.FlashDevice
= argv
[0];
389 } else if (strcmp (argv
[0], "-mco") == 0) {
393 // Used to specify a microcode output binary file to create.
394 // Check for additional argument.
397 Error (NULL
, 0, 0, (INT8
*) argv
[0], (INT8
*) "option requires an output microcode file name to create");
402 mGlobals
.MCOFileName
= argv
[0];
404 } else if (strcmp (argv
[0], "-asmincfile") == 0) {
406 // -asmincfile FileName
408 // Used to specify the name of the output assembly include file that contains
409 // equates for the flash region addresses and sizes.
410 // Check for additional argument.
413 Error (NULL
, 0, 0, argv
[0], "option requires an output ASM include file name to create");
418 mGlobals
.AsmIncludeFileName
= argv
[0];
420 } else if (strcmp (argv
[0], "-mci") == 0) {
424 // Used to specify an input microcode text file to parse.
425 // Check for additional argument
428 Error (NULL
, 0, 0, (INT8
*) argv
[0], (INT8
*) "option requires an input microcode text file name to parse");
433 mGlobals
.MCIFileName
= argv
[0];
434 } else if (strcmp (argv
[0], "-flashdeviceimage") == 0) {
436 // -flashdeviceimage FlashDeviceImage
438 // Used to specify which flash device image definition from the input flash definition file
440 // Check for additional argument.
443 Error (NULL
, 0, 0, argv
[0], "option requires the name of a flash definition image to use");
448 mGlobals
.FlashDeviceImage
= argv
[0];
449 } else if (strcmp (argv
[0], "-imageout") == 0) {
451 // -imageout FileName
453 // Used to specify the name of the output FD image file to create.
454 // Check for additional argument.
457 Error (NULL
, 0, 0, argv
[0], "option requires an output image filename to create");
462 mGlobals
.ImageOutFileName
= argv
[0];
464 } else if (strcmp (argv
[0], "-dsc") == 0) {
468 // Used to specify the name of the output DSC file to create.
469 // Check for additional argument.
472 Error (NULL
, 0, 0, argv
[0], "option requires an output DSC filename to create");
477 mGlobals
.DscFileName
= argv
[0];
479 } else if (strcmp (argv
[0], "-fdf") == 0) {
483 // Used to specify the name of the input flash definition file.
484 // Check for additional argument.
487 Error (NULL
, 0, 0, argv
[0], "option requires an input flash definition file name");
492 mGlobals
.FlashDefinitionFileName
= argv
[0];
493 } else if (strcmp (argv
[0], "-discover") == 0) {
495 // -discover FDFileName
497 // Debug functionality used to scan an existing FD image, trying to find
498 // firmware volumes at 64K boundaries.
499 // Check for additional argument.
502 Error (NULL
, 0, 0, argv
[0], "option requires an input FD image file name");
507 mGlobals
.DiscoverFDImageName
= argv
[0];
509 } else if (strcmp (argv
[0], "-baseaddr") == 0) {
513 // Used to specify a base address when doing a discover of an FD image.
514 // Check for additional argument.
517 Error (NULL
, 0, 0, argv
[0], "option requires a base address");
522 if (tolower (argv
[0][1]) == 'x') {
523 sscanf (argv
[0] + 2, "%x", &mGlobals
.BaseAddress
);
525 sscanf (argv
[0], "%d", &mGlobals
.BaseAddress
);
527 } else if (strcmp (argv
[0], "-padvalue") == 0) {
531 // Used to specify the value to pad with when aligning data while
532 // creating an FD image. Check for additional argument.
535 Error (NULL
, 0, 0, argv
[0], "option requires a byte value");
540 if (tolower (argv
[0][1]) == 'x') {
541 sscanf (argv
[0] + 2, "%x", &Temp
);
542 mGlobals
.MicrocodePadByteValue
= (char) Temp
;
544 sscanf (argv
[0], "%d", &Temp
);
545 mGlobals
.MicrocodePadByteValue
= (char) Temp
;
547 } else if (strcmp (argv
[0], "-align") == 0) {
551 // Used to specify how each data file is aligned in the region
552 // when creating an FD image. Check for additional argument.
555 Error (NULL
, 0, 0, argv
[0], "option requires an alignment");
560 if (tolower (argv
[0][1]) == 'x') {
561 sscanf (argv
[0] + 2, "%x", &mGlobals
.MicrocodeAlignment
);
563 sscanf (argv
[0], "%d", &mGlobals
.MicrocodeAlignment
);
565 } else if (strcmp (argv
[0], "-mcmerge") == 0) {
567 // -mcmerge FileName(s)
569 // Used to concatenate multiple microde binary files. Can specify
570 // multiple file names with the one -mcmerge flag. Check for additional argument.
572 if ((argc
< 2) || (argv
[1][0] == '-')) {
573 Error (NULL
, 0, 0, argv
[0], "option requires one or more input file names");
577 // Take input files until another option or end of list
580 while ((argc
> 1) && (argv
[1][0] != '-')) {
581 Str
= (STRING_LIST
*) _malloc (sizeof (STRING_LIST
));
583 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
586 memset (Str
, 0, sizeof (STRING_LIST
));
588 if (mGlobals
.MCIFileNames
== NULL
) {
589 mGlobals
.MCIFileNames
= Str
;
591 mGlobals
.LastMCIFileNames
->Next
= Str
;
593 mGlobals
.LastMCIFileNames
= Str
;
597 } else if (strcmp (argv
[0], "-strsub") == 0) {
599 // -strsub SrcFile DestFile
601 // Used to perform string substitutions on a file, writing the result to a new
602 // file. Check for two additional arguments.
605 Error (NULL
, 0, 0, argv
[0], "option requires input and output file names for string substitution");
610 mGlobals
.StringReplaceInFileName
= argv
[0];
613 mGlobals
.StringReplaceOutFileName
= argv
[0];
616 Error (NULL
, 0, 0, argv
[0], "invalid option");
623 // If no outputs requested, then report an error
625 if (ThingsToDo
== 0) {
626 Error (NULL
, 0, 0, "nothing to do", NULL
);
630 // If they want an asm file, #include file, or C file to be created, then they have to specify a
631 // flash device name and flash definition file name.
633 if ((mGlobals
.CIncludeFileName
!= NULL
) &&
634 ((mGlobals
.FlashDevice
== NULL
) || (mGlobals
.FlashDefinitionFileName
== NULL
))) {
635 Error (NULL
, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL
);
638 if ((mGlobals
.AsmIncludeFileName
!= NULL
) &&
639 ((mGlobals
.FlashDevice
== NULL
) || (mGlobals
.FlashDefinitionFileName
== NULL
))) {
640 Error (NULL
, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL
);
644 // If they want a dsc file to be created, then they have to specify a
645 // flash device name and a flash definition file name
647 if (mGlobals
.DscFileName
!= NULL
) {
648 if (mGlobals
.FlashDevice
== NULL
) {
649 Error (NULL
, 0, 0, "must specify -flashdevice with -dsc", NULL
);
652 if (mGlobals
.FlashDefinitionFileName
== NULL
) {
653 Error (NULL
, 0, 0, "must specify -fdf with -dsc", NULL
);
658 // If they specified an output microcode file name, then they have to specify an input
659 // file name, and vice versa.
661 if ((mGlobals
.MCIFileName
!= NULL
) && (mGlobals
.MCOFileName
== NULL
)) {
662 Error (NULL
, 0, 0, "must specify output microcode file name", NULL
);
665 if ((mGlobals
.MCOFileName
!= NULL
) && (mGlobals
.MCIFileName
== NULL
) && (mGlobals
.MCIFileNames
== NULL
)) {
666 Error (NULL
, 0, 0, "must specify input microcode file name", NULL
);
670 // If doing merge, then have to specify output file name
672 if ((mGlobals
.MCIFileNames
!= NULL
) && (mGlobals
.MCOFileName
== NULL
)) {
673 Error (NULL
, 0, 0, "must specify output microcode file name", NULL
);
677 // If they want an output image to be created, then they have to specify
678 // the flash device and the flash device image to use.
680 if (mGlobals
.ImageOutFileName
!= NULL
) {
681 if (mGlobals
.FlashDevice
== NULL
) {
682 Error (NULL
, 0, 0, "must specify -flashdevice with -imageout", NULL
);
685 if (mGlobals
.FlashDeviceImage
== NULL
) {
686 Error (NULL
, 0, 0, "must specify -flashdeviceimage with -imageout", NULL
);
689 if (mGlobals
.FlashDefinitionFileName
== NULL
) {
690 Error (NULL
, 0, 0, "must specify -c or -fdf with -imageout", NULL
);
694 return STATUS_SUCCESS
;
705 Print utility command line help
717 "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",
718 " -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",
719 " -discover FDImage -dsc DscFile -asmincfile AsmIncFile",
720 " -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",
721 " -baseaddr BaseAddr -align Alignment -padvalue PadValue",
722 " -mcmerge MCIFile(s)",
724 " FlashDefFile - input Flash Definition File",
725 " FlashDevice - flash device to use (from flash definition file)",
726 " FlashDeviceImage - flash device image to use (from flash definition file)",
727 " MCIFile - input microcode file to parse",
728 " MCOFile - output binary microcode image to create from MCIFile",
729 " HFile - output #include file to create",
730 " FDImage - name of input FDImage file to scan",
731 " ImageOutFile - output image file to create",
732 " DscFile - output DSC file to create",
733 " AsmIncFile - output ASM include file to create",
734 " InStrFile - input file to replace symbol names, writing result to OutStrFile",
735 " BaseAddr - base address of FDImage (used with -discover)",
736 " Alignment - alignment to use when merging microcode binaries",
737 " PadValue - byte value to use as pad value when aligning microcode binaries",
738 " MCIFile(s) - one or more microcode binary files to merge/concatenate",
742 for (i
= 0; Msg
[i
] != NULL
; i
++) {
743 fprintf (stdout
, "%s\n", Msg
[i
]);