@@ -13,6 +13,54 @@
#include <log.h>
#include <linux/libfdt.h>
+int dtb_fit_image_size(const void *fit)
+{
+ struct legacy_img_hdr *header;
+ int fdt_size, blob_total_size;
+ int images, conf, node;
+ int blob_offset, blob_len;
+
+ header = (struct legacy_img_hdr *)fit;
+ if (image_get_magic(header) != FDT_MAGIC) {
+ debug("No FIT image appended to U-Boot\n");
+ return -EINVAL;
+ }
+
+ fdt_size = fdt_totalsize(fit);
+ fdt_size = (fdt_size + 3) & ~3;
+
+ conf = fdt_path_offset(fit, FIT_CONFS_PATH);
+ if (conf < 0) {
+ debug("%s: Cannot find /configurations node: %d\n", __func__, conf);
+ return -EINVAL;
+ }
+
+ images = fdt_path_offset(fit, FIT_IMAGES_PATH);
+ if (images < 0) {
+ debug("%s: Cannot find /images node: %d\n", __func__, images);
+ return -EINVAL;
+ }
+
+ blob_total_size = 0;
+ node = fdt_first_subnode(fit, images);
+ while (node >= 0) {
+ blob_offset = fdt_getprop_u32(fit, node, "data-offset");
+ if (blob_offset == FDT_ERROR)
+ return -ENOENT;
+
+ blob_len = fdt_getprop_u32(fit, node, "data-size");
+ if (blob_len < 0)
+ return blob_len;
+
+ if (blob_total_size < blob_offset + blob_len)
+ blob_total_size = blob_offset + blob_len;
+
+ node = fdt_next_subnode(fit, node);
+ }
+
+ return fdt_size + blob_total_size;
+}
+
static int fdt_offset(const void *fit)
{
int images, node, fdt_len, fdt_node, fdt_offset;
@@ -49,6 +49,7 @@
#include <dm/root.h>
#include <linux/errno.h>
#include <linux/log2.h>
+#include <boot_fit.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -574,7 +575,24 @@ static int reserve_fdt(void)
* section, then it will be relocated with other data.
*/
if (gd->fdt_blob) {
- gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+ if (gd_multi_dtb_fit()) {
+ int dtb_fit_size = dtb_fit_image_size(gd_multi_dtb_fit());
+
+ if (dtb_fit_size < 0) {
+ /*
+ * Fallback to default:
+ * - switch to non-multi dtb case (single dtb)
+ * - reserve space for current dtb only
+ */
+ gd_set_multi_dtb_fit(NULL);
+ gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+ } else {
+ /* reserve space for the whole dtb fit image */
+ gd->fdt_size = ALIGN(dtb_fit_size, 32);
+ }
+ } else {
+ gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+ }
gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
@@ -668,9 +686,17 @@ static int reloc_fdt(void)
{
if (!IS_ENABLED(CONFIG_OF_EMBED)) {
if (gd->new_fdt) {
- memcpy(gd->new_fdt, gd->fdt_blob,
- fdt_totalsize(gd->fdt_blob));
- gd->fdt_blob = gd->new_fdt;
+ if (gd_multi_dtb_fit()) {
+ memcpy(gd->new_fdt, gd_multi_dtb_fit(),
+ dtb_fit_image_size(gd_multi_dtb_fit()));
+ gd->fdt_blob = gd->new_fdt + (gd->fdt_blob -
+ gd_multi_dtb_fit());
+ gd_set_multi_dtb_fit(gd->new_fdt);
+ } else {
+ memcpy(gd->new_fdt, gd->fdt_blob,
+ fdt_totalsize(gd->fdt_blob));
+ gd->fdt_blob = gd->new_fdt;
+ }
}
}
@@ -4,6 +4,14 @@
* Written by Franklin Cooper Jr. <fcooper@ti.com>
*/
+/**
+ * dtb_fit_image_size - Find a size of a DTB FIT image
+ * @fit: pointer to the FIT image
+ *
+ * Return: a size of DTB FIT image (negative value on error)
+ */
+int dtb_fit_image_size(const void *fit);
+
/**
* locate_dtb_in_fit - Find a DTB matching the board in a FIT image
* @fit: pointer to the FIT image
U-Boot with linked fit dtb image may be loaded by a bootloader to a low memory. On a later stage U-Boot will relocate itself and used dtb. There is no problem until we decide to reselect dtb on a later stage. In this case dtb placed in the low memory address may be selected. But this data can be overwritted by flash reading or network file transfer. Thus we will use damaged dtb. To fix it move the whole fit dtb image instead of just used dtb. Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu> --- boot/boot_fit.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ common/board_f.c | 34 ++++++++++++++++++++++++++++---- include/boot_fit.h | 8 ++++++++ 3 files changed, 86 insertions(+), 4 deletions(-)