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