Commit 4a4709d4 authored by Ang Tien Sung's avatar Ang Tien Sung Committed by Greg Kroah-Hartman
Browse files

firmware: stratix10-svc: add new FCS commands



Extending the fpga svc driver to support 6 new FPGA Crypto
Service(FCS) commands.
We are adding FCS SDOS data encryption and decryption,
random number generator, image validation request,
reading the data provision and certificate validation.

Signed-off-by: default avatarAng Tien Sung <tien.sung.ang@intel.com>
Signed-off-by: default avatarDinh Nguyen <dinguyen@kernel.org>
Link: https://lore.kernel.org/r/20220711223140.2307945-3-dinguyen@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 79b93625
Loading
Loading
Loading
Loading
+97 −8
Original line number Diff line number Diff line
@@ -99,8 +99,10 @@ struct stratix10_svc_data_mem {
/**
 * struct stratix10_svc_data - service data structure
 * @chan: service channel
 * @paddr: playload physical address
 * @size: playload size
 * @paddr: physical address of to be processed payload
 * @size: to be processed playload size
 * @paddr_output: physical address of processed payload
 * @size_output: processed payload size
 * @command: service command requested by client
 * @flag: configuration type (full or partial)
 * @arg: args to be passed via registers and not physically mapped buffers
@@ -111,6 +113,8 @@ struct stratix10_svc_data {
	struct stratix10_svc_chan *chan;
	phys_addr_t paddr;
	size_t size;
	phys_addr_t paddr_output;
	size_t size_output;
	u32 command;
	u32 flag;
	u64 arg[3];
@@ -320,7 +324,10 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data,
	case COMMAND_RECONFIG:
	case COMMAND_RSU_UPDATE:
	case COMMAND_RSU_NOTIFY:
	case COMMAND_POLL_SERVICE_STATUS:
	case COMMAND_FCS_REQUEST_SERVICE:
	case COMMAND_FCS_SEND_CERTIFICATE:
	case COMMAND_FCS_DATA_ENCRYPTION:
	case COMMAND_FCS_DATA_DECRYPTION:
		cb_data->status = BIT(SVC_STATUS_OK);
		break;
	case COMMAND_RECONFIG_DATA_SUBMIT:
@@ -340,6 +347,14 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data,
		cb_data->kaddr1 = &res.a1;
		cb_data->kaddr2 = &res.a2;
		break;
	case COMMAND_FCS_RANDOM_NUMBER_GEN:
	case COMMAND_FCS_GET_PROVISION_DATA:
	case COMMAND_POLL_SERVICE_STATUS:
		cb_data->status = BIT(SVC_STATUS_OK);
		cb_data->kaddr1 = &res.a1;
		cb_data->kaddr2 = svc_pa_to_va(res.a2);
		cb_data->kaddr3 = &res.a3;
		break;
	default:
		pr_warn("it shouldn't happen\n");
		break;
@@ -366,7 +381,7 @@ static int svc_normal_to_secure_thread(void *data)
	struct stratix10_svc_data *pdata;
	struct stratix10_svc_cb_data *cbdata;
	struct arm_smccc_res res;
	unsigned long a0, a1, a2;
	unsigned long a0, a1, a2, a3, a4, a5, a6, a7;
	int ret_fifo = 0;

	pdata =  kmalloc(sizeof(*pdata), GFP_KERNEL);
@@ -383,6 +398,11 @@ static int svc_normal_to_secure_thread(void *data)
	a0 = INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK;
	a1 = 0;
	a2 = 0;
	a3 = 0;
	a4 = 0;
	a5 = 0;
	a6 = 0;
	a7 = 0;

	pr_debug("smc_hvc_shm_thread is running\n");

@@ -453,12 +473,50 @@ static int svc_normal_to_secure_thread(void *data)
			a1 = 0;
			a2 = 0;
			break;

		/* for FCS */
		case COMMAND_FCS_DATA_ENCRYPTION:
			a0 = INTEL_SIP_SMC_FCS_CRYPTION;
			a1 = 1;
			a2 = (unsigned long)pdata->paddr;
			a3 = (unsigned long)pdata->size;
			a4 = (unsigned long)pdata->paddr_output;
			a5 = (unsigned long)pdata->size_output;
			break;
		case COMMAND_FCS_DATA_DECRYPTION:
			a0 = INTEL_SIP_SMC_FCS_CRYPTION;
			a1 = 0;
			a2 = (unsigned long)pdata->paddr;
			a3 = (unsigned long)pdata->size;
			a4 = (unsigned long)pdata->paddr_output;
			a5 = (unsigned long)pdata->size_output;
			break;
		case COMMAND_FCS_RANDOM_NUMBER_GEN:
			a0 = INTEL_SIP_SMC_FCS_RANDOM_NUMBER;
			a1 = (unsigned long)pdata->paddr;
			a2 = 0;
			break;
		case COMMAND_FCS_REQUEST_SERVICE:
			a0 = INTEL_SIP_SMC_FCS_SERVICE_REQUEST;
			a1 = (unsigned long)pdata->paddr;
			a2 = (unsigned long)pdata->size;
			break;
		case COMMAND_FCS_SEND_CERTIFICATE:
			a0 = INTEL_SIP_SMC_FCS_SEND_CERTIFICATE;
			a1 = (unsigned long)pdata->paddr;
			a2 = (unsigned long)pdata->size;
			break;
		case COMMAND_FCS_GET_PROVISION_DATA:
			a0 = INTEL_SIP_SMC_FCS_GET_PROVISION_DATA;
			a1 = (unsigned long)pdata->paddr;
			a2 = 0;
			break;

		/* for polling */
		case COMMAND_POLL_SERVICE_STATUS:
			a0 = INTEL_SIP_SMC_SERVICE_COMPLETED;
			a1 = (unsigned long)pdata->paddr;
			a2 = (unsigned long)pdata->size;

			break;

		default:
@@ -466,10 +524,14 @@ static int svc_normal_to_secure_thread(void *data)
			break;
		}
		pr_debug("%s: before SMC call -- a0=0x%016x a1=0x%016x",
			 __func__, (unsigned int)a0, (unsigned int)a1);
			 __func__,
			 (unsigned int)a0,
			 (unsigned int)a1);
		pr_debug(" a2=0x%016x\n", (unsigned int)a2);

		ctrl->invoke_fn(a0, a1, a2, 0, 0, 0, 0, 0, &res);
		pr_debug(" a3=0x%016x\n", (unsigned int)a3);
		pr_debug(" a4=0x%016x\n", (unsigned int)a4);
		pr_debug(" a5=0x%016x\n", (unsigned int)a5);
		ctrl->invoke_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);

		pr_debug("%s: after SMC call -- res.a0=0x%016x",
			 __func__, (unsigned int)res.a0);
