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-aggregator-srv"
18
19 #include "coverage.h"
20
21 #include <interface/coverage/aggregator.h>
22 #include <lib/coverage/common/ipc.h>
23 #include <lib/coverage/common/cov_shm.h>
24 #include <lib/tipc/tipc_srv.h>
25 #include <stdlib.h>
26 #include <trusty_log.h>
27 #include <uapi/err.h>
28
29 static size_t ta_idx = 0;
30
handle_register(handle_t chan,struct coverage_aggregator_req * req,struct coverage_record * record,struct cov_shm * mailbox)31 static int handle_register(handle_t chan,
32 struct coverage_aggregator_req* req,
33 struct coverage_record* record,
34 struct cov_shm* mailbox) {
35 int rc;
36 struct coverage_aggregator_resp resp;
37
38 resp.hdr.cmd = req->hdr.cmd | COVERAGE_AGGREGATOR_CMD_RESP_BIT;
39 resp.register_args.idx = record->idx;
40 resp.register_args.mailbox_len = mailbox->len;
41
42 rc = coverage_send(chan, &resp, sizeof(resp), &mailbox->memref);
43 if (rc != NO_ERROR) {
44 TLOGE("failed (%d) to send mailbox memref\n", rc);
45 return rc;
46 }
47
48 record->record_len = req->register_args.record_len;
49 return NO_ERROR;
50 }
51
handle_get_record(handle_t chan,struct coverage_aggregator_req * req,struct coverage_record * record)52 static int handle_get_record(handle_t chan,
53 struct coverage_aggregator_req* req,
54 struct coverage_record* record) {
55 int rc;
56 struct coverage_aggregator_resp resp;
57
58 if (record->data.memref == INVALID_IPC_HANDLE) {
59 return ERR_NOT_READY;
60 }
61
62 resp.hdr.cmd = req->hdr.cmd | COVERAGE_AGGREGATOR_CMD_RESP_BIT;
63 resp.get_record_args.shm_len = record->data.len;
64
65 rc = coverage_send(chan, &resp, sizeof(resp), &record->data.memref);
66 if (rc != NO_ERROR) {
67 TLOGE("failed (%d) to send coverage record memref\n", rc);
68 return rc;
69 }
70
71 return NO_ERROR;
72 }
73
on_connect(const struct tipc_port * port,handle_t chan,const struct uuid * peer,void ** ctx_p)74 static int on_connect(const struct tipc_port* port,
75 handle_t chan,
76 const struct uuid* peer,
77 void** ctx_p) {
78 struct coverage_record* record;
79 char uuid_str[UUID_STR_SIZE];
80 struct srv_state* state = get_srv_state(port);
81
82 uuid_to_str(peer, uuid_str);
83 TLOGI("App with UUID: %s connected to coverage aggregator\n", uuid_str);
84
85 record = find_coverage_record(&state->coverage_record_list, peer);
86 if (record) {
87 *ctx_p = record;
88 return NO_ERROR;
89 }
90
91 record = calloc(1, sizeof(*record));
92 if (!record) {
93 TLOGE("failed to allocate coverage record\n");
94 return ERR_NO_MEMORY;
95 }
96
97 record->uuid = *peer;
98 record->idx = ta_idx++;
99 list_add_tail(&state->coverage_record_list, &record->node);
100
101 *ctx_p = record;
102 return NO_ERROR;
103 }
104
on_message(const struct tipc_port * port,handle_t chan,void * ctx)105 static int on_message(const struct tipc_port* port, handle_t chan, void* ctx) {
106 int rc;
107 struct coverage_aggregator_req req;
108 struct coverage_record* record = (struct coverage_record*)ctx;
109 struct srv_state* state = get_srv_state(port);
110
111 rc = coverage_recv(chan, &req, sizeof(req), NULL);
112 if (rc != NO_ERROR) {
113 TLOGE("failed (%d) to receive coverage aggregator request\n", rc);
114 return rc;
115 }
116
117 switch (req.hdr.cmd) {
118 case COVERAGE_AGGREGATOR_CMD_REGISTER:
119 return handle_register(chan, &req, record, &state->mailbox);
120
121 case COVERAGE_AGGREGATOR_CMD_GET_RECORD:
122 return handle_get_record(chan, &req, record);
123
124 default:
125 TLOGE("cmd 0x%x: unknown command\n", req.hdr.cmd);
126 return ERR_CMD_UNKNOWN;
127 }
128 }
129
130 /* lib/tipc mandates we have this function. However, there is no work to do. */
on_channel_cleanup(void * ctx)131 static void on_channel_cleanup(void* ctx) {}
132
coverage_aggregator_init(struct srv_state * state)133 int coverage_aggregator_init(struct srv_state* state) {
134 static struct tipc_port_acl port_acl = {
135 .flags = IPC_PORT_ALLOW_TA_CONNECT,
136 };
137 static struct tipc_port port = {
138 .name = COVERAGE_AGGREGATOR_PORT,
139 .msg_max_size = MAX(sizeof(struct coverage_aggregator_req),
140 sizeof(struct coverage_aggregator_resp)),
141 .msg_queue_len = 1,
142 .acl = &port_acl,
143 };
144 static struct tipc_srv_ops ops = {
145 .on_connect = on_connect,
146 .on_message = on_message,
147 .on_channel_cleanup = on_channel_cleanup,
148 };
149
150 set_srv_state(&port, state);
151
152 return tipc_add_service(state->hset, &port, 1, MAX_NUM_APPS, &ops);
153 }
154