blob: efed0524295ee8334c7201c4e543ffc094f43a10 [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"
Cyril Burc85e34d2016-11-15 11:50:41 +110030#include "mbox.h"
31#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"
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110034#include "mboxd_flash.h"
35#include "mboxd_lpc.h"
36#include "mboxd_msg.h"
37#include "mboxd_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 Jeffery55f4d6f2018-08-06 12:26:44 +093053int mboxd_dbus_init(struct mbox_context *context);
54void mboxd_dbus_free(struct mbox_context *context);
55
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110056static int poll_loop(struct mbox_context *context)
Cyril Burc85e34d2016-11-15 11:50:41 +110057{
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110058 int rc = 0, i;
Cyril Bur46233672017-01-16 13:33:26 +110059
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110060 /* Set POLLIN on polling file descriptors */
61 for (i = 0; i < POLL_FDS; i++) {
62 context->fds[i].events = POLLIN;
Cyril Bur46233672017-01-16 13:33:26 +110063 }
64
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110065 while (1) {
66 rc = poll(context->fds, POLL_FDS, -1);
67
68 if (rc < 0) { /* Error */
69 MSG_ERR("Error from poll(): %s\n", strerror(errno));
70 break; /* This should mean we clean up nicely */
71 }
72
73 /* Event on Polled File Descriptor - Handle It */
74 if (context->fds[SIG_FD].revents & POLLIN) { /* Signal */
75 struct signalfd_siginfo info = { 0 };
76
77 rc = read(context->fds[SIG_FD].fd, (void *) &info,
78 sizeof(info));
79 if (rc != sizeof(info)) {
80 MSG_ERR("Error reading signal event: %s\n",
81 strerror(errno));
82 }
83
Suraj Jitindar Singh28519592017-04-27 14:48:58 +100084 MSG_DBG("Received signal: %d\n", info.ssi_signo);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110085 switch (info.ssi_signo) {
86 case SIGINT:
87 case SIGTERM:
Suraj Jitindar Singh28519592017-04-27 14:48:58 +100088 MSG_INFO("Caught Signal - Exiting...\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110089 context->terminate = true;
90 break;
91 case SIGHUP:
92 /* Host didn't request reset -> Notify it */
93 reset_all_windows(context, SET_BMC_EVENT);
Deepak Kodihalli017e45c2017-07-12 01:06:30 -050094 rc = reset_lpc(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +110095 if (rc < 0) {
96 MSG_ERR("WARNING: Failed to point the "
97 "LPC bus back to flash on "
98 "SIGHUP\nIf the host requires "
99 "this expect problems...\n");
100 }
101 break;
102 default:
103 MSG_ERR("Unhandled Signal: %d\n",
104 info.ssi_signo);
105 break;
106 }
107 }
108 if (context->fds[DBUS_FD].revents & POLLIN) { /* DBUS */
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000109 while ((rc = sd_bus_process(context->bus, NULL)) > 0) {
110 MSG_DBG("DBUS Event\n");
111 }
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100112 if (rc < 0) {
113 MSG_ERR("Error handling DBUS event: %s\n",
114 strerror(-rc));
115 }
116 }
117 if (context->terminate) {
118 break; /* This should mean we clean up nicely */
119 }
120 if (context->fds[MBOX_FD].revents & POLLIN) { /* MBOX */
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000121 MSG_DBG("MBOX Event\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100122 rc = dispatch_mbox(context);
123 if (rc < 0) {
124 MSG_ERR("Error handling MBOX event\n");
125 }
126 }
127 }
128
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500129 /* Best to reset windows and the lpc mapping for safety */
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100130 /* Host didn't request reset -> Notify it */
131 reset_all_windows(context, SET_BMC_EVENT);
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500132 rc = reset_lpc(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100133 /* Not much we can do if this fails */
134 if (rc < 0) {
135 MSG_ERR("WARNING: Failed to point the LPC bus back to flash\n"
136 "If the host requires this expect problems...\n");
137 }
138
139 return rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100140}
141
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100142static int init_signals(struct mbox_context *context, sigset_t *set)
Cyril Burc85e34d2016-11-15 11:50:41 +1100143{
144 int rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100145
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100146 /* Block SIGHUPs, SIGTERMs and SIGINTs */
147 sigemptyset(set);
148 sigaddset(set, SIGHUP);
149 sigaddset(set, SIGINT);
150 sigaddset(set, SIGTERM);
151 rc = sigprocmask(SIG_BLOCK, set, NULL);
152 if (rc < 0) {
153 MSG_ERR("Failed to set SIG_BLOCK mask %s\n", strerror(errno));
154 return rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100155 }
156
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100157 /* Get Signal File Descriptor */
158 rc = signalfd(-1, set, SFD_NONBLOCK);
159 if (rc < 0) {
160 MSG_ERR("Failed to get signalfd %s\n", strerror(errno));
161 return rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100162 }
163
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100164 context->fds[SIG_FD].fd = rc;
Cyril Burc85e34d2016-11-15 11:50:41 +1100165 return 0;
166}
167
Cyril Burc85e34d2016-11-15 11:50:41 +1100168static void usage(const char *name)
169{
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100170 printf(USAGE, name);
Cyril Burc85e34d2016-11-15 11:50:41 +1100171}
172
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100173static bool parse_cmdline(int argc, char **argv,
174 struct mbox_context *context)
Cyril Burc85e34d2016-11-15 11:50:41 +1100175{
Cyril Bure8f2de12017-01-17 16:56:02 +1100176 char *endptr;
Suraj Jitindar Singhc29172e2017-04-12 14:26:47 +1000177 int opt;
Cyril Burc85e34d2016-11-15 11:50:41 +1100178
179 static const struct option long_options[] = {
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100180 { "flash", required_argument, 0, 'f' },
181 { "window-size", optional_argument, 0, 'w' },
182 { "window-num", optional_argument, 0, 'n' },
183 { "verbose", no_argument, 0, 'v' },
184 { "syslog", no_argument, 0, 's' },
185 { "version", no_argument, 0, 'V' },
186 { "help", no_argument, 0, 'h' },
187 { 0, 0, 0, 0 }
Cyril Burc85e34d2016-11-15 11:50:41 +1100188 };
189
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100190 verbosity = MBOX_LOG_NONE;
Cyril Burc85e34d2016-11-15 11:50:41 +1100191 mbox_vlog = &mbox_log_console;
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100192
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100193 context->current = NULL; /* No current window */
194
195 while ((opt = getopt_long(argc, argv, "f:w::n::vsVh", long_options, NULL))
196 != -1) {
Cyril Burc85e34d2016-11-15 11:50:41 +1100197 switch (opt) {
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100198 case 0:
199 break;
200 case 'f':
201 context->flash_size = strtol(optarg, &endptr, 10);
202 if (optarg == endptr) {
203 fprintf(stderr, "Unparseable flash size\n");
204 return false;
205 }
206 switch (*endptr) {
207 case '\0':
Cyril Burc85e34d2016-11-15 11:50:41 +1100208 break;
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100209 case 'M':
210 context->flash_size <<= 10;
211 case 'K':
212 context->flash_size <<= 10;
Cyril Burc85e34d2016-11-15 11:50:41 +1100213 break;
214 default:
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100215 fprintf(stderr, "Unknown units '%c'\n",
216 *endptr);
217 return false;
218 }
219 break;
220 case 'n':
221 context->windows.num = strtol(argv[optind], &endptr,
222 10);
223 if (optarg == endptr || *endptr != '\0') {
224 fprintf(stderr, "Unparseable window num\n");
225 return false;
226 }
227 break;
228 case 'w':
229 context->windows.default_size = strtol(argv[optind],
230 &endptr, 10);
231 context->windows.default_size <<= 20; /* Given in MB */
232 if (optarg == endptr || (*endptr != '\0' &&
233 *endptr != 'M')) {
234 fprintf(stderr, "Unparseable window size\n");
235 return false;
236 }
Suraj Jitindar Singh0aff80c2017-04-12 14:37:24 +1000237 if (!is_power_of_2(context->windows.default_size)) {
238 fprintf(stderr, "Window size not power of 2\n");
239 return false;
240 }
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100241 break;
242 case 'v':
243 verbosity++;
244 break;
245 case 's':
246 /* Avoid a double openlog() */
247 if (mbox_vlog != &vsyslog) {
248 openlog(PREFIX, LOG_ODELAY, LOG_DAEMON);
249 mbox_vlog = &vsyslog;
250 }
251 break;
252 case 'V':
Suraj Jitindar Singh8d65bb42017-05-01 16:05:17 +1000253 printf("%s V%s\n", THIS_NAME, PACKAGE_VERSION);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100254 exit(0);
255 case 'h':
256 return false; /* This will print the usage message */
257 default:
258 return false;
Cyril Burc85e34d2016-11-15 11:50:41 +1100259 }
260 }
261
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100262 if (!context->flash_size) {
Cyril Bure8f2de12017-01-17 16:56:02 +1100263 fprintf(stderr, "Must specify a non-zero flash size\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100264 return false;
Cyril Bure8f2de12017-01-17 16:56:02 +1100265 }
266
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000267 MSG_INFO("Flash size: 0x%.8x\n", context->flash_size);
Cyril Burc85e34d2016-11-15 11:50:41 +1100268
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100269 if (verbosity) {
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000270 MSG_INFO("%s logging\n", verbosity == MBOX_LOG_DEBUG ? "Debug" :
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100271 "Verbose");
Cyril Burc85e34d2016-11-15 11:50:41 +1100272 }
273
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100274 return true;
Cyril Burc85e34d2016-11-15 11:50:41 +1100275}
276
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100277int main(int argc, char **argv)
278{
279 struct mbox_context *context;
280 char *name = argv[0];
281 sigset_t set;
282 int rc, i;
283
284 context = calloc(1, sizeof(*context));
285 if (!context) {
286 fprintf(stderr, "Memory allocation failed\n");
287 exit(1);
288 }
289
290 if (!parse_cmdline(argc, argv, context)) {
291 usage(name);
292 free(context);
293 exit(0);
294 }
295
296 for (i = 0; i < TOTAL_FDS; i++) {
297 context->fds[i].fd = -1;
298 }
299
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000300 MSG_INFO("Starting Daemon\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100301
302 rc = init_signals(context, &set);
303 if (rc) {
304 goto finish;
305 }
306
307 rc = init_mbox_dev(context);
308 if (rc) {
309 goto finish;
310 }
311
312 rc = init_lpc_dev(context);
313 if (rc) {
314 goto finish;
315 }
316
317 /* We've found the reserved memory region -> we can assign to windows */
Suraj Jitindar Singhc29172e2017-04-12 14:26:47 +1000318 rc = init_windows(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100319 if (rc) {
320 goto finish;
321 }
322
323 rc = init_flash_dev(context);
324 if (rc) {
325 goto finish;
326 }
327
Andrew Jefferyba0bbab2018-08-06 09:43:57 +0930328 rc = mboxd_dbus_init(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100329 if (rc) {
330 goto finish;
331 }
332
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500333#ifdef VIRTUAL_PNOR_ENABLED
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500334 init_vpnor(context);
Deepak Kodihalli017e45c2017-07-12 01:06:30 -0500335#endif
336
337 /* Set the LPC bus mapping */
338 rc = reset_lpc(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100339 if (rc) {
Andrew Jeffery8fe809e2018-05-17 09:54:32 +0930340 MSG_ERR("LPC configuration failed, RESET required: %d\n", rc);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100341 }
342
343 rc = set_bmc_events(context, BMC_EVENT_DAEMON_READY, SET_BMC_EVENT);
344 if (rc) {
345 goto finish;
346 }
347
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000348 MSG_INFO("Entering Polling Loop\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100349 rc = poll_loop(context);
350
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000351 MSG_INFO("Exiting Poll Loop: %d\n", rc);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100352
353finish:
Suraj Jitindar Singh28519592017-04-27 14:48:58 +1000354 MSG_INFO("Daemon Exiting...\n");
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100355 clr_bmc_events(context, BMC_EVENT_DAEMON_READY, SET_BMC_EVENT);
356
Andrew Jefferyba0bbab2018-08-06 09:43:57 +0930357 mboxd_dbus_free(context);
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100358 free_flash_dev(context);
359 free_lpc_dev(context);
360 free_mbox_dev(context);
Suraj Jitindar Singhc29172e2017-04-12 14:26:47 +1000361 free_windows(context);
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -0500362#ifdef VIRTUAL_PNOR_ENABLED
Deepak Kodihalli64ec3e42017-07-17 06:15:16 -0500363 destroy_vpnor(context);
Deepak Kodihalli6c2fa902017-05-01 06:36:02 -0500364#endif
Suraj Jitindar Singhe39c9162017-03-28 10:47:43 +1100365 free(context);
366
367 return rc;
368}