1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define TLOG_TAG "vmm_obj_ipc"
18
19 #include <inttypes.h>
20 #include <lib/tipc/tipc.h>
21 #include <lib/vmm_obj/vmm_obj.h>
22 #include <lk/macros.h>
23 #include <sys/auxv.h>
24 #include <sys/mman.h>
25 #include <trusty_log.h>
26 #include <uapi/err.h>
27 #include <uapi/mm.h>
28
29 #define PAGE_SIZE getauxval(AT_PAGESZ)
30
vmm_obj_map_ro(const char * port,const void ** base_out,size_t * size_out)31 int vmm_obj_map_ro(const char* port, const void** base_out, size_t* size_out) {
32 int rc;
33 handle_t chan;
34 handle_t memref = INVALID_IPC_HANDLE;
35 ipc_msg_info_t msg_inf;
36 uevent_t evt;
37 uint64_t size64;
38 size_t size;
39 void* base;
40
41 if (!base_out) {
42 TLOGE("Unexpected NULL base pointer\n");
43 rc = ERR_INVALID_ARGS;
44 goto err_null_base_out;
45 }
46 if (!size_out) {
47 TLOGE("Unexpected NULL size pointer\n");
48 rc = ERR_INVALID_ARGS;
49 goto err_null_size_out;
50 }
51
52 rc = tipc_connect(&chan, port);
53 if (rc < 0) {
54 goto err_connect;
55 }
56
57 do {
58 rc = wait(chan, &evt, INFINITE_TIME);
59 if (rc != NO_ERROR) {
60 TLOGE("Failed to wait for reply (%d)\n", rc);
61 goto err_wait;
62 }
63 if (evt.event & IPC_HANDLE_POLL_HUP) {
64 TLOGE("Service closed connection\n");
65 rc = ERR_CHANNEL_CLOSED;
66 goto err_wait;
67 }
68 } while (!(evt.event & IPC_HANDLE_POLL_MSG));
69
70 rc = get_msg(chan, &msg_inf);
71 if (rc) {
72 TLOGE("Failed to get message (%d)\n", rc);
73 goto err_get;
74 }
75
76 if (msg_inf.len != sizeof(size64)) {
77 TLOGE("Received message of invalid size (%zd)\n", msg_inf.len);
78 rc = ERR_BAD_LEN;
79 goto err_msg_len;
80 }
81
82 struct iovec iov = {
83 .iov_base = &size64,
84 .iov_len = sizeof(size64),
85 };
86 ipc_msg_t msg = {
87 .iov = &iov,
88 .num_iov = 1,
89 .handles = &memref,
90 .num_handles = 1,
91 };
92 rc = read_msg(chan, msg_inf.id, 0, &msg);
93 if (rc != (int)sizeof(size64)) {
94 TLOGE("Failed to read message (%d)\n", rc);
95 if (rc >= 0) {
96 rc = ERR_BAD_LEN;
97 }
98 goto err_read;
99 }
100
101 if (memref == INVALID_IPC_HANDLE) {
102 TLOGE("Received invalid memref handle\n");
103 rc = ERR_BAD_HANDLE;
104 goto err_invalid_memref;
105 }
106
107 size = (size_t)size64;
108 if (size64 != (uint64_t)size) {
109 TLOGE("Size too big for size_t (%" PRIu64 ")\n", size64);
110 rc = ERR_TOO_BIG;
111 goto err_size_too_big;
112 }
113
114 size_t aligned_size = round_up(size, PAGE_SIZE);
115 base = mmap(0, aligned_size, MMAP_FLAG_PROT_READ, 0, memref, 0);
116 if (base == MAP_FAILED) {
117 TLOGE("Failed to map device tree blob\n");
118 rc = ERR_BAD_HANDLE;
119 goto err_mmap;
120 }
121
122 *base_out = base;
123 *size_out = size;
124 rc = NO_ERROR;
125
126 err_mmap:
127 err_size_too_big:
128 err_invalid_memref:
129 err_read:
130 close(memref);
131 err_msg_len:
132 put_msg(chan, msg_inf.id);
133 err_get:
134 err_wait:
135 close(chan);
136 err_connect:
137 err_null_size_out:
138 err_null_base_out:
139 return rc;
140 }
141