From 4837a640934630f8034ceec1bb84cc40673d8a6b Mon Sep 17 00:00:00 2001 From: Sieu Mun Tang Date: Sat, 7 May 2022 00:50:37 +0800 Subject: [PATCH] fix(intel): allow non-secure access to FPGA Crypto Services (FCS) Allows non-secure software to access FPGA Crypto Services (FCS) through secure monitor calls (SMC). Signed-off-by: Abdul Halim, Muhammad Hadi Asyrafi Signed-off-by: Sieu Mun Tang Change-Id: I805b3f650abf5e118e2c55e469866d5d0ca68048 --- .../soc/common/include/socfpga_mailbox.h | 21 +++++ .../soc/common/include/socfpga_sip_svc.h | 16 +++- plat/intel/soc/common/soc/socfpga_mailbox.c | 91 +++++++++++++++++++ plat/intel/soc/common/socfpga_sip_svc.c | 59 ++++++++++++ 4 files changed, 182 insertions(+), 5 deletions(-) diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h index 64024b8a9..fcf5fc206 100644 --- a/plat/intel/soc/common/include/socfpga_mailbox.h +++ b/plat/intel/soc/common/include/socfpga_mailbox.h @@ -108,6 +108,7 @@ #define MBOX_NO_RESPONSE -2 #define MBOX_WRONG_ID -3 #define MBOX_BUFFER_FULL -4 +#define MBOX_BUSY -5 #define MBOX_TIMEOUT -2047 /* Reconfig Status Response */ @@ -157,6 +158,10 @@ #define MBOX_INDIRECT(val) ((val) << 11) #define MBOX_CMD_MASK(header) ((header) & 0x7ff) +/* Mailbox payload */ +#define MBOX_DATA_MAX_LEN 0x3ff +#define MBOX_PAYLOAD_FLAG_BUSY BIT(0) + /* RSU Macros */ #define RSU_VERSION_ACMF BIT(8) #define RSU_VERSION_ACMF_MASK 0xff00 @@ -166,6 +171,19 @@ #define CONFIG_STATUS_FW_VER_OFFSET 1 #define CONFIG_STATUS_FW_VER_MASK 0x00FFFFFF +/* Data structure */ + +typedef struct mailbox_payload { + uint32_t header; + uint32_t data[MBOX_DATA_MAX_LEN]; +} mailbox_payload_t; + +typedef struct mailbox_container { + uint32_t flag; + uint32_t index; + mailbox_payload_t *payload; +} mailbox_container_t; + /* Mailbox Function Definitions */ void mailbox_set_int(uint32_t interrupt_input); @@ -180,6 +198,9 @@ int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args, unsigned int len, unsigned int indirect); int mailbox_read_response(uint32_t *job_id, uint32_t *response, unsigned int *resp_len); +int mailbox_read_response_async(uint32_t *job_id, uint32_t *header, + uint32_t *response, unsigned int *resp_len, + uint8_t ignore_client_id); int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf, unsigned int *resp_len); diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h index 53aece3ba..e46bee701 100644 --- a/plat/intel/soc/common/include/socfpga_sip_svc.h +++ b/plat/intel/soc/common/include/socfpga_sip_svc.h @@ -12,6 +12,7 @@ #define INTEL_SIP_SMC_STATUS_OK 0 #define INTEL_SIP_SMC_STATUS_BUSY 0x1 #define INTEL_SIP_SMC_STATUS_REJECTED 0x2 +#define INTEL_SIP_SMC_STATUS_NO_RESPONSE 0x3 #define INTEL_SIP_SMC_STATUS_ERROR 0x4 #define INTEL_SIP_SMC_RSU_ERROR 0x7 @@ -68,16 +69,21 @@ #define INTEL_SIP_SMC_FIRMWARE_VERSION 0xC200001F #define INTEL_SIP_SMC_HPS_SET_BRIDGES 0xC2000032 +#define SERVICE_COMPLETED_MODE_ASYNC 0x00004F4E + /* Mailbox Command */ #define INTEL_SIP_SMC_GET_USERCODE 0xC200003D /* FPGA Crypto Services */ +#define INTEL_SIP_SMC_FCS_RANDOM_NUMBER 0xC200005A #define INTEL_SIP_SMC_FCS_CRYPTION 0x4200005B -#define INTEL_SIP_SMC_FCS_CNTR_SET_PREAUTH 0xC200005F -#define INTEL_SIP_SMC_FCS_PSGSIGMA_TEARDOWN 0xC2000064 -#define INTEL_SIP_SMC_FCS_CHIP_ID 0xC2000065 -#define INTEL_SIP_SMC_FCS_ATTESTATION_SUBKEY 0xC2000066 -#define INTEL_SIP_SMC_FCS_ATTESTATION_MEASUREMENTS 0xC2000067 +#define INTEL_SIP_SMC_FCS_SEND_CERTIFICATE 0x4200005D +#define INTEL_SIP_SMC_FCS_GET_PROVISION_DATA 0x4200005E +#define INTEL_SIP_SMC_FCS_CNTR_SET_PREAUTH 0xC200005F +#define INTEL_SIP_SMC_FCS_PSGSIGMA_TEARDOWN 0xC2000064 +#define INTEL_SIP_SMC_FCS_CHIP_ID 0xC2000065 +#define INTEL_SIP_SMC_FCS_ATTESTATION_SUBKEY 0xC2000066 +#define INTEL_SIP_SMC_FCS_ATTESTATION_MEASUREMENTS 0xC2000067 /* ECC DBE */ #define WARM_RESET_WFI_FLAG BIT(31) diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c index 8ecd6db60..0f1214731 100644 --- a/plat/intel/soc/common/soc/socfpga_mailbox.c +++ b/plat/intel/soc/common/soc/socfpga_mailbox.c @@ -11,6 +11,8 @@ #include "socfpga_mailbox.h" #include "socfpga_sip_svc.h" +static mailbox_payload_t mailbox_resp_payload; +static mailbox_container_t mailbox_resp_ctr = {0, 0, &mailbox_resp_payload}; static bool is_mailbox_cmdbuf_full(uint32_t cin) { @@ -171,6 +173,95 @@ int mailbox_read_response(unsigned int *job_id, uint32_t *response, return MBOX_NO_RESPONSE; } +int mailbox_read_response_async(unsigned int *job_id, uint32_t *header, + uint32_t *response, unsigned int *resp_len, + uint8_t ignore_client_id) +{ + uint32_t rin; + uint32_t rout; + uint32_t resp_data; + uint32_t ret_resp_len = 0; + uint8_t is_done = 0; + + if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) { + ret_resp_len = MBOX_RESP_LEN( + mailbox_resp_ctr.payload->header) - + mailbox_resp_ctr.index; + } + + if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) { + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); + } + + rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); + + while (rout != rin && !is_done) { + + resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++)); + + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + + if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) { + mailbox_resp_ctr.payload->data[mailbox_resp_ctr.index] = resp_data; + mailbox_resp_ctr.index++; + ret_resp_len--; + } else { + if (!ignore_client_id) { + if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) { + *resp_len = 0; + return MBOX_WRONG_ID; + } + } + + *job_id = MBOX_RESP_JOB_ID(resp_data); + ret_resp_len = MBOX_RESP_LEN(resp_data); + mailbox_resp_ctr.payload->header = resp_data; + mailbox_resp_ctr.flag |= MBOX_PAYLOAD_FLAG_BUSY; + } + + if (ret_resp_len == 0) { + is_done = 1; + } + } + + if (is_done != 0) { + + /* copy header data to input address if applicable */ + if (header != 0) { + *header = mailbox_resp_ctr.payload->header; + } + + /* copy response data to input buffer if applicable */ + ret_resp_len = MBOX_RESP_LEN(mailbox_resp_ctr.payload->header); + if (ret_resp_len > 0 && response && resp_len) { + if (*resp_len > ret_resp_len) { + *resp_len = ret_resp_len; + } + + memcpy((uint8_t *) response, + (uint8_t *) mailbox_resp_ctr.payload->data, + *resp_len * MBOX_WORD_BYTE); + } + + /* reset async response param */ + mailbox_resp_ctr.index = 0; + mailbox_resp_ctr.flag = 0; + + if (MBOX_RESP_ERR(mailbox_resp_ctr.payload->header) > 0U) { + INFO("Error in async response: %x\n", + mailbox_resp_ctr.payload->header); + return -MBOX_RESP_ERR(mailbox_resp_ctr.payload->header); + } + + return MBOX_RET_OK; + } + + *resp_len = 0; + return (mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) ? MBOX_BUSY : MBOX_NO_RESPONSE; +} int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response, unsigned int *resp_len) diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c index 294040b9b..b0b56e932 100644 --- a/plat/intel/soc/common/socfpga_sip_svc.c +++ b/plat/intel/soc/common/socfpga_sip_svc.c @@ -552,6 +552,52 @@ uint32_t intel_hps_set_bridges(uint64_t enable, uint64_t mask) return INTEL_SIP_SMC_STATUS_OK; } +uint32_t intel_smc_service_completed(uint64_t addr, uint32_t size, + uint32_t mode, uint32_t *job_id, + uint32_t *ret_size, uint32_t *mbox_error) +{ + int status = 0; + uint32_t resp_len = size / MBOX_WORD_BYTE; + + if (resp_len > MBOX_DATA_MAX_LEN) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + if (!is_address_in_ddr_range(addr, size)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + if (mode == SERVICE_COMPLETED_MODE_ASYNC) { + status = mailbox_read_response_async(job_id, + NULL, (uint32_t *) addr, &resp_len, 0); + } else { + status = mailbox_read_response(job_id, + (uint32_t *) addr, &resp_len); + + if (status == MBOX_NO_RESPONSE) { + status = MBOX_BUSY; + } + } + + if (status == MBOX_NO_RESPONSE) { + return INTEL_SIP_SMC_STATUS_NO_RESPONSE; + } + + if (status == MBOX_BUSY) { + return INTEL_SIP_SMC_STATUS_BUSY; + } + + *ret_size = resp_len * MBOX_WORD_BYTE; + flush_dcache_range(addr, *ret_size); + + if (status != MBOX_RET_OK) { + *mbox_error = -status; + return INTEL_SIP_SMC_STATUS_ERROR; + } + + return INTEL_SIP_SMC_STATUS_OK; +} + /* * This function is responsible for handling all SiP calls from the NS world */ @@ -724,6 +770,19 @@ uintptr_t sip_smc_handler(uint32_t smc_fid, SMC_RET3(handle, status, x4, x5); + case INTEL_SIP_SMC_FCS_RANDOM_NUMBER: + status = intel_fcs_random_number_gen(x1, &retval64, + &mbox_error); + SMC_RET4(handle, status, mbox_error, x1, retval64); + + case INTEL_SIP_SMC_FCS_SEND_CERTIFICATE: + status = intel_fcs_send_cert(x1, x2, &send_id); + SMC_RET1(handle, status); + + case INTEL_SIP_SMC_FCS_GET_PROVISION_DATA: + status = intel_fcs_get_provision_data(&send_id); + SMC_RET1(handle, status); + case INTEL_SIP_SMC_FCS_CNTR_SET_PREAUTH: status = intel_fcs_cntr_set_preauth(x1, x2, x3, &mbox_error);