blob: 5d3408ef2a468b29e7e157e5af330fc075247a33 [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>
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093010
Patrick Ventureee701962018-10-31 14:51:37 -070011#include <cstring>
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093012#include <fstream>
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093013#include <functional>
14#include <host-ipmid/ipmid-host-cmd-utils.hpp>
15#include <host-ipmid/ipmid-host-cmd.hpp>
16#include <iostream>
Patrick Ventureee701962018-10-31 14:51:37 -070017#include <map>
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093018#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>
Patrick Ventureee701962018-10-31 14:51:37 -070022#include <string>
23#include <tuple>
24#include <utility>
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093025
26using namespace sdbusplus;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093027using namespace phosphor::host::command;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093028
29static void register_openpower_hiomap_commands() __attribute__((constructor));
30
31namespace openpower
32{
33namespace flash
34{
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093035constexpr auto BMC_EVENT_DAEMON_READY = 1 << 7;
36constexpr auto BMC_EVENT_FLASH_CTRL_LOST = 1 << 6;
37constexpr auto BMC_EVENT_WINDOW_RESET = 1 << 1;
38constexpr auto BMC_EVENT_PROTOCOL_RESET = 1 << 0;
39
40constexpr auto IPMI_CMD_HIOMAP_EVENT = 0x0f;
41
42constexpr auto HIOMAPD_SERVICE = "xyz.openbmc_project.Hiomapd";
43constexpr auto HIOMAPD_OBJECT = "/xyz/openbmc_project/Hiomapd";
44constexpr auto HIOMAPD_IFACE = "xyz.openbmc_project.Hiomapd.Protocol";
45constexpr auto HIOMAPD_IFACE_V2 = "xyz.openbmc_project.Hiomapd.Protocol.V2";
46
47constexpr auto DBUS_IFACE_PROPERTIES = "org.freedesktop.DBus.Properties";
48
49struct hiomap
50{
Patrick Venture5b355062018-10-31 14:42:42 -070051 bus::bus* bus;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093052
53 /* Signals */
Patrick Venture5b355062018-10-31 14:42:42 -070054 bus::match::match* properties;
55 bus::match::match* window_reset;
56 bus::match::match* bmc_reboot;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093057
58 /* Protocol state */
59 std::map<std::string, int> event_lookup;
60 uint8_t bmc_events;
Andrew Jeffery04d75132018-09-26 00:58:52 +093061 uint8_t seq;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +093062};
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093063
64/* TODO: Replace get/put with packed structs and direct assignment */
Patrick Venture5b355062018-10-31 14:42:42 -070065template <typename T>
66static inline T get(void* buf)
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093067{
68 T t;
Patrick Ventureee701962018-10-31 14:51:37 -070069 std::memcpy(&t, buf, sizeof(t));
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093070 return t;
71}
72
Patrick Venture5b355062018-10-31 14:42:42 -070073template <typename T>
74static inline void put(void* buf, T&& t)
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093075{
Patrick Ventureee701962018-10-31 14:51:37 -070076 std::memcpy(buf, &t, sizeof(t));
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +093077}
78
79typedef ipmi_ret_t (*hiomap_command)(ipmi_request_t req, ipmi_response_t resp,
80 ipmi_data_len_t data_len,
81 ipmi_context_t context);
82
83struct errno_cc_entry
84{
85 int err;
86 int cc;
87};
88
89static const errno_cc_entry errno_cc_map[] = {
90 {0, IPMI_CC_OK},
91 {EBUSY, IPMI_CC_BUSY},
92 {ENOTSUP, IPMI_CC_INVALID},
93 {ETIMEDOUT, 0xc3}, /* FIXME: Replace when defined in ipmid-api.h */
94 {ENOSPC, 0xc4}, /* FIXME: Replace when defined in ipmid-api.h */
95 {EINVAL, IPMI_CC_PARM_OUT_OF_RANGE},
96 {ENODEV, IPMI_CC_SENSOR_INVALID},
97 {EPERM, IPMI_CC_INSUFFICIENT_PRIVILEGE},
98 {EACCES, IPMI_CC_INSUFFICIENT_PRIVILEGE},
99 {-1, IPMI_CC_UNSPECIFIED_ERROR},
100};
101
102static int hiomap_xlate_errno(int err)
103{
Patrick Venture5b355062018-10-31 14:42:42 -0700104 const errno_cc_entry* entry = &errno_cc_map[0];
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930105
106 while (!(entry->err == err || entry->err == -1))
107 {
108 entry++;
109 }
110
111 return entry->cc;
112}
113
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930114static void ipmi_hiomap_event_response(IpmiCmdData cmd, bool status)
115{
116 using namespace phosphor::logging;
117
118 if (!status)
119 {
120 log<level::ERR>("Failed to deliver host command",
121 entry("SEL_COMMAND=%x:%x", cmd.first, cmd.second));
122 }
123}
124
Patrick Venture5b355062018-10-31 14:42:42 -0700125static int hiomap_handle_property_update(struct hiomap* ctx,
126 sdbusplus::message::message& msg)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930127{
128 std::map<std::string, sdbusplus::message::variant<bool>> msgData;
129
130 std::string iface;
131 msg.read(iface, msgData);
132
Patrick Venture5b355062018-10-31 14:42:42 -0700133 for (auto const& x : msgData)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930134 {
135 if (!ctx->event_lookup.count(x.first))
136 {
137 /* Unsupported event? */
138 continue;
139 }
140
141 uint8_t mask = ctx->event_lookup[x.first];
142 auto value = sdbusplus::message::variant_ns::get<bool>(x.second);
143
144 if (value)
145 {
146 ctx->bmc_events |= mask;
147 }
148 else
149 {
150 ctx->bmc_events &= ~mask;
151 }
152 }
153
154 auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events);
155
156 ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response));
157
158 return 0;
159}
160
Patrick Venture5b355062018-10-31 14:42:42 -0700161static bus::match::match hiomap_match_properties(struct hiomap* ctx)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930162{
163 auto properties =
164 bus::match::rules::propertiesChanged(HIOMAPD_OBJECT, HIOMAPD_IFACE_V2);
165
166 bus::match::match match(
167 *ctx->bus, properties,
168 std::bind(hiomap_handle_property_update, ctx, std::placeholders::_1));
169
170 return match;
171}
172
Patrick Venture5b355062018-10-31 14:42:42 -0700173static int hiomap_handle_signal_v2(struct hiomap* ctx, const char* name)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930174{
175 ctx->bmc_events |= ctx->event_lookup[name];
176
177 auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events);
178
179 ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response));
180
181 return 0;
182}
183
Patrick Venture5b355062018-10-31 14:42:42 -0700184static bus::match::match hiomap_match_signal_v2(struct hiomap* ctx,
185 const char* name)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930186{
187 using namespace bus::match;
188
189 auto signals = rules::type::signal() + rules::path(HIOMAPD_OBJECT) +
190 rules::interface(HIOMAPD_IFACE_V2) + rules::member(name);
191
192 bus::match::match match(*ctx->bus, signals,
193 std::bind(hiomap_handle_signal_v2, ctx, name));
194
195 return match;
196}
197
198static ipmi_ret_t hiomap_reset(ipmi_request_t request, ipmi_response_t response,
199 ipmi_data_len_t data_len, ipmi_context_t context)
200{
Patrick Venture5b355062018-10-31 14:42:42 -0700201 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930202
203 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
204 HIOMAPD_IFACE, "Reset");
205 try
206 {
207 ctx->bus->call(m);
208
209 *data_len = 0;
210 }
Patrick Venture5b355062018-10-31 14:42:42 -0700211 catch (const exception::SdBusError& e)
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930212 {
213 return hiomap_xlate_errno(e.get_errno());
214 }
215
216 return IPMI_CC_OK;
217}
218
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930219static ipmi_ret_t hiomap_get_info(ipmi_request_t request,
220 ipmi_response_t response,
221 ipmi_data_len_t data_len,
222 ipmi_context_t context)
223{
Patrick Venture5b355062018-10-31 14:42:42 -0700224 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930225
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930226 if (*data_len < 1)
227 {
228 return IPMI_CC_REQ_DATA_LEN_INVALID;
229 }
230
Patrick Venture5b355062018-10-31 14:42:42 -0700231 uint8_t* reqdata = (uint8_t*)request;
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930232 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
233 HIOMAPD_IFACE, "GetInfo");
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930234 m.append(reqdata[0]);
235
236 try
237 {
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930238 auto reply = ctx->bus->call(m);
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930239
240 uint8_t version;
241 uint8_t blockSizeShift;
242 uint16_t timeout;
243 reply.read(version, blockSizeShift, timeout);
244
Patrick Venture5b355062018-10-31 14:42:42 -0700245 uint8_t* respdata = (uint8_t*)response;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930246
247 /* FIXME: Assumes v2! */
248 put(&respdata[0], version);
249 put(&respdata[1], blockSizeShift);
250 put(&respdata[2], htole16(timeout));
251
252 *data_len = 4;
253 }
Patrick Venture5b355062018-10-31 14:42:42 -0700254 catch (const exception::SdBusError& e)
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930255 {
256 return hiomap_xlate_errno(e.get_errno());
257 }
258
259 return IPMI_CC_OK;
260}
261
Andrew Jefferydb688e92018-08-23 21:21:30 +0930262static ipmi_ret_t hiomap_get_flash_info(ipmi_request_t request,
263 ipmi_response_t response,
264 ipmi_data_len_t data_len,
265 ipmi_context_t context)
266{
Patrick Venture5b355062018-10-31 14:42:42 -0700267 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferydb688e92018-08-23 21:21:30 +0930268
269 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
270 HIOMAPD_IFACE_V2, "GetFlashInfo");
271 try
272 {
273 auto reply = ctx->bus->call(m);
274
275 uint16_t flashSize, eraseSize;
276 reply.read(flashSize, eraseSize);
277
Patrick Venture5b355062018-10-31 14:42:42 -0700278 uint8_t* respdata = (uint8_t*)response;
Andrew Jefferydb688e92018-08-23 21:21:30 +0930279 put(&respdata[0], htole16(flashSize));
280 put(&respdata[2], htole16(eraseSize));
281
282 *data_len = 4;
283 }
Patrick Venture5b355062018-10-31 14:42:42 -0700284 catch (const exception::SdBusError& e)
Andrew Jefferydb688e92018-08-23 21:21:30 +0930285 {
286 return hiomap_xlate_errno(e.get_errno());
287 }
288
289 return IPMI_CC_OK;
290}
291
Patrick Venture5b355062018-10-31 14:42:42 -0700292static ipmi_ret_t hiomap_create_window(struct hiomap* ctx, bool ro,
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930293 ipmi_request_t request,
294 ipmi_response_t response,
295 ipmi_data_len_t data_len)
296{
297 if (*data_len < 4)
298 {
299 return IPMI_CC_REQ_DATA_LEN_INVALID;
300 }
301
Patrick Venture5b355062018-10-31 14:42:42 -0700302 uint8_t* reqdata = (uint8_t*)request;
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930303 auto windowType = ro ? "CreateReadWindow" : "CreateWriteWindow";
304
305 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
306 HIOMAPD_IFACE_V2, windowType);
307 m.append(le16toh(get<uint16_t>(&reqdata[0])));
308 m.append(le16toh(get<uint16_t>(&reqdata[2])));
309
310 try
311 {
312 auto reply = ctx->bus->call(m);
313
314 uint16_t lpcAddress, size, offset;
315 reply.read(lpcAddress, size, offset);
316
Patrick Venture5b355062018-10-31 14:42:42 -0700317 uint8_t* respdata = (uint8_t*)response;
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930318
319 /* FIXME: Assumes v2! */
320 put(&respdata[0], htole16(lpcAddress));
321 put(&respdata[2], htole16(size));
322 put(&respdata[4], htole16(offset));
323
324 *data_len = 6;
325 }
Patrick Venture5b355062018-10-31 14:42:42 -0700326 catch (const exception::SdBusError& e)
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930327 {
328 return hiomap_xlate_errno(e.get_errno());
329 }
330
331 return IPMI_CC_OK;
332}
333
334static ipmi_ret_t hiomap_create_read_window(ipmi_request_t request,
335 ipmi_response_t response,
336 ipmi_data_len_t data_len,
337 ipmi_context_t context)
338{
Patrick Venture5b355062018-10-31 14:42:42 -0700339 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930340
341 return hiomap_create_window(ctx, true, request, response, data_len);
342}
343
344static ipmi_ret_t hiomap_create_write_window(ipmi_request_t request,
345 ipmi_response_t response,
346 ipmi_data_len_t data_len,
347 ipmi_context_t context)
348{
Patrick Venture5b355062018-10-31 14:42:42 -0700349 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferya00f59b2018-08-23 22:25:49 +0930350
351 return hiomap_create_window(ctx, false, request, response, data_len);
352}
353
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930354static ipmi_ret_t hiomap_close_window(ipmi_request_t request,
355 ipmi_response_t response,
356 ipmi_data_len_t data_len,
357 ipmi_context_t context)
358{
Patrick Venture5b355062018-10-31 14:42:42 -0700359 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930360
361 if (*data_len < 1)
362 {
363 return IPMI_CC_REQ_DATA_LEN_INVALID;
364 }
365
Patrick Venture5b355062018-10-31 14:42:42 -0700366 uint8_t* reqdata = (uint8_t*)request;
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930367 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
368 HIOMAPD_IFACE_V2, "CloseWindow");
369 m.append(reqdata[0]);
370
371 try
372 {
373 auto reply = ctx->bus->call(m);
374
375 *data_len = 0;
376 }
Patrick Venture5b355062018-10-31 14:42:42 -0700377 catch (const exception::SdBusError& e)
Andrew Jefferyb52822c2018-08-23 23:01:39 +0930378 {
379 return hiomap_xlate_errno(e.get_errno());
380 }
381
382 return IPMI_CC_OK;
383}
384
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930385static ipmi_ret_t hiomap_mark_dirty(ipmi_request_t request,
386 ipmi_response_t response,
387 ipmi_data_len_t data_len,
388 ipmi_context_t context)
389{
Patrick Venture5b355062018-10-31 14:42:42 -0700390 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930391
392 if (*data_len < 4)
393 {
394 return IPMI_CC_REQ_DATA_LEN_INVALID;
395 }
396
Patrick Venture5b355062018-10-31 14:42:42 -0700397 uint8_t* reqdata = (uint8_t*)request;
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930398 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
399 HIOMAPD_IFACE_V2, "MarkDirty");
400 /* FIXME: Assumes v2 */
401 m.append(le16toh(get<uint16_t>(&reqdata[0]))); /* offset */
402 m.append(le16toh(get<uint16_t>(&reqdata[2]))); /* size */
403
404 try
405 {
406 auto reply = ctx->bus->call(m);
407
408 *data_len = 0;
409 }
Patrick Venture5b355062018-10-31 14:42:42 -0700410 catch (const exception::SdBusError& e)
Andrew Jeffery9847f1c2018-08-24 09:13:40 +0930411 {
412 return hiomap_xlate_errno(e.get_errno());
413 }
414
415 return IPMI_CC_OK;
416}
417
Andrew Jeffery7b225fb2018-08-24 09:19:21 +0930418static ipmi_ret_t hiomap_flush(ipmi_request_t request, ipmi_response_t response,
419 ipmi_data_len_t data_len, ipmi_context_t context)
420{
Patrick Venture5b355062018-10-31 14:42:42 -0700421 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery7b225fb2018-08-24 09:19:21 +0930422
423 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
424 HIOMAPD_IFACE_V2, "Flush");
425
426 try
427 {
428 /* FIXME: No argument call assumes v2 */
429 auto reply = ctx->bus->call(m);
430
431 *data_len = 0;
432 }
Patrick Venture5b355062018-10-31 14:42:42 -0700433 catch (const exception::SdBusError& e)
Andrew Jeffery7b225fb2018-08-24 09:19:21 +0930434 {
435 return hiomap_xlate_errno(e.get_errno());
436 }
437
438 return IPMI_CC_OK;
439}
440
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930441static ipmi_ret_t hiomap_ack(ipmi_request_t request, ipmi_response_t response,
442 ipmi_data_len_t data_len, ipmi_context_t context)
443{
Patrick Venture5b355062018-10-31 14:42:42 -0700444 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930445
446 if (*data_len < 1)
447 {
448 return IPMI_CC_REQ_DATA_LEN_INVALID;
449 }
450
Patrick Venture5b355062018-10-31 14:42:42 -0700451 uint8_t* reqdata = (uint8_t*)request;
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930452 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
453 HIOMAPD_IFACE_V2, "Ack");
454 auto acked = reqdata[0];
455 m.append(acked);
456
457 try
458 {
459 auto reply = ctx->bus->call(m);
460
461 /* Update our cache: Necessary because the signals do not carry a value
462 */
463 ctx->bmc_events &= ~acked;
464
465 *data_len = 0;
466 }
Patrick Venture5b355062018-10-31 14:42:42 -0700467 catch (const exception::SdBusError& e)
Andrew Jeffery99f277a2018-08-24 09:24:04 +0930468 {
469 return hiomap_xlate_errno(e.get_errno());
470 }
471
472 return IPMI_CC_OK;
473}
474
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930475static ipmi_ret_t hiomap_erase(ipmi_request_t request, ipmi_response_t response,
476 ipmi_data_len_t data_len, ipmi_context_t context)
477{
Patrick Venture5b355062018-10-31 14:42:42 -0700478 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930479
480 if (*data_len < 4)
481 {
482 return IPMI_CC_REQ_DATA_LEN_INVALID;
483 }
484
Patrick Venture5b355062018-10-31 14:42:42 -0700485 uint8_t* reqdata = (uint8_t*)request;
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930486 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
487 HIOMAPD_IFACE_V2, "Erase");
488 /* FIXME: Assumes v2 */
489 m.append(le16toh(get<uint16_t>(&reqdata[0]))); /* offset */
490 m.append(le16toh(get<uint16_t>(&reqdata[2]))); /* size */
491
492 try
493 {
494 auto reply = ctx->bus->call(m);
495
496 *data_len = 0;
497 }
Patrick Venture5b355062018-10-31 14:42:42 -0700498 catch (const exception::SdBusError& e)
Andrew Jefferya1e35b82018-08-24 09:39:10 +0930499 {
500 return hiomap_xlate_errno(e.get_errno());
501 }
502
503 return IPMI_CC_OK;
504}
505
Andrew Jeffery04d75132018-09-26 00:58:52 +0930506#define HIOMAP_C_RESET 1
507#define HIOMAP_C_GET_INFO 2
508#define HIOMAP_C_GET_FLASH_INFO 3
509#define HIOMAP_C_CREATE_READ_WINDOW 4
510#define HIOMAP_C_CLOSE_WINDOW 5
511#define HIOMAP_C_CREATE_WRITE_WINDOW 6
512#define HIOMAP_C_MARK_DIRTY 7
513#define HIOMAP_C_FLUSH 8
514#define HIOMAP_C_ACK 9
515#define HIOMAP_C_ERASE 10
516
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930517static const hiomap_command hiomap_commands[] = {
Andrew Jeffery04d75132018-09-26 00:58:52 +0930518 [0] = NULL, /* Invalid command ID */
519 [HIOMAP_C_RESET] = hiomap_reset,
520 [HIOMAP_C_GET_INFO] = hiomap_get_info,
521 [HIOMAP_C_GET_FLASH_INFO] = hiomap_get_flash_info,
522 [HIOMAP_C_CREATE_READ_WINDOW] = hiomap_create_read_window,
523 [HIOMAP_C_CLOSE_WINDOW] = hiomap_close_window,
524 [HIOMAP_C_CREATE_WRITE_WINDOW] = hiomap_create_write_window,
525 [HIOMAP_C_MARK_DIRTY] = hiomap_mark_dirty,
526 [HIOMAP_C_FLUSH] = hiomap_flush,
527 [HIOMAP_C_ACK] = hiomap_ack,
528 [HIOMAP_C_ERASE] = hiomap_erase,
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930529};
530
531/* FIXME: Define this in the "right" place, wherever that is */
532/* FIXME: Double evaluation */
533#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
534
535static ipmi_ret_t hiomap_dispatch(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
536 ipmi_request_t request,
537 ipmi_response_t response,
538 ipmi_data_len_t data_len,
539 ipmi_context_t context)
540{
Patrick Venture5b355062018-10-31 14:42:42 -0700541 struct hiomap* ctx = static_cast<struct hiomap*>(context);
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930542
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930543 if (*data_len < 2)
544 {
545 *data_len = 0;
546 return IPMI_CC_REQ_DATA_LEN_INVALID;
547 }
548
Patrick Venture5b355062018-10-31 14:42:42 -0700549 uint8_t* ipmi_req = (uint8_t*)request;
550 uint8_t* ipmi_resp = (uint8_t*)response;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930551 uint8_t hiomap_cmd = ipmi_req[0];
552
553 if (hiomap_cmd == 0 || hiomap_cmd > ARRAY_SIZE(hiomap_commands) - 1)
554 {
555 *data_len = 0;
556 return IPMI_CC_PARM_OUT_OF_RANGE;
557 }
Andrew Jeffery04d75132018-09-26 00:58:52 +0930558
559 bool is_unversioned =
560 (hiomap_cmd == HIOMAP_C_RESET || hiomap_cmd == HIOMAP_C_GET_INFO ||
561 hiomap_cmd == HIOMAP_C_ACK);
562 if (!is_unversioned && ctx->seq == ipmi_req[1])
563 {
564 *data_len = 0;
565 return IPMI_CC_INVALID_FIELD_REQUEST;
566 }
567
568 ctx->seq = ipmi_req[1];
569
Patrick Venture5b355062018-10-31 14:42:42 -0700570 uint8_t* flash_req = ipmi_req + 2;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930571 size_t flash_len = *data_len - 2;
Patrick Venture5b355062018-10-31 14:42:42 -0700572 uint8_t* flash_resp = ipmi_resp + 2;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930573
574 ipmi_ret_t cc =
575 hiomap_commands[hiomap_cmd](flash_req, flash_resp, &flash_len, context);
576 if (cc != IPMI_CC_OK)
577 {
578 *data_len = 0;
579 return cc;
580 }
581
582 /* Populate the response command and sequence */
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930583 ipmi_resp[0] = hiomap_cmd;
Andrew Jeffery04d75132018-09-26 00:58:52 +0930584 ipmi_resp[1] = ctx->seq;
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930585
586 *data_len = flash_len + 2;
587
588 return cc;
589}
590} // namespace flash
591} // namespace openpower
592
593static void register_openpower_hiomap_commands()
594{
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930595 using namespace openpower::flash;
596
597 /* FIXME: Clean this up? Can we unregister? */
Patrick Venture5b355062018-10-31 14:42:42 -0700598 struct hiomap* ctx = new hiomap();
Andrew Jeffery0a3358e2018-08-21 10:42:09 +0930599
600 /* Initialise mapping from signal and property names to status bit */
601 ctx->event_lookup["DaemonReady"] = BMC_EVENT_DAEMON_READY;
602 ctx->event_lookup["FlashControlLost"] = BMC_EVENT_FLASH_CTRL_LOST;
603 ctx->event_lookup["WindowReset"] = BMC_EVENT_WINDOW_RESET;
604 ctx->event_lookup["ProtocolReset"] = BMC_EVENT_PROTOCOL_RESET;
605
606 ctx->bus = new bus::bus(ipmid_get_sd_bus_connection());
607
608 /* Initialise signal handling */
609
610 /*
611 * Can't use temporaries here because that causes SEGFAULTs due to slot
612 * destruction (!?), so enjoy the weird wrapping.
613 */
614 ctx->properties =
615 new bus::match::match(std::move(hiomap_match_properties(ctx)));
616 ctx->bmc_reboot = new bus::match::match(
617 std::move(hiomap_match_signal_v2(ctx, "ProtocolReset")));
618 ctx->window_reset = new bus::match::match(
619 std::move(hiomap_match_signal_v2(ctx, "WindowReset")));
620
621 ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_HIOMAP, ctx,
Andrew Jeffery2c07f6f2018-08-10 16:24:32 +0930622 openpower::flash::hiomap_dispatch, SYSTEM_INTERFACE);
623}