diff options
author | Cédric Le Goater <clg@kaod.org> | 2019-10-28 08:00:27 +0100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2019-12-17 10:39:47 +1100 |
commit | ca661fae81d3b36b72c316a63165d9318dbd2439 (patch) | |
tree | 5171d2957f99f67c48132c71de30eff9d7ace561 /hw/ppc/pnv_bmc.c | |
parent | ed8da05cdb18a32a8a41165d5b7b367bc05fdab0 (diff) |
ppc/pnv: Add HIOMAP commands
This activates HIOMAP support on the QEMU PowerNV machine. The PnvPnor
model is used to access the flash contents. The model simply maps the
contents at a fix offset and enables or disables the mapping.
HIOMAP Protocol description :
https://github.com/openbmc/hiomapd/blob/master/Documentation/protocol.md
Reviewed-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20191028070027.22752-3-clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc/pnv_bmc.c')
-rw-r--r-- | hw/ppc/pnv_bmc.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c index dc5e918cb7..aa5c89586c 100644 --- a/hw/ppc/pnv_bmc.c +++ b/hw/ppc/pnv_bmc.c @@ -114,3 +114,105 @@ void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt) sdr->sensor_type))); } } + +/* + * HIOMAP protocol handler + */ +#define HIOMAP_C_RESET 1 +#define HIOMAP_C_GET_INFO 2 +#define HIOMAP_C_GET_FLASH_INFO 3 +#define HIOMAP_C_CREATE_READ_WINDOW 4 +#define HIOMAP_C_CLOSE_WINDOW 5 +#define HIOMAP_C_CREATE_WRITE_WINDOW 6 +#define HIOMAP_C_MARK_DIRTY 7 +#define HIOMAP_C_FLUSH 8 +#define HIOMAP_C_ACK 9 +#define HIOMAP_C_ERASE 10 +#define HIOMAP_C_DEVICE_NAME 11 +#define HIOMAP_C_LOCK 12 + +#define BLOCK_SHIFT 12 /* 4K */ + +static uint16_t bytes_to_blocks(uint32_t bytes) +{ + return bytes >> BLOCK_SHIFT; +} + +static void hiomap_cmd(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, + RspBuffer *rsp) +{ + PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); + PnvPnor *pnor = pnv->pnor; + uint32_t pnor_size = pnor->size; + uint32_t pnor_addr = PNOR_SPI_OFFSET; + bool readonly = false; + + rsp_buffer_push(rsp, cmd[2]); + rsp_buffer_push(rsp, cmd[3]); + + switch (cmd[2]) { + case HIOMAP_C_MARK_DIRTY: + case HIOMAP_C_FLUSH: + case HIOMAP_C_ERASE: + case HIOMAP_C_ACK: + break; + + case HIOMAP_C_GET_INFO: + rsp_buffer_push(rsp, 2); /* Version 2 */ + rsp_buffer_push(rsp, BLOCK_SHIFT); /* block size */ + rsp_buffer_push(rsp, 0); /* Timeout */ + rsp_buffer_push(rsp, 0); /* Timeout */ + break; + + case HIOMAP_C_GET_FLASH_INFO: + rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) & 0xFF); + rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) >> 8); + rsp_buffer_push(rsp, 0x01); /* erase size */ + rsp_buffer_push(rsp, 0x00); /* erase size */ + break; + + case HIOMAP_C_CREATE_READ_WINDOW: + readonly = true; + /* Fall through */ + + case HIOMAP_C_CREATE_WRITE_WINDOW: + memory_region_set_readonly(&pnor->mmio, readonly); + memory_region_set_enabled(&pnor->mmio, true); + + rsp_buffer_push(rsp, bytes_to_blocks(pnor_addr) & 0xFF); + rsp_buffer_push(rsp, bytes_to_blocks(pnor_addr) >> 8); + rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) & 0xFF); + rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) >> 8); + rsp_buffer_push(rsp, 0x00); /* offset */ + rsp_buffer_push(rsp, 0x00); /* offset */ + break; + + case HIOMAP_C_CLOSE_WINDOW: + memory_region_set_enabled(&pnor->mmio, false); + break; + + case HIOMAP_C_DEVICE_NAME: + case HIOMAP_C_RESET: + case HIOMAP_C_LOCK: + default: + qemu_log_mask(LOG_GUEST_ERROR, "HIOMAP: unknow command %02X\n", cmd[2]); + break; + } +} + +#define HIOMAP 0x5a + +static const IPMICmdHandler hiomap_cmds[] = { + [HIOMAP] = { hiomap_cmd, 3 }, +}; + +static const IPMINetfn hiomap_netfn = { + .cmd_nums = ARRAY_SIZE(hiomap_cmds), + .cmd_handlers = hiomap_cmds +}; + +int pnv_bmc_hiomap(IPMIBmc *bmc) +{ + return ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(bmc), + IPMI_NETFN_OEM, &hiomap_netfn); +} |