3 Copyright (c) 2004-2006 Intel Corporation. All rights reserved
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
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.
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"
36 // Version of this utility
38 #define UTILITY_NAME "FlashMap"
39 #define UTILITY_MAJOR_VERSION 1
40 #define UTILITY_MINOR_VERSION 0
43 typedef struct _STRING_LIST
{
44 struct _STRING_LIST
*Next
;
49 // Keep our globals in one of these structures
52 char *CIncludeFileName
;
54 char *FlashDeviceImage
;
57 char *ImageOutFileName
;
59 char *AsmIncludeFileName
;
60 char *FlashDefinitionFileName
;
61 char *StringReplaceInFileName
;
62 char *StringReplaceOutFileName
;
63 char *DiscoverFDImageName
;
64 char MicrocodePadByteValue
;
65 unsigned int MicrocodeAlignment
;
66 STRING_LIST
*MCIFileNames
;
67 STRING_LIST
*LastMCIFileNames
;
68 unsigned int BaseAddress
;
71 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
72 #define DEFAULT_MC_ALIGNMENT 16
85 STRING_LIST
*FileNames
,
86 unsigned int Alignment
,
115 Parse the command line arguments and then call worker functions to do the work
118 argc - number of elements in argv
119 argv - array of command-line arguments
122 STATUS_SUCCESS - no problems encountered while processing
123 STATUS_WARNING - warnings, but no errors, were encountered while processing
124 STATUS_ERROR - errors were encountered while processing
130 SetUtilityName (UTILITY_NAME
);
131 Status
= ProcessCommandLine (argc
, argv
);
132 if (Status
!= STATUS_SUCCESS
) {
136 // Check for discovery of an FD (command line option)
138 if (mGlobals
.DiscoverFDImageName
!= NULL
) {
139 Status
= FDDiscover (mGlobals
.DiscoverFDImageName
, mGlobals
.BaseAddress
);
143 // If they're doing microcode file parsing, then do that
145 if (mGlobals
.MCIFileName
!= NULL
) {
146 MicrocodeConstructor ();
147 MicrocodeParseFile (mGlobals
.MCIFileName
, mGlobals
.MCOFileName
);
148 MicrocodeDestructor ();
151 // If they're doing microcode file merging, then do that now
153 if (mGlobals
.MCIFileNames
!= NULL
) {
154 MergeMicrocodeFiles (
155 mGlobals
.MCOFileName
,
156 mGlobals
.MCIFileNames
,
157 mGlobals
.MicrocodeAlignment
,
158 mGlobals
.MicrocodePadByteValue
162 // If using a flash definition file, then process that and return
164 if (mGlobals
.FlashDefinitionFileName
!= NULL
) {
166 SymbolsConstructor ();
167 Status
= FDFParseFile (mGlobals
.FlashDefinitionFileName
);
168 if (GetUtilityStatus () != STATUS_ERROR
) {
170 // If they want us to do a string-replace on a file, then add the symbol definitions to
171 // the symbol table, and then do the string replace.
173 if (mGlobals
.StringReplaceInFileName
!= NULL
) {
174 Status
= FDFCreateSymbols (mGlobals
.FlashDevice
);
175 Status
= SymbolsFileStringsReplace (mGlobals
.StringReplaceInFileName
, mGlobals
.StringReplaceOutFileName
);
178 // If they want us to create a .h defines file or .c flashmap data file, then do so now
180 if (mGlobals
.CIncludeFileName
!= NULL
) {
181 Status
= FDFCreateCIncludeFile (mGlobals
.FlashDevice
, mGlobals
.CIncludeFileName
);
183 if (mGlobals
.AsmIncludeFileName
!= NULL
) {
184 Status
= FDFCreateAsmIncludeFile (mGlobals
.FlashDevice
, mGlobals
.AsmIncludeFileName
);
187 // If they want us to create an image, do that now
189 if (mGlobals
.ImageOutFileName
!= NULL
) {
190 Status
= FDFCreateImage (mGlobals
.FlashDevice
, mGlobals
.FlashDeviceImage
, mGlobals
.ImageOutFileName
);
193 // If they want to create an output DSC file, do that now
195 if (mGlobals
.DscFileName
!= NULL
) {
196 Status
= FDFCreateDscFile (mGlobals
.FlashDevice
, mGlobals
.DscFileName
);
199 SymbolsDestructor ();
206 while (mGlobals
.MCIFileNames
!= NULL
) {
207 mGlobals
.LastMCIFileNames
= mGlobals
.MCIFileNames
->Next
;
208 _free (mGlobals
.MCIFileNames
);
209 mGlobals
.MCIFileNames
= mGlobals
.LastMCIFileNames
;
211 return GetUtilityStatus ();
216 MergeMicrocodeFiles (
218 STRING_LIST
*FileNames
,
219 unsigned int Alignment
,
226 Merge binary microcode files into a single file, taking into consideration
227 the alignment and pad value.
231 OutFileName - name of the output file to create
232 FileNames - linked list of input microcode files to merge
233 Alignment - alignment for each microcode file in the output image
234 PadByteValue - value to use when padding to meet alignment requirements
238 STATUS_SUCCESS - merge completed successfully or with acceptable warnings
239 STATUS_ERROR - merge failed, output file not created
251 // Open the output file
253 if ((OutFptr
= fopen (OutFileName
, "wb")) == NULL
) {
254 Error (NULL
, 0, 0, OutFileName
, "failed to open output file for writing");
258 // Walk the list of files
260 Status
= STATUS_ERROR
;
264 while (FileNames
!= NULL
) {
266 // Open the file, determine the size, then read it in and write
269 if ((InFptr
= fopen (NormalizePath(FileNames
->Str
), "rb")) == NULL
) {
270 Error (NULL
, 0, 0, NormalizePath(FileNames
->Str
), "failed to open input file for reading");
273 fseek (InFptr
, 0, SEEK_END
);
274 FileSize
= ftell (InFptr
);
275 fseek (InFptr
, 0, SEEK_SET
);
277 Buffer
= (char *) _malloc (FileSize
);
278 if (Buffer
== NULL
) {
279 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
282 if (fread (Buffer
, FileSize
, 1, InFptr
) != 1) {
283 Error (NULL
, 0, 0, FileNames
->Str
, "failed to read file contents");
289 if (Alignment
!= 0) {
290 while ((TotalFileSize
% Alignment
) != 0) {
291 if (fwrite (&PadByteValue
, 1, 1, OutFptr
) != 1) {
292 Error (NULL
, 0, 0, OutFileName
, "failed to write pad bytes to output file");
298 TotalFileSize
+= FileSize
;
299 if (fwrite (Buffer
, FileSize
, 1, OutFptr
) != 1) {
300 Error (NULL
, 0, 0, OutFileName
, "failed to write to output file");
306 Warning (NULL
, 0, 0, FileNames
->Str
, "0-size file encountered");
310 FileNames
= FileNames
->Next
;
312 Status
= STATUS_SUCCESS
;
315 if (InFptr
!= NULL
) {
318 if (Buffer
!= NULL
) {
321 if (Status
== STATUS_ERROR
) {
322 remove (OutFileName
);
336 Process the command line arguments
339 argc - Standard C entry point arguments
340 argv[] - Standard C entry point arguments
343 STATUS_SUCCESS - no problems encountered while processing
344 STATUS_WARNING - warnings, but no errors, were encountered while processing
345 STATUS_ERROR - errors were encountered while processing
353 // Skip program name arg, process others
362 if ((strcmp(argv
[0], "-h") == 0) || (strcmp(argv
[0], "--help") == 0) ||
363 (strcmp(argv
[0], "-?") == 0) || (strcmp(argv
[0], "/?") == 0)) {
368 if ((strcmp(argv
[0], "-V") == 0) || (strcmp(argv
[0], "--version") == 0)) {
374 // Clear out our globals, then start walking the arguments
376 memset ((void *) &mGlobals
, 0, sizeof (mGlobals
));
377 mGlobals
.MicrocodePadByteValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
378 mGlobals
.MicrocodeAlignment
= DEFAULT_MC_ALIGNMENT
;
381 if (strcmp (argv
[0], "-?") == 0) {
384 } else if (strcmp (argv
[0], "-hfile") == 0) {
388 // Used to specify an output C #include file to create that contains
389 // #define statements for all the flashmap region offsets and sizes.
390 // Check for additional argument.
393 Error (NULL
, 0, 0, argv
[0], "option requires an output file name");
398 mGlobals
.CIncludeFileName
= argv
[0];
400 } else if (strcmp (argv
[0], "-flashdevice") == 0) {
402 // -flashdevice FLASH_DEVICE_NAME
404 // Used to select which flash device definition to operate on.
405 // Check for additional argument
408 Error (NULL
, 0, 0, argv
[0], "option requires a flash device name to use");
413 mGlobals
.FlashDevice
= argv
[0];
414 } else if (strcmp (argv
[0], "-mco") == 0) {
418 // Used to specify a microcode output binary file to create.
419 // Check for additional argument.
422 Error (NULL
, 0, 0, (INT8
*) argv
[0], (INT8
*) "option requires an output microcode file name to create");
427 mGlobals
.MCOFileName
= argv
[0];
429 } else if (strcmp (argv
[0], "-asmincfile") == 0) {
431 // -asmincfile FileName
433 // Used to specify the name of the output assembly include file that contains
434 // equates for the flash region addresses and sizes.
435 // Check for additional argument.
438 Error (NULL
, 0, 0, argv
[0], "option requires an output ASM include file name to create");
443 mGlobals
.AsmIncludeFileName
= argv
[0];
445 } else if (strcmp (argv
[0], "-mci") == 0) {
449 // Used to specify an input microcode text file to parse.
450 // Check for additional argument
453 Error (NULL
, 0, 0, (INT8
*) argv
[0], (INT8
*) "option requires an input microcode text file name to parse");
458 mGlobals
.MCIFileName
= argv
[0];
459 } else if (strcmp (argv
[0], "-flashdeviceimage") == 0) {
461 // -flashdeviceimage FlashDeviceImage
463 // Used to specify which flash device image definition from the input flash definition file
465 // Check for additional argument.
468 Error (NULL
, 0, 0, argv
[0], "option requires the name of a flash definition image to use");
473 mGlobals
.FlashDeviceImage
= argv
[0];
474 } else if (strcmp (argv
[0], "-imageout") == 0) {
476 // -imageout FileName
478 // Used to specify the name of the output FD image file to create.
479 // Check for additional argument.
482 Error (NULL
, 0, 0, argv
[0], "option requires an output image filename to create");
487 mGlobals
.ImageOutFileName
= argv
[0];
489 } else if (strcmp (argv
[0], "-dsc") == 0) {
493 // Used to specify the name of the output DSC file to create.
494 // Check for additional argument.
497 Error (NULL
, 0, 0, argv
[0], "option requires an output DSC filename to create");
502 mGlobals
.DscFileName
= argv
[0];
504 } else if (strcmp (argv
[0], "-fdf") == 0) {
508 // Used to specify the name of the input flash definition file.
509 // Check for additional argument.
512 Error (NULL
, 0, 0, argv
[0], "option requires an input flash definition file name");
517 mGlobals
.FlashDefinitionFileName
= argv
[0];
518 } else if (strcmp (argv
[0], "-discover") == 0) {
520 // -discover FDFileName
522 // Debug functionality used to scan an existing FD image, trying to find
523 // firmware volumes at 64K boundaries.
524 // Check for additional argument.
527 Error (NULL
, 0, 0, argv
[0], "option requires an input FD image file name");
532 mGlobals
.DiscoverFDImageName
= argv
[0];
534 } else if (strcmp (argv
[0], "-baseaddr") == 0) {
538 // Used to specify a base address when doing a discover of an FD image.
539 // Check for additional argument.
542 Error (NULL
, 0, 0, argv
[0], "option requires a base address");
547 if (tolower (argv
[0][1]) == 'x') {
548 sscanf (argv
[0] + 2, "%x", &mGlobals
.BaseAddress
);
550 sscanf (argv
[0], "%d", &mGlobals
.BaseAddress
);
552 } else if (strcmp (argv
[0], "-padvalue") == 0) {
556 // Used to specify the value to pad with when aligning data while
557 // creating an FD image. Check for additional argument.
560 Error (NULL
, 0, 0, argv
[0], "option requires a byte value");
565 if (tolower (argv
[0][1]) == 'x') {
566 sscanf (argv
[0] + 2, "%x", &Temp
);
567 mGlobals
.MicrocodePadByteValue
= (char) Temp
;
569 sscanf (argv
[0], "%d", &Temp
);
570 mGlobals
.MicrocodePadByteValue
= (char) Temp
;
572 } else if (strcmp (argv
[0], "-align") == 0) {
576 // Used to specify how each data file is aligned in the region
577 // when creating an FD image. Check for additional argument.
580 Error (NULL
, 0, 0, argv
[0], "option requires an alignment");
585 if (tolower (argv
[0][1]) == 'x') {
586 sscanf (argv
[0] + 2, "%x", &mGlobals
.MicrocodeAlignment
);
588 sscanf (argv
[0], "%d", &mGlobals
.MicrocodeAlignment
);
590 } else if (strcmp (argv
[0], "-mcmerge") == 0) {
592 // -mcmerge FileName(s)
594 // Used to concatenate multiple microde binary files. Can specify
595 // multiple file names with the one -mcmerge flag. Check for additional argument.
597 if ((argc
< 2) || (argv
[1][0] == '-')) {
598 Error (NULL
, 0, 0, argv
[0], "option requires one or more input file names");
602 // Take input files until another option or end of list
605 while ((argc
> 1) && (argv
[1][0] != '-')) {
606 Str
= (STRING_LIST
*) _malloc (sizeof (STRING_LIST
));
608 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
611 memset (Str
, 0, sizeof (STRING_LIST
));
613 if (mGlobals
.MCIFileNames
== NULL
) {
614 mGlobals
.MCIFileNames
= Str
;
616 mGlobals
.LastMCIFileNames
->Next
= Str
;
618 mGlobals
.LastMCIFileNames
= Str
;
622 } else if (strcmp (argv
[0], "-strsub") == 0) {
624 // -strsub SrcFile DestFile
626 // Used to perform string substitutions on a file, writing the result to a new
627 // file. Check for two additional arguments.
630 Error (NULL
, 0, 0, argv
[0], "option requires input and output file names for string substitution");
635 mGlobals
.StringReplaceInFileName
= argv
[0];
638 mGlobals
.StringReplaceOutFileName
= argv
[0];
641 Error (NULL
, 0, 0, argv
[0], "invalid option");
648 // If no outputs requested, then report an error
650 if (ThingsToDo
== 0) {
651 Error (NULL
, 0, 0, "nothing to do", NULL
);
655 // If they want an asm file, #include file, or C file to be created, then they have to specify a
656 // flash device name and flash definition file name.
658 if ((mGlobals
.CIncludeFileName
!= NULL
) &&
659 ((mGlobals
.FlashDevice
== NULL
) || (mGlobals
.FlashDefinitionFileName
== NULL
))) {
660 Error (NULL
, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL
);
663 if ((mGlobals
.AsmIncludeFileName
!= NULL
) &&
664 ((mGlobals
.FlashDevice
== NULL
) || (mGlobals
.FlashDefinitionFileName
== NULL
))) {
665 Error (NULL
, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL
);
669 // If they want a dsc file to be created, then they have to specify a
670 // flash device name and a flash definition file name
672 if (mGlobals
.DscFileName
!= NULL
) {
673 if (mGlobals
.FlashDevice
== NULL
) {
674 Error (NULL
, 0, 0, "must specify -flashdevice with -dsc", NULL
);
677 if (mGlobals
.FlashDefinitionFileName
== NULL
) {
678 Error (NULL
, 0, 0, "must specify -fdf with -dsc", NULL
);
683 // If they specified an output microcode file name, then they have to specify an input
684 // file name, and vice versa.
686 if ((mGlobals
.MCIFileName
!= NULL
) && (mGlobals
.MCOFileName
== NULL
)) {
687 Error (NULL
, 0, 0, "must specify output microcode file name", NULL
);
690 if ((mGlobals
.MCOFileName
!= NULL
) && (mGlobals
.MCIFileName
== NULL
) && (mGlobals
.MCIFileNames
== NULL
)) {
691 Error (NULL
, 0, 0, "must specify input microcode file name", NULL
);
695 // If doing merge, then have to specify output file name
697 if ((mGlobals
.MCIFileNames
!= NULL
) && (mGlobals
.MCOFileName
== NULL
)) {
698 Error (NULL
, 0, 0, "must specify output microcode file name", NULL
);
702 // If they want an output image to be created, then they have to specify
703 // the flash device and the flash device image to use.
705 if (mGlobals
.ImageOutFileName
!= NULL
) {
706 if (mGlobals
.FlashDevice
== NULL
) {
707 Error (NULL
, 0, 0, "must specify -flashdevice with -imageout", NULL
);
710 if (mGlobals
.FlashDeviceImage
== NULL
) {
711 Error (NULL
, 0, 0, "must specify -flashdeviceimage with -imageout", NULL
);
714 if (mGlobals
.FlashDefinitionFileName
== NULL
) {
715 Error (NULL
, 0, 0, "must specify -c or -fdf with -imageout", NULL
);
719 return STATUS_SUCCESS
;
731 Print version information for this utility.
742 printf ("%s v%d.%d -EDK Utility for flash management for EFI build environment.\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
743 printf ("Copyright (c) 1999-2006 Intel Corporation. All rights reserved.\n");
754 Print utility command line help
766 "\nUsage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",
767 " -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",
768 " -discover FDImage -dsc DscFile -asmincfile AsmIncFile",
769 " -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",
770 " -baseaddr BaseAddr -align Alignment -padvalue PadValue",
771 " -mcmerge MCIFile(s)",
772 " -h,--help,-?,/? - to display help messages",
773 " -V,--version - to display version information",
775 " FlashDefFile - input Flash Definition File",
776 " FlashDevice - flash device to use (from flash definition file)",
777 " FlashDeviceImage - flash device image to use (from flash definition file)",
778 " MCIFile - input microcode file to parse",
779 " MCOFile - output binary microcode image to create from MCIFile",
780 " HFile - output #include file to create",
781 " FDImage - name of input FDImage file to scan",
782 " ImageOutFile - output image file to create",
783 " DscFile - output DSC file to create",
784 " AsmIncFile - output ASM include file to create",
785 " InStrFile - input file to replace symbol names, writing result to OutStrFile",
786 " BaseAddr - base address of FDImage (used with -discover)",
787 " Alignment - alignment to use when merging microcode binaries",
788 " PadValue - byte value to use as pad value when aligning microcode binaries",
789 " MCIFile(s) - one or more microcode binary files to merge/concatenate",
794 for (i
= 0; Msg
[i
] != NULL
; i
++) {
795 fprintf (stdout
, "%s\n", Msg
[i
]);
806 if (OldPathName
== NULL
) {
810 Visitor
= OldPathName
;
811 while (*Visitor
!= '\0') {
812 if (*Visitor
== '\\') {