• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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