protocol: Rework publication of events over DBus transport

A set of races was discovered around the propagation of HIOMAP protocol
BMC status events during BMC shutdown. In particular the change impacts
the design of the DBus transport defined in the protocol specification,
as signalling of both acknowledgeable and non-acknowledgeable events
could not be made atomic.

A particular case where this matters is when the daemon is terminated,
at which point it should simultaneously clear BMC_EVENT_DAEMON_READY and
set BMC_EVENT_PROTOCOL_RESET. The DBus interface as designed required
this be done as two separate messages, which lead to races propagating
the complete state update to the host during shutdown of ipmid.

Change-Id: Iaf38f77c28b8e4e4dd092b0de97dc7e777bfac65
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/transport_dbus.c b/transport_dbus.c
index 21e097b..ad0ed0d 100644
--- a/transport_dbus.c
+++ b/transport_dbus.c
@@ -17,7 +17,7 @@
 					  uint8_t events)
 {
 	/* Two properties plus a terminating NULL */
-	char *props[3] = { 0 };
+	char *props[5] = { 0 };
 	int i = 0;
 	int rc;
 
@@ -29,6 +29,14 @@
 		props[i++] = "DaemonReady";
 	}
 
+	if (events & BMC_EVENT_WINDOW_RESET) {
+		props[i++] = "WindowReset";
+	}
+
+	if (events & BMC_EVENT_PROTOCOL_RESET) {
+		props[i++] = "ProtocolReset";
+	}
+
 	rc = sd_bus_emit_properties_changed_strv(context->bus,
 						 MBOX_DBUS_OBJECT,
 						 /* FIXME: Hard-coding v2 */
@@ -482,6 +490,10 @@
 		value = context->bmc_events & BMC_EVENT_FLASH_CTRL_LOST;
 	} else if (!strcmp("DaemonReady", property)) {
 		value = context->bmc_events & BMC_EVENT_DAEMON_READY;
+	} else if (!strcmp("WindowReset", property)) {
+		value = context->bmc_events & BMC_EVENT_WINDOW_RESET;
+	} else if (!strcmp("ProtocolReset", property)) {
+		value = context->bmc_events & BMC_EVENT_PROTOCOL_RESET;
 	} else {
 		MSG_ERR("Unknown DBus property: %s\n", property);
 		return -EINVAL;
@@ -534,6 +546,14 @@
 			SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
 	SD_BUS_SIGNAL("ProtocolReset", NULL, 0),
 	SD_BUS_SIGNAL("WindowReset", NULL, 0),
+	SD_BUS_PROPERTY("ProtocolReset",  "b",
+			transport_dbus_get_property,
+			0, /* Just a pointer to struct mbox_context */
+			SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+	SD_BUS_PROPERTY("WindowReset", "b",
+			transport_dbus_get_property,
+			0, /* Just a pointer to struct mbox_context */
+			SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
 	SD_BUS_VTABLE_END
 };