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.
28 #include <Common/UefiBaseTypes.h>
30 #include "EfiUtilityMsgs.h"
31 #include "Microcode.h"
32 #include "FlashDefFile.h"
35 #define UTILITY_NAME "FlashMap"
37 typedef struct _STRING_LIST
{
38 struct _STRING_LIST
*Next
;
43 // Keep our globals in one of these structures
46 char *CIncludeFileName
;
48 char *FlashDeviceImage
;
51 char *ImageOutFileName
;
53 char *AsmIncludeFileName
;
54 char *FlashDefinitionFileName
;
55 char *StringReplaceInFileName
;
56 char *StringReplaceOutFileName
;
57 char *DiscoverFDImageName
;
58 char MicrocodePadByteValue
;
59 unsigned int MicrocodeAlignment
;
60 STRING_LIST
*MCIFileNames
;
61 STRING_LIST
*LastMCIFileNames
;
62 unsigned int BaseAddress
;
65 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
66 #define DEFAULT_MC_ALIGNMENT 16
79 STRING_LIST
*FileNames
,
80 unsigned int Alignment
,
98 Parse the command line arguments and then call worker functions to do the work
101 argc - number of elements in argv
102 argv - array of command-line arguments
105 STATUS_SUCCESS - no problems encountered while processing
106 STATUS_WARNING - warnings, but no errors, were encountered while processing
107 STATUS_ERROR - errors were encountered while processing
113 SetUtilityName (UTILITY_NAME
);
114 Status
= ProcessCommandLine (argc
, argv
);
115 if (Status
!= STATUS_SUCCESS
) {
119 // Check for discovery of an FD (command line option)
121 if (mGlobals
.DiscoverFDImageName
!= NULL
) {
122 Status
= FDDiscover (mGlobals
.DiscoverFDImageName
, mGlobals
.BaseAddress
);
126 // If they're doing microcode file parsing, then do that
128 if (mGlobals
.MCIFileName
!= NULL
) {
129 MicrocodeConstructor ();
130 MicrocodeParseFile (mGlobals
.MCIFileName
, mGlobals
.MCOFileName
);
131 MicrocodeDestructor ();
134 // If they're doing microcode file merging, then do that now
136 if (mGlobals
.MCIFileNames
!= NULL
) {
137 MergeMicrocodeFiles (
138 mGlobals
.MCOFileName
,
139 mGlobals
.MCIFileNames
,
140 mGlobals
.MicrocodeAlignment
,
141 mGlobals
.MicrocodePadByteValue
145 // If using a flash definition file, then process that and return
147 if (mGlobals
.FlashDefinitionFileName
!= NULL
) {
149 SymbolsConstructor ();
150 Status
= FDFParseFile (mGlobals
.FlashDefinitionFileName
);
151 if (GetUtilityStatus () != STATUS_ERROR
) {
153 // If they want us to do a string-replace on a file, then add the symbol definitions to
154 // the symbol table, and then do the string replace.
156 if (mGlobals
.StringReplaceInFileName
!= NULL
) {
157 Status
= FDFCreateSymbols (mGlobals
.FlashDevice
);
158 Status
= SymbolsFileStringsReplace (mGlobals
.StringReplaceInFileName
, mGlobals
.StringReplaceOutFileName
);
161 // If they want us to create a .h defines file or .c flashmap data file, then do so now
163 if (mGlobals
.CIncludeFileName
!= NULL
) {
164 Status
= FDFCreateCIncludeFile (mGlobals
.FlashDevice
, mGlobals
.CIncludeFileName
);
166 if (mGlobals
.AsmIncludeFileName
!= NULL
) {
167 Status
= FDFCreateAsmIncludeFile (mGlobals
.FlashDevice
, mGlobals
.AsmIncludeFileName
);
170 // If they want us to create an image, do that now
172 if (mGlobals
.ImageOutFileName
!= NULL
) {
173 Status
= FDFCreateImage (mGlobals
.FlashDevice
, mGlobals
.FlashDeviceImage
, mGlobals
.ImageOutFileName
);
176 // If they want to create an output DSC file, do that now
178 if (mGlobals
.DscFileName
!= NULL
) {
179 Status
= FDFCreateDscFile (mGlobals
.FlashDevice
, mGlobals
.DscFileName
);
182 SymbolsDestructor ();
189 while (mGlobals
.MCIFileNames
!= NULL
) {
190 mGlobals
.LastMCIFileNames
= mGlobals
.MCIFileNames
->Next
;
191 _free (mGlobals
.MCIFileNames
);
192 mGlobals
.MCIFileNames
= mGlobals
.LastMCIFileNames
;
194 return GetUtilityStatus ();
199 MergeMicrocodeFiles (
201 STRING_LIST
*FileNames
,
202 unsigned int Alignment
,
209 Merge binary microcode files into a single file, taking into consideration
210 the alignment and pad value.
214 OutFileName - name of the output file to create
215 FileNames - linked list of input microcode files to merge
216 Alignment - alignment for each microcode file in the output image
217 PadByteValue - value to use when padding to meet alignment requirements
221 STATUS_SUCCESS - merge completed successfully or with acceptable warnings
222 STATUS_ERROR - merge failed, output file not created
234 // Open the output file
236 if ((OutFptr
= fopen (OutFileName
, "wb")) == NULL
) {
237 Error (NULL
, 0, 0, OutFileName
, "failed to open output file for writing");
241 // Walk the list of files
243 Status
= STATUS_ERROR
;
247 while (FileNames
!= NULL
) {
249 // Open the file, determine the size, then read it in and write
252 if ((InFptr
= fopen (FileNames
->Str
, "rb")) == NULL
) {
253 Error (NULL
, 0, 0, FileNames
->Str
, "failed to open input file for reading");
256 fseek (InFptr
, 0, SEEK_END
);
257 FileSize
= ftell (InFptr
);
258 fseek (InFptr
, 0, SEEK_SET
);
260 Buffer
= (char *) _malloc (FileSize
);
261 if (Buffer
== NULL
) {
262 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
265 if (fread (Buffer
, FileSize
, 1, InFptr
) != 1) {
266 Error (NULL
, 0, 0, FileNames
->Str
, "failed to read file contents");
272 if (Alignment
!= 0) {
273 while ((TotalFileSize
% Alignment
) != 0) {
274 if (fwrite (&PadByteValue
, 1, 1, OutFptr
) != 1) {
275 Error (NULL
, 0, 0, OutFileName
, "failed to write pad bytes to output file");
281 TotalFileSize
+= FileSize
;
282 if (fwrite (Buffer
, FileSize
, 1, OutFptr
) != 1) {
283 Error (NULL
, 0, 0, OutFileName
, "failed to write to output file");
289 Warning (NULL
, 0, 0, FileNames
->Str
, "0-size file encountered");
293 FileNames
= FileNames
->Next
;
295 Status
= STATUS_SUCCESS
;
298 if (InFptr
!= NULL
) {
301 if (Buffer
!= NULL
) {
304 if (Status
== STATUS_ERROR
) {
305 remove (OutFileName
);
319 Process the command line arguments
322 argc - Standard C entry point arguments
323 argv[] - Standard C entry point arguments
326 STATUS_SUCCESS - no problems encountered while processing
327 STATUS_WARNING - warnings, but no errors, were encountered while processing
328 STATUS_ERROR - errors were encountered while processing
336 // Skip program name arg, process others
345 // Clear out our globals, then start walking the arguments
347 memset ((void *) &mGlobals
, 0, sizeof (mGlobals
));
348 mGlobals
.MicrocodePadByteValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
349 mGlobals
.MicrocodeAlignment
= DEFAULT_MC_ALIGNMENT
;
352 if (strcmp (argv
[0], "-?") == 0) {
355 } else if (strcmp (argv
[0], "-hfile") == 0) {
359 // Used to specify an output C #include file to create that contains
360 // #define statements for all the flashmap region offsets and sizes.
361 // Check for additional argument.
364 Error (NULL
, 0, 0, argv
[0], "option requires an output file name");
369 mGlobals
.CIncludeFileName
= argv
[0];
371 } else if (strcmp (argv
[0], "-flashdevice") == 0) {
373 // -flashdevice FLASH_DEVICE_NAME
375 // Used to select which flash device definition to operate on.
376 // Check for additional argument
379 Error (NULL
, 0, 0, argv
[0], "option requires a flash device name to use");
384 mGlobals
.FlashDevice
= argv
[0];
385 } else if (strcmp (argv
[0], "-mco") == 0) {
389 // Used to specify a microcode output binary file to create.
390 // Check for additional argument.
393 Error (NULL
, 0, 0, (INT8
*) argv
[0], (INT8
*) "option requires an output microcode file name to create");
398 mGlobals
.MCOFileName
= argv
[0];
400 } else if (strcmp (argv
[0], "-asmincfile") == 0) {
402 // -asmincfile FileName
404 // Used to specify the name of the output assembly include file that contains
405 // equates for the flash region addresses and sizes.
406 // Check for additional argument.
409 Error (NULL
, 0, 0, argv
[0], "option requires an output ASM include file name to create");
414 mGlobals
.AsmIncludeFileName
= argv
[0];
416 } else if (strcmp (argv
[0], "-mci") == 0) {
420 // Used to specify an input microcode text file to parse.
421 // Check for additional argument
424 Error (NULL
, 0, 0, (INT8
*) argv
[0], (INT8
*) "option requires an input microcode text file name to parse");
429 mGlobals
.MCIFileName
= argv
[0];
430 } else if (strcmp (argv
[0], "-flashdeviceimage") == 0) {
432 // -flashdeviceimage FlashDeviceImage
434 // Used to specify which flash device image definition from the input flash definition file
436 // Check for additional argument.
439 Error (NULL
, 0, 0, argv
[0], "option requires the name of a flash definition image to use");
444 mGlobals
.FlashDeviceImage
= argv
[0];
445 } else if (strcmp (argv
[0], "-imageout") == 0) {
447 // -imageout FileName
449 // Used to specify the name of the output FD image file to create.
450 // Check for additional argument.
453 Error (NULL
, 0, 0, argv
[0], "option requires an output image filename to create");
458 mGlobals
.ImageOutFileName
= argv
[0];
460 } else if (strcmp (argv
[0], "-dsc") == 0) {
464 // Used to specify the name of the output DSC file to create.
465 // Check for additional argument.
468 Error (NULL
, 0, 0, argv
[0], "option requires an output DSC filename to create");
473 mGlobals
.DscFileName
= argv
[0];
475 } else if (strcmp (argv
[0], "-fdf") == 0) {
479 // Used to specify the name of the input flash definition file.
480 // Check for additional argument.
483 Error (NULL
, 0, 0, argv
[0], "option requires an input flash definition file name");
488 mGlobals
.FlashDefinitionFileName
= argv
[0];
489 } else if (strcmp (argv
[0], "-discover") == 0) {
491 // -discover FDFileName
493 // Debug functionality used to scan an existing FD image, trying to find
494 // firmware volumes at 64K boundaries.
495 // Check for additional argument.
498 Error (NULL
, 0, 0, argv
[0], "option requires an input FD image file name");
503 mGlobals
.DiscoverFDImageName
= argv
[0];
505 } else if (strcmp (argv
[0], "-baseaddr") == 0) {
509 // Used to specify a base address when doing a discover of an FD image.
510 // Check for additional argument.
513 Error (NULL
, 0, 0, argv
[0], "option requires a base address");
518 if (tolower (argv
[0][1]) == 'x') {
519 sscanf (argv
[0] + 2, "%x", &mGlobals
.BaseAddress
);
521 sscanf (argv
[0], "%d", &mGlobals
.BaseAddress
);
523 } else if (strcmp (argv
[0], "-padvalue") == 0) {
527 // Used to specify the value to pad with when aligning data while
528 // creating an FD image. Check for additional argument.
531 Error (NULL
, 0, 0, argv
[0], "option requires a byte value");
536 if (tolower (argv
[0][1]) == 'x') {
537 sscanf (argv
[0] + 2, "%x", &Temp
);
538 mGlobals
.MicrocodePadByteValue
= (char) Temp
;
540 sscanf (argv
[0], "%d", &Temp
);
541 mGlobals
.MicrocodePadByteValue
= (char) Temp
;
543 } else if (strcmp (argv
[0], "-align") == 0) {
547 // Used to specify how each data file is aligned in the region
548 // when creating an FD image. Check for additional argument.
551 Error (NULL
, 0, 0, argv
[0], "option requires an alignment");
556 if (tolower (argv
[0][1]) == 'x') {
557 sscanf (argv
[0] + 2, "%x", &mGlobals
.MicrocodeAlignment
);
559 sscanf (argv
[0], "%d", &mGlobals
.MicrocodeAlignment
);
561 } else if (strcmp (argv
[0], "-mcmerge") == 0) {
563 // -mcmerge FileName(s)
565 // Used to concatenate multiple microde binary files. Can specify
566 // multiple file names with the one -mcmerge flag. Check for additional argument.
568 if ((argc
< 2) || (argv
[1][0] == '-')) {
569 Error (NULL
, 0, 0, argv
[0], "option requires one or more input file names");
573 // Take input files until another option or end of list
576 while ((argc
> 1) && (argv
[1][0] != '-')) {
577 Str
= (STRING_LIST
*) _malloc (sizeof (STRING_LIST
));
579 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
582 memset (Str
, 0, sizeof (STRING_LIST
));
584 if (mGlobals
.MCIFileNames
== NULL
) {
585 mGlobals
.MCIFileNames
= Str
;
587 mGlobals
.LastMCIFileNames
->Next
= Str
;
589 mGlobals
.LastMCIFileNames
= Str
;
593 } else if (strcmp (argv
[0], "-strsub") == 0) {
595 // -strsub SrcFile DestFile
597 // Used to perform string substitutions on a file, writing the result to a new
598 // file. Check for two additional arguments.
601 Error (NULL
, 0, 0, argv
[0], "option requires input and output file names for string substitution");
606 mGlobals
.StringReplaceInFileName
= argv
[0];
609 mGlobals
.StringReplaceOutFileName
= argv
[0];
612 Error (NULL
, 0, 0, argv
[0], "invalid option");
619 // If no outputs requested, then report an error
621 if (ThingsToDo
== 0) {
622 Error (NULL
, 0, 0, "nothing to do", NULL
);
626 // If they want an asm file, #include file, or C file to be created, then they have to specify a
627 // flash device name and flash definition file name.
629 if ((mGlobals
.CIncludeFileName
!= NULL
) &&
630 ((mGlobals
.FlashDevice
== NULL
) || (mGlobals
.FlashDefinitionFileName
== NULL
))) {
631 Error (NULL
, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL
);
634 if ((mGlobals
.AsmIncludeFileName
!= NULL
) &&
635 ((mGlobals
.FlashDevice
== NULL
) || (mGlobals
.FlashDefinitionFileName
== NULL
))) {
636 Error (NULL
, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL
);
640 // If they want a dsc file to be created, then they have to specify a
641 // flash device name and a flash definition file name
643 if (mGlobals
.DscFileName
!= NULL
) {
644 if (mGlobals
.FlashDevice
== NULL
) {
645 Error (NULL
, 0, 0, "must specify -flashdevice with -dsc", NULL
);
648 if (mGlobals
.FlashDefinitionFileName
== NULL
) {
649 Error (NULL
, 0, 0, "must specify -fdf with -dsc", NULL
);
654 // If they specified an output microcode file name, then they have to specify an input
655 // file name, and vice versa.
657 if ((mGlobals
.MCIFileName
!= NULL
) && (mGlobals
.MCOFileName
== NULL
)) {
658 Error (NULL
, 0, 0, "must specify output microcode file name", NULL
);
661 if ((mGlobals
.MCOFileName
!= NULL
) && (mGlobals
.MCIFileName
== NULL
) && (mGlobals
.MCIFileNames
== NULL
)) {
662 Error (NULL
, 0, 0, "must specify input microcode file name", NULL
);
666 // If doing merge, then have to specify output file name
668 if ((mGlobals
.MCIFileNames
!= NULL
) && (mGlobals
.MCOFileName
== NULL
)) {
669 Error (NULL
, 0, 0, "must specify output microcode file name", NULL
);
673 // If they want an output image to be created, then they have to specify
674 // the flash device and the flash device image to use.
676 if (mGlobals
.ImageOutFileName
!= NULL
) {
677 if (mGlobals
.FlashDevice
== NULL
) {
678 Error (NULL
, 0, 0, "must specify -flashdevice with -imageout", NULL
);
681 if (mGlobals
.FlashDeviceImage
== NULL
) {
682 Error (NULL
, 0, 0, "must specify -flashdeviceimage with -imageout", NULL
);
685 if (mGlobals
.FlashDefinitionFileName
== NULL
) {
686 Error (NULL
, 0, 0, "must specify -c or -fdf with -imageout", NULL
);
690 return STATUS_SUCCESS
;
701 Print utility command line help
713 "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",
714 " -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",
715 " -discover FDImage -dsc DscFile -asmincfile AsmIncFile",
716 " -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",
717 " -baseaddr BaseAddr -align Alignment -padvalue PadValue",
718 " -mcmerge MCIFile(s)",
720 " FlashDefFile - input Flash Definition File",
721 " FlashDevice - flash device to use (from flash definition file)",
722 " FlashDeviceImage - flash device image to use (from flash definition file)",
723 " MCIFile - input microcode file to parse",
724 " MCOFile - output binary microcode image to create from MCIFile",
725 " HFile - output #include file to create",
726 " FDImage - name of input FDImage file to scan",
727 " ImageOutFile - output image file to create",
728 " DscFile - output DSC file to create",
729 " AsmIncFile - output ASM include file to create",
730 " InStrFile - input file to replace symbol names, writing result to OutStrFile",
731 " BaseAddr - base address of FDImage (used with -discover)",
732 " Alignment - alignment to use when merging microcode binaries",
733 " PadValue - byte value to use as pad value when aligning microcode binaries",
734 " MCIFile(s) - one or more microcode binary files to merge/concatenate",
738 for (i
= 0; Msg
[i
] != NULL
; i
++) {
739 fprintf (stdout
, "%s\n", Msg
[i
]);