blob: 14fdc24782c0601a25a54e4a4bcd42f4edf17123 [file] [log] [blame]
Andrew Jeffery23140be2018-09-05 14:15:07 +09301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
3#include "config.h"
4
Andrew Jefferya6ca7a92018-08-20 13:03:44 +09305#include <assert.h>
Andrew Jeffery23140be2018-09-05 14:15:07 +09306#include <errno.h>
Andrew Jefferya6ca7a92018-08-20 13:03:44 +09307#include <string.h>
Andrew Jeffery23140be2018-09-05 14:15:07 +09308#include <systemd/sd-bus.h>
9
10#include "common.h"
11#include "dbus.h"
12#include "mboxd.h"
13#include "protocol.h"
Andrew Jeffery23a48212018-08-10 14:41:48 +093014#include "transport.h"
15
Andrew Jefferya6ca7a92018-08-20 13:03:44 +093016static int transport_dbus_flush_events(struct mbox_context *context,
17 uint8_t events)
18{
19 char *props[3] = { 0 };
20 int i = 0;
21 int rc;
22
23 if (events & BMC_EVENT_FLASH_CTRL_LOST) {
24 props[i++] = "FlashControlLost";
25 }
26
27 if (events & BMC_EVENT_DAEMON_READY) {
28 props[i++] = "DaemonReady";
29 }
30
31 rc = sd_bus_emit_properties_changed_strv(context->bus,
32 MBOX_DBUS_OBJECT,
33 /* FIXME: Hard-coding v2 */
34 MBOX_DBUS_PROTOCOL_IFACE_V2,
35 props);
36 if (rc < 0) {
37 return rc;
38 }
39
40 if (events & BMC_EVENT_WINDOW_RESET) {
41 sd_bus_message *m = NULL;
42
43 rc = sd_bus_message_new_signal(context->bus, &m,
44 MBOX_DBUS_OBJECT,
45 /* FIXME: Hard-coding v2 */
46 MBOX_DBUS_PROTOCOL_IFACE_V2,
47 "WindowReset");
48 if (rc < 0) {
49 return rc;
50 }
51
52 rc = sd_bus_send(context->bus, m, NULL);
53 if (rc < 0) {
54 return rc;
55 }
56 }
57
58 if (events & BMC_EVENT_REBOOT) {
59 sd_bus_message *m = NULL;
60
61 rc = sd_bus_message_new_signal(context->bus, &m,
62 MBOX_DBUS_OBJECT,
63 /* FIXME: Hard-coding v2 */
64 MBOX_DBUS_PROTOCOL_IFACE_V2,
65 "ProtocolReset");
66 if (rc < 0) {
67 return rc;
68 }
69
70 rc = sd_bus_send(context->bus, m, NULL);
71 if (rc < 0) {
72 return rc;
73 }
74 }
75
76 return 0;
77}
78
Andrew Jeffery4414fb82018-08-20 12:13:09 +093079static int transport_dbus_set_events(struct mbox_context *context,
80 uint8_t events)
81{
Andrew Jefferya6ca7a92018-08-20 13:03:44 +093082 context->bmc_events |= events;
83
84 return transport_dbus_flush_events(context, events);
Andrew Jeffery4414fb82018-08-20 12:13:09 +093085}
86
87static int transport_dbus_clear_events(struct mbox_context *context,
88 uint8_t events)
Andrew Jeffery23a48212018-08-10 14:41:48 +093089{
Andrew Jefferya6ca7a92018-08-20 13:03:44 +093090 context->bmc_events &= ~events;
91
92 return transport_dbus_flush_events(context, events);
Andrew Jeffery23a48212018-08-10 14:41:48 +093093}
94
95static const struct transport_ops transport_dbus_ops = {
Andrew Jeffery4414fb82018-08-20 12:13:09 +093096 .set_events = transport_dbus_set_events,
97 .clear_events = transport_dbus_clear_events,
Andrew Jeffery23a48212018-08-10 14:41:48 +093098};
Andrew Jeffery23140be2018-09-05 14:15:07 +093099
100static int transport_dbus_get_info(sd_bus_message *m, void *userdata,
101 sd_bus_error *ret_error)
102{
103 struct mbox_context *context = userdata;
104 struct protocol_get_info io;
105 sd_bus_message *n;
106 int rc;
107
108 if (!context) {
109 MSG_ERR("DBUS Internal Error\n");
110 return -EINVAL;
111 }
112
113 rc = sd_bus_message_read_basic(m, 'y', &io.req.api_version);
114 if (rc < 0) {
115 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
116 return rc;
117 }
118
119 rc = context->protocol->get_info(context, &io);
120 if (rc < 0) {
121 return rc;
122 }
123
Andrew Jeffery23a48212018-08-10 14:41:48 +0930124 /* Switch transport to DBus. This is fine as DBus signals are async */
125 context->transport = &transport_dbus_ops;
Andrew Jefferya6ca7a92018-08-20 13:03:44 +0930126 transport_dbus_flush_events(context, context->bmc_events);
Andrew Jeffery23a48212018-08-10 14:41:48 +0930127
Andrew Jeffery23140be2018-09-05 14:15:07 +0930128 rc = sd_bus_message_new_method_return(m, &n);
129 if (rc < 0) {
130 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
131 return rc;
132 }
133
134 if (API_VERSION_2 != io.resp.api_version) {
135 MSG_ERR("Unsupported protocol version for DBus transport: %d\n",
136 io.resp.api_version);
137 return rc;
138 }
139
140 rc = sd_bus_message_append(n, "yyq",
141 io.resp.api_version,
142 io.resp.v2.block_size_shift,
143 io.resp.v2.timeout);
144 if (rc < 0) {
145 MSG_ERR("sd_bus_message_append failed!\n");
146 return rc;
147 }
148
149 return sd_bus_send(NULL, n, NULL);
150}
151
Andrew Jefferya6ca7a92018-08-20 13:03:44 +0930152static int transport_dbus_get_property(sd_bus *bus,
153 const char *path,
154 const char *interface,
155 const char *property,
156 sd_bus_message *reply,
157 void *userdata,
158 sd_bus_error *ret_error)
159{
160 struct mbox_context *context = userdata;
161 bool value;
162
163 assert(!strcmp(MBOX_DBUS_OBJECT, path));
164 assert(!strcmp(MBOX_DBUS_PROTOCOL_IFACE_V2, interface));
165
166 if (!strcmp("FlashControlLost", property)) {
167 value = context->bmc_events & BMC_EVENT_FLASH_CTRL_LOST;
168 } else if (!strcmp("DaemonReady", property)) {
169 value = context->bmc_events & BMC_EVENT_DAEMON_READY;
170 } else {
171 MSG_ERR("Unknown DBus property: %s\n", property);
172 return -EINVAL;
173 }
174
175 return sd_bus_message_append(reply, "b", value);
176}
177
Andrew Jeffery23140be2018-09-05 14:15:07 +0930178static const sd_bus_vtable protocol_unversioned_vtable[] = {
179 SD_BUS_VTABLE_START(0),
180 SD_BUS_METHOD("GetInfo", "y", "yyq", &transport_dbus_get_info,
181 SD_BUS_VTABLE_UNPRIVILEGED),
182 SD_BUS_VTABLE_END
183};
184
185static const sd_bus_vtable protocol_v2_vtable[] = {
186 SD_BUS_VTABLE_START(0),
187 SD_BUS_METHOD("GetInfo", "y", "yyq", &transport_dbus_get_info,
188 SD_BUS_VTABLE_UNPRIVILEGED),
Andrew Jefferya6ca7a92018-08-20 13:03:44 +0930189 SD_BUS_PROPERTY("FlashControlLost", "b", transport_dbus_get_property,
190 0, /* Just a pointer to struct mbox_context */
191 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
192 SD_BUS_PROPERTY("DaemonReady", "b", transport_dbus_get_property,
193 0, /* Just a pointer to struct mbox_context */
194 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
195 SD_BUS_SIGNAL("ProtocolReset", NULL, 0),
196 SD_BUS_SIGNAL("WindowReset", NULL, 0),
Andrew Jeffery23140be2018-09-05 14:15:07 +0930197 SD_BUS_VTABLE_END
198};
199
200int transport_dbus_init(struct mbox_context *context)
201{
202 int rc;
203
204 rc = sd_bus_add_object_vtable(context->bus, NULL,
205 MBOX_DBUS_OBJECT,
206 MBOX_DBUS_PROTOCOL_IFACE,
207 protocol_unversioned_vtable,
208 context);
209 if (rc < 0) {
210 return rc;
211 }
212
213 rc = sd_bus_add_object_vtable(context->bus, NULL,
214 MBOX_DBUS_OBJECT,
Andrew Jefferya6ca7a92018-08-20 13:03:44 +0930215 MBOX_DBUS_PROTOCOL_IFACE_V2,
Andrew Jeffery23140be2018-09-05 14:15:07 +0930216 protocol_v2_vtable, context);
217
218 return rc;
219}
220
221#define __unused __attribute__((unused))
222void transport_dbus_free(struct mbox_context *context __unused)
223{
224 return;
225}