From c262c4b26d663cfab106441cb4d4c7a505e8f228 Mon Sep 17 00:00:00 2001 From: Lionel Debieve <lionel.debieve@st.com> Date: Tue, 10 Nov 2020 09:21:08 +0100 Subject: [PATCH] plat/st: Add SSP support for STM32CubeProgrammer Add STM32CubeProgrammer communication update for SSP support. Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com> Change-Id: I1830bff82d87b3535f0787eb5f47c56960feccaa Reviewed-on: https://gerrit.st.com/c/mpu/oe/st/tf-a/+/185335 Reviewed-by: CITOOLS <smet-aci-reviews@lists.codex.cro.st.com> Reviewed-by: Lionel DEBIEVE <lionel.debieve@st.com> Reviewed-by: Yann GAUTIER <yann.gautier@st.com> Tested-by: Lionel DEBIEVE <lionel.debieve@st.com> --- plat/st/common/include/stm32cubeprogrammer.h | 14 ++ plat/st/common/stm32cubeprogrammer_uart.c | 143 ++++++++++++++++++- plat/st/common/stm32cubeprogrammer_usb.c | 93 +++++++++++- plat/st/stm32mp1/stm32mp1_usb.c | 6 +- 4 files changed, 252 insertions(+), 4 deletions(-) diff --git a/plat/st/common/include/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h index 6fee659c0..947ad43ae 100644 --- a/plat/st/common/include/stm32cubeprogrammer.h +++ b/plat/st/common/include/stm32cubeprogrammer.h @@ -13,6 +13,7 @@ #define PHASE_FSBL2 2U #define PHASE_SSBL 3U #define PHASE_CMD 0xF1U +#define PHASE_SSP 0xF3U #define PHASE_RESET 0xFFU /* Command definition */ @@ -20,6 +21,7 @@ #define GET_VER_COMMAND 0x01U #define GET_ID_COMMAND 0x02U #define PHASE_COMMAND 0x03U +#define READ_PART_COMMAND 0x12U #define START_COMMAND 0x21U #define DOWNLOAD_COMMAND 0x31U @@ -50,4 +52,16 @@ int stm32cubeprog_uart_load(unsigned int image_id, uintptr_t ssbl_base, size_t ssbl_len); +int stm32cubeprog_usb_ssp(usb_handle_t *usb_core_handle, + uintptr_t cert_base, + size_t cert_len, + uintptr_t ssp_base, + size_t ssp_len); + +int stm32cubeprog_uart_ssp(uintptr_t instance, + uintptr_t cert_base, + size_t cert_len, + uintptr_t ssp_base, + size_t ssp_len); + #endif /* STM32CUBEROGRAMMER_H */ diff --git a/plat/st/common/stm32cubeprogrammer_uart.c b/plat/st/common/stm32cubeprogrammer_uart.c index 2bfe509f3..3fd16aa39 100644 --- a/plat/st/common/stm32cubeprogrammer_uart.c +++ b/plat/st/common/stm32cubeprogrammer_uart.c @@ -32,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 }; @@ -43,6 +46,10 @@ struct stm32prog_uart_handle_s { uint8_t *addr; uint32_t len; uint8_t phase; +#if STM32MP_SSP + uintptr_t cert_base; + size_t cert_len; +#endif /* error msg buffer: max 255 in UART protocol, reduced in TF-A */ uint8_t error[64]; } handle; @@ -405,6 +412,97 @@ static int uart_start_cmd(unsigned int image_id, uintptr_t buffer) return 0; } +#if STM32MP_SSP +static int uart_read_part(void) +{ + uint8_t byte = 0U; + uint8_t xor = 0U; + uint8_t partid = 0U; + uint16_t size = 0U; + uint32_t start_address = 0U; + uint32_t i; + size_t length; + uint8_t *buffer; + + /* Get partition id */ + if (uart_read_8(&partid) != 0) { + return -EIO; + } + + if ((partid != PHASE_FLASHLAYOUT) && (partid != PHASE_SSP)) { + return -EPERM; + } + + xor = partid; + + /* Get address */ + for (i = 4U; i > 0U; i--) { + if (uart_read_8(&byte) != 0) { + return -EIO; + } + + xor ^= byte; + start_address = (start_address << 8) | byte; + } + + /* Checksum */ + if (uart_read_8(&byte) != 0) { + return -EIO; + } + + if (xor != byte) { + WARN("UART: Start cmd: address checksum: %x != %x\n", + xor, byte); + return -EPROTO; + } + /* OFFSET != 0 not supported */ + if (start_address != 0U) { + return -EIO; + } + + uart_write_8(ACK_BYTE); + + /* Get number of bytes to send */ + if (uart_read_8(&byte) != 0) { + return -EIO; + } + + xor = byte; + + /* Send Size + 1 */ + size = byte++; + + /* Checksum */ + if (uart_read_8(&byte) != 0) { + return -EIO; + } + + if ((xor ^ byte) != 0xFF) { + WARN("UART: Start cmd: length checksum: %x != %x\n", xor, byte); + return -EPROTO; + } + + uart_write_8(ACK_BYTE); + + if (partid != PHASE_SSP) { + WARN("Not supported\n"); + return -EPROTO; + } + + length = handle.cert_len; + buffer = (uint8_t *)handle.cert_base; + + for (i = 0U; i < length; i++, buffer++) { + uart_write_8(*buffer); + } + for (; i < size; i++) { + uart_write_8(0x0); + } + + return 0; +} +#endif /* STM32MP_SSP */ + static int uart_read(unsigned int image_id, uint8_t id, uintptr_t buffer, size_t length) { bool start_done = false; @@ -466,11 +564,21 @@ static int uart_read(unsigned int image_id, uint8_t id, uintptr_t buffer, size_t case DOWNLOAD_COMMAND: ret = uart_download_part(); break; - +#if STM32MP_SSP + case READ_PART_COMMAND: + ret = uart_read_part(); + break; +#endif case START_COMMAND: ret = uart_start_cmd(image_id, buffer); if ((ret == 0U) && (handle.phase == id)) { INFO("UART: Start phase %d\n", handle.phase); +#if STM32MP_SSP + if (handle.phase == PHASE_SSP) { + handle.phase = PHASE_RESET; + break; + } +#endif start_done = true; } break; @@ -508,6 +616,39 @@ const struct stm32_uart_init_s init = { .fifo_mode = STM32_UART_FIFOMODE_EN, }; +#if STM32MP_SSP +int stm32cubeprog_uart_ssp(uintptr_t instance, + uintptr_t cert_base, + size_t cert_len, + uintptr_t ssp_base, + size_t ssp_len) +{ + int ret; + + if (stm32_uart_init(&handle.uart, instance, &init) != 0U) { + return -EIO; + } + + /* NACK to synchronize STM32CubeProgrammer */ + ret = uart_flush_and_nack(); + if (ret != 0) { + return ret; + } + + if (cert_base == UNDEFINED_DOWN_ADDR) { + /* Send Provisioning message to programmer for reboot */ + STM32PROG_ERROR("Provisioning\n"); + } else { + handle.cert_base = cert_base; + handle.cert_len = cert_len; + handle.phase = PHASE_SSP; + } + + return uart_read(MAX_IMAGE_IDS, handle.phase, ssp_base, ssp_len); + +} +#endif + int stm32cubeprog_uart_load(unsigned int image_id, uintptr_t instance, uintptr_t flashlayout_base, diff --git a/plat/st/common/stm32cubeprogrammer_usb.c b/plat/st/common/stm32cubeprogrammer_usb.c index 0121af949..eefe6413b 100644 --- a/plat/st/common/stm32cubeprogrammer_usb.c +++ b/plat/st/common/stm32cubeprogrammer_usb.c @@ -29,6 +29,10 @@ typedef struct { /* parameter */ uintptr_t ssbl_base; size_t ssbl_len; +#if STM32MP_SSP + uintptr_t cert_base; + size_t cert_len; +#endif /* working buffer */ uint8_t buffer[255]; } dfu_state_t; @@ -66,7 +70,15 @@ static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len, switch (usb_dfu_get_phase(alt)) { case PHASE_CMD: /* Get Pḧase */ +#if STM32MP_SSP + if (dfu->phase == PHASE_SSP) { + dfu->buffer[0] = PHASE_FLASHLAYOUT; + } else { + dfu->buffer[0] = dfu->phase; + } +#else dfu->buffer[0] = dfu->phase; +#endif dfu->buffer[1] = (uint8_t)(dfu->address); dfu->buffer[2] = (uint8_t)(dfu->address >> 8); dfu->buffer[3] = (uint8_t)(dfu->address >> 16); @@ -88,6 +100,28 @@ static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len, } break; +#if STM32MP_SSP + case PHASE_SSP: + /* Fix phase to flashlayout phase */ + dfu->buffer[0] = PHASE_FLASHLAYOUT; + dfu->buffer[1] = (uint8_t)(dfu_state.cert_base); + dfu->buffer[2] = (uint8_t)(dfu_state.cert_base >> 8); + dfu->buffer[3] = (uint8_t)(dfu_state.cert_base >> 16); + dfu->buffer[4] = (uint8_t)(dfu_state.cert_base >> 24); + dfu->buffer[5] = 0x00; + dfu->buffer[6] = 0x00; + dfu->buffer[7] = 0x00; + dfu->buffer[8] = 0x00; + length = 9U; + + if ((length + dfu_state.cert_len) <= sizeof(dfu->buffer)) { + memcpy(&dfu->buffer[9], (uint8_t *)dfu_state.cert_base, + dfu_state.cert_len); + length += dfu_state.cert_len; + } + + break; +#endif default: DFU_ERROR("phase ID :%i, alternate %i for phase %i\n", dfu->phase, alt, usb_dfu_get_phase(alt)); @@ -131,7 +165,7 @@ static int dfu_callback_manifestation(uint8_t alt, void *user_data) #if STM32MP_USE_STM32IMAGE int result; #endif - boot_api_image_header_t *header; + boot_api_image_header_t *header __unused; dfu_state_t *dfu = (dfu_state_t *)user_data; if (dfu->phase != usb_dfu_get_phase(alt)) { @@ -143,6 +177,14 @@ static int dfu_callback_manifestation(uint8_t alt, void *user_data) INFO("phase ID :%i, Manifestation %d at %lx\n", dfu->phase, alt, dfu->address); switch (dfu->phase) { +#if STM32MP_SSP + case PHASE_SSP: + /* Configure End with request detach */ + dfu->phase = PHASE_FLASHLAYOUT; + dfu->address = UNDEFINED_DOWN_ADDR; + dfu->len = 0; + break; +#else case PHASE_FLASHLAYOUT: header = (boot_api_image_header_t *)(dfu->base); @@ -200,7 +242,7 @@ static int dfu_callback_manifestation(uint8_t alt, void *user_data) dfu->address = UNDEFINED_DOWN_ADDR; dfu->len = 0; break; - +#endif /* STM32MP_SSP */ default: DFU_ERROR("Unknown phase\n"); } @@ -215,6 +257,53 @@ static const usb_dfu_media_t usb_dfu_fops = { .manifestation = dfu_callback_manifestation, }; +#if STM32MP_SSP +int stm32cubeprog_usb_ssp(usb_handle_t *usb_core_handle, + uintptr_t cert_base, + size_t cert_len, + uintptr_t ssp_base, + size_t ssp_len) +{ + int ret; + + usb_core_handle->user_data = (void *)&dfu_state; + + INFO("DFU USB START...\n"); + ret = usb_core_start(usb_core_handle); + if (ret != USBD_OK) { + return -EIO; + } + + if (cert_base == UNDEFINED_DOWN_ADDR) { + dfu_state_t *dfu = (dfu_state_t *)usb_core_handle->user_data; + + /* Send Provisioning message to programmer for reboot */ + DFU_ERROR("Provisioning\n"); + } else { + dfu_state.phase = PHASE_SSP; + dfu_state.image_id = MAX_IMAGE_IDS; + dfu_state.address = ssp_base; + dfu_state.base = ssp_base; + dfu_state.len = ssp_len; + dfu_state.cert_base = cert_base; + dfu_state.cert_len = cert_len; + } + + ret = usb_dfu_loop(usb_core_handle, &usb_dfu_fops); + if (ret != USBD_OK) { + return -EIO; + } + + INFO("DFU USB STOP...\n"); + ret = usb_core_stop(usb_core_handle); + if (ret != USBD_OK) { + return -EIO; + } + + return 0; +} +#endif + int stm32cubeprog_usb_load(unsigned int image_id, usb_handle_t *usb_core_handle, uintptr_t flashlayout_base, diff --git a/plat/st/stm32mp1/stm32mp1_usb.c b/plat/st/stm32mp1/stm32mp1_usb.c index e1804c3e9..c63db4a2f 100644 --- a/plat/st/stm32mp1/stm32mp1_usb.c +++ b/plat/st/stm32mp1/stm32mp1_usb.c @@ -476,7 +476,11 @@ uint8_t usb_dfu_get_phase(uint8_t alt) { switch (alt) { case 0: - return PHASE_FLASHLAYOUT; +#if STM32MP_SSP + return PHASE_SSP; +#else + return PHASE_FLASHLAYOUT; +#endif case 3: return PHASE_SSBL; case 5: -- GitLab