1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
/*
* Copyright (c) 2022, Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/mmio.h>
#include "socfpga_mailbox.h"
#include "socfpga_sip_svc.h"
static uint32_t intel_v2_mbox_send_cmd(uint32_t req_header,
uint32_t *data, uint32_t data_size)
{
uint32_t value;
uint32_t len;
if ((data == NULL) || (data_size == 0)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (data_size > (MBOX_INC_HEADER_MAX_WORD_SIZE * MBOX_WORD_BYTE)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(data_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
/* Make sure client id align in SMC SiP V2 header and mailbox header */
value = (req_header >> INTEL_SIP_SMC_HEADER_CID_OFFSET) &
INTEL_SIP_SMC_HEADER_CID_MASK;
if (value != MBOX_RESP_CLIENT_ID(data[0])) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
/* Make sure job id align in SMC SiP V2 header and mailbox header */
value = (req_header >> INTEL_SIP_SMC_HEADER_JOB_ID_OFFSET) &
INTEL_SIP_SMC_HEADER_JOB_ID_MASK;
if (value != MBOX_RESP_JOB_ID(data[0])) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
/*
* Make sure data length align in SMC SiP V2 header and
* mailbox header
*/
len = (data_size / MBOX_WORD_BYTE) - 1;
if (len != MBOX_RESP_LEN(data[0])) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
return mailbox_send_cmd_async_ext(data[0], &data[1], len);
}
static uint32_t intel_v2_mbox_poll_resp(uint64_t req_header,
uint32_t *data, uint32_t *data_size,
uint64_t *resp_header)
{
int status = 0;
uint32_t resp_len;
uint32_t job_id = 0;
uint32_t client_id = 0;
uint32_t version;
if ((data == NULL) || (data_size == NULL) || (resp_header == NULL)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
if (!is_size_4_bytes_aligned(*data_size)) {
return INTEL_SIP_SMC_STATUS_REJECTED;
}
resp_len = (*data_size / MBOX_WORD_BYTE) - 1;
status = mailbox_read_response_async(&job_id, &data[0], &data[1],
&resp_len, 1);
if (status == MBOX_BUSY) {
status = INTEL_SIP_SMC_STATUS_BUSY;
} else if (status == MBOX_NO_RESPONSE) {
status = INTEL_SIP_SMC_STATUS_NO_RESPONSE;
} else {
*data_size = 0;
if (resp_len > 0) {
/*
* Fill in the final response length,
* the length include both mailbox header and payload
*/
*data_size = (resp_len + 1) * MBOX_WORD_BYTE;
/* Extract the client id from mailbox header */
client_id = MBOX_RESP_CLIENT_ID(data[0]);
}
/*
* Extract SMC SiP V2 protocol version from
* SMC request header
*/
version = (req_header >> INTEL_SIP_SMC_HEADER_VERSION_OFFSET) &
INTEL_SIP_SMC_HEADER_VERSION_MASK;
/* Fill in SMC SiP V2 protocol response header */
*resp_header = 0;
*resp_header |= (((uint64_t)job_id) &
INTEL_SIP_SMC_HEADER_JOB_ID_MASK) <<
INTEL_SIP_SMC_HEADER_JOB_ID_OFFSET;
*resp_header |= (((uint64_t)client_id) &
INTEL_SIP_SMC_HEADER_CID_MASK) <<
INTEL_SIP_SMC_HEADER_CID_OFFSET;
*resp_header |= (((uint64_t)version) &
INTEL_SIP_SMC_HEADER_VERSION_MASK) <<
INTEL_SIP_SMC_HEADER_VERSION_OFFSET;
}
return status;
}
uintptr_t sip_smc_handler_v2(uint32_t smc_fid,
u_register_t x1,
u_register_t x2,
u_register_t x3,
u_register_t x4,
void *cookie,
void *handle,
u_register_t flags)
{
uint32_t retval = 0;
uint64_t retval64 = 0;
int status = INTEL_SIP_SMC_STATUS_OK;
switch (smc_fid) {
case INTEL_SIP_SMC_V2_GET_SVC_VERSION:
SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, x1,
SIP_SVC_VERSION_MAJOR,
SIP_SVC_VERSION_MINOR);
case INTEL_SIP_SMC_V2_REG_READ:
status = intel_secure_reg_read(x2, &retval);
SMC_RET4(handle, status, x1, retval, x2);
case INTEL_SIP_SMC_V2_REG_WRITE:
status = intel_secure_reg_write(x2, (uint32_t)x3, &retval);
SMC_RET4(handle, status, x1, retval, x2);
case INTEL_SIP_SMC_V2_REG_UPDATE:
status = intel_secure_reg_update(x2, (uint32_t)x3,
(uint32_t)x4, &retval);
SMC_RET4(handle, status, x1, retval, x2);
case INTEL_SIP_SMC_V2_HPS_SET_BRIDGES:
status = intel_hps_set_bridges(x2, x3);
SMC_RET2(handle, status, x1);
case INTEL_SIP_SMC_V2_RSU_UPDATE_ADDR:
status = intel_rsu_update(x2);
SMC_RET2(handle, status, x1);
case INTEL_SIP_SMC_V2_MAILBOX_SEND_COMMAND:
status = intel_v2_mbox_send_cmd(x1, (uint32_t *)x2, x3);
SMC_RET2(handle, status, x1);
case INTEL_SIP_SMC_V2_MAILBOX_POLL_RESPONSE:
status = intel_v2_mbox_poll_resp(x1, (uint32_t *)x2,
(uint32_t *) &x3, &retval64);
SMC_RET4(handle, status, retval64, x2, x3);
default:
ERROR("%s: unhandled SMC V2 (0x%x)\n", __func__, smc_fid);
SMC_RET1(handle, SMC_UNK);
}
}
|