xref: /openbmc/hiomapd/mboxd.c (revision 68a24c9ea5ce11c87fab22a3f4648c7d88c98fee)
14fe996c2SAndrew Jeffery // SPDX-License-Identifier: Apache-2.0
24fe996c2SAndrew Jeffery // Copyright (C) 2018 IBM Corp.
3c85e34d1SCyril Bur 
4e39c9163SSuraj Jitindar Singh #define _GNU_SOURCE
5c85e34d1SCyril Bur #include <assert.h>
6c85e34d1SCyril Bur #include <errno.h>
7c85e34d1SCyril Bur #include <fcntl.h>
8c85e34d1SCyril Bur #include <getopt.h>
9c85e34d1SCyril Bur #include <limits.h>
10c85e34d1SCyril Bur #include <poll.h>
11c85e34d1SCyril Bur #include <stdbool.h>
12c85e34d1SCyril Bur #include <stdint.h>
13c85e34d1SCyril Bur #include <stdio.h>
14c85e34d1SCyril Bur #include <stdlib.h>
15c85e34d1SCyril Bur #include <string.h>
16c85e34d1SCyril Bur #include <syslog.h>
17899ebacaSMichael Neuling #include <signal.h>
18c85e34d1SCyril Bur #include <sys/ioctl.h>
19c85e34d1SCyril Bur #include <sys/mman.h>
20c85e34d1SCyril Bur #include <sys/stat.h>
21c85e34d1SCyril Bur #include <sys/timerfd.h>
22c85e34d1SCyril Bur #include <sys/types.h>
23e39c9163SSuraj Jitindar Singh #include <sys/signalfd.h>
24c85e34d1SCyril Bur #include <time.h>
25c85e34d1SCyril Bur #include <unistd.h>
2678210b9bSAndrew Jeffery #include <inttypes.h>
27e39c9163SSuraj Jitindar Singh #include <systemd/sd-bus.h>
28c85e34d1SCyril Bur 
298d65bb44SSuraj Jitindar Singh #include "config.h"
3026558dbbSAndrew Jeffery #include "mboxd.h"
31c85e34d1SCyril Bur #include "common.h"
32e39c9163SSuraj Jitindar Singh #include "dbus.h"
3355f4d6f9SAndrew Jeffery #include "control_dbus.h"
34f1e547c7SEvan Lojewski #include "backend.h"
35cd18611eSAndrew Jeffery #include "lpc.h"
3623140beeSAndrew Jeffery #include "transport_dbus.h"
37f593b1bdSAndrew Jeffery #include "windows.h"
38f4bc335bSAndrew Jeffery #include "vpnor/backend.h"
39c85e34d1SCyril Bur 
40a042978bSEvan Lojewski const char* USAGE =
41a042978bSEvan Lojewski 	"\nUsage: %s [-V | --version] [-h | --help] [-v[v] | --verbose] [-s | --syslog]\n"
42a042978bSEvan Lojewski 	"\t\t[-n | --window-num <num>]\n"
43a042978bSEvan Lojewski 	"\t\t[-w | --window-size <size>M]\n"
44a042978bSEvan Lojewski 	"\t\t-f | --flash <size>[K|M]\n"
45a042978bSEvan Lojewski #ifdef VIRTUAL_PNOR_ENABLED
465320f6e0SAndrew Jeffery 	"\t\t-b | --backend <vpnor|mtd[:PATH]|file:PATH>\n"
47a042978bSEvan Lojewski #else
485320f6e0SAndrew Jeffery 	"\t\t-b | --backend <mtd[:PATH]|file:PATH>\n"
49a042978bSEvan Lojewski #endif
50a042978bSEvan Lojewski 	"\t-v | --verbose\t\tBe [more] verbose\n"
51a042978bSEvan Lojewski 	"\t-s | --syslog\t\tLog output to syslog (pointless without -v)\n"
52a042978bSEvan Lojewski 	"\t-n | --window-num\tThe number of windows\n"
53a042978bSEvan Lojewski 	"\t\t\t\t(default: fill the reserved memory region)\n"
54a042978bSEvan Lojewski 	"\t-w | --window-size\tThe window size (power of 2) in MB\n"
55a042978bSEvan Lojewski 	"\t\t\t\t(default: 1MB)\n"
56ef0c8360SStewart Smith 	"\t-f | --flash\t\tSize of flash in [K|M] bytes\n\n"
57ef0c8360SStewart Smith 	"\t-t | --trace\t\tFile to write trace data to (in blktrace format)\n\n";
58c85e34d1SCyril Bur 
dbus_init(struct mbox_context * context,const struct transport_ops ** ops)59fe0c9e86SAndrew Jeffery static int dbus_init(struct mbox_context *context,
60fe0c9e86SAndrew Jeffery 		     const struct transport_ops **ops)
61ef9e62d3SAndrew Jeffery {
62ef9e62d3SAndrew Jeffery 	int rc;
63ef9e62d3SAndrew Jeffery 
64ef9e62d3SAndrew Jeffery 	rc = sd_bus_default_system(&context->bus);
65ef9e62d3SAndrew Jeffery 	if (rc < 0) {
66ef9e62d3SAndrew Jeffery 		MSG_ERR("Failed to connect to the system bus: %s\n",
67ef9e62d3SAndrew Jeffery 			strerror(-rc));
68ef9e62d3SAndrew Jeffery 		return rc;
69ef9e62d3SAndrew Jeffery 	}
70ef9e62d3SAndrew Jeffery 
71ef9e62d3SAndrew Jeffery 	rc = control_legacy_init(context);
72ef9e62d3SAndrew Jeffery 	if (rc < 0) {
73ef9e62d3SAndrew Jeffery 		MSG_ERR("Failed to initialise legacy DBus interface: %s\n",
74ef9e62d3SAndrew Jeffery 			strerror(-rc));
75ef9e62d3SAndrew Jeffery 		return rc;
76ef9e62d3SAndrew Jeffery 	}
77ef9e62d3SAndrew Jeffery 
78ef9e62d3SAndrew Jeffery 	rc = control_dbus_init(context);
79ef9e62d3SAndrew Jeffery 	if (rc < 0) {
80ef9e62d3SAndrew Jeffery 		MSG_ERR("Failed to initialise DBus control interface: %s\n",
81ef9e62d3SAndrew Jeffery 			strerror(-rc));
82ef9e62d3SAndrew Jeffery 		return rc;
83ef9e62d3SAndrew Jeffery 	}
84ef9e62d3SAndrew Jeffery 
85fe0c9e86SAndrew Jeffery 	rc = transport_dbus_init(context, ops);
8623140beeSAndrew Jeffery 	if (rc < 0) {
8723140beeSAndrew Jeffery 		MSG_ERR("Failed to initialise DBus protocol interface: %s\n",
8823140beeSAndrew Jeffery 			strerror(-rc));
8923140beeSAndrew Jeffery 		return rc;
9023140beeSAndrew Jeffery 	}
9123140beeSAndrew Jeffery 
92ef9e62d3SAndrew Jeffery 	rc = sd_bus_request_name(context->bus, MBOX_DBUS_NAME,
93ef9e62d3SAndrew Jeffery 				 SD_BUS_NAME_ALLOW_REPLACEMENT |
94ef9e62d3SAndrew Jeffery 				 SD_BUS_NAME_REPLACE_EXISTING);
95ef9e62d3SAndrew Jeffery 	if (rc < 0) {
9623140beeSAndrew Jeffery 		MSG_ERR("Failed to request DBus name: %s\n", strerror(-rc));
97ef9e62d3SAndrew Jeffery 		return rc;
98ef9e62d3SAndrew Jeffery 	}
99ef9e62d3SAndrew Jeffery 
100ef9e62d3SAndrew Jeffery 	rc = sd_bus_get_fd(context->bus);
101ef9e62d3SAndrew Jeffery 	if (rc < 0) {
102ef9e62d3SAndrew Jeffery 		MSG_ERR("Failed to get bus fd: %s\n", strerror(-rc));
103ef9e62d3SAndrew Jeffery 		return rc;
104ef9e62d3SAndrew Jeffery 	}
105ef9e62d3SAndrew Jeffery 
106ef9e62d3SAndrew Jeffery 	context->fds[DBUS_FD].fd = rc;
107ef9e62d3SAndrew Jeffery 
108ef9e62d3SAndrew Jeffery 	return 0;
109ef9e62d3SAndrew Jeffery }
110ef9e62d3SAndrew Jeffery 
dbus_free(struct mbox_context * context)111ef9e62d3SAndrew Jeffery static void dbus_free(struct mbox_context *context)
112ef9e62d3SAndrew Jeffery {
11323140beeSAndrew Jeffery 	transport_dbus_free(context);
114ef9e62d3SAndrew Jeffery 	control_dbus_free(context);
115ef9e62d3SAndrew Jeffery 	control_legacy_free(context);
116ef9e62d3SAndrew Jeffery 	sd_bus_unref(context->bus);
117ef9e62d3SAndrew Jeffery }
11855f4d6f9SAndrew Jeffery 
poll_loop(struct mbox_context * context)119e39c9163SSuraj Jitindar Singh static int poll_loop(struct mbox_context *context)
120c85e34d1SCyril Bur {
121e39c9163SSuraj Jitindar Singh 	int rc = 0, i;
12246233678SCyril Bur 
123e39c9163SSuraj Jitindar Singh 	/* Set POLLIN on polling file descriptors */
124e39c9163SSuraj Jitindar Singh 	for (i = 0; i < POLL_FDS; i++) {
125e39c9163SSuraj Jitindar Singh 		context->fds[i].events = POLLIN;
12646233678SCyril Bur 	}
12746233678SCyril Bur 
128e39c9163SSuraj Jitindar Singh 	while (1) {
129e39c9163SSuraj Jitindar Singh 		rc = poll(context->fds, POLL_FDS, -1);
130e39c9163SSuraj Jitindar Singh 
131e39c9163SSuraj Jitindar Singh 		if (rc < 0) { /* Error */
132e39c9163SSuraj Jitindar Singh 			MSG_ERR("Error from poll(): %s\n", strerror(errno));
133e39c9163SSuraj Jitindar Singh 			break; /* This should mean we clean up nicely */
134c85e34d1SCyril Bur 		}
135c85e34d1SCyril Bur 
136e39c9163SSuraj Jitindar Singh 		/* Event on Polled File Descriptor - Handle It */
137e39c9163SSuraj Jitindar Singh 		if (context->fds[SIG_FD].revents & POLLIN) { /* Signal */
138e39c9163SSuraj Jitindar Singh 			struct signalfd_siginfo info = { 0 };
139c85e34d1SCyril Bur 
140e39c9163SSuraj Jitindar Singh 			rc = read(context->fds[SIG_FD].fd, (void *) &info,
141e39c9163SSuraj Jitindar Singh 				  sizeof(info));
142e39c9163SSuraj Jitindar Singh 			if (rc != sizeof(info)) {
143e39c9163SSuraj Jitindar Singh 				MSG_ERR("Error reading signal event: %s\n",
144c85e34d1SCyril Bur 					strerror(errno));
145c85e34d1SCyril Bur 			}
146e39c9163SSuraj Jitindar Singh 
14728519598SSuraj Jitindar Singh 			MSG_DBG("Received signal: %d\n", info.ssi_signo);
148e39c9163SSuraj Jitindar Singh 			switch (info.ssi_signo) {
149e39c9163SSuraj Jitindar Singh 			case SIGINT:
150e39c9163SSuraj Jitindar Singh 			case SIGTERM:
15128519598SSuraj Jitindar Singh 				MSG_INFO("Caught Signal - Exiting...\n");
152e39c9163SSuraj Jitindar Singh 				context->terminate = true;
153c85e34d1SCyril Bur 				break;
154e39c9163SSuraj Jitindar Singh 			case SIGHUP:
155f69760daSAndrew Jeffery 				rc = protocol_reset(context);
1562ebfd20fSAndrew Jeffery 				if (rc < 0) {
157f69760daSAndrew Jeffery 					MSG_ERR("Failed to reset on SIGHUP\n");
158e39c9163SSuraj Jitindar Singh 				}
159c85e34d1SCyril Bur 				break;
160c85e34d1SCyril Bur 			default:
161e39c9163SSuraj Jitindar Singh 				MSG_ERR("Unhandled Signal: %d\n",
162e39c9163SSuraj Jitindar Singh 					info.ssi_signo);
163e39c9163SSuraj Jitindar Singh 				break;
164e39c9163SSuraj Jitindar Singh 			}
165e39c9163SSuraj Jitindar Singh 		}
166e39c9163SSuraj Jitindar Singh 		if (context->fds[DBUS_FD].revents & POLLIN) { /* DBUS */
16728519598SSuraj Jitindar Singh 			while ((rc = sd_bus_process(context->bus, NULL)) > 0) {
16828519598SSuraj Jitindar Singh 				MSG_DBG("DBUS Event\n");
16928519598SSuraj Jitindar Singh 			}
170e39c9163SSuraj Jitindar Singh 			if (rc < 0) {
171e39c9163SSuraj Jitindar Singh 				MSG_ERR("Error handling DBUS event: %s\n",
172e39c9163SSuraj Jitindar Singh 						strerror(-rc));
173e39c9163SSuraj Jitindar Singh 			}
174e39c9163SSuraj Jitindar Singh 		}
175e39c9163SSuraj Jitindar Singh 		if (context->terminate) {
176e39c9163SSuraj Jitindar Singh 			break; /* This should mean we clean up nicely */
177e39c9163SSuraj Jitindar Singh 		}
178c85e34d1SCyril Bur 	}
179c85e34d1SCyril Bur 
180f69760daSAndrew Jeffery 	rc = protocol_reset(context);
181e39c9163SSuraj Jitindar Singh 	if (rc < 0) {
182f69760daSAndrew Jeffery 		MSG_ERR("Failed to reset during poll loop cleanup\n");
183c85e34d1SCyril Bur 	}
184c85e34d1SCyril Bur 
185e39c9163SSuraj Jitindar Singh 	return rc;
186c85e34d1SCyril Bur }
187c85e34d1SCyril Bur 
init_signals(struct mbox_context * context,sigset_t * set)188e39c9163SSuraj Jitindar Singh static int init_signals(struct mbox_context *context, sigset_t *set)
189899ebacaSMichael Neuling {
190e39c9163SSuraj Jitindar Singh 	int rc;
191899ebacaSMichael Neuling 
192e39c9163SSuraj Jitindar Singh 	/* Block SIGHUPs, SIGTERMs and SIGINTs */
193e39c9163SSuraj Jitindar Singh 	sigemptyset(set);
194e39c9163SSuraj Jitindar Singh 	sigaddset(set, SIGHUP);
195e39c9163SSuraj Jitindar Singh 	sigaddset(set, SIGINT);
196e39c9163SSuraj Jitindar Singh 	sigaddset(set, SIGTERM);
197e39c9163SSuraj Jitindar Singh 	rc = sigprocmask(SIG_BLOCK, set, NULL);
198e39c9163SSuraj Jitindar Singh 	if (rc < 0) {
199e39c9163SSuraj Jitindar Singh 		MSG_ERR("Failed to set SIG_BLOCK mask %s\n", strerror(errno));
200e39c9163SSuraj Jitindar Singh 		return rc;
201899ebacaSMichael Neuling 	}
202e39c9163SSuraj Jitindar Singh 
203e39c9163SSuraj Jitindar Singh 	/* Get Signal File Descriptor */
204e39c9163SSuraj Jitindar Singh 	rc = signalfd(-1, set, SFD_NONBLOCK);
205e39c9163SSuraj Jitindar Singh 	if (rc < 0) {
206e39c9163SSuraj Jitindar Singh 		MSG_ERR("Failed to get signalfd %s\n", strerror(errno));
207e39c9163SSuraj Jitindar Singh 		return rc;
208899ebacaSMichael Neuling 	}
209e39c9163SSuraj Jitindar Singh 
210e39c9163SSuraj Jitindar Singh 	context->fds[SIG_FD].fd = rc;
211899ebacaSMichael Neuling 	return 0;
212899ebacaSMichael Neuling }
213899ebacaSMichael Neuling 
usage(const char * name)214c85e34d1SCyril Bur static void usage(const char *name)
215c85e34d1SCyril Bur {
216e39c9163SSuraj Jitindar Singh 	printf(USAGE, name);
217c85e34d1SCyril Bur }
218c85e34d1SCyril Bur 
parse_cmdline(int argc,char ** argv,struct mbox_context * context)219e39c9163SSuraj Jitindar Singh static bool parse_cmdline(int argc, char **argv,
220e39c9163SSuraj Jitindar Singh 			  struct mbox_context *context)
221c85e34d1SCyril Bur {
222e8f2de1fSCyril Bur 	char *endptr;
223c29172e1SSuraj Jitindar Singh 	int opt;
224c85e34d1SCyril Bur 
225c85e34d1SCyril Bur 	static const struct option long_options[] = {
226e8f2de1fSCyril Bur 		{ "flash",		required_argument,	0, 'f' },
227a042978bSEvan Lojewski 		{ "backend",		required_argument,	0, 'b' },
228e39c9163SSuraj Jitindar Singh 		{ "window-size",	optional_argument,	0, 'w' },
229e39c9163SSuraj Jitindar Singh 		{ "window-num",		optional_argument,	0, 'n' },
230c85e34d1SCyril Bur 		{ "verbose",		no_argument,		0, 'v' },
231c85e34d1SCyril Bur 		{ "syslog",		no_argument,		0, 's' },
232ef0c8360SStewart Smith 		{ "trace",		optional_argument,	0, 't' },
233e39c9163SSuraj Jitindar Singh 		{ "version",		no_argument,		0, 'V' },
234e39c9163SSuraj Jitindar Singh 		{ "help",		no_argument,		0, 'h' },
235c85e34d1SCyril Bur 		{ 0,			0,			0, 0   }
236c85e34d1SCyril Bur 	};
237c85e34d1SCyril Bur 
238e39c9163SSuraj Jitindar Singh 	verbosity = MBOX_LOG_NONE;
239c85e34d1SCyril Bur 	mbox_vlog = &mbox_log_console;
240e39c9163SSuraj Jitindar Singh 
241e39c9163SSuraj Jitindar Singh 	context->current = NULL; /* No current window */
242e39c9163SSuraj Jitindar Singh 
243ef0c8360SStewart Smith 	while ((opt = getopt_long(argc, argv, "f:b:w::n::vst::Vh", long_options, NULL))
244e39c9163SSuraj Jitindar Singh 			!= -1) {
245c85e34d1SCyril Bur 		switch (opt) {
246c85e34d1SCyril Bur 		case 0:
247c85e34d1SCyril Bur 			break;
248e8f2de1fSCyril Bur 		case 'f':
249f1e547c7SEvan Lojewski 			context->backend.flash_size = strtol(optarg, &endptr, 10);
250e8f2de1fSCyril Bur 			if (optarg == endptr) {
251e8f2de1fSCyril Bur 				fprintf(stderr, "Unparseable flash size\n");
252e39c9163SSuraj Jitindar Singh 				return false;
253e8f2de1fSCyril Bur 			}
254e39c9163SSuraj Jitindar Singh 			switch (*endptr) {
255e39c9163SSuraj Jitindar Singh 			case '\0':
256e39c9163SSuraj Jitindar Singh 				break;
257e39c9163SSuraj Jitindar Singh 			case 'M':
258*68a24c9eSPatrick Williams 				context->backend.flash_size <<= 20;
259*68a24c9eSPatrick Williams 				break;
260e39c9163SSuraj Jitindar Singh 			case 'K':
261f1e547c7SEvan Lojewski 				context->backend.flash_size <<= 10;
262e39c9163SSuraj Jitindar Singh 				break;
263e39c9163SSuraj Jitindar Singh 			default:
264e39c9163SSuraj Jitindar Singh 				fprintf(stderr, "Unknown units '%c'\n",
265e39c9163SSuraj Jitindar Singh 					*endptr);
266e39c9163SSuraj Jitindar Singh 				return false;
267e39c9163SSuraj Jitindar Singh 			}
268e39c9163SSuraj Jitindar Singh 			break;
269a042978bSEvan Lojewski 		case 'b':
2705320f6e0SAndrew Jeffery 			context->source = optarg;
271a042978bSEvan Lojewski 			break;
272e39c9163SSuraj Jitindar Singh 		case 'n':
273e39c9163SSuraj Jitindar Singh 			context->windows.num = strtol(argv[optind], &endptr,
274e39c9163SSuraj Jitindar Singh 						      10);
275e39c9163SSuraj Jitindar Singh 			if (optarg == endptr || *endptr != '\0') {
276e39c9163SSuraj Jitindar Singh 				fprintf(stderr, "Unparseable window num\n");
277e39c9163SSuraj Jitindar Singh 				return false;
278e39c9163SSuraj Jitindar Singh 			}
279e39c9163SSuraj Jitindar Singh 			break;
280e39c9163SSuraj Jitindar Singh 		case 'w':
281e39c9163SSuraj Jitindar Singh 			context->windows.default_size = strtol(argv[optind],
282e39c9163SSuraj Jitindar Singh 							       &endptr, 10);
283e39c9163SSuraj Jitindar Singh 			context->windows.default_size <<= 20; /* Given in MB */
284e39c9163SSuraj Jitindar Singh 			if (optarg == endptr || (*endptr != '\0' &&
285e39c9163SSuraj Jitindar Singh 						 *endptr != 'M')) {
286e39c9163SSuraj Jitindar Singh 				fprintf(stderr, "Unparseable window size\n");
287e39c9163SSuraj Jitindar Singh 				return false;
288e8f2de1fSCyril Bur 			}
2890aff80c0SSuraj Jitindar Singh 			if (!is_power_of_2(context->windows.default_size)) {
2900aff80c0SSuraj Jitindar Singh 				fprintf(stderr, "Window size not power of 2\n");
2910aff80c0SSuraj Jitindar Singh 				return false;
2920aff80c0SSuraj Jitindar Singh 			}
293e8f2de1fSCyril Bur 			break;
294c85e34d1SCyril Bur 		case 'v':
295c85e34d1SCyril Bur 			verbosity++;
296c85e34d1SCyril Bur 			break;
297c85e34d1SCyril Bur 		case 's':
298c85e34d1SCyril Bur 			/* Avoid a double openlog() */
299c85e34d1SCyril Bur 			if (mbox_vlog != &vsyslog) {
300c85e34d1SCyril Bur 				openlog(PREFIX, LOG_ODELAY, LOG_DAEMON);
301c85e34d1SCyril Bur 				mbox_vlog = &vsyslog;
302c85e34d1SCyril Bur 			}
303c85e34d1SCyril Bur 			break;
304e39c9163SSuraj Jitindar Singh 		case 'V':
3058d65bb44SSuraj Jitindar Singh 			printf("%s V%s\n", THIS_NAME, PACKAGE_VERSION);
306e39c9163SSuraj Jitindar Singh 			exit(0);
307ef0c8360SStewart Smith 		case 't':
308ef0c8360SStewart Smith 			context->blktracefd = open(argv[optind],
309ef0c8360SStewart Smith 						   O_CREAT|O_TRUNC|O_WRONLY,
310ef0c8360SStewart Smith 						   0666);
311ef0c8360SStewart Smith 			printf("Recording blktrace output to %s\n",
312ef0c8360SStewart Smith 			       argv[optind]);
313ef0c8360SStewart Smith 			if (context->blktracefd == -1) {
314ef0c8360SStewart Smith 				perror("Couldn't open blktrace file for writing");
315ef0c8360SStewart Smith 				exit(2);
316ef0c8360SStewart Smith 			}
317ef0c8360SStewart Smith 			break;
318e39c9163SSuraj Jitindar Singh 		case 'h':
319e39c9163SSuraj Jitindar Singh 			return false; /* This will print the usage message */
320c85e34d1SCyril Bur 		default:
321e39c9163SSuraj Jitindar Singh 			return false;
322c85e34d1SCyril Bur 		}
323c85e34d1SCyril Bur 	}
324c85e34d1SCyril Bur 
325f1e547c7SEvan Lojewski 	if (!context->backend.flash_size) {
326e8f2de1fSCyril Bur 		fprintf(stderr, "Must specify a non-zero flash size\n");
327e39c9163SSuraj Jitindar Singh 		return false;
328e8f2de1fSCyril Bur 	}
329e8f2de1fSCyril Bur 
330f1e547c7SEvan Lojewski 	MSG_INFO("Flash size: 0x%.8x\n", context->backend.flash_size);
331c85e34d1SCyril Bur 
332e39c9163SSuraj Jitindar Singh 	if (verbosity) {
33328519598SSuraj Jitindar Singh 		MSG_INFO("%s logging\n", verbosity == MBOX_LOG_DEBUG ? "Debug" :
334e39c9163SSuraj Jitindar Singh 					"Verbose");
335e39c9163SSuraj Jitindar Singh 	}
336e39c9163SSuraj Jitindar Singh 
337e39c9163SSuraj Jitindar Singh 	return true;
338e39c9163SSuraj Jitindar Singh }
339e39c9163SSuraj Jitindar Singh 
mboxd_backend_init(struct mbox_context * context)340f1e547c7SEvan Lojewski static int mboxd_backend_init(struct mbox_context *context)
341f1e547c7SEvan Lojewski {
3425320f6e0SAndrew Jeffery 	const char *delim;
3435320f6e0SAndrew Jeffery 	const char *path;
344f1e547c7SEvan Lojewski 	int rc;
345f1e547c7SEvan Lojewski 
3465320f6e0SAndrew Jeffery 	if (!context->source) {
347f1e547c7SEvan Lojewski 		struct vpnor_partition_paths paths;
348f1e547c7SEvan Lojewski 		vpnor_default_paths(&paths);
349f1e547c7SEvan Lojewski 
350f1e547c7SEvan Lojewski 		rc = backend_probe_vpnor(&context->backend, &paths);
3515320f6e0SAndrew Jeffery 		if(rc < 0)
3525320f6e0SAndrew Jeffery 			rc = backend_probe_mtd(&context->backend, NULL);
3535320f6e0SAndrew Jeffery 
3545320f6e0SAndrew Jeffery 		return rc;
355a042978bSEvan Lojewski 	}
3565320f6e0SAndrew Jeffery 
3575320f6e0SAndrew Jeffery 	delim = strchr(context->source, ':');
3585320f6e0SAndrew Jeffery 	path = delim ? delim + 1 : NULL;
3595320f6e0SAndrew Jeffery 
3605320f6e0SAndrew Jeffery 	if (!strncmp(context->source, "vpnor", strlen("vpnor"))) {
3615320f6e0SAndrew Jeffery 		struct vpnor_partition_paths paths;
3625320f6e0SAndrew Jeffery 
3635320f6e0SAndrew Jeffery 		if (path) {
3645320f6e0SAndrew Jeffery 			rc = -EINVAL;
3655320f6e0SAndrew Jeffery 		} else {
3665320f6e0SAndrew Jeffery 			vpnor_default_paths(&paths);
3675320f6e0SAndrew Jeffery 			rc = backend_probe_vpnor(&context->backend, &paths);
368f1e547c7SEvan Lojewski 		}
3695320f6e0SAndrew Jeffery 	} else if (!strncmp(context->source, "mtd", strlen("mtd"))) {
3705320f6e0SAndrew Jeffery 		rc = backend_probe_mtd(&context->backend, path);
3715320f6e0SAndrew Jeffery 	} else if (!strncmp(context->source, "file", strlen("file"))) {
3725320f6e0SAndrew Jeffery 		rc = backend_probe_file(&context->backend, path);
3735320f6e0SAndrew Jeffery 	} else {
3745320f6e0SAndrew Jeffery 		rc = -EINVAL;
3755320f6e0SAndrew Jeffery 	}
3765320f6e0SAndrew Jeffery 
3775320f6e0SAndrew Jeffery 	if (rc < 0)
3785320f6e0SAndrew Jeffery 		MSG_ERR("Invalid backend argument: %s\n", context->source);
379f1e547c7SEvan Lojewski 
380f1e547c7SEvan Lojewski 	return rc;
381f1e547c7SEvan Lojewski }
382f1e547c7SEvan Lojewski 
main(int argc,char ** argv)383e39c9163SSuraj Jitindar Singh int main(int argc, char **argv)
384e39c9163SSuraj Jitindar Singh {
385dfbeae25SJoel Stanley 	const struct transport_ops *dbus_ops;
386e39c9163SSuraj Jitindar Singh 	struct mbox_context *context;
387e39c9163SSuraj Jitindar Singh 	char *name = argv[0];
388e39c9163SSuraj Jitindar Singh 	sigset_t set;
389e39c9163SSuraj Jitindar Singh 	int rc, i;
390e39c9163SSuraj Jitindar Singh 
391e39c9163SSuraj Jitindar Singh 	context = calloc(1, sizeof(*context));
392e39c9163SSuraj Jitindar Singh 	if (!context) {
393e39c9163SSuraj Jitindar Singh 		fprintf(stderr, "Memory allocation failed\n");
394e39c9163SSuraj Jitindar Singh 		exit(1);
395e39c9163SSuraj Jitindar Singh 	}
396e39c9163SSuraj Jitindar Singh 
397e39c9163SSuraj Jitindar Singh 	if (!parse_cmdline(argc, argv, context)) {
398e39c9163SSuraj Jitindar Singh 		usage(name);
399e39c9163SSuraj Jitindar Singh 		free(context);
400e39c9163SSuraj Jitindar Singh 		exit(0);
401e39c9163SSuraj Jitindar Singh 	}
402e39c9163SSuraj Jitindar Singh 
403e39c9163SSuraj Jitindar Singh 	for (i = 0; i < TOTAL_FDS; i++) {
404e39c9163SSuraj Jitindar Singh 		context->fds[i].fd = -1;
405e39c9163SSuraj Jitindar Singh 	}
406e39c9163SSuraj Jitindar Singh 
40728519598SSuraj Jitindar Singh 	MSG_INFO("Starting Daemon\n");
408e39c9163SSuraj Jitindar Singh 
409e39c9163SSuraj Jitindar Singh 	rc = init_signals(context, &set);
410e39c9163SSuraj Jitindar Singh 	if (rc) {
4114ef0c132SAndrew Jeffery 		goto cleanup_context;
412c85e34d1SCyril Bur 	}
413c85e34d1SCyril Bur 
414f1e547c7SEvan Lojewski 	rc = mboxd_backend_init(context);
415f1e547c7SEvan Lojewski 	if (rc) {
4164ef0c132SAndrew Jeffery 		goto cleanup_context;
417f1e547c7SEvan Lojewski 	}
418f1e547c7SEvan Lojewski 
4191e531afdSAndrew Jeffery 	rc = protocol_init(context);
4201e531afdSAndrew Jeffery 	if (rc) {
4214ef0c132SAndrew Jeffery 		goto cleanup_backend;
4221e531afdSAndrew Jeffery 	}
4231e531afdSAndrew Jeffery 
424cb9b2100SAndrew Jeffery 	rc = lpc_dev_init(context);
425e39c9163SSuraj Jitindar Singh 	if (rc) {
426dfbeae25SJoel Stanley 		goto cleanup_protocol;
427c85e34d1SCyril Bur 	}
428c85e34d1SCyril Bur 
429e39c9163SSuraj Jitindar Singh 	/* We've found the reserved memory region -> we can assign to windows */
430c1a67fa8SAndrew Jeffery 	rc = windows_init(context);
431e39c9163SSuraj Jitindar Singh 	if (rc) {
4324ef0c132SAndrew Jeffery 		goto cleanup_lpc;
433c85e34d1SCyril Bur 	}
434c85e34d1SCyril Bur 
435fe0c9e86SAndrew Jeffery 	rc = dbus_init(context, &dbus_ops);
436e39c9163SSuraj Jitindar Singh 	if (rc) {
4374ef0c132SAndrew Jeffery 		goto cleanup_windows;
438c85e34d1SCyril Bur 	}
439c85e34d1SCyril Bur 
440017e45c3SDeepak Kodihalli 	/* Set the LPC bus mapping */
441f69760daSAndrew Jeffery 	__protocol_reset(context);
442d8f6d7a4SCyril Bur 
443fe0c9e86SAndrew Jeffery 	/* We're ready to go, alert the host */
444fe0c9e86SAndrew Jeffery 	context->bmc_events |= BMC_EVENT_DAEMON_READY;
4454c15bb17SAndrew Jeffery 	context->bmc_events |= BMC_EVENT_PROTOCOL_RESET;
446fe0c9e86SAndrew Jeffery 
4474b8203d7SAndrew Jeffery 	/* Alert on all supported transports, as required */
448fe0c9e86SAndrew Jeffery 	rc = protocol_events_put(context, dbus_ops);
449e39c9163SSuraj Jitindar Singh 	if (rc) {
4504ef0c132SAndrew Jeffery 		goto cleanup;
451899ebacaSMichael Neuling 	}
452c85e34d1SCyril Bur 
45328519598SSuraj Jitindar Singh 	MSG_INFO("Entering Polling Loop\n");
454e39c9163SSuraj Jitindar Singh 	rc = poll_loop(context);
455e39c9163SSuraj Jitindar Singh 
45628519598SSuraj Jitindar Singh 	MSG_INFO("Exiting Poll Loop: %d\n", rc);
457c85e34d1SCyril Bur 
45828519598SSuraj Jitindar Singh 	MSG_INFO("Daemon Exiting...\n");
459fe0c9e86SAndrew Jeffery 	context->bmc_events &= ~BMC_EVENT_DAEMON_READY;
460fab672bdSAndrew Jeffery 	context->bmc_events |= BMC_EVENT_PROTOCOL_RESET;
461fe0c9e86SAndrew Jeffery 
4624b8203d7SAndrew Jeffery 	/* Alert on all supported transports, as required */
463fe0c9e86SAndrew Jeffery 	protocol_events_put(context, dbus_ops);
464c85e34d1SCyril Bur 
4654ef0c132SAndrew Jeffery cleanup:
466ef9e62d3SAndrew Jeffery 	dbus_free(context);
4674ef0c132SAndrew Jeffery cleanup_windows:
468f5f51428SAndrew Jeffery 	windows_free(context);
4694ef0c132SAndrew Jeffery cleanup_lpc:
4704ef0c132SAndrew Jeffery 	lpc_dev_free(context);
471dfbeae25SJoel Stanley cleanup_protocol:
4721e531afdSAndrew Jeffery 	protocol_free(context);
4734ef0c132SAndrew Jeffery cleanup_backend:
4744ef0c132SAndrew Jeffery 	backend_free(&context->backend);
4754ef0c132SAndrew Jeffery cleanup_context:
476ef0c8360SStewart Smith 	if (context->blktracefd)
477ef0c8360SStewart Smith 		close(context->blktracefd);
478ef0c8360SStewart Smith 
479c85e34d1SCyril Bur 	free(context);
480c85e34d1SCyril Bur 
481e39c9163SSuraj Jitindar Singh 	return rc;
482c85e34d1SCyril Bur }
483