diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | tools/ifdtool.c | 65 |
2 files changed, 56 insertions, 10 deletions
@@ -1040,6 +1040,7 @@ IFDTOOL_FLAGS = -f 0:$(objtree)/u-boot.dtb IFDTOOL_FLAGS += -m 0x$(shell $(NM) u-boot |grep _dt_ucode_base_size |cut -d' ' -f1) IFDTOOL_FLAGS += -U $(CONFIG_SYS_TEXT_BASE):$(objtree)/u-boot.bin IFDTOOL_FLAGS += -w $(CONFIG_SYS_X86_START16):$(objtree)/u-boot-x86-16bit.bin +IFDTOOL_FLAGS += -C ifneq ($(CONFIG_HAVE_INTEL_ME),) IFDTOOL_ME_FLAGS = -D $(srctree)/board/$(BOARDDIR)/descriptor.bin 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, |