1 /*
2 * Copyright (c) 2022 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/i3c.h>
8 #include <string.h>
9 #include <zephyr/syscall_handler.h>
10
z_vrfy_i3c_do_ccc(const struct device * dev,struct i3c_ccc_payload * payload)11 static inline int z_vrfy_i3c_do_ccc(const struct device *dev,
12 struct i3c_ccc_payload *payload)
13 {
14 Z_OOPS(Z_SYSCALL_DRIVER_I3C(dev, do_ccc));
15 Z_OOPS(Z_SYSCALL_MEMORY_READ(payload, sizeof(*payload)));
16 Z_OOPS(Z_SYSCALL_MEMORY_WRITE(payload, sizeof(*payload)));
17
18 if (payload->ccc.data != NULL) {
19 Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(payload->ccc.data,
20 payload->ccc.data_len,
21 sizeof(*payload->ccc.data)));
22 Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(payload->ccc.data,
23 payload->ccc.data_len,
24 sizeof(*payload->ccc.data)));
25 }
26
27 if (payload->targets.payloads != NULL) {
28 Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(payload->targets.payloads,
29 payload->targets.num_targets,
30 sizeof(*payload->targets.payloads)));
31 Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(payload->targets.payloads,
32 payload->targets.num_targets,
33 sizeof(*payload->targets.payloads)));
34 }
35
36 return z_impl_i3c_do_ccc(dev, payload);
37 }
38 #include <syscalls/i3c_do_ccc_mrsh.c>
39
copy_i3c_msgs_and_transfer(struct i3c_device_desc * target,const struct i3c_msg * msgs,uint8_t num_msgs)40 static uint32_t copy_i3c_msgs_and_transfer(struct i3c_device_desc *target,
41 const struct i3c_msg *msgs,
42 uint8_t num_msgs)
43 {
44 struct i3c_msg copy[num_msgs];
45 uint8_t i;
46
47 /* Use a local copy to avoid switcheroo attacks. */
48 memcpy(copy, msgs, num_msgs * sizeof(*msgs));
49
50 /* Validate the buffers in each message struct. Read options require
51 * that the target buffer be writable
52 */
53 for (i = 0U; i < num_msgs; i++) {
54 Z_OOPS(Z_SYSCALL_MEMORY(copy[i].buf, copy[i].len,
55 copy[i].flags & I3C_MSG_READ));
56 }
57
58 return z_impl_i3c_transfer(target, copy, num_msgs);
59 }
60
z_vrfy_i3c_transfer(struct i3c_device_desc * target,struct i3c_msg * msgs,uint8_t num_msgs)61 static inline int z_vrfy_i3c_transfer(struct i3c_device_desc *target,
62 struct i3c_msg *msgs, uint8_t num_msgs)
63 {
64 Z_OOPS(Z_SYSCALL_MEMORY_READ(target, sizeof(*target)));
65 Z_OOPS(Z_SYSCALL_OBJ(target->bus, K_OBJ_DRIVER_I3C));
66
67 /* copy_msgs_and_transfer() will allocate a copy on the stack using
68 * VLA, so ensure this won't blow the stack. Most functions defined
69 * in i2c.h use only a handful of messages, so up to 32 messages
70 * should be more than sufficient.
71 */
72 Z_OOPS(Z_SYSCALL_VERIFY(num_msgs >= 1 && num_msgs < 32));
73
74 /* We need to be able to read the overall array of messages */
75 Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_READ(msgs, num_msgs,
76 sizeof(struct i3c_msg)));
77
78 return copy_i3c_msgs_and_transfer((struct i3c_device_desc *)target,
79 (struct i3c_msg *)msgs,
80 (uint8_t)num_msgs);
81 }
82 #include <syscalls/i3c_transfer_mrsh.c>
83