mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-28 23:50:26 +09:00
fit: Introduce methods for applying overlays on fit-load
Introduce an overlay based method for constructing a base DT blob to pass to the kernel. It is based on a specific method now to get the FDT from a FIT image named boot_get_fdt_fit(). Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com> Acked-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
7c3dc776b9
commit
169043d826
@ -356,17 +356,16 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
|
|||||||
if (fit_check_format(buf)) {
|
if (fit_check_format(buf)) {
|
||||||
ulong load, len;
|
ulong load, len;
|
||||||
|
|
||||||
fdt_noffset = fit_image_load(images,
|
fdt_noffset = boot_get_fdt_fit(images,
|
||||||
fdt_addr, &fit_uname_fdt,
|
fdt_addr, &fit_uname_fdt,
|
||||||
&fit_uname_config,
|
&fit_uname_config,
|
||||||
arch, IH_TYPE_FLATDT,
|
arch, &load, &len);
|
||||||
BOOTSTAGE_ID_FIT_FDT_START,
|
|
||||||
FIT_LOAD_OPTIONAL, &load, &len);
|
|
||||||
|
|
||||||
images->fit_hdr_fdt = map_sysmem(fdt_addr, 0);
|
images->fit_hdr_fdt = map_sysmem(fdt_addr, 0);
|
||||||
images->fit_uname_fdt = fit_uname_fdt;
|
images->fit_uname_fdt = fit_uname_fdt;
|
||||||
images->fit_noffset_fdt = fdt_noffset;
|
images->fit_noffset_fdt = fdt_noffset;
|
||||||
fdt_addr = load;
|
fdt_addr = load;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <mapmem.h>
|
#include <mapmem.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <malloc.h>
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
#endif /* !USE_HOSTCC*/
|
#endif /* !USE_HOSTCC*/
|
||||||
|
|
||||||
@ -434,6 +435,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
|
|||||||
printf("0x%08lx\n", load);
|
printf("0x%08lx\n", load);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* optional load address for FDT */
|
||||||
|
if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load))
|
||||||
|
printf("%s Load Address: 0x%08lx\n", p, load);
|
||||||
|
|
||||||
if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
|
if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
|
||||||
(type == IH_TYPE_RAMDISK)) {
|
(type == IH_TYPE_RAMDISK)) {
|
||||||
ret = fit_image_get_entry(fit, image_noffset, &entry);
|
ret = fit_image_get_entry(fit, image_noffset, &entry);
|
||||||
@ -1454,6 +1459,8 @@ int fit_conf_get_node(const void *fit, const char *conf_uname)
|
|||||||
{
|
{
|
||||||
int noffset, confs_noffset;
|
int noffset, confs_noffset;
|
||||||
int len;
|
int len;
|
||||||
|
const char *s;
|
||||||
|
char *conf_uname_copy = NULL;
|
||||||
|
|
||||||
confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
|
confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
|
||||||
if (confs_noffset < 0) {
|
if (confs_noffset < 0) {
|
||||||
@ -1475,12 +1482,29 @@ int fit_conf_get_node(const void *fit, const char *conf_uname)
|
|||||||
debug("Found default configuration: '%s'\n", conf_uname);
|
debug("Found default configuration: '%s'\n", conf_uname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s = strchr(conf_uname, '#');
|
||||||
|
if (s) {
|
||||||
|
len = s - conf_uname;
|
||||||
|
conf_uname_copy = malloc(len + 1);
|
||||||
|
if (!conf_uname_copy) {
|
||||||
|
debug("Can't allocate uname copy: '%s'\n",
|
||||||
|
conf_uname);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memcpy(conf_uname_copy, conf_uname, len);
|
||||||
|
conf_uname_copy[len] = '\0';
|
||||||
|
conf_uname = conf_uname_copy;
|
||||||
|
}
|
||||||
|
|
||||||
noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
|
noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
|
||||||
if (noffset < 0) {
|
if (noffset < 0) {
|
||||||
debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
|
debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
|
||||||
conf_uname, fdt_strerror(noffset));
|
conf_uname, fdt_strerror(noffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conf_uname_copy)
|
||||||
|
free(conf_uname_copy);
|
||||||
|
|
||||||
return noffset;
|
return noffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1527,7 +1551,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
|
|||||||
char *desc;
|
char *desc;
|
||||||
const char *uname;
|
const char *uname;
|
||||||
int ret;
|
int ret;
|
||||||
int loadables_index;
|
int fdt_index, loadables_index;
|
||||||
|
|
||||||
/* Mandatory properties */
|
/* Mandatory properties */
|
||||||
ret = fit_get_desc(fit, noffset, &desc);
|
ret = fit_get_desc(fit, noffset, &desc);
|
||||||
@ -1549,9 +1573,17 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
|
|||||||
if (uname)
|
if (uname)
|
||||||
printf("%s Init Ramdisk: %s\n", p, uname);
|
printf("%s Init Ramdisk: %s\n", p, uname);
|
||||||
|
|
||||||
uname = fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
|
for (fdt_index = 0;
|
||||||
if (uname)
|
uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP,
|
||||||
printf("%s FDT: %s\n", p, uname);
|
fdt_index, NULL), uname;
|
||||||
|
fdt_index++) {
|
||||||
|
|
||||||
|
if (fdt_index == 0)
|
||||||
|
printf("%s FDT: ", p);
|
||||||
|
else
|
||||||
|
printf("%s ", p);
|
||||||
|
printf("%s\n", uname);
|
||||||
|
}
|
||||||
|
|
||||||
uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
|
uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
|
||||||
if (uname)
|
if (uname)
|
||||||
@ -1888,3 +1920,144 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_HOSTCC
|
||||||
|
int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
|
||||||
|
const char **fit_unamep, const char **fit_uname_configp,
|
||||||
|
int arch, ulong *datap, ulong *lenp)
|
||||||
|
{
|
||||||
|
int fdt_noffset, cfg_noffset, count;
|
||||||
|
const void *fit;
|
||||||
|
const char *fit_uname = NULL;
|
||||||
|
const char *fit_uname_config = NULL;
|
||||||
|
char *fit_uname_config_copy = NULL;
|
||||||
|
char *next_config = NULL;
|
||||||
|
ulong load, len;
|
||||||
|
#ifdef CONFIG_OF_LIBFDT_OVERLAY
|
||||||
|
ulong image_start, image_end;
|
||||||
|
ulong ovload, ovlen;
|
||||||
|
const char *uconfig;
|
||||||
|
const char *uname;
|
||||||
|
void *base, *ov;
|
||||||
|
int i, err, noffset, ov_noffset;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fit_uname = fit_unamep ? *fit_unamep : NULL;
|
||||||
|
|
||||||
|
if (fit_uname_configp && *fit_uname_configp) {
|
||||||
|
fit_uname_config_copy = strdup(*fit_uname_configp);
|
||||||
|
if (!fit_uname_config_copy)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
next_config = strchr(fit_uname_config_copy, '#');
|
||||||
|
if (next_config)
|
||||||
|
*next_config++ = '\0';
|
||||||
|
if (next_config - 1 > fit_uname_config_copy)
|
||||||
|
fit_uname_config = fit_uname_config_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt_noffset = fit_image_load(images,
|
||||||
|
addr, &fit_uname, &fit_uname_config,
|
||||||
|
arch, IH_TYPE_FLATDT,
|
||||||
|
BOOTSTAGE_ID_FIT_FDT_START,
|
||||||
|
FIT_LOAD_OPTIONAL, &load, &len);
|
||||||
|
|
||||||
|
if (fdt_noffset < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
debug("fit_uname=%s, fit_uname_config=%s\n",
|
||||||
|
fit_uname ? fit_uname : "<NULL>",
|
||||||
|
fit_uname_config ? fit_uname_config : "<NULL>");
|
||||||
|
|
||||||
|
fit = map_sysmem(addr, 0);
|
||||||
|
|
||||||
|
cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
|
||||||
|
|
||||||
|
/* single blob, or error just return as well */
|
||||||
|
count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP);
|
||||||
|
if (count <= 1 && !next_config)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* we need to apply overlays */
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF_LIBFDT_OVERLAY
|
||||||
|
image_start = addr;
|
||||||
|
image_end = addr + fit_get_size(fit);
|
||||||
|
/* verify that relocation took place by load address not being in fit */
|
||||||
|
if (load >= image_start && load < image_end) {
|
||||||
|
/* check is simplified; fit load checks for overlaps */
|
||||||
|
printf("Overlayed FDT requires relocation\n");
|
||||||
|
fdt_noffset = -EBADF;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = map_sysmem(load, len);
|
||||||
|
|
||||||
|
/* apply extra configs in FIT first, followed by args */
|
||||||
|
for (i = 1; ; i++) {
|
||||||
|
if (i < count) {
|
||||||
|
noffset = fit_conf_get_prop_node_index(fit, cfg_noffset,
|
||||||
|
FIT_FDT_PROP, i);
|
||||||
|
uname = fit_get_name(fit, noffset, NULL);
|
||||||
|
uconfig = NULL;
|
||||||
|
} else {
|
||||||
|
if (!next_config)
|
||||||
|
break;
|
||||||
|
uconfig = next_config;
|
||||||
|
next_config = strchr(next_config, '#');
|
||||||
|
if (next_config)
|
||||||
|
*next_config++ = '\0';
|
||||||
|
uname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig);
|
||||||
|
|
||||||
|
ov_noffset = fit_image_load(images,
|
||||||
|
addr, &uname, &uconfig,
|
||||||
|
arch, IH_TYPE_FLATDT,
|
||||||
|
BOOTSTAGE_ID_FIT_FDT_START,
|
||||||
|
FIT_LOAD_REQUIRED, &ovload, &ovlen);
|
||||||
|
if (ov_noffset < 0) {
|
||||||
|
printf("load of %s failed\n", uname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
debug("%s loaded at 0x%08lx len=0x%08lx\n",
|
||||||
|
uname, ovload, ovlen);
|
||||||
|
ov = map_sysmem(ovload, ovlen);
|
||||||
|
|
||||||
|
base = map_sysmem(load, len + ovlen);
|
||||||
|
err = fdt_open_into(base, base, len + ovlen);
|
||||||
|
if (err < 0) {
|
||||||
|
printf("failed on fdt_open_into\n");
|
||||||
|
fdt_noffset = err;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* the verbose method prints out messages on error */
|
||||||
|
err = fdt_overlay_apply_verbose(base, ov);
|
||||||
|
if (err < 0) {
|
||||||
|
fdt_noffset = err;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
fdt_pack(base);
|
||||||
|
len = fdt_totalsize(base);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n");
|
||||||
|
fdt_noffset = -EBADF;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (datap)
|
||||||
|
*datap = load;
|
||||||
|
if (lenp)
|
||||||
|
*lenp = len;
|
||||||
|
if (fit_unamep)
|
||||||
|
*fit_unamep = fit_uname;
|
||||||
|
if (fit_uname_configp)
|
||||||
|
*fit_uname_configp = fit_uname_config;
|
||||||
|
|
||||||
|
if (fit_uname_config_copy)
|
||||||
|
free(fit_uname_config_copy);
|
||||||
|
return fdt_noffset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -593,6 +593,31 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
|
|||||||
int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
|
int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
|
||||||
ulong *setup_start, ulong *setup_len);
|
ulong *setup_start, ulong *setup_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* boot_get_fdt_fit() - load a DTB from a FIT file (applying overlays)
|
||||||
|
*
|
||||||
|
* This deals with all aspects of loading an DTB from a FIT.
|
||||||
|
* The correct base image based on configuration will be selected, and
|
||||||
|
* then any overlays specified will be applied (as present in fit_uname_configp).
|
||||||
|
*
|
||||||
|
* @param images Boot images structure
|
||||||
|
* @param addr Address of FIT in memory
|
||||||
|
* @param fit_unamep On entry this is the requested image name
|
||||||
|
* (e.g. "kernel@1") or NULL to use the default. On exit
|
||||||
|
* points to the selected image name
|
||||||
|
* @param fit_uname_configp On entry this is the requested configuration
|
||||||
|
* name (e.g. "conf@1") or NULL to use the default. On
|
||||||
|
* exit points to the selected configuration name.
|
||||||
|
* @param arch Expected architecture (IH_ARCH_...)
|
||||||
|
* @param datap Returns address of loaded image
|
||||||
|
* @param lenp Returns length of loaded image
|
||||||
|
*
|
||||||
|
* @return node offset of base image, or -ve error code on error
|
||||||
|
*/
|
||||||
|
int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
|
||||||
|
const char **fit_unamep, const char **fit_uname_configp,
|
||||||
|
int arch, ulong *datap, ulong *lenp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fit_image_load() - load an image from a FIT
|
* fit_image_load() - load an image from a FIT
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user