On 4/30/2026 2:14 PM, Richard Genoud (TI) wrote: > From: Prasanth Babu Mantena <[email protected]> > > From: Prasanth Babu Mantena <[email protected]> Drop duplication above > > On TI-k3 platform, at resume, uboot SPL needs to do several tasks: > - restore TIFS minimal context from DDR > - send DDR save address to TIFS > - load TFA and its context in MSMC > - set TFA resume vector to its warm_entrypoint > - authenticate certificates and apply firewalls > > All those operations are now done by TIFS with those messages: > ti_sci_cmd_min_context_restore > ti_sci_cmd_decrypt_tfa > ti_sci_cmd_core_resume > ti_sci_cmd_lpm_save_addr > ti_sci_cmd_proc_auth_apply_fwls > > https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html > https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/security/PROC_BOOT.html > > Signed-off-by: Prasanth Babu Mantena <[email protected]> > Co-developed-by: Richard Genoud (TI) <[email protected]> > Signed-off-by: Richard Genoud (TI) <[email protected]> > --- > arch/arm/mach-k3/include/mach/security.h | 1 + > arch/arm/mach-k3/security.c | 64 ++++++++ > drivers/firmware/ti_sci.c | 179 +++++++++++++++++++++++ > drivers/firmware/ti_sci.h | 92 ++++++++++++ > include/linux/soc/ti/ti_sci_protocol.h | 8 + > 5 files changed, 344 insertions(+) > > diff --git a/arch/arm/mach-k3/include/mach/security.h > b/arch/arm/mach-k3/include/mach/security.h > index 8502b57bd80a..d9f31e1500a1 100644 > --- a/arch/arm/mach-k3/include/mach/security.h > +++ b/arch/arm/mach-k3/include/mach/security.h > @@ -9,3 +9,4 @@ > #include <linux/types.h> > > void ti_secure_image_post_process(void **p_image, size_t *p_size); > +void ti_secure_image_auth_apply_fwls(void **p_image, size_t *p_size); > diff --git a/arch/arm/mach-k3/security.c b/arch/arm/mach-k3/security.c > index c7017bba99ab..752912c6930a 100644 > --- a/arch/arm/mach-k3/security.c > +++ b/arch/arm/mach-k3/security.c > @@ -133,3 +133,67 @@ void ti_secure_image_post_process(void **p_image, size_t > *p_size) > spl_boot_device() == BOOT_DEVICE_UART)) > printf("Authentication passed\n"); > } > + > +void ti_secure_image_auth_apply_fwls(void **p_image, size_t *p_size) > +{ > + struct ti_sci_handle *ti_sci = get_ti_sci_handle(); > + struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops; > + u64 image_addr; > + u32 image_size, backup_size; > + int ret; > + > + image_size = *p_size; > + backup_size = image_size; > + if (!image_size) { > + debug("%s: Image size is %d\n", __func__, image_size); > + return; > + } > + > + if (get_device_type() == K3_DEVICE_TYPE_GP) > + return; > + > + if (get_device_type() != K3_DEVICE_TYPE_HS_SE && > + !ti_secure_cert_detected(*p_image)) { > + printf("Warning: Did not detect image signing certificate. " > + "Skipping authentication to prevent boot failure. " > + "This will fail on Security Enforcing(HS-SE) devices\n"); > + return; > + } > + > + /* Clean out image so it can be seen by system firmware */ > + image_addr = dma_map_single(*p_image, *p_size, DMA_BIDIRECTIONAL); > + > + debug("Authenticating image at address 0x%016llx\n", image_addr); > + debug("Authenticating image of size %d bytes\n", image_size); > + > + /* Authenticate image */ > + ret = proc_ops->proc_auth_apply_fwls(ti_sci, &image_addr, &image_size); > + if (ret) { > + printf("Authentication failed..but assume pass!\n"); > + hang(); > + } > + > + /* Invalidate any stale lines over data written by system firmware */ > + if (backup_size) > + dma_unmap_single(image_addr, backup_size, DMA_BIDIRECTIONAL); > + > + /* > + * The image_size returned may be 0 when the authentication process has > + * moved the image. When this happens no further processing on the > + * image is needed or often even possible as it may have also been > + * placed behind a firewall when moved. > + */ > + *p_size = backup_size; > + > + /* > + * Output notification of successful authentication to re-assure the > + * user that the secure code is being processed as expected. However > + * suppress any such log output in case of building for SPL and booting > + * via YMODEM. This is done to avoid disturbing the YMODEM serial > + * protocol transactions. > + */ > + if (!(IS_ENABLED(CONFIG_XPL_BUILD) && > + IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) && > + spl_boot_device() == BOOT_DEVICE_UART)) > + printf("Certificate replay passed\n"); > +} > diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c > index c015bd3cc245..a40f2918d75f 100644 > --- a/drivers/firmware/ti_sci.c > +++ b/drivers/firmware/ti_sci.c > @@ -2014,6 +2014,62 @@ static int ti_sci_cmd_set_proc_boot_ctrl(const struct > ti_sci_handle *handle, > return ret; > } > > +/** > + * ti_sci_cmd_proc_auth_apply_fwls() - Command to authenticate certificate > and > + * apply the firewalls present in it. > + * @handle: Pointer to TI SCI handle > + * @image_addr: Memory address at which payload image and certificate is > + * located in memory, this is updated if the image data is > + * moved during authentication. > + * @image_size: This is updated with the final size of the image after > + * authentication. > + * > + * Return: 0 if all went well, else returns appropriate error value. > + */ > +static int ti_sci_cmd_proc_auth_apply_fwls(const struct ti_sci_handle > *handle, > + u64 *image_addr, u32 *image_size) > +{ > + struct ti_sci_msg_req_proc_auth_boot_image req; > + struct ti_sci_msg_resp_proc_auth_boot_image *resp; > + struct ti_sci_info *info; > + struct ti_sci_xfer *xfer; > + int ret = 0; > + > + if (IS_ERR(handle)) > + return PTR_ERR(handle); > + if (!handle) > + return -EINVAL; > + > + info = handle_to_ti_sci_info(handle); > + > + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_APPLY_FWLS, > + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, > + (u32 *)&req, sizeof(req), sizeof(*resp)); > + if (IS_ERR(xfer)) { > + ret = PTR_ERR(xfer); > + printf("%s Error making the tisci command\n", __func__); > + return ret; > + } > + req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK; > + req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >> > + TISCI_ADDR_HIGH_SHIFT; > + > + ret = ti_sci_do_xfer(info, xfer); > + if (ret) { > + printf("%s Error sending the tisci command\n", __func__); > + return ret; > + } > + > + resp = (struct ti_sci_msg_resp_proc_auth_boot_image > *)xfer->tx_message.buf; > + > + *image_addr = (resp->image_addr_low & TISCI_ADDR_LOW_MASK) | > + (((u64)resp->image_addr_high << > + TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK); > + *image_size = resp->image_size; > + > + return ret; > +} > + > /** > * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the > * image and then set the processor configuration flags. > @@ -2745,6 +2801,125 @@ static int ti_sci_cmd_min_context_restore(const > struct ti_sci_handle *handle, u6 > return ret; > } > > +/** > + * ti_sci_cmd_decrypt_tfa() - Request for decrypting TFA to specific address. > + * @handle: pointer to TI SCI handle > + * @unencrypted_address: Address where the unencrypted TFA will be restored > to. > + * > + * Return: 0 if all went well, else returns appropriate error value. > + */ > +static int ti_sci_cmd_decrypt_tfa(const struct ti_sci_handle *handle, > + u64 unencrypted_address) > +{ > + struct ti_sci_msg_decrypt_tfa_req req; > + struct ti_sci_msg_decrypt_tfa_resp *resp; > + struct ti_sci_info *info; > + struct ti_sci_xfer *xfer; > + int ret = 0; > + > + if (IS_ERR(handle)) > + return PTR_ERR(handle); > + if (!handle) > + return -EINVAL; > + > + info = handle_to_ti_sci_info(handle); > + > + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_LPM_DECRYPT, > + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, > + (u32 *)&req, sizeof(req), sizeof(*resp)); > + if (IS_ERR(xfer)) { > + ret = PTR_ERR(xfer); > + return ret; > + } > + > + req.unencrypted_address = unencrypted_address; > + > + ret = ti_sci_do_xfer(info, xfer); > + > + return ret; > +} > + > +/** > + * ti_sci_cmd_core_resume() - Request for resuming TFA. > + * > + * The TIFS will launch the TFA from the entrypoint saved via the ENTER_SLEEP > + * message. > + * > + * @handle: pointer to TI SCI handle > + * > + * Return: 0 if all went well, else returns appropriate error value. > + */ > +static int ti_sci_cmd_core_resume(const struct ti_sci_handle *handle) > +{ > + struct ti_sci_msg_core_resume_req req; > + struct ti_sci_msg_core_resume_resp *resp; > + struct ti_sci_info *info; > + struct ti_sci_xfer *xfer; > + int ret = 0; > + > + if (IS_ERR(handle)) > + return PTR_ERR(handle); > + if (!handle) > + return -EINVAL; > + > + info = handle_to_ti_sci_info(handle); > + > + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_CORE_RESUME, > + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, > + (u32 *)&req, sizeof(req), sizeof(*resp)); > + if (IS_ERR(xfer)) { > + ret = PTR_ERR(xfer); > + return ret; > + } > + > + ret = ti_sci_do_xfer(info, xfer); > + > + return ret; > +} > + > +/** > + * ti_sci_cmd_lpm_save_addr() - Message to inform TIFS about the context > save address. > + * > + * By restoring its context, TIFS will restore its firewall. > + * > + * @handle: pointer to TI SCI handle > + * @ctx_addr: address where the context will be store to and restored from > + * @size: Size of the context save region > + * > + * Return: 0 if all went well, else returns appropriate error value. > + */ > +static int ti_sci_cmd_lpm_save_addr(const struct ti_sci_handle *handle, > + u64 context_addr, u32 size) > +{ > + struct tisci_msg_lpm_save_ctx_addr_req req; > + struct tisci_msg_lpm_save_ctx_addr_resp *resp; > + struct ti_sci_info *info; > + struct ti_sci_xfer *xfer; > + int ret = 0; > + > + if (IS_ERR(handle)) > + return PTR_ERR(handle); > + if (!handle) > + return -EINVAL; > + > + info = handle_to_ti_sci_info(handle); > + > + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_LPM_SAVE_ADDR, > + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, > + (u32 *)&req, sizeof(req), sizeof(*resp)); > + if (IS_ERR(xfer)) { > + ret = PTR_ERR(xfer); > + return ret; > + } > + > + req.ctx_addr = context_addr; > + req.size = size; > + > + ret = ti_sci_do_xfer(info, xfer); > + > + return ret; > +} > + > /* > * ti_sci_setup_ops() - Setup the operations structures > * @info: pointer to TISCI pointer > @@ -2813,6 +2988,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) > pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg; > pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl; > pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image; > + pops->proc_auth_apply_fwls = ti_sci_cmd_proc_auth_apply_fwls; > pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status; > pops->proc_shutdown_no_wait = ti_sci_cmd_proc_shutdown_no_wait; > > @@ -2833,6 +3009,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) > fw_ops->query_dm_cap = ti_sci_cmd_query_dm_cap; > > lpm_ops->min_context_restore = ti_sci_cmd_min_context_restore; > + lpm_ops->decrypt_tfa = ti_sci_cmd_decrypt_tfa; > + lpm_ops->core_resume = ti_sci_cmd_core_resume; > + lpm_ops->lpm_save_addr = ti_sci_cmd_lpm_save_addr; > } > > /** > diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h > index 68908c6c8c46..8fb519b62dbd 100644 > --- a/drivers/firmware/ti_sci.h > +++ b/drivers/firmware/ti_sci.h > @@ -57,6 +57,7 @@ > #define TISCI_MSG_PROC_AUTH_BOOT_IMAGE 0xc120 > #define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400 > #define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401 > +#define TISCI_MSG_PROC_AUTH_APPLY_FWLS 0xc402 > > /* Resource Management Requests */ > #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 > @@ -85,6 +86,24 @@ > #define TISCI_MSG_FWL_GET 0x9001 > #define TISCI_MSG_FWL_CHANGE_OWNER 0x9002 > > +/* LPM requests */ > +#define TISCI_MSG_SYNC_RESUME (0x0302U) > +#define TISCI_MSG_CONTINUE_RESUME (0x0303U) > +#define TISCI_MSG_CORE_RESUME (0x0304U) > +#define TISCI_MSG_ABORT_ENTER_SLEEP (0x0305U) > +#define TISCI_MSG_LPM_WAKE_REASON (0x0306U) > +#define TISCI_MSG_SET_IO_ISOLATION (0x0307U) > +#define TISCI_MSG_MIN_CONTEXT_RESTORE (0x0308U) > +#define TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT (0x0309U) > +#define TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT (0x030AU) > +#define TISCI_MSG_LPM_GET_DEVICE_CONSTRAINT (0x030BU) > +#define TISCI_MSG_LPM_GET_LATENCY_CONSTRAINT (0x030CU) > +#define TISCI_MSG_LPM_GET_NEXT_SYS_MODE (0x030DU) > +#define TISCI_MSG_LPM_GET_NEXT_HOST_STATE (0x030EU) > +#define TISCI_MSG_LPM_ENCRYPT (0x030FU) > +#define TISCI_MSG_LPM_DECRYPT (0x0310U) > +#define TISCI_MSG_LPM_SAVE_ADDR (0x0313U) > + > /** > * struct ti_sci_msg_hdr - Generic Message Header for All messages and > responses > * @type: Type of messages: One of TI_SCI_MSG* values > @@ -1588,4 +1607,77 @@ struct ti_sci_msg_min_restore_context_req { > u32 ctx_hi; > } __packed; > > +/* > + * struct ti_sci_msg_core_resume_req - Request for TISCI_MSG_CORE_RESUME. > + * > + * @hdr: Generic Header > + * > + * This message is to be sent to start the TFA on the main core. > + * The TIFS will launch the TFA from the entrypoint saved via the ENTER_SLEEP > + * message. > + */ > +struct ti_sci_msg_core_resume_req { > + struct ti_sci_msg_hdr hdr; > +} __packed; > + > +/** > + * struct ti_sci_msg_core_resume_resp - Response for TISCI_MSG_CORE_RESUME. > + * > + * @hdr: Generic Header > + */ > +struct ti_sci_msg_core_resume_resp { > + struct ti_sci_msg_hdr hdr; > +} __packed; > + > +/** > + * struct ti_sci_msg_decrypt_tfa_req - Request for TISCI_MSG_LPM_DECRYPT. > + * > + * @hdr: Generic Header > + * @unencrypted_address: Address where the TFA should be decrypted > + * @encrypted_address: Address where the TFA lies encrypted > + * > + * This message is to be sent when the system is resuming from suspend, in > order > + * to restore the TFA. > + * The TIFS will decrypt the TFA at specified location and restore it in > SRAM. > + */ > +struct ti_sci_msg_decrypt_tfa_req { > + struct ti_sci_msg_hdr hdr; > + u64 unencrypted_address; > +} __packed; > + > +/** > + * struct ti_sci_msg_decrypt_tfa_resp - Response for TISCI_MSG_LPM_DECRYPT. > + * > + * @hdr: Generic Header > + */ > +struct ti_sci_msg_decrypt_tfa_resp { > + struct ti_sci_msg_hdr hdr; > +} __packed; > + > +/** > + * struct tisci_msg_lpm_save_ctx_addr_req - Request for > TISCI_MSG_LPM_SAVE_ADDR. > + * > + * @hdr: Generic Header > + * @ctx_addr: Address where the LPM data is to be saved > + * @size: Size of the context save memory region > + * > + * This message is sent to TIFS to inform it about the addresse where it > + * will save the context to in case of system suspend and where to get the > + * context back from when resuming the system > + */ > +struct tisci_msg_lpm_save_ctx_addr_req { > + struct ti_sci_msg_hdr hdr; > + u64 ctx_addr; > + u32 size; > +} __packed; > + > +/** > + * struct tisci_msg_lpm_save_ctx_addr_resp - Response for > TISCI_MSG_SAVE_ADDR. > + * > + * @hdr: Generic Header > + */ > +struct tisci_msg_lpm_save_ctx_addr_resp { > + struct ti_sci_msg_hdr hdr; > +} __packed; > + > #endif /* __TI_SCI_H */ > diff --git a/include/linux/soc/ti/ti_sci_protocol.h > b/include/linux/soc/ti/ti_sci_protocol.h > index 6b1dd801f5f8..1d0a6340e1ee 100644 > --- a/include/linux/soc/ti/ti_sci_protocol.h > +++ b/include/linux/soc/ti/ti_sci_protocol.h > @@ -336,6 +336,8 @@ struct ti_sci_proc_ops { > u32 *sts_flags); > int (*proc_shutdown_no_wait)(const struct ti_sci_handle *handle, > u8 pid); > + int (*proc_auth_apply_fwls)(const struct ti_sci_handle *handle, > + u64 *image_addr, u32 *image_size); > }; > > #define TI_SCI_RING_MODE_RING (0) > @@ -635,9 +637,15 @@ struct ti_sci_fwl_ops { > /** > * struct ti_sci_lpm_ops - Low Power Mode operations > * @min_context_restore: Request restoring context from DDR. > + * @decrypt_tfa: Request for decrypting TFA at specific address. > + * @core_resume: Request for resuming TFA once decrypted. > + * @lpm_save_addr: Send DDR Save address to TIFS > */ > struct ti_sci_lpm_ops { > int (*min_context_restore)(const struct ti_sci_handle *handle, u64 > ctx_addr); > + int (*decrypt_tfa)(const struct ti_sci_handle *handle, u64 > unencrypted_address); > + int (*core_resume)(const struct ti_sci_handle *handle); > + int (*lpm_save_addr)(const struct ti_sci_handle *handle, u64 > context_addr, u32 size); > }; > > /**