@@ -512,6 +574,22 @@ static int svc_normal_to_secure_thread(void *data)
			break;
		case INTEL_SIP_SMC_STATUS_REJECTED:
			pr_debug("%s: STATUS_REJECTED\n", __func__);
			/* for FCS */
			switch (pdata->command) {
			case COMMAND_FCS_REQUEST_SERVICE:
			case COMMAND_FCS_SEND_CERTIFICATE:
			case COMMAND_FCS_GET_PROVISION_DATA:
			case COMMAND_FCS_DATA_ENCRYPTION:
			case COMMAND_FCS_DATA_DECRYPTION:
			case COMMAND_FCS_RANDOM_NUMBER_GEN:
				cbdata->status = BIT(SVC_STATUS_INVALID_PARAM);
				cbdata->kaddr1 = NULL;
				cbdata->kaddr2 = NULL;
				cbdata->kaddr3 = NULL;
				pdata->chan->scl->receive_cb(pdata->chan->scl,
							     cbdata);
				break;
			}
			break;
		case INTEL_SIP_SMC_STATUS_ERROR:
		case INTEL_SIP_SMC_RSU_ERROR:
@@ -886,8 +964,19 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg)
		list_for_each_entry(p_mem, &svc_data_mem, node)
			if (p_mem->vaddr == p_msg->payload) {
				p_data->paddr = p_mem->paddr;
				p_data->size = p_msg->payload_length;
				break;
			}
		if (p_msg->payload_output) {
			list_for_each_entry(p_mem, &svc_data_mem, node)
				if (p_mem->vaddr == p_msg->payload_output) {
					p_data->paddr_output =
						p_mem->paddr;
					p_data->size_output =
						p_msg->payload_length_output;
					break;
				}
		}
	}

	p_data->command = p_msg->command;
