in tools/ifdtool.c [811:1109]
int main(int argc, char *argv[])
{
int opt, option_index = 0;
int mode_dump = 0, mode_extract = 0, mode_inject = 0;
int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0;
int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0;
int create = 0;
char *region_type_string = NULL, *inject_fname = NULL;
char *desc_fname = NULL, *addr_str = NULL;
int region_type = -1, inputfreq = 0;
enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
struct input_file input_file[WRITE_MAX], *ifile, *fdt = NULL;
unsigned char wr_idx, wr_num = 0;
int rom_size = -1;
bool write_it;
char *filename;
char *outfile = NULL;
struct stat buf;
int size = 0;
bool have_uboot = false;
int bios_fd;
char *image;
int ret;
static struct option long_options[] = {
{"create", 0, NULL, 'c'},
{"dump", 0, NULL, 'd'},
{"descriptor", 1, NULL, 'D'},
{"em100", 0, NULL, 'e'},
{"extract", 0, NULL, 'x'},
{"fdt", 1, NULL, 'f'},
{"inject", 1, NULL, 'i'},
{"lock", 0, NULL, 'l'},
{"romsize", 1, NULL, 'r'},
{"spifreq", 1, NULL, 's'},
{"unlock", 0, NULL, 'u'},
{"uboot", 1, NULL, 'U'},
{"write", 1, NULL, 'w'},
{"version", 0, NULL, 'v'},
{"help", 0, NULL, 'h'},
{0, 0, 0, 0}
};
while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lr:s:uU:vw:x?",
long_options, &option_index)) != EOF) {
switch (opt) {
case 'c':
create = 1;
break;
case 'd':
mode_dump = 1;
break;
case 'D':
mode_write_descriptor = 1;
desc_fname = optarg;
break;
case 'e':
mode_em100 = 1;
break;
case 'i':
if (get_two_words(optarg, ®ion_type_string,
&inject_fname)) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
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 'l':
mode_locked = 1;
break;
case 'r':
rom_size = strtol(optarg, NULL, 0);
debug("ROM size %d\n", rom_size);
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 'u':
mode_unlocked = 1;
break;
case 'v':
print_version();
exit(EXIT_SUCCESS);
break;
case 'w':
case 'U':
case 'f':
ifile = &input_file[wr_num];
mode_write = 1;
if (wr_num < WRITE_MAX) {
if (get_two_words(optarg, &addr_str,
&ifile->fname)) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
ifile->addr = strtoll(optarg, NULL, 0);
wr_num++;
} else {
fprintf(stderr,
"The number of files to write simultaneously exceeds the limitation (%d)\n",
WRITE_MAX);
}
break;
case 'x':
mode_extract = 1;
break;
case 'h':
case '?':
default:
print_usage(argv[0]);
exit(EXIT_SUCCESS);
break;
}
}
if (mode_locked == 1 && mode_unlocked == 1) {
fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
exit(EXIT_FAILURE);
}
if (mode_inject == 1 && mode_write == 1) {
fprintf(stderr, "Inject/Write are mutually exclusive\n");
exit(EXIT_FAILURE);
}
if ((mode_dump + mode_extract + mode_inject +
(mode_spifreq | mode_em100 | mode_unlocked |
mode_locked)) > 1) {
fprintf(stderr, "You may not specify more than one mode.\n\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
if ((mode_dump + mode_extract + mode_inject + mode_spifreq +
mode_em100 + mode_locked + mode_unlocked + mode_write +
mode_write_descriptor) == 0 && !create) {
fprintf(stderr, "You need to specify a mode.\n\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
if (create && rom_size == -1) {
fprintf(stderr, "You need to specify a rom size when creating.\n\n");
exit(EXIT_FAILURE);
}
if (optind + 1 != argc) {
fprintf(stderr, "You need to specify a file.\n\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
if (have_uboot && !fdt) {
fprintf(stderr,
"You must supply a device tree file for U-Boot\n\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
filename = argv[optind];
if (optind + 2 != argc)
outfile = argv[optind + 1];
if (create)
bios_fd = open(filename, O_WRONLY | O_CREAT, 0666);
else
bios_fd = open(filename, outfile ? O_RDONLY : O_RDWR);
if (bios_fd == -1) {
perror("Could not open file");
exit(EXIT_FAILURE);
}
if (!create) {
if (fstat(bios_fd, &buf) == -1) {
perror("Could not stat file");
exit(EXIT_FAILURE);
}
size = buf.st_size;
}
debug("File %s is %d bytes\n", filename, size);
if (rom_size == -1)
rom_size = size;
image = malloc(rom_size);
if (!image) {
printf("Out of memory.\n");
exit(EXIT_FAILURE);
}
memset(image, '\xff', rom_size);
if (!create && read(bios_fd, image, size) != size) {
perror("Could not read file");
exit(EXIT_FAILURE);
}
if (size != rom_size) {
debug("ROM size changed to %d bytes\n", rom_size);
size = rom_size;
}
write_it = true;
ret = 0;
if (mode_dump) {
ret = dump_fd(image, size);
write_it = false;
}
if (mode_extract) {
ret = write_regions(image, size);
write_it = false;
}
if (mode_write_descriptor)
ret = write_data(image, size, -size, desc_fname, 0, 0);
if (mode_inject)
ret = inject_region(image, size, region_type, inject_fname);
if (mode_write) {
int offset_uboot_top = 0;
int offset_uboot_start = 0;
for (wr_idx = 0; wr_idx < wr_num; wr_idx++) {
ifile = &input_file[wr_idx];
ret = write_data(image, size, ifile->addr,
ifile->fname, offset_uboot_top,
offset_uboot_start);
if (ret < 0)
break;
}
}
if (mode_spifreq)
set_spi_frequency(image, size, spifreq);
if (mode_em100)
set_em100_mode(image, size);
if (mode_locked)
lock_descriptor(image, size);
if (mode_unlocked)
unlock_descriptor(image, size);
if (write_it) {
if (outfile) {
ret = write_image(outfile, image, size);
} else {
if (lseek(bios_fd, 0, SEEK_SET)) {
perror("Error while seeking");
ret = -1;
}
if (write(bios_fd, image, size) != size) {
perror("Error while writing");
ret = -1;
}
}
}
free(image);
close(bios_fd);
return ret < 0 ? 1 : 0;
}