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 #include <lib/system_state/system_state.h>
18
19 #include <lib/tipc/tipc.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <trusty_ipc.h>
25 #include <trusty_log.h>
26 #include <uapi/err.h>
27
28 #define TLOG_TAG "lib_system_state"
29
30 /**
31 * long system_state_send_req() - sends request to system_state server
32 * @req: the request header to send to the system_state server
33 * @req_buf: the request payload to send to the system_state server
34 * @req_buf_len: the length of the request payload @req_buf
35 * @resp: buffer in which to store the response header
36 * @resp_buf: buffer in which to store the response payload
37 * @resp_buf_len: the size of the response buffer. Inout param, set
38 * to the actual response payload length.
39 *
40 * Returns: NO_ERROR on success, negative error code on failure
41 */
system_state_send_req(struct system_state_req * req,void * req_buf,size_t req_buf_len,struct system_state_resp * resp,void * resp_buf,size_t * resp_buf_len)42 static long system_state_send_req(struct system_state_req* req,
43 void* req_buf,
44 size_t req_buf_len,
45 struct system_state_resp* resp,
46 void* resp_buf,
47 size_t* resp_buf_len) {
48 int ret;
49
50 handle_t session = connect(SYSTEM_STATE_PORT, IPC_CONNECT_WAIT_FOR_PORT);
51 if (session == INVALID_IPC_HANDLE) {
52 TLOGE("%s: failed to connect\n", __func__);
53 return ERR_IO;
54 }
55
56 ret = tipc_send2(session, req, sizeof(*req), req_buf, req_buf_len);
57 if (ret < 0) {
58 goto err_io;
59 }
60
61 if (((size_t)ret) != sizeof(*req) + req_buf_len) {
62 ret = ERR_IO;
63 goto err_io;
64 }
65
66 uevent_t uevt;
67 ret = wait(session, &uevt, INFINITE_TIME);
68 if (ret != NO_ERROR) {
69 goto err_io;
70 }
71
72 ret = tipc_recv2(session, sizeof(*resp), resp, sizeof(*resp), resp_buf,
73 *resp_buf_len);
74 if (ret < 0) {
75 goto err_io;
76 }
77
78 size_t read_len = (size_t)ret;
79 if (read_len < sizeof(*resp)) {
80 TLOGE("%s: short read (%zu)\n", __func__, read_len);
81 ret = ERR_IO;
82 goto err_io;
83 }
84
85 if (resp->cmd != (req->cmd | SYSTEM_STATE_CMD_RESP_BIT)) {
86 TLOGE("%s: invalid response id (0x%x) for cmd (0x%x)\n", __func__,
87 resp->cmd, req->cmd);
88 ret = ERR_NOT_VALID;
89 goto err_io;
90 }
91
92 close(session);
93
94 *resp_buf_len = read_len - sizeof(*resp);
95 return resp->result;
96
97 err_io:
98 close(session);
99 TLOGE("%s: failed read_msg (%d)\n", __func__, ret);
100 return ret;
101 }
102
system_state_get_flag(enum system_state_flag flag,uint64_t * valuep)103 int system_state_get_flag(enum system_state_flag flag, uint64_t* valuep) {
104 int ret;
105 struct system_state_req req = {
106 .cmd = SYSTEM_STATE_CMD_GET_FLAG,
107 };
108 struct system_state_get_flag_req get_flag_req = {
109 .flag = flag,
110 };
111 struct system_state_resp resp;
112 struct system_state_get_flag_resp get_flag_resp;
113 size_t get_flag_resp_size = sizeof(get_flag_resp);
114
115 ret = system_state_send_req(&req, &get_flag_req, sizeof(get_flag_req),
116 &resp, &get_flag_resp, &get_flag_resp_size);
117 if (ret) {
118 TLOGE("%s: request failed (%d)\n", __func__, ret);
119 return ret;
120 }
121
122 if (get_flag_resp_size != sizeof(get_flag_resp)) {
123 TLOGE("%s: bad response size (%zd)\n", __func__, get_flag_resp_size);
124 return ERR_IO;
125 }
126
127 if (get_flag_resp.flag != flag) {
128 TLOGE("%s: bad response flag (%d)\n", __func__, get_flag_resp.flag);
129 return ERR_IO;
130 }
131
132 *valuep = get_flag_resp.value;
133
134 return 0;
135 }
136