mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 17:44:19 +00:00
NXP: Driver for NXP Security Monitor
NXP Security Monitor IP provides hardware anchored - current security state of the SoC. - Tamper detect etc. Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com> Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com> Change-Id: I8ff809fe2f3fd013844ab3d4a8733f53c2b06c81
This commit is contained in:
parent
3979c6d924
commit
d8e9799921
3 changed files with 299 additions and 0 deletions
27
drivers/nxp/sec_mon/sec_mon.mk
Normal file
27
drivers/nxp/sec_mon/sec_mon.mk
Normal file
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# Copyright 2021 NXP
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
ifeq (${ADD_SNVS},)
|
||||
|
||||
ADD_SNVS := 1
|
||||
|
||||
SNVS_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/sec_mon
|
||||
|
||||
PLAT_INCLUDES += -I$(SNVS_DRIVERS_PATH)
|
||||
|
||||
SNVS_SOURCES += $(SNVS_DRIVERS_PATH)/snvs.c
|
||||
|
||||
ifeq (${BL_COMM_SNVS_NEEDED},yes)
|
||||
BL_COMMON_SOURCES += ${SNVS_SOURCES}
|
||||
else
|
||||
ifeq (${BL2_SNVS_NEEDED},yes)
|
||||
BL2_SOURCES += ${SNVS_SOURCES}
|
||||
endif
|
||||
ifeq (${BL31_SNVS_NEEDED},yes)
|
||||
BL31_SOURCES += ${SNVS_SOURCES}
|
||||
endif
|
||||
endif
|
||||
endif
|
186
drivers/nxp/sec_mon/snvs.c
Normal file
186
drivers/nxp/sec_mon/snvs.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright 2021 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <snvs.h>
|
||||
|
||||
static uintptr_t g_nxp_snvs_addr;
|
||||
|
||||
void snvs_init(uintptr_t nxp_snvs_addr)
|
||||
{
|
||||
g_nxp_snvs_addr = nxp_snvs_addr;
|
||||
}
|
||||
|
||||
uint32_t get_snvs_state(void)
|
||||
{
|
||||
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
|
||||
|
||||
return (snvs_read32(&snvs->hp_stat) & HPSTS_MASK_SSM_ST);
|
||||
}
|
||||
|
||||
static uint32_t do_snvs_state_transition(uint32_t state_transtion_bit,
|
||||
uint32_t target_state)
|
||||
{
|
||||
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
|
||||
uint32_t sts = get_snvs_state();
|
||||
uint32_t fetch_cnt = 16U;
|
||||
uint32_t val = snvs_read32(&snvs->hp_com) | state_transtion_bit;
|
||||
|
||||
snvs_write32(&snvs->hp_com, val);
|
||||
|
||||
/* polling loop till SNVS is in target state */
|
||||
do {
|
||||
sts = get_snvs_state();
|
||||
} while ((sts != target_state) && ((--fetch_cnt) != 0));
|
||||
|
||||
return sts;
|
||||
}
|
||||
void transition_snvs_non_secure(void)
|
||||
{
|
||||
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
|
||||
uint32_t sts = get_snvs_state();
|
||||
|
||||
switch (sts) {
|
||||
/* If initial state is check or Non-Secure, then
|
||||
* set the Software Security Violation Bit and
|
||||
* transition to Non-Secure State.
|
||||
*/
|
||||
case HPSTS_CHECK_SSM_ST:
|
||||
sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST);
|
||||
break;
|
||||
|
||||
/* If initial state is Trusted, Secure or Soft-Fail, then
|
||||
* first set the Software Security Violation Bit and
|
||||
* transition to Soft-Fail State.
|
||||
*/
|
||||
case HPSTS_TRUST_SSM_ST:
|
||||
case HPSTS_SECURE_SSM_ST:
|
||||
case HPSTS_SOFT_FAIL_SSM_ST:
|
||||
sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST);
|
||||
|
||||
/* If SSM Soft Fail to Non-Secure State Transition
|
||||
* Disable is not set, then set SSM_ST bit and
|
||||
* transition to Non-Secure State.
|
||||
*/
|
||||
if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_SFNS_DIS) == 0) {
|
||||
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_NON_SECURE_SSM_ST);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void transition_snvs_soft_fail(void)
|
||||
{
|
||||
do_snvs_state_transition(HPCOM_SW_FSV, HPSTS_SOFT_FAIL_SSM_ST);
|
||||
}
|
||||
|
||||
uint32_t transition_snvs_trusted(void)
|
||||
{
|
||||
struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
|
||||
uint32_t sts = get_snvs_state();
|
||||
|
||||
switch (sts) {
|
||||
/* If initial state is check, set the SSM_ST bit to
|
||||
* change the state to trusted.
|
||||
*/
|
||||
case HPSTS_CHECK_SSM_ST:
|
||||
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
|
||||
break;
|
||||
/* If SSM Secure to Trusted State Transition Disable
|
||||
* is not set, then set SSM_ST bit and
|
||||
* transition to Trusted State.
|
||||
*/
|
||||
case HPSTS_SECURE_SSM_ST:
|
||||
if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_ST_DIS) == 0) {
|
||||
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
|
||||
}
|
||||
break;
|
||||
/* If initial state is Soft-Fail or Non-Secure, then
|
||||
* transition to Trusted is not Possible.
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
uint32_t transition_snvs_secure(void)
|
||||
{
|
||||
uint32_t sts = get_snvs_state();
|
||||
|
||||
if (sts == HPSTS_SECURE_SSM_ST) {
|
||||
return sts;
|
||||
}
|
||||
|
||||
if (sts != HPSTS_TRUST_SSM_ST) {
|
||||
sts = transition_snvs_trusted();
|
||||
if (sts != HPSTS_TRUST_SSM_ST) {
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
|
||||
sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val)
|
||||
{
|
||||
if (flag_val) {
|
||||
snvs_write32(g_nxp_snvs_addr + offset,
|
||||
(snvs_read32(g_nxp_snvs_addr + offset))
|
||||
| (1 << bit_pos));
|
||||
} else {
|
||||
snvs_write32(g_nxp_snvs_addr + offset,
|
||||
(snvs_read32(g_nxp_snvs_addr + offset))
|
||||
& ~(1 << bit_pos));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos)
|
||||
{
|
||||
return (snvs_read32(g_nxp_snvs_addr + offset) & (1 << bit_pos));
|
||||
}
|
||||
|
||||
void snvs_disable_zeroize_lp_gpr(void)
|
||||
{
|
||||
snvs_write_lp_gpr_bit(NXP_LPCR_OFFSET,
|
||||
NXP_GPR_Z_DIS_BIT,
|
||||
true);
|
||||
}
|
||||
|
||||
#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB)
|
||||
void snvs_write_app_data_bit(uint32_t bit_pos)
|
||||
{
|
||||
snvs_write_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET,
|
||||
bit_pos,
|
||||
true);
|
||||
}
|
||||
|
||||
uint32_t snvs_read_app_data(void)
|
||||
{
|
||||
return snvs_read32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET);
|
||||
}
|
||||
|
||||
uint32_t snvs_read_app_data_bit(uint32_t bit_pos)
|
||||
{
|
||||
uint8_t ret = snvs_read_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, bit_pos);
|
||||
|
||||
return ((ret != 0U) ? 1U : 0U);
|
||||
}
|
||||
|
||||
void snvs_clear_app_data(void)
|
||||
{
|
||||
snvs_write32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET, 0x0);
|
||||
}
|
||||
#endif
|
86
drivers/nxp/sec_mon/snvs.h
Normal file
86
drivers/nxp/sec_mon/snvs.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright 2021 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SNVS_H
|
||||
#define SNVS_H
|
||||
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <endian.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
struct snvs_regs {
|
||||
uint32_t reserved1;
|
||||
uint32_t hp_com; /* 0x04 SNVS_HP Command Register */
|
||||
uint32_t reserved2[3];
|
||||
uint32_t hp_stat; /* 0x14 SNVS_HP Status Register */
|
||||
};
|
||||
|
||||
#ifdef NXP_SNVS_BE
|
||||
#define snvs_read32(a) bswap32(mmio_read_32((uintptr_t)(a)))
|
||||
#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32((v)))
|
||||
#elif defined(NXP_SNVS_LE)
|
||||
#define snvs_read32(a) mmio_read_32((uintptr_t)(a))
|
||||
#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), (v))
|
||||
#else
|
||||
#error Please define CCSR SNVS register endianness
|
||||
#endif
|
||||
|
||||
void snvs_init(uintptr_t nxp_snvs_addr);
|
||||
uint32_t get_snvs_state(void);
|
||||
void transition_snvs_non_secure(void);
|
||||
void transition_snvs_soft_fail(void);
|
||||
uint32_t transition_snvs_trusted(void);
|
||||
uint32_t transition_snvs_secure(void);
|
||||
|
||||
uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos);
|
||||
void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val);
|
||||
|
||||
void snvs_disable_zeroize_lp_gpr(void);
|
||||
|
||||
#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB)
|
||||
uint32_t snvs_read_app_data(void);
|
||||
uint32_t snvs_read_app_data_bit(uint32_t bit_pos);
|
||||
void snvs_clear_app_data(void);
|
||||
void snvs_write_app_data_bit(uint32_t bit_pos);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/* SSM_ST field in SNVS status reg */
|
||||
#define HPSTS_CHECK_SSM_ST 0x900 /* SNVS is in check state */
|
||||
#define HPSTS_NON_SECURE_SSM_ST 0xb00 /* SNVS is in non secure state */
|
||||
#define HPSTS_TRUST_SSM_ST 0xd00 /* SNVS is in trusted state */
|
||||
#define HPSTS_SECURE_SSM_ST 0xf00 /* SNVS is in secure state */
|
||||
#define HPSTS_SOFT_FAIL_SSM_ST 0x300 /* SNVS is in soft fail state */
|
||||
#define HPSTS_MASK_SSM_ST 0xf00 /* SSM_ST field mask in SNVS reg */
|
||||
|
||||
/* SNVS register bits */
|
||||
#define HPCOM_SW_SV 0x100 /* Security Violation bit */
|
||||
#define HPCOM_SW_FSV 0x200 /* Fatal Security Violation bit */
|
||||
#define HPCOM_SSM_ST 0x1 /* SSM_ST field in SNVS command reg */
|
||||
#define HPCOM_SSM_ST_DIS 0x2 /* Disable Secure to Trusted State */
|
||||
#define HPCOM_SSM_SFNS_DIS 0x4 /* Disable Soft Fail to Non-Secure */
|
||||
|
||||
#define NXP_LP_GPR0_OFFSET 0x90
|
||||
#define NXP_LPCR_OFFSET 0x38
|
||||
#define NXP_GPR_Z_DIS_BIT 24
|
||||
|
||||
#ifdef NXP_COINED_BB
|
||||
|
||||
#ifndef NXP_APP_DATA_LP_GPR_OFFSET
|
||||
#define NXP_APP_DATA_LP_GPR_OFFSET NXP_LP_GPR0_OFFSET
|
||||
#endif
|
||||
|
||||
#define NXP_LPGPR_ZEROTH_BIT 0
|
||||
|
||||
#endif /* NXP_COINED_BB */
|
||||
|
||||
#endif /* SNVS_H */
|
Loading…
Add table
Reference in a new issue