From 3c7aab23a42264012d82937dd2a57e33ee288a92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Aug 2015 14:37:51 -0600 Subject: x86: ifdtool: Check that U-Boot does not overlap other regions Since U-Boot and its device tree can grow we should check that it does not overlap the regions above it. Track the ROM offset that U-Boot reaches and check that other regions (written after U-Boot) do not interfere. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- tools/ifdtool.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'tools') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index df16616..510a99c 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -706,10 +706,11 @@ 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 + * @offset_uboot_top: Offset of the top 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 write_fd, write_size; int offset; @@ -719,6 +720,14 @@ static int write_data(char *image, int size, unsigned int addr, return write_fd; offset = (uint32_t)(addr + size); + if (offset_uboot_top && 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; + } debug("Writing %s to offset %#x\n", write_fname, offset); if (offset < 0 || offset + write_size > size) { @@ -756,24 +765,23 @@ static int write_uboot(char *image, int size, struct input_file *uboot, { const void *blob; const char *data; - int uboot_size; + int uboot_size, fdt_size; uint32_t *ptr; int data_size; int offset; int node; - int ret; - uboot_size = write_data(image, size, uboot->addr, uboot->fname); + uboot_size = write_data(image, size, uboot->addr, uboot->fname, 0); 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; + fdt_size = write_data(image, size, fdt->addr, fdt->fname, 0); + if (fdt_size < 0) + return fdt_size; + blob = (void *)image + (uint32_t)(fdt->addr + size); 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"); @@ -796,7 +804,7 @@ static int write_uboot(char *image, int size, struct input_file *uboot, ucode_ptr, ptr[0], ptr[1]); } - return 0; + return ((char *)blob + fdt_size) - image; } static void print_version(void) @@ -1113,12 +1121,14 @@ int main(int argc, char *argv[]) } if (mode_write_descriptor) - ret = write_data(image, size, -size, desc_fname); + ret = write_data(image, size, -size, desc_fname, 0); if (mode_inject) ret = inject_region(image, size, region_type, inject_fname); if (mode_write) { + int offset_uboot_top = 0; + for (wr_idx = 0; wr_idx < wr_num; wr_idx++) { ifile = &input_file[wr_idx]; if (ifile->type == IF_fdt) { @@ -1126,9 +1136,10 @@ int main(int argc, char *argv[]) } else if (ifile->type == IF_uboot) { ret = write_uboot(image, size, ifile, fdt, ucode_ptr); + offset_uboot_top = ret; } else { ret = write_data(image, size, ifile->addr, - ifile->fname); + ifile->fname, offset_uboot_top); } if (ret < 0) break; -- cgit v1.1 From 88cf322e44b85a0e17ce5a5514eff85e7df78dc6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Aug 2015 14:37:52 -0600 Subject: x86: ifdtool: Split microcode linking into its own function The code to set up the microcode pointer in the ROM shares almost nothing with the write_uboot() function. Move it into its own function so it will be easier to extend. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- tools/ifdtool.c | 105 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 27 deletions(-) (limited to 'tools') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 510a99c..b794516 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -746,6 +746,82 @@ static int write_data(char *image, int size, unsigned int addr, return write_size; } +static int scan_ucode(const void *blob, char *ucode_base, int *countp, + const char **datap, int *data_sizep) +{ + const char *data = NULL; + int node, count; + int data_size; + char *ucode; + + for (node = 0, count = 0, ucode = ucode_base; node >= 0; count++) { + node = fdt_node_offset_by_compatible(blob, node, + "intel,microcode"); + if (node < 0) + break; + + data = fdt_getprop(blob, node, "data", &data_size); + if (!data) { + debug("Missing microcode data in FDT '%s': %s\n", + fdt_get_name(blob, node, NULL), + fdt_strerror(data_size)); + return -ENOENT; + } + + ucode += data_size; + } + + if (countp) + *countp = count; + if (datap) + *datap = data; + if (data_sizep) + *data_sizep = data_size; + + return ucode - ucode_base; +} + +static int write_ucode(char *image, int size, struct input_file *fdt, + int fdt_size, unsigned int ucode_ptr) +{ + const char *data = NULL; + const void *blob; + uint32_t *ptr; + int ucode_size; + int data_size; + int offset; + int count; + + blob = (void *)image + (uint32_t)(fdt->addr + size); + + debug("DTB at %lx\n", (char *)blob - image); + + /* Find out about the micrcode we have */ + ucode_size = scan_ucode(blob, NULL, &count, &data, &data_size); + if (ucode_size < 0) + return ucode_size; + if (!count) { + debug("No microcode found in FDT\n"); + return -ENOENT; + } + + if (count > 1) { + fprintf(stderr, + "Cannot handle multiple microcode blocks\n"); + return -EMLINK; + } + + offset = (uint32_t)(ucode_ptr + size); + ptr = (void *)image + offset; + + ptr[0] = (data - image) - size; + ptr[1] = data_size; + debug("Wrote microcode pointer at %x: addr=%x, size=%x\n", ucode_ptr, + ptr[0], ptr[1]); + + return 0; +} + /** * write_uboot() - Write U-Boot, device tree and microcode pointer * @@ -764,12 +840,7 @@ 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, fdt_size; - uint32_t *ptr; - int data_size; - int offset; - int node; uboot_size = write_data(image, size, uboot->addr, uboot->fname, 0); if (uboot_size < 0) @@ -781,28 +852,8 @@ static int write_uboot(char *image, int size, struct input_file *uboot, return fdt_size; blob = (void *)image + (uint32_t)(fdt->addr + size); - if (ucode_ptr) { - 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 = (uint32_t)(ucode_ptr + size); - ptr = (void *)image + offset; - ptr[0] = (data - image) - size; - ptr[1] = data_size; - debug("Wrote microcode pointer at %x: addr=%x, size=%x\n", - ucode_ptr, ptr[0], ptr[1]); - } + if (ucode_ptr) + return write_ucode(image, size, fdt, fdt_size, ucode_ptr); return ((char *)blob + fdt_size) - image; } -- cgit v1.1 From b098032387a6ba1cab181a897075932f7fa2a58d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Aug 2015 14:37:53 -0600 Subject: x86: ifdtool: Support collating microcode into one place The Intel Firmware Support Package (FSP) requires that microcode be provided very early before the device tree can be scanned. We already support adding a pointer to the microcode data in a place where early init code can access. However this just points into the device tree and can only point to a single lot of microcode. For boards which may have different CPU types we must support multiple microcodes and pass all of them to the FSP in one place. Enhance ifdtool to scan all the microcode, place it together in the ROM and update the microcode pointer to point there. This allows us to pass multiple microcode blocks to the FSP using its existing API. Enable the flag in the Makefile so that this feature is used by default for all boards. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- tools/ifdtool.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index b794516..d966c56 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -768,6 +768,8 @@ static int scan_ucode(const void *blob, char *ucode_base, int *countp, return -ENOENT; } + if (ucode_base) + memcpy(ucode, data, data_size); ucode += data_size; } @@ -782,15 +784,19 @@ static int scan_ucode(const void *blob, char *ucode_base, int *countp, } static int write_ucode(char *image, int size, struct input_file *fdt, - int fdt_size, unsigned int ucode_ptr) + int fdt_size, unsigned int ucode_ptr, + int collate_ucode) { const char *data = NULL; + char *ucode_buf; const void *blob; + char *ucode_base; uint32_t *ptr; int ucode_size; int data_size; int offset; int count; + int ret; blob = (void *)image + (uint32_t)(fdt->addr + size); @@ -805,12 +811,43 @@ static int write_ucode(char *image, int size, struct input_file *fdt, return -ENOENT; } - if (count > 1) { + if (count > 1 && !collate_ucode) { fprintf(stderr, - "Cannot handle multiple microcode blocks\n"); + "Cannot handle multiple microcode blocks - please use -C flag to collate them\n"); return -EMLINK; } + /* + * Collect the microcode into a buffer and place it immediately above + * the device tree. + */ + if (collate_ucode && count > 1) { + ucode_buf = malloc(ucode_size); + if (!ucode_buf) { + fprintf(stderr, + "Out of memory for microcode (%d bytes)\n", + ucode_size); + return -ENOMEM; + } + ret = scan_ucode(blob, ucode_buf, NULL, NULL, NULL); + if (ret < 0) + return ret; + + debug("Collated %d microcode block(s)\n", count); + + /* + * Place microcode area immediately above the FDT, aligned + * to a 16-byte boundary. + */ + ucode_base = (char *)(((unsigned long)blob + fdt_size + 15) & + ~15); + + data = ucode_base; + data_size = ucode_size; + memcpy(ucode_base, ucode_buf, ucode_size); + free(ucode_buf); + } + offset = (uint32_t)(ucode_ptr + size); ptr = (void *)image + offset; @@ -819,7 +856,8 @@ static int write_ucode(char *image, int size, struct input_file *fdt, debug("Wrote microcode pointer at %x: addr=%x, size=%x\n", ucode_ptr, ptr[0], ptr[1]); - return 0; + return (collate_ucode ? data + data_size : (char *)blob + fdt_size) - + image; } /** @@ -837,7 +875,8 @@ static int write_ucode(char *image, int size, struct input_file *fdt, * @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) + struct input_file *fdt, unsigned int ucode_ptr, + int collate_ucode) { const void *blob; int uboot_size, fdt_size; @@ -852,8 +891,10 @@ static int write_uboot(char *image, int size, struct input_file *uboot, return fdt_size; blob = (void *)image + (uint32_t)(fdt->addr + size); - if (ucode_ptr) - return write_ucode(image, size, fdt, fdt_size, ucode_ptr); + if (ucode_ptr) { + return write_ucode(image, size, fdt, fdt_size, ucode_ptr, + collate_ucode); + } return ((char *)blob + fdt_size) - image; } @@ -919,7 +960,7 @@ int main(int argc, char *argv[]) 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; + int create = 0, collate_ucode = 0; char *region_type_string = NULL, *inject_fname = NULL; char *desc_fname = NULL, *addr_str = NULL; int region_type = -1, inputfreq = 0; @@ -939,6 +980,7 @@ int main(int argc, char *argv[]) int ret; static struct option long_options[] = { {"create", 0, NULL, 'c'}, + {"collate-microcode", 0, NULL, 'C'}, {"dump", 0, NULL, 'd'}, {"descriptor", 1, NULL, 'D'}, {"em100", 0, NULL, 'e'}, @@ -957,12 +999,15 @@ int main(int argc, char *argv[]) {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lm:r:s:uU:vw:x?", + while ((opt = getopt_long(argc, argv, "cCdD:ef:hi:lm:r:s:uU:vw:x?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': create = 1; break; + case 'C': + collate_ucode = 1; + break; case 'd': mode_dump = 1; break; @@ -1186,7 +1231,7 @@ int main(int argc, char *argv[]) continue; } else if (ifile->type == IF_uboot) { ret = write_uboot(image, size, ifile, fdt, - ucode_ptr); + ucode_ptr, collate_ucode); offset_uboot_top = ret; } else { ret = write_data(image, size, ifile->addr, -- cgit v1.1 From f86f0c1897436e03b0e68874a56b257080d01386 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Aug 2015 14:37:54 -0600 Subject: x86: ifdtool: Drop microcode from the device tree when collating When ifdtool collates the microcode into one place it effectively creates a copy of the 'data' properties in the device tree microcode nodes. This is wasteful since we now have two copies of the microcode in the ROM. To avoid this, remove the microcode data from the device tree and shrink it down. This means that there is only one copy and the overall ROM space used by the microcode does not increase. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- tools/ifdtool.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/ifdtool.c b/tools/ifdtool.c index d966c56..1f95203 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -783,6 +783,47 @@ static int scan_ucode(const void *blob, char *ucode_base, int *countp, return ucode - ucode_base; } +static int remove_ucode(char *blob) +{ + int node, count; + int ret; + + /* Keep going until we find no more microcode to remove */ + do { + for (node = 0, count = 0; node >= 0;) { + int ret; + + node = fdt_node_offset_by_compatible(blob, node, + "intel,microcode"); + if (node < 0) + break; + + ret = fdt_delprop(blob, node, "data"); + + /* + * -FDT_ERR_NOTFOUND means we already removed the + * data for this one, so we just continue. + * 0 means we did remove it, so offsets may have + * changed and we need to restart our scan. + * Anything else indicates an error we should report. + */ + if (ret == -FDT_ERR_NOTFOUND) + continue; + else if (!ret) + node = 0; + else + return ret; + } + } while (count); + + /* Pack down to remove excees space */ + ret = fdt_pack(blob); + if (ret) + return ret; + + return fdt_totalsize(blob); +} + static int write_ucode(char *image, int size, struct input_file *fdt, int fdt_size, unsigned int ucode_ptr, int collate_ucode) @@ -818,8 +859,8 @@ static int write_ucode(char *image, int size, struct input_file *fdt, } /* - * Collect the microcode into a buffer and place it immediately above - * the device tree. + * Collect the microcode into a buffer, remove it from the device + * tree and place it immediately above the (now smaller) device tree. */ if (collate_ucode && count > 1) { ucode_buf = malloc(ucode_size); @@ -833,7 +874,17 @@ static int write_ucode(char *image, int size, struct input_file *fdt, if (ret < 0) return ret; + /* Remove the microcode from the device tree */ + ret = remove_ucode((char *)blob); + if (ret < 0) { + debug("Could not remove FDT microcode: %s\n", + fdt_strerror(ret)); + return -EINVAL; + } debug("Collated %d microcode block(s)\n", count); + debug("Device tree reduced from %x to %x bytes\n", + fdt_size, ret); + fdt_size = ret; /* * Place microcode area immediately above the FDT, aligned -- cgit v1.1 From 19b4a3369876f9215e2b861f211e8df1a75e26ca Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 18 Aug 2015 11:30:29 +0900 Subject: patman: use -D option for git format-patch This allows Patman to generate smaller patches for file removal. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass Acked-by: Heiko Schocher --- tools/patman/gitutil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index 9e739d8..67b086b 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -264,7 +264,7 @@ def CreatePatches(start, count, series): """ if series.get('version'): version = '%s ' % series['version'] - cmd = ['git', 'format-patch', '-M', '--signoff'] + cmd = ['git', 'format-patch', '-D', '-M', '--signoff'] if series.get('cover'): cmd.append('--cover-letter') prefix = series.GetPatchPrefix() -- cgit v1.1