stm32mp1: shared resources: apply registered configuration

BL32/SP_MIN configures platform security hardening from the shared
resources driver.  At the end of SP_MIN initialization, all shared
resources shall be assigned to secure or non-secure world by
drivers. A lock prevent from further change on the resource
assignation. By definition, resources not registered are assign
to non-secure world since not claimed by any component on the BL.

No functional change as all resources are currently in state
SHRES_UNREGISTERED hence assigned to non-secure world as prior
this change in stm32mp1_etzpc_early_setup() and
sp_min_platform_setup().

Change-Id: Ic41fab47216c3b8b7a6a75b8358cfcec411ed941
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
diff --git a/plat/st/common/include/stm32mp_shared_resources.h b/plat/st/common/include/stm32mp_shared_resources.h
index 2ab42ef..b148666 100644
--- a/plat/st/common/include/stm32mp_shared_resources.h
+++ b/plat/st/common/include/stm32mp_shared_resources.h
@@ -15,4 +15,7 @@
 /* Return true if and only if @reset_id relates to a non-secure peripheral */
 bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
 
+/* Consolidate peripheral states and lock against new peripheral registering */
+void stm32mp_lock_periph_registering(void);
+
 #endif /* STM32MP_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index e1799ed..e2c2b20 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -82,19 +82,12 @@
 
 static void stm32mp1_etzpc_early_setup(void)
 {
-	unsigned int n;
-
 	if (etzpc_init() != 0) {
 		panic();
 	}
 
 	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
 	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
-
-	/* Release security on all shared resources */
-	for (n = 0; n < STM32MP1_ETZPC_SEC_ID_LIMIT; n++) {
-		etzpc_configure_decprot(n, ETZPC_DECPROT_NS_RW);
-	}
 }
 
 /*******************************************************************************
@@ -181,14 +174,11 @@
 
 	stm32mp1_gic_init();
 
-	/* Set GPIO bank Z as non secure */
-	for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) {
-		set_gpio_secure_cfg(GPIO_BANK_Z, pin, false);
-	}
-
 	if (stm32_iwdg_init() < 0) {
 		panic();
 	}
+
+	stm32mp_lock_periph_registering();
 }
 
 void sp_min_plat_arch_setup(void)
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
index 1860681..268aa52 100644
--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -10,10 +10,59 @@
 #include <platform_def.h>
 
 #include <common/debug.h>
+#include <drivers/st/etzpc.h>
 #include <drivers/st/stm32_gpio.h>
 
 #include <stm32mp_shared_resources.h>
 
+/*
+ * Once one starts to get the resource registering state, one cannot register
+ * new resources. This ensures resource state cannot change.
+ */
+static bool registering_locked;
+
+/*
+ * Shared peripherals and resources registration
+ *
+ * Each resource assignation is stored in a table. The state defaults
+ * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
+ *
+ * Resource driver that as not embedded (a.k.a their related CFG_xxx build
+ * directive is disabled) are assigned to the non-secure world.
+ *
+ * Each pin of the GPIOZ bank can be secure or non-secure.
+ *
+ * It is the platform responsibility the ensure resource assignation
+ * matches the access permission firewalls configuration.
+ */
+enum shres_state {
+	SHRES_UNREGISTERED = 0,
+	SHRES_SECURE,
+	SHRES_NON_SECURE,
+};
+
+/* Force uint8_t array for array of enum shres_state for size considerations */
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+	registering_locked = true;
+}
+
+static bool periph_is_non_secure(enum stm32mp_shres id)
+{
+	lock_registering();
+
+	return (shres_state[id] == SHRES_NON_SECURE) ||
+	       (shres_state[id] == SHRES_UNREGISTERED);
+}
+
+static bool periph_is_secure(enum stm32mp_shres id)
+{
+	return !periph_is_non_secure(id);
+}
+
 /* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
 static int8_t gpioz_nbpin = -1;
 
@@ -38,7 +87,7 @@
 	return (unsigned int)gpioz_nbpin;
 }
 
-static unsigned int __unused get_gpioz_nbpin(void)
+static unsigned int get_gpioz_nbpin(void)
 {
 	return get_gpio_nbpin(GPIO_BANK_Z);
 }
@@ -54,3 +103,124 @@
 {
 	return true;
 }
+
+static bool mckprot_protects_periph(enum stm32mp_shres id)
+{
+	switch (id) {
+	case STM32MP1_SHRES_MCU:
+	case STM32MP1_SHRES_PLL3:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
+{
+	assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
+	       (id > STM32MP1_SHRES_GPIOZ(7)));
+
+	if (periph_is_non_secure(id)) {
+		return ETZPC_DECPROT_NS_RW;
+	}
+
+	return ETZPC_DECPROT_S_RW;
+}
+
+static void set_etzpc_secure_configuration(void)
+{
+	/* Some system peripherals shall be secure */
+	etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+
+	/* Configure ETZPC with peripheral registering */
+	etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_CRYP1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_HASH1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C4));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C6));
+	etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_IWDG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_RNG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_USART1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_SPI6));
+}
+
+static void check_rcc_secure_configuration(void)
+{
+	uint32_t n;
+	uint32_t error = 0U;
+	bool mckprot = stm32mp1_rcc_is_mckprot();
+	bool secure = stm32mp1_rcc_is_secure();
+
+	for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
+		if (shres_state[n] != SHRES_SECURE) {
+			continue;
+		}
+
+		if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
+			ERROR("RCC %s MCKPROT %s and %u secure\n",
+			      secure ? "secure" : "non-secure",
+			      mckprot ? "set" : "not set",
+			      n);
+			error++;
+		}
+	}
+
+	if (error != 0U) {
+		panic();
+	}
+}
+
+static void set_gpio_secure_configuration(void)
+{
+	uint32_t pin;
+
+	for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+		bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+		set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
+	}
+}
+
+static void print_shared_resources_state(void)
+{
+	unsigned int id;
+
+	for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
+		switch (shres_state[id]) {
+		case SHRES_SECURE:
+			INFO("stm32mp1 %u is secure\n", id);
+			break;
+		case SHRES_NON_SECURE:
+		case SHRES_UNREGISTERED:
+			VERBOSE("stm32mp %u is non-secure\n", id);
+			break;
+		default:
+			VERBOSE("stm32mp %u is invalid\n", id);
+			panic();
+		}
+	}
+}
+
+void stm32mp_lock_periph_registering(void)
+{
+	registering_locked = true;
+
+	print_shared_resources_state();
+
+	check_rcc_secure_configuration();
+	set_etzpc_secure_configuration();
+	set_gpio_secure_configuration();
+}