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