X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=tools%2Fifdtool.c;h=3a39b7bc701194e6bf1e9b0cb767c2feb7abca39;hb=221c4d982698d9f537237108f779b8174ce24c87;hp=a4b481fb60b45d7769fb48d5098a889d68d09f57;hpb=1fc4e6f486cc1e9d2dcf0ba86e6021c3d83dce51;p=oweals%2Fu-boot.git diff --git a/tools/ifdtool.c b/tools/ifdtool.c index a4b481fb60..3a39b7bc70 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -1,10 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ifdtool - Manage Intel Firmware Descriptor information * * Copyright 2014 Google, Inc * - * SPDX-License-Identifier: GPL-2.0 - * * From Coreboot project, but it got a serious code clean-up * and a few new features */ @@ -12,12 +11,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "ifdtool.h" #undef DEBUG @@ -32,6 +33,11 @@ #define FLREG_BASE(reg) ((reg & 0x00000fff) << 12); #define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff); +struct input_file { + char *fname; + unsigned int addr; +}; + /** * find_fd() - Find the flash description in the ROM image * @@ -54,7 +60,8 @@ static struct fdbar_t *find_fd(char *image, int size) return NULL; } - debug("Found Flash Descriptor signature at 0x%08x\n", i); + debug("Found Flash Descriptor signature at 0x%08lx\n", + (char *)ptr - image); return (struct fdbar_t *)ptr; } @@ -448,7 +455,7 @@ static int write_regions(char *image, int size) if (ret) return ret; dump_region(i, frba); - if (region.size == 0) + if (region.size <= 0) continue; region_fd = open(region_filename(i), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | @@ -464,6 +471,16 @@ static int write_regions(char *image, int size) return ret; } +static int perror_fname(const char *fmt, const char *fname) +{ + char msg[strlen(fmt) + strlen(fname) + 1]; + + sprintf(msg, fmt, fname); + perror(msg); + + return -1; +} + /** * write_image() - Write the image to a file * @@ -480,10 +497,10 @@ static int write_image(char *filename, char *image, int size) new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (write(new_fd, image, size) != size) { - perror("Error while writing"); - return -1; - } + if (new_fd < 0) + return perror_fname("Could not open file '%s'", filename); + if (write(new_fd, image, size) != size) + return perror_fname("Could not write file '%s'", filename); close(new_fd); return 0; @@ -585,14 +602,10 @@ int open_for_read(const char *fname, int *sizep) int fd = open(fname, O_RDONLY); struct stat buf; - if (fd == -1) { - perror("Could not open file"); - return -1; - } - if (fstat(fd, &buf) == -1) { - perror("Could not stat file"); - return -1; - } + if (fd == -1) + return perror_fname("Could not open file '%s'", fname); + if (fstat(fd, &buf) == -1) + return perror_fname("Could not stat file '%s'", fname); *sizep = buf.st_size; debug("File %s is %d bytes\n", fname, *sizep); @@ -686,10 +699,13 @@ int inject_region(char *image, int size, int region_type, char *region_fname) * 0xffffffff so use an address relative to that. For an * 8MB ROM the start address is 0xfff80000. * @write_fname: Filename to add to the image - * @return 0 if OK, -ve on error + * @offset_uboot_top: Offset of the top of U-Boot + * @offset_uboot_start: Offset of the start of U-Boot + * @return number of bytes written if OK, -ve on error */ static int write_data(char *image, int size, unsigned int addr, - const char *write_fname) + const char *write_fname, int offset_uboot_top, + int offset_uboot_start) { int write_fd, write_size; int offset; @@ -698,7 +714,27 @@ static int write_data(char *image, int size, unsigned int addr, if (write_fd < 0) return write_fd; - offset = addr + size; + offset = (uint32_t)(addr + size); + if (offset_uboot_top) { + if (offset_uboot_start < offset && + offset_uboot_top >= offset) { + fprintf(stderr, "U-Boot image overlaps with region '%s'\n", + write_fname); + fprintf(stderr, + "U-Boot finishes at offset %x, file starts at %x\n", + offset_uboot_top, offset); + return -EXDEV; + } + if (offset_uboot_start > offset && + offset_uboot_start <= offset + write_size) { + fprintf(stderr, "U-Boot image overlaps with region '%s'\n", + write_fname); + fprintf(stderr, + "U-Boot starts at offset %x, file finishes at %x\n", + offset_uboot_start, offset + write_size); + return -EXDEV; + } + } debug("Writing %s to offset %#x\n", write_fname, offset); if (offset < 0 || offset + write_size > size) { @@ -714,14 +750,14 @@ static int write_data(char *image, int size, unsigned int addr, close(write_fd); - return 0; + return write_size; } static void print_version(void) { printf("ifdtool v%s -- ", IFDTOOL_VERSION); printf("Copyright (C) 2014 Google Inc.\n\n"); - printf("SPDX-License-Identifier: GPL-2.0+\n"); + printf("SPDX-License-Identifier: GPL-2.0+\n"); } static void print_usage(const char *name) @@ -732,6 +768,7 @@ static void print_usage(const char *name) " -x | --extract: extract intel fd modules\n" " -i | --inject : inject file into region \n" " -w | --write : write file to appear at memory address \n" + " multiple files can be written simultaneously\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" @@ -778,17 +815,19 @@ int main(int argc, char *argv[]) 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, *src_fname = NULL; - char *addr_str = NULL; + 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; - unsigned int addr = 0; + 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; @@ -798,18 +837,20 @@ int main(int argc, char *argv[]) {"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:ehi:lr:s:uvw:x?", + while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lr:s:uU:vw:x?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': @@ -820,14 +861,14 @@ int main(int argc, char *argv[]) break; case 'D': mode_write_descriptor = 1; - src_fname = optarg; + desc_fname = optarg; break; case 'e': mode_em100 = 1; break; case 'i': if (get_two_words(optarg, ®ion_type_string, - &src_fname)) { + &inject_fname)) { print_usage(argv[0]); exit(EXIT_FAILURE); } @@ -885,12 +926,23 @@ int main(int argc, char *argv[]) exit(EXIT_SUCCESS); break; case 'w': + case 'U': + case 'f': + ifile = &input_file[wr_num]; mode_write = 1; - if (get_two_words(optarg, &addr_str, &src_fname)) { - print_usage(argv[0]); - exit(EXIT_FAILURE); + 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); } - addr = strtol(optarg, NULL, 0); break; case 'x': mode_extract = 1; @@ -941,6 +993,13 @@ int main(int argc, char *argv[]) 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]; @@ -997,13 +1056,24 @@ int main(int argc, char *argv[]) } if (mode_write_descriptor) - ret = write_data(image, size, -size, src_fname); + ret = write_data(image, size, -size, desc_fname, 0, 0); if (mode_inject) - ret = inject_region(image, size, region_type, src_fname); - - if (mode_write) - ret = write_data(image, size, addr, src_fname); + 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); @@ -1035,5 +1105,5 @@ int main(int argc, char *argv[]) free(image); close(bios_fd); - return ret ? 1 : 0; + return ret < 0 ? 1 : 0; }