#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;
};
/**
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);
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;
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'},
{"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'},
{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;
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);
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,
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;
}