mboxd: Broadcast the daemon is ready on all transports

The code as it stood only sent the state update at startup on the active
transport, which is somewhat arbitrarily chosen as an implementation
detail of the mbox initialisation function.

If the host firmware is using IPMI, it will not learn of the update
unless it attempts to contact mboxd, which it won't do if it knows the
daemon isn't there, which it may have learned of by receiving a state
update from the daemon's shutdown path. In this circumstance the host
firmware is now stuck.

Relieve the host firmware of this problem by always sending the daemon
state on all supported transports. To avoid some insanity we introduce a
new callback in struct transport_ops that allows use to send the BMC's
entire event state rather than just set or clear updates.

Change-Id: I094ff4089eeebd8be99fbd343b94f7bbef023fb1
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/mboxd.c b/mboxd.c
index 86a67f3..745785e 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -51,7 +51,8 @@
 "\t\t\t\t(default: 1MB)\n" \
 "\t-f | --flash\t\tSize of flash in [K|M] bytes\n\n"
 
-static int dbus_init(struct mbox_context *context)
+static int dbus_init(struct mbox_context *context,
+		     const struct transport_ops **ops)
 {
 	int rc;
 
@@ -76,7 +77,7 @@
 		return rc;
 	}
 
-	rc = transport_dbus_init(context);
+	rc = transport_dbus_init(context, ops);
 	if (rc < 0) {
 		MSG_ERR("Failed to initialise DBus protocol interface: %s\n",
 			strerror(-rc));
@@ -346,6 +347,7 @@
 
 int main(int argc, char **argv)
 {
+	const struct transport_ops *mbox_ops, *dbus_ops;
 	struct mbox_context *context;
 	char *name = argv[0];
 	sigset_t set;
@@ -379,7 +381,7 @@
 		goto finish;
 	}
 
-	rc = transport_mbox_init(context);
+	rc = transport_mbox_init(context, &mbox_ops);
 	if (rc) {
 		goto finish;
 	}
@@ -400,7 +402,7 @@
 		goto finish;
 	}
 
-	rc = dbus_init(context);
+	rc = dbus_init(context, &dbus_ops);
 	if (rc) {
 		goto finish;
 	}
@@ -415,7 +417,16 @@
 		MSG_ERR("LPC configuration failed, RESET required: %d\n", rc);
 	}
 
-	rc = protocol_events_set(context, BMC_EVENT_DAEMON_READY);
+	/* We're ready to go, alert the host */
+	context->bmc_events |= BMC_EVENT_DAEMON_READY;
+
+	/* Alert on all supported transports */
+	rc = protocol_events_put(context, mbox_ops);
+	if (rc) {
+		goto finish;
+	}
+
+	rc = protocol_events_put(context, dbus_ops);
 	if (rc) {
 		goto finish;
 	}
@@ -427,7 +438,11 @@
 
 finish:
 	MSG_INFO("Daemon Exiting...\n");
-	protocol_events_clear(context, BMC_EVENT_DAEMON_READY);
+	context->bmc_events &= ~BMC_EVENT_DAEMON_READY;
+
+	/* Alert on all supported transports */
+	protocol_events_put(context, mbox_ops);
+	protocol_events_put(context, dbus_ops);
 
 #ifdef VIRTUAL_PNOR_ENABLED
 	destroy_vpnor(context);