diff options
-rw-r--r-- | plat/allwinner/common/allwinner-common.mk | 2 | ||||
-rw-r--r-- | plat/allwinner/common/include/platform_def.h | 2 | ||||
-rw-r--r-- | plat/allwinner/common/sunxi_bl31_setup.c | 55 |
3 files changed, 58 insertions, 1 deletions
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk index 8c772bfc2..2dc058f54 100644 --- a/plat/allwinner/common/allwinner-common.mk +++ b/plat/allwinner/common/allwinner-common.mk @@ -13,6 +13,8 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common \ -I${AW_PLAT}/common/include \ -I${AW_PLAT}/${PLAT}/include +include lib/libfdt/libfdt.mk + PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \ drivers/ti/uart/${ARCH}/16550_console.S \ ${XLAT_TABLES_LIB_SRCS} \ diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h index 4f9c00ed1..08eb5cf2b 100644 --- a/plat/allwinner/common/include/platform_def.h +++ b/plat/allwinner/common/include/platform_def.h @@ -21,7 +21,7 @@ /* How much memory to reserve as secure for BL32, if configured */ #define SUNXI_DRAM_SEC_SIZE (32U << 20) -/* How much DRAM to map */ +/* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */ #define SUNXI_DRAM_MAP_SIZE (64U << 20) #define CACHE_WRITEBACK_SHIFT 6 diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c index 6c47e89fc..94b123a64 100644 --- a/plat/allwinner/common/sunxi_bl31_setup.c +++ b/plat/allwinner/common/sunxi_bl31_setup.c @@ -10,6 +10,7 @@ #include <debug.h> #include <generic_delay_timer.h> #include <gicv2.h> +#include <libfdt.h> #include <platform.h> #include <platform_def.h> #include <sunxi_def.h> @@ -28,6 +29,47 @@ static const gicv2_driver_data_t sunxi_gic_data = { .gicc_base = SUNXI_GICC_BASE, }; +/* + * Try to find a DTB loaded in memory by previous stages. + * + * At the moment we implement a heuristic to find the DTB attached to U-Boot: + * U-Boot appends its DTB to the end of the image. Assuming that BL33 is + * U-Boot, try to find the size of the U-Boot image to learn the DTB address. + * The generic ARMv8 U-Boot image contains the load address and its size + * as u64 variables at the beginning of the image. There might be padding + * or other headers before that data, so scan the first 2KB after the BL33 + * entry point to find the load address, which should be followed by the + * size. Adding those together gives us the address of the DTB. + */ +static void *sunxi_find_dtb(void) +{ + uint64_t *u_boot_base; + int i; + + u_boot_base = (void *)(SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE); + + for (i = 0; i < 2048 / sizeof(uint64_t); i++) { + uint32_t *dtb_base; + + if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET) + continue; + + /* Does the suspected U-Boot size look anyhow reasonable? */ + if (u_boot_base[i + 1] >= 256 * 1024 * 1024) + continue; + + /* end of the image: base address + size */ + dtb_base = (void *)((char *)u_boot_base + u_boot_base[i + 1]); + + if (fdt_check_header(dtb_base) != 0) + continue; + + return dtb_base; + } + + return NULL; +} + void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { @@ -66,6 +108,7 @@ void bl31_platform_setup(void) { const char *soc_name; uint16_t soc_id = sunxi_read_soc_id(); + void *fdt; switch (soc_id) { case SUNXI_SOC_A64: @@ -85,6 +128,18 @@ void bl31_platform_setup(void) generic_delay_timer_init(); + fdt = sunxi_find_dtb(); + if (fdt) { + const char *model; + int length; + + model = fdt_getprop(fdt, 0, "model", &length); + NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt, + model ?: "unknown"); + } else { + NOTICE("BL31: No DTB found.\n"); + } + /* Configure the interrupt controller */ gicv2_driver_init(&sunxi_gic_data); gicv2_distif_init(); |