mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-19 19:34:35 +00:00
fdt: Add option to default to most compatible conf in a fit image
When booting a fit image with multiple configurations, the user either has to specify which configuration to use explicitly, or there has to be a default defined which is chosen automatically. This change adds an option to change that behavior so that a configuration can be selected explicitly, or the configuration which has the device tree that claims to be compatible with the earliest item in U-Boot's device tree. In other words, if U-Boot claimed to be compatible with A, B, and then C, and the configurations claimed to be compatible with A, D and B, D and D, E, the first configuration, A, D, would be chosen. Both the first and second configurations match, but the first one matches a more specific entry in U-Boot's device tree. The order in the kernel's device tree is ignored. Signed-off-by: Gabe Black <gabeblack@google.com> Commit-Ready: Gabe Black <gabeblack@chromium.org> Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
67e1ea26e8
commit
d95f6ec733
4 changed files with 150 additions and 0 deletions
11
README
11
README
|
@ -2597,6 +2597,17 @@ FIT uImage format:
|
||||||
-150 common/cmd_nand.c Incorrect FIT image format
|
-150 common/cmd_nand.c Incorrect FIT image format
|
||||||
151 common/cmd_nand.c FIT image format OK
|
151 common/cmd_nand.c FIT image format OK
|
||||||
|
|
||||||
|
- FIT image support:
|
||||||
|
CONFIG_FIT
|
||||||
|
Enable support for the FIT uImage format.
|
||||||
|
|
||||||
|
CONFIG_FIT_BEST_MATCH
|
||||||
|
When no configuration is explicitly selected, default to the
|
||||||
|
one whose fdt's compatibility field best matches that of
|
||||||
|
U-Boot itself. A match is considered "best" if it matches the
|
||||||
|
most specific compatibility entry of U-Boot's fdt's root node.
|
||||||
|
The order of entries in the configuration's fdt is ignored.
|
||||||
|
|
||||||
- Standalone program support:
|
- Standalone program support:
|
||||||
CONFIG_STANDALONE_LOAD_ADDR
|
CONFIG_STANDALONE_LOAD_ADDR
|
||||||
|
|
||||||
|
|
|
@ -949,8 +949,19 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||||
* node
|
* node
|
||||||
*/
|
*/
|
||||||
bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
|
bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
|
||||||
|
#ifdef CONFIG_FIT_BEST_MATCH
|
||||||
|
if (fit_uname_config)
|
||||||
|
cfg_noffset =
|
||||||
|
fit_conf_get_node(fit_hdr,
|
||||||
|
fit_uname_config);
|
||||||
|
else
|
||||||
|
cfg_noffset =
|
||||||
|
fit_conf_find_compat(fit_hdr,
|
||||||
|
gd->fdt_blob);
|
||||||
|
#else
|
||||||
cfg_noffset = fit_conf_get_node(fit_hdr,
|
cfg_noffset = fit_conf_get_node(fit_hdr,
|
||||||
fit_uname_config);
|
fit_uname_config);
|
||||||
|
#endif
|
||||||
if (cfg_noffset < 0) {
|
if (cfg_noffset < 0) {
|
||||||
bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
|
bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
127
common/image.c
127
common/image.c
|
@ -3049,6 +3049,133 @@ int fit_check_format(const void *fit)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fit_conf_find_compat
|
||||||
|
* @fit: pointer to the FIT format image header
|
||||||
|
* @fdt: pointer to the device tree to compare against
|
||||||
|
*
|
||||||
|
* fit_conf_find_compat() attempts to find the configuration whose fdt is the
|
||||||
|
* most compatible with the passed in device tree.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* / o image-tree
|
||||||
|
* |-o images
|
||||||
|
* | |-o fdt@1
|
||||||
|
* | |-o fdt@2
|
||||||
|
* |
|
||||||
|
* |-o configurations
|
||||||
|
* |-o config@1
|
||||||
|
* | |-fdt = fdt@1
|
||||||
|
* |
|
||||||
|
* |-o config@2
|
||||||
|
* |-fdt = fdt@2
|
||||||
|
*
|
||||||
|
* / o U-Boot fdt
|
||||||
|
* |-compatible = "foo,bar", "bim,bam"
|
||||||
|
*
|
||||||
|
* / o kernel fdt1
|
||||||
|
* |-compatible = "foo,bar",
|
||||||
|
*
|
||||||
|
* / o kernel fdt2
|
||||||
|
* |-compatible = "bim,bam", "baz,biz"
|
||||||
|
*
|
||||||
|
* Configuration 1 would be picked because the first string in U-Boot's
|
||||||
|
* compatible list, "foo,bar", matches a compatible string in the root of fdt1.
|
||||||
|
* "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* offset to the configuration to use if one was found
|
||||||
|
* -1 otherwise
|
||||||
|
*/
|
||||||
|
int fit_conf_find_compat(const void *fit, const void *fdt)
|
||||||
|
{
|
||||||
|
int ndepth = 0;
|
||||||
|
int noffset, confs_noffset, images_noffset;
|
||||||
|
const void *fdt_compat;
|
||||||
|
int fdt_compat_len;
|
||||||
|
int best_match_offset = 0;
|
||||||
|
int best_match_pos = 0;
|
||||||
|
|
||||||
|
confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
|
||||||
|
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
||||||
|
if (confs_noffset < 0 || images_noffset < 0) {
|
||||||
|
debug("Can't find configurations or images nodes.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
|
||||||
|
if (!fdt_compat) {
|
||||||
|
debug("Fdt for comparison has no \"compatible\" property.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loop over the configurations in the FIT image.
|
||||||
|
*/
|
||||||
|
for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
|
||||||
|
(noffset >= 0) && (ndepth > 0);
|
||||||
|
noffset = fdt_next_node(fit, noffset, &ndepth)) {
|
||||||
|
const void *kfdt;
|
||||||
|
const char *kfdt_name;
|
||||||
|
int kfdt_noffset;
|
||||||
|
const char *cur_fdt_compat;
|
||||||
|
int len;
|
||||||
|
size_t size;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ndepth > 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
|
||||||
|
if (!kfdt_name) {
|
||||||
|
debug("No fdt property found.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
|
||||||
|
kfdt_name);
|
||||||
|
if (kfdt_noffset < 0) {
|
||||||
|
debug("No image node named \"%s\" found.\n",
|
||||||
|
kfdt_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Get a pointer to this configuration's fdt.
|
||||||
|
*/
|
||||||
|
if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
|
||||||
|
debug("Failed to get fdt \"%s\".\n", kfdt_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = fdt_compat_len;
|
||||||
|
cur_fdt_compat = fdt_compat;
|
||||||
|
/*
|
||||||
|
* Look for a match for each U-Boot compatibility string in
|
||||||
|
* turn in this configuration's fdt.
|
||||||
|
*/
|
||||||
|
for (i = 0; len > 0 &&
|
||||||
|
(!best_match_offset || best_match_pos > i); i++) {
|
||||||
|
int cur_len = strlen(cur_fdt_compat) + 1;
|
||||||
|
|
||||||
|
if (!fdt_node_check_compatible(kfdt, 0,
|
||||||
|
cur_fdt_compat)) {
|
||||||
|
best_match_offset = noffset;
|
||||||
|
best_match_pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len -= cur_len;
|
||||||
|
cur_fdt_compat += cur_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!best_match_offset) {
|
||||||
|
debug("No match found.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return best_match_offset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fit_conf_get_node - get node offset for configuration of a given unit name
|
* fit_conf_get_node - get node offset for configuration of a given unit name
|
||||||
* @fit: pointer to the FIT format image header
|
* @fit: pointer to the FIT format image header
|
||||||
|
|
|
@ -615,6 +615,7 @@ int fit_image_check_type(const void *fit, int noffset, uint8_t type);
|
||||||
int fit_image_check_comp(const void *fit, int noffset, uint8_t comp);
|
int fit_image_check_comp(const void *fit, int noffset, uint8_t comp);
|
||||||
int fit_check_format(const void *fit);
|
int fit_check_format(const void *fit);
|
||||||
|
|
||||||
|
int fit_conf_find_compat(const void *fit, const void *fdt);
|
||||||
int fit_conf_get_node(const void *fit, const char *conf_uname);
|
int fit_conf_get_node(const void *fit, const char *conf_uname);
|
||||||
int fit_conf_get_kernel_node(const void *fit, int noffset);
|
int fit_conf_get_kernel_node(const void *fit, int noffset);
|
||||||
int fit_conf_get_ramdisk_node(const void *fit, int noffset);
|
int fit_conf_get_ramdisk_node(const void *fit, int noffset);
|
||||||
|
|
Loading…
Add table
Reference in a new issue