diff --git a/src/arch/arm64/fit_payload.c b/src/arch/arm64/fit_payload.c index c4bbceee4c..fd1bae171a 100644 --- a/src/arch/arm64/fit_payload.c +++ b/src/arch/arm64/fit_payload.c @@ -184,20 +184,14 @@ bool fit_payload_arch(struct prog *payload, struct fit_config_node *config, bool place_anywhere; void *arg = NULL; - if (!config->fdt || !fdt) { - printk(BIOS_CRIT, "CRIT: Providing a valid FDT is mandatory to " - "boot an ARM64 kernel!\n"); - return false; - } - - if (!decompress_kernel_header(config->kernel_node)) { + if (!decompress_kernel_header(config->kernel)) { printk(BIOS_CRIT, "CRIT: Payload doesn't look like an ARM64" " kernel Image.\n"); return false; } /* Update kernel size from image header, if possible */ - kernel->size = get_kernel_size(config->kernel_node); + kernel->size = get_kernel_size(config->kernel); printk(BIOS_DEBUG, "FIT: Using kernel size of 0x%zx bytes\n", kernel->size); diff --git a/src/include/fit.h b/src/include/fit.h index 6e0667f6cf..758ee70c9c 100644 --- a/src/include/fit.h +++ b/src/include/fit.h @@ -27,7 +27,7 @@ struct fit_image_node { const char *name; - const void *data; + void *data; uint32_t size; int compression; @@ -37,12 +37,9 @@ struct fit_image_node struct fit_config_node { const char *name; - const char *kernel; - struct fit_image_node *kernel_node; - const char *fdt; - struct fit_image_node *fdt_node; - const char *ramdisk; - struct fit_image_node *ramdisk_node; + struct fit_image_node *kernel; + struct fit_image_node *fdt; + struct fit_image_node *ramdisk; struct fdt_property compat; int compat_rank; int compat_pos; diff --git a/src/lib/fit.c b/src/lib/fit.c index c98ba2f802..5fbcd77407 100644 --- a/src/lib/fit.c +++ b/src/lib/fit.c @@ -85,6 +85,17 @@ static void fit_add_default_compat_strings(void) fit_add_compat_string(compat_string); } +static struct fit_image_node *find_image(const char *name) +{ + struct fit_image_node *image; + list_for_each(image, image_nodes, list_node) { + if (!strcmp(image->name, name)) + return image; + } + printk(BIOS_ERR, "ERROR: Cannot find image node %s!\n", name); + return NULL; +} + static void image_node(struct device_tree_node *node) { struct fit_image_node *image = xzalloc(sizeof(*image)); @@ -120,11 +131,11 @@ static void config_node(struct device_tree_node *node) struct device_tree_property *prop; list_for_each(prop, node->properties, list_node) { if (!strcmp("kernel", prop->prop.name)) - config->kernel = prop->prop.data; + config->kernel = find_image(prop->prop.data); else if (!strcmp("fdt", prop->prop.name)) - config->fdt = prop->prop.data; + config->fdt = find_image(prop->prop.data); else if (!strcmp("ramdisk", prop->prop.name)) - config->ramdisk = prop->prop.data; + config->ramdisk = find_image(prop->prop.data); } list_insert_after(&config->list_node, &config_nodes); @@ -132,40 +143,22 @@ static void config_node(struct device_tree_node *node) static void fit_unpack(struct device_tree *tree, const char **default_config) { - assert(tree && tree->root); + struct device_tree_node *child; + struct device_tree_node *images = dt_find_node_by_path(tree, "/images", + NULL, NULL, 0); + if (images) + list_for_each(child, images->children, list_node) + image_node(child); - struct device_tree_node *top; - list_for_each(top, tree->root->children, list_node) { - struct device_tree_node *child; - if (!strcmp("images", top->name)) { - - list_for_each(child, top->children, list_node) - image_node(child); - - } else if (!strcmp("configurations", top->name)) { - struct device_tree_property *prop; - list_for_each(prop, top->properties, list_node) { - if (!strcmp("default", prop->prop.name) && - default_config) - *default_config = prop->prop.data; - } - - list_for_each(child, top->children, list_node) - config_node(child); - } + struct device_tree_node *configs = dt_find_node_by_path(tree, + "/configurations", NULL, NULL, 0); + if (configs) { + *default_config = dt_find_string_prop(configs, "default"); + list_for_each(child, configs->children, list_node) + config_node(child); } } -static struct fit_image_node *find_image(const char *name) -{ - struct fit_image_node *image; - list_for_each(image, image_nodes, list_node) { - if (!strcmp(image->name, name)) - return image; - } - return NULL; -} - static int fdt_find_compat(const void *blob, uint32_t start_offset, struct fdt_property *prop) { @@ -393,18 +386,27 @@ void fit_update_memory(struct device_tree *tree) /* * Finds a compat string and updates the compat position and rank. - * @param fdt_blob Pointer to FDT * @param config The current config node to operate on + * @return 0 if compat updated, -1 if this FDT cannot be used. */ -static void fit_update_compat(const void *fdt_blob, - struct fit_config_node *config) +static int fit_update_compat(struct fit_config_node *config) { + if (config->fdt->compression != CBFS_COMPRESS_NONE) { + printk(BIOS_ERR, + "FDT compression not yet supported, skipping %s.\n", + config->name); + return -1; + } + + void *fdt_blob = config->fdt->data; struct compat_string_entry *compat_node; const struct fdt_header *fdt_header = (const struct fdt_header *)fdt_blob; uint32_t fdt_offset = be32_to_cpu(fdt_header->structure_offset); size_t i = 0; + config->compat_pos = -1; + config->compat_rank = -1; if (!fdt_find_compat(fdt_blob, fdt_offset, &config->compat)) { list_for_each(compat_node, compat_strings, list_node) { int pos = fit_check_compat(&config->compat, @@ -419,6 +421,8 @@ static void fit_update_compat(const void *fdt_blob, i++; } } + + return 0; } struct fit_config_node *fit_load(void *fit) @@ -457,55 +461,41 @@ struct fit_config_node *fit_load(void *fit) printk(BIOS_DEBUG, "\n"); /* Process and list the configs. */ list_for_each(config, config_nodes, list_node) { - if (config->kernel) - config->kernel_node = find_image(config->kernel); - if (config->fdt) - config->fdt_node = find_image(config->fdt); - if (config->ramdisk) - config->ramdisk_node = find_image(config->ramdisk); + if (!config->kernel) { + printk(BIOS_ERR, + "ERROR: config %s has no kernel, skipping.\n", + config->name); + continue; + } + if (!config->fdt) { + printk(BIOS_ERR, + "ERROR: config %s has no FDT, skipping.\n", + config->name); + continue; + } - if (config->ramdisk_node && - config->ramdisk_node->compression < 0) { + if (config->ramdisk && + config->ramdisk->compression < 0) { printk(BIOS_WARNING, "WARN: Ramdisk is compressed with " "an unsupported algorithm, discarding config %s." "\n", config->name); - list_remove(&config->list_node); continue; } - if (!config->kernel_node || - (config->fdt && !config->fdt_node)) { - printk(BIOS_DEBUG, "FIT: Missing image, discarding " - "config %s.\n", config->name); - list_remove(&config->list_node); + if (fit_update_compat(config)) continue; - } - if (config->fdt_node) { - if (config->fdt_node->compression != - CBFS_COMPRESS_NONE) { - printk(BIOS_DEBUG, - "FIT: FDT compression not yet supported," - " skipping config %s.\n", config->name); - list_remove(&config->list_node); - continue; - } - - config->compat_pos = -1; - config->compat_rank = -1; - - fit_update_compat(config->fdt_node->data, config); - } printk(BIOS_DEBUG, "FIT: config %s", config->name); if (default_config_name && !strcmp(config->name, default_config_name)) { printk(BIOS_DEBUG, " (default)"); default_config = config; } - if (config->fdt) - printk(BIOS_DEBUG, ", fdt %s", config->fdt); + printk(BIOS_DEBUG, ", kernel %s", config->kernel->name); + printk(BIOS_DEBUG, ", fdt %s", config->fdt->name); if (config->ramdisk) - printk(BIOS_DEBUG, ", ramdisk %s", config->ramdisk); + printk(BIOS_DEBUG, ", ramdisk %s", + config->ramdisk->name); if (config->compat.name) { printk(BIOS_DEBUG, ", compat"); int bytes = config->compat.size; diff --git a/src/lib/fit_payload.c b/src/lib/fit_payload.c index e0158f2129..4bc6622b19 100644 --- a/src/lib/fit_payload.c +++ b/src/lib/fit_payload.c @@ -176,37 +176,34 @@ void fit_payload(struct prog *payload) struct fit_config_node *config = fit_load(data); - if (!config || !config->kernel_node) { + if (!config) { printk(BIOS_ERR, "ERROR: Could not load FIT\n"); rdev_munmap(prog_rdev(payload), data); return; } - if (config->fdt_node) { - dt = fdt_unflatten(config->fdt_node->data); - if (!dt) { - printk(BIOS_ERR, - "ERROR: Failed to unflatten the FDT.\n"); - rdev_munmap(prog_rdev(payload), data); - return; - } - - dt_apply_fixups(dt); - - /* Insert coreboot specific information */ - add_cb_fdt_data(dt); - - /* Update device_tree */ -#if defined(CONFIG_LINUX_COMMAND_LINE) - fit_update_chosen(dt, (char *)CONFIG_LINUX_COMMAND_LINE); -#endif - fit_update_memory(dt); + dt = fdt_unflatten(config->fdt->data); + if (!dt) { + printk(BIOS_ERR, "ERROR: Failed to unflatten the FDT.\n"); + rdev_munmap(prog_rdev(payload), data); + return; } + dt_apply_fixups(dt); + + /* Insert coreboot specific information */ + add_cb_fdt_data(dt); + + /* Update device_tree */ +#if defined(CONFIG_LINUX_COMMAND_LINE) + fit_update_chosen(dt, (char *)CONFIG_LINUX_COMMAND_LINE); +#endif + fit_update_memory(dt); + /* Collect infos for fit_payload_arch */ - kernel.size = config->kernel_node->size; + kernel.size = config->kernel->size; fdt.size = dt ? dt_flat_size(dt) : 0; - initrd.size = config->ramdisk_node ? config->ramdisk_node->size : 0; + initrd.size = config->ramdisk ? config->ramdisk->size : 0; /* Invoke arch specific payload placement and fixups */ if (!fit_payload_arch(payload, config, &kernel, &fdt, &initrd)) { @@ -216,17 +213,15 @@ void fit_payload(struct prog *payload) return; } - /* Load the images to given position */ - if (config->fdt_node) { - /* Update device_tree */ - if (config->ramdisk_node) - fit_add_ramdisk(dt, (void *)initrd.offset, initrd.size); + /* Update ramdisk location in FDT */ + if (config->ramdisk) + fit_add_ramdisk(dt, (void *)initrd.offset, initrd.size); - pack_fdt(&fdt, dt); - } + /* Repack FDT for handoff to kernel */ + pack_fdt(&fdt, dt); - if (config->ramdisk_node && - extract(&initrd, config->ramdisk_node)) { + if (config->ramdisk && + extract(&initrd, config->ramdisk)) { printk(BIOS_ERR, "ERROR: Failed to extract initrd\n"); prog_set_entry(payload, NULL, NULL); rdev_munmap(prog_rdev(payload), data); @@ -235,7 +230,7 @@ void fit_payload(struct prog *payload) timestamp_add_now(TS_KERNEL_DECOMPRESSION); - if (extract(&kernel, config->kernel_node)) { + if (extract(&kernel, config->kernel)) { printk(BIOS_ERR, "ERROR: Failed to extract kernel\n"); prog_set_entry(payload, NULL, NULL); rdev_munmap(prog_rdev(payload), data);