Skip to content

Commit a328988

Browse files
committed
sep: Add support for AKF mailboxes
Add support for SEP behind AKF mailboxes. Some SEPs of this type does not support the GETRAND operation, so handle that case as well. Signed-off-by: Nick Chan <towinchenmi@gmail.com>
1 parent e097241 commit a328988

3 files changed

Lines changed: 111 additions & 12 deletions

File tree

src/kboot.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ static int dt_set_rng_seed_sep(int node)
109109
u64 kaslr_seed;
110110
uint8_t rng_seed[128]; // same size used by Linux for kexec
111111

112+
if (!(sep_get_capabilities() & SEP_CAPABILITY_GETRAND))
113+
return -1;
114+
112115
if (sep_get_random(&kaslr_seed, sizeof(kaslr_seed)) != sizeof(kaslr_seed))
113116
bail("SEP: couldn't get enough random bytes for KASLR seed\n");
114117
if (sep_get_random(rng_seed, sizeof(rng_seed)) != sizeof(rng_seed))

src/sep.c

Lines changed: 103 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
#include <string.h>
44

5+
#include "adt.h"
6+
#include "akf.h"
57
#include "asc.h"
8+
#include "malloc.h"
69
#include "sep.h"
710
#include "types.h"
811
#include "utils.h"
@@ -18,21 +21,104 @@
1821

1922
#define SEP_TIMEOUT 1000
2023

21-
static asc_dev_t *sep_asc = NULL;
24+
enum sep_mbox_type {
25+
SEP_MBOX_TYPE_AKF,
26+
SEP_MBOX_TYPE_ASC,
27+
};
28+
29+
static struct sep_dev {
30+
enum sep_mbox_type type;
31+
enum sep_capabilities capabilities;
32+
union {
33+
akf_dev_t *akf;
34+
asc_dev_t *asc;
35+
};
36+
} *sep_dev;
2237

2338
int sep_init(void)
2439
{
25-
if (!sep_asc)
26-
sep_asc = asc_init("/arm-io/sep");
27-
if (!sep_asc)
40+
const char *path = "/arm-io/sep";
41+
int sep_path[8];
42+
43+
int node = adt_path_offset_trace(adt, path, sep_path);
44+
if (node < 0) {
45+
printf("sep: Error getting sep node %s\n", path);
46+
return -1;
47+
}
48+
49+
u64 base;
50+
if (adt_get_reg(adt, sep_path, "reg", 0, &base, NULL) < 0) {
51+
printf("sep: Error getting akf %s base address.\n", path);
2852
return -1;
53+
}
54+
55+
sep_dev = calloc(0, sizeof(*sep_dev));
56+
57+
if (adt_is_compatible(adt, node, "iop,s5l8960x") || adt_is_compatible(adt, node, "iop,s8000")) {
58+
sep_dev->type = SEP_MBOX_TYPE_AKF;
59+
} else {
60+
sep_dev->type = SEP_MBOX_TYPE_ASC;
61+
}
62+
63+
switch (sep_dev->type) {
64+
case SEP_MBOX_TYPE_AKF:
65+
sep_dev->akf = akf_init(path);
66+
break;
67+
case SEP_MBOX_TYPE_ASC:
68+
sep_dev->asc = asc_init(path);
69+
break;
70+
}
71+
72+
if (chip_id != 0x8960 && chip_id != 0x7000 && chip_id != 0x7001 && chip_id != 0x8000 &&
73+
chip_id != 0x8001 && chip_id != 0x8003)
74+
sep_dev->capabilities |= SEP_CAPABILITY_GETRAND;
75+
2976
return 0;
3077
}
3178

