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"
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
]);