blob: 08ac6f340b35d41e93ada6e273cb6f4f60ef81d6 [file] [log] [blame]
Andrew Jeffery68023072018-08-06 10:08:11 +09301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
3#include <errno.h>
4#include <stdlib.h>
5
6#include "common.h"
7#include "dbus.h"
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +09308#include "control_dbus.h"
Andrew Jeffery68023072018-08-06 10:08:11 +09309#include "mbox.h"
10
11/*
12 * Command: DBUS Ping
13 * Ping the daemon
14 *
15 * Args: NONE
16 * Resp: NONE
17 */
18static int control_legacy_ping(struct mbox_context *context,
19 struct mbox_dbus_msg *req,
20 struct mbox_dbus_msg *resp)
21{
22 return control_ping(context);
23}
24
25/*
26 * Command: DBUS Status
27 * Get the status of the daemon
28 *
29 * Args: NONE
30 * Resp[0]: Status Code
31 */
32static int control_legacy_daemon_state(struct mbox_context *context,
33 struct mbox_dbus_msg *req,
34 struct mbox_dbus_msg *resp)
35{
36 resp->num_args = DAEMON_STATE_NUM_ARGS;
37 resp->args = calloc(resp->num_args, sizeof(*resp->args));
38 resp->args[0] = control_daemon_state(context);
39
40 return 0;
41}
42
43/*
44 * Command: DBUS LPC State
45 * Get the state of the lpc bus mapping (whether it points to memory or flash
46 *
47 * Args: NONE
48 * Resp[0]: LPC Bus State Code
49 */
50static int control_legacy_lpc_state(struct mbox_context *context,
51 struct mbox_dbus_msg *req,
52 struct mbox_dbus_msg *resp)
53{
54 resp->num_args = LPC_STATE_NUM_ARGS;
55 resp->args = calloc(resp->num_args, sizeof(*resp->args));
56 resp->args[0] = control_lpc_state(context);
57
58 return 0;
59}
60
61/*
62 * Command: DBUS Reset
63 * Reset the daemon state, final operation TBA.
64 * For now we just point the lpc mapping back at the flash.
65 *
66 * Args: NONE
67 * Resp: NONE
68 */
69static int control_legacy_reset(struct mbox_context *context,
70 struct mbox_dbus_msg *req,
71 struct mbox_dbus_msg *resp)
72{
73 int rc;
74
75 rc = control_reset(context);
76
77 /* Map return codes for compatibility */
78 if (rc == -EBUSY) {
79 return -E_DBUS_REJECTED;
80 } else if (rc < 0) {
81 return -E_DBUS_HARDWARE;
82 }
83
84 return rc;
85}
86
87/*
88 * Command: DBUS Kill
89 * Stop the daemon
90 *
91 * Args: NONE
92 * Resp: NONE
93 */
94static int control_legacy_kill(struct mbox_context *context,
95 struct mbox_dbus_msg *req,
96 struct mbox_dbus_msg *resp)
97{
98 return control_kill(context);
99}
100
101/*
102 * Command: DBUS Flash Modified
103 * Used to notify the daemon that the flash has been modified out from under
104 * it - We need to reset all out windows to ensure flash will be reloaded
105 * when a new window is opened.
106 * Note: We don't flush any previously opened windows
107 *
108 * Args: NONE
109 * Resp: NONE
110 */
111static int control_legacy_modified(struct mbox_context *context,
112 struct mbox_dbus_msg *req,
113 struct mbox_dbus_msg *resp)
114{
115 return control_modified(context);
116}
117
118/*
119 * Command: DBUS Suspend
120 * Suspend the daemon to inhibit it from performing flash accesses.
121 * This is used to synchronise access to the flash between the daemon and
122 * directly from the BMC.
123 *
124 * Args: NONE
125 * Resp: NONE
126 */
127static int control_legacy_suspend(struct mbox_context *context,
128 struct mbox_dbus_msg *req,
129 struct mbox_dbus_msg *resp)
130{
131 int rc;
132
133 rc = control_suspend(context);
134 if (rc < 0) {
135 /* Map return codes for compatibility */
136 return -E_DBUS_HARDWARE;
137 }
138
139 return rc;
140}
141
142/*
143 * Command: DBUS Resume
144 * Resume the daemon to let it perform flash accesses again.
145 *
146 * Args[0]: Flash Modified (0 - no | 1 - yes)
147 * Resp: NONE
148 */
149static int control_legacy_resume(struct mbox_context *context,
150 struct mbox_dbus_msg *req,
151 struct mbox_dbus_msg *resp)
152{
153 int rc;
154
155 if (req->num_args != 1) {
156 return -E_DBUS_INVAL;
157 }
158
159 rc = control_resume(context, req->args[0] == RESUME_FLASH_MODIFIED);
160 if (rc < 0) {
161 /* Map return codes for compatibility */
162 rc = -E_DBUS_HARDWARE;
163 }
164
165 return rc;
166}
167
168typedef int (*control_action)(struct mbox_context *context,
169 struct mbox_dbus_msg *req,
170 struct mbox_dbus_msg *resp);
171static const control_action dbus_handlers[NUM_DBUS_CMDS] = {
172 control_legacy_ping,
173 control_legacy_daemon_state,
174 control_legacy_reset,
175 control_legacy_suspend,
176 control_legacy_resume,
177 control_legacy_modified,
178 control_legacy_kill,
179 control_legacy_lpc_state
180};
181
182static int method_cmd(sd_bus_message *m, void *userdata,
183 sd_bus_error *ret_error)
184{
185 struct mbox_dbus_msg req = { 0 }, resp = { 0 };
186 struct mbox_context *context;
187 sd_bus_message *n;
188 int rc, i;
189
190 context = (struct mbox_context *) userdata;
191 if (!context) {
192 MSG_ERR("DBUS Internal Error\n");
193 rc = -E_DBUS_INTERNAL;
194 goto out;
195 }
196
197 /* Read the command */
198 rc = sd_bus_message_read(m, "y", &req.cmd);
199 if (rc < 0) {
200 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
201 rc = -E_DBUS_INTERNAL;
202 goto out;
203 }
204 MSG_DBG("DBUS request: %u\n", req.cmd);
205
206 /* Read the args */
207 rc = sd_bus_message_read_array(m, 'y', (const void **) &req.args,
208 &req.num_args);
209 if (rc < 0) {
210 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
211 rc = -E_DBUS_INTERNAL;
212 goto out;
213 }
214 MSG_DBG("DBUS num_args: %u\n", (unsigned) req.num_args);
215 for (i = 0; i < req.num_args; i++) {
216 MSG_DBG("DBUS arg[%d]: %u\n", i, req.args[i]);
217 }
218
219 /* Handle the command */
220 if (req.cmd >= NUM_DBUS_CMDS) {
221 rc = -E_DBUS_INVAL;
222 MSG_ERR("Received unknown dbus cmd: %d\n", req.cmd);
223 } else {
224 rc = dbus_handlers[req.cmd](context, &req, &resp);
225 }
226
227out:
228 if (rc < 0) {
229 resp.cmd = -rc;
230 }
231 rc = sd_bus_message_new_method_return(m, &n); /* Generate response */
232 if (rc < 0) {
233 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
234 goto cleanup;
235 }
236
237 rc = sd_bus_message_append(n, "y", resp.cmd); /* Set return code */
238 if (rc < 0) {
239 MSG_ERR("sd_bus_message_append failed: %d\n", rc);
240 goto cleanup;
241 }
242
243 rc = sd_bus_message_append_array(n, 'y', resp.args, resp.num_args);
244 if (rc < 0) {
245 MSG_ERR("sd_bus_message_append_array failed: %d\n", rc);
246 goto cleanup;
247 }
248
249 MSG_DBG("DBUS response: %u\n", resp.cmd);
250 MSG_DBG("DBUS num_args: %u\n", (unsigned) resp.num_args);
251 for (i = 0; i < resp.num_args; i++) {
252 MSG_DBG("DBUS arg[%d]: %u\n", i, resp.args[i]);
253 }
254
255 rc = sd_bus_send(NULL, n, NULL); /* Send response */
256 if (rc < 0)
257 MSG_ERR("sd_bus_send failed: %d\n", rc);
258
259cleanup:
260 free(resp.args);
261 return rc;
262}
263
264static const sd_bus_vtable control_legacy_vtable[] = {
265 SD_BUS_VTABLE_START(0),
266 SD_BUS_METHOD("cmd", "yay", "yay", &method_cmd,
267 SD_BUS_VTABLE_UNPRIVILEGED),
268 SD_BUS_VTABLE_END
269};
270
271int control_legacy_init(struct mbox_context *context)
272{
273 int rc;
274
275 rc = sd_bus_add_object_vtable(context->bus, NULL,
276 MBOX_DBUS_LEGACY_OBJECT,
277 MBOX_DBUS_LEGACY_NAME,
278 control_legacy_vtable, context);
279 if (rc < 0) {
280 MSG_ERR("Failed to register vtable: %s\n", strerror(-rc));
281 return rc;
282 }
283
284 return sd_bus_request_name(context->bus, MBOX_DBUS_LEGACY_NAME,
285 SD_BUS_NAME_ALLOW_REPLACEMENT |
286 SD_BUS_NAME_REPLACE_EXISTING);
287}
288
289void control_legacy_free(struct mbox_context *context __attribute__((unused)))
290{
291 return;
292}