79+
bool sep_send(u64 msg)
80+
{
81+
switch (sep_dev->type) {
82+
case SEP_MBOX_TYPE_AKF: {
83+
const struct akf_message akf_msg = {.msg0 = FIELD_GET(msg, MASK(32)),
84+
.msg1 = FIELD_GET(msg, GENMASK(63, 32))};
85+
return akf_send(sep_dev->akf, &akf_msg);
86+
}
87+
case SEP_MBOX_TYPE_ASC: {
88+
const struct asc_message asc_msg = {.msg0 = msg};
89+
return asc_send(sep_dev->asc, &asc_msg);
90+
}
91+
}
92+
}
93+
94+
bool sep_recv(u64 *reply)
95+
{
96+
switch (sep_dev->type) {
97+
case SEP_MBOX_TYPE_ASC: {
98+
struct asc_message asc_reply;
99+
int retval = asc_recv_timeout(sep_dev->asc, &asc_reply, SEP_TIMEOUT);
100+
*reply = asc_reply.msg0;
101+
return retval;
102+
}
103+
case SEP_MBOX_TYPE_AKF: {
104+
struct akf_message akf_reply;
105+
int retval = akf_recv_timeout(sep_dev->akf, &akf_reply, SEP_TIMEOUT);
106+
*reply =
107+
FIELD_PREP(MASK(32), akf_reply.msg0) | FIELD_PREP(GENMASK(63, 32), akf_reply.msg1);
108+
return retval;
109+
}
110+
}
111+
}
112+
32113
size_t sep_get_random(void *buffer, size_t len)
33114
{
34-
const struct asc_message msg_getrand = {.msg0 = FIELD_PREP(SEP_MSG_EP, SEP_EP_ROM) |
35-
FIELD_PREP(SEP_MSG_CMD, SEP_MSG_GETRAND)};
115+
if (!(sep_dev->capabilities & SEP_CAPABILITY_GETRAND)) {
116+
printf("sep: SEP does not support GETRAND\n");
117+
return 0;
118+
}
119+
120+
const u64 msg_getrand =
121+
FIELD_PREP(SEP_MSG_EP, SEP_EP_ROM) | FIELD_PREP(SEP_MSG_CMD, SEP_MSG_GETRAND);
36122
int ret;
37123
size_t done = 0;
38124

@@ -41,20 +127,20 @@ size_t sep_get_random(void *buffer, size_t len)
41127
return 0;
42128

43129
while (len) {
44-
struct asc_message reply;
130+
u64 reply;
45131
u32 rng;
46132
size_t copy;
47133

48-
if (!asc_send(sep_asc, &msg_getrand))
134+
if (!sep_send(msg_getrand))
49135
return done;
50-
if (!asc_recv_timeout(sep_asc, &reply, SEP_TIMEOUT))
136+
if (!sep_recv(&reply))
51137
return done;
52-
if (FIELD_GET(SEP_MSG_CMD, reply.msg0) != SEP_REPLY_GETRAND) {
53-
printf("SEP: unexpected getrand reply: %016lx\n", reply.msg0);
138+
if (FIELD_GET(SEP_MSG_CMD, reply) != SEP_REPLY_GETRAND) {
139+
printf("SEP: unexpected getrand reply: %016lx\n", reply);
54140
return done;
55141
}
56142

57-
rng = FIELD_GET(SEP_MSG_DATA, reply.msg0);
143+
rng = FIELD_GET(SEP_MSG_DATA, reply);
58144
copy = sizeof(rng);
59145
if (copy > len)
60146
copy = len;
@@ -66,3 +152,8 @@ size_t sep_get_random(void *buffer, size_t len)
66152

67153
return done;
68154
}
155+
156+
enum sep_capabilities sep_get_capabilities(void)
157+
{
158+
return sep_dev->capabilities;
159+
}

src/sep.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
#include "asc.h"
77
#include "types.h"
88

9+
enum sep_capabilities {
10+
SEP_CAPABILITY_GETRAND = BIT(0),
11+
};
12+
913
int sep_init(void);
1014
size_t sep_get_random(void *buffer, size_t len);
15+
enum sep_capabilities sep_get_capabilities(void);
1116

1217
#endif

0 commit comments

Comments
 (0)