feat(rcar3): populate kaslr-seed in next stage DT

The SCEG CC6.3S which contains TRNG is only accessible from secure
world. Pull 8 random bytes out of the TRNG and pass them to the next
stage via DT fragment as /chosen/kaslr-seed property, so Linux can
use those random bytes to initialize KASLR in case it is compiled
with CONFIG_RANDOMIZE_BASE .

Linux before this patch prints early on boot:
KASLR disabled due to lack of seed

Linux after this patch prints early on boot:
KASLR enabled

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Change-Id: Ie05473e4e15d348febaca208247541e8a1532534
This commit is contained in:
Marek Vasut 2024-06-02 21:09:59 +02:00
parent 638e3aa5a2
commit b9e34d14c9
2 changed files with 93 additions and 0 deletions

View file

@ -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 */

View file

@ -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) {