summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--tools/ifdtool.c65
2 files changed, 56 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index 9919314f0a..7b8efea231 100644
--- a/Makefile
+++ b/Makefile
@@ -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 b794516189..d966c563da 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,
OpenPOWER on IntegriCloud