1 /*
2 * Copyright (C) 2018 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 #include <app_mgmt_port_consts.h>
18 #include <app_mgmt_test.h>
19 #include <assert.h>
20 #include <lib/tipc/tipc.h>
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <trusty/time.h>
27 #include <trusty_ipc.h>
28 #include <uapi/err.h>
29
30 #define TLOG_TAG "port-start-srv"
31
32 /* Handles a cmd from the client and returns true if the server should exit */
handle_cmd(uint8_t cmd,handle_t channel,handle_t * start_port)33 static bool handle_cmd(uint8_t cmd, handle_t channel, handle_t* start_port) {
34 int rc;
35 bool done = false;
36 uint8_t rsp = RSP_OK;
37
38 switch (cmd) {
39 case CMD_NOP:
40 break;
41 case CMD_CLOSE_PORT:
42 rc = close(*start_port);
43 if (rc != NO_ERROR) {
44 TLOGI("port close failed: %d\n", rc);
45 rsp = RSP_CMD_FAILED;
46 done = true;
47 }
48 break;
49 case CMD_OPEN_PORT:
50 rc = port_create(START_PORT, 1, MAX_CMD_LEN, IPC_PORT_ALLOW_TA_CONNECT);
51 if (rc < 0) {
52 TLOGI("failed (%d) to create port: %s\n", rc, START_PORT);
53 rsp = RSP_CMD_FAILED;
54 done = true;
55 } else {
56 *start_port = (handle_t)rc;
57 }
58 break;
59 case CMD_EXIT:
60 done = true;
61 break;
62 default:
63 TLOGI("Invalid cmd: %d\n", cmd);
64 rsp = RSP_INVALID_CMD;
65 done = true;
66 }
67
68 rc = tipc_send1(channel, &rsp, sizeof(rsp));
69 if (rc < 0) {
70 TLOGI("Failed to send response: %d \n", rc);
71 done = true;
72 }
73
74 return done;
75 }
76
77 /* Creates port_name and adds it to hset */
prepare_port(const char * port_name,handle_t hset)78 static int prepare_port(const char* port_name, handle_t hset) {
79 int rc;
80 uevent_t uevt;
81 handle_t port;
82
83 assert(port_name);
84 assert(hset);
85
86 rc = port_create(port_name, 1, MAX_CMD_LEN, IPC_PORT_ALLOW_TA_CONNECT);
87 if (rc < 0) {
88 TLOGI("failed (%d) to create port: %s\n", rc, port_name);
89 return rc;
90 }
91
92 port = (handle_t)rc;
93
94 uevt.handle = port;
95 uevt.event = ~0U;
96 uevt.cookie = NULL;
97
98 rc = handle_set_ctrl(hset, HSET_ADD, &uevt);
99 if (rc < 0) {
100 TLOGI("failed (%d) to add port %s to handle set \n", rc, port_name);
101 close(port);
102 return rc;
103 }
104
105 return port;
106 }
107
main(void)108 int main(void) {
109 int rc;
110 uint8_t cmd;
111 bool done = false;
112 handle_t ctrl_port;
113 handle_t start_port;
114 handle_t shutdown_port;
115 handle_t channel;
116 handle_t port_hset;
117 handle_t mixed_hset;
118 uevent_t uevt;
119 uuid_t peer_uuid;
120
121 rc = handle_set_create();
122 if (rc < 0) {
123 TLOGI("failed (%d) to create port handle set \n", rc);
124 return rc;
125 }
126 port_hset = (handle_t)rc;
127
128 rc = prepare_port(START_PORT, port_hset);
129 if (rc < 0) {
130 TLOGI("failed(%d) to prepare START_PORT\n", rc);
131 goto err_prep_start;
132 }
133 start_port = (handle_t)rc;
134
135 rc = prepare_port(CTRL_PORT, port_hset);
136 if (rc < 0) {
137 TLOGI("failed(%d) to prepare CTRL_PORT\n", rc);
138 goto err_prep_ctrl;
139 }
140 ctrl_port = (handle_t)rc;
141
142 rc = handle_set_create();
143 if (rc < 0) {
144 TLOGI("failed (%d) to create mixed handle set \n", rc);
145 goto err_hset_create;
146 }
147 mixed_hset = (handle_t)rc;
148
149 rc = prepare_port(SHUTDOWN_PORT, mixed_hset);
150 if (rc < 0) {
151 TLOGI("failed(%d) to prepare CTRL_PORT\n", rc);
152 goto err_prep_shutdown;
153 }
154 shutdown_port = (handle_t)rc;
155
156 rc = wait(port_hset, &uevt, INFINITE_TIME);
157 if (rc != NO_ERROR || !(uevt.event & IPC_HANDLE_POLL_READY)) {
158 TLOGI("Port wait failed: %d(%d)\n", rc, uevt.event);
159 goto err_port_wait;
160 }
161
162 rc = accept(uevt.handle, &peer_uuid);
163 if (rc < 0) {
164 TLOGI("Accept failed %d\n", rc);
165 goto err_accept;
166 }
167 channel = (handle_t)rc;
168
169 uevt.handle = channel;
170 uevt.event = ~0U;
171 uevt.cookie = NULL;
172
173 rc = handle_set_ctrl(mixed_hset, HSET_ADD, &uevt);
174 if (rc < 0) {
175 TLOGI("failed (%d) to add channel to mixed handle set \n", rc);
176 goto err_hset_ctrl;
177 }
178
179 while (!done) {
180 rc = wait(mixed_hset, &uevt, INFINITE_TIME);
181 if (rc < 0) {
182 TLOGI("Channel wait failed: %d\n", uevt.event);
183 goto err_channel_wait;
184 }
185
186 if (uevt.handle == shutdown_port)
187 break;
188
189 if (!(uevt.event & IPC_HANDLE_POLL_MSG)) {
190 TLOGI("Received unexpected event %d\n", uevt.event);
191 goto err_evt;
192 }
193
194 rc = tipc_recv1(channel, sizeof(cmd), &cmd, sizeof(cmd));
195 if (rc < 0) {
196 TLOGI("recv_cmd failed: %d\n", rc);
197 goto err_recv;
198 }
199 rc = 0;
200
201 done = handle_cmd(cmd, channel, &start_port);
202 }
203
204 err_recv:
205 err_evt:
206 err_channel_wait:
207 err_hset_ctrl:
208 close(channel);
209 err_accept:
210 err_port_wait:
211 close(shutdown_port);
212 err_prep_shutdown:
213 close(mixed_hset);
214 err_hset_create:
215 close(ctrl_port);
216 err_prep_ctrl:
217 close(start_port);
218 err_prep_start:
219 close(port_hset);
220
221 return rc;
222 }
223