12c07f6f0SAndrew Jeffery // SPDX-License-Identifier: Apache-2.0 22c07f6f0SAndrew Jeffery // Copyright (C) 2018 IBM Corp. 32c07f6f0SAndrew Jeffery 42c07f6f0SAndrew Jeffery #include "config.h" 52c07f6f0SAndrew Jeffery 62c07f6f0SAndrew Jeffery #include "hiomap.hpp" 72c07f6f0SAndrew Jeffery 82c07f6f0SAndrew Jeffery #include <endian.h> 92c07f6f0SAndrew Jeffery #include <host-ipmid/ipmid-api.h> 102c07f6f0SAndrew Jeffery #include <string.h> 112c07f6f0SAndrew Jeffery #include <systemd/sd-bus.h> 122c07f6f0SAndrew Jeffery 132c07f6f0SAndrew Jeffery #include <fstream> 140a3358e7SAndrew Jeffery #include <functional> 150a3358e7SAndrew Jeffery #include <host-ipmid/ipmid-host-cmd-utils.hpp> 160a3358e7SAndrew Jeffery #include <host-ipmid/ipmid-host-cmd.hpp> 170a3358e7SAndrew Jeffery #include <iostream> 180a3358e7SAndrew Jeffery #include <phosphor-logging/log.hpp> 192c07f6f0SAndrew Jeffery #include <sdbusplus/bus.hpp> 200a3358e7SAndrew Jeffery #include <sdbusplus/bus/match.hpp> 212c07f6f0SAndrew Jeffery #include <sdbusplus/exception.hpp> 222c07f6f0SAndrew Jeffery 232c07f6f0SAndrew Jeffery using namespace sdbusplus; 240a3358e7SAndrew Jeffery using namespace phosphor::host::command; 252c07f6f0SAndrew Jeffery 262c07f6f0SAndrew Jeffery static void register_openpower_hiomap_commands() __attribute__((constructor)); 272c07f6f0SAndrew Jeffery 282c07f6f0SAndrew Jeffery namespace openpower 292c07f6f0SAndrew Jeffery { 302c07f6f0SAndrew Jeffery namespace flash 312c07f6f0SAndrew Jeffery { 320a3358e7SAndrew Jeffery constexpr auto BMC_EVENT_DAEMON_READY = 1 << 7; 330a3358e7SAndrew Jeffery constexpr auto BMC_EVENT_FLASH_CTRL_LOST = 1 << 6; 340a3358e7SAndrew Jeffery constexpr auto BMC_EVENT_WINDOW_RESET = 1 << 1; 350a3358e7SAndrew Jeffery constexpr auto BMC_EVENT_PROTOCOL_RESET = 1 << 0; 360a3358e7SAndrew Jeffery 370a3358e7SAndrew Jeffery constexpr auto IPMI_CMD_HIOMAP_EVENT = 0x0f; 380a3358e7SAndrew Jeffery 390a3358e7SAndrew Jeffery constexpr auto HIOMAPD_SERVICE = "xyz.openbmc_project.Hiomapd"; 400a3358e7SAndrew Jeffery constexpr auto HIOMAPD_OBJECT = "/xyz/openbmc_project/Hiomapd"; 410a3358e7SAndrew Jeffery constexpr auto HIOMAPD_IFACE = "xyz.openbmc_project.Hiomapd.Protocol"; 420a3358e7SAndrew Jeffery constexpr auto HIOMAPD_IFACE_V2 = "xyz.openbmc_project.Hiomapd.Protocol.V2"; 430a3358e7SAndrew Jeffery 440a3358e7SAndrew Jeffery constexpr auto DBUS_IFACE_PROPERTIES = "org.freedesktop.DBus.Properties"; 450a3358e7SAndrew Jeffery 460a3358e7SAndrew Jeffery struct hiomap 470a3358e7SAndrew Jeffery { 480a3358e7SAndrew Jeffery bus::bus *bus; 490a3358e7SAndrew Jeffery 500a3358e7SAndrew Jeffery /* Signals */ 510a3358e7SAndrew Jeffery bus::match::match *properties; 520a3358e7SAndrew Jeffery bus::match::match *window_reset; 530a3358e7SAndrew Jeffery bus::match::match *bmc_reboot; 540a3358e7SAndrew Jeffery 550a3358e7SAndrew Jeffery /* Protocol state */ 560a3358e7SAndrew Jeffery std::map<std::string, int> event_lookup; 570a3358e7SAndrew Jeffery uint8_t bmc_events; 580a3358e7SAndrew Jeffery }; 592c07f6f0SAndrew Jeffery 602c07f6f0SAndrew Jeffery /* TODO: Replace get/put with packed structs and direct assignment */ 612c07f6f0SAndrew Jeffery template <typename T> static inline T get(void *buf) 622c07f6f0SAndrew Jeffery { 632c07f6f0SAndrew Jeffery T t; 642c07f6f0SAndrew Jeffery memcpy(&t, buf, sizeof(t)); 652c07f6f0SAndrew Jeffery return t; 662c07f6f0SAndrew Jeffery } 672c07f6f0SAndrew Jeffery 682c07f6f0SAndrew Jeffery template <typename T> static inline void put(void *buf, T &&t) 692c07f6f0SAndrew Jeffery { 702c07f6f0SAndrew Jeffery memcpy(buf, &t, sizeof(t)); 712c07f6f0SAndrew Jeffery } 722c07f6f0SAndrew Jeffery 732c07f6f0SAndrew Jeffery typedef ipmi_ret_t (*hiomap_command)(ipmi_request_t req, ipmi_response_t resp, 742c07f6f0SAndrew Jeffery ipmi_data_len_t data_len, 752c07f6f0SAndrew Jeffery ipmi_context_t context); 762c07f6f0SAndrew Jeffery 772c07f6f0SAndrew Jeffery struct errno_cc_entry 782c07f6f0SAndrew Jeffery { 792c07f6f0SAndrew Jeffery int err; 802c07f6f0SAndrew Jeffery int cc; 812c07f6f0SAndrew Jeffery }; 822c07f6f0SAndrew Jeffery 832c07f6f0SAndrew Jeffery static const errno_cc_entry errno_cc_map[] = { 842c07f6f0SAndrew Jeffery {0, IPMI_CC_OK}, 852c07f6f0SAndrew Jeffery {EBUSY, IPMI_CC_BUSY}, 862c07f6f0SAndrew Jeffery {ENOTSUP, IPMI_CC_INVALID}, 872c07f6f0SAndrew Jeffery {ETIMEDOUT, 0xc3}, /* FIXME: Replace when defined in ipmid-api.h */ 882c07f6f0SAndrew Jeffery {ENOSPC, 0xc4}, /* FIXME: Replace when defined in ipmid-api.h */ 892c07f6f0SAndrew Jeffery {EINVAL, IPMI_CC_PARM_OUT_OF_RANGE}, 902c07f6f0SAndrew Jeffery {ENODEV, IPMI_CC_SENSOR_INVALID}, 912c07f6f0SAndrew Jeffery {EPERM, IPMI_CC_INSUFFICIENT_PRIVILEGE}, 922c07f6f0SAndrew Jeffery {EACCES, IPMI_CC_INSUFFICIENT_PRIVILEGE}, 932c07f6f0SAndrew Jeffery {-1, IPMI_CC_UNSPECIFIED_ERROR}, 942c07f6f0SAndrew Jeffery }; 952c07f6f0SAndrew Jeffery 962c07f6f0SAndrew Jeffery static int hiomap_xlate_errno(int err) 972c07f6f0SAndrew Jeffery { 982c07f6f0SAndrew Jeffery const errno_cc_entry *entry = &errno_cc_map[0]; 992c07f6f0SAndrew Jeffery 1002c07f6f0SAndrew Jeffery while (!(entry->err == err || entry->err == -1)) 1012c07f6f0SAndrew Jeffery { 1022c07f6f0SAndrew Jeffery entry++; 1032c07f6f0SAndrew Jeffery } 1042c07f6f0SAndrew Jeffery 1052c07f6f0SAndrew Jeffery return entry->cc; 1062c07f6f0SAndrew Jeffery } 1072c07f6f0SAndrew Jeffery 1080a3358e7SAndrew Jeffery static void ipmi_hiomap_event_response(IpmiCmdData cmd, bool status) 1090a3358e7SAndrew Jeffery { 1100a3358e7SAndrew Jeffery using namespace phosphor::logging; 1110a3358e7SAndrew Jeffery 1120a3358e7SAndrew Jeffery if (!status) 1130a3358e7SAndrew Jeffery { 1140a3358e7SAndrew Jeffery log<level::ERR>("Failed to deliver host command", 1150a3358e7SAndrew Jeffery entry("SEL_COMMAND=%x:%x", cmd.first, cmd.second)); 1160a3358e7SAndrew Jeffery } 1170a3358e7SAndrew Jeffery } 1180a3358e7SAndrew Jeffery 1190a3358e7SAndrew Jeffery static int hiomap_handle_property_update(struct hiomap *ctx, 1200a3358e7SAndrew Jeffery sdbusplus::message::message &msg) 1210a3358e7SAndrew Jeffery { 1220a3358e7SAndrew Jeffery std::map<std::string, sdbusplus::message::variant<bool>> msgData; 1230a3358e7SAndrew Jeffery 1240a3358e7SAndrew Jeffery std::string iface; 1250a3358e7SAndrew Jeffery msg.read(iface, msgData); 1260a3358e7SAndrew Jeffery 1270a3358e7SAndrew Jeffery for (auto const &x : msgData) 1280a3358e7SAndrew Jeffery { 1290a3358e7SAndrew Jeffery if (!ctx->event_lookup.count(x.first)) 1300a3358e7SAndrew Jeffery { 1310a3358e7SAndrew Jeffery /* Unsupported event? */ 1320a3358e7SAndrew Jeffery continue; 1330a3358e7SAndrew Jeffery } 1340a3358e7SAndrew Jeffery 1350a3358e7SAndrew Jeffery uint8_t mask = ctx->event_lookup[x.first]; 1360a3358e7SAndrew Jeffery auto value = sdbusplus::message::variant_ns::get<bool>(x.second); 1370a3358e7SAndrew Jeffery 1380a3358e7SAndrew Jeffery if (value) 1390a3358e7SAndrew Jeffery { 1400a3358e7SAndrew Jeffery ctx->bmc_events |= mask; 1410a3358e7SAndrew Jeffery } 1420a3358e7SAndrew Jeffery else 1430a3358e7SAndrew Jeffery { 1440a3358e7SAndrew Jeffery ctx->bmc_events &= ~mask; 1450a3358e7SAndrew Jeffery } 1460a3358e7SAndrew Jeffery } 1470a3358e7SAndrew Jeffery 1480a3358e7SAndrew Jeffery auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events); 1490a3358e7SAndrew Jeffery 1500a3358e7SAndrew Jeffery ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response)); 1510a3358e7SAndrew Jeffery 1520a3358e7SAndrew Jeffery return 0; 1530a3358e7SAndrew Jeffery } 1540a3358e7SAndrew Jeffery 1550a3358e7SAndrew Jeffery static bus::match::match hiomap_match_properties(struct hiomap *ctx) 1560a3358e7SAndrew Jeffery { 1570a3358e7SAndrew Jeffery auto properties = 1580a3358e7SAndrew Jeffery bus::match::rules::propertiesChanged(HIOMAPD_OBJECT, HIOMAPD_IFACE_V2); 1590a3358e7SAndrew Jeffery 1600a3358e7SAndrew Jeffery bus::match::match match( 1610a3358e7SAndrew Jeffery *ctx->bus, properties, 1620a3358e7SAndrew Jeffery std::bind(hiomap_handle_property_update, ctx, std::placeholders::_1)); 1630a3358e7SAndrew Jeffery 1640a3358e7SAndrew Jeffery return match; 1650a3358e7SAndrew Jeffery } 1660a3358e7SAndrew Jeffery 1670a3358e7SAndrew Jeffery static int hiomap_handle_signal_v2(struct hiomap *ctx, const char *name) 1680a3358e7SAndrew Jeffery { 1690a3358e7SAndrew Jeffery ctx->bmc_events |= ctx->event_lookup[name]; 1700a3358e7SAndrew Jeffery 1710a3358e7SAndrew Jeffery auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events); 1720a3358e7SAndrew Jeffery 1730a3358e7SAndrew Jeffery ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response)); 1740a3358e7SAndrew Jeffery 1750a3358e7SAndrew Jeffery return 0; 1760a3358e7SAndrew Jeffery } 1770a3358e7SAndrew Jeffery 1780a3358e7SAndrew Jeffery static bus::match::match hiomap_match_signal_v2(struct hiomap *ctx, 1790a3358e7SAndrew Jeffery const char *name) 1800a3358e7SAndrew Jeffery { 1810a3358e7SAndrew Jeffery using namespace bus::match; 1820a3358e7SAndrew Jeffery 1830a3358e7SAndrew Jeffery auto signals = rules::type::signal() + rules::path(HIOMAPD_OBJECT) + 1840a3358e7SAndrew Jeffery rules::interface(HIOMAPD_IFACE_V2) + rules::member(name); 1850a3358e7SAndrew Jeffery 1860a3358e7SAndrew Jeffery bus::match::match match(*ctx->bus, signals, 1870a3358e7SAndrew Jeffery std::bind(hiomap_handle_signal_v2, ctx, name)); 1880a3358e7SAndrew Jeffery 1890a3358e7SAndrew Jeffery return match; 1900a3358e7SAndrew Jeffery } 1910a3358e7SAndrew Jeffery 1920a3358e7SAndrew Jeffery static ipmi_ret_t hiomap_reset(ipmi_request_t request, ipmi_response_t response, 1930a3358e7SAndrew Jeffery ipmi_data_len_t data_len, ipmi_context_t context) 1940a3358e7SAndrew Jeffery { 1950a3358e7SAndrew Jeffery struct hiomap *ctx = static_cast<struct hiomap *>(context); 1960a3358e7SAndrew Jeffery 1970a3358e7SAndrew Jeffery auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, 1980a3358e7SAndrew Jeffery HIOMAPD_IFACE, "Reset"); 1990a3358e7SAndrew Jeffery try 2000a3358e7SAndrew Jeffery { 2010a3358e7SAndrew Jeffery ctx->bus->call(m); 2020a3358e7SAndrew Jeffery 2030a3358e7SAndrew Jeffery *data_len = 0; 2040a3358e7SAndrew Jeffery } 2050a3358e7SAndrew Jeffery catch (const exception::SdBusError &e) 2060a3358e7SAndrew Jeffery { 2070a3358e7SAndrew Jeffery return hiomap_xlate_errno(e.get_errno()); 2080a3358e7SAndrew Jeffery } 2090a3358e7SAndrew Jeffery 2100a3358e7SAndrew Jeffery return IPMI_CC_OK; 2110a3358e7SAndrew Jeffery } 2120a3358e7SAndrew Jeffery 2132c07f6f0SAndrew Jeffery static ipmi_ret_t hiomap_get_info(ipmi_request_t request, 2142c07f6f0SAndrew Jeffery ipmi_response_t response, 2152c07f6f0SAndrew Jeffery ipmi_data_len_t data_len, 2162c07f6f0SAndrew Jeffery ipmi_context_t context) 2172c07f6f0SAndrew Jeffery { 2180a3358e7SAndrew Jeffery struct hiomap *ctx = static_cast<struct hiomap *>(context); 2190a3358e7SAndrew Jeffery 2202c07f6f0SAndrew Jeffery if (*data_len < 1) 2212c07f6f0SAndrew Jeffery { 2222c07f6f0SAndrew Jeffery return IPMI_CC_REQ_DATA_LEN_INVALID; 2232c07f6f0SAndrew Jeffery } 2242c07f6f0SAndrew Jeffery 2252c07f6f0SAndrew Jeffery uint8_t *reqdata = (uint8_t *)request; 2260a3358e7SAndrew Jeffery auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, 2270a3358e7SAndrew Jeffery HIOMAPD_IFACE, "GetInfo"); 2282c07f6f0SAndrew Jeffery m.append(reqdata[0]); 2292c07f6f0SAndrew Jeffery 2302c07f6f0SAndrew Jeffery try 2312c07f6f0SAndrew Jeffery { 2320a3358e7SAndrew Jeffery auto reply = ctx->bus->call(m); 2332c07f6f0SAndrew Jeffery 2342c07f6f0SAndrew Jeffery uint8_t version; 2352c07f6f0SAndrew Jeffery uint8_t blockSizeShift; 2362c07f6f0SAndrew Jeffery uint16_t timeout; 2372c07f6f0SAndrew Jeffery reply.read(version, blockSizeShift, timeout); 2382c07f6f0SAndrew Jeffery 2392c07f6f0SAndrew Jeffery uint8_t *respdata = (uint8_t *)response; 2402c07f6f0SAndrew Jeffery 2412c07f6f0SAndrew Jeffery /* FIXME: Assumes v2! */ 2422c07f6f0SAndrew Jeffery put(&respdata[0], version); 2432c07f6f0SAndrew Jeffery put(&respdata[1], blockSizeShift); 2442c07f6f0SAndrew Jeffery put(&respdata[2], htole16(timeout)); 2452c07f6f0SAndrew Jeffery 2462c07f6f0SAndrew Jeffery *data_len = 4; 2472c07f6f0SAndrew Jeffery } 2482c07f6f0SAndrew Jeffery catch (const exception::SdBusError &e) 2492c07f6f0SAndrew Jeffery { 2502c07f6f0SAndrew Jeffery return hiomap_xlate_errno(e.get_errno()); 2512c07f6f0SAndrew Jeffery } 2522c07f6f0SAndrew Jeffery 2532c07f6f0SAndrew Jeffery return IPMI_CC_OK; 2542c07f6f0SAndrew Jeffery } 2552c07f6f0SAndrew Jeffery 256db688e9fSAndrew Jeffery static ipmi_ret_t hiomap_get_flash_info(ipmi_request_t request, 257db688e9fSAndrew Jeffery ipmi_response_t response, 258db688e9fSAndrew Jeffery ipmi_data_len_t data_len, 259db688e9fSAndrew Jeffery ipmi_context_t context) 260db688e9fSAndrew Jeffery { 261db688e9fSAndrew Jeffery struct hiomap *ctx = static_cast<struct hiomap *>(context); 262db688e9fSAndrew Jeffery 263db688e9fSAndrew Jeffery auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, 264db688e9fSAndrew Jeffery HIOMAPD_IFACE_V2, "GetFlashInfo"); 265db688e9fSAndrew Jeffery try 266db688e9fSAndrew Jeffery { 267db688e9fSAndrew Jeffery auto reply = ctx->bus->call(m); 268db688e9fSAndrew Jeffery 269db688e9fSAndrew Jeffery uint16_t flashSize, eraseSize; 270db688e9fSAndrew Jeffery reply.read(flashSize, eraseSize); 271db688e9fSAndrew Jeffery 272db688e9fSAndrew Jeffery uint8_t *respdata = (uint8_t *)response; 273db688e9fSAndrew Jeffery put(&respdata[0], htole16(flashSize)); 274db688e9fSAndrew Jeffery put(&respdata[2], htole16(eraseSize)); 275db688e9fSAndrew Jeffery 276db688e9fSAndrew Jeffery *data_len = 4; 277db688e9fSAndrew Jeffery } 278db688e9fSAndrew Jeffery catch (const exception::SdBusError &e) 279db688e9fSAndrew Jeffery { 280db688e9fSAndrew Jeffery return hiomap_xlate_errno(e.get_errno()); 281db688e9fSAndrew Jeffery } 282db688e9fSAndrew Jeffery 283db688e9fSAndrew Jeffery return IPMI_CC_OK; 284db688e9fSAndrew Jeffery } 285db688e9fSAndrew Jeffery 286*a00f59baSAndrew Jeffery static ipmi_ret_t hiomap_create_window(struct hiomap *ctx, bool ro, 287*a00f59baSAndrew Jeffery ipmi_request_t request, 288*a00f59baSAndrew Jeffery ipmi_response_t response, 289*a00f59baSAndrew Jeffery ipmi_data_len_t data_len) 290*a00f59baSAndrew Jeffery { 291*a00f59baSAndrew Jeffery if (*data_len < 4) 292*a00f59baSAndrew Jeffery { 293*a00f59baSAndrew Jeffery return IPMI_CC_REQ_DATA_LEN_INVALID; 294*a00f59baSAndrew Jeffery } 295*a00f59baSAndrew Jeffery 296*a00f59baSAndrew Jeffery uint8_t *reqdata = (uint8_t *)request; 297*a00f59baSAndrew Jeffery auto windowType = ro ? "CreateReadWindow" : "CreateWriteWindow"; 298*a00f59baSAndrew Jeffery 299*a00f59baSAndrew Jeffery auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, 300*a00f59baSAndrew Jeffery HIOMAPD_IFACE_V2, windowType); 301*a00f59baSAndrew Jeffery m.append(le16toh(get<uint16_t>(&reqdata[0]))); 302*a00f59baSAndrew Jeffery m.append(le16toh(get<uint16_t>(&reqdata[2]))); 303*a00f59baSAndrew Jeffery 304*a00f59baSAndrew Jeffery try 305*a00f59baSAndrew Jeffery { 306*a00f59baSAndrew Jeffery auto reply = ctx->bus->call(m); 307*a00f59baSAndrew Jeffery 308*a00f59baSAndrew Jeffery uint16_t lpcAddress, size, offset; 309*a00f59baSAndrew Jeffery reply.read(lpcAddress, size, offset); 310*a00f59baSAndrew Jeffery 311*a00f59baSAndrew Jeffery uint8_t *respdata = (uint8_t *)response; 312*a00f59baSAndrew Jeffery 313*a00f59baSAndrew Jeffery /* FIXME: Assumes v2! */ 314*a00f59baSAndrew Jeffery put(&respdata[0], htole16(lpcAddress)); 315*a00f59baSAndrew Jeffery put(&respdata[2], htole16(size)); 316*a00f59baSAndrew Jeffery put(&respdata[4], htole16(offset)); 317*a00f59baSAndrew Jeffery 318*a00f59baSAndrew Jeffery *data_len = 6; 319*a00f59baSAndrew Jeffery } 320*a00f59baSAndrew Jeffery catch (const exception::SdBusError &e) 321*a00f59baSAndrew Jeffery { 322*a00f59baSAndrew Jeffery return hiomap_xlate_errno(e.get_errno()); 323*a00f59baSAndrew Jeffery } 324*a00f59baSAndrew Jeffery 325*a00f59baSAndrew Jeffery return IPMI_CC_OK; 326*a00f59baSAndrew Jeffery } 327*a00f59baSAndrew Jeffery 328*a00f59baSAndrew Jeffery static ipmi_ret_t hiomap_create_read_window(ipmi_request_t request, 329*a00f59baSAndrew Jeffery ipmi_response_t response, 330*a00f59baSAndrew Jeffery ipmi_data_len_t data_len, 331*a00f59baSAndrew Jeffery ipmi_context_t context) 332*a00f59baSAndrew Jeffery { 333*a00f59baSAndrew Jeffery struct hiomap *ctx = static_cast<struct hiomap *>(context); 334*a00f59baSAndrew Jeffery 335*a00f59baSAndrew Jeffery return hiomap_create_window(ctx, true, request, response, data_len); 336*a00f59baSAndrew Jeffery } 337*a00f59baSAndrew Jeffery 338*a00f59baSAndrew Jeffery static ipmi_ret_t hiomap_create_write_window(ipmi_request_t request, 339*a00f59baSAndrew Jeffery ipmi_response_t response, 340*a00f59baSAndrew Jeffery ipmi_data_len_t data_len, 341*a00f59baSAndrew Jeffery ipmi_context_t context) 342*a00f59baSAndrew Jeffery { 343*a00f59baSAndrew Jeffery struct hiomap *ctx = static_cast<struct hiomap *>(context); 344*a00f59baSAndrew Jeffery 345*a00f59baSAndrew Jeffery return hiomap_create_window(ctx, false, request, response, data_len); 346*a00f59baSAndrew Jeffery } 347*a00f59baSAndrew Jeffery 3482c07f6f0SAndrew Jeffery static const hiomap_command hiomap_commands[] = { 3492c07f6f0SAndrew Jeffery [0] = NULL, /* 0 is an invalid command ID */ 3500a3358e7SAndrew Jeffery [1] = hiomap_reset, 3512c07f6f0SAndrew Jeffery [2] = hiomap_get_info, 352db688e9fSAndrew Jeffery [3] = hiomap_get_flash_info, 353*a00f59baSAndrew Jeffery [4] = hiomap_create_read_window, 354*a00f59baSAndrew Jeffery [5] = NULL, /* CLOSE_WINDOW */ 355*a00f59baSAndrew Jeffery [6] = hiomap_create_write_window, 3562c07f6f0SAndrew Jeffery }; 3572c07f6f0SAndrew Jeffery 3582c07f6f0SAndrew Jeffery /* FIXME: Define this in the "right" place, wherever that is */ 3592c07f6f0SAndrew Jeffery /* FIXME: Double evaluation */ 3602c07f6f0SAndrew Jeffery #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 3612c07f6f0SAndrew Jeffery 3622c07f6f0SAndrew Jeffery static ipmi_ret_t hiomap_dispatch(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 3632c07f6f0SAndrew Jeffery ipmi_request_t request, 3642c07f6f0SAndrew Jeffery ipmi_response_t response, 3652c07f6f0SAndrew Jeffery ipmi_data_len_t data_len, 3662c07f6f0SAndrew Jeffery ipmi_context_t context) 3672c07f6f0SAndrew Jeffery { 3680a3358e7SAndrew Jeffery struct hiomap *ctx = static_cast<struct hiomap *>(context); 3690a3358e7SAndrew Jeffery 3702c07f6f0SAndrew Jeffery if (*data_len < 2) 3712c07f6f0SAndrew Jeffery { 3722c07f6f0SAndrew Jeffery *data_len = 0; 3732c07f6f0SAndrew Jeffery return IPMI_CC_REQ_DATA_LEN_INVALID; 3742c07f6f0SAndrew Jeffery } 3752c07f6f0SAndrew Jeffery 3762c07f6f0SAndrew Jeffery uint8_t *ipmi_req = (uint8_t *)request; 3772c07f6f0SAndrew Jeffery uint8_t *ipmi_resp = (uint8_t *)response; 3782c07f6f0SAndrew Jeffery uint8_t hiomap_cmd = ipmi_req[0]; 3792c07f6f0SAndrew Jeffery 3802c07f6f0SAndrew Jeffery if (hiomap_cmd == 0 || hiomap_cmd > ARRAY_SIZE(hiomap_commands) - 1) 3812c07f6f0SAndrew Jeffery { 3822c07f6f0SAndrew Jeffery *data_len = 0; 3832c07f6f0SAndrew Jeffery return IPMI_CC_PARM_OUT_OF_RANGE; 3842c07f6f0SAndrew Jeffery } 3852c07f6f0SAndrew Jeffery uint8_t *flash_req = ipmi_req + 2; 3862c07f6f0SAndrew Jeffery size_t flash_len = *data_len - 2; 3872c07f6f0SAndrew Jeffery uint8_t *flash_resp = ipmi_resp + 2; 3882c07f6f0SAndrew Jeffery 3892c07f6f0SAndrew Jeffery ipmi_ret_t cc = 3902c07f6f0SAndrew Jeffery hiomap_commands[hiomap_cmd](flash_req, flash_resp, &flash_len, context); 3912c07f6f0SAndrew Jeffery if (cc != IPMI_CC_OK) 3922c07f6f0SAndrew Jeffery { 3932c07f6f0SAndrew Jeffery *data_len = 0; 3942c07f6f0SAndrew Jeffery return cc; 3952c07f6f0SAndrew Jeffery } 3962c07f6f0SAndrew Jeffery 3972c07f6f0SAndrew Jeffery /* Populate the response command and sequence */ 3980a3358e7SAndrew Jeffery ipmi_resp[0] = hiomap_cmd; 3990a3358e7SAndrew Jeffery ipmi_resp[1] = ipmi_req[1]; 4002c07f6f0SAndrew Jeffery 4012c07f6f0SAndrew Jeffery *data_len = flash_len + 2; 4022c07f6f0SAndrew Jeffery 4032c07f6f0SAndrew Jeffery return cc; 4042c07f6f0SAndrew Jeffery } 4052c07f6f0SAndrew Jeffery } // namespace flash 4062c07f6f0SAndrew Jeffery } // namespace openpower 4072c07f6f0SAndrew Jeffery 4082c07f6f0SAndrew Jeffery static void register_openpower_hiomap_commands() 4092c07f6f0SAndrew Jeffery { 4100a3358e7SAndrew Jeffery using namespace openpower::flash; 4110a3358e7SAndrew Jeffery 4120a3358e7SAndrew Jeffery /* FIXME: Clean this up? Can we unregister? */ 4130a3358e7SAndrew Jeffery struct hiomap *ctx = new hiomap(); 4140a3358e7SAndrew Jeffery 4150a3358e7SAndrew Jeffery /* Initialise mapping from signal and property names to status bit */ 4160a3358e7SAndrew Jeffery ctx->event_lookup["DaemonReady"] = BMC_EVENT_DAEMON_READY; 4170a3358e7SAndrew Jeffery ctx->event_lookup["FlashControlLost"] = BMC_EVENT_FLASH_CTRL_LOST; 4180a3358e7SAndrew Jeffery ctx->event_lookup["WindowReset"] = BMC_EVENT_WINDOW_RESET; 4190a3358e7SAndrew Jeffery ctx->event_lookup["ProtocolReset"] = BMC_EVENT_PROTOCOL_RESET; 4200a3358e7SAndrew Jeffery 4210a3358e7SAndrew Jeffery ctx->bus = new bus::bus(ipmid_get_sd_bus_connection()); 4220a3358e7SAndrew Jeffery 4230a3358e7SAndrew Jeffery /* Initialise signal handling */ 4240a3358e7SAndrew Jeffery 4250a3358e7SAndrew Jeffery /* 4260a3358e7SAndrew Jeffery * Can't use temporaries here because that causes SEGFAULTs due to slot 4270a3358e7SAndrew Jeffery * destruction (!?), so enjoy the weird wrapping. 4280a3358e7SAndrew Jeffery */ 4290a3358e7SAndrew Jeffery ctx->properties = 4300a3358e7SAndrew Jeffery new bus::match::match(std::move(hiomap_match_properties(ctx))); 4310a3358e7SAndrew Jeffery ctx->bmc_reboot = new bus::match::match( 4320a3358e7SAndrew Jeffery std::move(hiomap_match_signal_v2(ctx, "ProtocolReset"))); 4330a3358e7SAndrew Jeffery ctx->window_reset = new bus::match::match( 4340a3358e7SAndrew Jeffery std::move(hiomap_match_signal_v2(ctx, "WindowReset"))); 4350a3358e7SAndrew Jeffery 4360a3358e7SAndrew Jeffery ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_HIOMAP, ctx, 4372c07f6f0SAndrew Jeffery openpower::flash::hiomap_dispatch, SYSTEM_INTERFACE); 4382c07f6f0SAndrew Jeffery } 439