blob: 616aee33f59263afd12308ad0a6ae5e4929f3b7f [file] [log] [blame]
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +09301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
3
4#include "config.h"
5
6#include "hiomap.hpp"
7
8#include <endian.h>
9#include <host-ipmid/ipmid-api.h>
10#include <string.h>
11#include <systemd/sd-bus.h>
12
13#include <fstream>
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093014#include <functional>
15#include <host-ipmid/ipmid-host-cmd-utils.hpp>
16#include <host-ipmid/ipmid-host-cmd.hpp>
17#include <iostream>
18#include <phosphor-logging/log.hpp>
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093019#include <sdbusplus/bus.hpp>
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093020#include <sdbusplus/bus/match.hpp>
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093021#include <sdbusplus/exception.hpp>
22
23using namespace sdbusplus;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093024using namespace phosphor::host::command;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093025
26static void register_openpower_hiomap_commands() __attribute__((constructor));
27
28namespace openpower
29{
30namespace flash
31{
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093032constexpr auto BMC_EVENT_DAEMON_READY = 1 << 7;
33constexpr auto BMC_EVENT_FLASH_CTRL_LOST = 1 << 6;
34constexpr auto BMC_EVENT_WINDOW_RESET = 1 << 1;
35constexpr auto BMC_EVENT_PROTOCOL_RESET = 1 << 0;
36
37constexpr auto IPMI_CMD_HIOMAP_EVENT = 0x0f;
38
39constexpr auto HIOMAPD_SERVICE = "xyz.openbmc_project.Hiomapd";
40constexpr auto HIOMAPD_OBJECT = "/xyz/openbmc_project/Hiomapd";
41constexpr auto HIOMAPD_IFACE = "xyz.openbmc_project.Hiomapd.Protocol";
42constexpr auto HIOMAPD_IFACE_V2 = "xyz.openbmc_project.Hiomapd.Protocol.V2";
43
44constexpr auto DBUS_IFACE_PROPERTIES = "org.freedesktop.DBus.Properties";
45
46struct hiomap
47{
Patrick Venture5b355062018-10-31 14:42:42 -070048 bus::bus* bus;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093049
50 /* Signals */
Patrick Venture5b355062018-10-31 14:42:42 -070051 bus::match::match* properties;
52 bus::match::match* window_reset;
53 bus::match::match* bmc_reboot;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093054
55 /* Protocol state */
56 std::map<std::string, int> event_lookup;
57 uint8_t bmc_events;
Andrew Jeffery04d75132018-09-26 00:58:52 +093058 uint8_t seq;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093059};
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093060
61/* TODO: Replace get/put with packed structs and direct assignment */
Patrick Venture5b355062018-10-31 14:42:42 -070062template <typename T>
63static inline T get(void* buf)
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093064{
65 T t;
66 memcpy(&t, buf, sizeof(t));
67 return t;
68}
69
Patrick Venture5b355062018-10-31 14:42:42 -070070template <typename T>
71static inline void put(void* buf, T&& t)
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093072{
73 memcpy(buf, &t, sizeof(t));
74}
75
76typedef ipmi_ret_t (*hiomap_command)(ipmi_request_t req, ipmi_response_t resp,
77 ipmi_data_len_t data_len,
78 ipmi_context_t context);
79
80struct errno_cc_entry
81{
82 int err;
83 int cc;
84};
85
86static const errno_cc_entry errno_cc_map[] = {
87 {0, IPMI_CC_OK},
88 {EBUSY, IPMI_CC_BUSY},
89 {ENOTSUP, IPMI_CC_INVALID},
90 {ETIMEDOUT, 0xc3}, /* FIXME: Replace when defined in ipmid-api.h */
91 {ENOSPC, 0xc4}, /* FIXME: Replace when defined in ipmid-api.h */
92 {EINVAL, IPMI_CC_PARM_OUT_OF_RANGE},
93 {ENODEV, IPMI_CC_SENSOR_INVALID},
94 {EPERM, IPMI_CC_INSUFFICIENT_PRIVILEGE},
95 {EACCES, IPMI_CC_INSUFFICIENT_PRIVILEGE},
96 {-1, IPMI_CC_UNSPECIFIED_ERROR},
97};
98
99static int hiomap_xlate_errno(int err)
100{
Patrick Venture5b355062018-10-31 14:42:42 -0700101 const errno_cc_entry* entry = &errno_cc_map[0];
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930102
103 while (!(entry->err == err || entry->err == -1))
104 {
105 entry++;
106 }
107
108 return entry->cc;
109}
110
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930111static void ipmi_hiomap_event_response(IpmiCmdData cmd, bool status)
112{
113 using namespace phosphor::logging;
114
115 if (!status)
116 {
117 log<level::ERR>("Failed to deliver host command",
118 entry("SEL_COMMAND=%x:%x", cmd.first, cmd.second));
119 }
120}
121
Patrick Venture5b355062018-10-31 14:42:42 -0700122static int hiomap_handle_property_update(struct hiomap* ctx,
123 sdbusplus::message::message& msg)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930124{
125 std::map<std::string, sdbusplus::message::variant<bool>> msgData;
126
127 std::string iface;
128 msg.read(iface, msgData);
129
Patrick Venture5b355062018-10-31 14:42:42 -0700130 for (auto const& x : msgData)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930131 {
132 if (!ctx->event_lookup.count(x.first))
133 {
134 /* Unsupported event? */
135 continue;
136 }
137
138 uint8_t mask = ctx->event_lookup[x.first];
139 auto value = sdbusplus::message::variant_ns::get<bool>(x.second);
140
141 if (value)
142 {
143 ctx->bmc_events |= mask;
144 }
145 else
146 {
147 ctx->bmc_events &= ~mask;
148 }
149 }
150
151 auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events);
152
153 ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response));
154
155 return 0;
156}
157
Patrick Venture5b355062018-10-31 14:42:42 -0700158static bus::match::match hiomap_match_properties(struct hiomap* ctx)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930159{
160 auto properties =
161 bus::match::rules::propertiesChanged(HIOMAPD_OBJECT, HIOMAPD_IFACE_V2);
162
163 bus::match::match match(
164 *ctx->bus, properties,
165 std::bind(hiomap_handle_property_update, ctx, std::placeholders::_1));
166
167 return match;
168}
169
Patrick Venture5b355062018-10-31 14:42:42 -0700170static int hiomap_handle_signal_v2(struct hiomap* ctx, const char* name)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930171{
172 ctx->bmc_events |= ctx->event_lookup[name];
173
174 auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events);
175
176 ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response));
177
178 return 0;
179}
180
Patrick Venture5b355062018-10-31 14:42:42 -0700181static bus::match::match hiomap_match_signal_v2(struct hiomap* ctx,
182 const char* name)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930183{
184 using namespace bus::match;
185
186 auto signals = rules::type::signal() + rules::path(HIOMAPD_OBJECT) +
187 rules::interface(HIOMAPD_IFACE_V2) + rules::member(name);
188
189 bus::match::match match(*ctx->bus, signals,
190 std::bind(hiomap_handle_signal_v2, ctx, name));
191
192 return match;
193}
194
195static ipmi_ret_t hiomap_reset(ipmi_request_t request, ipmi_response_t response,
196 ipmi_data_len_t data_len, ipmi_context_t context)
197{
Patrick Venture5b355062018-10-31 14:42:42 -0700198 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930199
200 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
201 HIOMAPD_IFACE, "Reset");
202 try
203 {
204 ctx->bus->call(m);
205
206 *data_len = 0;
207 }
Patrick Venture5b355062018-10-31 14:42:42 -0700208 catch (const exception::SdBusError& e)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930209 {
210 return hiomap_xlate_errno(e.get_errno());
211 }
212
213 return IPMI_CC_OK;
214}
215
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930216static ipmi_ret_t hiomap_get_info(ipmi_request_t request,
217 ipmi_response_t response,
218 ipmi_data_len_t data_len,
219 ipmi_context_t context)
220{
Patrick Venture5b355062018-10-31 14:42:42 -0700221 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930222
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930223 if (*data_len < 1)
224 {
225 return IPMI_CC_REQ_DATA_LEN_INVALID;
226 }
227
Patrick Venture5b355062018-10-31 14:42:42 -0700228 uint8_t* reqdata = (uint8_t*)request;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930229 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
230 HIOMAPD_IFACE, "GetInfo");
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930231 m.append(reqdata[0]);
232
233 try
234 {
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930235 auto reply = ctx->bus->call(m);
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930236
237 uint8_t version;
238 uint8_t blockSizeShift;
239 uint16_t timeout;
240 reply.read(version, blockSizeShift, timeout);
241
Patrick Venture5b355062018-10-31 14:42:42 -0700242 uint8_t* respdata = (uint8_t*)response;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930243
244 /* FIXME: Assumes v2! */
245 put(&respdata[0], version);
246 put(&respdata[1], blockSizeShift);
247 put(&respdata[2], htole16(timeout));
248
249 *data_len = 4;
250 }
Patrick Venture5b355062018-10-31 14:42:42 -0700251 catch (const exception::SdBusError& e)
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930252 {
253 return hiomap_xlate_errno(e.get_errno());
254 }
255
256 return IPMI_CC_OK;
257}
258
Andrew Jefferydb688e92018-08-23 21:21:30 +0930259static ipmi_ret_t hiomap_get_flash_info(ipmi_request_t request,
260 ipmi_response_t response,
261 ipmi_data_len_t data_len,
262 ipmi_context_t context)
263{
Patrick Venture5b355062018-10-31 14:42:42 -0700264 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferydb688e92018-08-23 21:21:30 +0930265
266 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
267 HIOMAPD_IFACE_V2, "GetFlashInfo");
268 try
269 {
270 auto reply = ctx->bus->call(m);
271
272 uint16_t flashSize, eraseSize;
273 reply.read(flashSize, eraseSize);
274
Patrick Venture5b355062018-10-31 14:42:42 -0700275 uint8_t* respdata = (uint8_t*)response;
Andrew Jefferydb688e92018-08-23 21:21:30 +0930276 put(&respdata[0], htole16(flashSize));
277 put(&respdata[2], htole16(eraseSize));
278
279 *data_len = 4;
280 }
Patrick Venture5b355062018-10-31 14:42:42 -0700281 catch (const exception::SdBusError& e)
Andrew Jefferydb688e92018-08-23 21:21:30 +0930282 {
283 return hiomap_xlate_errno(e.get_errno());
284 }
285
286 return IPMI_CC_OK;
287}
288
Patrick Venture5b355062018-10-31 14:42:42 -0700289static ipmi_ret_t hiomap_create_window(struct hiomap* ctx, bool ro,
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930290 ipmi_request_t request,
291 ipmi_response_t response,
292 ipmi_data_len_t data_len)
293{
294 if (*data_len < 4)
295 {
296 return IPMI_CC_REQ_DATA_LEN_INVALID;
297 }
298
Patrick Venture5b355062018-10-31 14:42:42 -0700299 uint8_t* reqdata = (uint8_t*)request;
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930300 auto windowType = ro ? "CreateReadWindow" : "CreateWriteWindow";
301
302 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
303 HIOMAPD_IFACE_V2, windowType);
304 m.append(le16toh(get<uint16_t>(&reqdata[0])));
305 m.append(le16toh(get<uint16_t>(&reqdata[2])));
306
307 try
308 {
309 auto reply = ctx->bus->call(m);
310
311 uint16_t lpcAddress, size, offset;
312 reply.read(lpcAddress, size, offset);
313
Patrick Venture5b355062018-10-31 14:42:42 -0700314 uint8_t* respdata = (uint8_t*)response;
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930315
316 /* FIXME: Assumes v2! */
317 put(&respdata[0], htole16(lpcAddress));
318 put(&respdata[2], htole16(size));
319 put(&respdata[4], htole16(offset));
320
321 *data_len = 6;
322 }
Patrick Venture5b355062018-10-31 14:42:42 -0700323 catch (const exception::SdBusError& e)
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930324 {
325 return hiomap_xlate_errno(e.get_errno());
326 }
327
328 return IPMI_CC_OK;
329}
330
331static ipmi_ret_t hiomap_create_read_window(ipmi_request_t request,
332 ipmi_response_t response,
333 ipmi_data_len_t data_len,
334 ipmi_context_t context)
335{
Patrick Venture5b355062018-10-31 14:42:42 -0700336 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930337
338 return hiomap_create_window(ctx, true, request, response, data_len);
339}
340
341static ipmi_ret_t hiomap_create_write_window(ipmi_request_t request,
342 ipmi_response_t response,
343 ipmi_data_len_t data_len,
344 ipmi_context_t context)
345{
Patrick Venture5b355062018-10-31 14:42:42 -0700346 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930347
348 return hiomap_create_window(ctx, false, request, response, data_len);
349}
350
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930351static ipmi_ret_t hiomap_close_window(ipmi_request_t request,
352 ipmi_response_t response,
353 ipmi_data_len_t data_len,
354 ipmi_context_t context)
355{
Patrick Venture5b355062018-10-31 14:42:42 -0700356 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930357
358 if (*data_len < 1)
359 {
360 return IPMI_CC_REQ_DATA_LEN_INVALID;
361 }
362
Patrick Venture5b355062018-10-31 14:42:42 -0700363 uint8_t* reqdata = (uint8_t*)request;
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930364 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
365 HIOMAPD_IFACE_V2, "CloseWindow");
366 m.append(reqdata[0]);
367
368 try
369 {
370 auto reply = ctx->bus->call(m);
371
372 *data_len = 0;
373 }
Patrick Venture5b355062018-10-31 14:42:42 -0700374 catch (const exception::SdBusError& e)
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930375 {
376 return hiomap_xlate_errno(e.get_errno());
377 }
378
379 return IPMI_CC_OK;
380}
381
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930382static ipmi_ret_t hiomap_mark_dirty(ipmi_request_t request,
383 ipmi_response_t response,
384 ipmi_data_len_t data_len,
385 ipmi_context_t context)
386{
Patrick Venture5b355062018-10-31 14:42:42 -0700387 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930388
389 if (*data_len < 4)
390 {
391 return IPMI_CC_REQ_DATA_LEN_INVALID;
392 }
393
Patrick Venture5b355062018-10-31 14:42:42 -0700394 uint8_t* reqdata = (uint8_t*)request;
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930395 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
396 HIOMAPD_IFACE_V2, "MarkDirty");
397 /* FIXME: Assumes v2 */
398 m.append(le16toh(get<uint16_t>(&reqdata[0]))); /* offset */
399 m.append(le16toh(get<uint16_t>(&reqdata[2]))); /* size */
400
401 try
402 {
403 auto reply = ctx->bus->call(m);
404
405 *data_len = 0;
406 }
Patrick Venture5b355062018-10-31 14:42:42 -0700407 catch (const exception::SdBusError& e)
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930408 {
409 return hiomap_xlate_errno(e.get_errno());
410 }
411
412 return IPMI_CC_OK;
413}
414
Andrew Jeffery7b225fb2018-08-24 09:19:21 +0930415static ipmi_ret_t hiomap_flush(ipmi_request_t request, ipmi_response_t response,
416 ipmi_data_len_t data_len, ipmi_context_t context)
417{
Patrick Venture5b355062018-10-31 14:42:42 -0700418 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery7b225fb2018-08-24 09:19:21 +0930419
420 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
421 HIOMAPD_IFACE_V2, "Flush");
422
423 try
424 {
425 /* FIXME: No argument call assumes v2 */
426 auto reply = ctx->bus->call(m);
427
428 *data_len = 0;
429 }
Patrick Venture5b355062018-10-31 14:42:42 -0700430 catch (const exception::SdBusError& e)
Andrew Jeffery7b225fb2018-08-24 09:19:21 +0930431 {
432 return hiomap_xlate_errno(e.get_errno());
433 }
434
435 return IPMI_CC_OK;
436}
437
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930438static ipmi_ret_t hiomap_ack(ipmi_request_t request, ipmi_response_t response,
439 ipmi_data_len_t data_len, ipmi_context_t context)
440{
Patrick Venture5b355062018-10-31 14:42:42 -0700441 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930442
443 if (*data_len < 1)
444 {
445 return IPMI_CC_REQ_DATA_LEN_INVALID;
446 }
447
Patrick Venture5b355062018-10-31 14:42:42 -0700448 uint8_t* reqdata = (uint8_t*)request;
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930449 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
450 HIOMAPD_IFACE_V2, "Ack");
451 auto acked = reqdata[0];
452 m.append(acked);
453
454 try
455 {
456 auto reply = ctx->bus->call(m);
457
458 /* Update our cache: Necessary because the signals do not carry a value
459 */
460 ctx->bmc_events &= ~acked;
461
462 *data_len = 0;
463 }
Patrick Venture5b355062018-10-31 14:42:42 -0700464 catch (const exception::SdBusError& e)
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930465 {
466 return hiomap_xlate_errno(e.get_errno());
467 }
468
469 return IPMI_CC_OK;
470}
471
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930472static ipmi_ret_t hiomap_erase(ipmi_request_t request, ipmi_response_t response,
473 ipmi_data_len_t data_len, ipmi_context_t context)
474{
Patrick Venture5b355062018-10-31 14:42:42 -0700475 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930476
477 if (*data_len < 4)
478 {
479 return IPMI_CC_REQ_DATA_LEN_INVALID;
480 }
481
Patrick Venture5b355062018-10-31 14:42:42 -0700482 uint8_t* reqdata = (uint8_t*)request;
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930483 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
484 HIOMAPD_IFACE_V2, "Erase");
485 /* FIXME: Assumes v2 */
486 m.append(le16toh(get<uint16_t>(&reqdata[0]))); /* offset */
487 m.append(le16toh(get<uint16_t>(&reqdata[2]))); /* size */
488
489 try
490 {
491 auto reply = ctx->bus->call(m);
492
493 *data_len = 0;
494 }
Patrick Venture5b355062018-10-31 14:42:42 -0700495 catch (const exception::SdBusError& e)
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930496 {
497 return hiomap_xlate_errno(e.get_errno());
498 }
499
500 return IPMI_CC_OK;
501}
502
Andrew Jeffery04d75132018-09-26 00:58:52 +0930503#define HIOMAP_C_RESET 1
504#define HIOMAP_C_GET_INFO 2
505#define HIOMAP_C_GET_FLASH_INFO 3
506#define HIOMAP_C_CREATE_READ_WINDOW 4
507#define HIOMAP_C_CLOSE_WINDOW 5
508#define HIOMAP_C_CREATE_WRITE_WINDOW 6
509#define HIOMAP_C_MARK_DIRTY 7
510#define HIOMAP_C_FLUSH 8
511#define HIOMAP_C_ACK 9
512#define HIOMAP_C_ERASE 10
513
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930514static const hiomap_command hiomap_commands[] = {
Andrew Jeffery04d75132018-09-26 00:58:52 +0930515 [0] = NULL, /* Invalid command ID */
516 [HIOMAP_C_RESET] = hiomap_reset,
517 [HIOMAP_C_GET_INFO] = hiomap_get_info,
518 [HIOMAP_C_GET_FLASH_INFO] = hiomap_get_flash_info,
519 [HIOMAP_C_CREATE_READ_WINDOW] = hiomap_create_read_window,
520 [HIOMAP_C_CLOSE_WINDOW] = hiomap_close_window,
521 [HIOMAP_C_CREATE_WRITE_WINDOW] = hiomap_create_write_window,
522 [HIOMAP_C_MARK_DIRTY] = hiomap_mark_dirty,
523 [HIOMAP_C_FLUSH] = hiomap_flush,
524 [HIOMAP_C_ACK] = hiomap_ack,
525 [HIOMAP_C_ERASE] = hiomap_erase,
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930526};
527
528/* FIXME: Define this in the "right" place, wherever that is */
529/* FIXME: Double evaluation */
530#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
531
532static ipmi_ret_t hiomap_dispatch(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
533 ipmi_request_t request,
534 ipmi_response_t response,
535 ipmi_data_len_t data_len,
536 ipmi_context_t context)
537{
Patrick Venture5b355062018-10-31 14:42:42 -0700538 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930539
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930540 if (*data_len < 2)
541 {
542 *data_len = 0;
543 return IPMI_CC_REQ_DATA_LEN_INVALID;
544 }
545
Patrick Venture5b355062018-10-31 14:42:42 -0700546 uint8_t* ipmi_req = (uint8_t*)request;
547 uint8_t* ipmi_resp = (uint8_t*)response;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930548 uint8_t hiomap_cmd = ipmi_req[0];
549
550 if (hiomap_cmd == 0 || hiomap_cmd > ARRAY_SIZE(hiomap_commands) - 1)
551 {
552 *data_len = 0;
553 return IPMI_CC_PARM_OUT_OF_RANGE;
554 }
Andrew Jeffery04d75132018-09-26 00:58:52 +0930555
556 bool is_unversioned =
557 (hiomap_cmd == HIOMAP_C_RESET || hiomap_cmd == HIOMAP_C_GET_INFO ||
558 hiomap_cmd == HIOMAP_C_ACK);
559 if (!is_unversioned && ctx->seq == ipmi_req[1])
560 {
561 *data_len = 0;
562 return IPMI_CC_INVALID_FIELD_REQUEST;
563 }
564
565 ctx->seq = ipmi_req[1];
566
Patrick Venture5b355062018-10-31 14:42:42 -0700567 uint8_t* flash_req = ipmi_req + 2;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930568 size_t flash_len = *data_len - 2;
Patrick Venture5b355062018-10-31 14:42:42 -0700569 uint8_t* flash_resp = ipmi_resp + 2;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930570
571 ipmi_ret_t cc =
572 hiomap_commands[hiomap_cmd](flash_req, flash_resp, &flash_len, context);
573 if (cc != IPMI_CC_OK)
574 {
575 *data_len = 0;
576 return cc;
577 }
578
579 /* Populate the response command and sequence */
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930580 ipmi_resp[0] = hiomap_cmd;
Andrew Jeffery04d75132018-09-26 00:58:52 +0930581 ipmi_resp[1] = ctx->seq;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930582
583 *data_len = flash_len + 2;
584
585 return cc;
586}
587} // namespace flash
588} // namespace openpower
589
590static void register_openpower_hiomap_commands()
591{
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930592 using namespace openpower::flash;
593
594 /* FIXME: Clean this up? Can we unregister? */
Patrick Venture5b355062018-10-31 14:42:42 -0700595 struct hiomap* ctx = new hiomap();
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930596
597 /* Initialise mapping from signal and property names to status bit */
598 ctx->event_lookup["DaemonReady"] = BMC_EVENT_DAEMON_READY;
599 ctx->event_lookup["FlashControlLost"] = BMC_EVENT_FLASH_CTRL_LOST;
600 ctx->event_lookup["WindowReset"] = BMC_EVENT_WINDOW_RESET;
601 ctx->event_lookup["ProtocolReset"] = BMC_EVENT_PROTOCOL_RESET;
602
603 ctx->bus = new bus::bus(ipmid_get_sd_bus_connection());
604
605 /* Initialise signal handling */
606
607 /*
608 * Can't use temporaries here because that causes SEGFAULTs due to slot
609 * destruction (!?), so enjoy the weird wrapping.
610 */
611 ctx->properties =
612 new bus::match::match(std::move(hiomap_match_properties(ctx)));
613 ctx->bmc_reboot = new bus::match::match(
614 std::move(hiomap_match_signal_v2(ctx, "ProtocolReset")));
615 ctx->window_reset = new bus::match::match(
616 std::move(hiomap_match_signal_v2(ctx, "WindowReset")));
617
618 ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_HIOMAP, ctx,
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930619 openpower::flash::hiomap_dispatch, SYSTEM_INTERFACE);
620}