1 /*
2  * Copyright (C) 2020 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 "coverage-common-ipc"
18 
19 #include <lib/coverage/common/ipc.h>
20 #include <lib/tipc/tipc.h>
21 #include <trusty_log.h>
22 #include <uapi/err.h>
23 
coverage_send(handle_t chan,void * msg,size_t msg_len,handle_t * h)24 int coverage_send(handle_t chan, void* msg, size_t msg_len, handle_t* h) {
25     int rc;
26     struct iovec iov = {
27             .iov_base = msg,
28             .iov_len = msg_len,
29     };
30     struct ipc_msg ipc_msg = {
31             .iov = &iov,
32             .num_iov = 1,
33             .handles = h,
34             .num_handles = h ? 1 : 0,
35     };
36 
37     rc = send_msg(chan, &ipc_msg);
38     if (rc != (int)msg_len) {
39         TLOGE("failed (%d) to send_msg()\n", rc);
40         if (rc >= 0) {
41             rc = ERR_BAD_LEN;
42         }
43         return rc;
44     }
45 
46     return NO_ERROR;
47 }
48 
coverage_recv(handle_t chan,void * msg,size_t msg_len,handle_t * h)49 int coverage_recv(handle_t chan, void* msg, size_t msg_len, handle_t* h) {
50     int rc;
51     struct ipc_msg_info msg_inf;
52 
53     rc = get_msg(chan, &msg_inf);
54     if (rc != NO_ERROR) {
55         TLOGE("failed (%d) to get_msg()\n", rc);
56         return rc;
57     }
58 
59     struct iovec iov = {
60             .iov_base = msg,
61             .iov_len = msg_len,
62     };
63     struct ipc_msg ipc_msg = {
64             .iov = &iov,
65             .num_iov = 1,
66             .handles = h,
67             .num_handles = h ? 1 : 0,
68     };
69 
70     rc = read_msg(chan, msg_inf.id, 0, &ipc_msg);
71     if (rc != (int)msg_len) {
72         TLOGE("failed (%d) to read_msg()\n", rc);
73         if (rc >= 0) {
74             rc = ERR_BAD_LEN;
75         }
76         goto out;
77     }
78 
79     rc = NO_ERROR;
80 out:
81     put_msg(chan, msg_inf.id);
82     return rc;
83 }
84 
coverage_rpc(handle_t chan,void * req,size_t req_len,handle_t * req_h,void * resp,size_t resp_len,handle_t * resp_h)85 int coverage_rpc(handle_t chan,
86                  void* req,
87                  size_t req_len,
88                  handle_t* req_h,
89                  void* resp,
90                  size_t resp_len,
91                  handle_t* resp_h) {
92     int rc;
93     uevent_t evt;
94 
95     rc = coverage_send(chan, req, req_len, req_h);
96     if (rc != NO_ERROR) {
97         TLOGE("failed (%d) to send request\n", rc);
98         return rc;
99     }
100 
101     rc = wait(chan, &evt, INFINITE_TIME);
102     if (rc != NO_ERROR) {
103         TLOGE("failed (%d) to wait for reply\n", rc);
104         return rc;
105     }
106 
107     rc = coverage_recv(chan, resp, resp_len, resp_h);
108     if (rc != NO_ERROR) {
109         TLOGE("failed (%d) to receive response\n", rc);
110         return rc;
111     }
112 
113     return NO_ERROR;
114 }
115 
coverage_aggregator_rpc(handle_t chan,struct coverage_aggregator_req * req,handle_t * req_h,struct coverage_aggregator_resp * resp,handle_t * resp_h)116 int coverage_aggregator_rpc(handle_t chan,
117                             struct coverage_aggregator_req* req,
118                             handle_t* req_h,
119                             struct coverage_aggregator_resp* resp,
120                             handle_t* resp_h) {
121     int rc = coverage_rpc(chan, req, sizeof(*req), req_h, resp, sizeof(*resp),
122                           resp_h);
123     if (rc != NO_ERROR) {
124         return rc;
125     }
126 
127     if (resp->hdr.cmd != (req->hdr.cmd | COVERAGE_AGGREGATOR_CMD_RESP_BIT)) {
128         TLOGE("cmd 0x%x: unknown command\n", resp->hdr.cmd);
129         return ERR_CMD_UNKNOWN;
130     }
131 
132     return NO_ERROR;
133 }
134 
coverage_client_rpc(handle_t chan,struct coverage_client_req * req,handle_t * req_h,struct coverage_client_resp * resp,handle_t * resp_h)135 int coverage_client_rpc(handle_t chan,
136                         struct coverage_client_req* req,
137                         handle_t* req_h,
138                         struct coverage_client_resp* resp,
139                         handle_t* resp_h) {
140     int rc = coverage_rpc(chan, req, sizeof(*req), req_h, resp, sizeof(*resp),
141                           resp_h);
142     if (rc != NO_ERROR) {
143         return rc;
144     }
145 
146     if (resp->hdr.cmd != (req->hdr.cmd | COVERAGE_CLIENT_CMD_RESP_BIT)) {
147         TLOGE("cmd 0x%x: unknown command\n", resp->hdr.cmd);
148         return ERR_CMD_UNKNOWN;
149     }
150 
151     return NO_ERROR;
152 }
153