blob: 3c109987f8875e8bfcd948d1ebfbacc9d70b7295 [file] [log] [blame]
Andrew Jeffery4fe996c2018-02-27 12:16:48 +10301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
Cyril Burc85e34d2016-11-15 11:50:41 +11003
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +11004#define _GNU_SOURCE
Cyril Burc85e34d2016-11-15 11:50:41 +11005#include <assert.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <getopt.h>
9#include <limits.h>
10#include <poll.h>
11#include <stdbool.h>
12#include <stdint.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <syslog.h>
Michael Neuling899ebac2017-01-14 11:20:26 -060017#include <signal.h>
Cyril Burc85e34d2016-11-15 11:50:41 +110018#include <sys/ioctl.h>
19#include <sys/mman.h>
20#include <sys/stat.h>
21#include <sys/timerfd.h>
22#include <sys/types.h>
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110023#include <sys/signalfd.h>
Cyril Burc85e34d2016-11-15 11:50:41 +110024#include <time.h>
25#include <unistd.h>
Andrew Jeffery78210b92017-01-13 13:06:09 +103026#include <inttypes.h>
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110027#include <systemd/sd-bus.h>
Cyril Burc85e34d2016-11-15 11:50:41 +110028
Suraj Jitindar Singh8d65bb42017-05-01 16:05:17 +100029#include "config.h"
Andrew Jeffery26558db2018-08-10 00:22:38 +093030#include "mboxd.h"
Cyril Burc85e34d2016-11-15 11:50:41 +110031#include "common.h"
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110032#include "dbus.h"
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +093033#include "control_dbus.h"
Andrew Jefferyeebc6bd2018-08-08 10:38:19 +093034#include "flash.h"
Andrew Jefferycd186112018-08-08 10:47:55 +093035#include "lpc.h"
Andrew Jeffery457a6e52018-08-08 11:21:08 +093036#include "transport_mbox.h"
Andrew Jefferyf593b1b2018-08-08 11:01:04 +093037#include "windows.h"
Andrew Jeffery53c21aa2018-03-26 11:56:16 +103038#include "vpnor/mboxd_pnor_partition_table.h"
Cyril Burc85e34d2016-11-15 11:50:41 +110039
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110040#define USAGE \
41"\nUsage: %s [-V | --version] [-h | --help] [-v[v] | --verbose] [-s | --syslog]\n" \
Suraj Jitindar Singhc29172e2017-04-12 14:26:47 +100042"\t\t[-n | --window-num <num>]\n" \
43"\t\t[-w | --window-size <size>M]\n" \
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110044"\t\t-f | --flash <size>[K|M]\n\n" \
45"\t-v | --verbose\t\tBe [more] verbose\n" \
46"\t-s | --syslog\t\tLog output to syslog (pointless without -v)\n" \
47"\t-n | --window-num\tThe number of windows\n" \
Suraj Jitindar Singhc29172e2017-04-12 14:26:47 +100048"\t\t\t\t(default: fill the reserved memory region)\n" \
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110049"\t-w | --window-size\tThe window size (power of 2) in MB\n" \
Suraj Jitindar Singhc29172e2017-04-12 14:26:47 +100050"\t\t\t\t(default: 1MB)\n" \
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110051"\t-f | --flash\t\tSize of flash in [K|M] bytes\n\n"
Cyril Burc85e34d2016-11-15 11:50:41 +110052
Andrew Jefferyef9e62d2018-08-08 15:48:27 +093053static int dbus_init(struct mbox_context *context)
54{
55 int rc;
56
57 rc = sd_bus_default_system(&context->bus);
58 if (rc < 0) {
59 MSG_ERR("Failed to connect to the system bus: %s\n",
60 strerror(-rc));
61 return rc;
62 }
63
64 rc = control_legacy_init(context);
65 if (rc < 0) {
66 MSG_ERR("Failed to initialise legacy DBus interface: %s\n",
67 strerror(-rc));
68 return rc;
69 }
70
71 rc = control_dbus_init(context);
72 if (rc < 0) {
73 MSG_ERR("Failed to initialise DBus control interface: %s\n",
74 strerror(-rc));
75 return rc;
76 }
77
78 rc = sd_bus_request_name(context->bus, MBOX_DBUS_NAME,
79 SD_BUS_NAME_ALLOW_REPLACEMENT |
80 SD_BUS_NAME_REPLACE_EXISTING);
81 if (rc < 0) {
82 MSG_ERR("Failed to request name on the bus: %s\n",
83 strerror(-rc));
84 return rc;
85 }
86
87 rc = sd_bus_get_fd(context->bus);
88 if (rc < 0) {
89 MSG_ERR("Failed to get bus fd: %s\n", strerror(-rc));
90 return rc;
91 }
92
93 context->fds[DBUS_FD].fd = rc;
94
95 return 0;
96}
97
98static void dbus_free(struct mbox_context *context)
99{
100 control_dbus_free(context);
101 control_legacy_free(context);
102 sd_bus_unref(context->bus);
103}
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +0930104
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100105static int poll_loop(struct mbox_context *context)
Cyril Burc85e34d2016-11-15 11:50:41 +1100106{
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100107 int rc = 0, i;
Cyril Bur46233672017-01-16 13:33:26 +1100108
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100109 /* Set POLLIN on polling file descriptors */
110 for (i = 0; i < POLL_FDS; i++) {
111 context->fds[i].events = POLLIN;
Cyril Bur46233672017-01-16 13:33:26 +1100112 }
113
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100114 while (1) {
115 rc = poll(context->fds, POLL_FDS, -1);
116
117 if (rc < 0) { /* Error */
118 MSG_ERR("Error from poll(): %s\n", strerror(errno));
119 break; /* This should mean we clean up nicely */
120 }
121
122 /* Event on Polled File Descriptor - Handle It */
123 if (context->fds[SIG_FD].revents & POLLIN) { /* Signal */
124 struct signalfd_siginfo info = { 0 };
125
126 rc = read(context->fds[SIG_FD].fd, (void *) &info,
127 sizeof(info));
128 if (rc != sizeof(info)) {
129 MSG_ERR("Error reading signal event: %s\n",
130 strerror(errno));
131 }
132
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000133 MSG_DBG("Received signal: %d\n", info.ssi_signo);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100134 switch (info.ssi_signo) {
135 case SIGINT:
136 case SIGTERM:
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000137 MSG_INFO("Caught Signal - Exiting...\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100138 context->terminate = true;
139 break;
140 case SIGHUP:
141 /* Host didn't request reset -> Notify it */
Andrew Jeffery5335f092018-08-09 14:56:08 +0930142 windows_reset_all(context, EVENT_TRIGGER);
Andrew Jeffery17971e42018-08-08 16:36:10 +0930143 rc = lpc_reset(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100144 if (rc < 0) {
145 MSG_ERR("WARNING: Failed to point the "
146 "LPC bus back to flash on "
147 "SIGHUP\nIf the host requires "
148 "this expect problems...\n");
149 }
150 break;
151 default:
152 MSG_ERR("Unhandled Signal: %d\n",
153 info.ssi_signo);
154 break;
155 }
156 }
157 if (context->fds[DBUS_FD].revents & POLLIN) { /* DBUS */
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000158 while ((rc = sd_bus_process(context->bus, NULL)) > 0) {
159 MSG_DBG("DBUS Event\n");
160 }
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100161 if (rc < 0) {
162 MSG_ERR("Error handling DBUS event: %s\n",
163 strerror(-rc));
164 }
165 }
166 if (context->terminate) {
167 break; /* This should mean we clean up nicely */
168 }
169 if (context->fds[MBOX_FD].revents & POLLIN) { /* MBOX */
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000170 MSG_DBG("MBOX Event\n");
Andrew Jefferyd86141b2018-08-09 14:58:53 +0930171 rc = transport_mbox_dispatch(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100172 if (rc < 0) {
173 MSG_ERR("Error handling MBOX event\n");
174 }
175 }
176 }
177
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500178 /* Best to reset windows and the lpc mapping for safety */
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100179 /* Host didn't request reset -> Notify it */
Andrew Jeffery5335f092018-08-09 14:56:08 +0930180 windows_reset_all(context, EVENT_TRIGGER);
Andrew Jeffery17971e42018-08-08 16:36:10 +0930181 rc = lpc_reset(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100182 /* Not much we can do if this fails */
183 if (rc < 0) {
184 MSG_ERR("WARNING: Failed to point the LPC bus back to flash\n"
185 "If the host requires this expect problems...\n");
186 }
187
188 return rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100189}
190
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100191static int init_signals(struct mbox_context *context, sigset_t *set)
Cyril Burc85e34d2016-11-15 11:50:41 +1100192{
193 int rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100194
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100195 /* Block SIGHUPs, SIGTERMs and SIGINTs */
196 sigemptyset(set);
197 sigaddset(set, SIGHUP);
198 sigaddset(set, SIGINT);
199 sigaddset(set, SIGTERM);
200 rc = sigprocmask(SIG_BLOCK, set, NULL);
201 if (rc < 0) {
202 MSG_ERR("Failed to set SIG_BLOCK mask %s\n", strerror(errno));
203 return rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100204 }
205
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100206 /* Get Signal File Descriptor */
207 rc = signalfd(-1, set, SFD_NONBLOCK);
208 if (rc < 0) {
209 MSG_ERR("Failed to get signalfd %s\n", strerror(errno));
210 return rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100211 }
212
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100213 context->fds[SIG_FD].fd = rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100214 return 0;
215}
216
Cyril Burc85e34d2016-11-15 11:50:41 +1100217static void usage(const char *name)
218{
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100219 printf(USAGE, name);
Cyril Burc85e34d2016-11-15 11:50:41 +1100220}
221
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100222static bool parse_cmdline(int argc, char **argv,
223 struct mbox_context *context)
Cyril Burc85e34d2016-11-15 11:50:41 +1100224{
Cyril Bure8f2de12017-01-17 16:56:02 +1100225 char *endptr;
Suraj Jitindar Singhc29172e2017-04-12 14:26:47 +1000226 int opt;
Cyril Burc85e34d2016-11-15 11:50:41 +1100227
228 static const struct option long_options[] = {
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100229 { "flash", required_argument, 0, 'f' },
230 { "window-size", optional_argument, 0, 'w' },
231 { "window-num", optional_argument, 0, 'n' },
232 { "verbose", no_argument, 0, 'v' },
233 { "syslog", no_argument, 0, 's' },
234 { "version", no_argument, 0, 'V' },
235 { "help", no_argument, 0, 'h' },
236 { 0, 0, 0, 0 }
Cyril Burc85e34d2016-11-15 11:50:41 +1100237 };
238
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100239 verbosity = MBOX_LOG_NONE;
Cyril Burc85e34d2016-11-15 11:50:41 +1100240 mbox_vlog = &mbox_log_console;
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100241
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100242 context->current = NULL; /* No current window */
243
244 while ((opt = getopt_long(argc, argv, "f:w::n::vsVh", long_options, NULL))
245 != -1) {
Cyril Burc85e34d2016-11-15 11:50:41 +1100246 switch (opt) {
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100247 case 0:
248 break;
249 case 'f':
250 context->flash_size = strtol(optarg, &endptr, 10);
251 if (optarg == endptr) {
252 fprintf(stderr, "Unparseable flash size\n");
253 return false;
254 }
255 switch (*endptr) {
256 case '\0':
Cyril Burc85e34d2016-11-15 11:50:41 +1100257 break;
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100258 case 'M':
259 context->flash_size <<= 10;
260 case 'K':
261 context->flash_size <<= 10;
Cyril Burc85e34d2016-11-15 11:50:41 +1100262 break;
263 default:
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100264 fprintf(stderr, "Unknown units '%c'\n",
265 *endptr);
266 return false;
267 }
268 break;
269 case 'n':
270 context->windows.num = strtol(argv[optind], &endptr,
271 10);
272 if (optarg == endptr || *endptr != '\0') {
273 fprintf(stderr, "Unparseable window num\n");
274 return false;
275 }
276 break;
277 case 'w':
278 context->windows.default_size = strtol(argv[optind],
279 &endptr, 10);
280 context->windows.default_size <<= 20; /* Given in MB */
281 if (optarg == endptr || (*endptr != '\0' &&
282 *endptr != 'M')) {
283 fprintf(stderr, "Unparseable window size\n");
284 return false;
285 }
Suraj Jitindar Singh0aff80c2017-04-12 14:37:24 +1000286 if (!is_power_of_2(context->windows.default_size)) {
287 fprintf(stderr, "Window size not power of 2\n");
288 return false;
289 }
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100290 break;
291 case 'v':
292 verbosity++;
293 break;
294 case 's':
295 /* Avoid a double openlog() */
296 if (mbox_vlog != &vsyslog) {
297 openlog(PREFIX, LOG_ODELAY, LOG_DAEMON);
298 mbox_vlog = &vsyslog;
299 }
300 break;
301 case 'V':
Suraj Jitindar Singh8d65bb42017-05-01 16:05:17 +1000302 printf("%s V%s\n", THIS_NAME, PACKAGE_VERSION);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100303 exit(0);
304 case 'h':
305 return false; /* This will print the usage message */
306 default:
307 return false;
Cyril Burc85e34d2016-11-15 11:50:41 +1100308 }
309 }
310
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100311 if (!context->flash_size) {
Cyril Bure8f2de12017-01-17 16:56:02 +1100312 fprintf(stderr, "Must specify a non-zero flash size\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100313 return false;
Cyril Bure8f2de12017-01-17 16:56:02 +1100314 }
315
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000316 MSG_INFO("Flash size: 0x%.8x\n", context->flash_size);
Cyril Burc85e34d2016-11-15 11:50:41 +1100317
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100318 if (verbosity) {
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000319 MSG_INFO("%s logging\n", verbosity == MBOX_LOG_DEBUG ? "Debug" :
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100320 "Verbose");
Cyril Burc85e34d2016-11-15 11:50:41 +1100321 }
322
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100323 return true;
Cyril Burc85e34d2016-11-15 11:50:41 +1100324}
325
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100326int main(int argc, char **argv)
327{
328 struct mbox_context *context;
329 char *name = argv[0];
330 sigset_t set;
331 int rc, i;
332
333 context = calloc(1, sizeof(*context));
334 if (!context) {
335 fprintf(stderr, "Memory allocation failed\n");
336 exit(1);
337 }
338
339 if (!parse_cmdline(argc, argv, context)) {
340 usage(name);
341 free(context);
342 exit(0);
343 }
344
345 for (i = 0; i < TOTAL_FDS; i++) {
346 context->fds[i].fd = -1;
347 }
348
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000349 MSG_INFO("Starting Daemon\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100350
351 rc = init_signals(context, &set);
352 if (rc) {
353 goto finish;
354 }
355
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930356 rc = protocol_init(context);
357 if (rc) {
358 goto finish;
359 }
360
Andrew Jefferyb2466ee2018-08-09 15:03:27 +0930361 rc = transport_mbox_init(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100362 if (rc) {
363 goto finish;
364 }
365
Andrew Jefferycb9b2102018-08-08 16:31:07 +0930366 rc = lpc_dev_init(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100367 if (rc) {
368 goto finish;
369 }
370
371 /* We've found the reserved memory region -> we can assign to windows */
Andrew Jefferyc1a67fa2018-08-08 17:07:38 +0930372 rc = windows_init(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100373 if (rc) {
374 goto finish;
375 }
376
Andrew Jefferyd6b09bc2018-08-08 16:47:54 +0930377 rc = flash_dev_init(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100378 if (rc) {
379 goto finish;
380 }
381
Andrew Jefferyef9e62d2018-08-08 15:48:27 +0930382 rc = dbus_init(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100383 if (rc) {
384 goto finish;
385 }
386
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500387#ifdef VIRTUAL_PNOR_ENABLED
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500388 init_vpnor(context);
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500389#endif
390
391 /* Set the LPC bus mapping */
Andrew Jeffery17971e42018-08-08 16:36:10 +0930392 rc = lpc_reset(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100393 if (rc) {
Andrew Jeffery8fe809e2018-05-17 09:54:32 +0930394 MSG_ERR("LPC configuration failed, RESET required: %d\n", rc);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100395 }
396
Andrew Jeffery5335f092018-08-09 14:56:08 +0930397 rc = protocol_events_set(context, BMC_EVENT_DAEMON_READY, EVENT_TRIGGER);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100398 if (rc) {
399 goto finish;
400 }
401
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000402 MSG_INFO("Entering Polling Loop\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100403 rc = poll_loop(context);
404
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000405 MSG_INFO("Exiting Poll Loop: %d\n", rc);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100406
407finish:
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000408 MSG_INFO("Daemon Exiting...\n");
Andrew Jeffery5335f092018-08-09 14:56:08 +0930409 protocol_events_clear(context, BMC_EVENT_DAEMON_READY, EVENT_TRIGGER);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100410
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930411#ifdef VIRTUAL_PNOR_ENABLED
412 destroy_vpnor(context);
413#endif
Andrew Jefferyef9e62d2018-08-08 15:48:27 +0930414 dbus_free(context);
Andrew Jefferydec6ca62018-08-08 16:49:43 +0930415 flash_dev_free(context);
Andrew Jeffery2e2df282018-08-08 16:32:22 +0930416 lpc_dev_free(context);
Andrew Jeffery55260ce2018-08-09 15:05:59 +0930417 transport_mbox_free(context);
Andrew Jefferyf5f51422018-08-08 17:08:33 +0930418 windows_free(context);
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930419 protocol_free(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100420 free(context);
421
422 return rc;
423}