diff --git a/plat/renesas/common/include/rcar_def.h b/plat/renesas/common/include/rcar_def.h index f1c255377..86764442d 100644 --- a/plat/renesas/common/include/rcar_def.h +++ b/plat/renesas/common/include/rcar_def.h @@ -310,4 +310,31 @@ #define LOSSY_FMT2 LOSSY_FMT_YUV422INTLV #define LOSSY_ENA_DIS2 LOSSY_DISABLE +#define RCAR_CC63_BASE 0xE6600000U +#define CC63_TRNG_ISR_REG_ADDR 0x104U +#define CC63_TRNG_ISR_REG_EHR_VALID BIT_32(0) +#define CC63_TRNG_ISR_REG_AUTOCORR_ERR BIT_32(1) +#define CC63_TRNG_ICR_REG_ADDR 0x108U +#define CC63_TRNG_CONFIG_REG_ADDR 0x10CU +#define CC63_TRNG_CONFIG_REG_ROSC_MAX_LENGTH 3 +#define CC63_TRNG_VALID_REG_ADDR 0x110U +#define CC63_TRNG_VALID_REG_EHR_NOT_READY 0x0 +#define CC63_TRNG_EHR_DATA_ADDR_0_REG_ADDR 0x114U +#define CC63_TRNG_SOURCE_ENABLE_REG_ADDR 0x12CU +#define CC63_TRNG_SOURCE_ENABLE_REG_SET 0x1 +#define CC63_TRNG_SOURCE_ENABLE_REG_CLR 0x0 +#define CC63_TRNG_SAMPLE_CNT1_REG_ADDR 0x130U +#define CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT 100 +#define CC63_TRNG_DEBUG_CONTROL_REG_ADDR 0x138U +#define CC63_TRNG_DEBUG_CONTROL_REG_VNC_BYPASS BIT_32(1) +#define CC63_TRNG_DEBUG_CONTROL_REG_AUTOCORR_BYPASS BIT_32(3) +#define CC63_TRNG_DEBUG_CONTROL_REG_80090B \ + (CC63_TRNG_DEBUG_CONTROL_REG_VNC_BYPASS | \ + CC63_TRNG_DEBUG_CONTROL_REG_AUTOCORR_BYPASS) +#define CC63_TRNG_SW_RESET_REG_ADDR 0x140U +#define CC63_TRNG_SW_RESET_REG_SET 0x1 +#define CC63_TRNG_VERSION_REG_ADDR 0x1C0U +#define CC63_TRNG_CLK_ENABLE_REG_ADDR 0x1C4U +#define CC63_TRNG_CLK_ENABLE_REG_SET 0x1 + #endif /* RCAR_DEF_H */ diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c index 41031d68e..c5482403a 100644 --- a/plat/renesas/rcar/bl2_plat_setup.c +++ b/plat/renesas/rcar/bl2_plat_setup.c @@ -756,6 +756,69 @@ err: #endif } +static void bl2_add_kaslr_seed(void) +{ + uint32_t cnt, isr, prr; + uint64_t seed; + int ret, node; + + /* SCEG is only available on H3/M3-W/M3-N */ + prr = mmio_read_32(RCAR_PRR); + switch (prr & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: + case PRR_PRODUCT_M3: + case PRR_PRODUCT_M3N: + break; + default: + return; + } + + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SW_RESET_REG_ADDR, + CC63_TRNG_SW_RESET_REG_SET); + + do { + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_CLK_ENABLE_REG_ADDR, + CC63_TRNG_CLK_ENABLE_REG_SET); + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SAMPLE_CNT1_REG_ADDR, + CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT); + cnt = mmio_read_32(RCAR_CC63_BASE + CC63_TRNG_SAMPLE_CNT1_REG_ADDR); + } while (cnt != CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT); + + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_CONFIG_REG_ADDR, + CC63_TRNG_CONFIG_REG_ROSC_MAX_LENGTH); + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_DEBUG_CONTROL_REG_ADDR, + CC63_TRNG_DEBUG_CONTROL_REG_80090B); + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SOURCE_ENABLE_REG_ADDR, + CC63_TRNG_SOURCE_ENABLE_REG_SET); + + do { + isr = mmio_read_32(RCAR_CC63_BASE + CC63_TRNG_ISR_REG_ADDR); + if ((isr & CC63_TRNG_ISR_REG_AUTOCORR_ERR) != 0U) { + panic(); + } + } while ((isr & CC63_TRNG_ISR_REG_EHR_VALID) == 0U); + + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_ICR_REG_ADDR, UINT32_MAX); + seed = mmio_read_64(RCAR_CC63_BASE + CC63_TRNG_EHR_DATA_ADDR_0_REG_ADDR); + mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SOURCE_ENABLE_REG_ADDR, + CC63_TRNG_SOURCE_ENABLE_REG_CLR); + + node = ret = fdt_add_subnode(fdt, 0, "chosen"); + if (ret < 0) { + goto err; + } + + ret = fdt_setprop_u64(fdt, node, "kaslr-seed", seed); + if (ret < 0) { + goto err; + } + + return; +err: + NOTICE("BL2: Cannot add KASLR seed to FDT (ret=%i)\n", ret); + panic(); +} + static void bl2_add_dram_entry(uint64_t start, uint64_t size) { char nodename[32] = { 0 }; @@ -1215,6 +1278,9 @@ lcm_state: /* Print DRAM layout */ bl2_advertise_dram_size(product); + /* Add KASLR seed */ + bl2_add_kaslr_seed(); + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { if (rcar_emmc_init() != EMMC_SUCCESS) {