+111 −0
Original line number Diff line number Diff line
@@ -445,4 +445,115 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
#define INTEL_SIP_SMC_FIRMWARE_VERSION \
        INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FIRMWARE_VERSION)

/**
 * SMC call protocol for FPGA Crypto Service (FCS)
 * FUNCID starts from 90
 */

/**
 * Request INTEL_SIP_SMC_FCS_RANDOM_NUMBER
 *
 * Sync call used to query the random number generated by the firmware
 *
 * Call register usage:
 * a0 INTEL_SIP_SMC_FCS_RANDOM_NUMBER
 * a1 the physical address for firmware to write generated random data
 * a2-a7 not used
 *
 * Return status:
 * a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FCS_ERROR or
 *      INTEL_SIP_SMC_FCS_REJECTED
 * a1 mailbox error
 * a2 the physical address of generated random number
 * a3 size
 */
#define INTEL_SIP_SMC_FUNCID_FCS_RANDOM_NUMBER 90
#define INTEL_SIP_SMC_FCS_RANDOM_NUMBER \
	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_RANDOM_NUMBER)

/**
 * Request INTEL_SIP_SMC_FCS_CRYPTION
 * Async call for data encryption and HMAC signature generation, or for
 * data decryption and HMAC verification.
 *
 * Call INTEL_SIP_SMC_SERVICE_COMPLETED to get the output encrypted or
 * decrypted data
 *
 * Call register usage:
 * a0 INTEL_SIP_SMC_FCS_CRYPTION
 * a1 cryption mode (1 for encryption and 0 for decryption)
 * a2 physical address which stores to be encrypted or decrypted data
 * a3 input data size
 * a4 physical address which will hold the encrypted or decrypted output data
 * a5 output data size
 * a6-a7 not used
 *
 * Return status:
 * a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_ERROR or
 *      INTEL_SIP_SMC_STATUS_REJECTED
 * a1-3 not used
 */
#define INTEL_SIP_SMC_FUNCID_FCS_CRYPTION 91
#define INTEL_SIP_SMC_FCS_CRYPTION \
	INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_CRYPTION)

/**
 * Request INTEL_SIP_SMC_FCS_SERVICE_REQUEST
 * Async call for authentication service of HPS software
 *
 * Call register usage:
 * a0 INTEL_SIP_SMC_FCS_SERVICE_REQUEST
 * a1 the physical address of data block
 * a2 size of data block
 * a3-a7 not used
 *
 * Return status:
 * a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_ERROR or
 *      INTEL_SIP_SMC_REJECTED
 * a1-a3 not used
 */
#define INTEL_SIP_SMC_FUNCID_FCS_SERVICE_REQUEST 92
#define INTEL_SIP_SMC_FCS_SERVICE_REQUEST \
	INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_SERVICE_REQUEST)

/**
 * Request INTEL_SIP_SMC_FUNCID_FCS_SEND_CERTIFICATE
 * Sync call to send a signed certificate
 *
 * Call register usage:
 * a0 INTEL_SIP_SMC_FCS_SEND_CERTIFICATE
 * a1 the physical address of CERTIFICATE block
 * a2 size of data block
 * a3-a7 not used
 *
 * Return status:
 * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_FCS_REJECTED
 * a1-a3 not used
 */
#define INTEL_SIP_SMC_FUNCID_FCS_SEND_CERTIFICATE 93
#define INTEL_SIP_SMC_FCS_SEND_CERTIFICATE \
	INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_SEND_CERTIFICATE)

/**
 * Request INTEL_SIP_SMC_FCS_GET_PROVISION_DATA
 * Sync call to dump all the fuses and key hashes
 *
 * Call register usage:
 * a0 INTEL_SIP_SMC_FCS_GET_PROVISION_DATA
 * a1 the physical address for firmware to write structure of fuse and
 *    key hashes
 * a2-a7 not used
 *
 * Return status:
 * a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FCS_ERROR or
 *      INTEL_SIP_SMC_FCS_REJECTED
 * a1 mailbox error
 * a2 physical address for the structure of fuse and key hashes
 * a3 the size of structure
 *
 */
