xref: /optee_os/core/drivers/scmi-msg/shm_msg.c (revision 916cc52ae46d43e1ad1ce87f4618b3c104eb15ee)
1*916cc52aSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
2*916cc52aSEtienne Carriere /*
3*916cc52aSEtienne Carriere  * Copyright (c) 2021-2022, Linaro Limited
4*916cc52aSEtienne Carriere  */
5*916cc52aSEtienne Carriere #include <assert.h>
6*916cc52aSEtienne Carriere #include <drivers/scmi-msg.h>
7*916cc52aSEtienne Carriere #include <drivers/scmi.h>
8*916cc52aSEtienne Carriere #include <io.h>
9*916cc52aSEtienne Carriere #include <kernel/misc.h>
10*916cc52aSEtienne Carriere #include <stdint.h>
11*916cc52aSEtienne Carriere #include <string.h>
12*916cc52aSEtienne Carriere #include <trace.h>
13*916cc52aSEtienne Carriere #include <util.h>
14*916cc52aSEtienne Carriere 
15*916cc52aSEtienne Carriere #include "common.h"
16*916cc52aSEtienne Carriere 
17*916cc52aSEtienne Carriere /**
18*916cc52aSEtienne Carriere  * struct msg_header - MSG formatted header for MSG base shared memory transfer
19*916cc52aSEtienne Carriere  *
20*916cc52aSEtienne Carriere  * @message_header: 32bit header used in MSG shared memory protocol
21*916cc52aSEtienne Carriere  * @payload: SCMI message payload data
22*916cc52aSEtienne Carriere  */
23*916cc52aSEtienne Carriere struct msg_header {
24*916cc52aSEtienne Carriere 	uint32_t message_header;
25*916cc52aSEtienne Carriere 	uint32_t payload[];
26*916cc52aSEtienne Carriere };
27*916cc52aSEtienne Carriere 
28*916cc52aSEtienne Carriere /* Bit fields packed in msg_header::message_header */
29*916cc52aSEtienne Carriere #define MSG_ID_MASK		GENMASK_32(7, 0)
30*916cc52aSEtienne Carriere #define MSG_ID(_hdr)		((_hdr) & MSG_ID_MASK)
31*916cc52aSEtienne Carriere 
32*916cc52aSEtienne Carriere #define MSG_TYPE_MASK		GENMASK_32(9, 8)
33*916cc52aSEtienne Carriere #define MSG_TYPE(_hdr)		(((_hdr) & MSG_TYPE_MASK) >> 8)
34*916cc52aSEtienne Carriere 
35*916cc52aSEtienne Carriere #define MSG_PROT_ID_MASK	GENMASK_32(17, 10)
36*916cc52aSEtienne Carriere #define MSG_PROT_ID(_hdr)	(((_hdr) & MSG_PROT_ID_MASK) >> 10)
37*916cc52aSEtienne Carriere 
38*916cc52aSEtienne Carriere /*
39*916cc52aSEtienne Carriere  * Creates a SCMI message instance in secure memory and push it in the SCMI
40*916cc52aSEtienne Carriere  * message drivers. Message structure contains SCMI protocol meta-data and
41*916cc52aSEtienne Carriere  * references to input payload in secure memory and output message buffer
42*916cc52aSEtienne Carriere  * in shared memory.
43*916cc52aSEtienne Carriere  */
scmi_entry_msg(unsigned int channel_id,void * in_buf,size_t in_size,void * out_buf,size_t * out_size,uint32_t * sec_buf)44*916cc52aSEtienne Carriere TEE_Result scmi_entry_msg(unsigned int channel_id, void *in_buf, size_t in_size,
45*916cc52aSEtienne Carriere 			  void *out_buf, size_t *out_size, uint32_t *sec_buf)
46*916cc52aSEtienne Carriere {
47*916cc52aSEtienne Carriere 	struct scmi_msg_channel *channel = plat_scmi_get_channel(channel_id);
48*916cc52aSEtienne Carriere 	struct msg_header *hdr = NULL;
49*916cc52aSEtienne Carriere 	struct scmi_msg msg = { };
50*916cc52aSEtienne Carriere 	uint32_t msg_header = 0;
51*916cc52aSEtienne Carriere 
52*916cc52aSEtienne Carriere 	if (!channel) {
53*916cc52aSEtienne Carriere 		DMSG("Invalid channel ID %u", channel_id);
54*916cc52aSEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
55*916cc52aSEtienne Carriere 	}
56*916cc52aSEtienne Carriere 
57*916cc52aSEtienne Carriere 	assert(in_buf && out_buf && out_size && sec_buf);
58*916cc52aSEtienne Carriere 
59*916cc52aSEtienne Carriere 	if (in_size < sizeof(struct msg_header) ||
60*916cc52aSEtienne Carriere 	    in_size - sizeof(struct msg_header) > SCMI_SEC_PAYLOAD_SIZE ||
61*916cc52aSEtienne Carriere 	    !IS_ALIGNED_WITH_TYPE(in_buf, uint32_t) ||
62*916cc52aSEtienne Carriere 	    *out_size < sizeof(struct msg_header) ||
63*916cc52aSEtienne Carriere 	    !IS_ALIGNED_WITH_TYPE(out_buf, uint32_t)) {
64*916cc52aSEtienne Carriere 		DMSG("Invalid SCMI buffer references %zu@%p / %zu@%p",
65*916cc52aSEtienne Carriere 		     in_size, in_buf, *out_size, out_buf);
66*916cc52aSEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
67*916cc52aSEtienne Carriere 	}
68*916cc52aSEtienne Carriere 
69*916cc52aSEtienne Carriere 	if (!scmi_msg_claim_channel(channel)) {
70*916cc52aSEtienne Carriere 		DMSG("SCMI channel %u busy", channel_id);
71*916cc52aSEtienne Carriere 		return TEE_ERROR_BUSY;
72*916cc52aSEtienne Carriere 	}
73*916cc52aSEtienne Carriere 
74*916cc52aSEtienne Carriere 	/* Copy SCMI protocol data and message payload in secure memory */
75*916cc52aSEtienne Carriere 	hdr = (struct msg_header *)in_buf;
76*916cc52aSEtienne Carriere 	msg_header = READ_ONCE(hdr->message_header);
77*916cc52aSEtienne Carriere 
78*916cc52aSEtienne Carriere 	msg.protocol_id = MSG_PROT_ID(msg_header);
79*916cc52aSEtienne Carriere 	msg.message_id = MSG_ID(msg_header);
80*916cc52aSEtienne Carriere 	msg.channel_id = channel_id;
81*916cc52aSEtienne Carriere 
82*916cc52aSEtienne Carriere 	msg.in = (char *)sec_buf;
83*916cc52aSEtienne Carriere 	msg.in_size = in_size - sizeof(struct msg_header);
84*916cc52aSEtienne Carriere 	memcpy(msg.in, hdr->payload, msg.in_size);
85*916cc52aSEtienne Carriere 
86*916cc52aSEtienne Carriere 	/* Prepare output message buffer references */
87*916cc52aSEtienne Carriere 	hdr = (struct msg_header *)out_buf;
88*916cc52aSEtienne Carriere 
89*916cc52aSEtienne Carriere 	msg.out = (char *)hdr->payload;
90*916cc52aSEtienne Carriere 	msg.out_size = *out_size - sizeof(struct msg_header);
91*916cc52aSEtienne Carriere 
92*916cc52aSEtienne Carriere 	scmi_process_message(&msg);
93*916cc52aSEtienne Carriere 
94*916cc52aSEtienne Carriere 	/* Update SCMI protocol data and output shared buffer size */
95*916cc52aSEtienne Carriere 	hdr->message_header = msg_header;
96*916cc52aSEtienne Carriere 	*out_size = msg.out_size_out + sizeof(struct msg_header);
97*916cc52aSEtienne Carriere 
98*916cc52aSEtienne Carriere 	scmi_msg_release_channel(channel);
99*916cc52aSEtienne Carriere 
100*916cc52aSEtienne Carriere 	return TEE_SUCCESS;
101*916cc52aSEtienne Carriere }
102