The ROM event log[1] is a data structure populated by the i.MX BootROM on i.MX6 and later. It's found by dereferencing a 32-bit address at a fixed location within the BootROM. If valid, this address will point into the On-Chip SRAM. On the i.MX8M, we load the ARM trusted firmware into the On-Chip SRAM and may end up overwriting the BootROM event log, before the user has a chance to parse it. Thus save the BootROM log into the newly defined i.MX scratch space for later usage. [1]: NXP AN12853 "i.MX ROMs Log Events" Rev. 0 - May 2020 Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- arch/arm/mach-imx/Kconfig | 3 +++ arch/arm/mach-imx/atf.c | 3 +++ arch/arm/mach-imx/include/mach/imx8m-regs.h | 8 +++++++ arch/arm/mach-imx/include/mach/romapi.h | 11 +++++++++ arch/arm/mach-imx/romapi.c | 26 +++++++++++++++++++++ 5 files changed, 51 insertions(+) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index da71480887ad..e99cadb1f53a 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -932,6 +932,9 @@ config IMX_IIM_FUSE_BLOW enable it: imx_iim0.permanent_write_enable=1 +config IMX_SAVE_BOOTROM_LOG + bool + config HAB bool diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c index 67462bc36189..9907e5f2ba97 100644 --- a/arch/arm/mach-imx/atf.c +++ b/arch/arm/mach-imx/atf.c @@ -125,6 +125,7 @@ void imx8mm_load_bl33(void *bl33) __noreturn void imx8mm_load_and_start_image_via_tfa(void) { + imx8mm_save_bootrom_log(); imx8mm_load_bl33((void *)MX8M_ATF_BL33_BASE_ADDR); imx8mm_load_and_start_tfa(imx8mm_bl31_bin); } @@ -161,6 +162,7 @@ void imx8mp_load_bl33(void *bl33) void imx8mp_load_and_start_image_via_tfa(void) { + imx8mp_save_bootrom_log(); imx8mp_load_bl33((void *)MX8M_ATF_BL33_BASE_ADDR); imx8mp_load_and_start_tfa(imx8mp_bl31_bin); } @@ -197,6 +199,7 @@ void imx8mn_load_bl33(void *bl33) void imx8mn_load_and_start_image_via_tfa(void) { + imx8mn_save_bootrom_log(); imx8mn_load_bl33((void *)MX8M_ATF_BL33_BASE_ADDR); imx8mn_load_and_start_tfa(imx8mn_bl31_bin); } diff --git a/arch/arm/mach-imx/include/mach/imx8m-regs.h b/arch/arm/mach-imx/include/mach/imx8m-regs.h index a5017faf830e..794e1bdd88a4 100644 --- a/arch/arm/mach-imx/include/mach/imx8m-regs.h +++ b/arch/arm/mach-imx/include/mach/imx8m-regs.h @@ -3,6 +3,14 @@ #ifndef __MACH_IMX8M_REGS_H #define __MACH_IMX8M_REGS_H +/* + * Actual addressable OCRAM size may differ from SoC to SoC, but all of + * i.MX8MQ/M/N/P have this region of MMIO address space set aside for + * OCRAM only. + */ +#define MX8M_OCRAM_BASE_ADDR 0x00900000 +#define MX8M_OCRAM_MAX_SIZE 0x00200000 + #define MX8M_GPIO1_BASE_ADDR 0X30200000 #define MX8M_GPIO2_BASE_ADDR 0x30210000 #define MX8M_GPIO3_BASE_ADDR 0x30220000 diff --git a/arch/arm/mach-imx/include/mach/romapi.h b/arch/arm/mach-imx/include/mach/romapi.h index 8022fc411e9d..d22ba7259dd0 100644 --- a/arch/arm/mach-imx/include/mach/romapi.h +++ b/arch/arm/mach-imx/include/mach/romapi.h @@ -1,6 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef __MACH_IMX_ROMAPI_H #define __MACH_IMX_ROMAPI_H +#include <mach/xload.h> + struct rom_api { u16 ver; u16 tag; @@ -34,4 +37,12 @@ enum boot_dev_type_e { int imx8mp_bootrom_load_image(void); int imx8mn_bootrom_load_image(void); +/* only call after DRAM has been configured */ +void imx8m_save_bootrom_log(void *dst); + +#define imx8mq_save_bootrom_log() imx8m_save_bootrom_log(imx8mq_scratch_space()) +#define imx8mm_save_bootrom_log() imx8m_save_bootrom_log(imx8mm_scratch_space()) +#define imx8mn_save_bootrom_log() imx8m_save_bootrom_log(imx8mn_scratch_space()) +#define imx8mp_save_bootrom_log() imx8m_save_bootrom_log(imx8mp_scratch_space()) + #endif /* __MACH_IMX_ROMAPI_H */ diff --git a/arch/arm/mach-imx/romapi.c b/arch/arm/mach-imx/romapi.c index 5d00d71154d7..48512a8d045e 100644 --- a/arch/arm/mach-imx/romapi.c +++ b/arch/arm/mach-imx/romapi.c @@ -1,7 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) "romapi: " fmt + #include <common.h> #include <asm/sections.h> #include <mach/romapi.h> #include <mach/atf.h> +#include <mach/imx8m-regs.h> static int imx8m_bootrom_load(struct rom_api *rom_api, void *adr, size_t size) { @@ -42,3 +47,24 @@ int imx8mn_bootrom_load_image(void) { return imx8mp_bootrom_load_image(); } + +void imx8m_save_bootrom_log(void *dest) +{ + ulong rom_log_addr; + + if (!IS_ENABLED(CONFIG_IMX_SAVE_BOOTROM_LOG)) { + pr_debug("skipping bootrom log saving\n"); + return; + } + + rom_log_addr = *(u32 *)0x9e0; + + if (rom_log_addr < MX8M_OCRAM_BASE_ADDR || + rom_log_addr >= MX8M_OCRAM_BASE_ADDR + MX8M_OCRAM_MAX_SIZE || + rom_log_addr & 0x3) { + pr_warn("No BootROM log found at address 0x%08lx\n", rom_log_addr); + return; + } + + memcpy(dest, (u32 *)rom_log_addr, 128 * sizeof(u32)); +} -- 2.30.2