1b1309f289
To avoid having two copies for every firmware descriptor (one for EM100 use and one for real SPI flash use), add an EM100 mode to ifdtool that allows to "dumb down" a fast image to the settings required for the EM100 to work. Change-Id: I0ed989f0a49316bc63d8627cb5d4bd988ae7a103 Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/1039 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
607 lines
17 KiB
C
607 lines
17 KiB
C
/*
|
|
* ifdtool - dump Intel Firmware Descriptor information
|
|
*
|
|
* Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include "ifdtool.h"
|
|
|
|
static fdbar_t *find_fd(char *image, int size)
|
|
{
|
|
int i, found = 0;
|
|
|
|
/* Scan for FD signature */
|
|
for (i = 0; i < (size - 4); i += 4) {
|
|
if (*(uint32_t *) (image + i) == 0x0FF0A55A) {
|
|
found = 1;
|
|
break; // signature found.
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
printf("No Flash Descriptor found in this image\n");
|
|
return NULL;
|
|
}
|
|
|
|
printf("Found Flash Descriptor signature at 0x%08x\n", i);
|
|
|
|
return (fdbar_t *) (image + i);
|
|
}
|
|
|
|
typedef struct {
|
|
int base, limit, size;
|
|
} region_t;
|
|
|
|
static region_t get_region(frba_t *frba, int region_type)
|
|
{
|
|
region_t region;
|
|
region.base = 0, region.limit = 0, region.size = 0;
|
|
|
|
switch (region_type) {
|
|
case 0:
|
|
region.base = (frba->flreg0 & 0x00000fff) << 12;
|
|
region.limit = ((frba->flreg0 & 0x0fff0000) >> 4) | 0xfff;
|
|
break;
|
|
case 1:
|
|
region.base = (frba->flreg1 & 0x00000fff) << 12;
|
|
region.limit = ((frba->flreg1 & 0x0fff0000) >> 4) | 0xfff;
|
|
break;
|
|
case 2:
|
|
region.base = (frba->flreg2 & 0x00000fff) << 12;
|
|
region.limit = ((frba->flreg2 & 0x0fff0000) >> 4) | 0xfff;
|
|
break;
|
|
case 3:
|
|
region.base = (frba->flreg3 & 0x00000fff) << 12;
|
|
region.limit = ((frba->flreg3 & 0x0fff0000) >> 4) | 0xfff;
|
|
break;
|
|
case 4:
|
|
region.base = (frba->flreg4 & 0x00000fff) << 12;
|
|
region.limit = ((frba->flreg4 & 0x0fff0000) >> 4) | 0xfff;
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Invalid region type.\n");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
region.size = region.limit - region.base + 1;
|
|
|
|
return region;
|
|
}
|
|
|
|
static const char *region_name(int region_type)
|
|
{
|
|
static const char *regions[5] = {
|
|
"Flash Descriptor",
|
|
"BIOS",
|
|
"Intel ME",
|
|
"GbE",
|
|
"Platform Data"
|
|
};
|
|
|
|
if (region_type < 0 || region_type > 4) {
|
|
fprintf(stderr, "Invalid region type.\n");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
return regions[region_type];
|
|
}
|
|
|
|
static const char *region_filename(int region_type)
|
|
{
|
|
static const char *region_filenames[5] = {
|
|
"flashregion_0_flashdescriptor.bin",
|
|
"flashregion_1_bios.bin",
|
|
"flashregion_2_intel_me.bin",
|
|
"flashregion_3_gbe.bin",
|
|
"flashregion_4_platform_data.bin"
|
|
};
|
|
|
|
if (region_type < 0 || region_type > 4) {
|
|
fprintf(stderr, "Invalid region type.\n");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
return region_filenames[region_type];
|
|
}
|
|
|
|
static void dump_frba(frba_t * frba)
|
|
{
|
|
printf("\nFound Region Section\n");
|
|
printf("FLREG0: 0x%08x\n", frba->flreg0);
|
|
printf("FLREG1: 0x%08x\n", frba->flreg1);
|
|
printf("FLREG2: 0x%08x\n", frba->flreg2);
|
|
printf("FLREG3: 0x%08x\n", frba->flreg3);
|
|
printf("FLREG4: 0x%08x\n", frba->flreg4);
|
|
}
|
|
|
|
static void decode_spi_frequency(unsigned int freq)
|
|
{
|
|
switch (freq) {
|
|
case SPI_FREQUENCY_20MHZ:
|
|
printf("20MHz");
|
|
break;
|
|
case SPI_FREQUENCY_33MHZ:
|
|
printf("33MHz");
|
|
break;
|
|
case SPI_FREQUENCY_50MHZ:
|
|
printf("50MHz");
|
|
break;
|
|
default:
|
|
printf("unknown<%x>MHz", freq);
|
|
}
|
|
}
|
|
|
|
static void decode_component_density(unsigned int density)
|
|
{
|
|
switch (density) {
|
|
case COMPONENT_DENSITY_512KB:
|
|
printf("512KB");
|
|
break;
|
|
case COMPONENT_DENSITY_1MB:
|
|
printf("1MB");
|
|
break;
|
|
case COMPONENT_DENSITY_2MB:
|
|
printf("2MB");
|
|
break;
|
|
case COMPONENT_DENSITY_4MB:
|
|
printf("4MB");
|
|
break;
|
|
case COMPONENT_DENSITY_8MB:
|
|
printf("8MB");
|
|
break;
|
|
case COMPONENT_DENSITY_16MB:
|
|
printf("16MB");
|
|
break;
|
|
default:
|
|
printf("unknown<%x>MB", density);
|
|
}
|
|
}
|
|
|
|
static void dump_fcba(fcba_t * fcba)
|
|
{
|
|
printf("\nFound Component Section\n");
|
|
printf("FLCOMP 0x%08x\n", fcba->flcomp);
|
|
printf(" Dual Output Fast Read Support: %ssupported\n",
|
|
(fcba->flcomp & (1 << 30))?"":"not ");
|
|
printf(" Read ID/Read Status Clock Frequency: ");
|
|
decode_spi_frequency((fcba->flcomp >> 27) & 7);
|
|
printf("\n Write/Erase Clock Frequency: ");
|
|
decode_spi_frequency((fcba->flcomp >> 24) & 7);
|
|
printf("\n Fast Read Clock Frequency: ");
|
|
decode_spi_frequency((fcba->flcomp >> 21) & 7);
|
|
printf("\n Fast Read Support: %ssupported",
|
|
(fcba->flcomp & (1 << 20))?"":"not ");
|
|
printf("\n Read Clock Frequency: ");
|
|
decode_spi_frequency((fcba->flcomp >> 17) & 7);
|
|
printf("\n Component 2 Density: ");
|
|
decode_component_density((fcba->flcomp >> 3) & 7);
|
|
printf("\n Component 1 Density: ");
|
|
decode_component_density(fcba->flcomp & 7);
|
|
printf("\n");
|
|
printf("FLILL 0x%08x\n", fcba->flill);
|
|
printf("FLPB 0x%08x\n", fcba->flpb);
|
|
}
|
|
|
|
static void dump_fpsba(fpsba_t * fpsba)
|
|
{
|
|
printf("\nFound PCH Strap Section\n");
|
|
printf("PCHSTRP0: 0x%08x\n", fpsba->pchstrp0);
|
|
printf("PCHSTRP1: 0x%08x\n", fpsba->pchstrp1);
|
|
printf("PCHSTRP2: 0x%08x\n", fpsba->pchstrp2);
|
|
printf("PCHSTRP3: 0x%08x\n", fpsba->pchstrp3);
|
|
printf("PCHSTRP4: 0x%08x\n", fpsba->pchstrp4);
|
|
printf("PCHSTRP5: 0x%08x\n", fpsba->pchstrp5);
|
|
printf("PCHSTRP6: 0x%08x\n", fpsba->pchstrp6);
|
|
printf("PCHSTRP7: 0x%08x\n", fpsba->pchstrp7);
|
|
printf("PCHSTRP8: 0x%08x\n", fpsba->pchstrp8);
|
|
printf("PCHSTRP9: 0x%08x\n", fpsba->pchstrp9);
|
|
printf("PCHSTRP10: 0x%08x\n", fpsba->pchstrp10);
|
|
printf("PCHSTRP11: 0x%08x\n", fpsba->pchstrp11);
|
|
printf("PCHSTRP12: 0x%08x\n", fpsba->pchstrp12);
|
|
printf("PCHSTRP13: 0x%08x\n", fpsba->pchstrp13);
|
|
printf("PCHSTRP14: 0x%08x\n", fpsba->pchstrp14);
|
|
printf("PCHSTRP15: 0x%08x\n", fpsba->pchstrp15);
|
|
}
|
|
|
|
static void dump_fmba(fmba_t * fmba)
|
|
{
|
|
printf("\nFound Master Section\n");
|
|
printf("FLMSTR1: 0x%08x\n", fmba->flmstr1);
|
|
printf("FLMSTR2: 0x%08x\n", fmba->flmstr2);
|
|
printf("FLMSTR3: 0x%08x\n", fmba->flmstr3);
|
|
}
|
|
|
|
static void dump_fmsba(fmsba_t * fmsba)
|
|
{
|
|
printf("\nFound Processor Strap Section\n");
|
|
printf("????: 0x%08x\n", fmsba->data[0]);
|
|
printf("????: 0x%08x\n", fmsba->data[1]);
|
|
printf("????: 0x%08x\n", fmsba->data[2]);
|
|
printf("????: 0x%08x\n", fmsba->data[3]);
|
|
}
|
|
|
|
static void dump_fd(char *image, int size)
|
|
{
|
|
fdbar_t *fdb = find_fd(image, size);
|
|
if (!fdb)
|
|
exit(EXIT_FAILURE);
|
|
|
|
printf("FLMAP0: 0x%08x\n", fdb->flmap0);
|
|
printf(" NR: %d\n", (fdb->flmap0 >> 24) & 7);
|
|
printf(" FRBA: 0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4);
|
|
printf(" NC: %d\n", ((fdb->flmap0 >> 8) & 3) + 1);
|
|
printf(" FCBA: 0x%x\n", ((fdb->flmap0) & 0xff) << 4);
|
|
|
|
printf("FLMAP1: 0x%08x\n", fdb->flmap1);
|
|
printf(" ISL: 0x%02x\n", (fdb->flmap1 >> 24) & 0xff);
|
|
printf(" FPSBA: 0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4);
|
|
printf(" NM: %d\n", (fdb->flmap1 >> 8) & 3);
|
|
printf(" FMBA: 0x%x\n", ((fdb->flmap1) & 0xff) << 4);
|
|
|
|
printf("FLMAP2: 0x%08x\n", fdb->flmap2);
|
|
printf(" PSL: 0x%04x\n", (fdb->flmap2 >> 8) & 0xffff);
|
|
printf(" FMSBA: 0x%x\n", ((fdb->flmap2) & 0xff) << 4);
|
|
|
|
printf("FLUMAP1: 0x%08x\n", fdb->flumap1);
|
|
|
|
dump_frba((frba_t *)
|
|
(image + (((fdb->flmap0 >> 16) & 0xff) << 4)));
|
|
dump_fcba((fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4)));
|
|
dump_fpsba((fpsba_t *)
|
|
(image + (((fdb->flmap1 >> 16) & 0xff) << 4)));
|
|
dump_fmba((fmba_t *) (image + (((fdb->flmap1) & 0xff) << 4)));
|
|
dump_fmsba((fmsba_t *) (image + (((fdb->flmap2) & 0xff) << 4)));
|
|
}
|
|
|
|
static void write_regions(char *image, int size)
|
|
{
|
|
int i;
|
|
|
|
fdbar_t *fdb = find_fd(image, size);
|
|
if (!fdb)
|
|
exit(EXIT_FAILURE);
|
|
|
|
frba_t *frba =
|
|
(frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
|
|
|
|
for (i = 0; i<5; i++) {
|
|
region_t region = get_region(frba, i);
|
|
printf("Flash Region %d (%s): %08x - %08x %s\n",
|
|
i, region_name(i), region.base, region.limit,
|
|
region.size < 1 ? "(unused)" : "");
|
|
if (region.size > 0) {
|
|
int region_fd;
|
|
region_fd = open(region_filename(i),
|
|
O_WRONLY | O_CREAT | O_TRUNC,
|
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
|
if (write(region_fd, image + region.base, region.size) != region.size)
|
|
printf("Error while writing.");
|
|
close(region_fd);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void write_image(char *filename, char *image, int size)
|
|
{
|
|
char new_filename[FILENAME_MAX]; // allow long file names
|
|
int new_fd;
|
|
|
|
strncpy(new_filename, filename, FILENAME_MAX);
|
|
strncat(new_filename, ".new", FILENAME_MAX - strlen(filename));
|
|
|
|
printf("Writing new image to %s\n", new_filename);
|
|
|
|
// Now write out new image
|
|
new_fd = open(new_filename,
|
|
O_WRONLY | O_CREAT | O_TRUNC,
|
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
|
if (write(new_fd, image, size) != size)
|
|
printf("Error while writing.");
|
|
close(new_fd);
|
|
}
|
|
|
|
static void set_spi_frequency(char *filename, char *image, int size,
|
|
enum spi_frequency freq)
|
|
{
|
|
fdbar_t *fdb = find_fd(image, size);
|
|
fcba_t *fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
|
|
|
|
/* clear bits 21-29 */
|
|
fcba->flcomp &= ~0x3fe00000;
|
|
/* Read ID and Read Status Clock Frequency */
|
|
fcba->flcomp |= freq << 27;
|
|
/* Write and Erase Clock Frequency */
|
|
fcba->flcomp |= freq << 24;
|
|
/* Fast Read Clock Frequency */
|
|
fcba->flcomp |= freq << 21;
|
|
|
|
write_image(filename, image, size);
|
|
}
|
|
|
|
static void set_em100_mode(char *filename, char *image, int size)
|
|
{
|
|
fdbar_t *fdb = find_fd(image, size);
|
|
fcba_t *fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
|
|
|
|
fcba->flcomp &= ~(1 << 30);
|
|
set_spi_frequency(filename, image, size, SPI_FREQUENCY_20MHZ);
|
|
}
|
|
|
|
void inject_region(char *filename, char *image, int size, int region_type,
|
|
char *region_fname)
|
|
{
|
|
fdbar_t *fdb = find_fd(image, size);
|
|
if (!fdb)
|
|
exit(EXIT_FAILURE);
|
|
frba_t *frba =
|
|
(frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
|
|
|
|
region_t region = get_region(frba, region_type);
|
|
if (region.size <= 0xfff) {
|
|
fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",
|
|
region_name(region_type));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int region_fd = open(region_fname, O_RDONLY);
|
|
if (region_fd == -1) {
|
|
perror("Could not open file");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
struct stat buf;
|
|
if (fstat(region_fd, &buf) == -1) {
|
|
perror("Could not stat file");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
int region_size = buf.st_size;
|
|
|
|
printf("File %s is %d bytes\n", region_fname, region_size);
|
|
|
|
if ( (region_size > region.size) || ((region_type != 1) &&
|
|
(region_size > region.size))) {
|
|
fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
|
|
" bytes. Not injecting.\n",
|
|
region_name(region_type), region.size,
|
|
region.size, region_size, region_size);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int offset = 0;
|
|
if ((region_type == 1) && (region_size < region.size)) {
|
|
fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
|
|
" bytes. Padding before injecting.\n",
|
|
region_name(region_type), region.size,
|
|
region.size, region_size, region_size);
|
|
offset = region.size - region_size;
|
|
memset(image + region.base, 0xff, offset);
|
|
}
|
|
|
|
if (read(region_fd, image + region.base + offset, region_size)
|
|
!= region_size) {
|
|
perror("Could not read file");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
close(region_fd);
|
|
|
|
printf("Adding %s as the %s section of %s\n",
|
|
region_fname, region_name(region_type), filename);
|
|
write_image(filename, image, size);
|
|
}
|
|
|
|
static void print_version(void)
|
|
{
|
|
printf("ifdtool v%s -- ", IFDTOOL_VERSION);
|
|
printf("Copyright (C) 2011 Google Inc.\n\n");
|
|
printf
|
|
("This program is free software: you can redistribute it and/or modify\n"
|
|
"it under the terms of the GNU General Public License as published by\n"
|
|
"the Free Software Foundation, version 2 of the License.\n\n"
|
|
"This program is distributed in the hope that it will be useful,\n"
|
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
"GNU General Public License for more details.\n\n"
|
|
"You should have received a copy of the GNU General Public License\n"
|
|
"along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n");
|
|
}
|
|
|
|
static void print_usage(const char *name)
|
|
{
|
|
printf("usage: %s [-vhdix?] <filename>\n", name);
|
|
printf("\n"
|
|
" -d | --dump: dump intel firmware descriptor\n"
|
|
" -x | --extract: extract intel fd modules\n"
|
|
" -i | --inject <region>:<module> inject file <module> into region <region>\n"
|
|
" -s | --spifreq <20|33|50> set the SPI frequency\n"
|
|
" -e | --em100 set SPI frequency to 20MHz and disable\n"
|
|
" Dual Output Fast Read Support\n"
|
|
" -v | --version: print the version\n"
|
|
" -h | --help: print this help\n\n"
|
|
"<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
|
|
"\n");
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int opt, option_index = 0;
|
|
int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
|
|
int mode_em100 = 0;
|
|
char *region_type_string = NULL, *region_fname = NULL;
|
|
int region_type = -1, inputfreq = 0;
|
|
enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
|
|
|
|
static struct option long_options[] = {
|
|
{"dump", 0, NULL, 'd'},
|
|
{"extract", 0, NULL, 'x'},
|
|
{"inject", 1, NULL, 'i'},
|
|
{"spifreq", 1, NULL, 's'},
|
|
{"em100", 0, NULL, 'e'},
|
|
{"version", 0, NULL, 'v'},
|
|
{"help", 0, NULL, 'h'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
while ((opt = getopt_long(argc, argv, "dxi:s:evh?",
|
|
long_options, &option_index)) != EOF) {
|
|
switch (opt) {
|
|
case 'd':
|
|
mode_dump = 1;
|
|
break;
|
|
case 'x':
|
|
mode_extract = 1;
|
|
break;
|
|
case 'i':
|
|
// separate type and file name
|
|
region_type_string = strdup(optarg);
|
|
region_fname = strchr(region_type_string, ':');
|
|
if (!region_fname) {
|
|
print_usage(argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
region_fname[0] = '\0';
|
|
region_fname++;
|
|
// Descriptor, BIOS, ME, GbE, Platform
|
|
// valid type?
|
|
if (!strcasecmp("Descriptor", region_type_string))
|
|
region_type = 0;
|
|
else if (!strcasecmp("BIOS", region_type_string))
|
|
region_type = 1;
|
|
else if (!strcasecmp("ME", region_type_string))
|
|
region_type = 2;
|
|
else if (!strcasecmp("GbE", region_type_string))
|
|
region_type = 3;
|
|
else if (!strcasecmp("Platform", region_type_string))
|
|
region_type = 4;
|
|
if (region_type == -1) {
|
|
fprintf(stderr, "No such region type: '%s'\n\n",
|
|
region_type_string);
|
|
print_usage(argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
mode_inject = 1;
|
|
break;
|
|
case 's':
|
|
// Parse the requested SPI frequency
|
|
inputfreq = strtol(optarg, NULL, 0);
|
|
switch (inputfreq) {
|
|
case 20:
|
|
spifreq = SPI_FREQUENCY_20MHZ;
|
|
break;
|
|
case 33:
|
|
spifreq = SPI_FREQUENCY_33MHZ;
|
|
break;
|
|
case 50:
|
|
spifreq = SPI_FREQUENCY_50MHZ;
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Invalid SPI Frequency: %d\n",
|
|
inputfreq);
|
|
print_usage(argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
mode_spifreq = 1;
|
|
break;
|
|
case 'e':
|
|
mode_em100 = 1;
|
|
break;
|
|
case 'v':
|
|
print_version();
|
|
exit(EXIT_SUCCESS);
|
|
break;
|
|
case 'h':
|
|
case '?':
|
|
default:
|
|
print_usage(argv[0]);
|
|
exit(EXIT_SUCCESS);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((mode_dump + mode_extract + mode_inject + mode_spifreq) > 1) {
|
|
fprintf(stderr, "Only one mode allowed.\n\n");
|
|
print_usage(argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if ((mode_dump + mode_extract + mode_inject + mode_spifreq +
|
|
mode_em100) == 0) {
|
|
fprintf(stderr, "You need to specify a mode.\n\n");
|
|
print_usage(argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (optind + 1 != argc) {
|
|
fprintf(stderr, "You need to specify a file.\n\n");
|
|
print_usage(argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
char *filename = argv[optind];
|
|
int bios_fd = open(filename, O_RDONLY);
|
|
if (bios_fd == -1) {
|
|
perror("Could not open file");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
struct stat buf;
|
|
if (fstat(bios_fd, &buf) == -1) {
|
|
perror("Could not stat file");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
int size = buf.st_size;
|
|
|
|
printf("File %s is %d bytes\n", filename, size);
|
|
|
|
char *image = malloc(size);
|
|
if (!image) {
|
|
printf("Out of memory.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (read(bios_fd, image, size) != size) {
|
|
perror("Could not read file");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
close(bios_fd);
|
|
|
|
if (mode_dump)
|
|
dump_fd(image, size);
|
|
|
|
if (mode_extract)
|
|
write_regions(image, size);
|
|
|
|
if (mode_inject)
|
|
inject_region(filename, image, size, region_type,
|
|
region_fname);
|
|
|
|
if (mode_spifreq)
|
|
set_spi_frequency(filename, image, size, spifreq);
|
|
|
|
if (mode_em100)
|
|
set_em100_mode(filename, image, size);
|
|
|
|
free(image);
|
|
|
|
return 0;
|
|
}
|