1*2c07f6f0SAndrew Jeffery // SPDX-License-Identifier: Apache-2.0 2*2c07f6f0SAndrew Jeffery // Copyright (C) 2018 IBM Corp. 3*2c07f6f0SAndrew Jeffery 4*2c07f6f0SAndrew Jeffery #include "config.h" 5*2c07f6f0SAndrew Jeffery 6*2c07f6f0SAndrew Jeffery #include "hiomap.hpp" 7*2c07f6f0SAndrew Jeffery 8*2c07f6f0SAndrew Jeffery #include <endian.h> 9*2c07f6f0SAndrew Jeffery #include <host-ipmid/ipmid-api.h> 10*2c07f6f0SAndrew Jeffery #include <string.h> 11*2c07f6f0SAndrew Jeffery #include <systemd/sd-bus.h> 12*2c07f6f0SAndrew Jeffery 13*2c07f6f0SAndrew Jeffery #include <fstream> 14*2c07f6f0SAndrew Jeffery #include <sdbusplus/bus.hpp> 15*2c07f6f0SAndrew Jeffery #include <sdbusplus/exception.hpp> 16*2c07f6f0SAndrew Jeffery 17*2c07f6f0SAndrew Jeffery using namespace sdbusplus; 18*2c07f6f0SAndrew Jeffery 19*2c07f6f0SAndrew Jeffery static void register_openpower_hiomap_commands() __attribute__((constructor)); 20*2c07f6f0SAndrew Jeffery 21*2c07f6f0SAndrew Jeffery namespace openpower 22*2c07f6f0SAndrew Jeffery { 23*2c07f6f0SAndrew Jeffery namespace flash 24*2c07f6f0SAndrew Jeffery { 25*2c07f6f0SAndrew Jeffery 26*2c07f6f0SAndrew Jeffery /* TODO: Replace get/put with packed structs and direct assignment */ 27*2c07f6f0SAndrew Jeffery template <typename T> static inline T get(void *buf) 28*2c07f6f0SAndrew Jeffery { 29*2c07f6f0SAndrew Jeffery T t; 30*2c07f6f0SAndrew Jeffery memcpy(&t, buf, sizeof(t)); 31*2c07f6f0SAndrew Jeffery return t; 32*2c07f6f0SAndrew Jeffery } 33*2c07f6f0SAndrew Jeffery 34*2c07f6f0SAndrew Jeffery template <typename T> static inline void put(void *buf, T &&t) 35*2c07f6f0SAndrew Jeffery { 36*2c07f6f0SAndrew Jeffery memcpy(buf, &t, sizeof(t)); 37*2c07f6f0SAndrew Jeffery } 38*2c07f6f0SAndrew Jeffery 39*2c07f6f0SAndrew Jeffery typedef ipmi_ret_t (*hiomap_command)(ipmi_request_t req, ipmi_response_t resp, 40*2c07f6f0SAndrew Jeffery ipmi_data_len_t data_len, 41*2c07f6f0SAndrew Jeffery ipmi_context_t context); 42*2c07f6f0SAndrew Jeffery 43*2c07f6f0SAndrew Jeffery struct errno_cc_entry 44*2c07f6f0SAndrew Jeffery { 45*2c07f6f0SAndrew Jeffery int err; 46*2c07f6f0SAndrew Jeffery int cc; 47*2c07f6f0SAndrew Jeffery }; 48*2c07f6f0SAndrew Jeffery 49*2c07f6f0SAndrew Jeffery static const errno_cc_entry errno_cc_map[] = { 50*2c07f6f0SAndrew Jeffery {0, IPMI_CC_OK}, 51*2c07f6f0SAndrew Jeffery {EBUSY, IPMI_CC_BUSY}, 52*2c07f6f0SAndrew Jeffery {ENOTSUP, IPMI_CC_INVALID}, 53*2c07f6f0SAndrew Jeffery {ETIMEDOUT, 0xc3}, /* FIXME: Replace when defined in ipmid-api.h */ 54*2c07f6f0SAndrew Jeffery {ENOSPC, 0xc4}, /* FIXME: Replace when defined in ipmid-api.h */ 55*2c07f6f0SAndrew Jeffery {EINVAL, IPMI_CC_PARM_OUT_OF_RANGE}, 56*2c07f6f0SAndrew Jeffery {ENODEV, IPMI_CC_SENSOR_INVALID}, 57*2c07f6f0SAndrew Jeffery {EPERM, IPMI_CC_INSUFFICIENT_PRIVILEGE}, 58*2c07f6f0SAndrew Jeffery {EACCES, IPMI_CC_INSUFFICIENT_PRIVILEGE}, 59*2c07f6f0SAndrew Jeffery {-1, IPMI_CC_UNSPECIFIED_ERROR}, 60*2c07f6f0SAndrew Jeffery }; 61*2c07f6f0SAndrew Jeffery 62*2c07f6f0SAndrew Jeffery static int hiomap_xlate_errno(int err) 63*2c07f6f0SAndrew Jeffery { 64*2c07f6f0SAndrew Jeffery const errno_cc_entry *entry = &errno_cc_map[0]; 65*2c07f6f0SAndrew Jeffery 66*2c07f6f0SAndrew Jeffery while (!(entry->err == err || entry->err == -1)) 67*2c07f6f0SAndrew Jeffery { 68*2c07f6f0SAndrew Jeffery entry++; 69*2c07f6f0SAndrew Jeffery } 70*2c07f6f0SAndrew Jeffery 71*2c07f6f0SAndrew Jeffery return entry->cc; 72*2c07f6f0SAndrew Jeffery } 73*2c07f6f0SAndrew Jeffery 74*2c07f6f0SAndrew Jeffery static ipmi_ret_t hiomap_get_info(ipmi_request_t request, 75*2c07f6f0SAndrew Jeffery ipmi_response_t response, 76*2c07f6f0SAndrew Jeffery ipmi_data_len_t data_len, 77*2c07f6f0SAndrew Jeffery ipmi_context_t context) 78*2c07f6f0SAndrew Jeffery { 79*2c07f6f0SAndrew Jeffery if (*data_len < 1) 80*2c07f6f0SAndrew Jeffery { 81*2c07f6f0SAndrew Jeffery return IPMI_CC_REQ_DATA_LEN_INVALID; 82*2c07f6f0SAndrew Jeffery } 83*2c07f6f0SAndrew Jeffery 84*2c07f6f0SAndrew Jeffery uint8_t *reqdata = (uint8_t *)request; 85*2c07f6f0SAndrew Jeffery auto b = bus::new_system(); 86*2c07f6f0SAndrew Jeffery auto m = b.new_method_call( 87*2c07f6f0SAndrew Jeffery "xyz.openbmc_project.Hiomapd", "/xyz/openbmc_project/Hiomapd", 88*2c07f6f0SAndrew Jeffery "xyz.openbmc_project.Hiomapd.Protocol", "GetInfo"); 89*2c07f6f0SAndrew Jeffery m.append(reqdata[0]); 90*2c07f6f0SAndrew Jeffery 91*2c07f6f0SAndrew Jeffery try 92*2c07f6f0SAndrew Jeffery { 93*2c07f6f0SAndrew Jeffery auto reply = b.call(m); 94*2c07f6f0SAndrew Jeffery 95*2c07f6f0SAndrew Jeffery uint8_t version; 96*2c07f6f0SAndrew Jeffery uint8_t blockSizeShift; 97*2c07f6f0SAndrew Jeffery uint16_t timeout; 98*2c07f6f0SAndrew Jeffery reply.read(version, blockSizeShift, timeout); 99*2c07f6f0SAndrew Jeffery 100*2c07f6f0SAndrew Jeffery uint8_t *respdata = (uint8_t *)response; 101*2c07f6f0SAndrew Jeffery 102*2c07f6f0SAndrew Jeffery /* FIXME: Assumes v2! */ 103*2c07f6f0SAndrew Jeffery put(&respdata[0], version); 104*2c07f6f0SAndrew Jeffery put(&respdata[1], blockSizeShift); 105*2c07f6f0SAndrew Jeffery put(&respdata[2], htole16(timeout)); 106*2c07f6f0SAndrew Jeffery 107*2c07f6f0SAndrew Jeffery *data_len = 4; 108*2c07f6f0SAndrew Jeffery } 109*2c07f6f0SAndrew Jeffery catch (const exception::SdBusError &e) 110*2c07f6f0SAndrew Jeffery { 111*2c07f6f0SAndrew Jeffery return hiomap_xlate_errno(e.get_errno()); 112*2c07f6f0SAndrew Jeffery } 113*2c07f6f0SAndrew Jeffery 114*2c07f6f0SAndrew Jeffery return IPMI_CC_OK; 115*2c07f6f0SAndrew Jeffery } 116*2c07f6f0SAndrew Jeffery 117*2c07f6f0SAndrew Jeffery static const hiomap_command hiomap_commands[] = { 118*2c07f6f0SAndrew Jeffery [0] = NULL, /* 0 is an invalid command ID */ 119*2c07f6f0SAndrew Jeffery [1] = NULL, /* RESET */ 120*2c07f6f0SAndrew Jeffery [2] = hiomap_get_info, 121*2c07f6f0SAndrew Jeffery }; 122*2c07f6f0SAndrew Jeffery 123*2c07f6f0SAndrew Jeffery /* FIXME: Define this in the "right" place, wherever that is */ 124*2c07f6f0SAndrew Jeffery /* FIXME: Double evaluation */ 125*2c07f6f0SAndrew Jeffery #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 126*2c07f6f0SAndrew Jeffery 127*2c07f6f0SAndrew Jeffery static ipmi_ret_t hiomap_dispatch(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 128*2c07f6f0SAndrew Jeffery ipmi_request_t request, 129*2c07f6f0SAndrew Jeffery ipmi_response_t response, 130*2c07f6f0SAndrew Jeffery ipmi_data_len_t data_len, 131*2c07f6f0SAndrew Jeffery ipmi_context_t context) 132*2c07f6f0SAndrew Jeffery { 133*2c07f6f0SAndrew Jeffery if (*data_len < 2) 134*2c07f6f0SAndrew Jeffery { 135*2c07f6f0SAndrew Jeffery *data_len = 0; 136*2c07f6f0SAndrew Jeffery return IPMI_CC_REQ_DATA_LEN_INVALID; 137*2c07f6f0SAndrew Jeffery } 138*2c07f6f0SAndrew Jeffery 139*2c07f6f0SAndrew Jeffery uint8_t *ipmi_req = (uint8_t *)request; 140*2c07f6f0SAndrew Jeffery uint8_t *ipmi_resp = (uint8_t *)response; 141*2c07f6f0SAndrew Jeffery uint8_t hiomap_cmd = ipmi_req[0]; 142*2c07f6f0SAndrew Jeffery 143*2c07f6f0SAndrew Jeffery if (hiomap_cmd == 0 || hiomap_cmd > ARRAY_SIZE(hiomap_commands) - 1) 144*2c07f6f0SAndrew Jeffery { 145*2c07f6f0SAndrew Jeffery *data_len = 0; 146*2c07f6f0SAndrew Jeffery return IPMI_CC_PARM_OUT_OF_RANGE; 147*2c07f6f0SAndrew Jeffery } 148*2c07f6f0SAndrew Jeffery uint8_t *flash_req = ipmi_req + 2; 149*2c07f6f0SAndrew Jeffery size_t flash_len = *data_len - 2; 150*2c07f6f0SAndrew Jeffery uint8_t *flash_resp = ipmi_resp + 2; 151*2c07f6f0SAndrew Jeffery 152*2c07f6f0SAndrew Jeffery ipmi_ret_t cc = 153*2c07f6f0SAndrew Jeffery hiomap_commands[hiomap_cmd](flash_req, flash_resp, &flash_len, context); 154*2c07f6f0SAndrew Jeffery if (cc != IPMI_CC_OK) 155*2c07f6f0SAndrew Jeffery { 156*2c07f6f0SAndrew Jeffery *data_len = 0; 157*2c07f6f0SAndrew Jeffery return cc; 158*2c07f6f0SAndrew Jeffery } 159*2c07f6f0SAndrew Jeffery 160*2c07f6f0SAndrew Jeffery /* Populate the response command and sequence */ 161*2c07f6f0SAndrew Jeffery put(&ipmi_resp[0], ipmi_req[0]); 162*2c07f6f0SAndrew Jeffery put(&ipmi_resp[1], ipmi_req[1]); 163*2c07f6f0SAndrew Jeffery 164*2c07f6f0SAndrew Jeffery *data_len = flash_len + 2; 165*2c07f6f0SAndrew Jeffery 166*2c07f6f0SAndrew Jeffery return cc; 167*2c07f6f0SAndrew Jeffery } 168*2c07f6f0SAndrew Jeffery } // namespace flash 169*2c07f6f0SAndrew Jeffery } // namespace openpower 170*2c07f6f0SAndrew Jeffery 171*2c07f6f0SAndrew Jeffery static void register_openpower_hiomap_commands() 172*2c07f6f0SAndrew Jeffery { 173*2c07f6f0SAndrew Jeffery ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_HIOMAP, NULL, 174*2c07f6f0SAndrew Jeffery openpower::flash::hiomap_dispatch, SYSTEM_INTERFACE); 175*2c07f6f0SAndrew Jeffery } 176