1
2
3
4
5
6
7#include <common.h>
8#include <mailbox.h>
9#include <malloc.h>
10
11#include <asm/arch/rtkit.h>
12#include <linux/apple-mailbox.h>
13#include <linux/bitfield.h>
14
15#define APPLE_RTKIT_EP_MGMT 0
16#define APPLE_RTKIT_EP_CRASHLOG 1
17#define APPLE_RTKIT_EP_SYSLOG 2
18#define APPLE_RTKIT_EP_DEBUG 3
19#define APPLE_RTKIT_EP_IOREPORT 4
20#define APPLE_RTKIT_EP_TRACEKIT 10
21
22
23#define APPLE_RTKIT_MGMT_TYPE GENMASK(59, 52)
24
25#define APPLE_RTKIT_MGMT_PWR_STATE GENMASK(15, 0)
26
27#define APPLE_RTKIT_MGMT_HELLO 1
28#define APPLE_RTKIT_MGMT_HELLO_REPLY 2
29#define APPLE_RTKIT_MGMT_HELLO_MINVER GENMASK(15, 0)
30#define APPLE_RTKIT_MGMT_HELLO_MAXVER GENMASK(31, 16)
31
32#define APPLE_RTKIT_MGMT_STARTEP 5
33#define APPLE_RTKIT_MGMT_STARTEP_EP GENMASK(39, 32)
34#define APPLE_RTKIT_MGMT_STARTEP_FLAG BIT(1)
35
36#define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE 6
37#define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK 7
38
39#define APPLE_RTKIT_MGMT_EPMAP 8
40#define APPLE_RTKIT_MGMT_EPMAP_LAST BIT(51)
41#define APPLE_RTKIT_MGMT_EPMAP_BASE GENMASK(34, 32)
42#define APPLE_RTKIT_MGMT_EPMAP_BITMAP GENMASK(31, 0)
43
44#define APPLE_RTKIT_MGMT_EPMAP_REPLY 8
45#define APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE BIT(0)
46
47#define APPLE_RTKIT_MIN_SUPPORTED_VERSION 11
48#define APPLE_RTKIT_MAX_SUPPORTED_VERSION 12
49
50
51#define APPLE_RTKIT_BUFFER_REQUEST 1
52#define APPLE_RTKIT_BUFFER_REQUEST_SIZE GENMASK(51, 44)
53#define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK(41, 0)
54
55#define TIMEOUT_1SEC_US 1000000
56
57struct apple_rtkit {
58 struct mbox_chan *chan;
59 void *cookie;
60 apple_rtkit_shmem_setup shmem_setup;
61 apple_rtkit_shmem_destroy shmem_destroy;
62
63 struct apple_rtkit_buffer syslog_buffer;
64 struct apple_rtkit_buffer crashlog_buffer;
65 struct apple_rtkit_buffer ioreport_buffer;
66};
67
68struct apple_rtkit *apple_rtkit_init(struct mbox_chan *chan, void *cookie,
69 apple_rtkit_shmem_setup shmem_setup,
70 apple_rtkit_shmem_destroy shmem_destroy)
71{
72 struct apple_rtkit *rtk;
73
74 rtk = calloc(sizeof(*rtk), 1);
75 if (!rtk)
76 return NULL;
77
78 rtk->chan = chan;
79 rtk->cookie = cookie;
80 rtk->shmem_setup = shmem_setup;
81 rtk->shmem_destroy = shmem_destroy;
82
83 return rtk;
84}
85
86void apple_rtkit_free(struct apple_rtkit *rtk)
87{
88 if (rtk->shmem_destroy) {
89 if (rtk->syslog_buffer.buffer)
90 rtk->shmem_destroy(rtk->cookie, &rtk->syslog_buffer);
91 if (rtk->crashlog_buffer.buffer)
92 rtk->shmem_destroy(rtk->cookie, &rtk->crashlog_buffer);
93 if (rtk->ioreport_buffer.buffer)
94 rtk->shmem_destroy(rtk->cookie, &rtk->ioreport_buffer);
95 }
96 free(rtk);
97}
98
99static int rtkit_handle_buf_req(struct apple_rtkit *rtk, int endpoint, struct apple_mbox_msg *msg)
100{
101 struct apple_rtkit_buffer *buf;
102 size_t num_4kpages;
103 int ret;
104
105 num_4kpages = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg->msg0);
106
107 if (num_4kpages == 0) {
108 printf("%s: unexpected request for buffer without size\n", __func__);
109 return -1;
110 }
111
112 switch (endpoint) {
113 case APPLE_RTKIT_EP_CRASHLOG:
114 buf = &rtk->crashlog_buffer;
115 break;
116 case APPLE_RTKIT_EP_SYSLOG:
117 buf = &rtk->syslog_buffer;
118 break;
119 case APPLE_RTKIT_EP_IOREPORT:
120 buf = &rtk->ioreport_buffer;
121 break;
122 default:
123 printf("%s: unexpected endpoint %d\n", __func__, endpoint);
124 return -1;
125 }
126
127 buf->dva = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg->msg0);
128 buf->size = num_4kpages << 12;
129 buf->is_mapped = false;
130
131 if (rtk->shmem_setup) {
132 ret = rtk->shmem_setup(rtk->cookie, buf);
133 if (ret < 0) {
134 printf("%s: shmen_setup failed for endpoint %d\n", __func__,
135 endpoint);
136 return ret;
137 }
138 }
139
140 if (!buf->is_mapped) {
141 msg->msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_BUFFER_REQUEST) |
142 FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, num_4kpages) |
143 FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, buf->dva);
144 msg->msg1 = endpoint;
145
146 return mbox_send(rtk->chan, msg);
147 }
148
149 return 0;
150}
151
152int apple_rtkit_boot(struct apple_rtkit *rtk)
153{
154 struct apple_mbox_msg msg;
155 int endpoints[256];
156 int nendpoints = 0;
157 int endpoint;
158 int min_ver, max_ver, want_ver;
159 int msgtype, pwrstate;
160 u64 reply;
161 u32 bitmap, base;
162 int i, ret;
163
164
165 msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE) |
166 FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, APPLE_RTKIT_PWR_STATE_ON);
167 msg.msg1 = APPLE_RTKIT_EP_MGMT;
168 ret = mbox_send(rtk->chan, &msg);
169 if (ret < 0)
170 return ret;
171
172
173 ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US);
174 if (ret < 0)
175 return ret;
176
177 endpoint = msg.msg1;
178 msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0);
179 if (endpoint != APPLE_RTKIT_EP_MGMT) {
180 printf("%s: unexpected endpoint %d\n", __func__, endpoint);
181 return -EINVAL;
182 }
183 if (msgtype != APPLE_RTKIT_MGMT_HELLO) {
184 printf("%s: unexpected message type %d\n", __func__, msgtype);
185 return -EINVAL;
186 }
187
188 min_ver = FIELD_GET(APPLE_RTKIT_MGMT_HELLO_MINVER, msg.msg0);
189 max_ver = FIELD_GET(APPLE_RTKIT_MGMT_HELLO_MAXVER, msg.msg0);
190 want_ver = min(APPLE_RTKIT_MAX_SUPPORTED_VERSION, max_ver);
191
192 if (min_ver > APPLE_RTKIT_MAX_SUPPORTED_VERSION) {
193 printf("%s: firmware min version %d is too new\n",
194 __func__, min_ver);
195 return -ENOTSUPP;
196 }
197
198 if (max_ver < APPLE_RTKIT_MIN_SUPPORTED_VERSION) {
199 printf("%s: firmware max version %d is too old\n",
200 __func__, max_ver);
201 return -ENOTSUPP;
202 }
203
204
205 msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_HELLO_REPLY) |
206 FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MINVER, want_ver) |
207 FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MAXVER, want_ver);
208 msg.msg1 = APPLE_RTKIT_EP_MGMT;
209 ret = mbox_send(rtk->chan, &msg);
210 if (ret < 0)
211 return ret;
212
213wait_epmap:
214
215 ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US);
216 if (ret < 0)
217 return ret;
218
219 endpoint = msg.msg1;
220 msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0);
221 if (endpoint != APPLE_RTKIT_EP_MGMT) {
222 printf("%s: unexpected endpoint %d\n", __func__, endpoint);
223 return -EINVAL;
224 }
225 if (msgtype != APPLE_RTKIT_MGMT_EPMAP) {
226 printf("%s: unexpected message type %d\n", __func__, msgtype);
227 return -EINVAL;
228 }
229
230 bitmap = FIELD_GET(APPLE_RTKIT_MGMT_EPMAP_BITMAP, msg.msg0);
231 base = FIELD_GET(APPLE_RTKIT_MGMT_EPMAP_BASE, msg.msg0);
232 for (i = 0; i < 32; i++) {
233 if (bitmap & (1U << i))
234 endpoints[nendpoints++] = base * 32 + i;
235 }
236
237
238 reply = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_EPMAP_REPLY) |
239 FIELD_PREP(APPLE_RTKIT_MGMT_EPMAP_BASE, base);
240 if (msg.msg0 & APPLE_RTKIT_MGMT_EPMAP_LAST)
241 reply |= APPLE_RTKIT_MGMT_EPMAP_LAST;
242 else
243 reply |= APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE;
244 msg.msg0 = reply;
245 msg.msg1 = APPLE_RTKIT_EP_MGMT;
246 ret = mbox_send(rtk->chan, &msg);
247 if (ret < 0)
248 return ret;
249
250 if (reply & APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE)
251 goto wait_epmap;
252
253 for (i = 0; i < nendpoints; i++) {
254
255
256
257
258 switch (endpoints[i]) {
259 case APPLE_RTKIT_EP_MGMT:
260 case APPLE_RTKIT_EP_SYSLOG:
261 case APPLE_RTKIT_EP_DEBUG:
262 case APPLE_RTKIT_EP_TRACEKIT:
263 continue;
264 default:
265 break;
266 }
267
268
269 msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_STARTEP) |
270 FIELD_PREP(APPLE_RTKIT_MGMT_STARTEP_EP, endpoints[i]) |
271 APPLE_RTKIT_MGMT_STARTEP_FLAG;
272 msg.msg1 = APPLE_RTKIT_EP_MGMT;
273 ret = mbox_send(rtk->chan, &msg);
274 if (ret < 0)
275 return ret;
276 }
277
278 pwrstate = APPLE_RTKIT_PWR_STATE_SLEEP;
279 while (pwrstate != APPLE_RTKIT_PWR_STATE_ON) {
280 ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US);
281 if (ret < 0)
282 return ret;
283
284 endpoint = msg.msg1;
285 msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0);
286
287 if (endpoint == APPLE_RTKIT_EP_CRASHLOG ||
288 endpoint == APPLE_RTKIT_EP_SYSLOG ||
289 endpoint == APPLE_RTKIT_EP_IOREPORT) {
290 if (msgtype == APPLE_RTKIT_BUFFER_REQUEST) {
291 ret = rtkit_handle_buf_req(rtk, endpoint, &msg);
292 if (ret < 0)
293 return ret;
294 continue;
295 }
296 }
297
298 if (endpoint == APPLE_RTKIT_EP_IOREPORT) {
299
300 if (msgtype == 0xc || msgtype == 0x8) {
301 ret = mbox_send(rtk->chan, &msg);
302 if (ret < 0)
303 return ret;
304 continue;
305 }
306 }
307
308 if (endpoint != APPLE_RTKIT_EP_MGMT) {
309 printf("%s: unexpected endpoint %d\n", __func__, endpoint);
310 return -EINVAL;
311 }
312 if (msgtype != APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK) {
313 printf("%s: unexpected message type %d\n", __func__, msgtype);
314 return -EINVAL;
315 }
316
317 pwrstate = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0);
318 }
319
320 return 0;
321}
322
323int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate)
324{
325 struct apple_mbox_msg msg;
326 int ret;
327
328 msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE) |
329 FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate);
330 msg.msg1 = APPLE_RTKIT_EP_MGMT;
331 ret = mbox_send(rtk->chan, &msg);
332 if (ret < 0)
333 return ret;
334
335 ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US);
336 if (ret < 0)
337 return ret;
338
339 return 0;
340}
341