#define INTEL_SIP_SMC_FUNCID_FCS_GET_PROVISION_DATA 94
#define INTEL_SIP_SMC_FCS_GET_PROVISION_DATA \
	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_GET_PROVISION_DATA)

#endif
+37 −4
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@
#define SVC_STATUS_BUSY			4
#define SVC_STATUS_ERROR		5
#define SVC_STATUS_NO_SUPPORT		6

/*
#define SVC_STATUS_INVALID_PARAM	7
/**
 * Flag bit for COMMAND_RECONFIG
 *
 * COMMAND_RECONFIG_FLAG_PARTIAL:
@@ -67,6 +67,8 @@
#define SVC_RECONFIG_REQUEST_TIMEOUT_MS         300
#define SVC_RECONFIG_BUFFER_TIMEOUT_MS          720
#define SVC_RSU_REQUEST_TIMEOUT_MS              300
#define SVC_FCS_REQUEST_TIMEOUT_MS		2000
#define SVC_COMPLETED_TIMEOUT_MS		30000

struct stratix10_svc_chan;

@@ -111,20 +113,47 @@ struct stratix10_svc_chan;
 *
 * @COMMAND_FIRMWARE_VERSION: query running firmware version, return status
 * is SVC_STATUS_OK or SVC_STATUS_ERROR
 *
 * @COMMAND_FCS_REQUEST_SERVICE: request validation of image from firmware,
 * return status is SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM
 *
 * @COMMAND_FCS_SEND_CERTIFICATE: send a certificate, return status is
 * SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
 *
 * @COMMAND_FCS_GET_PROVISION_DATA: read the provisioning data, return status is
 * SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
 *
 * @COMMAND_FCS_DATA_ENCRYPTION: encrypt the data, return status is
 * SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
 *
 * @COMMAND_FCS_DATA_DECRYPTION: decrypt the data, return status is
 * SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
 *
 * @COMMAND_FCS_RANDOM_NUMBER_GEN: generate a random number, return status
 * is SVC_STATUS_OK, SVC_STATUS_ERROR
 */
enum stratix10_svc_command_code {
	/* for FPGA */
	COMMAND_NOOP = 0,
	COMMAND_RECONFIG,
	COMMAND_RECONFIG_DATA_SUBMIT,
	COMMAND_RECONFIG_DATA_CLAIM,
	COMMAND_RECONFIG_STATUS,
	COMMAND_RSU_STATUS,
	/* for RSU */
	COMMAND_RSU_STATUS = 10,
	COMMAND_RSU_UPDATE,
	COMMAND_RSU_NOTIFY,
	COMMAND_RSU_RETRY,
	COMMAND_RSU_MAX_RETRY,
	COMMAND_RSU_DCMF_VERSION,
	COMMAND_FIRMWARE_VERSION,
	/* for FCS */
	COMMAND_FCS_REQUEST_SERVICE = 20,
	COMMAND_FCS_SEND_CERTIFICATE,
	COMMAND_FCS_GET_PROVISION_DATA,
	COMMAND_FCS_DATA_ENCRYPTION,
	COMMAND_FCS_DATA_DECRYPTION,
	COMMAND_FCS_RANDOM_NUMBER_GEN,
	/* for general status poll */
	COMMAND_POLL_SERVICE_STATUS = 40,
};
@@ -132,13 +161,17 @@ enum stratix10_svc_command_code {
/**
 * struct stratix10_svc_client_msg - message sent by client to service
 * @payload: starting address of data need be processed
 * @payload_length: data size in bytes
 * @payload_length: to be processed data size in bytes
 * @payload_output: starting address of processed data
 * @payload_length_output: processed data size in bytes
 * @command: service command
 * @arg: args to be passed via registers and not physically mapped buffers
 */
struct stratix10_svc_client_msg {
	void *payload;
	size_t payload_length;
	void *payload_output;
	size_t payload_length_output;
	enum stratix10_svc_command_code command;
	u64 arg[3];
};