2858 lines
76 KiB
Diff
2858 lines
76 KiB
Diff
From 3a5830ccfbcebfaa60540d50d42f0e37f3b532e9 Mon Sep 17 00:00:00 2001
|
|
From: Lionel Debieve <lionel.debieve@st.com>
|
|
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 <lionel.debieve@st.com>
|
|
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 <drivers/st/io_programmer_st_usb.h>
|
|
#include <drivers/st/io_stm32image.h>
|
|
#include <drivers/st/stm32_iwdg.h>
|
|
+#include <lib/ssp_lib.h>
|
|
#include <lib/usb/usb_st_dfu.h>
|
|
|
|
#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 <drivers/st/io_stm32image.h>
|
|
#include <drivers/st/io_uart.h>
|
|
#include <drivers/st/stm32_iwdg.h>
|
|
+#include <lib/ssp_lib.h>
|
|
|
|
/* 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 <boot_api.h>
|
|
+
|
|
+/* 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 <arch_helpers.h>
|
|
+#include <endian.h>
|
|
+#include <limits.h>
|
|
+#include <stdint.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include <platform_def.h>
|
|
+
|
|
+#include <drivers/io/io_driver.h>
|
|
+#include <drivers/st/bsec.h>
|
|
+#include <drivers/st/io_stm32image.h>
|
|
+#include <drivers/st/stm32mp_pmic.h>
|
|
+#include <drivers/st/stm32_hash.h>
|
|
+#include <drivers/st/stpmic1.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <lib/ssp_lib.h>
|
|
+#include <lib/utils.h>
|
|
+#include <lib/utils_def.h>
|
|
+#include <plat/common/platform.h>
|
|
+
|
|
+/* 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 <lib/usb/usb_st_dfu.h>
|
|
|
|
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 <drivers/st/stpmic1.h>
|
|
#include <lib/mmio.h>
|
|
#include <lib/optee_utils.h>
|
|
+#include <lib/ssp_lib.h>
|
|
#include <lib/xlat_tables/xlat_tables_v2.h>
|
|
#include <plat/common/platform.h>
|
|
|
|
@@ -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 <platform_def.h>
|
|
+
|
|
+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
|
|
|