From 7e8ffa4ed8194e11c52830a7ea47e28f496c24d5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 14 Dec 2014 17:15:35 -0700 Subject: x86: ifdtool: Correct a debug() missing parameter This is missing a parameter. Fix it to avoid a warning when debug is enabled. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- tools/ifdtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools/ifdtool.c') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 4a27b82c2e0..4cdfdcc03e0 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -54,7 +54,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; } -- cgit v1.2.3 From fa8d3b00f9a1d0cdedcac3c26993f0b0230f2771 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 14 Dec 2014 17:15:36 -0700 Subject: x86: ifdtool: Display filename when file errors are reported When a file is missing it helps to know which file. Update the error message to print this information. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- tools/ifdtool.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'tools/ifdtool.c') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 4cdfdcc03e0..8afb6b5fe24 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -465,6 +465,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 * @@ -481,10 +491,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; @@ -586,14 +596,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); -- cgit v1.2.3 From 65851fcec305bae079b35e17103aa61c8ef54674 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 14 Dec 2014 17:15:37 -0700 Subject: x86: ifdtool: Use a structure for the file/address list Rather than two independent arrays, use a single array of a suitable structure. Also add a 'type' member since we will shortly add additional types. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- tools/ifdtool.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'tools/ifdtool.c') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 8afb6b5fe24..4077ba8b2ed 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -32,6 +32,16 @@ #define FLREG_BASE(reg) ((reg & 0x00000fff) << 12); #define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff); +enum input_file_type_t { + IF_normal, +}; + +struct input_file { + char *fname; + unsigned int addr; + enum input_file_type_t type; +}; + /** * find_fd() - Find the flash description in the ROM image * @@ -790,8 +800,7 @@ int main(int argc, char *argv[]) char *desc_fname = NULL, *addr_str = NULL; int region_type = -1, inputfreq = 0; enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ; - unsigned int addr[WRITE_MAX]; - char *wr_fname[WRITE_MAX]; + struct input_file input_file[WRITE_MAX], *ifile; unsigned char wr_idx, wr_num = 0; int rom_size = -1; bool write_it; @@ -895,14 +904,16 @@ int main(int argc, char *argv[]) exit(EXIT_SUCCESS); break; case 'w': + ifile = &input_file[wr_num]; mode_write = 1; if (wr_num < WRITE_MAX) { if (get_two_words(optarg, &addr_str, - &wr_fname[wr_num])) { + &ifile->fname)) { print_usage(argv[0]); exit(EXIT_FAILURE); } - addr[wr_num] = strtol(optarg, NULL, 0); + ifile->addr = strtol(optarg, NULL, 0); + ifile->type = IF_normal; wr_num++; } else { fprintf(stderr, @@ -1022,8 +1033,9 @@ int main(int argc, char *argv[]) if (mode_write) { for (wr_idx = 0; wr_idx < wr_num; wr_idx++) { - ret = write_data(image, size, - addr[wr_idx], wr_fname[wr_idx]); + ifile = &input_file[wr_idx]; + ret = write_data(image, size, ifile->addr, + ifile->fname); if (ret) break; } -- cgit v1.2.3 From 31eca697276ef9aced10b802a869e7783439482e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Dec 2014 22:02:38 -0700 Subject: x86: ifdtool: Add support for early microcode access Some Intel CPUs use an 'FSP' binary blob which provides an inflexible means of starting up the CPU. One result is that microcode updates can only be done before RAM is available and therefore parsing of the device tree is impracticle. Worse, the addess of the microcode update must be stored in ROM since a pointer to its start address and size is passed to the 'FSP' blob. It is not possible to perform any calculations to obtain the address and size. To work around this, ifdtool is enhanced to work out the address and size of the first microcode update it finds in the supplied device tree. It then writes these into the correct place in the ROM. U-Boot can then start up the FSP correctly. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- tools/ifdtool.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 8 deletions(-) (limited to 'tools/ifdtool.c') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 4077ba8b2ed..fe8366ba4f6 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "ifdtool.h" #undef DEBUG @@ -34,6 +35,8 @@ enum input_file_type_t { IF_normal, + IF_fdt, + IF_uboot, }; struct input_file { @@ -703,7 +706,7 @@ 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 + * @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) @@ -715,7 +718,7 @@ 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); debug("Writing %s to offset %#x\n", write_fname, offset); if (offset < 0 || offset + write_size > size) { @@ -731,6 +734,68 @@ static int write_data(char *image, int size, unsigned int addr, close(write_fd); + return write_size; +} + +/** + * write_uboot() - Write U-Boot, device tree and microcode pointer + * + * This writes U-Boot into a place in the flash, followed by its device tree. + * The microcode pointer is written so that U-Boot can find the microcode in + * the device tree very early in boot. + * + * @image: Pointer to image + * @size: Size of image in bytes + * @uboot: Input file information for u-boot.bin + * @fdt: Input file information for u-boot.dtb + * @ucode_ptr: Address in U-Boot where the microcode pointer should be placed + * @return 0 if OK, -ve on error + */ +static int write_uboot(char *image, int size, struct input_file *uboot, + struct input_file *fdt, unsigned int ucode_ptr) +{ + const void *blob; + const char *data; + int uboot_size; + uint32_t *ptr; + int data_size; + int offset; + int node; + int ret; + + uboot_size = write_data(image, size, uboot->addr, uboot->fname); + if (uboot_size < 0) + return uboot_size; + fdt->addr = uboot->addr + uboot_size; + debug("U-Boot size %#x, FDT at %#x\n", uboot_size, fdt->addr); + ret = write_data(image, size, fdt->addr, fdt->fname); + if (ret < 0) + return ret; + + if (ucode_ptr) { + blob = (void *)image + (uint32_t)(fdt->addr + size); + debug("DTB at %lx\n", (char *)blob - image); + node = fdt_node_offset_by_compatible(blob, 0, + "intel,microcode"); + if (node < 0) { + debug("No microcode found in FDT: %s\n", + fdt_strerror(node)); + return -ENOENT; + } + data = fdt_getprop(blob, node, "data", &data_size); + if (!data) { + debug("No microcode data found in FDT: %s\n", + fdt_strerror(data_size)); + return -ENOENT; + } + offset = ucode_ptr - uboot->addr; + ptr = (void *)image + offset; + ptr[0] = uboot->addr + (data - image); + ptr[1] = data_size; + debug("Wrote microcode pointer at %x: addr=%x, size=%x\n", + ucode_ptr, ptr[0], ptr[1]); + } + return 0; } @@ -800,7 +865,7 @@ int main(int argc, char *argv[]) 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; + struct input_file input_file[WRITE_MAX], *ifile, *fdt = NULL; unsigned char wr_idx, wr_num = 0; int rom_size = -1; bool write_it; @@ -808,6 +873,8 @@ int main(int argc, char *argv[]) char *outfile = NULL; struct stat buf; int size = 0; + unsigned int ucode_ptr = 0; + bool have_uboot = false; int bios_fd; char *image; int ret; @@ -817,18 +884,21 @@ 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'}, + {"microcode", 1, NULL, 'm'}, {"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:lm:r:s:uU:vw:x?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': @@ -871,6 +941,9 @@ int main(int argc, char *argv[]) case 'l': mode_locked = 1; break; + case 'm': + ucode_ptr = strtoul(optarg, NULL, 0); + break; case 'r': rom_size = strtol(optarg, NULL, 0); debug("ROM size %d\n", rom_size); @@ -904,6 +977,8 @@ 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 (wr_num < WRITE_MAX) { @@ -913,7 +988,12 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } ifile->addr = strtol(optarg, NULL, 0); - ifile->type = IF_normal; + ifile->type = opt == 'f' ? IF_fdt : + opt == 'U' ? IF_uboot : IF_normal; + if (ifile->type == IF_fdt) + fdt = ifile; + else if (ifile->type == IF_uboot) + have_uboot = true; wr_num++; } else { fprintf(stderr, @@ -970,6 +1050,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]; @@ -1034,9 +1121,16 @@ int main(int argc, char *argv[]) if (mode_write) { for (wr_idx = 0; wr_idx < wr_num; wr_idx++) { ifile = &input_file[wr_idx]; - ret = write_data(image, size, ifile->addr, + if (ifile->type == IF_fdt) { + continue; + } else if (ifile->type == IF_uboot) { + ret = write_uboot(image, size, ifile, fdt, + ucode_ptr); + } else { + ret = write_data(image, size, ifile->addr, ifile->fname); - if (ret) + } + if (ret < 0) break; } } @@ -1071,5 +1165,5 @@ int main(int argc, char *argv[]) free(image); close(bios_fd); - return ret ? 1 : 0; + return ret < 0 ? 1 : 0; } -- cgit v1.2.3