diff options
-rw-r--r-- | tools/ifdtool.c | 254 |
1 files changed, 5 insertions, 249 deletions
diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 48059c0..195b153 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -33,16 +33,9 @@ #define FLREG_BASE(reg) ((reg & 0x00000fff) << 12); #define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff); -enum input_file_type_t { - IF_normal, - IF_fdt, - IF_uboot, -}; - struct input_file { char *fname; unsigned int addr; - enum input_file_type_t type; }; /** @@ -760,219 +753,6 @@ 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; - } - - if (ucode_base) - memcpy(ucode, data, data_size); - ucode += data_size; - } - - if (countp) - *countp = count; - if (datap) - *datap = data; - if (data_sizep) - *data_sizep = data_size; - - 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) -{ - 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); - - 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 && !collate_ucode) { - fprintf(stderr, - "Cannot handle multiple microcode blocks - please use -C flag to collate them\n"); - return -EMLINK; - } - - /* - * 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); - 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; - - /* 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 - * 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; - - 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 (collate_ucode ? data + data_size : (char *)blob + fdt_size) - - image; -} - -/** - * 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, - int collate_ucode, int *offset_uboot_top, - int *offset_uboot_start) -{ - int uboot_size, fdt_size; - int uboot_top; - - uboot_size = write_data(image, size, uboot->addr, uboot->fname, 0, 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); - fdt_size = write_data(image, size, fdt->addr, fdt->fname, 0, 0); - if (fdt_size < 0) - return fdt_size; - - uboot_top = (uint32_t)(fdt->addr + size) + fdt_size; - - if (ucode_ptr) { - uboot_top = write_ucode(image, size, fdt, fdt_size, ucode_ptr, - collate_ucode); - if (uboot_top < 0) - return uboot_top; - } - - if (offset_uboot_top && offset_uboot_start) { - *offset_uboot_top = uboot_top; - *offset_uboot_start = (uint32_t)(uboot->addr + size); - } - - return 0; -} - static void print_version(void) { printf("ifdtool v%s -- ", IFDTOOL_VERSION); @@ -1034,7 +814,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, collate_ucode = 0; + int create = 0; char *region_type_string = NULL, *inject_fname = NULL; char *desc_fname = NULL, *addr_str = NULL; int region_type = -1, inputfreq = 0; @@ -1047,14 +827,12 @@ 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; 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'}, @@ -1062,7 +840,6 @@ int main(int argc, char *argv[]) {"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'}, @@ -1073,15 +850,12 @@ int main(int argc, char *argv[]) {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "cCdD:ef:hi:lm:r:s:uU:vw:x?", + while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lr: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; @@ -1119,9 +893,6 @@ 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); @@ -1166,12 +937,6 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } ifile->addr = strtoll(optarg, NULL, 0); - 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, @@ -1302,18 +1067,9 @@ int main(int argc, char *argv[]) for (wr_idx = 0; wr_idx < wr_num; wr_idx++) { ifile = &input_file[wr_idx]; - if (ifile->type == IF_fdt) { - continue; - } else if (ifile->type == IF_uboot) { - ret = write_uboot(image, size, ifile, fdt, - ucode_ptr, collate_ucode, - &offset_uboot_top, - &offset_uboot_start); - } else { - ret = write_data(image, size, ifile->addr, - ifile->fname, offset_uboot_top, - offset_uboot_start); - } + ret = write_data(image, size, ifile->addr, + ifile->fname, offset_uboot_top, + offset_uboot_start); if (ret < 0) break; } |