From 730fb4e12c7ca37a2b6fa7d0e41ffe807e80c9bc Mon Sep 17 00:00:00 2001 From: Romuald JEANNE Date: Wed, 17 Jun 2020 17:24:01 +0200 Subject: [PATCH] TF-A-STM32MP-SSP: integration for v2.0.0 (v2.2-stm32mp-ssp-r1) Change-Id: I5299ae4f408e9a320330b90c85d13df4e9046b59 --- .../tf-a-stm32mp-ssp-archiver.inc | 112 + .../tf-a-stm32mp-ssp_2.2.bb | 30 + .../0100-st-update-ssp-v2.2-r2.0.0.patch | 2857 +++++++++++++++++ 3 files changed, 2999 insertions(+) create mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp-archiver.inc create mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp_2.2.bb create mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0100-st-update-ssp-v2.2-r2.0.0.patch diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp-archiver.inc b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp-archiver.inc new file mode 100644 index 0000000..66b4899 --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp-archiver.inc @@ -0,0 +1,112 @@ +# +# Archiver Configuration +# +SRC_URI_append = " file://README.HOW_TO.txt " + +inherit archiver +ARCHIVER_MODE[src] = "original" +COPYLEFT_LICENSE_INCLUDE_append = " BSD-3* " + +inherit archiver_stm32mp_clean + +archiver_create_makefile_for_sdk() { + . ${T}/tfaconfig_env + + # Init internal var for tfa_config_oemake: should be 'config,extraoemake' + for config in ${TF_A_CONFIG}; do + tf_a_config_oemake="${tf_a_config_oemake} ${config},\"$(eval echo \$TF_A_CONFIG_${config})\"" + done + + mkdir -p ${ARCHIVER_OUTDIR} + cat << EOF > ${ARCHIVER_OUTDIR}/Makefile.sdk +#remove default variable +LDFLAGS= +CFLAGS= +CPPFLAGS= +CC= +CPP= +AS= +AR= +LD= +NM= + +LOCAL_PATH=\$(PWD) + +EXTRA_OEMAKE=${EXTRA_OEMAKE} + +# Set default config +ELF_DEBUG_ENABLE ?= ${ELF_DEBUG_ENABLE} +TF_A_CONFIG ?= ${TF_A_CONFIG} + +# Set specific OEMAKE config +TF_A_CONFIG_OEMAKE = ${tf_a_config_oemake} +# Set default TFA_DEVICETREE +TFA_DEVICETREE ?= ${TF_A_DEVICETREE} + +#Set default TF_A_ENABLE_DEBUG_WRAPPER +TF_A_ENABLE_DEBUG_WRAPPER ?= ${TF_A_ENABLE_DEBUG_WRAPPER} + +help: + @echo + @echo "Available targets:" + @echo " all : build TF-A binaries for defined config(s)" + @echo " clean : clean build directories from generated files" + @echo + @echo "TF-A configuration:" + @echo " TF_A_CONFIG = \$(TF_A_CONFIG)" + @echo " TFA_DEVICETREE = \$(TFA_DEVICETREE)" + @echo " ELF_DEBUG_ENABLE = '\$(ELF_DEBUG_ENABLE)' ('1' to export elf files)" + @echo " TF_A_ENABLE_DEBUG_WRAPPER = '\$(TF_A_ENABLE_DEBUG_WRAPPER)' ('1' to generate tf-a for debugging)" + @echo + +all: tf + +host_tools: + @\$(MAKE) --no-print-directory -C \$(LOCAL_PATH)/tools/stm32image + +tf: host_tools + for config in \$(TF_A_CONFIG) ; do \\ + # Init any extraoemake \\ + add_extraoemake= ; \\ + for fullconfig in \$(TF_A_CONFIG_OEMAKE) ; do \\ + extraconfig=\$\$(echo \$\$fullconfig | cut -d',' -f1) ; \\ + if [ "\$\$extraconfig" = "\$\$config" ]; then \\ + add_extraoemake=\$\$(echo \$\$fullconfig | cut -d',' -f2) ; \\ + fi ; \\ + done ; \\ + mkdir -p \$(LOCAL_PATH)/../build/\$\$config ; \\ + if test -n "\$(TFA_DEVICETREE)" ; then \\ + for dt in \$(TFA_DEVICETREE) ; do \\ + \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) DTB_FILE_NAME=\$\$dt.dtb BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake ; \\ + # Copy binary file with explicit name \\ + cp -f \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt-\$\$config.${TF_A_SUFFIX} ; \\ + if [ "\$(TF_A_ENABLE_DEBUG_WRAPPER)" = "1" ]; then \\ + # Generate wrapper for debugging \\ + stm32wrapper4dbg -s \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt.${TF_A_SUFFIX} -d \$(LOCAL_PATH)/../build/\$\$config/debug-${TF_A_BASENAME}-\$\$dt-\$\$config.${TF_A_SUFFIX} ; \\ + fi \\ + done ; \\ + else \\ + \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake; \\ + tf_version=\$\$(find \$(LOCAL_PATH)/../build/\$\$config -name ${TF_A_BASENAME}*.${TF_A_SUFFIX} -exec basename {} \; | sed "s/\.${TF_A_SUFFIX}//") ; \\ + # Copy binary file with explicit name \\ + cp -f \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version-\$\$config.${TF_A_SUFFIX} ; \\ + if [ "\$(TF_A_ENABLE_DEBUG_WRAPPER)" = "1" ]; then \\ + # Generate wrapper for debugging \\ + stm32wrapper4dbg -s \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/debug-\$\$tf_version-\$\$config.${TF_A_SUFFIX} ; \\ + fi \\ + fi ; \\ + # Copy elf files with explicit name \\ + if [ "\$(ELF_DEBUG_ENABLE)" = "1" ] ; then \\ + if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} ] ; then \\ + cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL2_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\ + fi ; \\ + fi ; \\ + done + +clean: + @for config in \$(TF_A_CONFIG) ; do \\ + rm -rf \$(LOCAL_PATH)/../build/\$\$config ; \\ + done +EOF +} +do_ar_original[prefuncs] += "tfaconfig_env archiver_create_makefile_for_sdk" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp_2.2.bb b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp_2.2.bb new file mode 100644 index 0000000..bfb7486 --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp_2.2.bb @@ -0,0 +1,30 @@ +require tf-a-stm32mp-common_${PV}.inc +require tf-a-stm32mp-common.inc + +SUMMARY = "Trusted Firmware-A SSP for STM32MP1" +LICENSE = "BSD-3-Clause" + +PROVIDES += "virtual/trusted-firmware-a-ssp" + +TFA_SHARED_SOURCES = "0" + +SRC_URI += " \ + file://0100-st-update-ssp-v2.2-r2.0.0.patch \ +" + +TF_A_BASENAME = "tf-a-ssp" +TF_A_CONFIG = "ssp" +TF_A_CONFIG_ssp = " STM32MP_SSP=1 " + +# Configure stm32mp1 make settings +EXTRA_OEMAKE += 'PLAT=stm32mp1' +EXTRA_OEMAKE += 'ARCH=aarch32' +EXTRA_OEMAKE += 'ARM_ARCH_MAJOR=7' +EXTRA_OEMAKE += 'STM32MP_UART_PROGRAMMER=1' +EXTRA_OEMAKE += 'STM32MP_USB_PROGRAMMER=1' + + +# --------------------------------- +# Configure archiver use +# --------------------------------- +include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'tf-a-stm32mp-ssp-archiver.inc','')} diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0100-st-update-ssp-v2.2-r2.0.0.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0100-st-update-ssp-v2.2-r2.0.0.patch new file mode 100644 index 0000000..93029ad --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0100-st-update-ssp-v2.2-r2.0.0.patch @@ -0,0 +1,2857 @@ +From 3a5830ccfbcebfaa60540d50d42f0e37f3b532e9 Mon Sep 17 00:00:00 2001 +From: Lionel Debieve +Date: Mon, 30 Mar 2020 13:29:17 +0200 +Subject: [PATCH] stm32mp: ssp: Add secure secret provisioning feature + +This patch adds changes to support the secure secret +provisioning (SSP). +Main changes are: + - Add SSP library which includes OTP fusing services + - Change TF-A binary layout for SSP binary to embed only BL2 + and device tree. + - Modify some generic drivers to embed only needed functions + - Add read functionality for UART/USB programmer mode to receive + the encrypted binary. + +Signed-off-by: Lionel Debieve +Change-Id: Ie5cdc173c3e924c466ce9a66a98c679a9ace08d4 +--- + drivers/st/clk/stm32mp1_clk.c | 8 + + drivers/st/io/io_programmer_st_usb.c | 92 +++- + drivers/st/uart/io_programmer_uart.c | 206 +++++++- + fdts/stm32mp151.dtsi | 26 +- + fdts/stm32mp15xx-dkx.dtsi | 12 +- + fdts/stm32mp15xx-edx.dtsi | 12 +- + include/drivers/st/io_programmer.h | 8 +- + include/lib/ssp_lib.h | 35 ++ + include/lib/usb/usb_st_dfu.h | 10 +- + lib/ssp/ssp.c | 748 +++++++++++++++++++++++++++ + lib/usb/usb_st_dfu.c | 101 +++- + plat/st/common/bl2_io_storage.c | 10 +- + plat/st/common/include/stm32mp_common.h | 6 + + plat/st/common/include/stm32mp_dt.h | 1 + + plat/st/common/stm32mp_common.c | 16 + + plat/st/common/stm32mp_dt.c | 27 + + plat/st/common/stm32mp_trusted_boot.c | 1 + + plat/st/stm32mp1/bl2_plat_setup.c | 40 ++ + plat/st/stm32mp1/include/boot_api.h | 265 +++++++++- + plat/st/stm32mp1/include/platform_def.h | 15 +- + plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 4 +- + plat/st/stm32mp1/plat_image_load.c | 3 +- + plat/st/stm32mp1/platform.mk | 12 + + plat/st/stm32mp1/services/bsec_svc.c | 4 - + plat/st/stm32mp1/stm32mp1_def.h | 44 ++ + plat/st/stm32mp1/stm32mp1_private.c | 34 ++ + plat/st/stm32mp1/stm32mp1_shared_resources.c | 9 + + plat/st/stm32mp1/stm32mp1_ssp.S | 11 + + plat/st/stm32mp1/stm32mp1_ssp.ld.S | 58 +++ + plat/st/stm32mp1/stm32mp1_ssp.mk | 66 +++ + 30 files changed, 1830 insertions(+), 54 deletions(-) + create mode 100644 include/lib/ssp_lib.h + create mode 100644 lib/ssp/ssp.c + create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.S + create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.ld.S + create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.mk + +diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c +index 5efe343..d294536 100644 +--- a/drivers/st/clk/stm32mp1_clk.c ++++ b/drivers/st/clk/stm32mp1_clk.c +@@ -698,20 +698,24 @@ static unsigned int gate_refcounts[NB_GATES]; + static struct spinlock refcount_lock; + static struct stm32mp1_pll_settings pll1_settings; + static uint32_t current_opp_khz; ++#if !STM32MP_SSP + static uint32_t pll3cr; + static uint32_t pll4cr; + static uint32_t mssckselr; + static uint32_t mcudivr; ++#endif + + static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) + { + return &stm32mp1_clk_gate[idx]; + } + ++#if !STM32MP_SSP + static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) + { + return gate->secure == N_S; + } ++#endif + + static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) + { +@@ -2848,6 +2852,7 @@ unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit) + return get_id_from_rcc_bit(offset, bit); + } + ++#if !STM32MP_SSP + #ifdef IMAGE_BL32 + /* + * Get the parent ID of the target parent clock, for tagging as secure +@@ -3449,6 +3454,7 @@ static void sync_earlyboot_clocks_state(void) + + stm32mp_clk_enable(RTCAPB); + } ++#endif /* !STM32MP_SSP */ + + int stm32mp1_clk_probe(void) + { +@@ -3458,7 +3464,9 @@ int stm32mp1_clk_probe(void) + + stm32mp1_osc_init(); + ++#if !STM32MP_SSP + sync_earlyboot_clocks_state(); ++#endif + + /* Save current CPU operating point value */ + freq_khz = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000UL); +diff --git a/drivers/st/io/io_programmer_st_usb.c b/drivers/st/io/io_programmer_st_usb.c +index 20da965..02ade11 100644 +--- a/drivers/st/io/io_programmer_st_usb.c ++++ b/drivers/st/io/io_programmer_st_usb.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + + #define USB_STATE_READY 0 +@@ -89,13 +90,22 @@ static uint16_t usb_callback_write_done(uint32_t *written_in, uint32_t len) + } + + /* Call back to notify that a read memory is requested */ +-static uint8_t *usb_callback_read(uint8_t *src, uint8_t *dest, uint32_t len) ++static uint16_t usb_callback_read(uint8_t *src, uint8_t *dest, uint32_t len) + { ++#if STM32MP_SSP ++ if (current_phase.phase_id == SSP_PHASE) { ++ const size_t size = SSP_KEY_CERTIFICATE_SIZE * sizeof(uint32_t); ++ ++ if (len >= size) { ++ memcpy(dest, src, size); ++ return size; ++ } ++ } ++#else + ERROR("%s read is not supported src 0x%lx dest 0x%lx len %i\n", + __func__, (uintptr_t)src, (uintptr_t)dest, len); +- +- /* Return a valid address to avoid HardFault */ +- return (uint8_t *)(dest); ++#endif ++ return 0; + } + + /* Get the status to know if written operation has been checked */ +@@ -173,10 +183,11 @@ static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) + { + int result; ++#if !STM32MP_SSP + uint32_t length = 0; + boot_api_image_header_t *header = + (boot_api_image_header_t *)first_usb_buffer; +- ++#endif + const struct stm32image_part_info *partition_spec = + (struct stm32image_part_info *)spec; + +@@ -186,7 +197,7 @@ static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + assert(entity); + + current_phase.current_packet = 0; +- ++#if !STM32MP_SSP + if (!strcmp(partition_spec->name, BL33_IMAGE_NAME)) { + /* read flash layout first for U-boot */ + current_phase.phase_id = PHASE_FLASHLAYOUT; +@@ -221,6 +232,16 @@ static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + current_phase.phase_id = PHASE_SSBL; + current_phase.max_size = dt_get_ddr_size(); + } ++#else ++ if (!strcmp(partition_spec->name, "SSP")) { ++ current_phase.phase_id = SSP_PHASE; ++ current_phase.keep_header = 1; ++ } ++ ++ if (!strcmp(partition_spec->name, "SSP_INIT")) { ++ current_phase.phase_id = RESET_PHASE; ++ } ++#endif + entity->info = (uintptr_t)¤t_phase; + result = 0; + } else { +@@ -267,6 +288,64 @@ static int usb_block_seek(io_entity_t *entity, int mode, + } + + /* Read data from a file on the usb device */ ++#if STM32MP_SSP ++static int usb_block_read(io_entity_t *entity, uintptr_t buffer, ++ size_t length, size_t *length_read) ++{ ++ uint64_t timeout; ++ uint32_t detach_timeout = DETACH_TIMEOUT; ++ ssp_exchange_t *exchange = (ssp_exchange_t *)buffer; ++ ++ if (current_phase.phase_id == RESET_PHASE) { ++ usb_dfu_set_phase_id(RESET_PHASE); ++ usb_dfu_set_upload_addr(buffer); ++ usb_dfu_error_msg_size(length); ++ } else { ++ usb_dfu_set_upload_addr((uint32_t)exchange->msg); ++ usb_dfu_set_download_addr((uint32_t)exchange->blob); ++ ++ /* Use flashlayout partition for SSP exchange */ ++ usb_dfu_set_phase_id(PHASE_FLASHLAYOUT); ++ ++ INFO("Start Download partition SSP address 0x%lx length %i\n", ++ (uintptr_t)exchange->blob, length); ++ } ++ ++ while (!usb_dfu_download_is_completed()) { ++ /* Reload watchdog */ ++ stm32_iwdg_refresh(); ++ usb_core_handle_it((usb_handle_t *)usb_dev_info.info); ++ } ++ ++ /* Wait Detach in case */ ++ usb_dfu_set_phase_id(0x0); ++ usb_dfu_set_upload_addr(UNDEFINE_DOWN_ADDR); ++ usb_dfu_request_detach(); ++ timeout = timeout_init_us(IO_USB_TIMEOUT_10_SEC); ++ while (detach_timeout != 0U) { ++ usb_core_handle_it((usb_handle_t *)usb_dev_info.info); ++ ++ if (usb_dfu_detach_req() == 0U) { ++ /* ++ * Continue to handle usb core IT to assure ++ * complete data transmission. ++ */ ++ detach_timeout--; ++ } ++ ++ if (timeout_elapsed(timeout)) { ++ return -EIO; ++ } ++ } ++ ++ /* STOP the USB Handler */ ++ usb_core_stop((usb_handle_t *)usb_dev_info.info); ++ ++ *length_read = length; ++ ++ return 0; ++} ++#else /* STM32MP_SSP */ + static int usb_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) + { +@@ -355,6 +434,7 @@ static int usb_block_read(io_entity_t *entity, uintptr_t buffer, + + return 0; + } ++#endif /* STM32MP_SSP */ + + /* Close a file on the usb device */ + static int usb_block_close(io_entity_t *entity) +diff --git a/drivers/st/uart/io_programmer_uart.c b/drivers/st/uart/io_programmer_uart.c +index 6d024e1..f3c8631 100644 +--- a/drivers/st/uart/io_programmer_uart.c ++++ b/drivers/st/uart/io_programmer_uart.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + /* USART bootloader protocol version V4.0*/ + #define USART_BL_VERSION 0x40 +@@ -31,6 +32,9 @@ static const uint8_t command_tab[] = { + GET_VER_COMMAND, + GET_ID_COMMAND, + PHASE_COMMAND, ++#if STM32MP_SSP ++ READ_PART_COMMAND, ++#endif + START_COMMAND, + DOWNLOAD_COMMAND + }; +@@ -195,8 +199,10 @@ static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + int result = -EIO; + const struct stm32image_part_info *partition_spec = + (struct stm32image_part_info *)spec; ++#if !STM32MP_SSP + uint32_t length = 0; + uint32_t layout_length = 0; ++#endif + + /* Use PHASE_FSBL1 like init value*/ + if (current_phase.phase_id == PHASE_FSBL1) { +@@ -205,6 +211,7 @@ static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + + current_phase.current_packet = 0; + ++#if !STM32MP_SSP + if (!strcmp(partition_spec->name, BL33_IMAGE_NAME)) { + /* read flashlayout first for U-boot */ + current_phase.phase_id = PHASE_FLASHLAYOUT; +@@ -224,6 +231,18 @@ static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + current_phase.max_size = dt_get_ddr_size(); + current_phase.keep_header = 0; + } ++#else ++ if (!strcmp(partition_spec->name, "SSP")) { ++ current_phase.phase_id = SSP_PHASE; ++ header_length_read = 0; ++ } ++ ++ if (!strcmp(partition_spec->name, "SSP_INIT")) { ++ current_phase.phase_id = RESET_PHASE; ++ header_length_read = 0; ++ } ++#endif ++ + entity->info = (uintptr_t)¤t_phase; + result = 0; + } else { +@@ -303,17 +322,128 @@ static int get_id_command(void) + return 0; + } + +-static int uart_send_phase(uint32_t address) ++static int uart_send_phase(uint32_t address, size_t length) + { +- uart_write_byte(0x05); /* length of data - 1 */ ++ size_t local_length = 0; ++ uint32_t i; ++ ++ if (current_phase.phase_id == RESET_PHASE) { ++ local_length = length; ++ } ++ ++ if ((local_length + 5U) > UINT8_MAX) { ++ return -EINVAL; ++ } ++ ++ uart_write_byte(local_length + 5U); /* length of data - 1 */ ++ + /* Send the ID of next partition */ + uart_write_byte(current_phase.phase_id); /* partition ID */ + + uart_write_uint32(address); /* destination address */ +- uart_write_byte(0x00); /* length of extra data */ ++ ++ uart_write_byte(local_length); /* length of extra data */ ++ ++ for (i = 0; i < local_length; i++) { ++ uart_write_byte(((char *)address)[i]); ++ } ++ ++ return 0; ++} ++ ++#if STM32MP_SSP ++static int uart_read_part(uint8_t *buffer, size_t length, size_t *length_read) ++{ ++ uint8_t byte = 0U; ++ uint8_t xor = 0U; ++ uint8_t partid = 0U; ++ uint16_t size = 0U; ++ uint32_t start_address = 0U; ++ uint32_t i; ++ ++ /* Get partition id */ ++ if (uart_read_byte(&partid) != 0) { ++ return -EIO; ++ } ++ ++ if (partid != SSP_PART_ID) { ++ return -EPERM; ++ } ++ ++ xor = partid; ++ ++ /* Get address */ ++ for (i = 4U; i > 0U; i--) { ++ if (uart_read_byte(&byte) != 0) { ++ return -EIO; ++ } ++ ++ xor ^= byte; ++ start_address = (start_address << 8) | byte; ++ } ++ ++ /* Checksum */ ++ if (uart_read_byte(&byte) != 0) { ++ return -EIO; ++ } ++ ++ if (xor != byte) { ++ WARN("UART: Start cmd: address checksum: %x != %x\n", ++ xor, byte); ++ return -EPROTO; ++ } ++ ++ uart_write_byte(ACK_BYTE); ++ ++ /* Get number of bytes to send */ ++ if (uart_read_byte(&byte) != 0) { ++ return -EIO; ++ } ++ ++ xor = byte; ++ ++ /* Send Size + 1 */ ++ size = byte++; ++ ++ /* Checksum */ ++ if (uart_read_byte(&byte) != 0) { ++ return -EIO; ++ } ++ ++ if ((xor ^ byte) != 0xFF) { ++ WARN("UART: Start cmd: length checksum: %x != %x\n", xor, byte); ++ return -EPROTO; ++ } ++ ++ uart_write_byte(ACK_BYTE); ++ ++ switch (partid) { ++ case SSP_PART_ID: ++ if ((start_address != 0U) || ++ (size < (SSP_KEY_CERTIFICATE_SIZE * sizeof(uint32_t)))) { ++ return -EIO; ++ } ++ ++ for (i = 0U; ++ i < (SSP_KEY_CERTIFICATE_SIZE * sizeof(uint32_t)); ++ i++, buffer++) { ++ uart_write_byte(*buffer); ++ } ++ ++ for (; i < size; i++) { ++ uart_write_byte(0x0); ++ } ++ ++ break; ++ ++ default: ++ WARN("Not supported\n"); ++ return -EPROTO; ++ } + + return 0; + } ++#endif /* STM32MP_SSP */ + + static int uart_download_part(uint8_t *buffer, uint32_t *length_read) + { +@@ -325,15 +455,23 @@ static int uart_download_part(uint8_t *buffer, uint32_t *length_read) + int i = 0; + volatile uint8_t *ptr = (uint8_t *)buffer; + +- /* get operation number */ +- if (uart_read_byte(&operation)) ++ /* Get operation number */ ++ if (uart_read_byte(&operation) != 0) { + return -EIO; ++ } ++ + xor = operation; + +- /* get packet Number */ +- for (i = 3, byte = 0; i > 0; i--) { +- if (uart_read_byte(&byte)) ++ if ((operation != 0x0) && (operation != 0xF3)) { ++ return -EPERM; ++ } ++ ++ /* Get packet number */ ++ for (i = 3; i > 0; i--) { ++ if (uart_read_byte(&byte) != 0) { + return -EIO; ++ } ++ + xor ^= byte; + packet_number = (packet_number << 8) | byte; + } +@@ -430,6 +568,12 @@ static int uart_start_cmd(boot_api_image_header_t *header, uintptr_t buffer) + + return stm32mp_check_header(header, buffer); + ++#if STM32MP_SSP ++ case SSP_PHASE: ++ current_phase.phase_id = RESET_PHASE; ++ break; ++#endif ++ + default: + ERROR("Invalid phase ID : %i\n", current_phase.phase_id); + return -EINVAL; +@@ -447,6 +591,9 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer, + uint32_t ptr_offset = 0; + uint8_t command = 0; + uint8_t all_commands_done = 0; ++#if STM32MP_SSP ++ ssp_exchange_t *exchange = (ssp_exchange_t *)buffer; ++#endif + boot_api_image_header_t *header = + (boot_api_image_header_t *)&header_buffer[0]; + +@@ -508,12 +655,44 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer, + break; + + case PHASE_COMMAND: +- result = uart_send_phase((uint32_t)buffer); ++ result = uart_send_phase((uint32_t)buffer, length); ++#if STM32MP_SSP ++ if (current_phase.phase_id == RESET_PHASE) { ++ all_commands_done = 1; ++ } ++#endif + break; + ++#if STM32MP_SSP ++ case READ_PART_COMMAND: ++ result = uart_read_part((uint8_t *)(buffer), length, ++ length_read); ++ ++ if (result == 0) { ++ /* No ACK_BYTE needed */ ++ continue; ++ } ++ ++ break; ++#endif ++ + case DOWNLOAD_COMMAND: +- result = uart_download_part((uint8_t *)(buffer + +- ptr_offset), ++#if STM32MP_SSP ++ result = uart_download_part((uint8_t *) ++ (exchange->blob + ++ ptr_offset), ++ &read_length); ++ if (!result) { ++ ptr_offset += read_length; ++ total_length += read_length; ++ if (total_length > length) { ++ /* Buffer too long */ ++ all_commands_done = 1; ++ } ++ } ++#else ++ result = uart_download_part((uint8_t *) ++ (buffer + ptr_offset), + &read_length); + if (!result) { + ptr_offset += read_length; +@@ -524,6 +703,7 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer, + all_commands_done = 1; + } + } ++#endif + + break; + +@@ -531,7 +711,6 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer, + result = uart_start_cmd(header, buffer); + if (!result) + all_commands_done = 1; +- + break; + + default: +@@ -557,8 +736,7 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer, + *length_read = total_length; + + INFO("Read block in buffer 0x%lx size 0x%x phase ID %i\n", +- buffer, length, current_phase.phase_id); +- ++ buffer, *length_read, current_phase.phase_id); + return 0; + } + +diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi +index 6e6dff4..087481d 100644 +--- a/fdts/stm32mp151.dtsi ++++ b/fdts/stm32mp151.dtsi +@@ -41,7 +41,12 @@ + <&nand_otp>, + <&uid_otp>, + <&package_otp>, +- <&hw2_otp>; ++ <&hw2_otp>, ++ <&pkh_otp>, ++ <&cfg2_otp>, ++ <&ssp_otp>, ++ <&chip_otp>, ++ <&rma_otp>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", +@@ -49,7 +54,12 @@ + "nand_otp", + "uid_otp", + "package_otp", +- "hw2_otp"; ++ "hw2_otp", ++ "pkh_otp", ++ "cfg2_otp", ++ "ssp_otp", ++ "chip_otp", ++ "rma_otp"; + }; + + psci { +@@ -456,9 +466,15 @@ + part_number_otp: part_number_otp@4 { + reg = <0x4 0x1>; + }; ++ cfg2_otp: cfg2_otp@8 { ++ reg = <0x8 0x4>; ++ }; + monotonic_otp: monotonic_otp@10 { + reg = <0x10 0x4>; + }; ++ ssp_otp: ssp_otp@20 { ++ reg = <0x20 0x4>; ++ }; + nand_otp: nand_otp@24 { + reg = <0x24 0x4>; + }; +@@ -480,6 +496,12 @@ + pkh_otp: pkh_otp@60 { + reg = <0x60 0x20>; + }; ++ chip_otp: chip_otp@a0 { ++ reg = <0xa0 0x40>; ++ }; ++ rma_otp: rma_otp@e0 { ++ reg = <0xe0 0x4>; ++ }; + mac_addr: mac_addr@e4 { + reg = <0xe4 0x8>; + st,non-secure-otp; +diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi +index 53790f2..787c1f2 100644 +--- a/fdts/stm32mp15xx-dkx.dtsi ++++ b/fdts/stm32mp15xx-dkx.dtsi +@@ -289,7 +289,11 @@ + <&package_otp>, + <&hw2_otp>, + <&pkh_otp>, +- <&board_id>; ++ <&board_id>, ++ <&cfg2_otp>, ++ <&ssp_otp>, ++ <&chip_otp>, ++ <&rma_otp>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", +@@ -299,7 +303,11 @@ + "package_otp", + "hw2_otp", + "pkh_otp", +- "board_id"; ++ "board_id", ++ "cfg2_otp", ++ "ssp_otp", ++ "chip_otp", ++ "rma_otp"; + }; + + &pwr_regulators { +diff --git a/fdts/stm32mp15xx-edx.dtsi b/fdts/stm32mp15xx-edx.dtsi +index dd92190..26f2a14 100644 +--- a/fdts/stm32mp15xx-edx.dtsi ++++ b/fdts/stm32mp15xx-edx.dtsi +@@ -296,7 +296,11 @@ + <&package_otp>, + <&hw2_otp>, + <&pkh_otp>, +- <&board_id>; ++ <&board_id>, ++ <&cfg2_otp>, ++ <&ssp_otp>, ++ <&chip_otp>, ++ <&rma_otp>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", +@@ -306,7 +310,11 @@ + "package_otp", + "hw2_otp", + "pkh_otp", +- "board_id"; ++ "board_id", ++ "cfg2_otp", ++ "ssp_otp", ++ "chip_otp", ++ "rma_otp"; + }; + + &pwr_regulators { +diff --git a/include/drivers/st/io_programmer.h b/include/drivers/st/io_programmer.h +index c6c2de1..6f3fd44 100644 +--- a/include/drivers/st/io_programmer.h ++++ b/include/drivers/st/io_programmer.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -12,12 +12,18 @@ + #define PHASE_FSBL1 1 + #define PHASE_FSBL2 2 + #define PHASE_SSBL 3 ++#define RESET_PHASE 0xFF ++ ++#if STM32MP_SSP ++#define SSP_PHASE 0xF3 ++#endif + + /* Command definition */ + #define GET_CMD_COMMAND 0x00 + #define GET_VER_COMMAND 0x01 + #define GET_ID_COMMAND 0x02 + #define PHASE_COMMAND 0x03 ++#define READ_PART_COMMAND 0x12 + #define START_COMMAND 0x21 + #define DOWNLOAD_COMMAND 0x31 + +diff --git a/include/lib/ssp_lib.h b/include/lib/ssp_lib.h +new file mode 100644 +index 0000000..26232d1 +--- /dev/null ++++ b/include/lib/ssp_lib.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef SSP_LIB_H ++#define SSP_LIB_H ++#include ++ ++/* Constants */ ++#define SSP_BLOB_FILE_MAX_ADDR (BL2_RW_LIMIT - PLAT_XLAT_SIZE) ++#define SSP_KEY_CERTIFICATE_SIZE U(34) // 4 * 34 bytes : 136 bytes ++#define SSP_PART_ID 0xF3 ++ ++/* ++ * SSP message format for flashloader exchange. ++ * ++ * msg: Message containing public key and certificate. ++ * blob: Output buffer for encrypted file. ++ */ ++typedef struct ssp_exchange { ++ uint32_t msg[SSP_KEY_CERTIFICATE_SIZE]; ++ uint8_t *blob; ++} ssp_exchange_t __aligned(4); ++ ++/* ++ * Start the SSP processing. ++ * ++ * Parameters: ++ * boot_context : Shared boot_context ++ */ ++void ssp_start(boot_api_context_t *boot_context); ++ ++#endif /* SSP_LIB_H */ +diff --git a/include/lib/usb/usb_st_dfu.h b/include/lib/usb/usb_st_dfu.h +index 8a3a5a5..57f4e8f 100644 +--- a/include/lib/usb/usb_st_dfu.h ++++ b/include/lib/usb/usb_st_dfu.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -89,7 +89,11 @@ typedef enum { + typedef void (*p_function)(void); + + typedef struct { ++#if STM32MP_SSP ++ uint8_t buffer[512]; ++#else + uint8_t buffer[10]; ++#endif + uint8_t dev_state; + uint8_t dev_status[DFU_STATUS_DEPTH]; + uint8_t manif_state; +@@ -101,16 +105,18 @@ typedef struct { + + typedef struct { + uint16_t (*write_done)(uint32_t *written_in, uint32_t len); +- uint8_t* (*read)(uint8_t *src, uint8_t *dest, uint32_t len); ++ uint16_t (*read)(uint8_t *src, uint8_t *dest, uint32_t len); + uint16_t (*get_status)(void); + } usb_dfu_media_t; + + void usb_dfu_register_callback(usb_handle_t *pdev); + void usb_dfu_set_phase_id(uint32_t phase_id); + void usb_dfu_set_download_addr(uintptr_t addr); ++void usb_dfu_set_upload_addr(uintptr_t addr); + uint32_t usb_dfu_download_is_completed(void); + uint32_t usb_dfu_get_current_req(void); + uint32_t usb_dfu_detach_req(void); + void usb_dfu_request_detach(void); ++void usb_dfu_error_msg_size(uint32_t size); + + #endif /* USB_ST_DFU_H */ +diff --git a/lib/ssp/ssp.c b/lib/ssp/ssp.c +new file mode 100644 +index 0000000..dff8bfe +--- /dev/null ++++ b/lib/ssp/ssp.c +@@ -0,0 +1,748 @@ ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Local status for SSP processing sequences */ ++typedef enum { ++ SSP_NONE, ++ SSP_GET_CERT, ++ SSP_FLASH_OEM, ++ SSP_DONE, ++ SSP_ERROR ++} ssp_result_e; ++ ++struct otp_val { ++ uint32_t idx; ++ uint32_t nb; ++}; ++ ++static struct otp_val otp_ssp; ++static struct otp_val otp_rma; ++static struct otp_val otp_pubkey; ++ ++static int initialize_otp(void) ++{ ++ uint32_t len; ++ ++ /* OTP SSP */ ++ if (stm32_get_otp_index(SSP_OTP, &otp_ssp.idx, NULL) != 0) { ++ VERBOSE("%s: get index error\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* OTP public key */ ++ if (stm32_get_otp_index(PKH_OTP, &(otp_pubkey.idx), &len) != 0) { ++ VERBOSE("%s: get index error\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) { ++ VERBOSE("%s: length Error\n", __func__); ++ return -EINVAL; ++ } ++ ++ otp_pubkey.nb = len / (CHAR_BIT * sizeof(uint32_t)); ++ ++ /* OTP RMA */ ++ if (stm32_get_otp_index(RMA_OTP, &otp_rma.idx, NULL) != 0) { ++ VERBOSE("%s: get index error\n", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Return device handler for flashloader interface. ++ */ ++static int ssp_get_loader_handle(uintptr_t *dev_handle, uintptr_t *dev_spec) ++{ ++ int result; ++ ++ /* Obtain a reference to the image handle to get boot device */ ++ result = plat_get_image_source(BL33_IMAGE_ID, dev_handle, dev_spec); ++ if (result != 0) { ++ WARN("Failed to obtain reference to image '%s' (%i)\n", ++ BL33_IMAGE_NAME, result); ++ return -EINVAL; ++ } ++ ++ return result; ++} ++ ++/* ++ * Compute HASH from public key and burn it in OTP. ++ */ ++static int ssp_pub_key_prog(boot_api_context_t *boot_context) ++{ ++ uint8_t key_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; ++ uint8_t *pubk = (uint8_t *) ++ boot_context->p_ssp_config->p_blob_payload->oem_ecdsa_pubk; ++ uint32_t *value = (uint32_t *)key_hash; ++ uint32_t i; ++ ++ if (stm32_hash_register() != 0) { ++ return -EINVAL; ++ } ++ ++ stm32_hash_init(HASH_SHA256); ++ ++ if (stm32_hash_final_update(pubk, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES, ++ key_hash) != 0) { ++ ERROR("Hash of payload failed\n"); ++ return -EINVAL; ++ } ++ ++ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) { ++ if (bsec_program_otp(bswap32(*value), i) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++ value++; ++ if (bsec_permanent_lock_otp(i) != BSEC_OK) { ++ ERROR("Error locking OTP %i\n", i); ++ panic(); ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Burn OTP to close device. ++ */ ++static int ssp_close_device(void) ++{ ++ uint32_t otp; ++ uint32_t value; ++ ++ if (stm32_get_otp_index(CFG0_OTP, &otp, NULL) != 0) { ++ return -EINVAL; ++ } ++ ++ if (bsec_read_otp(&value, otp) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++ if ((value & CFG0_CLOSED_DEVICE) != 0U) { ++ ERROR("Device already closed\n"); ++ return -EINVAL; ++ } ++ ++ value |= CFG0_CLOSED_DEVICE; ++ if (bsec_program_otp(value, otp) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * OTP initial check to detect previous values. ++ */ ++static int ssp_secrets_check(boot_api_context_t *boot_ctx) ++{ ++ uint32_t i; ++ uint32_t check_val; ++ uint32_t otp_byte = ++ boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes; ++ uint32_t otp_decrypted = round_up(otp_byte, sizeof(uint32_t)) / ++ sizeof(uint32_t); ++ ++ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) { ++ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (check_val != 0U) { ++ ERROR("OTP %d value already programmed\n", i); ++ return -EINVAL; ++ } ++ } ++ ++ /* OTP decrypted include RMA password */ ++ if (otp_decrypted > (2U + SSP_OTP_SECRET_END - SSP_OTP_SECRET_BASE)) { ++ return -EINVAL; ++ } ++ ++ /* Check RMA password */ ++ if (stm32_get_otp_value_from_idx(otp_rma.idx, &check_val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (check_val != 0U) { ++ ERROR("OTP %s value already programmed\n", RMA_OTP); ++ return -EINVAL; ++ } ++ ++ /* Check all OTP available */ ++ for (i = SSP_OTP_SECRET_BASE; ++ i < SSP_OTP_SECRET_BASE + otp_decrypted - 1; i++) { ++ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (check_val != 0U) { ++ ERROR("OTP %d value already programmed\n", i); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Burn OTP with the decrypted secret received. ++ */ ++static int ssp_secrets_flash(boot_api_context_t *boot_ctx) ++{ ++ uint32_t i; ++ uint32_t *val; ++ uint32_t otp_byte = ++ boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes; ++ uint32_t otp_decrypted = round_up(otp_byte, sizeof(uint32_t)) / ++ sizeof(uint32_t); ++ uint32_t otp_mask = 0U; ++ ++ if (otp_byte % sizeof(uint32_t) != 0U) { ++ otp_mask = GENMASK_32(((otp_byte % sizeof(uint32_t)) * ++ sizeof(uint32_t)) - 1, 0); ++ } ++ ++ val = (uint32_t *)boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted; ++ ++ /* Burn RMA password */ ++ if (otp_decrypted != 0U) { ++ if (bsec_program_otp((*val & RMA_OTP_MASK), otp_rma.idx) != ++ BSEC_OK) { ++ WARN("RMA programing failed\n"); ++ return -EINVAL; ++ } ++ ++ val++; ++ otp_decrypted--; ++ ++ for (i = SSP_OTP_SECRET_BASE; ++ i < (SSP_OTP_SECRET_BASE + otp_decrypted - 1); i++) { ++ ++ if (*val == 0U) { ++ val++; ++ continue; ++ } ++ ++ if (bsec_program_otp(*val, i) != BSEC_OK) { ++ WARN("Error writing OTP %i\n", i); ++ return -EINVAL; ++ } ++ ++ if (bsec_permanent_lock_otp(i) != BSEC_OK) { ++ WARN("Error locking OTP %i\n", i); ++ return -EINVAL; ++ } ++ ++ val++; ++ } ++ ++ if (*val != 0U) { ++ /* Mask the last OTP value if needed */ ++ if (otp_mask != 0U) { ++ *val &= otp_mask; ++ } ++ ++ if (bsec_program_otp(*val, i) != BSEC_OK) { ++ WARN("Error writing OTP %i\n", i); ++ return -EINVAL; ++ } ++ ++ if (bsec_permanent_lock_otp(i) != BSEC_OK) { ++ WARN("Error locking OTP %i\n", i); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Finish SSP processing by fusing OTP SSP success. ++ */ ++static int ssp_finish_process(void) ++{ ++ uint32_t val; ++ ++ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) { ++ return -EINVAL; ++ } ++ ++ if ((val & SSP_OTP_SUCCESS) != 0U) { ++ WARN("Error while configuring OTP\n"); ++ return -EINVAL; ++ } ++ ++ val |= SSP_OTP_SUCCESS; ++ if (bsec_program_otp(val, otp_ssp.idx) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++ VERBOSE("Write OTP Success\n"); ++ ++ return 0; ++} ++ ++/* ++ * Transform integer to string. ++ */ ++static void itoa(uint32_t num, char *str, int nb) ++{ ++ if (num == 0U) { ++ while (nb--) { ++ str[nb] = '0'; ++ } ++ return; ++ } ++ ++ while (num != 0U) { ++ int rem = num % 16; ++ ++ str[--nb] = (rem > 9) ? (rem - 10) + 'A' : rem + '0'; ++ num /= 16; ++ } ++ ++ while (nb != 0) { ++ str[--nb] = '0'; ++ } ++} ++ ++/* ++ * Return chip product ID. ++ */ ++static int ssp_get_product_id(char *msg) ++{ ++ uint32_t otp; ++ uint32_t otp_idx; ++ uint32_t chip_id; ++ ++ if (stm32_get_otp_index(CFG2_OTP, &otp_idx, NULL) != 0) { ++ VERBOSE("Get index error\n"); ++ return -EINVAL; ++ } ++ ++ if (stm32_get_otp_value_from_idx(otp_idx, &otp) != 0) { ++ return -EINVAL; ++ } ++ ++ if (stm32mp1_dbgmcu_get_chip_dev_id(&chip_id) < 0) { ++ return -EINVAL; ++ } ++ ++ itoa(chip_id, msg, 3); ++ itoa((otp & OTP_CFG2_SEC_COUNTER_MASK) >> ++ OTP_CFG2_SEC_COUNTER_SHIFT, msg + 3, 2); ++ ++ itoa(0, msg + 5, 1); ++ itoa((otp & OTP_CFG2_ST_KEY_MASK) >> ++ OTP_CFG2_ST_KEY_SHIFT, msg + 6, 2); ++ ++ return 0; ++} ++ ++/* ++ * Clean external data and bootrom context secret values. ++ */ ++static void ssp_cleanup(boot_api_context_t *boot_context) ++{ ++ boot_api_ssp_config_t *ssp_config = boot_context->p_ssp_config; ++ ++ /* Cleanup boot_context */ ++ if (ssp_config->p_ssp_oem_secrets_decrypted != NULL) { ++ zeromem(ssp_config->p_ssp_oem_secrets_decrypted, ++ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES); ++ zeromem(ssp_config->p_chip_pubk, ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); ++ zeromem(ssp_config->p_blob_license, ++ sizeof(boot_api_ssp_blob_license_t)); ++ zeromem(ssp_config->p_blob_payload, ++ sizeof(boot_api_ssp_blob_payload_t)); ++ } ++ ++ ssp_config->ssp_cmd = 0U; ++ ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)ssp_config->p_ssp_oem_secrets_decrypted, ++ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES); ++ ++ flush_dcache_range((uintptr_t)ssp_config->p_chip_pubk, ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); ++ ++ flush_dcache_range((uintptr_t)ssp_config->p_blob_license, ++ sizeof(boot_api_ssp_blob_license_t)); ++ ++ flush_dcache_range((uintptr_t)ssp_config->p_blob_payload, ++ sizeof(boot_api_ssp_blob_payload_t)); ++#endif ++ ++ ssp_config->p_ssp_oem_secrets_decrypted = NULL; ++ ssp_config->p_chip_pubk = NULL; ++ ssp_config->p_blob_license = NULL; ++ ssp_config->p_blob_payload = NULL; ++ ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)boot_context, ++ sizeof(boot_api_context_t)); ++ ++ flush_dcache_range((uintptr_t)ssp_config, ++ sizeof(boot_api_ssp_config_t)); ++#endif ++} ++ ++/* ++ * Send certificate to the programmer and retrieve the associated ++ * encrypted file. ++ */ ++static int ssp_download_phase(boot_api_context_t *boot_ctx) ++{ ++ uint32_t i; ++ uint32_t j; ++ uint32_t otp; ++ uint32_t otp_idx; ++ uint32_t otp_len; ++ uint8_t *blob_file; ++ int result = 0; ++ uintptr_t dev_handle, handle, dev_spec; ++ size_t length_read; ++ struct stm32image_part_info partition_spec = { ++ .name = "SSP" ++ }; ++ ++ blob_file = (uint8_t *)page_align(SSP_BLOB_FILE_MAX_ADDR - ++ sizeof(boot_api_ssp_blob_license_t) - ++ sizeof(boot_api_ssp_blob_payload_t), ++ DOWN); ++ ++ ssp_exchange_t flash_exch = { ++ .blob = blob_file ++ }; ++ ++ /* Prepare the ROM Security constant */ ++ if (ssp_get_product_id((char *)flash_exch.msg) != 0) { ++ return -EINVAL; ++ } ++ ++ /* Prepare public key and certificate for flashloader */ ++ /* Read Public Key from boot_context */ ++ memcpy((uint8_t *)flash_exch.msg + 8, ++ boot_ctx->p_ssp_config->p_chip_pubk, ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); ++ ++ if (stm32_get_otp_index(CHIP_CERTIFICATE_OTP, ++ &otp_idx, &otp_len) != 0) { ++ VERBOSE("Get index error\n"); ++ return -EINVAL; ++ } ++ ++ if (otp_len != (CHAR_BIT * CHIP_CERTIFICATE_MAX_SIZE)) { ++ VERBOSE("Length Error\n"); ++ return -EINVAL; ++ } ++ ++ otp_len /= (CHAR_BIT * sizeof(uint32_t)); ++ ++ /* Read Certificat from OTP */ ++ for (i = otp_idx, j = 0; i < (otp_idx + otp_len); i++, j++) { ++ stm32_get_otp_value_from_idx(i, &otp); ++ flash_exch.msg[18 + j] = bswap32(otp); ++ } ++ ++ if (ssp_get_loader_handle(&dev_handle, &dev_spec) != 0) { ++ WARN("Error while retrieving handle\n"); ++ return -ENOENT; ++ } ++ ++ result = io_open(dev_handle, (uintptr_t)&partition_spec, &handle); ++ if (result != 0) { ++ WARN("SSP io open error %i\n", result); ++ return -EINVAL; ++ } ++ ++ result = io_read(handle, (uintptr_t)&flash_exch, ++ sizeof(boot_api_ssp_blob_license_t) + ++ sizeof(boot_api_ssp_blob_payload_t), ++ &length_read); ++ if (result != 0) { ++ WARN("SSP read command error %i\n", result); ++ return -EINVAL; ++ } ++ ++ boot_ctx->p_ssp_config->p_blob_license = ++ (boot_api_ssp_blob_license_t *)blob_file; ++ ++ /* Payload is concatene with license file */ ++ boot_ctx->p_ssp_config->p_blob_payload = ++ (boot_api_ssp_blob_payload_t *)(blob_file + ++ sizeof(boot_api_ssp_blob_license_t)); ++ ++ /* Set return address for decrypted_secrets */ ++ boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted = ++ boot_ctx->p_ssp_config->p_blob_payload->oem_encrypted_secrets; ++ ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)boot_ctx->p_ssp_config->p_blob_license, ++ sizeof(boot_api_ssp_blob_license_t)); ++ flush_dcache_range((uintptr_t)boot_ctx->p_ssp_config->p_blob_payload, ++ sizeof(boot_api_ssp_blob_payload_t)); ++#endif ++ result = io_close(handle); ++ ++ return result; ++} ++ ++/* ++ * Burn decrypted secrets into OTP, clean memory and close the device. ++ */ ++static int ssp_secret_programming(boot_api_context_t *boot_context) ++{ ++ int result; ++ ++ result = ssp_secrets_check(boot_context); ++ if (result != 0) { ++ WARN("SSP ERROR checking OTP\n"); ++ goto clean; ++ } ++ ++ result = ssp_pub_key_prog(boot_context); ++ if (result != 0) { ++ WARN("SSP ERROR writing HASH key\n"); ++ goto clean; ++ } ++ ++ result = ssp_close_device(); ++ if (result != 0) { ++ WARN("SSP close device failed\n"); ++ goto clean; ++ } ++ ++ result = ssp_secrets_flash(boot_context); ++ if (result != 0) { ++ WARN("SSP Secret flash failed\n"); ++ } ++ ++clean: ++ ssp_cleanup(boot_context); ++ ++ if (result != 0) { ++ return result; ++ } ++ ++ return ssp_finish_process(); ++} ++ ++/* ++ * Enable the SSP processing. ++ */ ++static int ssp_enable_processing(boot_api_context_t *boot_context) ++{ ++ static const char buf_err[] = "Provisioning"; ++ uint32_t val; ++ int result; ++ uintptr_t dev_handle, handle, dev_spec; ++ size_t length_read; ++ struct stm32image_part_info partition_spec = { ++ .name = "SSP_INIT" ++ }; ++ ++ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (((val & SSP_OTP_MASK) == SSP_OTP_MASK) || ++ ((val & SSP_OTP_MASK) == SSP_OTP_SUCCESS)) { ++ return -EINVAL; ++ } ++ ++ if ((val & SSP_OTP_MASK) == 0U) { ++ if (bsec_program_otp(SSP_OTP_REQ, otp_ssp.idx) != BSEC_OK) { ++ return -EINVAL; ++ } ++ } ++ ++ if (ssp_get_loader_handle(&dev_handle, &dev_spec) != 0) { ++ WARN("Error while retrieving handle\n"); ++ return -ENOENT; ++ } ++ ++ result = io_open(dev_handle, (uintptr_t)&partition_spec, &handle); ++ if (result != 0) { ++ WARN("SSP io open error %i\n", result); ++ return -EINVAL; ++ } ++ ++ result = io_read(handle, (uintptr_t)&buf_err, sizeof(buf_err), ++ &length_read); ++ if (result != 0) { ++ WARN("SSP read command error %i\n", result); ++ return -EINVAL; ++ } ++ ++ result = io_close(handle); ++ if (result != 0) { ++ WARN("SSP io close error %i\n", result); ++ return -EINVAL; ++ } ++ ++ boot_context->p_ssp_config->ssp_cmd = ++ BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK; ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, ++ sizeof(boot_api_ssp_config_t)); ++#endif ++ return 0; ++} ++ ++/* ++ * Retrieve the current status of the SSP from bootrom context and OTP value. ++ */ ++static ssp_result_e ssp_check_status(boot_api_context_t *boot_context) ++{ ++ uint32_t otp; ++ ++ if (initialize_otp() < 0) { ++ return SSP_ERROR; ++ } ++ ++ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &otp) != 0) { ++ return SSP_ERROR; ++ } ++ ++ if ((otp & SSP_OTP_REQ) == 0U) { ++ return SSP_NONE; ++ } ++ ++ if ((otp & SSP_OTP_SUCCESS) != 0U) { ++ return SSP_DONE; ++ } ++ ++ VERBOSE("Start Get ssp_cmd : %x\n", ++ boot_context->p_ssp_config->ssp_cmd); ++ ++ switch (boot_context->p_ssp_config->ssp_cmd) { ++ case BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK: ++ INFO("Detected start SSP Phase 2\n"); ++ return SSP_GET_CERT; ++ case BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK: ++ INFO("Detected start SSP Phase 3\n"); ++ return SSP_FLASH_OEM; ++ default: ++ return SSP_NONE; ++ } ++} ++ ++/* ++ * Start the SSP processing. ++ */ ++void ssp_start(boot_api_context_t *boot_context) ++{ ++ int result; ++ ++ switch (ssp_check_status(boot_context)) { ++ case SSP_GET_CERT: ++ result = ssp_download_phase(boot_context); ++ if (result != 0) { ++ /* ++ * Download Phase failed, clean, reset ++ */ ++ ssp_cleanup(boot_context); ++ ++ ERROR("SSP_Error: Resetting target\n"); ++ goto out; ++ } ++ ++ /* Process completed, go to Phase 3 */ ++ boot_context->p_ssp_config->ssp_cmd = ++ BOOT_API_CTX_SSP_CMD_PROV_SECRET; ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, ++ sizeof(boot_api_ssp_config_t)); ++#endif ++ break; ++ ++ case SSP_FLASH_OEM: ++ result = ssp_secret_programming(boot_context); ++ if (result != 0) { ++ ERROR("Error during provisionning\n"); ++ goto out; ++ } ++ ++ NOTICE("Provisioning completed\n"); ++ goto out; ++ ++ case SSP_ERROR: ++ /* ++ * Error during bootrom SSP processing ++ */ ++ ERROR("SSP_Error: Resetting target\n"); ++ goto out; ++ ++ case SSP_NONE: ++ default: ++ result = ssp_enable_processing(boot_context); ++ if (result != 0) { ++ ERROR("Start SSP Failed (%i)\n", result); ++ goto out; ++ } ++ } ++ ++ if (result == 0) { ++ /* ++ * Keep VDDCORE && VDD enabled if pmic used to generate ++ * the required MPSYSRST. ++ */ ++ if (dt_pmic_status() > 0) { ++ const char *name; ++ ++ name = stm32mp_get_cpu_supply_name(); ++ if (name == NULL) { ++ goto out; ++ } ++ ++ if (stpmic1_regulator_mask_reset_set(name) != 0) { ++ WARN("Failed to write %s reset mask\n", name); ++ } ++ ++ name = stm32mp_get_vdd_supply_name(); ++ if (name == NULL) { ++ goto out; ++ } ++ ++ if (stpmic1_regulator_mask_reset_set(name) != 0) { ++ WARN("Failed to write %s reset mask\n", name); ++ } ++ } ++ } ++ ++out: ++ stm32mp_plat_reset(plat_my_core_pos()); ++} +diff --git a/lib/usb/usb_st_dfu.c b/lib/usb/usb_st_dfu.c +index 8876b74..1c0c2ef 100644 +--- a/lib/usb/usb_st_dfu.c ++++ b/lib/usb/usb_st_dfu.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -12,10 +12,12 @@ + #include + + static uintptr_t usbd_dfu_download_address; ++static uintptr_t usbd_dfu_upload_address; + static uint32_t usbd_dfu_phase_id; + static uint32_t usbd_dfu_operation_complete; + static uint32_t usbd_dfu_current_req; + static uint32_t usbd_detach_req; ++static uint32_t usbd_error_msg_size; + + /* + * @brief USBD_DFU_Init +@@ -370,28 +372,21 @@ static void usb_dfu_upload(usb_handle_t *pdev, usb_setup_req_t *req) + + INFO("UPLOAD :\n"); + INFO("\t\tPhase ID : %i\n", usbd_dfu_phase_id); ++#if STM32MP_SSP + INFO("\t\taddress 0x%lx\n", +- usbd_dfu_download_address); ++ usbd_dfu_upload_address); + + hdfu->buffer[0] = usbd_dfu_phase_id; +- hdfu->buffer[1] = (uint8_t) +- (usbd_dfu_download_address); +- hdfu->buffer[2] = (uint8_t) +- (usbd_dfu_download_address >> +- 8); +- hdfu->buffer[3] = (uint8_t) +- (usbd_dfu_download_address >> +- 16); +- hdfu->buffer[4] = (uint8_t) +- (usbd_dfu_download_address >> +- 24); +- ++ hdfu->buffer[1] = usbd_dfu_upload_address; ++ hdfu->buffer[2] = usbd_dfu_upload_address >> 8; ++ hdfu->buffer[3] = usbd_dfu_upload_address >> 16; ++ hdfu->buffer[4] = usbd_dfu_upload_address >> 24; + hdfu->buffer[5] = 0x00; + hdfu->buffer[6] = 0x00; + hdfu->buffer[7] = 0x00; + hdfu->buffer[8] = 0x00; + +- if ((usbd_dfu_download_address == ++ if ((usbd_dfu_upload_address == + UNDEFINE_DOWN_ADDR) && + (usbd_detach_req)) { + INFO("Send detach request\n"); +@@ -399,10 +394,69 @@ static void usb_dfu_upload(usb_handle_t *pdev, usb_setup_req_t *req) + pdev->ep_in[0].total_length = 10; + pdev->ep_in[0].rem_length = 10; + } else { ++ if (usbd_dfu_phase_id != 0xFF) { ++ pdev->ep_in[0].total_length = 9; ++ pdev->ep_in[0].rem_length = 9; ++ } else { ++ memcpy(&hdfu->buffer[9], ++ (char *) ++ usbd_dfu_upload_address, ++ usbd_error_msg_size); ++ pdev->ep_in[0].total_length = ++ 9 + usbd_error_msg_size; ++ pdev->ep_in[0].rem_length = ++ 9 + usbd_error_msg_size; ++ usbd_dfu_operation_complete = 1; ++ } ++ } ++ ++ if (hdfu->alt_setting != DFU_GET_PHASE) { ++ uint16_t size; ++ ++ /* Change SSP phase */ ++ size = ((usb_dfu_media_t *) ++ pdev->user_data)-> ++ read((uint8_t *) ++ usbd_dfu_upload_address, ++ &hdfu->buffer[9], ++ hdfu->wlength); ++ ++ if (size != 0) { ++ pdev->ep_in[0].total_length += ++ size; ++ pdev->ep_in[0].rem_length += ++ size; ++ } ++ } ++#else /* STM32MP_SSP */ ++ INFO("\t\taddress 0x%lx\n", ++ usbd_dfu_download_address); ++ ++ hdfu->buffer[0] = usbd_dfu_phase_id; ++ hdfu->buffer[1] = usbd_dfu_download_address; ++ hdfu->buffer[2] = usbd_dfu_download_address >> ++ 8; ++ hdfu->buffer[3] = usbd_dfu_download_address >> ++ 16; ++ hdfu->buffer[4] = usbd_dfu_download_address >> ++ 24; ++ hdfu->buffer[5] = 0x00; ++ hdfu->buffer[6] = 0x00; ++ hdfu->buffer[7] = 0x00; ++ hdfu->buffer[8] = 0x00; ++ ++ if ((usbd_dfu_download_address == ++ UNDEFINE_DOWN_ADDR) && ++ (usbd_detach_req)) { ++ INFO("Send detach request\n"); ++ hdfu->buffer[9] = 0x01; ++ pdev->ep_in[0].total_length = 10; ++ pdev->ep_in[0].rem_length = 10; ++ } else { + pdev->ep_in[0].total_length = 9; + pdev->ep_in[0].rem_length = 9; + } +- ++#endif /* STM32MP_SSP */ + /* Send the status data over EP0 */ + pdev->ep0_state = USBD_EP0_DATA_IN; + /* Start the transfer */ +@@ -662,6 +716,10 @@ static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req) + usb_dfu_upload(pdev, req); + break; + ++ case DFU_DNLOAD: ++ usb_dfu_download(pdev, req); ++ break; ++ + case DFU_GETSTATUS: + INFO("GETSTATUS :\n"); + usb_dfu_get_status(pdev); +@@ -759,6 +817,7 @@ static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req) + break; + + case DFU_DETACH: ++ INFO("Receive DFU detach\n"); + usb_dfu_detach(pdev, req); + break; + +@@ -844,6 +903,11 @@ void usb_dfu_set_download_addr(uintptr_t addr) + usbd_dfu_download_address = addr; + } + ++void usb_dfu_set_upload_addr(uintptr_t addr) ++{ ++ usbd_dfu_upload_address = addr; ++} ++ + uint32_t usb_dfu_download_is_completed(void) + { + return usbd_dfu_operation_complete; +@@ -863,3 +927,8 @@ void usb_dfu_request_detach(void) + { + usbd_detach_req = 1; + } ++ ++void usb_dfu_error_msg_size(uint32_t size) ++{ ++ usbd_error_msg_size = size; ++} +diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c +index f94a5c2..6050358 100644 +--- a/plat/st/common/bl2_io_storage.c ++++ b/plat/st/common/bl2_io_storage.c +@@ -128,6 +128,7 @@ static pcd_handle_t pcd_handle; + static const io_dev_connector_t *usb_dev_con; + #endif /* STM32MP_USB_PROGRAMMER */ + ++#if !STM32MP_SSP + #ifdef AARCH32_SP_OPTEE + static const struct stm32image_part_info optee_header_partition_spec = { + .name = OPTEE_HEADER_IMAGE_NAME, +@@ -154,6 +155,7 @@ static const io_block_spec_t bl2_block_spec = { + .offset = BL2_BASE, + .length = STM32MP_BL2_SIZE, + }; ++#endif /* !STM32MP_SSP */ + + static const struct stm32image_part_info bl33_partition_spec = { + .name = BL33_IMAGE_NAME, +@@ -199,7 +201,9 @@ static io_block_spec_t stm32image_block_spec = { + + static const io_dev_connector_t *stm32image_dev_con __unused; + ++#if !STM32MP_SSP + static int open_dummy(const uintptr_t spec); ++#endif + static int open_image(const uintptr_t spec); + static int open_storage(const uintptr_t spec); + +@@ -210,6 +214,7 @@ struct plat_io_policy { + }; + + static const struct plat_io_policy policies[] = { ++#if !STM32MP_SSP + [BL2_IMAGE_ID] = { + .dev_handle = &dummy_dev_handle, + .image_spec = (uintptr_t)&bl2_block_spec, +@@ -237,7 +242,8 @@ static const struct plat_io_policy policies[] = { + .image_spec = (uintptr_t)&bl32_block_spec, + .check = open_dummy + }, +-#endif ++#endif /* AARCH32_SP_OPTEE */ ++#endif /* !STM32MP_SSP */ + [BL33_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&bl33_partition_spec, +@@ -257,10 +263,12 @@ static const struct plat_io_policy policies[] = { + } + }; + ++#if !STM32MP_SSP + static int open_dummy(const uintptr_t spec) + { + return io_dev_init(dummy_dev_handle, 0); + } ++#endif + + static int open_image(const uintptr_t spec) + { +diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h +index ab419f1..65d4806 100644 +--- a/plat/st/common/include/stm32mp_common.h ++++ b/plat/st/common/include/stm32mp_common.h +@@ -23,6 +23,7 @@ bool stm32mp_is_closed_device(void); + bool stm32mp_is_auth_supported(void); + + const char *stm32mp_get_cpu_supply_name(void); ++const char *stm32mp_get_vdd_supply_name(void); + + /* Return the base address of the DDR controller */ + uintptr_t stm32mp_ddrctrl_base(void); +@@ -94,6 +95,11 @@ void stm32mp_print_boardinfo(void); + /* Check HW CPU OPP support */ + bool stm32mp_supports_cpu_opp(uint32_t opp_id); + ++#if STM32MP_SSP ++/* Check HW support SSP */ ++bool stm32mp_supports_ssp(void); ++#endif ++ + /* + * Util for clock gating and to get clock rate for stm32 and platform drivers + * @id: Target clock ID, ID used in clock DT bindings +diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h +index 873bed5..996ed0a 100644 +--- a/plat/st/common/include/stm32mp_dt.h ++++ b/plat/st/common/include/stm32mp_dt.h +@@ -49,6 +49,7 @@ int dt_get_max_opp_freqvolt(uint32_t *freq_khz, uint32_t *voltage_mv); + int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array, + uint32_t *voltage_mv_array); + uint32_t dt_get_pwr_vdd_voltage(void); ++const char *dt_get_vdd_regulator_name(void); + const char *dt_get_cpu_regulator_name(void); + const char *dt_get_board_model(void); + int fdt_get_gpio_bank_pinctrl_node(unsigned int bank); +diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c +index e838995..612358c 100644 +--- a/plat/st/common/stm32mp_common.c ++++ b/plat/st/common/stm32mp_common.c +@@ -170,6 +170,22 @@ const char *stm32mp_get_cpu_supply_name(void) + return supply; + } + ++/* Return VDD supply name */ ++const char *stm32mp_get_vdd_supply_name(void) ++{ ++ const char *supply = NULL; ++ ++ if (dt_pmic_status() > 0) { ++ const char *regulator = dt_get_vdd_regulator_name(); ++ ++ if (regulator != NULL) { ++ dt_pmic_find_supply(&supply, regulator); ++ } ++ } ++ ++ return supply; ++} ++ + #if TRUSTED_BOARD_BOOT + /* Save pointer to last loaded header */ + static boot_api_image_header_t *latest_stm32_header; +diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c +index f6de0b6..b12fc86 100644 +--- a/plat/st/common/stm32mp_dt.c ++++ b/plat/st/common/stm32mp_dt.c +@@ -651,6 +651,33 @@ uint32_t dt_get_pwr_vdd_voltage(void) + } + + /******************************************************************************* ++ * This function retrieves VDD regulator name from DT. ++ * Returns string taken from supply node, NULL otherwise. ++ ******************************************************************************/ ++const char *dt_get_vdd_regulator_name(void) ++{ ++ int node; ++ const fdt32_t *cuint; ++ ++ node = dt_get_node_by_compatible(DT_PWR_COMPAT); ++ if (node < 0) { ++ return NULL; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "vdd-supply", NULL); ++ if (cuint == NULL) { ++ return NULL; ++ } ++ ++ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); ++ if (node < 0) { ++ return NULL; ++ } ++ ++ return (const char *)fdt_getprop(fdt, node, "regulator-name", NULL); ++} ++ ++/******************************************************************************* + * This function retrieves CPU regulator name from DT. + * Returns string taken from supply node, NULL otherwise. + ******************************************************************************/ +diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c +index f475842..57c0983 100644 +--- a/plat/st/common/stm32mp_trusted_boot.c ++++ b/plat/st/common/stm32mp_trusted_boot.c +@@ -32,6 +32,7 @@ int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + VERBOSE("get_rot_pk_hash: get index error\n"); + return -EINVAL; + } ++ + if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) { + VERBOSE("get_rot_pk_hash: length Error\n"); + return -EINVAL; +diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c +index 3f5eb56..e62e911 100644 +--- a/plat/st/stm32mp1/bl2_plat_setup.c ++++ b/plat/st/stm32mp1/bl2_plat_setup.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -41,6 +42,7 @@ + + #define TIMEOUT_US_1MS U(1000) + ++#if !STM32MP_SSP + static const char debug_msg[626] = { + "***************************************************\n" + "** NOTICE NOTICE NOTICE NOTICE NOTICE **\n" +@@ -55,6 +57,7 @@ static const char debug_msg[626] = { + "** **\n" + "***************************************************\n" + }; ++#endif + + static struct console_stm32 console; + static enum boot_device_e boot_device = BOOT_DEVICE_BOARD; +@@ -158,6 +161,11 @@ void bl2_el3_early_platform_setup(u_register_t arg0, + stm32mp_save_boot_ctx_address(arg0); + } + ++#if STM32MP_SSP ++void bl2_platform_setup(void) ++{ ++} ++#else + void bl2_platform_setup(void) + { + int ret; +@@ -217,6 +225,7 @@ void bl2_platform_setup(void) + configure_pmic(); + } + } ++#endif /* STM32MP_SSP */ + + static void update_monotonic_counter(void) + { +@@ -258,9 +267,11 @@ static void initialize_clock(void) + uint32_t freq_khz = 0U; + int ret = 0; + ++#if !STM32MP_SSP + if (wakeup_standby) { + ret = stm32_get_pll1_settings_from_context(); + } ++#endif + + /* + * If no pre-defined PLL1 settings in DT, find the highest frequency +@@ -343,6 +354,13 @@ void bl2_el3_plat_arch_setup(void) + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + ++#if SEPARATE_CODE_AND_RODATA ++ mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, ++ BL_RO_DATA_END - BL_RO_DATA_BASE, ++ MT_RO_DATA | MT_SECURE); ++#endif ++ ++#if !STM32MP_SSP + #ifdef AARCH32_SP_OPTEE + mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, + STM32MP_OPTEE_SIZE, +@@ -353,6 +371,7 @@ void bl2_el3_plat_arch_setup(void) + BL32_LIMIT - BL32_BASE, + MT_RO_DATA | MT_SECURE); + #endif ++#endif + /* Prevent corruption of preloaded Device Tree */ + mmap_add_region(DTB_BASE, DTB_BASE, + DTB_LIMIT - DTB_BASE, +@@ -502,7 +521,17 @@ void bl2_el3_plat_arch_setup(void) + console_set_scope(&console.console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF); + ++#if STM32MP_SSP ++ if (boot_context->p_ssp_config->ssp_cmd != ++ BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK) { ++ stm32mp_print_cpuinfo(); ++ if (!stm32mp_supports_ssp()) { ++ ERROR("Chip doesn't support SSP\n"); ++ } ++ } ++#else + stm32mp_print_cpuinfo(); ++#endif + + board_model = dt_get_board_model(); + if (board_model != NULL) { +@@ -536,6 +565,7 @@ skip_console_init: + + stm32_iwdg_refresh(); + ++#if !STM32MP_SSP + if (bsec_read_debug_conf() != 0U) { + result = stm32mp1_dbgmcu_freeze_iwdg2(); + if (result != 0) { +@@ -554,6 +584,7 @@ skip_console_init: + } + + stm32mp1_arch_security_setup(); ++#endif + + print_reset_reason(); + +@@ -564,7 +595,16 @@ skip_console_init: + print_pmic_info_and_debug(); + } + ++#if STM32MP_SSP ++ if (boot_context->p_ssp_config->ssp_cmd != ++ BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK) { ++ stm32mp_io_setup(); ++ } ++ ++ ssp_start(boot_context); ++#else + stm32mp_io_setup(); ++#endif + } + + #if defined(AARCH32_SP_OPTEE) +diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h +index 872e204..04be28d 100644 +--- a/plat/st/stm32mp1/include/boot_api.h ++++ b/plat/st/stm32mp1/include/boot_api.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -335,15 +335,278 @@ BOOT_API_MCIC_RETRAM_REGION_TO_HASH_IN_BYTES_TAMP_BCK_REG_IDX 23 + /* 'K' 'B' 'U' 'P' -.> 'PUBK' */ + #define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK 0x4B425550 + ++#if STM32MP_SSP ++/* 'V' 'O' 'R' 'P' -.> 'PROV' */ ++#define BOOT_API_CTX_SSP_CMD_PROV_SECRET 0x564F5250 ++/* ++ * Possible values of boot context field ++ * 'ssp_config_ptr_in->ssp_cmd' written by bootROM as Acknowledge ++ * of a request of SSP by FSBL. ++ */ ++ ++/* Written by bootROM on SSP error */ ++#define BOOT_API_CTX_SSP_CMD_INVALID 0x00000000 ++/* ++ * 'A' 'B' 'U' 'P' -.> 'PUBA' : ACK of ECIES_CHIP_PUBK calculation ++ * request by bootROM. ++ */ ++#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK 0x41425550 ++/* ++ * 'A' 'O' 'R' 'P' -.> 'PROA' : ACK of OEM Secret Provisioning request ++ * by bootROM. ++ */ ++#define BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK 0x414F5250 ++ ++/* ++ * Constants required for SSP ++ */ ++/* '.' 'P' 'S' 'S' -.> 'SSP.' */ ++#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_NORMAL 0x2E505353 ++/* 'L' 'P' 'S' 'S' -.> 'SSPL' */ ++#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_LIVE 0x4C505353 ++/* version 1 */ ++#define BOOT_API_SSP_LICENSE_LAYOUT_VERSION_TO_MATCH 0x00000001 ++/* 'P' 'P' 'S' 'S' -.> 'SSPP' */ ++#define BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP 0x50505353 ++/* IV AES on 128 bits = 16 bytes and KEY AES on 128 bits = 16 bytes */ ++#define BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES 32 ++/* version 1 */ ++#define BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH 0x00000001 ++/* ++ * Scalar in Elliptic curve cryptography is an integer (often a Prime) ++ * the number of bytes of this scalar is defined below. ++ */ ++#define BOOT_API_SSP_SCALAR_SIZE_BYTES 32 ++ ++/* ++ * In Elliptic curve cryptography coordinates of points are 2D P ++ * (Px, Py) as concatenation of two scalars. ++ */ ++#define BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES \ ++ (2 * BOOT_API_SSP_SCALAR_SIZE_BYTES) ++ ++/* In Elliptic curve cryptography Private Keys are scalars */ ++#define BOOT_API_SSP_PRIVK_KEY_SIZE_BYTES \ ++ BOOT_API_SSP_SCALAR_SIZE_BYTES ++ ++/* ++ * In ECIES algorithm the Shared Secret (SS) is ++ * the x coordinate (Px) of a point P(Px,Py) obtained on reference ++ * NIST-P256 Elliptic curve chosen. ++ */ ++#define BOOT_API_SSP_ECDH_SHARED_SECRET_SIZE_BYTES \ ++ BOOT_API_SSP_SCALAR_SIZE_BYTES ++ ++/* ++ * In Elliptic curve cryptography Public Keys are Points on Elliptic ++ * curve chosen P(x,y). ++ * Public Key is the x, y coordinates concatenated ++ * Ecies_eph_pubk and OEM_ECDSA_PUBK are each 64 bytes = 512 bits key ++ * sizes. ++ */ ++#define BOOT_API_SSP_PUBK_KEY_SIZE_BYTES \ ++ BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES ++ ++/* ++ * Size in bytes of ECIES_Chip_pubk obtained from bootROM at end of SSP ++ * phase 1 : Chip public key calculation. ++ */ ++#define BOOT_API_SSP_ECIES_CHIP_PUBK_SIZE_BYTES \ ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES ++ ++/* AES-GCM authentication tag size is 16 bytes = 128 bits */ ++#define BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES 16 ++ ++/* AES-GCM Symmetric Key size is 16 bytes = 128 bits */ ++#define BOOT_API_SSP_AES_GCM_KEY_SIZE_BYTES 16 ++ ++/* AES-GCM Initialization Vector (IV) size is of 16 bytes = 128 bits */ ++#define BOOT_API_SSP_AES_GCM_IV_SIZE_BYTES 16 ++ ++/* ++ * 88 bytes (license_type, live_session_id, license_version, ++ * fsbl_min_version, rfu[8], eph_ecies_pubk[]) ++ */ ++#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE 88 ++ ++/* ++ * 32 bytes AAD License Secret from 2nd round KDF-SHA-256 ++ * from ECDH Shared Secret hence KDF[32..63] aka "Authorization Token" ++ */ ++#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF 32 ++ ++/* ++ * Total License AAD size = 88 + 32 = 120 bytes ++ */ ++#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_SIZE_BYTES \ ++ (BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE + \ ++ BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF) ++ ++/* ++ * AAD for Payload size : composed of : ++ * payload_magic, payload_protocol_version, oem_ecdsa_pubk[], oem_secret_size ++ * = 4 + 4 + 64 + 4 = 76 bytes AAD for Payload ++ */ ++#define BOOT_API_SSP_AES_GCM_PAYLOAD_AAD_SIZE_BYTES 76 ++ ++/* ++ * OEM Secrets max size in bytes : ++ * [OTP[95:59] + OTP_CFG56 (RMA Unlock and Relock passwords)] x 4 bytes ++ * by OTP word = 152 bytes ++ */ ++#define BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES 152 ++ ++/* ++ * Possible values of boot context field 'ssp_status' ++ * as can be read by FSBL-SSP ++ */ ++#define BOOT_API_CTX_SSP_STATUS_NO_SSP 0 ++#define BOOT_API_CTX_SSP_STATUS_CHIP_PUBK_CALC_FINISHED 1 ++#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FINISHED 2 ++#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FORBIDDEN 3 ++ ++/* ++ * Reserved size for future use ++ */ ++#define BOOT_API_SSP_HSM_OEM_RFU_SIZE 8 ++ + /* + * Exported types + */ + ++/* ++ * SSP related definitions ++ */ ++/* ++ * SSP BLOB License structure : Binary Large OBject License structure ++ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret ++ * provisioning. ++ * License information data, the structure is read by bootROM. ++ */ ++typedef struct { ++ /* ++ * License Type provided by HSM-OEM tool ++ * should match Normal SSP License of Live SSP License. ++ */ ++ uint32_t license_type; ++ ++ /* Live Session ID provided by HSM-OEM tool */ ++ uint32_t live_session_id; ++ ++ /* ++ * Version of the License Protocol (Structure) ++ * should be incremented each time a new. ++ */ ++ uint32_t license_version; ++ ++ /* ++ * Minimum FSBL version to be compared ++ * with FSBL Header field 'imageVersion'. ++ */ ++ uint32_t fsbl_min_version; ++ ++ /* RFU provided by HSM-OEM tool */ ++ uint8_t rfu[BOOT_API_SSP_HSM_OEM_RFU_SIZE]; ++ ++ /* ++ * Ephemeral ECIES Public Key from HSM-OEM ++ * 64 bytes = 512 bits. ++ */ ++ uint8_t eph_ecies_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES]; ++ ++ /* ++ * Encrypted (IV,Key) : with Shared Secret based on ++ * 'Ephemeral ECIES Key pair' and 'ECIES Chip Key pair'. ++ */ ++ uint8_t encrypted_iv_and_key ++ [BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES]; ++ ++ /* ++ * AUTH_TAG AES-GCM from encryption of (IV, Key) ++ * in HSM-OEM with License AAD scheme ++ * License Tag is 16 bytes = 128 bits. ++ */ ++ uint8_t license_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES]; ++ ++} boot_api_ssp_blob_license_t; ++ ++/* ++ * SSP BLOB Payload structure : Binary Large OBject Payload Structure ++ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret ++ * provisioning input data, the structure is read by bootROM ++ * The BLOB Payload size is fixed to a max size of 244 bytes based ++ * on a max number of bytes of OEM secret derived from OTP upper free ++ * area in STM32MP15xx cut 2.0.In this table oem_encrypted_secrets[] ++ * of max size only the first 'p_blob_payload->oem_secret_size_bytes' ++ * bytes will be considered and used by bootROM. ++ */ ++typedef struct { ++ /* ++ * BLOB Payload Magic : for memory validity check of BLOB Payload ++ * to match against BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP by bootROM. ++ */ ++ uint32_t payload_magic; ++ ++ /* ++ * SSP Payload protocol version : on 32 bits ++ * to be checked by bootROM for equality with ++ * BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH ++ * ie : 0x00000001 : version 1 of SSP Payload ++ */ ++ uint32_t payload_protocol_version; ++ ++ /* ++ * OEM_ECDSA_PUBK Public Key defined by OEM ++ * 64 bytes = 512 bits ++ */ ++ uint8_t oem_ecdsa_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES]; ++ ++ /* ++ * Size of Table of OEM Secrets encrypted with AES-GCM (Key,IV) from ++ * License field 'encrypted_iv_and_key[]' ++ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES: ++ * is verified by bootROM. ++ */ ++ uint32_t oem_secret_size_bytes; ++ ++ /* ++ * AUTH_TAG AES-GCM computed by HSM-OEM when encrypting OEM Secrets with ++ * (Key,IV) using special AAD scheme for Payload. ++ * 16 bytes = 128 bits ++ */ ++ uint8_t payload_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES]; ++ ++ /* ++ * OEM Secrets encrypted with AES-GCM (IV, Key) from ++ * License field 'encrypted_iv_and_key[]'. ++ * The payload size is 'oem_secret_size_bytes' ++ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES = ++ * 152 bytes : OEM Secrets max size in bytes : ++ * [OTP_CFG56, OTP_CFG59, OTP_CFG60..95] x 4 bytes by OTP word. ++ */ ++ uint8_t oem_encrypted_secrets[BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES]; ++ ++} boot_api_ssp_blob_payload_t; ++#endif ++ + /* SSP Configuration structure */ + typedef struct { + /* SSP Command*/ + uint32_t ssp_cmd; ++#if STM32MP_SSP ++ /* ECIES chip public key */ ++ uint8_t *p_chip_pubk; ++ /* Blob License Address */ ++ boot_api_ssp_blob_license_t *p_blob_license; ++ /* Blob Payload Address */ ++ boot_api_ssp_blob_payload_t *p_blob_payload; ++ /* Secrets Decrypted Address */ ++ uint8_t *p_ssp_oem_secrets_decrypted; ++ /* Reserved for Future Use (RFU) */ ++ uint32_t padding_rfu; ++#else + uint8_t reserved[20]; ++#endif + } boot_api_ssp_config_t; + + /* +diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h +index 694c3c4..380e120 100644 +--- a/plat/st/stm32mp1/include/platform_def.h ++++ b/plat/st/stm32mp1/include/platform_def.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -60,18 +60,31 @@ + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ ++#if !STM32MP_SSP + #define BL2_BASE STM32MP_BL2_BASE + #define BL2_LIMIT (STM32MP_BL2_BASE + \ + STM32MP_BL2_SIZE) ++#else ++#define BL2_RO_BASE STM32MP_BL2_BASE ++#define BL2_RO_LIMIT (STM32MP_BL2_BASE + \ ++ STM32MP_BL2_SIZE) ++#define BL2_RW_BASE BL2_RO_LIMIT ++#define BL2_RW_LIMIT (STM32MP_SYSRAM_BASE + \ ++ STM32MP_SYSRAM_SIZE - \ ++ PLAT_XLAT_SIZE - \ ++ STM32MP_BL2_SIZE) ++#endif + + /******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ ++#if !STM32MP_SSP + #ifndef AARCH32_SP_OPTEE + #define BL32_BASE STM32MP_BL32_BASE + #define BL32_LIMIT (STM32MP_BL32_BASE + \ + STM32MP_BL32_SIZE) + #endif ++#endif + + /******************************************************************************* + * BL33 specific defines. +diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c +index 1d407bb..5597886 100644 +--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c ++++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -19,6 +19,7 @@ + * the next executable image id. + ******************************************************************************/ + static bl_mem_params_node_t bl2_mem_params_descs[] = { ++#if !STM32MP_SSP + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, +@@ -78,6 +79,7 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + #endif /* AARCH32_SP_OPTEE */ ++#endif /* !STM32MP_SSP */ + + /* Fill BL33 related information */ + { +diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c +index 0a7437b..2434e87 100644 +--- a/plat/st/stm32mp1/plat_image_load.c ++++ b/plat/st/stm32mp1/plat_image_load.c +@@ -33,6 +33,7 @@ static bool addr_inside_backupsram(uintptr_t addr) + ******************************************************************************/ + bl_load_info_t *plat_get_bl_image_load_info(void) + { ++#if !STM32MP_SSP + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + #ifdef AARCH32_SP_OPTEE +@@ -86,7 +87,7 @@ bl_load_info_t *plat_get_bl_image_load_info(void) + STM32MP_DDR_S_SIZE - + STM32MP_DDR_SHMEM_SIZE - + bl33->image_info.image_base; +- ++#endif /* STM32MP_SSP */ + return get_bl_load_info_from_mem_params_desc(); + } + +diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk +index 840a38d..61443b5 100644 +--- a/plat/st/stm32mp1/platform.mk ++++ b/plat/st/stm32mp1/platform.mk +@@ -15,6 +15,14 @@ VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE + + TRUSTED_BOARD_BOOT := 1 + ++STM32MP_SSP ?= 0 ++$(eval $(call assert_boolean,STM32MP_SSP)) ++$(eval $(call add_define,STM32MP_SSP)) ++ ++ifeq ($(STM32MP_SSP),1) ++include plat/st/stm32mp1/stm32mp1_ssp.mk ++endif ++ + # Please don't increment this value without good understanding of + # the monotonic counter + STM32_TF_VERSION ?= 0 +@@ -185,8 +193,10 @@ BL2_SOURCES += drivers/st/uart/io_programmer_uart.c \ + drivers/st/uart/stm32mp1xx_hal_uart.c + endif + ++ifeq ($(STM32MP_SSP),0) + BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \ + drivers/st/ddr/stm32mp1_ram.c ++endif + + BL2_SOURCES += common/desc_image_load.c \ + plat/st/stm32mp1/plat_bl2_mem_params_desc.c \ +@@ -227,7 +237,9 @@ STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c + .PHONY: check_dtc_version stm32image clean_stm32image + .SUFFIXES: + ++ifeq ($(STM32MP_SSP),0) + all: check_dtc_version stm32image ${STM32_TF_STM32} ++endif + + ifeq ($(AARCH32_SP),sp_min) + # BL32 is built only if using SP_MIN +diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c +index e75571f..273c1cf 100644 +--- a/plat/st/stm32mp1/services/bsec_svc.c ++++ b/plat/st/stm32mp1/services/bsec_svc.c +@@ -27,10 +27,6 @@ + + #include "bsec_svc.h" + +-#define SSP_OTP_REQ BIT(BOOT_API_OTP_SSP_REQ_BIT_POS) +-#define SSP_OTP_SUCCESS BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS) +-#define SSP_OTP_MASK (SSP_OTP_REQ | SSP_OTP_SUCCESS) +- + enum bsec_ssp_status { + BSEC_NO_SSP = 0, + BSEC_SSP_SET, +diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h +index d458805..bc6dd8f 100644 +--- a/plat/st/stm32mp1/stm32mp1_def.h ++++ b/plat/st/stm32mp1/stm32mp1_def.h +@@ -131,6 +131,12 @@ enum ddr_type { + (STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE)) + ++#if STM32MP_SSP ++#define STM32MP_BL2_SIZE U(0x00010000) /* 64 Ko for BL2 */ ++ ++#define STM32MP_BL2_BASE STM32MP_DTB_BASE + \ ++ STM32MP_DTB_SIZE ++#else /* STM32MP_SSP */ + #ifdef AARCH32_SP_OPTEE + #define STM32MP_BL32_SIZE U(0) + +@@ -166,6 +172,7 @@ enum ddr_type { + + #define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ + STM32MP_BL2_SIZE) ++#endif /* STM32MP_SSP */ + + #if STM32MP_USB_PROGRAMMER + /* BL2 and BL32/sp_min require 5 finer granularity tables */ +@@ -179,6 +186,9 @@ enum ddr_type { + * MAX_MMAP_REGIONS is usually: + * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup + */ ++#if STM32MP_SSP ++ #define MAX_MMAP_REGIONS 8 ++#else + #if defined(IMAGE_BL2) + #if STM32MP_USB_PROGRAMMER + #define MAX_MMAP_REGIONS 12 +@@ -189,19 +199,30 @@ enum ddr_type { + #if defined(IMAGE_BL32) + #define MAX_MMAP_REGIONS 6 + #endif ++#endif /* STM32MP_SSP */ + + #define XLAT_TABLE_OCTETSIZE U(0x1000) + #define PLAT_XLAT_SIZE (MAX_XLAT_TABLES * \ + XLAT_TABLE_OCTETSIZE) + ++#if STM32MP_SSP ++#define PLAT_XLAT_BASE (STM32MP_SYSRAM_BASE + \ ++ STM32MP_SYSRAM_SIZE - \ ++ PLAT_XLAT_SIZE) ++#else + #define PLAT_XLAT_BASE (STM32MP_BL2_BASE - \ + PLAT_XLAT_SIZE) ++#endif + + /* DTB initialization value */ + #define STM32MP_DTB_SIZE U(0x00006000) /* 24 KB for DTB */ + ++#if STM32MP_SSP ++#define STM32MP_DTB_BASE U(0x2FFC3000) ++#else + #define STM32MP_DTB_BASE (PLAT_XLAT_BASE - \ + STM32MP_DTB_SIZE) ++#endif + + #define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) + +@@ -404,11 +425,34 @@ enum ddr_type { + #define UID_OTP "uid_otp" + #define PKH_OTP "pkh_otp" + #define BOARD_ID_OTP "board_id" ++#define CFG2_OTP "cfg2_otp" ++#define SSP_OTP "ssp_otp" ++#define CHIP_CERTIFICATE_OTP "chip_otp" ++#define RMA_OTP "rma_otp" + + /* OTP mask */ + /* CFG0 */ + #define CFG0_CLOSED_DEVICE BIT(6) + ++/* CFG2 */ ++#define OTP_CFG2_SEC_COUNTER_MASK GENMASK_32(27, 20) ++#define OTP_CFG2_SEC_COUNTER_SHIFT U(20) ++#define OTP_CFG2_ST_KEY_MASK GENMASK_32(31, 28) ++#define OTP_CFG2_ST_KEY_SHIFT U(28) ++ ++/* SSP */ ++#define SSP_OTP_REQ BIT(BOOT_API_OTP_SSP_REQ_BIT_POS) ++#define SSP_OTP_SUCCESS BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS) ++#define SSP_OTP_MASK GENMASK_32(9, 8) ++#define SSP_OTP_SECRET_BASE U(59) ++#define SSP_OTP_SECRET_END U(95) ++ ++/* CHIP_CERT */ ++#define CHIP_CERTIFICATE_MAX_SIZE U(0x40) ++ ++/* RMA */ ++#define RMA_OTP_MASK GENMASK_32(29, 0) ++ + /* PART NUMBER */ + #define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0) + #define PART_NUMBER_OTP_PART_SHIFT 0 +diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c +index b94857b..1a57a7b 100644 +--- a/plat/st/stm32mp1/stm32mp1_private.c ++++ b/plat/st/stm32mp1/stm32mp1_private.c +@@ -101,7 +101,9 @@ static const mmap_region_t stm32mp1_mmap[] = { + MAP_SRAM_MCU, + #endif + MAP_DEVICE1, ++#if !STM32MP_SSP + MAP_DEVICE2, ++#endif + {0} + }; + #endif +@@ -189,6 +191,7 @@ void __dead2 stm32mp_wait_cpu_reset(void) + } + } + ++#if defined(IMAGE_BL32) + /* + * tzc_source_ip contains the TZC transaction source IPs that need to be reset + * before a C-A7 subsystem is reset (i.e. independent reset): +@@ -232,9 +235,22 @@ static const struct tzc_source_ip tzc_source_ip[] = { + _TZC_COND(DMA1_R, DMA1, STM32MP1_ETZPC_DMA1_ID), + _TZC_COND(DMA2_R, DMA2, STM32MP1_ETZPC_DMA2_ID), + }; ++#endif + + #define TIMEOUT_US_1MS U(1000) + ++#if defined(IMAGE_BL2) ++void __dead2 stm32mp_plat_reset(int cpu) ++{ ++ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, ++ RCC_MP_GRSTCSETR_MPSYSRST); ++ ++ /* Loop in case system reset is not immediately caught */ ++ for ( ; ; ) { ++ ; ++ } ++} ++#else + void __dead2 stm32mp_plat_reset(int cpu) + { + uint32_t reg = RCC_MP_GRSTCSETR_MPUP0RST; +@@ -289,6 +305,7 @@ void __dead2 stm32mp_plat_reset(int cpu) + + stm32mp_wait_cpu_reset(); + } ++#endif /* IMAGE_BL2 */ + + unsigned long stm32_get_gpio_bank_clock(unsigned int bank) + { +@@ -420,6 +437,23 @@ bool stm32mp_supports_cpu_opp(uint32_t opp_id) + } + } + ++#if STM32MP_SSP ++bool stm32mp_supports_ssp(void) ++{ ++ switch (get_part_number()) { ++ case STM32MP157F_PART_NB: ++ case STM32MP157C_PART_NB: ++ case STM32MP153F_PART_NB: ++ case STM32MP153C_PART_NB: ++ case STM32MP151F_PART_NB: ++ case STM32MP151C_PART_NB: ++ return true; ++ default: ++ return false; ++ } ++} ++#endif /* STM32MP_SSP */ ++ + void stm32mp_print_cpuinfo(void) + { + const char *cpu_s, *cpu_r, *pkg; +diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c +index 232fbeb..6773bd7 100644 +--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c ++++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c +@@ -66,6 +66,7 @@ static const char *shres2str_id(unsigned int id) + return shres2str_id_tbl[id]; + } + ++#if !STM32MP_SSP + static const char *shres2str_state_tbl[4] = { + [SHRES_UNREGISTERED] = "unregistered", + [SHRES_NON_SECURE] = "non-secure", +@@ -76,6 +77,7 @@ static const char *shres2str_state(unsigned int id) + { + return shres2str_state_tbl[id]; + } ++#endif /* !STM32MP_SSP */ + + struct shres2decprot { + unsigned int shres_id; +@@ -146,6 +148,12 @@ static unsigned int get_gpioz_nbpin(void) + return (unsigned int)gpioz_nbpin; + } + ++#if STM32MP_SSP ++static void register_periph(unsigned int id __unused, ++ unsigned int state __unused) ++{ ++} ++#else + static void register_periph(unsigned int id, unsigned int state) + { + assert((id < STM32MP1_SHRES_COUNT) && +@@ -227,6 +235,7 @@ static void register_periph(unsigned int id, unsigned int state) + } + } + } ++#endif /* STM32MP_SSP */ + + static bool stm32mp1_mckprot_resource(unsigned int id) + { +diff --git a/plat/st/stm32mp1/stm32mp1_ssp.S b/plat/st/stm32mp1/stm32mp1_ssp.S +new file mode 100644 +index 0000000..83a66c2 +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_ssp.S +@@ -0,0 +1,11 @@ ++/* ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++.section .dtb_image ++.incbin DTB_BIN_PATH ++ ++.section .bl2_image ++.incbin BL2_BIN_PATH +diff --git a/plat/st/stm32mp1/stm32mp1_ssp.ld.S b/plat/st/stm32mp1/stm32mp1_ssp.ld.S +new file mode 100644 +index 0000000..5f05e7b +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_ssp.ld.S +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define TF_LINKER_SCRIPT ++#include ++ ++OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) ++OUTPUT_ARCH(PLATFORM_LINKER_ARCH) ++ ++ENTRY(__BL2_IMAGE_START__) ++ ++MEMORY { ++ HEADER (rw) : ORIGIN = STM32MP_DTB_BASE, LENGTH = 0x3000 ++ RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE ++} ++ ++SECTIONS ++{ ++ /* ++ * TF mapping must conform to ROM code specification. ++ */ ++ .header : { ++ __HEADER_START__ = .; ++ KEEP(*(.header)) ++ . = ALIGN(4); ++ __HEADER_END__ = .; ++ } >HEADER ++ ++ . = STM32MP_BINARY_BASE; ++ .data . : { ++ . = ALIGN(PAGE_SIZE); ++ __DATA_START__ = .; ++ *(.data*) ++ ++ /* ++ * Device tree ++ */ ++ __DTB_IMAGE_START__ = .; ++ *(.dtb_image*) ++ __DTB_IMAGE_END__ = .; ++ ++ /* ++ * BL2 image ++ */ ++ . = (STM32MP_BL2_BASE - STM32MP_BINARY_BASE); ++ __BL2_IMAGE_START__ = .; ++ *(.bl2_image*) ++ __BL2_IMAGE_END__ = .; ++ __DATA_END__ = .; ++ } >RAM ++ ++ __TF_END__ = .; ++ ++} ++#undef TF_LINKER_SCRIPT +diff --git a/plat/st/stm32mp1/stm32mp1_ssp.mk b/plat/st/stm32mp1/stm32mp1_ssp.mk +new file mode 100644 +index 0000000..6d1fc49 +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_ssp.mk +@@ -0,0 +1,66 @@ ++# ++# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++ ++ST_VERSION := r1.0 ++VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} ++ ++# Required to use BL2_IN_XIP_MEM ++BL2_IN_XIP_MEM := 1 ++$(eval $(call add_define,BL2_IN_XIP_MEM)) ++ ++SEPARATE_CODE_AND_RODATA := 1 ++ ++# Macros and rules to build TF-A binary ++STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed ++STM32_DT_BASENAME := $(DTB_FILE_NAME:.dtb=) ++STM32_TF_SSP_STM32 := ${BUILD_PLAT}/tf-a-ssp-${STM32_DT_BASENAME}.stm32 ++STM32_TF_SSP_BINARY := $(STM32_TF_SSP_STM32:.stm32=.bin) ++STM32_TF_SSP_MAPFILE := $(STM32_TF_SSP_STM32:.stm32=.map) ++STM32_TF_SSP_LINKERFILE := $(STM32_TF_SSP_STM32:.stm32=.ld) ++STM32_TF_SSP_ELF := $(STM32_TF_SSP_STM32:.stm32=.elf) ++STM32_TF_SSP_OBJS := ${BUILD_PLAT}/stm32mp1-ssp.o ++STM32_TF_SSP_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME} ++ ++BL2_SOURCES += lib/ssp/ssp.c ++ ++${STM32_TF_SSP_OBJS}: plat/st/stm32mp1/stm32mp1_ssp.S bl2 ${STM32_TF_SSP_DTBFILE} ++ @echo " AS $<" ++ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ ++ -DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\" \ ++ -DDTB_BIN_PATH=\"${STM32_TF_SSP_DTBFILE}\" \ ++ -c plat/st/stm32mp1/stm32mp1_ssp.S -o $@ ++ ++ ++${STM32_TF_SSP_LINKERFILE}: plat/st/stm32mp1/stm32mp1_ssp.ld.S ++ @echo " LDS $<" ++ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@ ++ ++${STM32_TF_SSP_ELF}: ${STM32_TF_SSP_OBJS} ${STM32_TF_SSP_LINKERFILE} ++ @echo " LDS $<" ++ ${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} \ ++ -Map=${STM32_TF_SSP_MAPFILE} \ ++ --script ${STM32_TF_SSP_LINKERFILE} \ ++ ${STM32_TF_SSP_OBJS} ++ ++${STM32_TF_SSP_BINARY}: ${STM32_TF_SSP_ELF} ++ ${Q}${OC} -O binary ${STM32_TF_SSP_ELF} $@ ++ @echo ++ @echo "Built $@ successfully" ++ @echo ++ ++${STM32_TF_SSP_STM32}: check_dtc_version stm32image ${STM32_TF_SSP_BINARY} ++ @echo ++ @echo "Generated $@" ++ $(eval LOADADDR = $(shell cat ${STM32_TF_SSP_MAPFILE} | grep RAM | awk '{print $$2}')) ++ $(eval ENTRY = $(shell cat ${STM32_TF_SSP_MAPFILE} | grep "__BL2_IMAGE_START" | awk '{print $$1}')) ++ ${STM32IMAGE} -s ${STM32_TF_SSP_BINARY} -d $@ \ ++ -l $(LOADADDR) -e ${ENTRY} \ ++ -v ${STM32_TF_VERSION} \ ++ -m ${STM32_HEADER_VERSION_MAJOR} \ ++ -n ${STM32_HEADER_VERSION_MINOR} ++ @echo ++ ++all: ${STM32_TF_SSP_STM32} +-- +2.7.4 +