1 /*
2 * Copyright (c) 2022, Google Inc. All rights reserved
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <err.h>
25 #include <kernel/vm.h>
26 #include <lib/ktipc/ktipc.h>
27 #include <lib/trusty/ipc.h>
28 #include <lib/trusty/memref.h>
29 #include <lk/compiler.h>
30 #include <lk/trace.h>
31 #include <uapi/mm.h>
32
33 struct vmm_obj_service {
34 struct ktipc_port port;
35 struct handle* memref;
36 size_t size;
37 };
38
vmm_obj_service_create_ro(const char * port,struct ktipc_port_acl * acl,struct vmm_obj * obj,size_t offset,size_t size,struct vmm_obj_service ** srv_out)39 int vmm_obj_service_create_ro(const char* port,
40 struct ktipc_port_acl* acl,
41 struct vmm_obj* obj,
42 size_t offset,
43 size_t size,
44 struct vmm_obj_service** srv_out) {
45 int rc;
46 struct vmm_obj_service* srv;
47
48 if (!srv_out) {
49 TRACEF("vmm_obj_service_create got NULL pointer");
50 rc = ERR_INVALID_ARGS;
51 goto err_null_srv_out;
52 }
53 if (!IS_PAGE_ALIGNED(offset)) {
54 TRACEF("unaligned offset: %zx\n", offset);
55 rc = ERR_INVALID_ARGS;
56 goto err_unaligned_offset;
57 }
58 if (!IS_PAGE_ALIGNED(size)) {
59 TRACEF("unaligned size: %zd\n", size);
60 rc = ERR_INVALID_ARGS;
61 goto err_unaligned_size;
62 }
63 if (size != (uint64_t)size) {
64 TRACEF("size too big: %zd\n", size);
65 rc = ERR_TOO_BIG;
66 goto err_size_too_big;
67 }
68
69 srv = calloc(1, sizeof(*srv));
70 if (!srv) {
71 TRACEF("failed to allocate vmm_obj_service\n");
72 rc = ERR_NO_MEMORY;
73 goto err_alloc_srv;
74 }
75
76 rc = memref_create_from_vmm_obj(obj, offset, size, MMAP_FLAG_PROT_READ,
77 &srv->memref);
78 if (rc != NO_ERROR) {
79 TRACEF("error (%d) creating memref\n", rc);
80 goto err_memref_create;
81 }
82
83 srv->port.name = port;
84 srv->port.uuid = &kernel_uuid;
85 srv->port.msg_max_size = sizeof(uint64_t);
86 srv->port.msg_queue_len = 1;
87 srv->port.acl = acl;
88 srv->size = size;
89
90 *srv_out = srv;
91 return NO_ERROR;
92
93 err_memref_create:
94 free(srv);
95 err_alloc_srv:
96 err_size_too_big:
97 err_unaligned_size:
98 err_unaligned_offset:
99 err_null_srv_out:
100 return rc;
101 }
102
vmm_obj_service_destroy(struct vmm_obj_service ** srv)103 void vmm_obj_service_destroy(struct vmm_obj_service** srv) {
104 DEBUG_ASSERT(srv);
105 if (!*srv) {
106 TRACEF("tried to destroy an uninitialized object");
107 return;
108 }
109
110 handle_decref((*srv)->memref);
111 free(*srv);
112 *srv = NULL;
113 }
114
vmm_obj_service_handle_msg(const struct ktipc_port * port,struct handle * channel,void * ctx)115 static int vmm_obj_service_handle_msg(const struct ktipc_port* port,
116 struct handle* channel,
117 void* ctx) {
118 TRACEF("unexpected message");
119 return ERR_NOT_SUPPORTED;
120 }
121
vmm_obj_service_handle_connect(const struct ktipc_port * port,struct handle * chan,const struct uuid * peer,void ** ctx_p)122 static int vmm_obj_service_handle_connect(const struct ktipc_port* port,
123 struct handle* chan,
124 const struct uuid* peer,
125 void** ctx_p) {
126 struct vmm_obj_service* srv =
127 containerof(port, struct vmm_obj_service, port);
128 int rc;
129
130 struct handle* handles[] = {srv->memref};
131 uint64_t out_size = (uint64_t)srv->size;
132 rc = ktipc_send_handles(chan, handles, countof(handles), &out_size,
133 sizeof(out_size));
134 if ((size_t)rc != sizeof(out_size)) {
135 TRACEF("failed (%d) to send response\n", rc);
136 if (rc >= 0) {
137 return ERR_BAD_LEN;
138 }
139 return rc;
140 }
141
142 return NO_ERROR;
143 }
144
vmm_obj_service_handle_channel_cleanup(void * ctx)145 static void vmm_obj_service_handle_channel_cleanup(void* ctx) {}
146
147 const static struct ktipc_srv_ops vmm_obj_service_ops = {
148 .on_message = vmm_obj_service_handle_msg,
149 .on_connect = vmm_obj_service_handle_connect,
150 .on_channel_cleanup = vmm_obj_service_handle_channel_cleanup,
151 };
152
vmm_obj_service_add(struct vmm_obj_service * srv,struct ktipc_server * server)153 int vmm_obj_service_add(struct vmm_obj_service* srv,
154 struct ktipc_server* server) {
155 return ktipc_server_add_port(server, &srv->port, &vmm_obj_service_ops);
156 }
157