Add ifdtool, utility to read / modify Intel Firmware Descriptor images
Change-Id: Ie78b97bf573d238d0dff9a663e774deb1b7dea44 Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/272 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
parent
c31c4de681
commit
1c795ad109
|
@ -0,0 +1,53 @@
|
|||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
PROGRAM = ifdtool
|
||||
|
||||
CC = gcc
|
||||
INSTALL = /usr/bin/install
|
||||
PREFIX = /usr/local
|
||||
CFLAGS = -O2 -g -Wall -W
|
||||
LDFLAGS =
|
||||
|
||||
OBJS = ifdtool.o
|
||||
|
||||
all: dep $(PROGRAM)
|
||||
|
||||
$(PROGRAM): $(OBJS)
|
||||
$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(PROGRAM) *.o *~
|
||||
|
||||
distclean: clean
|
||||
rm -f .dependencies
|
||||
|
||||
dep:
|
||||
@$(CC) $(CFLAGS) -MM *.c > .dependencies
|
||||
|
||||
install: $(PROGRAM)
|
||||
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||
$(INSTALL) $(PROGRAM) $(DESTDIR)$(PREFIX)/bin
|
||||
mkdir -p $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
$(INSTALL) $(PROGRAM).8 $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
|
||||
.PHONY: all clean distclean dep
|
||||
|
||||
-include .dependencies
|
||||
|
|
@ -0,0 +1,551 @@
|
|||
/*
|
||||
* 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 dump_fcba(fcba_t * fcba)
|
||||
{
|
||||
printf("\nFound Component Section\n");
|
||||
printf("FLCOMP 0x%08x\n", fcba->flcomp);
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
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"
|
||||
" -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;
|
||||
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'},
|
||||
{"version", 0, NULL, 'v'},
|
||||
{"help", 0, NULL, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "dxi:s:vh?",
|
||||
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 '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) == 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);
|
||||
|
||||
free(image);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
#define IFDTOOL_VERSION "1.0"
|
||||
|
||||
enum spi_frequency {
|
||||
SPI_FREQUENCY_20MHZ = 0,
|
||||
SPI_FREQUENCY_33MHZ = 1,
|
||||
SPI_FREQUENCY_50MHZ = 4,
|
||||
};
|
||||
|
||||
// flash descriptor
|
||||
typedef struct {
|
||||
uint32_t flvalsig;
|
||||
uint32_t flmap0;
|
||||
uint32_t flmap1;
|
||||
uint32_t flmap2;
|
||||
uint8_t reserved[0xefc - 0x20];
|
||||
uint32_t flumap1;
|
||||
} __attribute__((packed)) fdbar_t;
|
||||
|
||||
// regions
|
||||
typedef struct {
|
||||
uint32_t flreg0;
|
||||
uint32_t flreg1;
|
||||
uint32_t flreg2;
|
||||
uint32_t flreg3;
|
||||
uint32_t flreg4;
|
||||
} __attribute__((packed)) frba_t;
|
||||
|
||||
// component section
|
||||
typedef struct {
|
||||
uint32_t flcomp;
|
||||
uint32_t flill;
|
||||
uint32_t flpb;
|
||||
} __attribute__((packed)) fcba_t;
|
||||
|
||||
// pch strap
|
||||
typedef struct {
|
||||
uint32_t pchstrp0;
|
||||
uint32_t pchstrp1;
|
||||
uint32_t pchstrp2;
|
||||
uint32_t pchstrp3;
|
||||
uint32_t pchstrp4;
|
||||
uint32_t pchstrp5;
|
||||
uint32_t pchstrp6;
|
||||
uint32_t pchstrp7;
|
||||
uint32_t pchstrp8;
|
||||
uint32_t pchstrp9;
|
||||
uint32_t pchstrp10;
|
||||
uint32_t pchstrp11;
|
||||
uint32_t pchstrp12;
|
||||
uint32_t pchstrp13;
|
||||
uint32_t pchstrp14;
|
||||
uint32_t pchstrp15;
|
||||
} __attribute__((packed)) fpsba_t;
|
||||
|
||||
// master
|
||||
typedef struct {
|
||||
uint32_t flmstr1;
|
||||
uint32_t flmstr2;
|
||||
uint32_t flmstr3;
|
||||
} __attribute__((packed)) fmba_t;
|
||||
|
||||
// processor strap
|
||||
typedef struct {
|
||||
uint32_t data[8];
|
||||
} __attribute__((packed)) fmsba_t;
|
||||
|
||||
|
Loading…
Reference in New Issue