* Descriptor to instantiate RNG State Handle 0 in normal mode and
* load the JDKEK, TDKEK and TDSK registers
*/
-void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc)
+void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc, int handle)
{
u32 *jump_cmd;
/* INIT RNG in non-test mode */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_AS_INIT);
-
- /* wait for done */
- jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
- set_jump_tgt_here(desc, jump_cmd);
-
- /*
- * load 1 to clear written reg:
- * resets the done interrrupt and returns the RNG to idle.
- */
- append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
-
- /* generate secure keys (non-test) */
- append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_RNG4_SK);
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT);
+
+ /* For SH0, Secure Keys must be generated as well */
+ if (handle == 0) {
+ /* wait for done */
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /*
+ * load 1 to clear written reg:
+ * resets the done interrupt and returns the RNG to idle.
+ */
+ append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+ /* generate secure keys (non-test) */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ OP_ALG_RNG4_SK);
+ }
}
/* Change key size to bytes form bits in calling function*/
#ifndef CONFIG_SPL_BUILD
static int instantiate_rng(uint8_t sec_idx)
{
- struct result op;
u32 *desc;
u32 rdsta_val;
- int ret = 0;
+ int ret = 0, sh_idx, size;
ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
- memset(&op, 0, sizeof(struct result));
-
desc = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * 6);
if (!desc) {
printf("cannot allocate RNG init descriptor memory\n");
return -1;
}
- inline_cnstr_jobdesc_rng_instantiation(desc);
- int size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
- flush_dcache_range((unsigned long)desc,
- (unsigned long)desc + size);
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, this state handle
+ * was initialized by somebody else, so it's left alone.
+ */
+ rdsta_val = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+ if (rdsta_val & (1 << sh_idx))
+ continue;
+
+ inline_cnstr_jobdesc_rng_instantiation(desc, sh_idx);
+ size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)desc,
+ (unsigned long)desc + size);
- ret = run_descriptor_jr_idx(desc, sec_idx);
+ ret = run_descriptor_jr_idx(desc, sec_idx);
- if (ret)
- printf("RNG: Instantiation failed with error %x\n", ret);
+ if (ret)
+ printf("RNG: Instantiation failed with error 0x%x\n",
+ ret);
- rdsta_val = sec_in32(&rng->rdsta);
- if (op.status || !(rdsta_val & RNG_STATE0_HANDLE_INSTANTIATED))
- return -1;
+ rdsta_val = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+ if (!(rdsta_val & (1 << sh_idx))) {
+ free(desc);
+ return -1;
+ }
+
+ memset(desc, 0, sizeof(uint32_t) * 6);
+ }
+
+ free(desc);
return ret;
}
ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
-
- u32 rdsta = sec_in32(&rng->rdsta);
-
- /* Check if RNG state 0 handler is already instantiated */
- if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED)
- return 0;
+ u32 inst_handles;
do {
+ inst_handles = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+
/*
* If either of the SH's were instantiated by somebody else
* then it is assumed that the entropy
* Also, if a handle was instantiated, do not change
* the TRNG parameters.
*/
- kick_trng(ent_delay, sec_idx);
- ent_delay += 400;
+ if (!inst_handles) {
+ kick_trng(ent_delay, sec_idx);
+ ent_delay += 400;
+ }
/*
* if instantiate_rng(...) fails, the loop will rerun
* and the kick_trng(...) function will modfiy the