All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2)
@ 2016-03-02 10:14 Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro Cédric Le Goater
                   ` (9 more replies)
  0 siblings, 10 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

Hello,

The first patches are cleanups and prepare ground for an extension of
the BMC simulator providing a SDR loader using a file. A simple FRU
support comes next.

Changes since v1:

  - Added initial cleanups removing the macros implicitely making use
    of local variables in the command handlers  
  - Fixed property naming
  - Kept the API extensions to expose SDR and generate events for
    later

Based on 9c279bec754a and also available here  :

  https://github.com/legoater/qemu/commits/ipmi

Thanks,

C.

Cédric Le Goater (10):
  ipmi: remove IPMI_CHECK_CMD_LEN() macro
  ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  ipmi: remove IPMI_CHECK_RESERVATION() macro
  ipmi: add rsp_buffer_set_error() helper
  ipmi: add a realize function to the device class
  ipmi: use a function to initialize the SDR table
  ipmi: remove the need of an ending record in the SDR table
  ipmi: add some local variables in ipmi_sdr_init
  ipmi: use a file to load SDRs
  ipmi: provide support for FRUs

 hw/ipmi/ipmi_bmc_sim.c | 855 ++++++++++++++++++++++++++++---------------------
 qemu-options.hx        |  15 +-
 2 files changed, 506 insertions(+), 364 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-05 11:41   ` Corey Minyard
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers Cédric Le Goater
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

Most IPMI command handlers in the BMC simulator start with a call to
the macro IPMI_CHECK_CMD_LEN() which verifies that a minimal number of
arguments expected by the command are indeed available. To achieve
this task, the macro implicitly uses local variables which is
misleading in the code.

This patch adds a 'cmd_len_min' attribute to the struct IPMICmdHandler
defining the minimal number of arguments expected by the command and
moves this check in the global command handler ipmi_sim_handle_command().

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 hw/ipmi/ipmi_bmc_sim.c | 137 ++++++++++++++++++++++---------------------------
 1 file changed, 62 insertions(+), 75 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 51d234aa1bf2..30b9fb48ea2d 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -155,10 +155,15 @@ typedef struct IPMISensor {
 typedef struct IPMIBmcSim IPMIBmcSim;
 
 #define MAX_NETFNS 64
-typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
-                               uint8_t *cmd, unsigned int cmd_len,
-                               uint8_t *rsp, unsigned int *rsp_len,
-                               unsigned int max_rsp_len);
+
+typedef struct IPMICmdHandler {
+    void (*cmd_handler)(IPMIBmcSim *s,
+                        uint8_t *cmd, unsigned int cmd_len,
+                        uint8_t *rsp, unsigned int *rsp_len,
+                        unsigned int max_rsp_len);
+    unsigned int cmd_len_min;
+} IPMICmdHandler;
+
 typedef struct IPMINetfn {
     unsigned int cmd_nums;
     const IPMICmdHandler *cmd_handlers;
@@ -269,13 +274,6 @@ struct IPMIBmcSim {
         rsp[(*rsp_len)++] = (b);                           \
     } while (0)
 
-/* Verify that the received command is a certain length. */
-#define IPMI_CHECK_CMD_LEN(l) \
-    if (cmd_len < l) {                                     \
-        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;      \
-        return; \
-    }
-
 /* Check that the reservation in the command is valid. */
 #define IPMI_CHECK_RESERVATION(off, r) \
     do {                                                   \
@@ -623,14 +621,19 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
 
     /* Odd netfns are not valid, make sure the command is registered */
     if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
-                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
-                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
+        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
+        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
         rsp[2] = IPMI_CC_INVALID_CMD;
         goto out;
     }
 
-    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
-                                                max_rsp_len);
+    if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
+        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        goto out;
+    }
+
+    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
+                                                rsp, rsp_len, max_rsp_len);
 
  out:
     k->handle_rsp(s, msg_id, rsp, *rsp_len);
@@ -737,7 +740,6 @@ static void chassis_control(IPMIBmcSim *ibs,
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
 
-    IPMI_CHECK_CMD_LEN(3);
     switch (cmd[2] & 0xf) {
     case 0: /* power down */
         rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
@@ -838,7 +840,6 @@ static void set_acpi_power_state(IPMIBmcSim *ibs,
                           uint8_t *rsp, unsigned int *rsp_len,
                           unsigned int max_rsp_len)
 {
-    IPMI_CHECK_CMD_LEN(4);
     ibs->acpi_power_state[0] = cmd[2];
     ibs->acpi_power_state[1] = cmd[3];
 }
@@ -869,7 +870,6 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs,
                                    uint8_t *rsp, unsigned int *rsp_len,
                                    unsigned int max_rsp_len)
 {
-    IPMI_CHECK_CMD_LEN(3);
     set_global_enables(ibs, cmd[2]);
 }
 
@@ -889,7 +889,6 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
 
-    IPMI_CHECK_CMD_LEN(3);
     ibs->msg_flags &= ~cmd[2];
     k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
 }
@@ -976,15 +975,17 @@ static void send_msg(IPMIBmcSim *ibs,
     uint8_t *buf;
     uint8_t netfn, rqLun, rsLun, rqSeq;
 
-    IPMI_CHECK_CMD_LEN(3);
-
     if (cmd[2] != 0) {
         /* We only handle channel 0 with no options */
         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
 
-    IPMI_CHECK_CMD_LEN(10);
+    if (cmd_len < 10) {
+        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        return;
+    }
+
     if (cmd[3] != 0x40) {
         /* We only emulate a MC at address 0x40. */
         rsp[2] = 0x83; /* NAK on write */
@@ -1092,7 +1093,6 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
     unsigned int val;
 
-    IPMI_CHECK_CMD_LEN(8);
     val = cmd[2] & 0x7; /* Validate use */
     if (val == 0 || val > 5) {
         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
@@ -1217,7 +1217,6 @@ static void get_sdr(IPMIBmcSim *ibs,
     uint16_t nextrec;
     struct ipmi_sdr_header *sdrh;
 
-    IPMI_CHECK_CMD_LEN(8);
     if (cmd[6]) {
         IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
     }
@@ -1271,7 +1270,6 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
                           uint8_t *rsp, unsigned int *rsp_len,
                           unsigned int max_rsp_len)
 {
-    IPMI_CHECK_CMD_LEN(8);
     IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
@@ -1330,7 +1328,6 @@ static void get_sel_entry(IPMIBmcSim *ibs,
 {
     unsigned int val;
 
-    IPMI_CHECK_CMD_LEN(8);
     if (cmd[6]) {
         IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
     }
@@ -1375,7 +1372,6 @@ static void add_sel_entry(IPMIBmcSim *ibs,
                           uint8_t *rsp, unsigned int *rsp_len,
                           unsigned int max_rsp_len)
 {
-    IPMI_CHECK_CMD_LEN(18);
     if (sel_add_event(ibs, cmd + 2)) {
         rsp[2] = IPMI_CC_OUT_OF_SPACE;
         return;
@@ -1390,7 +1386,6 @@ static void clear_sel(IPMIBmcSim *ibs,
                       uint8_t *rsp, unsigned int *rsp_len,
                       unsigned int max_rsp_len)
 {
-    IPMI_CHECK_CMD_LEN(8);
     IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
         rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
@@ -1434,7 +1429,6 @@ static void set_sel_time(IPMIBmcSim *ibs,
     uint32_t val;
     struct ipmi_time now;
 
-    IPMI_CHECK_CMD_LEN(6);
     val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
     ipmi_gettime(&now);
     ibs->sel.time_offset = now.tv_sec - ((long) val);
@@ -1447,7 +1441,6 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
 {
     IPMISensor *sens;
 
-    IPMI_CHECK_CMD_LEN(4);
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1499,7 +1492,6 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
 {
     IPMISensor *sens;
 
-    IPMI_CHECK_CMD_LEN(3);
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1520,7 +1512,6 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
 {
     IPMISensor *sens;
 
-    IPMI_CHECK_CMD_LEN(4);
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1542,7 +1533,6 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
 {
     IPMISensor *sens;
 
-    IPMI_CHECK_CMD_LEN(3);
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1564,7 +1554,6 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
 {
     IPMISensor *sens;
 
-    IPMI_CHECK_CMD_LEN(3);
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1587,7 +1576,6 @@ static void set_sensor_type(IPMIBmcSim *ibs,
     IPMISensor *sens;
 
 
-    IPMI_CHECK_CMD_LEN(5);
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1606,7 +1594,6 @@ static void get_sensor_type(IPMIBmcSim *ibs,
     IPMISensor *sens;
 
 
-    IPMI_CHECK_CMD_LEN(3);
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
         rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1619,10 +1606,10 @@ static void get_sensor_type(IPMIBmcSim *ibs,
 
 
 static const IPMICmdHandler chassis_cmds[] = {
-    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
-    [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
-    [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
-    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
+    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
+    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
+    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
+    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
 };
 static const IPMINetfn chassis_netfn = {
     .cmd_nums = ARRAY_SIZE(chassis_cmds),
@@ -1630,13 +1617,13 @@ static const IPMINetfn chassis_netfn = {
 };
 
 static const IPMICmdHandler sensor_event_cmds[] = {
-    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
-    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
-    [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
-    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
-    [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
-    [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
-    [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
+    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
+    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
+    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
+    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
+    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
+    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
+    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
 };
 static const IPMINetfn sensor_event_netfn = {
     .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
@@ -1644,22 +1631,22 @@ static const IPMINetfn sensor_event_netfn = {
 };
 
 static const IPMICmdHandler app_cmds[] = {
-    [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
-    [IPMI_CMD_COLD_RESET] = cold_reset,
-    [IPMI_CMD_WARM_RESET] = warm_reset,
-    [IPMI_CMD_SET_ACPI_POWER_STATE] = set_acpi_power_state,
-    [IPMI_CMD_GET_ACPI_POWER_STATE] = get_acpi_power_state,
-    [IPMI_CMD_GET_DEVICE_GUID] = get_device_guid,
-    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
-    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
-    [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
-    [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
-    [IPMI_CMD_GET_MSG] = get_msg,
-    [IPMI_CMD_SEND_MSG] = send_msg,
-    [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
-    [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
-    [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
-    [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
+    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
+    [IPMI_CMD_COLD_RESET] = { cold_reset },
+    [IPMI_CMD_WARM_RESET] = { warm_reset },
+    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
+    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
+    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
+    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
+    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
+    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
+    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
+    [IPMI_CMD_GET_MSG] = { get_msg },
+    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
+    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
+    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
+    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
+    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
 };
 static const IPMINetfn app_netfn = {
     .cmd_nums = ARRAY_SIZE(app_cmds),
@@ -1667,18 +1654,18 @@ static const IPMINetfn app_netfn = {
 };
 
 static const IPMICmdHandler storage_cmds[] = {
-    [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
-    [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
-    [IPMI_CMD_GET_SDR] = get_sdr,
-    [IPMI_CMD_ADD_SDR] = add_sdr,
-    [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
-    [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
-    [IPMI_CMD_RESERVE_SEL] = reserve_sel,
-    [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
-    [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
-    [IPMI_CMD_CLEAR_SEL] = clear_sel,
-    [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
-    [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
+    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
+    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
+    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
+    [IPMI_CMD_ADD_SDR] = { add_sdr },
+    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
+    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
+    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
+    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
+    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
+    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
+    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
+    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
 };
 
 static const IPMINetfn storage_netfn = {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-02 10:25   ` Michael S. Tsirkin
  2016-03-05 11:41   ` Corey Minyard
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 03/10] ipmi: remove IPMI_CHECK_RESERVATION() macro Cédric Le Goater
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

The IPMI command handlers in the BMC simulator use a macro
IPMI_ADD_RSP_DATA() to push bytes in a response buffer. The macro
hides the fact that it implicitly uses variables local to the handler,
which is misleading.

This patch introduces a simple 'struct rsp_buffer' and inlined helper
routines to store byte(s) in a response buffer. rsp_buffer_push()
replaces the macro IPMI_ADD_RSP_DATA() and rsp_buffer_pushmore() is
new helper to push multiple bytes. The latest is used in the command
handlers get_msg() and get_sdr() which are manipulating the buffer
directly.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 hw/ipmi/ipmi_bmc_sim.c | 482 +++++++++++++++++++++++--------------------------
 1 file changed, 229 insertions(+), 253 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 30b9fb48ea2d..32efb87c8232 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -153,14 +153,14 @@ typedef struct IPMISensor {
 #define IPMI_WATCHDOG_SENSOR 0
 
 typedef struct IPMIBmcSim IPMIBmcSim;
+struct rsp_buffer;
 
 #define MAX_NETFNS 64
 
 typedef struct IPMICmdHandler {
     void (*cmd_handler)(IPMIBmcSim *s,
                         uint8_t *cmd, unsigned int cmd_len,
-                        uint8_t *rsp, unsigned int *rsp_len,
-                        unsigned int max_rsp_len);
+                        struct rsp_buffer *rsp);
     unsigned int cmd_len_min;
 } IPMICmdHandler;
 
@@ -263,22 +263,41 @@ struct IPMIBmcSim {
 #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
 #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3
 
+struct rsp_buffer {
+    uint8_t buffer[MAX_IPMI_MSG_SIZE];
+    unsigned int len;
+    unsigned int max_len;
+};
+
+#define RSP_BUFFER_INITIALIZER { { 0 }, 0, MAX_IPMI_MSG_SIZE }
 
 /* Add a byte to the response. */
-#define IPMI_ADD_RSP_DATA(b) \
-    do {                                                   \
-        if (*rsp_len >= max_rsp_len) {                     \
-            rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;       \
-            return;                                        \
-        }                                                  \
-        rsp[(*rsp_len)++] = (b);                           \
-    } while (0)
+static inline void rsp_buffer_push(struct rsp_buffer *rsp, uint8_t byte)
+{
+    if (rsp->len >= rsp->max_len) {
+        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+        return;
+    }
+    rsp->buffer[rsp->len++] = byte;
+}
+
+static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
+                                       unsigned int n)
+{
+    if (rsp->len + n >= rsp->max_len) {
+        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+        return;
+    }
+
+    memcpy(&rsp->buffer[rsp->len], bytes, n);
+    rsp->len += n;
+}
 
 /* Check that the reservation in the command is valid. */
 #define IPMI_CHECK_RESERVATION(off, r) \
     do {                                                   \
         if ((cmd[off] | (cmd[off + 1] << 8)) != r) {       \
-            rsp[2] = IPMI_CC_INVALID_RESERVATION;          \
+            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;     \
             return;                                        \
         }                                                  \
     } while (0)
@@ -585,35 +604,32 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
     unsigned int netfn;
-    uint8_t rsp[MAX_IPMI_MSG_SIZE];
-    unsigned int rsp_len_holder = 0;
-    unsigned int *rsp_len = &rsp_len_holder;
-    unsigned int max_rsp_len = sizeof(rsp);
+    struct rsp_buffer rsp = RSP_BUFFER_INITIALIZER;
 
     /* Set up the response, set the low bit of NETFN. */
     /* Note that max_rsp_len must be at least 3 */
-    if (max_rsp_len < 3) {
-        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+    if (rsp.max_len < 3) {
+        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
         goto out;
     }
 
-    IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
-    IPMI_ADD_RSP_DATA(cmd[1]);
-    IPMI_ADD_RSP_DATA(0); /* Assume success */
+    rsp_buffer_push(&rsp, cmd[0] | 0x04);
+    rsp_buffer_push(&rsp, cmd[1]);
+    rsp_buffer_push(&rsp, 0); /* Assume success */
 
     /* If it's too short or it was truncated, return an error. */
     if (cmd_len < 2) {
-        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
         goto out;
     }
     if (cmd_len > max_cmd_len) {
-        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
         goto out;
     }
 
     if ((cmd[0] & 0x03) != 0) {
         /* Only have stuff on LUN 0 */
-        rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
+        rsp.buffer[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
         goto out;
     }
 
@@ -623,20 +639,20 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
     if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
         (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
         (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
-        rsp[2] = IPMI_CC_INVALID_CMD;
+        rsp.buffer[2] = IPMI_CC_INVALID_CMD;
         goto out;
     }
 
     if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
-        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
         goto out;
     }
 
     ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
-                                                rsp, rsp_len, max_rsp_len);
+                                                &rsp);
 
  out:
-    k->handle_rsp(s, msg_id, rsp, *rsp_len);
+    k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
 
     next_timeout(ibs);
 }
@@ -711,86 +727,82 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
 
 static void chassis_capabilities(IPMIBmcSim *ibs,
                                  uint8_t *cmd, unsigned int cmd_len,
-                                 uint8_t *rsp, unsigned int *rsp_len,
-                                 unsigned int max_rsp_len)
+                                 struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(0);
-    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
-    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
-    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
-    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
+    rsp_buffer_push(rsp, 0);
+    rsp_buffer_push(rsp, ibs->parent.slave_addr);
+    rsp_buffer_push(rsp, ibs->parent.slave_addr);
+    rsp_buffer_push(rsp, ibs->parent.slave_addr);
+    rsp_buffer_push(rsp, ibs->parent.slave_addr);
 }
 
 static void chassis_status(IPMIBmcSim *ibs,
                            uint8_t *cmd, unsigned int cmd_len,
-                           uint8_t *rsp, unsigned int *rsp_len,
-                           unsigned int max_rsp_len)
+                           struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
-    IPMI_ADD_RSP_DATA(0);
-    IPMI_ADD_RSP_DATA(0);
-    IPMI_ADD_RSP_DATA(0);
+    rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
+    rsp_buffer_push(rsp, 0);
+    rsp_buffer_push(rsp, 0);
+    rsp_buffer_push(rsp, 0);
 }
 
 static void chassis_control(IPMIBmcSim *ibs,
                             uint8_t *cmd, unsigned int cmd_len,
-                            uint8_t *rsp, unsigned int *rsp_len,
-                            unsigned int max_rsp_len)
+                            struct rsp_buffer *rsp)
 {
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
 
     switch (cmd[2] & 0xf) {
     case 0: /* power down */
-        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
         break;
     case 1: /* power up */
-        rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
         break;
     case 2: /* power cycle */
-        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
         break;
     case 3: /* hard reset */
-        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
         break;
     case 4: /* pulse diagnostic interrupt */
-        rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
         break;
     case 5: /* soft shutdown via ACPI by overtemp emulation */
-        rsp[2] = k->do_hw_op(s,
+        rsp->buffer[2] = k->do_hw_op(s,
                              IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
         break;
     default:
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
 }
 
 static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
                            uint8_t *cmd, unsigned int cmd_len,
-                           uint8_t *rsp, unsigned int *rsp_len,
-                           unsigned int max_rsp_len)
+                           struct rsp_buffer *rsp)
+
 {
-    IPMI_ADD_RSP_DATA(ibs->restart_cause & 0xf); /* Restart Cause */
-    IPMI_ADD_RSP_DATA(0);  /* Channel 0 */
+    rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
+    rsp_buffer_push(rsp, 0);  /* Channel 0 */
 }
 
 static void get_device_id(IPMIBmcSim *ibs,
                           uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
-{
-    IPMI_ADD_RSP_DATA(ibs->device_id);
-    IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
-    IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
-    IPMI_ADD_RSP_DATA(ibs->fwrev2);
-    IPMI_ADD_RSP_DATA(ibs->ipmi_version);
-    IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
-    IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
-    IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
-    IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
-    IPMI_ADD_RSP_DATA(ibs->product_id[0]);
-    IPMI_ADD_RSP_DATA(ibs->product_id[1]);
+                          struct rsp_buffer *rsp)
+{
+    rsp_buffer_push(rsp, ibs->device_id);
+    rsp_buffer_push(rsp, ibs->device_rev & 0xf);
+    rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
+    rsp_buffer_push(rsp, ibs->fwrev2);
+    rsp_buffer_push(rsp, ibs->ipmi_version);
+    rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
+    rsp_buffer_push(rsp, ibs->mfg_id[0]);
+    rsp_buffer_push(rsp, ibs->mfg_id[1]);
+    rsp_buffer_push(rsp, ibs->mfg_id[2]);
+    rsp_buffer_push(rsp, ibs->product_id[0]);
+    rsp_buffer_push(rsp, ibs->product_id[1]);
 }
 
 static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
@@ -809,8 +821,7 @@ static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
 
 static void cold_reset(IPMIBmcSim *ibs,
                        uint8_t *cmd, unsigned int cmd_len,
-                       uint8_t *rsp, unsigned int *rsp_len,
-                       unsigned int max_rsp_len)
+                       struct rsp_buffer *rsp)
 {
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
@@ -825,8 +836,7 @@ static void cold_reset(IPMIBmcSim *ibs,
 
 static void warm_reset(IPMIBmcSim *ibs,
                        uint8_t *cmd, unsigned int cmd_len,
-                       uint8_t *rsp, unsigned int *rsp_len,
-                       unsigned int max_rsp_len)
+                       struct rsp_buffer *rsp)
 {
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
@@ -836,55 +846,49 @@ static void warm_reset(IPMIBmcSim *ibs,
     }
 }
 static void set_acpi_power_state(IPMIBmcSim *ibs,
-                          uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                                 uint8_t *cmd, unsigned int cmd_len,
+                                 struct rsp_buffer *rsp)
 {
     ibs->acpi_power_state[0] = cmd[2];
     ibs->acpi_power_state[1] = cmd[3];
 }
 
 static void get_acpi_power_state(IPMIBmcSim *ibs,
-                          uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                                 uint8_t *cmd, unsigned int cmd_len,
+                                 struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[0]);
-    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[1]);
+    rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
+    rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
 }
 
 static void get_device_guid(IPMIBmcSim *ibs,
-                          uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                            uint8_t *cmd, unsigned int cmd_len,
+                            struct rsp_buffer *rsp)
 {
     unsigned int i;
 
     for (i = 0; i < 16; i++) {
-        IPMI_ADD_RSP_DATA(ibs->uuid[i]);
+        rsp_buffer_push(rsp, ibs->uuid[i]);
     }
 }
 
 static void set_bmc_global_enables(IPMIBmcSim *ibs,
                                    uint8_t *cmd, unsigned int cmd_len,
-                                   uint8_t *rsp, unsigned int *rsp_len,
-                                   unsigned int max_rsp_len)
+                                   struct rsp_buffer *rsp)
 {
     set_global_enables(ibs, cmd[2]);
 }
 
 static void get_bmc_global_enables(IPMIBmcSim *ibs,
                                    uint8_t *cmd, unsigned int cmd_len,
-                                   uint8_t *rsp, unsigned int *rsp_len,
-                                   unsigned int max_rsp_len)
+                                   struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
+    rsp_buffer_push(rsp, ibs->bmc_global_enables);
 }
 
 static void clr_msg_flags(IPMIBmcSim *ibs,
                           uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                          struct rsp_buffer *rsp)
 {
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
@@ -895,27 +899,25 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
 
 static void get_msg_flags(IPMIBmcSim *ibs,
                           uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                          struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(ibs->msg_flags);
+    rsp_buffer_push(rsp, ibs->msg_flags);
 }
 
 static void read_evt_msg_buf(IPMIBmcSim *ibs,
                              uint8_t *cmd, unsigned int cmd_len,
-                             uint8_t *rsp, unsigned int *rsp_len,
-                            unsigned int max_rsp_len)
+                             struct rsp_buffer *rsp)
 {
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
     unsigned int i;
 
     if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
-        rsp[2] = 0x80;
+        rsp->buffer[2] = 0x80;
         return;
     }
     for (i = 0; i < 16; i++) {
-        IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
+        rsp_buffer_push(rsp, ibs->evtbuf[i]);
     }
     ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
     k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
@@ -923,21 +925,18 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs,
 
 static void get_msg(IPMIBmcSim *ibs,
                     uint8_t *cmd, unsigned int cmd_len,
-                    uint8_t *rsp, unsigned int *rsp_len,
-                    unsigned int max_rsp_len)
+                    struct rsp_buffer *rsp)
 {
     IPMIRcvBufEntry *msg;
 
     qemu_mutex_lock(&ibs->lock);
     if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
-        rsp[2] = 0x80; /* Queue empty */
+        rsp->buffer[2] = 0x80; /* Queue empty */
         goto out;
     }
-    rsp[3] = 0; /* Channel 0 */
-    *rsp_len += 1;
+    rsp_buffer_push(rsp, 0); /* Channel 0 */
     msg = QTAILQ_FIRST(&ibs->rcvbufs);
-    memcpy(rsp + 4, msg->buf, msg->len);
-    *rsp_len += msg->len;
+    rsp_buffer_pushmore(rsp, msg->buf, msg->len);
     QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
     g_free(msg);
 
@@ -966,8 +965,7 @@ ipmb_checksum(unsigned char *data, int size, unsigned char csum)
 
 static void send_msg(IPMIBmcSim *ibs,
                      uint8_t *cmd, unsigned int cmd_len,
-                     uint8_t *rsp, unsigned int *rsp_len,
-                     unsigned int max_rsp_len)
+                     struct rsp_buffer *rsp)
 {
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
@@ -977,18 +975,18 @@ static void send_msg(IPMIBmcSim *ibs,
 
     if (cmd[2] != 0) {
         /* We only handle channel 0 with no options */
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
 
     if (cmd_len < 10) {
-        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
         return;
     }
 
     if (cmd[3] != 0x40) {
         /* We only emulate a MC at address 0x40. */
-        rsp[2] = 0x83; /* NAK on write */
+        rsp->buffer[2] = 0x83; /* NAK on write */
         return;
     }
 
@@ -1074,11 +1072,10 @@ static void do_watchdog_reset(IPMIBmcSim *ibs)
 
 static void reset_watchdog_timer(IPMIBmcSim *ibs,
                                  uint8_t *cmd, unsigned int cmd_len,
-                                 uint8_t *rsp, unsigned int *rsp_len,
-                                 unsigned int max_rsp_len)
+                                 struct rsp_buffer *rsp)
 {
     if (!ibs->watchdog_initialized) {
-        rsp[2] = 0x80;
+        rsp->buffer[2] = 0x80;
         return;
     }
     do_watchdog_reset(ibs);
@@ -1086,8 +1083,7 @@ static void reset_watchdog_timer(IPMIBmcSim *ibs,
 
 static void set_watchdog_timer(IPMIBmcSim *ibs,
                                uint8_t *cmd, unsigned int cmd_len,
-                               uint8_t *rsp, unsigned int *rsp_len,
-                               unsigned int max_rsp_len)
+                               struct rsp_buffer *rsp)
 {
     IPMIInterface *s = ibs->parent.intf;
     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
@@ -1095,7 +1091,7 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
 
     val = cmd[2] & 0x7; /* Validate use */
     if (val == 0 || val > 5) {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
     val = cmd[3] & 0x7; /* Validate action */
@@ -1104,22 +1100,22 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
         break;
 
     case IPMI_BMC_WATCHDOG_ACTION_RESET:
-        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
         break;
 
     case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
-        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
         break;
 
     case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
-        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
+        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
         break;
 
     default:
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
     }
-    if (rsp[2]) {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+    if (rsp->buffer[2]) {
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
 
@@ -1132,14 +1128,14 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
     case IPMI_BMC_WATCHDOG_PRE_NMI:
         if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
             /* NMI not supported. */
-            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+            rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
             return;
         }
         break;
 
     default:
         /* We don't support PRE_SMI */
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
 
@@ -1158,60 +1154,56 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
 
 static void get_watchdog_timer(IPMIBmcSim *ibs,
                                uint8_t *cmd, unsigned int cmd_len,
-                               uint8_t *rsp, unsigned int *rsp_len,
-                               unsigned int max_rsp_len)
+                               struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(ibs->watchdog_use);
-    IPMI_ADD_RSP_DATA(ibs->watchdog_action);
-    IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
-    IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
+    rsp_buffer_push(rsp, ibs->watchdog_use);
+    rsp_buffer_push(rsp, ibs->watchdog_action);
+    rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
+    rsp_buffer_push(rsp, ibs->watchdog_expired);
     if (ibs->watchdog_running) {
         long timeout;
         timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
                    / 100000000);
-        IPMI_ADD_RSP_DATA(timeout & 0xff);
-        IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
+        rsp_buffer_push(rsp, timeout & 0xff);
+        rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
     } else {
-        IPMI_ADD_RSP_DATA(0);
-        IPMI_ADD_RSP_DATA(0);
+        rsp_buffer_push(rsp, 0);
+        rsp_buffer_push(rsp, 0);
     }
 }
 
 static void get_sdr_rep_info(IPMIBmcSim *ibs,
                              uint8_t *cmd, unsigned int cmd_len,
-                             uint8_t *rsp, unsigned int *rsp_len,
-                             unsigned int max_rsp_len)
+                             struct rsp_buffer *rsp)
 {
     unsigned int i;
 
-    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
-    IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
-    IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
-    IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
-    IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
+    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
+    rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
+    rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
+    rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
+    rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
     for (i = 0; i < 4; i++) {
-        IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
+        rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
     }
     for (i = 0; i < 4; i++) {
-        IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
+        rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
     }
     /* Only modal support, reserve supported */
-    IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
+    rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
 }
 
 static void reserve_sdr_rep(IPMIBmcSim *ibs,
                             uint8_t *cmd, unsigned int cmd_len,
-                            uint8_t *rsp, unsigned int *rsp_len,
-                            unsigned int max_rsp_len)
+                            struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
-    IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
+    rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
+    rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
 }
 
 static void get_sdr(IPMIBmcSim *ibs,
                     uint8_t *cmd, unsigned int cmd_len,
-                    uint8_t *rsp, unsigned int *rsp_len,
-                    unsigned int max_rsp_len)
+                    struct rsp_buffer *rsp)
 {
     unsigned int pos;
     uint16_t nextrec;
@@ -1223,108 +1215,103 @@ static void get_sdr(IPMIBmcSim *ibs,
     pos = 0;
     if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
                        &pos, &nextrec)) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
 
     sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
 
     if (cmd[6] > ipmi_sdr_length(sdrh)) {
-        rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
+        rsp->buffer[2] = IPMI_CC_PARM_OUT_OF_RANGE;
         return;
     }
 
-    IPMI_ADD_RSP_DATA(nextrec & 0xff);
-    IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
+    rsp_buffer_push(rsp, nextrec & 0xff);
+    rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
 
     if (cmd[7] == 0xff) {
         cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
     }
 
-    if ((cmd[7] + *rsp_len) > max_rsp_len) {
-        rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
+    if ((cmd[7] + rsp->len) > rsp->max_len) {
+        rsp->buffer[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
         return;
     }
-    memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
-    *rsp_len += cmd[7];
+
+    rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
 }
 
 static void add_sdr(IPMIBmcSim *ibs,
                     uint8_t *cmd, unsigned int cmd_len,
-                    uint8_t *rsp, unsigned int *rsp_len,
-                    unsigned int max_rsp_len)
+                    struct rsp_buffer *rsp)
 {
     uint16_t recid;
     struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
 
     if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
-    IPMI_ADD_RSP_DATA(recid & 0xff);
-    IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
+    rsp_buffer_push(rsp, recid & 0xff);
+    rsp_buffer_push(rsp, (recid >> 8) & 0xff);
 }
 
 static void clear_sdr_rep(IPMIBmcSim *ibs,
                           uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                          struct rsp_buffer *rsp)
 {
     IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
     if (cmd[7] == 0xaa) {
         ibs->sdr.next_free = 0;
         ibs->sdr.overflow = 0;
         set_timestamp(ibs, ibs->sdr.last_clear);
-        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
+        rsp_buffer_push(rsp, 1); /* Erasure complete */
         sdr_inc_reservation(&ibs->sdr);
     } else if (cmd[7] == 0) {
-        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
+        rsp_buffer_push(rsp, 1); /* Erasure complete */
     } else {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
 }
 
 static void get_sel_info(IPMIBmcSim *ibs,
                          uint8_t *cmd, unsigned int cmd_len,
-                         uint8_t *rsp, unsigned int *rsp_len,
-                         unsigned int max_rsp_len)
+                         struct rsp_buffer *rsp)
 {
     unsigned int i, val;
 
-    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
-    IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
-    IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
+    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
+    rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
+    rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
     val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
-    IPMI_ADD_RSP_DATA(val & 0xff);
-    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
+    rsp_buffer_push(rsp, val & 0xff);
+    rsp_buffer_push(rsp, (val >> 8) & 0xff);
     for (i = 0; i < 4; i++) {
-        IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
+        rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
     }
     for (i = 0; i < 4; i++) {
-        IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
+        rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
     }
     /* Only support Reserve SEL */
-    IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
+    rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
 }
 
 static void reserve_sel(IPMIBmcSim *ibs,
                         uint8_t *cmd, unsigned int cmd_len,
-                        uint8_t *rsp, unsigned int *rsp_len,
-                        unsigned int max_rsp_len)
+                        struct rsp_buffer *rsp)
 {
-    IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
-    IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
+    rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
+    rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
 }
 
 static void get_sel_entry(IPMIBmcSim *ibs,
                           uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                          struct rsp_buffer *rsp)
 {
     unsigned int val;
 
@@ -1332,17 +1319,17 @@ static void get_sel_entry(IPMIBmcSim *ibs,
         IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
     }
     if (ibs->sel.next_free == 0) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     if (cmd[6] > 15) {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
     if (cmd[7] == 0xff) {
         cmd[7] = 16;
     } else if ((cmd[7] + cmd[6]) > 16) {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     } else {
         cmd[7] += cmd[6];
@@ -1352,79 +1339,75 @@ static void get_sel_entry(IPMIBmcSim *ibs,
     if (val == 0xffff) {
         val = ibs->sel.next_free - 1;
     } else if (val >= ibs->sel.next_free) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     if ((val + 1) == ibs->sel.next_free) {
-        IPMI_ADD_RSP_DATA(0xff);
-        IPMI_ADD_RSP_DATA(0xff);
+        rsp_buffer_push(rsp, 0xff);
+        rsp_buffer_push(rsp, 0xff);
     } else {
-        IPMI_ADD_RSP_DATA((val + 1) & 0xff);
-        IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
+        rsp_buffer_push(rsp, (val + 1) & 0xff);
+        rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
     }
     for (; cmd[6] < cmd[7]; cmd[6]++) {
-        IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
+        rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
     }
 }
 
 static void add_sel_entry(IPMIBmcSim *ibs,
                           uint8_t *cmd, unsigned int cmd_len,
-                          uint8_t *rsp, unsigned int *rsp_len,
-                          unsigned int max_rsp_len)
+                          struct rsp_buffer *rsp)
 {
     if (sel_add_event(ibs, cmd + 2)) {
-        rsp[2] = IPMI_CC_OUT_OF_SPACE;
+        rsp->buffer[2] = IPMI_CC_OUT_OF_SPACE;
         return;
     }
     /* sel_add_event fills in the record number. */
-    IPMI_ADD_RSP_DATA(cmd[2]);
-    IPMI_ADD_RSP_DATA(cmd[3]);
+    rsp_buffer_push(rsp, cmd[2]);
+    rsp_buffer_push(rsp, cmd[3]);
 }
 
 static void clear_sel(IPMIBmcSim *ibs,
                       uint8_t *cmd, unsigned int cmd_len,
-                      uint8_t *rsp, unsigned int *rsp_len,
-                      unsigned int max_rsp_len)
+                      struct rsp_buffer *rsp)
 {
     IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
     if (cmd[7] == 0xaa) {
         ibs->sel.next_free = 0;
         ibs->sel.overflow = 0;
         set_timestamp(ibs, ibs->sdr.last_clear);
-        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
+        rsp_buffer_push(rsp, 1); /* Erasure complete */
         sel_inc_reservation(&ibs->sel);
     } else if (cmd[7] == 0) {
-        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
+        rsp_buffer_push(rsp, 1); /* Erasure complete */
     } else {
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
 }
 
 static void get_sel_time(IPMIBmcSim *ibs,
                          uint8_t *cmd, unsigned int cmd_len,
-                         uint8_t *rsp, unsigned int *rsp_len,
-                         unsigned int max_rsp_len)
+                         struct rsp_buffer *rsp)
 {
     uint32_t val;
     struct ipmi_time now;
 
     ipmi_gettime(&now);
     val = now.tv_sec + ibs->sel.time_offset;
-    IPMI_ADD_RSP_DATA(val & 0xff);
-    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
-    IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
-    IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
+    rsp_buffer_push(rsp, val & 0xff);
+    rsp_buffer_push(rsp, (val >> 8) & 0xff);
+    rsp_buffer_push(rsp, (val >> 16) & 0xff);
+    rsp_buffer_push(rsp, (val >> 24) & 0xff);
 }
 
 static void set_sel_time(IPMIBmcSim *ibs,
                          uint8_t *cmd, unsigned int cmd_len,
-                         uint8_t *rsp, unsigned int *rsp_len,
-                         unsigned int max_rsp_len)
+                         struct rsp_buffer *rsp)
 {
     uint32_t val;
     struct ipmi_time now;
@@ -1436,14 +1419,13 @@ static void set_sel_time(IPMIBmcSim *ibs,
 
 static void set_sensor_evt_enable(IPMIBmcSim *ibs,
                                   uint8_t *cmd, unsigned int cmd_len,
-                                  uint8_t *rsp, unsigned int *rsp_len,
-                                  unsigned int max_rsp_len)
+                                  struct rsp_buffer *rsp)
 {
     IPMISensor *sens;
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1479,7 +1461,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
         }
         break;
     case 3:
-        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
     }
     IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
@@ -1487,34 +1469,32 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
 
 static void get_sensor_evt_enable(IPMIBmcSim *ibs,
                                   uint8_t *cmd, unsigned int cmd_len,
-                                  uint8_t *rsp, unsigned int *rsp_len,
-                                  unsigned int max_rsp_len)
+                                  struct rsp_buffer *rsp)
 {
     IPMISensor *sens;
 
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     sens = ibs->sensors + cmd[2];
-    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
-    IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
-    IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
-    IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
-    IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
+    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
+    rsp_buffer_push(rsp, sens->assert_enable & 0xff);
+    rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
+    rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
+    rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
 }
 
 static void rearm_sensor_evts(IPMIBmcSim *ibs,
                               uint8_t *cmd, unsigned int cmd_len,
-                              uint8_t *rsp, unsigned int *rsp_len,
-                              unsigned int max_rsp_len)
+                              struct rsp_buffer *rsp)
 {
     IPMISensor *sens;
 
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1528,57 +1508,54 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
 
 static void get_sensor_evt_status(IPMIBmcSim *ibs,
                                   uint8_t *cmd, unsigned int cmd_len,
-                                  uint8_t *rsp, unsigned int *rsp_len,
-                                  unsigned int max_rsp_len)
+                                  struct rsp_buffer *rsp)
 {
     IPMISensor *sens;
 
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     sens = ibs->sensors + cmd[2];
-    IPMI_ADD_RSP_DATA(sens->reading);
-    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
-    IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
-    IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
-    IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
-    IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
+    rsp_buffer_push(rsp, sens->reading);
+    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
+    rsp_buffer_push(rsp, sens->assert_states & 0xff);
+    rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
+    rsp_buffer_push(rsp, sens->deassert_states & 0xff);
+    rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
 }
 
 static void get_sensor_reading(IPMIBmcSim *ibs,
                                uint8_t *cmd, unsigned int cmd_len,
-                               uint8_t *rsp, unsigned int *rsp_len,
-                               unsigned int max_rsp_len)
+                               struct rsp_buffer *rsp)
 {
     IPMISensor *sens;
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     sens = ibs->sensors + cmd[2];
-    IPMI_ADD_RSP_DATA(sens->reading);
-    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
-    IPMI_ADD_RSP_DATA(sens->states & 0xff);
+    rsp_buffer_push(rsp, sens->reading);
+    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
+    rsp_buffer_push(rsp, sens->states & 0xff);
     if (IPMI_SENSOR_IS_DISCRETE(sens)) {
-        IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
+        rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
     }
 }
 
 static void set_sensor_type(IPMIBmcSim *ibs,
-                               uint8_t *cmd, unsigned int cmd_len,
-                               uint8_t *rsp, unsigned int *rsp_len,
-                               unsigned int max_rsp_len)
+                            uint8_t *cmd, unsigned int cmd_len,
+                            struct rsp_buffer *rsp)
 {
     IPMISensor *sens;
 
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1587,21 +1564,20 @@ static void set_sensor_type(IPMIBmcSim *ibs,
 }
 
 static void get_sensor_type(IPMIBmcSim *ibs,
-                               uint8_t *cmd, unsigned int cmd_len,
-                               uint8_t *rsp, unsigned int *rsp_len,
-                               unsigned int max_rsp_len)
+                            uint8_t *cmd, unsigned int cmd_len,
+                            struct rsp_buffer *rsp)
 {
     IPMISensor *sens;
 
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
         return;
     }
     sens = ibs->sensors + cmd[2];
-    IPMI_ADD_RSP_DATA(sens->sensor_type);
-    IPMI_ADD_RSP_DATA(sens->evt_reading_type_code);
+    rsp_buffer_push(rsp, sens->sensor_type);
+    rsp_buffer_push(rsp, sens->evt_reading_type_code);
 }
 
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 03/10] ipmi: remove IPMI_CHECK_RESERVATION() macro
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-02 15:40   ` Corey Minyard
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 04/10] ipmi: add rsp_buffer_set_error() helper Cédric Le Goater
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

Some IPMI command handlers in the BMC simulator use a macro
IPMI_CHECK_RESERVATION() to check a SDR reservation but the macro
implicitly uses local variables. This patch simply removes it.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 hw/ipmi/ipmi_bmc_sim.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 32efb87c8232..72166a7da291 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -293,16 +293,6 @@ static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
     rsp->len += n;
 }
 
-/* Check that the reservation in the command is valid. */
-#define IPMI_CHECK_RESERVATION(off, r) \
-    do {                                                   \
-        if ((cmd[off] | (cmd[off + 1] << 8)) != r) {       \
-            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;     \
-            return;                                        \
-        }                                                  \
-    } while (0)
-
-
 static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
 
 static void ipmi_gettime(struct ipmi_time *time)
@@ -1210,8 +1200,12 @@ static void get_sdr(IPMIBmcSim *ibs,
     struct ipmi_sdr_header *sdrh;
 
     if (cmd[6]) {
-        IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
+        if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
+            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+            return;
+        }
     }
+
     pos = 0;
     if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
                        &pos, &nextrec)) {
@@ -1260,7 +1254,11 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
                           uint8_t *cmd, unsigned int cmd_len,
                           struct rsp_buffer *rsp)
 {
-    IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
+    if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
+        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+        return;
+    }
+
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
         rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
@@ -1316,7 +1314,10 @@ static void get_sel_entry(IPMIBmcSim *ibs,
     unsigned int val;
 
     if (cmd[6]) {
-        IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
+        if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
+            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+            return;
+        }
     }
     if (ibs->sel.next_free == 0) {
         rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
@@ -1371,7 +1372,11 @@ static void clear_sel(IPMIBmcSim *ibs,
                       uint8_t *cmd, unsigned int cmd_len,
                       struct rsp_buffer *rsp)
 {
-    IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
+    if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
+        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+        return;
+    }
+
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
         rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
         return;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 04/10] ipmi: add rsp_buffer_set_error() helper
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
                   ` (2 preceding siblings ...)
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 03/10] ipmi: remove IPMI_CHECK_RESERVATION() macro Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-05 11:42   ` Corey Minyard
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 05/10] ipmi: add a realize function to the device class Cédric Le Goater
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

The third byte in the response buffer of an IPMI command holds the
error code. In many IPMI command handlers, this byte is updated
directly. This patch adds a helper routine to clarify why this byte is
being used.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 hw/ipmi/ipmi_bmc_sim.c | 115 ++++++++++++++++++++++++++-----------------------
 1 file changed, 60 insertions(+), 55 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 72166a7da291..2626aff06c60 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -271,11 +271,16 @@ struct rsp_buffer {
 
 #define RSP_BUFFER_INITIALIZER { { 0 }, 0, MAX_IPMI_MSG_SIZE }
 
+static inline void rsp_buffer_set_error(struct rsp_buffer *rsp, uint8_t byte)
+{
+    rsp->buffer[2] = byte;
+}
+
 /* Add a byte to the response. */
 static inline void rsp_buffer_push(struct rsp_buffer *rsp, uint8_t byte)
 {
     if (rsp->len >= rsp->max_len) {
-        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
         return;
     }
     rsp->buffer[rsp->len++] = byte;
@@ -285,7 +290,7 @@ static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
                                        unsigned int n)
 {
     if (rsp->len + n >= rsp->max_len) {
-        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
         return;
     }
 
@@ -599,7 +604,7 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
     /* Set up the response, set the low bit of NETFN. */
     /* Note that max_rsp_len must be at least 3 */
     if (rsp.max_len < 3) {
-        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
         goto out;
     }
 
@@ -609,17 +614,17 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
 
     /* If it's too short or it was truncated, return an error. */
     if (cmd_len < 2) {
-        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
         goto out;
     }
     if (cmd_len > max_cmd_len) {
-        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
         goto out;
     }
 
     if ((cmd[0] & 0x03) != 0) {
         /* Only have stuff on LUN 0 */
-        rsp.buffer[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
+        rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
         goto out;
     }
 
@@ -629,12 +634,12 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
     if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
         (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
         (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
-        rsp.buffer[2] = IPMI_CC_INVALID_CMD;
+        rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
         goto out;
     }
 
     if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
-        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
         goto out;
     }
 
@@ -745,26 +750,26 @@ static void chassis_control(IPMIBmcSim *ibs,
 
     switch (cmd[2] & 0xf) {
     case 0: /* power down */
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
         break;
     case 1: /* power up */
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
         break;
     case 2: /* power cycle */
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
         break;
     case 3: /* hard reset */
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
         break;
     case 4: /* pulse diagnostic interrupt */
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
         break;
     case 5: /* soft shutdown via ACPI by overtemp emulation */
-        rsp->buffer[2] = k->do_hw_op(s,
-                             IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s,
+                                          IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
         break;
     default:
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
 }
@@ -903,7 +908,7 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs,
     unsigned int i;
 
     if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
-        rsp->buffer[2] = 0x80;
+        rsp_buffer_set_error(rsp, 0x80);
         return;
     }
     for (i = 0; i < 16; i++) {
@@ -921,7 +926,7 @@ static void get_msg(IPMIBmcSim *ibs,
 
     qemu_mutex_lock(&ibs->lock);
     if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
-        rsp->buffer[2] = 0x80; /* Queue empty */
+        rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
         goto out;
     }
     rsp_buffer_push(rsp, 0); /* Channel 0 */
@@ -965,18 +970,18 @@ static void send_msg(IPMIBmcSim *ibs,
 
     if (cmd[2] != 0) {
         /* We only handle channel 0 with no options */
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
 
     if (cmd_len < 10) {
-        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
         return;
     }
 
     if (cmd[3] != 0x40) {
         /* We only emulate a MC at address 0x40. */
-        rsp->buffer[2] = 0x83; /* NAK on write */
+        rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
         return;
     }
 
@@ -1065,7 +1070,7 @@ static void reset_watchdog_timer(IPMIBmcSim *ibs,
                                  struct rsp_buffer *rsp)
 {
     if (!ibs->watchdog_initialized) {
-        rsp->buffer[2] = 0x80;
+        rsp_buffer_set_error(rsp, 0x80);
         return;
     }
     do_watchdog_reset(ibs);
@@ -1081,7 +1086,7 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
 
     val = cmd[2] & 0x7; /* Validate use */
     if (val == 0 || val > 5) {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
     val = cmd[3] & 0x7; /* Validate action */
@@ -1090,22 +1095,22 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
         break;
 
     case IPMI_BMC_WATCHDOG_ACTION_RESET:
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
         break;
 
     case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
         break;
 
     case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
-        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
+        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
         break;
 
     default:
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
     }
     if (rsp->buffer[2]) {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
 
@@ -1118,14 +1123,14 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
     case IPMI_BMC_WATCHDOG_PRE_NMI:
         if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
             /* NMI not supported. */
-            rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
             return;
         }
         break;
 
     default:
         /* We don't support PRE_SMI */
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
 
@@ -1201,7 +1206,7 @@ static void get_sdr(IPMIBmcSim *ibs,
 
     if (cmd[6]) {
         if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
-            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
             return;
         }
     }
@@ -1209,14 +1214,14 @@ static void get_sdr(IPMIBmcSim *ibs,
     pos = 0;
     if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
                        &pos, &nextrec)) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
 
     sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
 
     if (cmd[6] > ipmi_sdr_length(sdrh)) {
-        rsp->buffer[2] = IPMI_CC_PARM_OUT_OF_RANGE;
+        rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
         return;
     }
 
@@ -1228,7 +1233,7 @@ static void get_sdr(IPMIBmcSim *ibs,
     }
 
     if ((cmd[7] + rsp->len) > rsp->max_len) {
-        rsp->buffer[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
+        rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
         return;
     }
 
@@ -1243,7 +1248,7 @@ static void add_sdr(IPMIBmcSim *ibs,
     struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
 
     if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
     rsp_buffer_push(rsp, recid & 0xff);
@@ -1255,12 +1260,12 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
                           struct rsp_buffer *rsp)
 {
     if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
-        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
         return;
     }
 
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
     if (cmd[7] == 0xaa) {
@@ -1272,7 +1277,7 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
     } else if (cmd[7] == 0) {
         rsp_buffer_push(rsp, 1); /* Erasure complete */
     } else {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
 }
@@ -1315,22 +1320,22 @@ static void get_sel_entry(IPMIBmcSim *ibs,
 
     if (cmd[6]) {
         if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
-            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
             return;
         }
     }
     if (ibs->sel.next_free == 0) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     if (cmd[6] > 15) {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
     if (cmd[7] == 0xff) {
         cmd[7] = 16;
     } else if ((cmd[7] + cmd[6]) > 16) {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     } else {
         cmd[7] += cmd[6];
@@ -1340,7 +1345,7 @@ static void get_sel_entry(IPMIBmcSim *ibs,
     if (val == 0xffff) {
         val = ibs->sel.next_free - 1;
     } else if (val >= ibs->sel.next_free) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     if ((val + 1) == ibs->sel.next_free) {
@@ -1360,7 +1365,7 @@ static void add_sel_entry(IPMIBmcSim *ibs,
                           struct rsp_buffer *rsp)
 {
     if (sel_add_event(ibs, cmd + 2)) {
-        rsp->buffer[2] = IPMI_CC_OUT_OF_SPACE;
+        rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
         return;
     }
     /* sel_add_event fills in the record number. */
@@ -1373,12 +1378,12 @@ static void clear_sel(IPMIBmcSim *ibs,
                       struct rsp_buffer *rsp)
 {
     if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
-        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
         return;
     }
 
     if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
     if (cmd[7] == 0xaa) {
@@ -1390,7 +1395,7 @@ static void clear_sel(IPMIBmcSim *ibs,
     } else if (cmd[7] == 0) {
         rsp_buffer_push(rsp, 1); /* Erasure complete */
     } else {
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
 }
@@ -1430,7 +1435,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1466,7 +1471,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
         }
         break;
     case 3:
-        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
         return;
     }
     IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
@@ -1480,7 +1485,7 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
 
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1499,7 +1504,7 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
 
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1519,7 +1524,7 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
 
     if ((cmd[2] >= MAX_SENSORS) ||
         !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1539,7 +1544,7 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1560,7 +1565,7 @@ static void set_sensor_type(IPMIBmcSim *ibs,
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     sens = ibs->sensors + cmd[2];
@@ -1577,7 +1582,7 @@ static void get_sensor_type(IPMIBmcSim *ibs,
 
     if ((cmd[2] >= MAX_SENSORS) ||
             !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
-        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
+        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
         return;
     }
     sens = ibs->sensors + cmd[2];
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 05/10] ipmi: add a realize function to the device class
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
                   ` (3 preceding siblings ...)
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 04/10] ipmi: add rsp_buffer_set_error() helper Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 06/10] ipmi: use a function to initialize the SDR table Cédric Le Goater
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

This will be useful to define and use properties when the object is
instantiated.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
---

Changes since v1:

 - removed empty properties.

 hw/ipmi/ipmi_bmc_sim.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 2626aff06c60..096f71010659 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1706,9 +1706,9 @@ static const VMStateDescription vmstate_ipmi_sim = {
     }
 };
 
-static void ipmi_sim_init(Object *obj)
+static void ipmi_sim_realize(DeviceState *dev, Error **errp)
 {
-    IPMIBmc *b = IPMI_BMC(obj);
+    IPMIBmc *b = IPMI_BMC(dev);
     unsigned int i;
     unsigned int recid;
     IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
@@ -1767,8 +1767,10 @@ static void ipmi_sim_init(Object *obj)
 
 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
 
+    dc->realize = ipmi_sim_realize;
     bk->handle_command = ipmi_sim_handle_command;
 }
 
@@ -1776,7 +1778,6 @@ static const TypeInfo ipmi_sim_type = {
     .name          = TYPE_IPMI_BMC_SIMULATOR,
     .parent        = TYPE_IPMI_BMC,
     .instance_size = sizeof(IPMIBmcSim),
-    .instance_init = ipmi_sim_init,
     .class_init    = ipmi_sim_class_init,
 };
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 06/10] ipmi: use a function to initialize the SDR table
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
                   ` (4 preceding siblings ...)
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 05/10] ipmi: add a realize function to the device class Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 07/10] ipmi: remove the need of an ending record in " Cédric Le Goater
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

This patch moves the code section initializing the sdrs in its own
routine to prepare ground for changes in the subsequent patches.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
---
 hw/ipmi/ipmi_bmc_sim.c | 49 ++++++++++++++++++++++++++++---------------------
 1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 096f71010659..1556332b9f5d 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1678,6 +1678,33 @@ static const uint8_t init_sdrs[] = {
     0xff, 0xff, 0x00, 0x00, 0x00
 };
 
+static void ipmi_sdr_init(IPMIBmcSim *ibs)
+{
+    unsigned int i;
+    unsigned int recid;
+
+    for (i = 0;;) {
+        struct ipmi_sdr_header *sdrh;
+        int len;
+        if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
+            error_report("Problem with recid 0x%4.4x", i);
+            return;
+        }
+        sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
+        len = ipmi_sdr_length(sdrh);
+        recid = ipmi_sdr_recid(sdrh);
+        if (recid == 0xffff) {
+            break;
+        }
+        if ((i + len) > sizeof(init_sdrs)) {
+            error_report("Problem with recid 0x%4.4x", i);
+            return;
+        }
+        sdr_add_entry(ibs, sdrh, len, NULL);
+        i += len;
+    }
+}
+
 static const VMStateDescription vmstate_ipmi_sim = {
     .name = TYPE_IPMI_BMC_SIMULATOR,
     .version_id = 1,
@@ -1710,7 +1737,6 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
 {
     IPMIBmc *b = IPMI_BMC(dev);
     unsigned int i;
-    unsigned int recid;
     IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
 
     qemu_mutex_init(&ibs->lock);
@@ -1727,26 +1753,7 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
         ibs->sdr.last_clear[i] = 0xff;
     }
 
-    for (i = 0;;) {
-        struct ipmi_sdr_header *sdrh;
-        int len;
-        if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
-            error_report("Problem with recid 0x%4.4x", i);
-            return;
-        }
-        sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
-        len = ipmi_sdr_length(sdrh);
-        recid = ipmi_sdr_recid(sdrh);
-        if (recid == 0xffff) {
-            break;
-        }
-        if ((i + len) > sizeof(init_sdrs)) {
-            error_report("Problem with recid 0x%4.4x", i);
-            return;
-        }
-        sdr_add_entry(ibs, sdrh, len, NULL);
-        i += len;
-    }
+    ipmi_sdr_init(ibs);
 
     ibs->acpi_power_state[0] = 0;
     ibs->acpi_power_state[1] = 0;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 07/10] ipmi: remove the need of an ending record in the SDR table
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
                   ` (5 preceding siblings ...)
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 06/10] ipmi: use a function to initialize the SDR table Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 08/10] ipmi: add some local variables in ipmi_sdr_init Cédric Le Goater
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

Currently, the code initializing the sdr table relies on an ending
record with a recid of 0xffff. This patch changes the loop to use the
sdr size as a breaking condition.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
---
 hw/ipmi/ipmi_bmc_sim.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 1556332b9f5d..522cafa0ab4d 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1674,34 +1674,27 @@ static const uint8_t init_sdrs[] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
     'W',  'a',  't',  'c',  'h',  'd',  'o',  'g',
-    /* End */
-    0xff, 0xff, 0x00, 0x00, 0x00
 };
 
 static void ipmi_sdr_init(IPMIBmcSim *ibs)
 {
     unsigned int i;
-    unsigned int recid;
+    int len;
 
-    for (i = 0;;) {
+    for (i = 0; i < sizeof(init_sdrs); i += len) {
         struct ipmi_sdr_header *sdrh;
-        int len;
+
         if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
             error_report("Problem with recid 0x%4.4x", i);
             return;
         }
         sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
         len = ipmi_sdr_length(sdrh);
-        recid = ipmi_sdr_recid(sdrh);
-        if (recid == 0xffff) {
-            break;
-        }
         if ((i + len) > sizeof(init_sdrs)) {
             error_report("Problem with recid 0x%4.4x", i);
             return;
         }
         sdr_add_entry(ibs, sdrh, len, NULL);
-        i += len;
     }
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 08/10] ipmi: add some local variables in ipmi_sdr_init
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
                   ` (6 preceding siblings ...)
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 07/10] ipmi: remove the need of an ending record in " Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 09/10] ipmi: use a file to load SDRs Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 10/10] ipmi: provide support for FRUs Cédric Le Goater
  9 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

This patch adds a couple of variables to manipulate the raw sdr
entries. The const attribute is also removed on init_sdrs. This will
ease the introduction of a sdr loader using a file.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
---
 hw/ipmi/ipmi_bmc_sim.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 522cafa0ab4d..a086eecafe3b 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1667,7 +1667,7 @@ static void register_cmds(IPMIBmcSim *s)
     ipmi_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
 }
 
-static const uint8_t init_sdrs[] = {
+static uint8_t init_sdrs[] = {
     /* Watchdog device */
     0x00, 0x00, 0x51, 0x02,   35, 0x20, 0x00, 0x00,
     0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
@@ -1680,17 +1680,22 @@ static void ipmi_sdr_init(IPMIBmcSim *ibs)
 {
     unsigned int i;
     int len;
+    size_t sdrs_size;
+    uint8_t *sdrs;
 
-    for (i = 0; i < sizeof(init_sdrs); i += len) {
+    sdrs_size = sizeof(init_sdrs);
+    sdrs = init_sdrs;
+
+    for (i = 0; i < sdrs_size; i += len) {
         struct ipmi_sdr_header *sdrh;
 
-        if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
+        if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
             error_report("Problem with recid 0x%4.4x", i);
             return;
         }
-        sdrh = (struct ipmi_sdr_header *) &init_sdrs[i];
+        sdrh = (struct ipmi_sdr_header *) &sdrs[i];
         len = ipmi_sdr_length(sdrh);
-        if ((i + len) > sizeof(init_sdrs)) {
+        if (i + len > sdrs_size) {
             error_report("Problem with recid 0x%4.4x", i);
             return;
         }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 09/10] ipmi: use a file to load SDRs
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
                   ` (7 preceding siblings ...)
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 08/10] ipmi: add some local variables in ipmi_sdr_init Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 10/10] ipmi: provide support for FRUs Cédric Le Goater
  9 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

The IPMI BMC simulator populates the sdr/sensor tables with a minimal
set of entries (Watchdog). But some qemu platforms might want to use
extra entries for their custom needs.

This patch modifies slighty the initializing routine to take into
account a larger set read from a file. The name of the file to use is
defined through a new 'sdr' property of the simulator device.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
---

Changes since v1:

 - log an error if file does not exist.
 - change property name to 'sdrfile'
 - add documentation of new properties
 
 hw/ipmi/ipmi_bmc_sim.c | 23 +++++++++++++++++++++--
 qemu-options.hx        | 11 ++++++++++-
 2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index a086eecafe3b..6b29b9e11bce 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -27,6 +27,7 @@
 #include "qemu/timer.h"
 #include "hw/ipmi/ipmi.h"
 #include "qemu/error-report.h"
+#include "hw/loader.h"
 
 #define IPMI_NETFN_CHASSIS            0x00
 
@@ -213,6 +214,7 @@ struct IPMIBmcSim {
     IPMISel sel;
     IPMISdr sdr;
     IPMISensor sensors[MAX_SENSORS];
+    char *sdr_filename;
 
     /* Odd netfns are for responses, so we only need the even ones. */
     const IPMINetfn *netfns[MAX_NETFNS / 2];
@@ -1685,22 +1687,33 @@ static void ipmi_sdr_init(IPMIBmcSim *ibs)
 
     sdrs_size = sizeof(init_sdrs);
     sdrs = init_sdrs;
+    if (ibs->sdr_filename &&
+        !g_file_get_contents(ibs->sdr_filename, (gchar **) &sdrs, &sdrs_size,
+                             NULL)) {
+        error_report("failed to load sdr file '%s'", ibs->sdr_filename);
+        sdrs_size = sizeof(init_sdrs);
+        sdrs = init_sdrs;
+    }
 
     for (i = 0; i < sdrs_size; i += len) {
         struct ipmi_sdr_header *sdrh;
 
         if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
             error_report("Problem with recid 0x%4.4x", i);
-            return;
+            break;
         }
         sdrh = (struct ipmi_sdr_header *) &sdrs[i];
         len = ipmi_sdr_length(sdrh);
         if (i + len > sdrs_size) {
             error_report("Problem with recid 0x%4.4x", i);
-            return;
+            break;
         }
         sdr_add_entry(ibs, sdrh, len, NULL);
     }
+
+    if (sdrs != init_sdrs) {
+        g_free(sdrs);
+    }
 }
 
 static const VMStateDescription vmstate_ipmi_sim = {
@@ -1770,12 +1783,18 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
     vmstate_register(NULL, 0, &vmstate_ipmi_sim, ibs);
 }
 
+static Property ipmi_sim_properties[] = {
+    DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void ipmi_sim_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);
 
     dc->realize = ipmi_sim_realize;
+    dc->props = ipmi_sim_properties;
     bk->handle_command = ipmi_sim_handle_command;
 }
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 144e6a9b764a..44c446146eed 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -388,7 +388,7 @@ possible drivers and properties, use @code{-device help} and
 @code{-device @var{driver},help}.
 
 Some drivers are:
-@item -device ipmi-bmc-sim,id=@var{id}[,slave_addr=@var{val}]
+@item -device ipmi-bmc-sim,id=@var{id}[,slave_addr=@var{val}][,sdrfile=@var{file}]
 
 Add an IPMI BMC.  This is a simulation of a hardware management
 interface processor that normally sits on a system.  It provides
@@ -400,6 +400,15 @@ This address is the BMC's address on the I2C network of management
 controllers.  If you don't know what this means, it is safe to ignore
 it.
 
+@table @option
+@item bmc=@var{id}
+The BMC to connect to, one of ipmi-bmc-sim or ipmi-bmc-extern above.
+@item slave_addr=@var{val}
+Define slave address to use for the BMC.  The default is 0x20.
+@item sdrfile=@var{file}
+file containing raw Sensor Data Records (SDR) data.  The default is none.
+@end table
+
 @item -device ipmi-bmc-extern,id=@var{id},chardev=@var{id}[,slave_addr=@var{val}]
 
 Add a connection to an external IPMI BMC simulator.  Instead of
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v2 10/10] ipmi: provide support for FRUs
  2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
                   ` (8 preceding siblings ...)
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 09/10] ipmi: use a file to load SDRs Cédric Le Goater
@ 2016-03-02 10:14 ` Cédric Le Goater
  9 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 10:14 UTC (permalink / raw)
  To: Corey Minyard
  Cc: Marcel Apfelbaum, Cédric Le Goater, qemu-devel, Michael S. Tsirkin

This patch provides a simple FRU support for the BMC simulator. FRUs
are loaded from a file which name is specified in the object
properties, each entry having a fixed size, also specified in the
properties. If the file is unknown or not accessible for some reason,
a unique entry of 1024 bytes is created as a default. Just enough to
start some simulation.

These commands complies with the IPMI spec : "34. FRU Inventory Device
Commands".

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
---

Changes since v1:

 - change property name to 'fruareasize' and 'frudatafile'
 - add documentation of new properties
 
 hw/ipmi/ipmi_bmc_sim.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-options.hx        |   8 ++-
 2 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 6b29b9e11bce..00b736f88af8 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -80,6 +80,9 @@
 #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE   0x2A
 #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE    0x2B
 #define IPMI_CMD_RUN_INIT_AGENT           0x2C
+#define IPMI_CMD_GET_FRU_AREA_INFO        0x10
+#define IPMI_CMD_READ_FRU_DATA            0x11
+#define IPMI_CMD_WRITE_FRU_DATA           0x12
 #define IPMI_CMD_GET_SEL_INFO             0x40
 #define IPMI_CMD_GET_SEL_ALLOC_INFO       0x41
 #define IPMI_CMD_RESERVE_SEL              0x42
@@ -122,6 +125,13 @@ typedef struct IPMISdr {
     uint8_t overflow;
 } IPMISdr;
 
+typedef struct IPMIFru {
+    char *filename;
+    unsigned int nentries;
+    uint16_t areasize;
+    uint8_t *data;
+} IPMIFru;
+
 typedef struct IPMISensor {
     uint8_t status;
     uint8_t reading;
@@ -213,6 +223,7 @@ struct IPMIBmcSim {
 
     IPMISel sel;
     IPMISdr sdr;
+    IPMIFru fru;
     IPMISensor sensors[MAX_SENSORS];
     char *sdr_filename;
 
@@ -1306,6 +1317,94 @@ static void get_sel_info(IPMIBmcSim *ibs,
     rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
 }
 
+static void get_fru_area_info(IPMIBmcSim *ibs,
+                         uint8_t *cmd, unsigned int cmd_len,
+                         struct rsp_buffer *rsp)
+{
+    uint8_t fruid;
+    uint16_t fru_entry_size;
+
+    fruid = cmd[2];
+
+    if (fruid >= ibs->fru.nentries) {
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+        return;
+    }
+
+    fru_entry_size = ibs->fru.areasize;
+
+    rsp_buffer_push(rsp, fru_entry_size & 0xff);
+    rsp_buffer_push(rsp, fru_entry_size >> 8 & 0xff);
+    rsp_buffer_push(rsp, 0x0);
+}
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
+static void read_fru_data(IPMIBmcSim *ibs,
+                         uint8_t *cmd, unsigned int cmd_len,
+                         struct rsp_buffer *rsp)
+{
+    uint8_t fruid;
+    uint16_t offset;
+    int i;
+    uint8_t *fru_entry;
+    unsigned int count;
+
+    fruid = cmd[2];
+    offset = (cmd[3] | cmd[4] << 8);
+
+    if (fruid >= ibs->fru.nentries) {
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+        return;
+    }
+
+    if (offset >= ibs->fru.areasize - 1) {
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+        return;
+    }
+
+    fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
+
+    count = min(cmd[5], ibs->fru.areasize - offset);
+
+    rsp_buffer_push(rsp, count & 0xff);
+    for (i = 0; i < count; i++) {
+        rsp_buffer_push(rsp, fru_entry[offset + i]);
+    }
+}
+
+static void write_fru_data(IPMIBmcSim *ibs,
+                         uint8_t *cmd, unsigned int cmd_len,
+                         struct rsp_buffer *rsp)
+{
+    uint8_t fruid;
+    uint16_t offset;
+    uint8_t *fru_entry;
+    unsigned int count;
+
+    fruid = cmd[2];
+    offset = (cmd[3] | cmd[4] << 8);
+
+    if (fruid >= ibs->fru.nentries) {
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+        return;
+    }
+
+    if (offset >= ibs->fru.areasize - 1) {
+        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+        return;
+    }
+
+    fru_entry = &ibs->fru.data[fruid * ibs->fru.areasize];
+
+    count = min(cmd_len - 5, ibs->fru.areasize - offset);
+
+    memcpy(fru_entry + offset, cmd + 5, count);
+
+    rsp_buffer_push(rsp, count & 0xff);
+}
+
 static void reserve_sel(IPMIBmcSim *ibs,
                         uint8_t *cmd, unsigned int cmd_len,
                         struct rsp_buffer *rsp)
@@ -1642,6 +1741,9 @@ static const IPMINetfn app_netfn = {
 };
 
 static const IPMICmdHandler storage_cmds[] = {
+    [IPMI_CMD_GET_FRU_AREA_INFO] = { get_fru_area_info, 3 },
+    [IPMI_CMD_READ_FRU_DATA] = { read_fru_data, 5 },
+    [IPMI_CMD_WRITE_FRU_DATA] = { write_fru_data, 5 },
     [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
     [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
     [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
@@ -1744,6 +1846,31 @@ static const VMStateDescription vmstate_ipmi_sim = {
     }
 };
 
+static void ipmi_fru_init(IPMIFru *fru)
+{
+    int fsize;
+    int size = 0;
+
+    fsize = get_image_size(fru->filename);
+    if (fsize > 0) {
+        size = QEMU_ALIGN_UP(fsize, fru->areasize);
+        fru->data = g_malloc0(size);
+        if (load_image_size(fru->filename, fru->data, fsize) != fsize) {
+            error_report("Could not load file '%s'", fru->filename);
+            g_free(fru->data);
+            fru->data = NULL;
+        }
+    }
+
+    if (!fru->data) {
+        /* give one default FRU */
+        size = fru->areasize;
+        fru->data = g_malloc0(size);
+    }
+
+    fru->nentries = size / fru->areasize;
+}
+
 static void ipmi_sim_realize(DeviceState *dev, Error **errp)
 {
     IPMIBmc *b = IPMI_BMC(dev);
@@ -1766,6 +1893,8 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
 
     ipmi_sdr_init(ibs);
 
+    ipmi_fru_init(&ibs->fru);
+
     ibs->acpi_power_state[0] = 0;
     ibs->acpi_power_state[1] = 0;
 
@@ -1784,6 +1913,8 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
 }
 
 static Property ipmi_sim_properties[] = {
+    DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
+    DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
     DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
     DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/qemu-options.hx b/qemu-options.hx
index 44c446146eed..51d5f59459e9 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -388,7 +388,7 @@ possible drivers and properties, use @code{-device help} and
 @code{-device @var{driver},help}.
 
 Some drivers are:
-@item -device ipmi-bmc-sim,id=@var{id}[,slave_addr=@var{val}][,sdrfile=@var{file}]
+@item -device ipmi-bmc-sim,id=@var{id}[,slave_addr=@var{val}][,sdrfile=@var{file}][,furareasize=@var{val}][,furdatafile=@var{file}]
 
 Add an IPMI BMC.  This is a simulation of a hardware management
 interface processor that normally sits on a system.  It provides
@@ -406,7 +406,11 @@ The BMC to connect to, one of ipmi-bmc-sim or ipmi-bmc-extern above.
 @item slave_addr=@var{val}
 Define slave address to use for the BMC.  The default is 0x20.
 @item sdrfile=@var{file}
-file containing raw Sensor Data Records (SDR) data.  The default is none.
+file containing raw Sensor Data Records (SDR) data. The default is none.
+@item fruareasize=@var{val}
+size of a Field Replaceable Unit (FRU) area.  The default is 1024.
+@item frudatafile=@var{file}
+file containing raw Field Replaceable Unit (FRU) inventory data. The default is none.
 @end table
 
 @item -device ipmi-bmc-extern,id=@var{id},chardev=@var{id}[,slave_addr=@var{val}]
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers Cédric Le Goater
@ 2016-03-02 10:25   ` Michael S. Tsirkin
  2016-03-02 17:53     ` Cédric Le Goater
  2016-03-05 11:41   ` Corey Minyard
  1 sibling, 1 reply; 23+ messages in thread
From: Michael S. Tsirkin @ 2016-03-02 10:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: Marcel Apfelbaum, Corey Minyard, qemu-devel

On Wed, Mar 02, 2016 at 11:14:50AM +0100, Cédric Le Goater wrote:
> The IPMI command handlers in the BMC simulator use a macro
> IPMI_ADD_RSP_DATA() to push bytes in a response buffer. The macro
> hides the fact that it implicitly uses variables local to the handler,
> which is misleading.
> 
> This patch introduces a simple 'struct rsp_buffer' and inlined helper
> routines to store byte(s) in a response buffer. rsp_buffer_push()
> replaces the macro IPMI_ADD_RSP_DATA() and rsp_buffer_pushmore() is
> new helper to push multiple bytes. The latest is used in the command
> handlers get_msg() and get_sdr() which are manipulating the buffer
> directly.
> 
> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>


Looks good overall.
Some stylistic comments.

> ---
>  hw/ipmi/ipmi_bmc_sim.c | 482 +++++++++++++++++++++++--------------------------
>  1 file changed, 229 insertions(+), 253 deletions(-)
> 
> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
> index 30b9fb48ea2d..32efb87c8232 100644
> --- a/hw/ipmi/ipmi_bmc_sim.c
> +++ b/hw/ipmi/ipmi_bmc_sim.c
> @@ -153,14 +153,14 @@ typedef struct IPMISensor {
>  #define IPMI_WATCHDOG_SENSOR 0
>  
>  typedef struct IPMIBmcSim IPMIBmcSim;
> +struct rsp_buffer;
>

typedef struct RspBuffer RspBuffer;

  
>  #define MAX_NETFNS 64
>  
>  typedef struct IPMICmdHandler {
>      void (*cmd_handler)(IPMIBmcSim *s,
>                          uint8_t *cmd, unsigned int cmd_len,
> -                        uint8_t *rsp, unsigned int *rsp_len,
> -                        unsigned int max_rsp_len);
> +                        struct rsp_buffer *rsp);
>      unsigned int cmd_len_min;
>  } IPMICmdHandler;
>  
> @@ -263,22 +263,41 @@ struct IPMIBmcSim {
>  #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
>  #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3
>  
> +struct rsp_buffer {
> +    uint8_t buffer[MAX_IPMI_MSG_SIZE];
> +    unsigned int len;
> +    unsigned int max_len;
> +};
> +
> +#define RSP_BUFFER_INITIALIZER { { 0 }, 0, MAX_IPMI_MSG_SIZE }

max_len seems to always be a constant. So just use ARRAY_SIZE(buffer)
and RSP_BUFFER_INITIALIZER can then be replaced with plain { };

>  
>  /* Add a byte to the response. */
> -#define IPMI_ADD_RSP_DATA(b) \
> -    do {                                                   \
> -        if (*rsp_len >= max_rsp_len) {                     \
> -            rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;       \
> -            return;                                        \
> -        }                                                  \
> -        rsp[(*rsp_len)++] = (b);                           \
> -    } while (0)
> +static inline void rsp_buffer_push(struct rsp_buffer *rsp, uint8_t byte)
> +{
> +    if (rsp->len >= rsp->max_len) {

Why not simply
	rsp->len >= ARRAY_SIZE(rsp->buffer)
?



> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        return;
> +    }
> +    rsp->buffer[rsp->len++] = byte;
> +}
> +
> +static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
> +                                       unsigned int n)
> +{
> +    if (rsp->len + n >= rsp->max_len) {
> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        return;
> +    }
> +
> +    memcpy(&rsp->buffer[rsp->len], bytes, n);
> +    rsp->len += n;
> +}
>  
>  /* Check that the reservation in the command is valid. */
>  #define IPMI_CHECK_RESERVATION(off, r) \
>      do {                                                   \
>          if ((cmd[off] | (cmd[off + 1] << 8)) != r) {       \
> -            rsp[2] = IPMI_CC_INVALID_RESERVATION;          \
> +            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;     \
>              return;                                        \
>          }                                                  \
>      } while (0)
> @@ -585,35 +604,32 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>      unsigned int netfn;
> -    uint8_t rsp[MAX_IPMI_MSG_SIZE];
> -    unsigned int rsp_len_holder = 0;
> -    unsigned int *rsp_len = &rsp_len_holder;
> -    unsigned int max_rsp_len = sizeof(rsp);
> +    struct rsp_buffer rsp = RSP_BUFFER_INITIALIZER;
>  
>      /* Set up the response, set the low bit of NETFN. */
>      /* Note that max_rsp_len must be at least 3 */
> -    if (max_rsp_len < 3) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +    if (rsp.max_len < 3) {
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>          goto out;
>      }
>  
> -    IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
> -    IPMI_ADD_RSP_DATA(cmd[1]);
> -    IPMI_ADD_RSP_DATA(0); /* Assume success */
> +    rsp_buffer_push(&rsp, cmd[0] | 0x04);
> +    rsp_buffer_push(&rsp, cmd[1]);
> +    rsp_buffer_push(&rsp, 0); /* Assume success */
>  
>      /* If it's too short or it was truncated, return an error. */
>      if (cmd_len < 2) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>          goto out;
>      }
>      if (cmd_len > max_cmd_len) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>          goto out;
>      }
>  
>      if ((cmd[0] & 0x03) != 0) {
>          /* Only have stuff on LUN 0 */
> -        rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
> +        rsp.buffer[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
>          goto out;
>      }
>  
> @@ -623,20 +639,20 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>      if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>          (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>          (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
> -        rsp[2] = IPMI_CC_INVALID_CMD;
> +        rsp.buffer[2] = IPMI_CC_INVALID_CMD;
>          goto out;
>      }
>  
>      if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>          goto out;
>      }
>  
>      ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
> -                                                rsp, rsp_len, max_rsp_len);
> +                                                &rsp);
>  
>   out:
> -    k->handle_rsp(s, msg_id, rsp, *rsp_len);
> +    k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
>  
>      next_timeout(ibs);
>  }
> @@ -711,86 +727,82 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
>  
>  static void chassis_capabilities(IPMIBmcSim *ibs,
>                                   uint8_t *cmd, unsigned int cmd_len,
> -                                 uint8_t *rsp, unsigned int *rsp_len,
> -                                 unsigned int max_rsp_len)
> +                                 struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(0);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, 0);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
>  }
>  
>  static void chassis_status(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                           uint8_t *rsp, unsigned int *rsp_len,
> -                           unsigned int max_rsp_len)
> +                           struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
> -    IPMI_ADD_RSP_DATA(0);
> -    IPMI_ADD_RSP_DATA(0);
> -    IPMI_ADD_RSP_DATA(0);
> +    rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
> +    rsp_buffer_push(rsp, 0);
> +    rsp_buffer_push(rsp, 0);
> +    rsp_buffer_push(rsp, 0);
>  }
>  
>  static void chassis_control(IPMIBmcSim *ibs,
>                              uint8_t *cmd, unsigned int cmd_len,
> -                            uint8_t *rsp, unsigned int *rsp_len,
> -                            unsigned int max_rsp_len)
> +                            struct rsp_buffer *rsp)
>  {
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>  
>      switch (cmd[2] & 0xf) {
>      case 0: /* power down */
> -        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>          break;
>      case 1: /* power up */
> -        rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
>          break;
>      case 2: /* power cycle */
> -        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
>          break;
>      case 3: /* hard reset */
> -        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
>          break;
>      case 4: /* pulse diagnostic interrupt */
> -        rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
>          break;
>      case 5: /* soft shutdown via ACPI by overtemp emulation */
> -        rsp[2] = k->do_hw_op(s,
> +        rsp->buffer[2] = k->do_hw_op(s,
>                               IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
>          break;
>      default:
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>  }
>  
>  static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                           uint8_t *rsp, unsigned int *rsp_len,
> -                           unsigned int max_rsp_len)
> +                           struct rsp_buffer *rsp)
> +
>  {
> -    IPMI_ADD_RSP_DATA(ibs->restart_cause & 0xf); /* Restart Cause */
> -    IPMI_ADD_RSP_DATA(0);  /* Channel 0 */
> +    rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
> +    rsp_buffer_push(rsp, 0);  /* Channel 0 */
>  }
>  
>  static void get_device_id(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> -{
> -    IPMI_ADD_RSP_DATA(ibs->device_id);
> -    IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
> -    IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
> -    IPMI_ADD_RSP_DATA(ibs->fwrev2);
> -    IPMI_ADD_RSP_DATA(ibs->ipmi_version);
> -    IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
> -    IPMI_ADD_RSP_DATA(ibs->product_id[0]);
> -    IPMI_ADD_RSP_DATA(ibs->product_id[1]);
> +                          struct rsp_buffer *rsp)
> +{
> +    rsp_buffer_push(rsp, ibs->device_id);
> +    rsp_buffer_push(rsp, ibs->device_rev & 0xf);
> +    rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
> +    rsp_buffer_push(rsp, ibs->fwrev2);
> +    rsp_buffer_push(rsp, ibs->ipmi_version);
> +    rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
> +    rsp_buffer_push(rsp, ibs->mfg_id[0]);
> +    rsp_buffer_push(rsp, ibs->mfg_id[1]);
> +    rsp_buffer_push(rsp, ibs->mfg_id[2]);
> +    rsp_buffer_push(rsp, ibs->product_id[0]);
> +    rsp_buffer_push(rsp, ibs->product_id[1]);
>  }
>  
>  static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
> @@ -809,8 +821,7 @@ static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
>  
>  static void cold_reset(IPMIBmcSim *ibs,
>                         uint8_t *cmd, unsigned int cmd_len,
> -                       uint8_t *rsp, unsigned int *rsp_len,
> -                       unsigned int max_rsp_len)
> +                       struct rsp_buffer *rsp)
>  {
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -825,8 +836,7 @@ static void cold_reset(IPMIBmcSim *ibs,
>  
>  static void warm_reset(IPMIBmcSim *ibs,
>                         uint8_t *cmd, unsigned int cmd_len,
> -                       uint8_t *rsp, unsigned int *rsp_len,
> -                       unsigned int max_rsp_len)
> +                       struct rsp_buffer *rsp)
>  {
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -836,55 +846,49 @@ static void warm_reset(IPMIBmcSim *ibs,
>      }
>  }
>  static void set_acpi_power_state(IPMIBmcSim *ibs,
> -                          uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                                 uint8_t *cmd, unsigned int cmd_len,
> +                                 struct rsp_buffer *rsp)
>  {
>      ibs->acpi_power_state[0] = cmd[2];
>      ibs->acpi_power_state[1] = cmd[3];
>  }
>  
>  static void get_acpi_power_state(IPMIBmcSim *ibs,
> -                          uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                                 uint8_t *cmd, unsigned int cmd_len,
> +                                 struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[0]);
> -    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[1]);
> +    rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
> +    rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
>  }
>  
>  static void get_device_guid(IPMIBmcSim *ibs,
> -                          uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                            uint8_t *cmd, unsigned int cmd_len,
> +                            struct rsp_buffer *rsp)
>  {
>      unsigned int i;
>  
>      for (i = 0; i < 16; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->uuid[i]);
> +        rsp_buffer_push(rsp, ibs->uuid[i]);
>      }
>  }
>  
>  static void set_bmc_global_enables(IPMIBmcSim *ibs,
>                                     uint8_t *cmd, unsigned int cmd_len,
> -                                   uint8_t *rsp, unsigned int *rsp_len,
> -                                   unsigned int max_rsp_len)
> +                                   struct rsp_buffer *rsp)
>  {
>      set_global_enables(ibs, cmd[2]);
>  }
>  
>  static void get_bmc_global_enables(IPMIBmcSim *ibs,
>                                     uint8_t *cmd, unsigned int cmd_len,
> -                                   uint8_t *rsp, unsigned int *rsp_len,
> -                                   unsigned int max_rsp_len)
> +                                   struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
> +    rsp_buffer_push(rsp, ibs->bmc_global_enables);
>  }
>  
>  static void clr_msg_flags(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>  {
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -895,27 +899,25 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>  
>  static void get_msg_flags(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(ibs->msg_flags);
> +    rsp_buffer_push(rsp, ibs->msg_flags);
>  }
>  
>  static void read_evt_msg_buf(IPMIBmcSim *ibs,
>                               uint8_t *cmd, unsigned int cmd_len,
> -                             uint8_t *rsp, unsigned int *rsp_len,
> -                            unsigned int max_rsp_len)
> +                             struct rsp_buffer *rsp)
>  {
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>      unsigned int i;
>  
>      if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
> -        rsp[2] = 0x80;
> +        rsp->buffer[2] = 0x80;
>          return;
>      }
>      for (i = 0; i < 16; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
> +        rsp_buffer_push(rsp, ibs->evtbuf[i]);
>      }
>      ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
>      k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
> @@ -923,21 +925,18 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs,
>  
>  static void get_msg(IPMIBmcSim *ibs,
>                      uint8_t *cmd, unsigned int cmd_len,
> -                    uint8_t *rsp, unsigned int *rsp_len,
> -                    unsigned int max_rsp_len)
> +                    struct rsp_buffer *rsp)
>  {
>      IPMIRcvBufEntry *msg;
>  
>      qemu_mutex_lock(&ibs->lock);
>      if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
> -        rsp[2] = 0x80; /* Queue empty */
> +        rsp->buffer[2] = 0x80; /* Queue empty */
>          goto out;
>      }
> -    rsp[3] = 0; /* Channel 0 */
> -    *rsp_len += 1;
> +    rsp_buffer_push(rsp, 0); /* Channel 0 */
>      msg = QTAILQ_FIRST(&ibs->rcvbufs);
> -    memcpy(rsp + 4, msg->buf, msg->len);
> -    *rsp_len += msg->len;
> +    rsp_buffer_pushmore(rsp, msg->buf, msg->len);
>      QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
>      g_free(msg);
>  
> @@ -966,8 +965,7 @@ ipmb_checksum(unsigned char *data, int size, unsigned char csum)
>  
>  static void send_msg(IPMIBmcSim *ibs,
>                       uint8_t *cmd, unsigned int cmd_len,
> -                     uint8_t *rsp, unsigned int *rsp_len,
> -                     unsigned int max_rsp_len)
> +                     struct rsp_buffer *rsp)
>  {
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -977,18 +975,18 @@ static void send_msg(IPMIBmcSim *ibs,
>  
>      if (cmd[2] != 0) {
>          /* We only handle channel 0 with no options */
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>  
>      if (cmd_len < 10) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>          return;
>      }
>  
>      if (cmd[3] != 0x40) {
>          /* We only emulate a MC at address 0x40. */
> -        rsp[2] = 0x83; /* NAK on write */
> +        rsp->buffer[2] = 0x83; /* NAK on write */
>          return;
>      }
>  
> @@ -1074,11 +1072,10 @@ static void do_watchdog_reset(IPMIBmcSim *ibs)
>  
>  static void reset_watchdog_timer(IPMIBmcSim *ibs,
>                                   uint8_t *cmd, unsigned int cmd_len,
> -                                 uint8_t *rsp, unsigned int *rsp_len,
> -                                 unsigned int max_rsp_len)
> +                                 struct rsp_buffer *rsp)
>  {
>      if (!ibs->watchdog_initialized) {
> -        rsp[2] = 0x80;
> +        rsp->buffer[2] = 0x80;
>          return;
>      }
>      do_watchdog_reset(ibs);
> @@ -1086,8 +1083,7 @@ static void reset_watchdog_timer(IPMIBmcSim *ibs,
>  
>  static void set_watchdog_timer(IPMIBmcSim *ibs,
>                                 uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                               struct rsp_buffer *rsp)
>  {
>      IPMIInterface *s = ibs->parent.intf;
>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -1095,7 +1091,7 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>  
>      val = cmd[2] & 0x7; /* Validate use */
>      if (val == 0 || val > 5) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>      val = cmd[3] & 0x7; /* Validate action */
> @@ -1104,22 +1100,22 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>          break;
>  
>      case IPMI_BMC_WATCHDOG_ACTION_RESET:
> -        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
>          break;
>  
>      case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
> -        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
>          break;
>  
>      case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
> -        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
>          break;
>  
>      default:
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>      }
> -    if (rsp[2]) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +    if (rsp->buffer[2]) {
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>  
> @@ -1132,14 +1128,14 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>      case IPMI_BMC_WATCHDOG_PRE_NMI:
>          if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
>              /* NMI not supported. */
> -            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +            rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>              return;
>          }
>          break;
>  
>      default:
>          /* We don't support PRE_SMI */
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>  
> @@ -1158,60 +1154,56 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>  
>  static void get_watchdog_timer(IPMIBmcSim *ibs,
>                                 uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                               struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_use);
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_action);
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
> +    rsp_buffer_push(rsp, ibs->watchdog_use);
> +    rsp_buffer_push(rsp, ibs->watchdog_action);
> +    rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
> +    rsp_buffer_push(rsp, ibs->watchdog_expired);
>      if (ibs->watchdog_running) {
>          long timeout;
>          timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
>                     / 100000000);
> -        IPMI_ADD_RSP_DATA(timeout & 0xff);
> -        IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
> +        rsp_buffer_push(rsp, timeout & 0xff);
> +        rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
>      } else {
> -        IPMI_ADD_RSP_DATA(0);
> -        IPMI_ADD_RSP_DATA(0);
> +        rsp_buffer_push(rsp, 0);
> +        rsp_buffer_push(rsp, 0);
>      }
>  }
>  
>  static void get_sdr_rep_info(IPMIBmcSim *ibs,
>                               uint8_t *cmd, unsigned int cmd_len,
> -                             uint8_t *rsp, unsigned int *rsp_len,
> -                             unsigned int max_rsp_len)
> +                             struct rsp_buffer *rsp)
>  {
>      unsigned int i;
>  
> -    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
> -    IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
> -    IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
> +    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
> +    rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
> +    rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
> +    rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
>      for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
> +        rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
>      }
>      for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
> +        rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
>      }
>      /* Only modal support, reserve supported */
> -    IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
> +    rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
>  }
>  
>  static void reserve_sdr_rep(IPMIBmcSim *ibs,
>                              uint8_t *cmd, unsigned int cmd_len,
> -                            uint8_t *rsp, unsigned int *rsp_len,
> -                            unsigned int max_rsp_len)
> +                            struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
> +    rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
>  }
>  
>  static void get_sdr(IPMIBmcSim *ibs,
>                      uint8_t *cmd, unsigned int cmd_len,
> -                    uint8_t *rsp, unsigned int *rsp_len,
> -                    unsigned int max_rsp_len)
> +                    struct rsp_buffer *rsp)
>  {
>      unsigned int pos;
>      uint16_t nextrec;
> @@ -1223,108 +1215,103 @@ static void get_sdr(IPMIBmcSim *ibs,
>      pos = 0;
>      if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
>                         &pos, &nextrec)) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>  
>      sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
>  
>      if (cmd[6] > ipmi_sdr_length(sdrh)) {
> -        rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
> +        rsp->buffer[2] = IPMI_CC_PARM_OUT_OF_RANGE;
>          return;
>      }
>  
> -    IPMI_ADD_RSP_DATA(nextrec & 0xff);
> -    IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
> +    rsp_buffer_push(rsp, nextrec & 0xff);
> +    rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
>  
>      if (cmd[7] == 0xff) {
>          cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
>      }
>  
> -    if ((cmd[7] + *rsp_len) > max_rsp_len) {
> -        rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
> +    if ((cmd[7] + rsp->len) > rsp->max_len) {
> +        rsp->buffer[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
>          return;
>      }
> -    memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
> -    *rsp_len += cmd[7];
> +
> +    rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
>  }
>  
>  static void add_sdr(IPMIBmcSim *ibs,
>                      uint8_t *cmd, unsigned int cmd_len,
> -                    uint8_t *rsp, unsigned int *rsp_len,
> -                    unsigned int max_rsp_len)
> +                    struct rsp_buffer *rsp)
>  {
>      uint16_t recid;
>      struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
>  
>      if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
> -    IPMI_ADD_RSP_DATA(recid & 0xff);
> -    IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
> +    rsp_buffer_push(rsp, recid & 0xff);
> +    rsp_buffer_push(rsp, (recid >> 8) & 0xff);
>  }
>  
>  static void clear_sdr_rep(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>  {
>      IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>      if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>      if (cmd[7] == 0xaa) {
>          ibs->sdr.next_free = 0;
>          ibs->sdr.overflow = 0;
>          set_timestamp(ibs, ibs->sdr.last_clear);
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>          sdr_inc_reservation(&ibs->sdr);
>      } else if (cmd[7] == 0) {
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>      } else {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>  }
>  
>  static void get_sel_info(IPMIBmcSim *ibs,
>                           uint8_t *cmd, unsigned int cmd_len,
> -                         uint8_t *rsp, unsigned int *rsp_len,
> -                         unsigned int max_rsp_len)
> +                         struct rsp_buffer *rsp)
>  {
>      unsigned int i, val;
>  
> -    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
> -    IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
> +    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
> +    rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
>      val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
> -    IPMI_ADD_RSP_DATA(val & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
> +    rsp_buffer_push(rsp, val & 0xff);
> +    rsp_buffer_push(rsp, (val >> 8) & 0xff);
>      for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
> +        rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
>      }
>      for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
> +        rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
>      }
>      /* Only support Reserve SEL */
> -    IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
> +    rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
>  }
>  
>  static void reserve_sel(IPMIBmcSim *ibs,
>                          uint8_t *cmd, unsigned int cmd_len,
> -                        uint8_t *rsp, unsigned int *rsp_len,
> -                        unsigned int max_rsp_len)
> +                        struct rsp_buffer *rsp)
>  {
> -    IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
> +    rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
>  }
>  
>  static void get_sel_entry(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>  {
>      unsigned int val;
>  
> @@ -1332,17 +1319,17 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>          IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>      }
>      if (ibs->sel.next_free == 0) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      if (cmd[6] > 15) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>      if (cmd[7] == 0xff) {
>          cmd[7] = 16;
>      } else if ((cmd[7] + cmd[6]) > 16) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      } else {
>          cmd[7] += cmd[6];
> @@ -1352,79 +1339,75 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>      if (val == 0xffff) {
>          val = ibs->sel.next_free - 1;
>      } else if (val >= ibs->sel.next_free) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      if ((val + 1) == ibs->sel.next_free) {
> -        IPMI_ADD_RSP_DATA(0xff);
> -        IPMI_ADD_RSP_DATA(0xff);
> +        rsp_buffer_push(rsp, 0xff);
> +        rsp_buffer_push(rsp, 0xff);
>      } else {
> -        IPMI_ADD_RSP_DATA((val + 1) & 0xff);
> -        IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
> +        rsp_buffer_push(rsp, (val + 1) & 0xff);
> +        rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
>      }
>      for (; cmd[6] < cmd[7]; cmd[6]++) {
> -        IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
> +        rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
>      }
>  }
>  
>  static void add_sel_entry(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>  {
>      if (sel_add_event(ibs, cmd + 2)) {
> -        rsp[2] = IPMI_CC_OUT_OF_SPACE;
> +        rsp->buffer[2] = IPMI_CC_OUT_OF_SPACE;
>          return;
>      }
>      /* sel_add_event fills in the record number. */
> -    IPMI_ADD_RSP_DATA(cmd[2]);
> -    IPMI_ADD_RSP_DATA(cmd[3]);
> +    rsp_buffer_push(rsp, cmd[2]);
> +    rsp_buffer_push(rsp, cmd[3]);
>  }
>  
>  static void clear_sel(IPMIBmcSim *ibs,
>                        uint8_t *cmd, unsigned int cmd_len,
> -                      uint8_t *rsp, unsigned int *rsp_len,
> -                      unsigned int max_rsp_len)
> +                      struct rsp_buffer *rsp)
>  {
>      IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>      if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>      if (cmd[7] == 0xaa) {
>          ibs->sel.next_free = 0;
>          ibs->sel.overflow = 0;
>          set_timestamp(ibs, ibs->sdr.last_clear);
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>          sel_inc_reservation(&ibs->sel);
>      } else if (cmd[7] == 0) {
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>      } else {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>  }
>  
>  static void get_sel_time(IPMIBmcSim *ibs,
>                           uint8_t *cmd, unsigned int cmd_len,
> -                         uint8_t *rsp, unsigned int *rsp_len,
> -                         unsigned int max_rsp_len)
> +                         struct rsp_buffer *rsp)
>  {
>      uint32_t val;
>      struct ipmi_time now;
>  
>      ipmi_gettime(&now);
>      val = now.tv_sec + ibs->sel.time_offset;
> -    IPMI_ADD_RSP_DATA(val & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
> +    rsp_buffer_push(rsp, val & 0xff);
> +    rsp_buffer_push(rsp, (val >> 8) & 0xff);
> +    rsp_buffer_push(rsp, (val >> 16) & 0xff);
> +    rsp_buffer_push(rsp, (val >> 24) & 0xff);
>  }
>  
>  static void set_sel_time(IPMIBmcSim *ibs,
>                           uint8_t *cmd, unsigned int cmd_len,
> -                         uint8_t *rsp, unsigned int *rsp_len,
> -                         unsigned int max_rsp_len)
> +                         struct rsp_buffer *rsp)
>  {
>      uint32_t val;
>      struct ipmi_time now;
> @@ -1436,14 +1419,13 @@ static void set_sel_time(IPMIBmcSim *ibs,
>  
>  static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>                                    uint8_t *cmd, unsigned int cmd_len,
> -                                  uint8_t *rsp, unsigned int *rsp_len,
> -                                  unsigned int max_rsp_len)
> +                                  struct rsp_buffer *rsp)
>  {
>      IPMISensor *sens;
>  
>      if ((cmd[2] >= MAX_SENSORS) ||
>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      sens = ibs->sensors + cmd[2];
> @@ -1479,7 +1461,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>          }
>          break;
>      case 3:
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>          return;
>      }
>      IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
> @@ -1487,34 +1469,32 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>  
>  static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>                                    uint8_t *cmd, unsigned int cmd_len,
> -                                  uint8_t *rsp, unsigned int *rsp_len,
> -                                  unsigned int max_rsp_len)
> +                                  struct rsp_buffer *rsp)
>  {
>      IPMISensor *sens;
>  
>      if ((cmd[2] >= MAX_SENSORS) ||
>          !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
> -    IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
> +    rsp_buffer_push(rsp, sens->assert_enable & 0xff);
> +    rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
> +    rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
> +    rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
>  }
>  
>  static void rearm_sensor_evts(IPMIBmcSim *ibs,
>                                uint8_t *cmd, unsigned int cmd_len,
> -                              uint8_t *rsp, unsigned int *rsp_len,
> -                              unsigned int max_rsp_len)
> +                              struct rsp_buffer *rsp)
>  {
>      IPMISensor *sens;
>  
>      if ((cmd[2] >= MAX_SENSORS) ||
>          !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      sens = ibs->sensors + cmd[2];
> @@ -1528,57 +1508,54 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>  
>  static void get_sensor_evt_status(IPMIBmcSim *ibs,
>                                    uint8_t *cmd, unsigned int cmd_len,
> -                                  uint8_t *rsp, unsigned int *rsp_len,
> -                                  unsigned int max_rsp_len)
> +                                  struct rsp_buffer *rsp)
>  {
>      IPMISensor *sens;
>  
>      if ((cmd[2] >= MAX_SENSORS) ||
>          !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(sens->reading);
> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
> -    IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
> +    rsp_buffer_push(rsp, sens->reading);
> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
> +    rsp_buffer_push(rsp, sens->assert_states & 0xff);
> +    rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
> +    rsp_buffer_push(rsp, sens->deassert_states & 0xff);
> +    rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
>  }
>  
>  static void get_sensor_reading(IPMIBmcSim *ibs,
>                                 uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                               struct rsp_buffer *rsp)
>  {
>      IPMISensor *sens;
>  
>      if ((cmd[2] >= MAX_SENSORS) ||
>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(sens->reading);
> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
> -    IPMI_ADD_RSP_DATA(sens->states & 0xff);
> +    rsp_buffer_push(rsp, sens->reading);
> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
> +    rsp_buffer_push(rsp, sens->states & 0xff);
>      if (IPMI_SENSOR_IS_DISCRETE(sens)) {
> -        IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
> +        rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
>      }
>  }
>  
>  static void set_sensor_type(IPMIBmcSim *ibs,
> -                               uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                            uint8_t *cmd, unsigned int cmd_len,
> +                            struct rsp_buffer *rsp)
>  {
>      IPMISensor *sens;
>  
>  
>      if ((cmd[2] >= MAX_SENSORS) ||
>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      sens = ibs->sensors + cmd[2];
> @@ -1587,21 +1564,20 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>  }
>  
>  static void get_sensor_type(IPMIBmcSim *ibs,
> -                               uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                            uint8_t *cmd, unsigned int cmd_len,
> +                            struct rsp_buffer *rsp)
>  {
>      IPMISensor *sens;
>  
>  
>      if ((cmd[2] >= MAX_SENSORS) ||
>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>          return;
>      }
>      sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(sens->sensor_type);
> -    IPMI_ADD_RSP_DATA(sens->evt_reading_type_code);
> +    rsp_buffer_push(rsp, sens->sensor_type);
> +    rsp_buffer_push(rsp, sens->evt_reading_type_code);
>  }
>  
>  
> -- 
> 2.1.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 03/10] ipmi: remove IPMI_CHECK_RESERVATION() macro
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 03/10] ipmi: remove IPMI_CHECK_RESERVATION() macro Cédric Le Goater
@ 2016-03-02 15:40   ` Corey Minyard
  0 siblings, 0 replies; 23+ messages in thread
From: Corey Minyard @ 2016-03-02 15:40 UTC (permalink / raw)
  To: Cédric Le Goater, Corey Minyard
  Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
> Some IPMI command handlers in the BMC simulator use a macro
> IPMI_CHECK_RESERVATION() to check a SDR reservation but the macro
> implicitly uses local variables. This patch simply removes it.
>
> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>

Acked-by: Corey Minyard <cminyard@mvista.com>

> ---
>   hw/ipmi/ipmi_bmc_sim.c | 33 +++++++++++++++++++--------------
>   1 file changed, 19 insertions(+), 14 deletions(-)
>
> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
> index 32efb87c8232..72166a7da291 100644
> --- a/hw/ipmi/ipmi_bmc_sim.c
> +++ b/hw/ipmi/ipmi_bmc_sim.c
> @@ -293,16 +293,6 @@ static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
>       rsp->len += n;
>   }
>   
> -/* Check that the reservation in the command is valid. */
> -#define IPMI_CHECK_RESERVATION(off, r) \
> -    do {                                                   \
> -        if ((cmd[off] | (cmd[off + 1] << 8)) != r) {       \
> -            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;     \
> -            return;                                        \
> -        }                                                  \
> -    } while (0)
> -
> -
>   static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs);
>   
>   static void ipmi_gettime(struct ipmi_time *time)
> @@ -1210,8 +1200,12 @@ static void get_sdr(IPMIBmcSim *ibs,
>       struct ipmi_sdr_header *sdrh;
>   
>       if (cmd[6]) {
> -        IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
> +        if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
> +            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +            return;
> +        }
>       }
> +
>       pos = 0;
>       if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
>                          &pos, &nextrec)) {
> @@ -1260,7 +1254,11 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
>                             struct rsp_buffer *rsp)
>   {
> -    IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
> +    if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
> +        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +        return;
> +    }
> +
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>           rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
> @@ -1316,7 +1314,10 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>       unsigned int val;
>   
>       if (cmd[6]) {
> -        IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
> +        if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
> +            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +            return;
> +        }
>       }
>       if (ibs->sel.next_free == 0) {
>           rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1371,7 +1372,11 @@ static void clear_sel(IPMIBmcSim *ibs,
>                         uint8_t *cmd, unsigned int cmd_len,
>                         struct rsp_buffer *rsp)
>   {
> -    IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
> +    if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
> +        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +        return;
> +    }
> +
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>           rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  2016-03-02 10:25   ` Michael S. Tsirkin
@ 2016-03-02 17:53     ` Cédric Le Goater
  2016-03-02 18:02       ` Michael S. Tsirkin
  0 siblings, 1 reply; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 17:53 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Marcel Apfelbaum, Corey Minyard, qemu-devel

On 03/02/2016 11:25 AM, Michael S. Tsirkin wrote:
> On Wed, Mar 02, 2016 at 11:14:50AM +0100, Cédric Le Goater wrote:
>> The IPMI command handlers in the BMC simulator use a macro
>> IPMI_ADD_RSP_DATA() to push bytes in a response buffer. The macro
>> hides the fact that it implicitly uses variables local to the handler,
>> which is misleading.
>>
>> This patch introduces a simple 'struct rsp_buffer' and inlined helper
>> routines to store byte(s) in a response buffer. rsp_buffer_push()
>> replaces the macro IPMI_ADD_RSP_DATA() and rsp_buffer_pushmore() is
>> new helper to push multiple bytes. The latest is used in the command
>> handlers get_msg() and get_sdr() which are manipulating the buffer
>> directly.
>>
>> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
> 
> 
> Looks good overall.
> Some stylistic comments.
> 
>> ---
>>  hw/ipmi/ipmi_bmc_sim.c | 482 +++++++++++++++++++++++--------------------------
>>  1 file changed, 229 insertions(+), 253 deletions(-)
>>
>> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
>> index 30b9fb48ea2d..32efb87c8232 100644
>> --- a/hw/ipmi/ipmi_bmc_sim.c
>> +++ b/hw/ipmi/ipmi_bmc_sim.c
>> @@ -153,14 +153,14 @@ typedef struct IPMISensor {
>>  #define IPMI_WATCHDOG_SENSOR 0
>>  
>>  typedef struct IPMIBmcSim IPMIBmcSim;
>> +struct rsp_buffer;
>>
> 
> typedef struct RspBuffer RspBuffer;

OK. So that's the rule for structs in qemu. It is not that clear
when you look at the code around. I will change. np.

>>  #define MAX_NETFNS 64
>>  
>>  typedef struct IPMICmdHandler {
>>      void (*cmd_handler)(IPMIBmcSim *s,
>>                          uint8_t *cmd, unsigned int cmd_len,
>> -                        uint8_t *rsp, unsigned int *rsp_len,
>> -                        unsigned int max_rsp_len);
>> +                        struct rsp_buffer *rsp);
>>      unsigned int cmd_len_min;
>>  } IPMICmdHandler;
>>  
>> @@ -263,22 +263,41 @@ struct IPMIBmcSim {
>>  #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
>>  #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3
>>  
>> +struct rsp_buffer {
>> +    uint8_t buffer[MAX_IPMI_MSG_SIZE];
>> +    unsigned int len;
>> +    unsigned int max_len;
>> +};
>> +
>> +#define RSP_BUFFER_INITIALIZER { { 0 }, 0, MAX_IPMI_MSG_SIZE }
> 
> max_len seems to always be a constant. So just use ARRAY_SIZE(buffer)
> and RSP_BUFFER_INITIALIZER can then be replaced with plain { };

Yes. or : 

#define RSP_BUFFER_INITIALIZER \
	{ { 0 }, 0, ARRAY_SIZE(((struct rsp_buffer *)NULL)->buffer) }

This is purely stylistic. I agree that specifying MAX_IPMI_MSG_SIZE
twice is ugly. It needs a fix.

>>  
>>  /* Add a byte to the response. */
>> -#define IPMI_ADD_RSP_DATA(b) \
>> -    do {                                                   \
>> -        if (*rsp_len >= max_rsp_len) {                     \
>> -            rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;       \
>> -            return;                                        \
>> -        }                                                  \
>> -        rsp[(*rsp_len)++] = (b);                           \
>> -    } while (0)
>> +static inline void rsp_buffer_push(struct rsp_buffer *rsp, uint8_t byte)
>> +{
>> +    if (rsp->len >= rsp->max_len) {
> 
> Why not simply
> 	rsp->len >= ARRAY_SIZE(rsp->buffer)
> ?
> 
> 
> 
>> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>> +        return;
>> +    }
>> +    rsp->buffer[rsp->len++] = byte;
>> +}
>> +
>> +static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
>> +                                       unsigned int n)
>> +{
>> +    if (rsp->len + n >= rsp->max_len) {
>> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>> +        return;
>> +    }
>> +
>> +    memcpy(&rsp->buffer[rsp->len], bytes, n);
>> +    rsp->len += n;
>> +}
>>  
>>  /* Check that the reservation in the command is valid. */
>>  #define IPMI_CHECK_RESERVATION(off, r) \
>>      do {                                                   \
>>          if ((cmd[off] | (cmd[off + 1] << 8)) != r) {       \
>> -            rsp[2] = IPMI_CC_INVALID_RESERVATION;          \
>> +            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;     \
>>              return;                                        \
>>          }                                                  \
>>      } while (0)
>> @@ -585,35 +604,32 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>      unsigned int netfn;
>> -    uint8_t rsp[MAX_IPMI_MSG_SIZE];
>> -    unsigned int rsp_len_holder = 0;
>> -    unsigned int *rsp_len = &rsp_len_holder;
>> -    unsigned int max_rsp_len = sizeof(rsp);
>> +    struct rsp_buffer rsp = RSP_BUFFER_INITIALIZER;
>>  
>>      /* Set up the response, set the low bit of NETFN. */
>>      /* Note that max_rsp_len must be at least 3 */
>> -    if (max_rsp_len < 3) {
>> -        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>> +    if (rsp.max_len < 3) {
>> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>>          goto out;
>>      }
>>  
>> -    IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
>> -    IPMI_ADD_RSP_DATA(cmd[1]);
>> -    IPMI_ADD_RSP_DATA(0); /* Assume success */
>> +    rsp_buffer_push(&rsp, cmd[0] | 0x04);
>> +    rsp_buffer_push(&rsp, cmd[1]);
>> +    rsp_buffer_push(&rsp, 0); /* Assume success */
>>  
>>      /* If it's too short or it was truncated, return an error. */
>>      if (cmd_len < 2) {
>> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>          goto out;
>>      }
>>      if (cmd_len > max_cmd_len) {
>> -        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>>          goto out;
>>      }
>>  
>>      if ((cmd[0] & 0x03) != 0) {
>>          /* Only have stuff on LUN 0 */
>> -        rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
>> +        rsp.buffer[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
>>          goto out;
>>      }
>>  
>> @@ -623,20 +639,20 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>>      if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>>          (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>>          (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
>> -        rsp[2] = IPMI_CC_INVALID_CMD;
>> +        rsp.buffer[2] = IPMI_CC_INVALID_CMD;
>>          goto out;
>>      }
>>  
>>      if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
>> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>          goto out;
>>      }
>>  
>>      ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
>> -                                                rsp, rsp_len, max_rsp_len);
>> +                                                &rsp);
>>  
>>   out:
>> -    k->handle_rsp(s, msg_id, rsp, *rsp_len);
>> +    k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
>>  
>>      next_timeout(ibs);
>>  }
>> @@ -711,86 +727,82 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
>>  
>>  static void chassis_capabilities(IPMIBmcSim *ibs,
>>                                   uint8_t *cmd, unsigned int cmd_len,
>> -                                 uint8_t *rsp, unsigned int *rsp_len,
>> -                                 unsigned int max_rsp_len)
>> +                                 struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(0);
>> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
>> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
>> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
>> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
>> +    rsp_buffer_push(rsp, 0);
>> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
>> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
>> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
>> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
>>  }
>>  
>>  static void chassis_status(IPMIBmcSim *ibs,
>>                             uint8_t *cmd, unsigned int cmd_len,
>> -                           uint8_t *rsp, unsigned int *rsp_len,
>> -                           unsigned int max_rsp_len)
>> +                           struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
>> -    IPMI_ADD_RSP_DATA(0);
>> -    IPMI_ADD_RSP_DATA(0);
>> -    IPMI_ADD_RSP_DATA(0);
>> +    rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
>> +    rsp_buffer_push(rsp, 0);
>> +    rsp_buffer_push(rsp, 0);
>> +    rsp_buffer_push(rsp, 0);
>>  }
>>  
>>  static void chassis_control(IPMIBmcSim *ibs,
>>                              uint8_t *cmd, unsigned int cmd_len,
>> -                            uint8_t *rsp, unsigned int *rsp_len,
>> -                            unsigned int max_rsp_len)
>> +                            struct rsp_buffer *rsp)
>>  {
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>  
>>      switch (cmd[2] & 0xf) {
>>      case 0: /* power down */
>> -        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>>          break;
>>      case 1: /* power up */
>> -        rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
>>          break;
>>      case 2: /* power cycle */
>> -        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
>>          break;
>>      case 3: /* hard reset */
>> -        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
>>          break;
>>      case 4: /* pulse diagnostic interrupt */
>> -        rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
>>          break;
>>      case 5: /* soft shutdown via ACPI by overtemp emulation */
>> -        rsp[2] = k->do_hw_op(s,
>> +        rsp->buffer[2] = k->do_hw_op(s,
>>                               IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
>>          break;
>>      default:
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>  }
>>  
>>  static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
>>                             uint8_t *cmd, unsigned int cmd_len,
>> -                           uint8_t *rsp, unsigned int *rsp_len,
>> -                           unsigned int max_rsp_len)
>> +                           struct rsp_buffer *rsp)
>> +
>>  {
>> -    IPMI_ADD_RSP_DATA(ibs->restart_cause & 0xf); /* Restart Cause */
>> -    IPMI_ADD_RSP_DATA(0);  /* Channel 0 */
>> +    rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
>> +    rsp_buffer_push(rsp, 0);  /* Channel 0 */
>>  }
>>  
>>  static void get_device_id(IPMIBmcSim *ibs,
>>                            uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> -{
>> -    IPMI_ADD_RSP_DATA(ibs->device_id);
>> -    IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
>> -    IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
>> -    IPMI_ADD_RSP_DATA(ibs->fwrev2);
>> -    IPMI_ADD_RSP_DATA(ibs->ipmi_version);
>> -    IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
>> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
>> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
>> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
>> -    IPMI_ADD_RSP_DATA(ibs->product_id[0]);
>> -    IPMI_ADD_RSP_DATA(ibs->product_id[1]);
>> +                          struct rsp_buffer *rsp)
>> +{
>> +    rsp_buffer_push(rsp, ibs->device_id);
>> +    rsp_buffer_push(rsp, ibs->device_rev & 0xf);
>> +    rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
>> +    rsp_buffer_push(rsp, ibs->fwrev2);
>> +    rsp_buffer_push(rsp, ibs->ipmi_version);
>> +    rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
>> +    rsp_buffer_push(rsp, ibs->mfg_id[0]);
>> +    rsp_buffer_push(rsp, ibs->mfg_id[1]);
>> +    rsp_buffer_push(rsp, ibs->mfg_id[2]);
>> +    rsp_buffer_push(rsp, ibs->product_id[0]);
>> +    rsp_buffer_push(rsp, ibs->product_id[1]);
>>  }
>>  
>>  static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
>> @@ -809,8 +821,7 @@ static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
>>  
>>  static void cold_reset(IPMIBmcSim *ibs,
>>                         uint8_t *cmd, unsigned int cmd_len,
>> -                       uint8_t *rsp, unsigned int *rsp_len,
>> -                       unsigned int max_rsp_len)
>> +                       struct rsp_buffer *rsp)
>>  {
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>> @@ -825,8 +836,7 @@ static void cold_reset(IPMIBmcSim *ibs,
>>  
>>  static void warm_reset(IPMIBmcSim *ibs,
>>                         uint8_t *cmd, unsigned int cmd_len,
>> -                       uint8_t *rsp, unsigned int *rsp_len,
>> -                       unsigned int max_rsp_len)
>> +                       struct rsp_buffer *rsp)
>>  {
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>> @@ -836,55 +846,49 @@ static void warm_reset(IPMIBmcSim *ibs,
>>      }
>>  }
>>  static void set_acpi_power_state(IPMIBmcSim *ibs,
>> -                          uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                                 uint8_t *cmd, unsigned int cmd_len,
>> +                                 struct rsp_buffer *rsp)
>>  {
>>      ibs->acpi_power_state[0] = cmd[2];
>>      ibs->acpi_power_state[1] = cmd[3];
>>  }
>>  
>>  static void get_acpi_power_state(IPMIBmcSim *ibs,
>> -                          uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                                 uint8_t *cmd, unsigned int cmd_len,
>> +                                 struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[0]);
>> -    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[1]);
>> +    rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
>> +    rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
>>  }
>>  
>>  static void get_device_guid(IPMIBmcSim *ibs,
>> -                          uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                            uint8_t *cmd, unsigned int cmd_len,
>> +                            struct rsp_buffer *rsp)
>>  {
>>      unsigned int i;
>>  
>>      for (i = 0; i < 16; i++) {
>> -        IPMI_ADD_RSP_DATA(ibs->uuid[i]);
>> +        rsp_buffer_push(rsp, ibs->uuid[i]);
>>      }
>>  }
>>  
>>  static void set_bmc_global_enables(IPMIBmcSim *ibs,
>>                                     uint8_t *cmd, unsigned int cmd_len,
>> -                                   uint8_t *rsp, unsigned int *rsp_len,
>> -                                   unsigned int max_rsp_len)
>> +                                   struct rsp_buffer *rsp)
>>  {
>>      set_global_enables(ibs, cmd[2]);
>>  }
>>  
>>  static void get_bmc_global_enables(IPMIBmcSim *ibs,
>>                                     uint8_t *cmd, unsigned int cmd_len,
>> -                                   uint8_t *rsp, unsigned int *rsp_len,
>> -                                   unsigned int max_rsp_len)
>> +                                   struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
>> +    rsp_buffer_push(rsp, ibs->bmc_global_enables);
>>  }
>>  
>>  static void clr_msg_flags(IPMIBmcSim *ibs,
>>                            uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                          struct rsp_buffer *rsp)
>>  {
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>> @@ -895,27 +899,25 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>>  
>>  static void get_msg_flags(IPMIBmcSim *ibs,
>>                            uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                          struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(ibs->msg_flags);
>> +    rsp_buffer_push(rsp, ibs->msg_flags);
>>  }
>>  
>>  static void read_evt_msg_buf(IPMIBmcSim *ibs,
>>                               uint8_t *cmd, unsigned int cmd_len,
>> -                             uint8_t *rsp, unsigned int *rsp_len,
>> -                            unsigned int max_rsp_len)
>> +                             struct rsp_buffer *rsp)
>>  {
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>      unsigned int i;
>>  
>>      if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
>> -        rsp[2] = 0x80;
>> +        rsp->buffer[2] = 0x80;
>>          return;
>>      }
>>      for (i = 0; i < 16; i++) {
>> -        IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
>> +        rsp_buffer_push(rsp, ibs->evtbuf[i]);
>>      }
>>      ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
>>      k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
>> @@ -923,21 +925,18 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs,
>>  
>>  static void get_msg(IPMIBmcSim *ibs,
>>                      uint8_t *cmd, unsigned int cmd_len,
>> -                    uint8_t *rsp, unsigned int *rsp_len,
>> -                    unsigned int max_rsp_len)
>> +                    struct rsp_buffer *rsp)
>>  {
>>      IPMIRcvBufEntry *msg;
>>  
>>      qemu_mutex_lock(&ibs->lock);
>>      if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
>> -        rsp[2] = 0x80; /* Queue empty */
>> +        rsp->buffer[2] = 0x80; /* Queue empty */
>>          goto out;
>>      }
>> -    rsp[3] = 0; /* Channel 0 */
>> -    *rsp_len += 1;
>> +    rsp_buffer_push(rsp, 0); /* Channel 0 */
>>      msg = QTAILQ_FIRST(&ibs->rcvbufs);
>> -    memcpy(rsp + 4, msg->buf, msg->len);
>> -    *rsp_len += msg->len;
>> +    rsp_buffer_pushmore(rsp, msg->buf, msg->len);
>>      QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
>>      g_free(msg);
>>  
>> @@ -966,8 +965,7 @@ ipmb_checksum(unsigned char *data, int size, unsigned char csum)
>>  
>>  static void send_msg(IPMIBmcSim *ibs,
>>                       uint8_t *cmd, unsigned int cmd_len,
>> -                     uint8_t *rsp, unsigned int *rsp_len,
>> -                     unsigned int max_rsp_len)
>> +                     struct rsp_buffer *rsp)
>>  {
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>> @@ -977,18 +975,18 @@ static void send_msg(IPMIBmcSim *ibs,
>>  
>>      if (cmd[2] != 0) {
>>          /* We only handle channel 0 with no options */
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>  
>>      if (cmd_len < 10) {
>> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>          return;
>>      }
>>  
>>      if (cmd[3] != 0x40) {
>>          /* We only emulate a MC at address 0x40. */
>> -        rsp[2] = 0x83; /* NAK on write */
>> +        rsp->buffer[2] = 0x83; /* NAK on write */
>>          return;
>>      }
>>  
>> @@ -1074,11 +1072,10 @@ static void do_watchdog_reset(IPMIBmcSim *ibs)
>>  
>>  static void reset_watchdog_timer(IPMIBmcSim *ibs,
>>                                   uint8_t *cmd, unsigned int cmd_len,
>> -                                 uint8_t *rsp, unsigned int *rsp_len,
>> -                                 unsigned int max_rsp_len)
>> +                                 struct rsp_buffer *rsp)
>>  {
>>      if (!ibs->watchdog_initialized) {
>> -        rsp[2] = 0x80;
>> +        rsp->buffer[2] = 0x80;
>>          return;
>>      }
>>      do_watchdog_reset(ibs);
>> @@ -1086,8 +1083,7 @@ static void reset_watchdog_timer(IPMIBmcSim *ibs,
>>  
>>  static void set_watchdog_timer(IPMIBmcSim *ibs,
>>                                 uint8_t *cmd, unsigned int cmd_len,
>> -                               uint8_t *rsp, unsigned int *rsp_len,
>> -                               unsigned int max_rsp_len)
>> +                               struct rsp_buffer *rsp)
>>  {
>>      IPMIInterface *s = ibs->parent.intf;
>>      IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>> @@ -1095,7 +1091,7 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>  
>>      val = cmd[2] & 0x7; /* Validate use */
>>      if (val == 0 || val > 5) {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>      val = cmd[3] & 0x7; /* Validate action */
>> @@ -1104,22 +1100,22 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>          break;
>>  
>>      case IPMI_BMC_WATCHDOG_ACTION_RESET:
>> -        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
>>          break;
>>  
>>      case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
>> -        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
>>          break;
>>  
>>      case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
>> -        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
>> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
>>          break;
>>  
>>      default:
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>      }
>> -    if (rsp[2]) {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +    if (rsp->buffer[2]) {
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>  
>> @@ -1132,14 +1128,14 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>      case IPMI_BMC_WATCHDOG_PRE_NMI:
>>          if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
>>              /* NMI not supported. */
>> -            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +            rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>              return;
>>          }
>>          break;
>>  
>>      default:
>>          /* We don't support PRE_SMI */
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>  
>> @@ -1158,60 +1154,56 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>  
>>  static void get_watchdog_timer(IPMIBmcSim *ibs,
>>                                 uint8_t *cmd, unsigned int cmd_len,
>> -                               uint8_t *rsp, unsigned int *rsp_len,
>> -                               unsigned int max_rsp_len)
>> +                               struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(ibs->watchdog_use);
>> -    IPMI_ADD_RSP_DATA(ibs->watchdog_action);
>> -    IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
>> -    IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
>> +    rsp_buffer_push(rsp, ibs->watchdog_use);
>> +    rsp_buffer_push(rsp, ibs->watchdog_action);
>> +    rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
>> +    rsp_buffer_push(rsp, ibs->watchdog_expired);
>>      if (ibs->watchdog_running) {
>>          long timeout;
>>          timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
>>                     / 100000000);
>> -        IPMI_ADD_RSP_DATA(timeout & 0xff);
>> -        IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
>> +        rsp_buffer_push(rsp, timeout & 0xff);
>> +        rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
>>      } else {
>> -        IPMI_ADD_RSP_DATA(0);
>> -        IPMI_ADD_RSP_DATA(0);
>> +        rsp_buffer_push(rsp, 0);
>> +        rsp_buffer_push(rsp, 0);
>>      }
>>  }
>>  
>>  static void get_sdr_rep_info(IPMIBmcSim *ibs,
>>                               uint8_t *cmd, unsigned int cmd_len,
>> -                             uint8_t *rsp, unsigned int *rsp_len,
>> -                             unsigned int max_rsp_len)
>> +                             struct rsp_buffer *rsp)
>>  {
>>      unsigned int i;
>>  
>> -    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
>> -    IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
>> -    IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
>> -    IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
>> -    IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
>> +    rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
>> +    rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
>> +    rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
>>      for (i = 0; i < 4; i++) {
>> -        IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
>> +        rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
>>      }
>>      for (i = 0; i < 4; i++) {
>> -        IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
>> +        rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
>>      }
>>      /* Only modal support, reserve supported */
>> -    IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
>> +    rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
>>  }
>>  
>>  static void reserve_sdr_rep(IPMIBmcSim *ibs,
>>                              uint8_t *cmd, unsigned int cmd_len,
>> -                            uint8_t *rsp, unsigned int *rsp_len,
>> -                            unsigned int max_rsp_len)
>> +                            struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
>> -    IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
>> +    rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
>>  }
>>  
>>  static void get_sdr(IPMIBmcSim *ibs,
>>                      uint8_t *cmd, unsigned int cmd_len,
>> -                    uint8_t *rsp, unsigned int *rsp_len,
>> -                    unsigned int max_rsp_len)
>> +                    struct rsp_buffer *rsp)
>>  {
>>      unsigned int pos;
>>      uint16_t nextrec;
>> @@ -1223,108 +1215,103 @@ static void get_sdr(IPMIBmcSim *ibs,
>>      pos = 0;
>>      if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
>>                         &pos, &nextrec)) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>  
>>      sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
>>  
>>      if (cmd[6] > ipmi_sdr_length(sdrh)) {
>> -        rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
>> +        rsp->buffer[2] = IPMI_CC_PARM_OUT_OF_RANGE;
>>          return;
>>      }
>>  
>> -    IPMI_ADD_RSP_DATA(nextrec & 0xff);
>> -    IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, nextrec & 0xff);
>> +    rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
>>  
>>      if (cmd[7] == 0xff) {
>>          cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
>>      }
>>  
>> -    if ((cmd[7] + *rsp_len) > max_rsp_len) {
>> -        rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
>> +    if ((cmd[7] + rsp->len) > rsp->max_len) {
>> +        rsp->buffer[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
>>          return;
>>      }
>> -    memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
>> -    *rsp_len += cmd[7];
>> +
>> +    rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
>>  }
>>  
>>  static void add_sdr(IPMIBmcSim *ibs,
>>                      uint8_t *cmd, unsigned int cmd_len,
>> -                    uint8_t *rsp, unsigned int *rsp_len,
>> -                    unsigned int max_rsp_len)
>> +                    struct rsp_buffer *rsp)
>>  {
>>      uint16_t recid;
>>      struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
>>  
>>      if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>> -    IPMI_ADD_RSP_DATA(recid & 0xff);
>> -    IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, recid & 0xff);
>> +    rsp_buffer_push(rsp, (recid >> 8) & 0xff);
>>  }
>>  
>>  static void clear_sdr_rep(IPMIBmcSim *ibs,
>>                            uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                          struct rsp_buffer *rsp)
>>  {
>>      IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>      if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>      if (cmd[7] == 0xaa) {
>>          ibs->sdr.next_free = 0;
>>          ibs->sdr.overflow = 0;
>>          set_timestamp(ibs, ibs->sdr.last_clear);
>> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
>> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>>          sdr_inc_reservation(&ibs->sdr);
>>      } else if (cmd[7] == 0) {
>> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
>> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>>      } else {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>  }
>>  
>>  static void get_sel_info(IPMIBmcSim *ibs,
>>                           uint8_t *cmd, unsigned int cmd_len,
>> -                         uint8_t *rsp, unsigned int *rsp_len,
>> -                         unsigned int max_rsp_len)
>> +                         struct rsp_buffer *rsp)
>>  {
>>      unsigned int i, val;
>>  
>> -    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
>> -    IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
>> -    IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
>> +    rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
>> +    rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
>>      val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
>> -    IPMI_ADD_RSP_DATA(val & 0xff);
>> -    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, val & 0xff);
>> +    rsp_buffer_push(rsp, (val >> 8) & 0xff);
>>      for (i = 0; i < 4; i++) {
>> -        IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
>> +        rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
>>      }
>>      for (i = 0; i < 4; i++) {
>> -        IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
>> +        rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
>>      }
>>      /* Only support Reserve SEL */
>> -    IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
>> +    rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
>>  }
>>  
>>  static void reserve_sel(IPMIBmcSim *ibs,
>>                          uint8_t *cmd, unsigned int cmd_len,
>> -                        uint8_t *rsp, unsigned int *rsp_len,
>> -                        unsigned int max_rsp_len)
>> +                        struct rsp_buffer *rsp)
>>  {
>> -    IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
>> -    IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
>> +    rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
>>  }
>>  
>>  static void get_sel_entry(IPMIBmcSim *ibs,
>>                            uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                          struct rsp_buffer *rsp)
>>  {
>>      unsigned int val;
>>  
>> @@ -1332,17 +1319,17 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>>          IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>      }
>>      if (ibs->sel.next_free == 0) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      if (cmd[6] > 15) {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>      if (cmd[7] == 0xff) {
>>          cmd[7] = 16;
>>      } else if ((cmd[7] + cmd[6]) > 16) {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      } else {
>>          cmd[7] += cmd[6];
>> @@ -1352,79 +1339,75 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>>      if (val == 0xffff) {
>>          val = ibs->sel.next_free - 1;
>>      } else if (val >= ibs->sel.next_free) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      if ((val + 1) == ibs->sel.next_free) {
>> -        IPMI_ADD_RSP_DATA(0xff);
>> -        IPMI_ADD_RSP_DATA(0xff);
>> +        rsp_buffer_push(rsp, 0xff);
>> +        rsp_buffer_push(rsp, 0xff);
>>      } else {
>> -        IPMI_ADD_RSP_DATA((val + 1) & 0xff);
>> -        IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
>> +        rsp_buffer_push(rsp, (val + 1) & 0xff);
>> +        rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
>>      }
>>      for (; cmd[6] < cmd[7]; cmd[6]++) {
>> -        IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
>> +        rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
>>      }
>>  }
>>  
>>  static void add_sel_entry(IPMIBmcSim *ibs,
>>                            uint8_t *cmd, unsigned int cmd_len,
>> -                          uint8_t *rsp, unsigned int *rsp_len,
>> -                          unsigned int max_rsp_len)
>> +                          struct rsp_buffer *rsp)
>>  {
>>      if (sel_add_event(ibs, cmd + 2)) {
>> -        rsp[2] = IPMI_CC_OUT_OF_SPACE;
>> +        rsp->buffer[2] = IPMI_CC_OUT_OF_SPACE;
>>          return;
>>      }
>>      /* sel_add_event fills in the record number. */
>> -    IPMI_ADD_RSP_DATA(cmd[2]);
>> -    IPMI_ADD_RSP_DATA(cmd[3]);
>> +    rsp_buffer_push(rsp, cmd[2]);
>> +    rsp_buffer_push(rsp, cmd[3]);
>>  }
>>  
>>  static void clear_sel(IPMIBmcSim *ibs,
>>                        uint8_t *cmd, unsigned int cmd_len,
>> -                      uint8_t *rsp, unsigned int *rsp_len,
>> -                      unsigned int max_rsp_len)
>> +                      struct rsp_buffer *rsp)
>>  {
>>      IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>      if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>      if (cmd[7] == 0xaa) {
>>          ibs->sel.next_free = 0;
>>          ibs->sel.overflow = 0;
>>          set_timestamp(ibs, ibs->sdr.last_clear);
>> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
>> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>>          sel_inc_reservation(&ibs->sel);
>>      } else if (cmd[7] == 0) {
>> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
>> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>>      } else {
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>  }
>>  
>>  static void get_sel_time(IPMIBmcSim *ibs,
>>                           uint8_t *cmd, unsigned int cmd_len,
>> -                         uint8_t *rsp, unsigned int *rsp_len,
>> -                         unsigned int max_rsp_len)
>> +                         struct rsp_buffer *rsp)
>>  {
>>      uint32_t val;
>>      struct ipmi_time now;
>>  
>>      ipmi_gettime(&now);
>>      val = now.tv_sec + ibs->sel.time_offset;
>> -    IPMI_ADD_RSP_DATA(val & 0xff);
>> -    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
>> -    IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
>> -    IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
>> +    rsp_buffer_push(rsp, val & 0xff);
>> +    rsp_buffer_push(rsp, (val >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, (val >> 16) & 0xff);
>> +    rsp_buffer_push(rsp, (val >> 24) & 0xff);
>>  }
>>  
>>  static void set_sel_time(IPMIBmcSim *ibs,
>>                           uint8_t *cmd, unsigned int cmd_len,
>> -                         uint8_t *rsp, unsigned int *rsp_len,
>> -                         unsigned int max_rsp_len)
>> +                         struct rsp_buffer *rsp)
>>  {
>>      uint32_t val;
>>      struct ipmi_time now;
>> @@ -1436,14 +1419,13 @@ static void set_sel_time(IPMIBmcSim *ibs,
>>  
>>  static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>>                                    uint8_t *cmd, unsigned int cmd_len,
>> -                                  uint8_t *rsp, unsigned int *rsp_len,
>> -                                  unsigned int max_rsp_len)
>> +                                  struct rsp_buffer *rsp)
>>  {
>>      IPMISensor *sens;
>>  
>>      if ((cmd[2] >= MAX_SENSORS) ||
>>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      sens = ibs->sensors + cmd[2];
>> @@ -1479,7 +1461,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>>          }
>>          break;
>>      case 3:
>> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>>          return;
>>      }
>>      IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
>> @@ -1487,34 +1469,32 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>>  
>>  static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>>                                    uint8_t *cmd, unsigned int cmd_len,
>> -                                  uint8_t *rsp, unsigned int *rsp_len,
>> -                                  unsigned int max_rsp_len)
>> +                                  struct rsp_buffer *rsp)
>>  {
>>      IPMISensor *sens;
>>  
>>      if ((cmd[2] >= MAX_SENSORS) ||
>>          !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      sens = ibs->sensors + cmd[2];
>> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
>> -    IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
>> -    IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
>> -    IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
>> -    IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
>> +    rsp_buffer_push(rsp, sens->assert_enable & 0xff);
>> +    rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
>> +    rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
>>  }
>>  
>>  static void rearm_sensor_evts(IPMIBmcSim *ibs,
>>                                uint8_t *cmd, unsigned int cmd_len,
>> -                              uint8_t *rsp, unsigned int *rsp_len,
>> -                              unsigned int max_rsp_len)
>> +                              struct rsp_buffer *rsp)
>>  {
>>      IPMISensor *sens;
>>  
>>      if ((cmd[2] >= MAX_SENSORS) ||
>>          !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      sens = ibs->sensors + cmd[2];
>> @@ -1528,57 +1508,54 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>>  
>>  static void get_sensor_evt_status(IPMIBmcSim *ibs,
>>                                    uint8_t *cmd, unsigned int cmd_len,
>> -                                  uint8_t *rsp, unsigned int *rsp_len,
>> -                                  unsigned int max_rsp_len)
>> +                                  struct rsp_buffer *rsp)
>>  {
>>      IPMISensor *sens;
>>  
>>      if ((cmd[2] >= MAX_SENSORS) ||
>>          !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      sens = ibs->sensors + cmd[2];
>> -    IPMI_ADD_RSP_DATA(sens->reading);
>> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
>> -    IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
>> -    IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
>> -    IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
>> -    IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, sens->reading);
>> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
>> +    rsp_buffer_push(rsp, sens->assert_states & 0xff);
>> +    rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
>> +    rsp_buffer_push(rsp, sens->deassert_states & 0xff);
>> +    rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
>>  }
>>  
>>  static void get_sensor_reading(IPMIBmcSim *ibs,
>>                                 uint8_t *cmd, unsigned int cmd_len,
>> -                               uint8_t *rsp, unsigned int *rsp_len,
>> -                               unsigned int max_rsp_len)
>> +                               struct rsp_buffer *rsp)
>>  {
>>      IPMISensor *sens;
>>  
>>      if ((cmd[2] >= MAX_SENSORS) ||
>>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      sens = ibs->sensors + cmd[2];
>> -    IPMI_ADD_RSP_DATA(sens->reading);
>> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
>> -    IPMI_ADD_RSP_DATA(sens->states & 0xff);
>> +    rsp_buffer_push(rsp, sens->reading);
>> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
>> +    rsp_buffer_push(rsp, sens->states & 0xff);
>>      if (IPMI_SENSOR_IS_DISCRETE(sens)) {
>> -        IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
>> +        rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
>>      }
>>  }
>>  
>>  static void set_sensor_type(IPMIBmcSim *ibs,
>> -                               uint8_t *cmd, unsigned int cmd_len,
>> -                               uint8_t *rsp, unsigned int *rsp_len,
>> -                               unsigned int max_rsp_len)
>> +                            uint8_t *cmd, unsigned int cmd_len,
>> +                            struct rsp_buffer *rsp)
>>  {
>>      IPMISensor *sens;
>>  
>>  
>>      if ((cmd[2] >= MAX_SENSORS) ||
>>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      sens = ibs->sensors + cmd[2];
>> @@ -1587,21 +1564,20 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>>  }
>>  
>>  static void get_sensor_type(IPMIBmcSim *ibs,
>> -                               uint8_t *cmd, unsigned int cmd_len,
>> -                               uint8_t *rsp, unsigned int *rsp_len,
>> -                               unsigned int max_rsp_len)
>> +                            uint8_t *cmd, unsigned int cmd_len,
>> +                            struct rsp_buffer *rsp)
>>  {
>>      IPMISensor *sens;
>>  
>>  
>>      if ((cmd[2] >= MAX_SENSORS) ||
>>              !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>          return;
>>      }
>>      sens = ibs->sensors + cmd[2];
>> -    IPMI_ADD_RSP_DATA(sens->sensor_type);
>> -    IPMI_ADD_RSP_DATA(sens->evt_reading_type_code);
>> +    rsp_buffer_push(rsp, sens->sensor_type);
>> +    rsp_buffer_push(rsp, sens->evt_reading_type_code);
>>  }
>>  
>>  
>> -- 
>> 2.1.4
> 
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  2016-03-02 17:53     ` Cédric Le Goater
@ 2016-03-02 18:02       ` Michael S. Tsirkin
  2016-03-02 18:08         ` Cédric Le Goater
  0 siblings, 1 reply; 23+ messages in thread
From: Michael S. Tsirkin @ 2016-03-02 18:02 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: Marcel Apfelbaum, Corey Minyard, qemu-devel

On Wed, Mar 02, 2016 at 06:53:08PM +0100, Cédric Le Goater wrote:
> > typedef struct RspBuffer RspBuffer;
> 
> OK. So that's the rule for structs in qemu. It is not that clear
> when you look at the code around. I will change. np.

Did you look at CODING_STYLE? Pls do.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  2016-03-02 18:02       ` Michael S. Tsirkin
@ 2016-03-02 18:08         ` Cédric Le Goater
  0 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-02 18:08 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Marcel Apfelbaum, Corey Minyard, qemu-devel

On 03/02/2016 07:02 PM, Michael S. Tsirkin wrote:
> On Wed, Mar 02, 2016 at 06:53:08PM +0100, Cédric Le Goater wrote:
>>> typedef struct RspBuffer RspBuffer;
>>
>> OK. So that's the rule for structs in qemu. It is not that clear
>> when you look at the code around. I will change. np.
> 
> Did you look at CODING_STYLE? Pls do.

This is clear. Thanks.

C.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro Cédric Le Goater
@ 2016-03-05 11:41   ` Corey Minyard
  2016-03-07 10:40     ` Cédric Le Goater
  0 siblings, 1 reply; 23+ messages in thread
From: Corey Minyard @ 2016-03-05 11:41 UTC (permalink / raw)
  To: Cédric Le Goater, Corey Minyard
  Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
> Most IPMI command handlers in the BMC simulator start with a call to
> the macro IPMI_CHECK_CMD_LEN() which verifies that a minimal number of
> arguments expected by the command are indeed available. To achieve
> this task, the macro implicitly uses local variables which is
> misleading in the code.
>
> This patch adds a 'cmd_len_min' attribute to the struct IPMICmdHandler
> defining the minimal number of arguments expected by the command and
> moves this check in the global command handler ipmi_sim_handle_command().

This is much better.  One style comment inline...

Acked-by: Corey Minyard <cminyard@mvista.com>

> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
> ---
>   hw/ipmi/ipmi_bmc_sim.c | 137 ++++++++++++++++++++++---------------------------
>   1 file changed, 62 insertions(+), 75 deletions(-)
>
> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
> index 51d234aa1bf2..30b9fb48ea2d 100644
> --- a/hw/ipmi/ipmi_bmc_sim.c
> +++ b/hw/ipmi/ipmi_bmc_sim.c
> @@ -155,10 +155,15 @@ typedef struct IPMISensor {
>   typedef struct IPMIBmcSim IPMIBmcSim;
>
>   #define MAX_NETFNS 64
> -typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
> -                               uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len);
> +
> +typedef struct IPMICmdHandler {
> +    void (*cmd_handler)(IPMIBmcSim *s,
> +                        uint8_t *cmd, unsigned int cmd_len,
> +                        uint8_t *rsp, unsigned int *rsp_len,
> +                        unsigned int max_rsp_len);
> +    unsigned int cmd_len_min;
> +} IPMICmdHandler;
> +
>   typedef struct IPMINetfn {
>       unsigned int cmd_nums;
>       const IPMICmdHandler *cmd_handlers;
> @@ -269,13 +274,6 @@ struct IPMIBmcSim {
>           rsp[(*rsp_len)++] = (b);                           \
>       } while (0)
>
> -/* Verify that the received command is a certain length. */
> -#define IPMI_CHECK_CMD_LEN(l) \
> -    if (cmd_len < l) {                                     \
> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;      \
> -        return; \
> -    }
> -
>   /* Check that the reservation in the command is valid. */
>   #define IPMI_CHECK_RESERVATION(off, r) \
>       do {                                                   \
> @@ -623,14 +621,19 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>
>       /* Odd netfns are not valid, make sure the command is registered */
>       if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
> -                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
> -                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
> +        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
> +        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
>           rsp[2] = IPMI_CC_INVALID_CMD;
>           goto out;

I'm not sure of the qemu style here, but the above change makes the code 
hard to read.

The qemu style really seems to be to not have big if statements like
this, so maybe this crasy check should be moved to a separate function?

>       }
>
> -    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
> -                                                max_rsp_len);
> +    if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        goto out;
> +    }
> +
> +    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
> +                                                rsp, rsp_len, max_rsp_len);
>
>    out:
>       k->handle_rsp(s, msg_id, rsp, *rsp_len);
> @@ -737,7 +740,6 @@ static void chassis_control(IPMIBmcSim *ibs,
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>
> -    IPMI_CHECK_CMD_LEN(3);
>       switch (cmd[2] & 0xf) {
>       case 0: /* power down */
>           rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
> @@ -838,7 +840,6 @@ static void set_acpi_power_state(IPMIBmcSim *ibs,
>                             uint8_t *rsp, unsigned int *rsp_len,
>                             unsigned int max_rsp_len)
>   {
> -    IPMI_CHECK_CMD_LEN(4);
>       ibs->acpi_power_state[0] = cmd[2];
>       ibs->acpi_power_state[1] = cmd[3];
>   }
> @@ -869,7 +870,6 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs,
>                                      uint8_t *rsp, unsigned int *rsp_len,
>                                      unsigned int max_rsp_len)
>   {
> -    IPMI_CHECK_CMD_LEN(3);
>       set_global_enables(ibs, cmd[2]);
>   }
>
> @@ -889,7 +889,6 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>
> -    IPMI_CHECK_CMD_LEN(3);
>       ibs->msg_flags &= ~cmd[2];
>       k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
>   }
> @@ -976,15 +975,17 @@ static void send_msg(IPMIBmcSim *ibs,
>       uint8_t *buf;
>       uint8_t netfn, rqLun, rsLun, rqSeq;
>
> -    IPMI_CHECK_CMD_LEN(3);
> -
>       if (cmd[2] != 0) {
>           /* We only handle channel 0 with no options */
>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>
> -    IPMI_CHECK_CMD_LEN(10);
> +    if (cmd_len < 10) {
> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        return;
> +    }
> +
>       if (cmd[3] != 0x40) {
>           /* We only emulate a MC at address 0x40. */
>           rsp[2] = 0x83; /* NAK on write */
> @@ -1092,7 +1093,6 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>       unsigned int val;
>
> -    IPMI_CHECK_CMD_LEN(8);
>       val = cmd[2] & 0x7; /* Validate use */
>       if (val == 0 || val > 5) {
>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> @@ -1217,7 +1217,6 @@ static void get_sdr(IPMIBmcSim *ibs,
>       uint16_t nextrec;
>       struct ipmi_sdr_header *sdrh;
>
> -    IPMI_CHECK_CMD_LEN(8);
>       if (cmd[6]) {
>           IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>       }
> @@ -1271,7 +1270,6 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>                             uint8_t *rsp, unsigned int *rsp_len,
>                             unsigned int max_rsp_len)
>   {
> -    IPMI_CHECK_CMD_LEN(8);
>       IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> @@ -1330,7 +1328,6 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>   {
>       unsigned int val;
>
> -    IPMI_CHECK_CMD_LEN(8);
>       if (cmd[6]) {
>           IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>       }
> @@ -1375,7 +1372,6 @@ static void add_sel_entry(IPMIBmcSim *ibs,
>                             uint8_t *rsp, unsigned int *rsp_len,
>                             unsigned int max_rsp_len)
>   {
> -    IPMI_CHECK_CMD_LEN(18);
>       if (sel_add_event(ibs, cmd + 2)) {
>           rsp[2] = IPMI_CC_OUT_OF_SPACE;
>           return;
> @@ -1390,7 +1386,6 @@ static void clear_sel(IPMIBmcSim *ibs,
>                         uint8_t *rsp, unsigned int *rsp_len,
>                         unsigned int max_rsp_len)
>   {
> -    IPMI_CHECK_CMD_LEN(8);
>       IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> @@ -1434,7 +1429,6 @@ static void set_sel_time(IPMIBmcSim *ibs,
>       uint32_t val;
>       struct ipmi_time now;
>
> -    IPMI_CHECK_CMD_LEN(6);
>       val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
>       ipmi_gettime(&now);
>       ibs->sel.time_offset = now.tv_sec - ((long) val);
> @@ -1447,7 +1441,6 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>   {
>       IPMISensor *sens;
>
> -    IPMI_CHECK_CMD_LEN(4);
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1499,7 +1492,6 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>   {
>       IPMISensor *sens;
>
> -    IPMI_CHECK_CMD_LEN(3);
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1520,7 +1512,6 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>   {
>       IPMISensor *sens;
>
> -    IPMI_CHECK_CMD_LEN(4);
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1542,7 +1533,6 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
>   {
>       IPMISensor *sens;
>
> -    IPMI_CHECK_CMD_LEN(3);
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1564,7 +1554,6 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
>   {
>       IPMISensor *sens;
>
> -    IPMI_CHECK_CMD_LEN(3);
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1587,7 +1576,6 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>       IPMISensor *sens;
>
>
> -    IPMI_CHECK_CMD_LEN(5);
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1606,7 +1594,6 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>       IPMISensor *sens;
>
>
> -    IPMI_CHECK_CMD_LEN(3);
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> @@ -1619,10 +1606,10 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>
>
>   static const IPMICmdHandler chassis_cmds[] = {
> -    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
> -    [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
> -    [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
> -    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
> +    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
> +    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
> +    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
> +    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
>   };
>   static const IPMINetfn chassis_netfn = {
>       .cmd_nums = ARRAY_SIZE(chassis_cmds),
> @@ -1630,13 +1617,13 @@ static const IPMINetfn chassis_netfn = {
>   };
>
>   static const IPMICmdHandler sensor_event_cmds[] = {
> -    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
> -    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
> -    [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
> -    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
> -    [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
> -    [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
> -    [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
> +    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
> +    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
> +    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
> +    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
> +    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
> +    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
> +    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
>   };
>   static const IPMINetfn sensor_event_netfn = {
>       .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
> @@ -1644,22 +1631,22 @@ static const IPMINetfn sensor_event_netfn = {
>   };
>
>   static const IPMICmdHandler app_cmds[] = {
> -    [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
> -    [IPMI_CMD_COLD_RESET] = cold_reset,
> -    [IPMI_CMD_WARM_RESET] = warm_reset,
> -    [IPMI_CMD_SET_ACPI_POWER_STATE] = set_acpi_power_state,
> -    [IPMI_CMD_GET_ACPI_POWER_STATE] = get_acpi_power_state,
> -    [IPMI_CMD_GET_DEVICE_GUID] = get_device_guid,
> -    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
> -    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
> -    [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
> -    [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
> -    [IPMI_CMD_GET_MSG] = get_msg,
> -    [IPMI_CMD_SEND_MSG] = send_msg,
> -    [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
> -    [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
> -    [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
> -    [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
> +    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
> +    [IPMI_CMD_COLD_RESET] = { cold_reset },
> +    [IPMI_CMD_WARM_RESET] = { warm_reset },
> +    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
> +    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
> +    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
> +    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
> +    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
> +    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
> +    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
> +    [IPMI_CMD_GET_MSG] = { get_msg },
> +    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
> +    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
> +    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
> +    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
> +    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
>   };
>   static const IPMINetfn app_netfn = {
>       .cmd_nums = ARRAY_SIZE(app_cmds),
> @@ -1667,18 +1654,18 @@ static const IPMINetfn app_netfn = {
>   };
>
>   static const IPMICmdHandler storage_cmds[] = {
> -    [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
> -    [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
> -    [IPMI_CMD_GET_SDR] = get_sdr,
> -    [IPMI_CMD_ADD_SDR] = add_sdr,
> -    [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
> -    [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
> -    [IPMI_CMD_RESERVE_SEL] = reserve_sel,
> -    [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
> -    [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
> -    [IPMI_CMD_CLEAR_SEL] = clear_sel,
> -    [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
> -    [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
> +    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
> +    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
> +    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
> +    [IPMI_CMD_ADD_SDR] = { add_sdr },
> +    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
> +    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
> +    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
> +    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
> +    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
> +    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
> +    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
> +    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
>   };
>
>   static const IPMINetfn storage_netfn = {

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers Cédric Le Goater
  2016-03-02 10:25   ` Michael S. Tsirkin
@ 2016-03-05 11:41   ` Corey Minyard
  1 sibling, 0 replies; 23+ messages in thread
From: Corey Minyard @ 2016-03-05 11:41 UTC (permalink / raw)
  To: Cédric Le Goater, Corey Minyard
  Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
> The IPMI command handlers in the BMC simulator use a macro
> IPMI_ADD_RSP_DATA() to push bytes in a response buffer. The macro
> hides the fact that it implicitly uses variables local to the handler,
> which is misleading.
>
> This patch introduces a simple 'struct rsp_buffer' and inlined helper
> routines to store byte(s) in a response buffer. rsp_buffer_push()
> replaces the macro IPMI_ADD_RSP_DATA() and rsp_buffer_pushmore() is
> new helper to push multiple bytes. The latest is used in the command
> handlers get_msg() and get_sdr() which are manipulating the buffer
> directly.
>
> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>

Acked-by: Corey Minyard <cminyard@mvista.com>

> ---
>   hw/ipmi/ipmi_bmc_sim.c | 482 +++++++++++++++++++++++--------------------------
>   1 file changed, 229 insertions(+), 253 deletions(-)
>
> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
> index 30b9fb48ea2d..32efb87c8232 100644
> --- a/hw/ipmi/ipmi_bmc_sim.c
> +++ b/hw/ipmi/ipmi_bmc_sim.c
> @@ -153,14 +153,14 @@ typedef struct IPMISensor {
>   #define IPMI_WATCHDOG_SENSOR 0
>
>   typedef struct IPMIBmcSim IPMIBmcSim;
> +struct rsp_buffer;
>
>   #define MAX_NETFNS 64
>
>   typedef struct IPMICmdHandler {
>       void (*cmd_handler)(IPMIBmcSim *s,
>                           uint8_t *cmd, unsigned int cmd_len,
> -                        uint8_t *rsp, unsigned int *rsp_len,
> -                        unsigned int max_rsp_len);
> +                        struct rsp_buffer *rsp);
>       unsigned int cmd_len_min;
>   } IPMICmdHandler;
>
> @@ -263,22 +263,41 @@ struct IPMIBmcSim {
>   #define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN      2
>   #define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE     3
>
> +struct rsp_buffer {
> +    uint8_t buffer[MAX_IPMI_MSG_SIZE];
> +    unsigned int len;
> +    unsigned int max_len;
> +};
> +
> +#define RSP_BUFFER_INITIALIZER { { 0 }, 0, MAX_IPMI_MSG_SIZE }
>
>   /* Add a byte to the response. */
> -#define IPMI_ADD_RSP_DATA(b) \
> -    do {                                                   \
> -        if (*rsp_len >= max_rsp_len) {                     \
> -            rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;       \
> -            return;                                        \
> -        }                                                  \
> -        rsp[(*rsp_len)++] = (b);                           \
> -    } while (0)
> +static inline void rsp_buffer_push(struct rsp_buffer *rsp, uint8_t byte)
> +{
> +    if (rsp->len >= rsp->max_len) {
> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        return;
> +    }
> +    rsp->buffer[rsp->len++] = byte;
> +}
> +
> +static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
> +                                       unsigned int n)
> +{
> +    if (rsp->len + n >= rsp->max_len) {
> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        return;
> +    }
> +
> +    memcpy(&rsp->buffer[rsp->len], bytes, n);
> +    rsp->len += n;
> +}
>
>   /* Check that the reservation in the command is valid. */
>   #define IPMI_CHECK_RESERVATION(off, r) \
>       do {                                                   \
>           if ((cmd[off] | (cmd[off + 1] << 8)) != r) {       \
> -            rsp[2] = IPMI_CC_INVALID_RESERVATION;          \
> +            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;     \
>               return;                                        \
>           }                                                  \
>       } while (0)
> @@ -585,35 +604,32 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>       unsigned int netfn;
> -    uint8_t rsp[MAX_IPMI_MSG_SIZE];
> -    unsigned int rsp_len_holder = 0;
> -    unsigned int *rsp_len = &rsp_len_holder;
> -    unsigned int max_rsp_len = sizeof(rsp);
> +    struct rsp_buffer rsp = RSP_BUFFER_INITIALIZER;
>
>       /* Set up the response, set the low bit of NETFN. */
>       /* Note that max_rsp_len must be at least 3 */
> -    if (max_rsp_len < 3) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +    if (rsp.max_len < 3) {
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>           goto out;
>       }
>
> -    IPMI_ADD_RSP_DATA(cmd[0] | 0x04);
> -    IPMI_ADD_RSP_DATA(cmd[1]);
> -    IPMI_ADD_RSP_DATA(0); /* Assume success */
> +    rsp_buffer_push(&rsp, cmd[0] | 0x04);
> +    rsp_buffer_push(&rsp, cmd[1]);
> +    rsp_buffer_push(&rsp, 0); /* Assume success */
>
>       /* If it's too short or it was truncated, return an error. */
>       if (cmd_len < 2) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>           goto out;
>       }
>       if (cmd_len > max_cmd_len) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
>           goto out;
>       }
>
>       if ((cmd[0] & 0x03) != 0) {
>           /* Only have stuff on LUN 0 */
> -        rsp[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
> +        rsp.buffer[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
>           goto out;
>       }
>
> @@ -623,20 +639,20 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>       if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>           (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>           (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
> -        rsp[2] = IPMI_CC_INVALID_CMD;
> +        rsp.buffer[2] = IPMI_CC_INVALID_CMD;
>           goto out;
>       }
>
>       if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>           goto out;
>       }
>
>       ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
> -                                                rsp, rsp_len, max_rsp_len);
> +                                                &rsp);
>
>    out:
> -    k->handle_rsp(s, msg_id, rsp, *rsp_len);
> +    k->handle_rsp(s, msg_id, rsp.buffer, rsp.len);
>
>       next_timeout(ibs);
>   }
> @@ -711,86 +727,82 @@ static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs)
>
>   static void chassis_capabilities(IPMIBmcSim *ibs,
>                                    uint8_t *cmd, unsigned int cmd_len,
> -                                 uint8_t *rsp, unsigned int *rsp_len,
> -                                 unsigned int max_rsp_len)
> +                                 struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(0);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> -    IPMI_ADD_RSP_DATA(ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, 0);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
> +    rsp_buffer_push(rsp, ibs->parent.slave_addr);
>   }
>
>   static void chassis_status(IPMIBmcSim *ibs,
>                              uint8_t *cmd, unsigned int cmd_len,
> -                           uint8_t *rsp, unsigned int *rsp_len,
> -                           unsigned int max_rsp_len)
> +                           struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(0x61); /* Unknown power restore, power is on */
> -    IPMI_ADD_RSP_DATA(0);
> -    IPMI_ADD_RSP_DATA(0);
> -    IPMI_ADD_RSP_DATA(0);
> +    rsp_buffer_push(rsp, 0x61); /* Unknown power restore, power is on */
> +    rsp_buffer_push(rsp, 0);
> +    rsp_buffer_push(rsp, 0);
> +    rsp_buffer_push(rsp, 0);
>   }
>
>   static void chassis_control(IPMIBmcSim *ibs,
>                               uint8_t *cmd, unsigned int cmd_len,
> -                            uint8_t *rsp, unsigned int *rsp_len,
> -                            unsigned int max_rsp_len)
> +                            struct rsp_buffer *rsp)
>   {
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>
>       switch (cmd[2] & 0xf) {
>       case 0: /* power down */
> -        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>           break;
>       case 1: /* power up */
> -        rsp[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
>           break;
>       case 2: /* power cycle */
> -        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
>           break;
>       case 3: /* hard reset */
> -        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
>           break;
>       case 4: /* pulse diagnostic interrupt */
> -        rsp[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
>           break;
>       case 5: /* soft shutdown via ACPI by overtemp emulation */
> -        rsp[2] = k->do_hw_op(s,
> +        rsp->buffer[2] = k->do_hw_op(s,
>                                IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
>           break;
>       default:
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>   }
>
>   static void chassis_get_sys_restart_cause(IPMIBmcSim *ibs,
>                              uint8_t *cmd, unsigned int cmd_len,
> -                           uint8_t *rsp, unsigned int *rsp_len,
> -                           unsigned int max_rsp_len)
> +                           struct rsp_buffer *rsp)
> +
>   {
> -    IPMI_ADD_RSP_DATA(ibs->restart_cause & 0xf); /* Restart Cause */
> -    IPMI_ADD_RSP_DATA(0);  /* Channel 0 */
> +    rsp_buffer_push(rsp, ibs->restart_cause & 0xf); /* Restart Cause */
> +    rsp_buffer_push(rsp, 0);  /* Channel 0 */
>   }
>
>   static void get_device_id(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> -{
> -    IPMI_ADD_RSP_DATA(ibs->device_id);
> -    IPMI_ADD_RSP_DATA(ibs->device_rev & 0xf);
> -    IPMI_ADD_RSP_DATA(ibs->fwrev1 & 0x7f);
> -    IPMI_ADD_RSP_DATA(ibs->fwrev2);
> -    IPMI_ADD_RSP_DATA(ibs->ipmi_version);
> -    IPMI_ADD_RSP_DATA(0x07); /* sensor, SDR, and SEL. */
> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[0]);
> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[1]);
> -    IPMI_ADD_RSP_DATA(ibs->mfg_id[2]);
> -    IPMI_ADD_RSP_DATA(ibs->product_id[0]);
> -    IPMI_ADD_RSP_DATA(ibs->product_id[1]);
> +                          struct rsp_buffer *rsp)
> +{
> +    rsp_buffer_push(rsp, ibs->device_id);
> +    rsp_buffer_push(rsp, ibs->device_rev & 0xf);
> +    rsp_buffer_push(rsp, ibs->fwrev1 & 0x7f);
> +    rsp_buffer_push(rsp, ibs->fwrev2);
> +    rsp_buffer_push(rsp, ibs->ipmi_version);
> +    rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
> +    rsp_buffer_push(rsp, ibs->mfg_id[0]);
> +    rsp_buffer_push(rsp, ibs->mfg_id[1]);
> +    rsp_buffer_push(rsp, ibs->mfg_id[2]);
> +    rsp_buffer_push(rsp, ibs->product_id[0]);
> +    rsp_buffer_push(rsp, ibs->product_id[1]);
>   }
>
>   static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
> @@ -809,8 +821,7 @@ static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
>
>   static void cold_reset(IPMIBmcSim *ibs,
>                          uint8_t *cmd, unsigned int cmd_len,
> -                       uint8_t *rsp, unsigned int *rsp_len,
> -                       unsigned int max_rsp_len)
> +                       struct rsp_buffer *rsp)
>   {
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -825,8 +836,7 @@ static void cold_reset(IPMIBmcSim *ibs,
>
>   static void warm_reset(IPMIBmcSim *ibs,
>                          uint8_t *cmd, unsigned int cmd_len,
> -                       uint8_t *rsp, unsigned int *rsp_len,
> -                       unsigned int max_rsp_len)
> +                       struct rsp_buffer *rsp)
>   {
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -836,55 +846,49 @@ static void warm_reset(IPMIBmcSim *ibs,
>       }
>   }
>   static void set_acpi_power_state(IPMIBmcSim *ibs,
> -                          uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                                 uint8_t *cmd, unsigned int cmd_len,
> +                                 struct rsp_buffer *rsp)
>   {
>       ibs->acpi_power_state[0] = cmd[2];
>       ibs->acpi_power_state[1] = cmd[3];
>   }
>
>   static void get_acpi_power_state(IPMIBmcSim *ibs,
> -                          uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                                 uint8_t *cmd, unsigned int cmd_len,
> +                                 struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[0]);
> -    IPMI_ADD_RSP_DATA(ibs->acpi_power_state[1]);
> +    rsp_buffer_push(rsp, ibs->acpi_power_state[0]);
> +    rsp_buffer_push(rsp, ibs->acpi_power_state[1]);
>   }
>
>   static void get_device_guid(IPMIBmcSim *ibs,
> -                          uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                            uint8_t *cmd, unsigned int cmd_len,
> +                            struct rsp_buffer *rsp)
>   {
>       unsigned int i;
>
>       for (i = 0; i < 16; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->uuid[i]);
> +        rsp_buffer_push(rsp, ibs->uuid[i]);
>       }
>   }
>
>   static void set_bmc_global_enables(IPMIBmcSim *ibs,
>                                      uint8_t *cmd, unsigned int cmd_len,
> -                                   uint8_t *rsp, unsigned int *rsp_len,
> -                                   unsigned int max_rsp_len)
> +                                   struct rsp_buffer *rsp)
>   {
>       set_global_enables(ibs, cmd[2]);
>   }
>
>   static void get_bmc_global_enables(IPMIBmcSim *ibs,
>                                      uint8_t *cmd, unsigned int cmd_len,
> -                                   uint8_t *rsp, unsigned int *rsp_len,
> -                                   unsigned int max_rsp_len)
> +                                   struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(ibs->bmc_global_enables);
> +    rsp_buffer_push(rsp, ibs->bmc_global_enables);
>   }
>
>   static void clr_msg_flags(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>   {
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -895,27 +899,25 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>
>   static void get_msg_flags(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(ibs->msg_flags);
> +    rsp_buffer_push(rsp, ibs->msg_flags);
>   }
>
>   static void read_evt_msg_buf(IPMIBmcSim *ibs,
>                                uint8_t *cmd, unsigned int cmd_len,
> -                             uint8_t *rsp, unsigned int *rsp_len,
> -                            unsigned int max_rsp_len)
> +                             struct rsp_buffer *rsp)
>   {
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>       unsigned int i;
>
>       if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
> -        rsp[2] = 0x80;
> +        rsp->buffer[2] = 0x80;
>           return;
>       }
>       for (i = 0; i < 16; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->evtbuf[i]);
> +        rsp_buffer_push(rsp, ibs->evtbuf[i]);
>       }
>       ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
>       k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
> @@ -923,21 +925,18 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs,
>
>   static void get_msg(IPMIBmcSim *ibs,
>                       uint8_t *cmd, unsigned int cmd_len,
> -                    uint8_t *rsp, unsigned int *rsp_len,
> -                    unsigned int max_rsp_len)
> +                    struct rsp_buffer *rsp)
>   {
>       IPMIRcvBufEntry *msg;
>
>       qemu_mutex_lock(&ibs->lock);
>       if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
> -        rsp[2] = 0x80; /* Queue empty */
> +        rsp->buffer[2] = 0x80; /* Queue empty */
>           goto out;
>       }
> -    rsp[3] = 0; /* Channel 0 */
> -    *rsp_len += 1;
> +    rsp_buffer_push(rsp, 0); /* Channel 0 */
>       msg = QTAILQ_FIRST(&ibs->rcvbufs);
> -    memcpy(rsp + 4, msg->buf, msg->len);
> -    *rsp_len += msg->len;
> +    rsp_buffer_pushmore(rsp, msg->buf, msg->len);
>       QTAILQ_REMOVE(&ibs->rcvbufs, msg, entry);
>       g_free(msg);
>
> @@ -966,8 +965,7 @@ ipmb_checksum(unsigned char *data, int size, unsigned char csum)
>
>   static void send_msg(IPMIBmcSim *ibs,
>                        uint8_t *cmd, unsigned int cmd_len,
> -                     uint8_t *rsp, unsigned int *rsp_len,
> -                     unsigned int max_rsp_len)
> +                     struct rsp_buffer *rsp)
>   {
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -977,18 +975,18 @@ static void send_msg(IPMIBmcSim *ibs,
>
>       if (cmd[2] != 0) {
>           /* We only handle channel 0 with no options */
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>
>       if (cmd_len < 10) {
> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>           return;
>       }
>
>       if (cmd[3] != 0x40) {
>           /* We only emulate a MC at address 0x40. */
> -        rsp[2] = 0x83; /* NAK on write */
> +        rsp->buffer[2] = 0x83; /* NAK on write */
>           return;
>       }
>
> @@ -1074,11 +1072,10 @@ static void do_watchdog_reset(IPMIBmcSim *ibs)
>
>   static void reset_watchdog_timer(IPMIBmcSim *ibs,
>                                    uint8_t *cmd, unsigned int cmd_len,
> -                                 uint8_t *rsp, unsigned int *rsp_len,
> -                                 unsigned int max_rsp_len)
> +                                 struct rsp_buffer *rsp)
>   {
>       if (!ibs->watchdog_initialized) {
> -        rsp[2] = 0x80;
> +        rsp->buffer[2] = 0x80;
>           return;
>       }
>       do_watchdog_reset(ibs);
> @@ -1086,8 +1083,7 @@ static void reset_watchdog_timer(IPMIBmcSim *ibs,
>
>   static void set_watchdog_timer(IPMIBmcSim *ibs,
>                                  uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                               struct rsp_buffer *rsp)
>   {
>       IPMIInterface *s = ibs->parent.intf;
>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
> @@ -1095,7 +1091,7 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>
>       val = cmd[2] & 0x7; /* Validate use */
>       if (val == 0 || val > 5) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>       val = cmd[3] & 0x7; /* Validate action */
> @@ -1104,22 +1100,22 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>           break;
>
>       case IPMI_BMC_WATCHDOG_ACTION_RESET:
> -        rsp[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
>           break;
>
>       case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
> -        rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
>           break;
>
>       case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
> -        rsp[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
> +        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
>           break;
>
>       default:
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>       }
> -    if (rsp[2]) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +    if (rsp->buffer[2]) {
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>
> @@ -1132,14 +1128,14 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>       case IPMI_BMC_WATCHDOG_PRE_NMI:
>           if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
>               /* NMI not supported. */
> -            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +            rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>               return;
>           }
>           break;
>
>       default:
>           /* We don't support PRE_SMI */
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>
> @@ -1158,60 +1154,56 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>
>   static void get_watchdog_timer(IPMIBmcSim *ibs,
>                                  uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                               struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_use);
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_action);
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_pretimeout);
> -    IPMI_ADD_RSP_DATA(ibs->watchdog_expired);
> +    rsp_buffer_push(rsp, ibs->watchdog_use);
> +    rsp_buffer_push(rsp, ibs->watchdog_action);
> +    rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
> +    rsp_buffer_push(rsp, ibs->watchdog_expired);
>       if (ibs->watchdog_running) {
>           long timeout;
>           timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 50000000)
>                      / 100000000);
> -        IPMI_ADD_RSP_DATA(timeout & 0xff);
> -        IPMI_ADD_RSP_DATA((timeout >> 8) & 0xff);
> +        rsp_buffer_push(rsp, timeout & 0xff);
> +        rsp_buffer_push(rsp, (timeout >> 8) & 0xff);
>       } else {
> -        IPMI_ADD_RSP_DATA(0);
> -        IPMI_ADD_RSP_DATA(0);
> +        rsp_buffer_push(rsp, 0);
> +        rsp_buffer_push(rsp, 0);
>       }
>   }
>
>   static void get_sdr_rep_info(IPMIBmcSim *ibs,
>                                uint8_t *cmd, unsigned int cmd_len,
> -                             uint8_t *rsp, unsigned int *rsp_len,
> -                             unsigned int max_rsp_len)
> +                             struct rsp_buffer *rsp)
>   {
>       unsigned int i;
>
> -    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 spec */
> -    IPMI_ADD_RSP_DATA(ibs->sdr.next_rec_id & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sdr.next_rec_id >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA((MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
> -    IPMI_ADD_RSP_DATA(((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
> +    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 spec */
> +    rsp_buffer_push(rsp, ibs->sdr.next_rec_id & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sdr.next_rec_id >> 8) & 0xff);
> +    rsp_buffer_push(rsp, (MAX_SDR_SIZE - ibs->sdr.next_free) & 0xff);
> +    rsp_buffer_push(rsp, ((MAX_SDR_SIZE - ibs->sdr.next_free) >> 8) & 0xff);
>       for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sdr.last_addition[i]);
> +        rsp_buffer_push(rsp, ibs->sdr.last_addition[i]);
>       }
>       for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sdr.last_clear[i]);
> +        rsp_buffer_push(rsp, ibs->sdr.last_clear[i]);
>       }
>       /* Only modal support, reserve supported */
> -    IPMI_ADD_RSP_DATA((ibs->sdr.overflow << 7) | 0x22);
> +    rsp_buffer_push(rsp, (ibs->sdr.overflow << 7) | 0x22);
>   }
>
>   static void reserve_sdr_rep(IPMIBmcSim *ibs,
>                               uint8_t *cmd, unsigned int cmd_len,
> -                            uint8_t *rsp, unsigned int *rsp_len,
> -                            unsigned int max_rsp_len)
> +                            struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(ibs->sdr.reservation & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sdr.reservation >> 8) & 0xff);
> +    rsp_buffer_push(rsp, ibs->sdr.reservation & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sdr.reservation >> 8) & 0xff);
>   }
>
>   static void get_sdr(IPMIBmcSim *ibs,
>                       uint8_t *cmd, unsigned int cmd_len,
> -                    uint8_t *rsp, unsigned int *rsp_len,
> -                    unsigned int max_rsp_len)
> +                    struct rsp_buffer *rsp)
>   {
>       unsigned int pos;
>       uint16_t nextrec;
> @@ -1223,108 +1215,103 @@ static void get_sdr(IPMIBmcSim *ibs,
>       pos = 0;
>       if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
>                          &pos, &nextrec)) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>
>       sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
>
>       if (cmd[6] > ipmi_sdr_length(sdrh)) {
> -        rsp[2] = IPMI_CC_PARM_OUT_OF_RANGE;
> +        rsp->buffer[2] = IPMI_CC_PARM_OUT_OF_RANGE;
>           return;
>       }
>
> -    IPMI_ADD_RSP_DATA(nextrec & 0xff);
> -    IPMI_ADD_RSP_DATA((nextrec >> 8) & 0xff);
> +    rsp_buffer_push(rsp, nextrec & 0xff);
> +    rsp_buffer_push(rsp, (nextrec >> 8) & 0xff);
>
>       if (cmd[7] == 0xff) {
>           cmd[7] = ipmi_sdr_length(sdrh) - cmd[6];
>       }
>
> -    if ((cmd[7] + *rsp_len) > max_rsp_len) {
> -        rsp[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
> +    if ((cmd[7] + rsp->len) > rsp->max_len) {
> +        rsp->buffer[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
>           return;
>       }
> -    memcpy(rsp + *rsp_len, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
> -    *rsp_len += cmd[7];
> +
> +    rsp_buffer_pushmore(rsp, ibs->sdr.sdr + pos + cmd[6], cmd[7]);
>   }
>
>   static void add_sdr(IPMIBmcSim *ibs,
>                       uint8_t *cmd, unsigned int cmd_len,
> -                    uint8_t *rsp, unsigned int *rsp_len,
> -                    unsigned int max_rsp_len)
> +                    struct rsp_buffer *rsp)
>   {
>       uint16_t recid;
>       struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
>
>       if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
> -    IPMI_ADD_RSP_DATA(recid & 0xff);
> -    IPMI_ADD_RSP_DATA((recid >> 8) & 0xff);
> +    rsp_buffer_push(rsp, recid & 0xff);
> +    rsp_buffer_push(rsp, (recid >> 8) & 0xff);
>   }
>
>   static void clear_sdr_rep(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>   {
>       IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>       if (cmd[7] == 0xaa) {
>           ibs->sdr.next_free = 0;
>           ibs->sdr.overflow = 0;
>           set_timestamp(ibs, ibs->sdr.last_clear);
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>           sdr_inc_reservation(&ibs->sdr);
>       } else if (cmd[7] == 0) {
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>       } else {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>   }
>
>   static void get_sel_info(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                         uint8_t *rsp, unsigned int *rsp_len,
> -                         unsigned int max_rsp_len)
> +                         struct rsp_buffer *rsp)
>   {
>       unsigned int i, val;
>
> -    IPMI_ADD_RSP_DATA(0x51); /* Conform to IPMI 1.5 */
> -    IPMI_ADD_RSP_DATA(ibs->sel.next_free & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sel.next_free >> 8) & 0xff);
> +    rsp_buffer_push(rsp, 0x51); /* Conform to IPMI 1.5 */
> +    rsp_buffer_push(rsp, ibs->sel.next_free & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sel.next_free >> 8) & 0xff);
>       val = (MAX_SEL_SIZE - ibs->sel.next_free) * 16;
> -    IPMI_ADD_RSP_DATA(val & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
> +    rsp_buffer_push(rsp, val & 0xff);
> +    rsp_buffer_push(rsp, (val >> 8) & 0xff);
>       for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sel.last_addition[i]);
> +        rsp_buffer_push(rsp, ibs->sel.last_addition[i]);
>       }
>       for (i = 0; i < 4; i++) {
> -        IPMI_ADD_RSP_DATA(ibs->sel.last_clear[i]);
> +        rsp_buffer_push(rsp, ibs->sel.last_clear[i]);
>       }
>       /* Only support Reserve SEL */
> -    IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
> +    rsp_buffer_push(rsp, (ibs->sel.overflow << 7) | 0x02);
>   }
>
>   static void reserve_sel(IPMIBmcSim *ibs,
>                           uint8_t *cmd, unsigned int cmd_len,
> -                        uint8_t *rsp, unsigned int *rsp_len,
> -                        unsigned int max_rsp_len)
> +                        struct rsp_buffer *rsp)
>   {
> -    IPMI_ADD_RSP_DATA(ibs->sel.reservation & 0xff);
> -    IPMI_ADD_RSP_DATA((ibs->sel.reservation >> 8) & 0xff);
> +    rsp_buffer_push(rsp, ibs->sel.reservation & 0xff);
> +    rsp_buffer_push(rsp, (ibs->sel.reservation >> 8) & 0xff);
>   }
>
>   static void get_sel_entry(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>   {
>       unsigned int val;
>
> @@ -1332,17 +1319,17 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>           IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>       }
>       if (ibs->sel.next_free == 0) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       if (cmd[6] > 15) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>       if (cmd[7] == 0xff) {
>           cmd[7] = 16;
>       } else if ((cmd[7] + cmd[6]) > 16) {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       } else {
>           cmd[7] += cmd[6];
> @@ -1352,79 +1339,75 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>       if (val == 0xffff) {
>           val = ibs->sel.next_free - 1;
>       } else if (val >= ibs->sel.next_free) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       if ((val + 1) == ibs->sel.next_free) {
> -        IPMI_ADD_RSP_DATA(0xff);
> -        IPMI_ADD_RSP_DATA(0xff);
> +        rsp_buffer_push(rsp, 0xff);
> +        rsp_buffer_push(rsp, 0xff);
>       } else {
> -        IPMI_ADD_RSP_DATA((val + 1) & 0xff);
> -        IPMI_ADD_RSP_DATA(((val + 1) >> 8) & 0xff);
> +        rsp_buffer_push(rsp, (val + 1) & 0xff);
> +        rsp_buffer_push(rsp, ((val + 1) >> 8) & 0xff);
>       }
>       for (; cmd[6] < cmd[7]; cmd[6]++) {
> -        IPMI_ADD_RSP_DATA(ibs->sel.sel[val][cmd[6]]);
> +        rsp_buffer_push(rsp, ibs->sel.sel[val][cmd[6]]);
>       }
>   }
>
>   static void add_sel_entry(IPMIBmcSim *ibs,
>                             uint8_t *cmd, unsigned int cmd_len,
> -                          uint8_t *rsp, unsigned int *rsp_len,
> -                          unsigned int max_rsp_len)
> +                          struct rsp_buffer *rsp)
>   {
>       if (sel_add_event(ibs, cmd + 2)) {
> -        rsp[2] = IPMI_CC_OUT_OF_SPACE;
> +        rsp->buffer[2] = IPMI_CC_OUT_OF_SPACE;
>           return;
>       }
>       /* sel_add_event fills in the record number. */
> -    IPMI_ADD_RSP_DATA(cmd[2]);
> -    IPMI_ADD_RSP_DATA(cmd[3]);
> +    rsp_buffer_push(rsp, cmd[2]);
> +    rsp_buffer_push(rsp, cmd[3]);
>   }
>
>   static void clear_sel(IPMIBmcSim *ibs,
>                         uint8_t *cmd, unsigned int cmd_len,
> -                      uint8_t *rsp, unsigned int *rsp_len,
> -                      unsigned int max_rsp_len)
> +                      struct rsp_buffer *rsp)
>   {
>       IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>       if (cmd[7] == 0xaa) {
>           ibs->sel.next_free = 0;
>           ibs->sel.overflow = 0;
>           set_timestamp(ibs, ibs->sdr.last_clear);
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>           sel_inc_reservation(&ibs->sel);
>       } else if (cmd[7] == 0) {
> -        IPMI_ADD_RSP_DATA(1); /* Erasure complete */
> +        rsp_buffer_push(rsp, 1); /* Erasure complete */
>       } else {
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>   }
>
>   static void get_sel_time(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                         uint8_t *rsp, unsigned int *rsp_len,
> -                         unsigned int max_rsp_len)
> +                         struct rsp_buffer *rsp)
>   {
>       uint32_t val;
>       struct ipmi_time now;
>
>       ipmi_gettime(&now);
>       val = now.tv_sec + ibs->sel.time_offset;
> -    IPMI_ADD_RSP_DATA(val & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 16) & 0xff);
> -    IPMI_ADD_RSP_DATA((val >> 24) & 0xff);
> +    rsp_buffer_push(rsp, val & 0xff);
> +    rsp_buffer_push(rsp, (val >> 8) & 0xff);
> +    rsp_buffer_push(rsp, (val >> 16) & 0xff);
> +    rsp_buffer_push(rsp, (val >> 24) & 0xff);
>   }
>
>   static void set_sel_time(IPMIBmcSim *ibs,
>                            uint8_t *cmd, unsigned int cmd_len,
> -                         uint8_t *rsp, unsigned int *rsp_len,
> -                         unsigned int max_rsp_len)
> +                         struct rsp_buffer *rsp)
>   {
>       uint32_t val;
>       struct ipmi_time now;
> @@ -1436,14 +1419,13 @@ static void set_sel_time(IPMIBmcSim *ibs,
>
>   static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>                                     uint8_t *cmd, unsigned int cmd_len,
> -                                  uint8_t *rsp, unsigned int *rsp_len,
> -                                  unsigned int max_rsp_len)
> +                                  struct rsp_buffer *rsp)
>   {
>       IPMISensor *sens;
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1479,7 +1461,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>           }
>           break;
>       case 3:
> -        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
>           return;
>       }
>       IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
> @@ -1487,34 +1469,32 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>
>   static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>                                     uint8_t *cmd, unsigned int cmd_len,
> -                                  uint8_t *rsp, unsigned int *rsp_len,
> -                                  unsigned int max_rsp_len)
> +                                  struct rsp_buffer *rsp)
>   {
>       IPMISensor *sens;
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
> -    IPMI_ADD_RSP_DATA(sens->assert_enable & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->assert_enable >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA(sens->deassert_enable & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->deassert_enable >> 8) & 0xff);
> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
> +    rsp_buffer_push(rsp, sens->assert_enable & 0xff);
> +    rsp_buffer_push(rsp, (sens->assert_enable >> 8) & 0xff);
> +    rsp_buffer_push(rsp, sens->deassert_enable & 0xff);
> +    rsp_buffer_push(rsp, (sens->deassert_enable >> 8) & 0xff);
>   }
>
>   static void rearm_sensor_evts(IPMIBmcSim *ibs,
>                                 uint8_t *cmd, unsigned int cmd_len,
> -                              uint8_t *rsp, unsigned int *rsp_len,
> -                              unsigned int max_rsp_len)
> +                              struct rsp_buffer *rsp)
>   {
>       IPMISensor *sens;
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1528,57 +1508,54 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>
>   static void get_sensor_evt_status(IPMIBmcSim *ibs,
>                                     uint8_t *cmd, unsigned int cmd_len,
> -                                  uint8_t *rsp, unsigned int *rsp_len,
> -                                  unsigned int max_rsp_len)
> +                                  struct rsp_buffer *rsp)
>   {
>       IPMISensor *sens;
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(sens->reading);
> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
> -    IPMI_ADD_RSP_DATA(sens->assert_states & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->assert_states >> 8) & 0xff);
> -    IPMI_ADD_RSP_DATA(sens->deassert_states & 0xff);
> -    IPMI_ADD_RSP_DATA((sens->deassert_states >> 8) & 0xff);
> +    rsp_buffer_push(rsp, sens->reading);
> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
> +    rsp_buffer_push(rsp, sens->assert_states & 0xff);
> +    rsp_buffer_push(rsp, (sens->assert_states >> 8) & 0xff);
> +    rsp_buffer_push(rsp, sens->deassert_states & 0xff);
> +    rsp_buffer_push(rsp, (sens->deassert_states >> 8) & 0xff);
>   }
>
>   static void get_sensor_reading(IPMIBmcSim *ibs,
>                                  uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                               struct rsp_buffer *rsp)
>   {
>       IPMISensor *sens;
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(sens->reading);
> -    IPMI_ADD_RSP_DATA(IPMI_SENSOR_GET_RET_STATUS(sens));
> -    IPMI_ADD_RSP_DATA(sens->states & 0xff);
> +    rsp_buffer_push(rsp, sens->reading);
> +    rsp_buffer_push(rsp, IPMI_SENSOR_GET_RET_STATUS(sens));
> +    rsp_buffer_push(rsp, sens->states & 0xff);
>       if (IPMI_SENSOR_IS_DISCRETE(sens)) {
> -        IPMI_ADD_RSP_DATA((sens->states >> 8) & 0xff);
> +        rsp_buffer_push(rsp, (sens->states >> 8) & 0xff);
>       }
>   }
>
>   static void set_sensor_type(IPMIBmcSim *ibs,
> -                               uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                            uint8_t *cmd, unsigned int cmd_len,
> +                            struct rsp_buffer *rsp)
>   {
>       IPMISensor *sens;
>
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1587,21 +1564,20 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>   }
>
>   static void get_sensor_type(IPMIBmcSim *ibs,
> -                               uint8_t *cmd, unsigned int cmd_len,
> -                               uint8_t *rsp, unsigned int *rsp_len,
> -                               unsigned int max_rsp_len)
> +                            uint8_t *cmd, unsigned int cmd_len,
> +                            struct rsp_buffer *rsp)
>   {
>       IPMISensor *sens;
>
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> -    IPMI_ADD_RSP_DATA(sens->sensor_type);
> -    IPMI_ADD_RSP_DATA(sens->evt_reading_type_code);
> +    rsp_buffer_push(rsp, sens->sensor_type);
> +    rsp_buffer_push(rsp, sens->evt_reading_type_code);
>   }
>
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 04/10] ipmi: add rsp_buffer_set_error() helper
  2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 04/10] ipmi: add rsp_buffer_set_error() helper Cédric Le Goater
@ 2016-03-05 11:42   ` Corey Minyard
  0 siblings, 0 replies; 23+ messages in thread
From: Corey Minyard @ 2016-03-05 11:42 UTC (permalink / raw)
  To: Cédric Le Goater, Corey Minyard
  Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
> The third byte in the response buffer of an IPMI command holds the
> error code. In many IPMI command handlers, this byte is updated
> directly. This patch adds a helper routine to clarify why this byte is
> being used.
>
> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>

Yes, more clear.

Acked-by: Corey Minyard <cminyard@mvista.com>

> ---
>   hw/ipmi/ipmi_bmc_sim.c | 115 ++++++++++++++++++++++++++-----------------------
>   1 file changed, 60 insertions(+), 55 deletions(-)
>
> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
> index 72166a7da291..2626aff06c60 100644
> --- a/hw/ipmi/ipmi_bmc_sim.c
> +++ b/hw/ipmi/ipmi_bmc_sim.c
> @@ -271,11 +271,16 @@ struct rsp_buffer {
>
>   #define RSP_BUFFER_INITIALIZER { { 0 }, 0, MAX_IPMI_MSG_SIZE }
>
> +static inline void rsp_buffer_set_error(struct rsp_buffer *rsp, uint8_t byte)
> +{
> +    rsp->buffer[2] = byte;
> +}
> +
>   /* Add a byte to the response. */
>   static inline void rsp_buffer_push(struct rsp_buffer *rsp, uint8_t byte)
>   {
>       if (rsp->len >= rsp->max_len) {
> -        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
>           return;
>       }
>       rsp->buffer[rsp->len++] = byte;
> @@ -285,7 +290,7 @@ static inline void rsp_buffer_pushmore(struct rsp_buffer *rsp, uint8_t *bytes,
>                                          unsigned int n)
>   {
>       if (rsp->len + n >= rsp->max_len) {
> -        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
>           return;
>       }
>
> @@ -599,7 +604,7 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>       /* Set up the response, set the low bit of NETFN. */
>       /* Note that max_rsp_len must be at least 3 */
>       if (rsp.max_len < 3) {
> -        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
>           goto out;
>       }
>
> @@ -609,17 +614,17 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>
>       /* If it's too short or it was truncated, return an error. */
>       if (cmd_len < 2) {
> -        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
>           goto out;
>       }
>       if (cmd_len > max_cmd_len) {
> -        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
> +        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
>           goto out;
>       }
>
>       if ((cmd[0] & 0x03) != 0) {
>           /* Only have stuff on LUN 0 */
> -        rsp.buffer[2] = IPMI_CC_COMMAND_INVALID_FOR_LUN;
> +        rsp_buffer_set_error(&rsp, IPMI_CC_COMMAND_INVALID_FOR_LUN);
>           goto out;
>       }
>
> @@ -629,12 +634,12 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>       if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>           (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>           (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
> -        rsp.buffer[2] = IPMI_CC_INVALID_CMD;
> +        rsp_buffer_set_error(&rsp, IPMI_CC_INVALID_CMD);
>           goto out;
>       }
>
>       if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
> -        rsp.buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp_buffer_set_error(&rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
>           goto out;
>       }
>
> @@ -745,26 +750,26 @@ static void chassis_control(IPMIBmcSim *ibs,
>
>       switch (cmd[2] & 0xf) {
>       case 0: /* power down */
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0));
>           break;
>       case 1: /* power up */
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERON_CHASSIS, 0));
>           break;
>       case 2: /* power cycle */
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 0));
>           break;
>       case 3: /* hard reset */
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 0);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 0));
>           break;
>       case 4: /* pulse diagnostic interrupt */
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_PULSE_DIAG_IRQ, 0));
>           break;
>       case 5: /* soft shutdown via ACPI by overtemp emulation */
> -        rsp->buffer[2] = k->do_hw_op(s,
> -                             IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s,
> +                                          IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0));
>           break;
>       default:
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>   }
> @@ -903,7 +908,7 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs,
>       unsigned int i;
>
>       if (!(ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL)) {
> -        rsp->buffer[2] = 0x80;
> +        rsp_buffer_set_error(rsp, 0x80);
>           return;
>       }
>       for (i = 0; i < 16; i++) {
> @@ -921,7 +926,7 @@ static void get_msg(IPMIBmcSim *ibs,
>
>       qemu_mutex_lock(&ibs->lock);
>       if (QTAILQ_EMPTY(&ibs->rcvbufs)) {
> -        rsp->buffer[2] = 0x80; /* Queue empty */
> +        rsp_buffer_set_error(rsp, 0x80); /* Queue empty */
>           goto out;
>       }
>       rsp_buffer_push(rsp, 0); /* Channel 0 */
> @@ -965,18 +970,18 @@ static void send_msg(IPMIBmcSim *ibs,
>
>       if (cmd[2] != 0) {
>           /* We only handle channel 0 with no options */
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>
>       if (cmd_len < 10) {
> -        rsp->buffer[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
>           return;
>       }
>
>       if (cmd[3] != 0x40) {
>           /* We only emulate a MC at address 0x40. */
> -        rsp->buffer[2] = 0x83; /* NAK on write */
> +        rsp_buffer_set_error(rsp, 0x83); /* NAK on write */
>           return;
>       }
>
> @@ -1065,7 +1070,7 @@ static void reset_watchdog_timer(IPMIBmcSim *ibs,
>                                    struct rsp_buffer *rsp)
>   {
>       if (!ibs->watchdog_initialized) {
> -        rsp->buffer[2] = 0x80;
> +        rsp_buffer_set_error(rsp, 0x80);
>           return;
>       }
>       do_watchdog_reset(ibs);
> @@ -1081,7 +1086,7 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>
>       val = cmd[2] & 0x7; /* Validate use */
>       if (val == 0 || val > 5) {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>       val = cmd[3] & 0x7; /* Validate action */
> @@ -1090,22 +1095,22 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>           break;
>
>       case IPMI_BMC_WATCHDOG_ACTION_RESET:
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_RESET_CHASSIS, 1);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_RESET_CHASSIS, 1));
>           break;
>
>       case IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN:
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1));
>           break;
>
>       case IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE:
> -        rsp->buffer[2] = k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1);
> +        rsp_buffer_set_error(rsp, k->do_hw_op(s, IPMI_POWERCYCLE_CHASSIS, 1));
>           break;
>
>       default:
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>       }
>       if (rsp->buffer[2]) {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>
> @@ -1118,14 +1123,14 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>       case IPMI_BMC_WATCHDOG_PRE_NMI:
>           if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
>               /* NMI not supported. */
> -            rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>               return;
>           }
>           break;
>
>       default:
>           /* We don't support PRE_SMI */
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>
> @@ -1201,7 +1206,7 @@ static void get_sdr(IPMIBmcSim *ibs,
>
>       if (cmd[6]) {
>           if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
> -            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
>               return;
>           }
>       }
> @@ -1209,14 +1214,14 @@ static void get_sdr(IPMIBmcSim *ibs,
>       pos = 0;
>       if (sdr_find_entry(&ibs->sdr, cmd[4] | (cmd[5] << 8),
>                          &pos, &nextrec)) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>
>       sdrh = (struct ipmi_sdr_header *) &ibs->sdr.sdr[pos];
>
>       if (cmd[6] > ipmi_sdr_length(sdrh)) {
> -        rsp->buffer[2] = IPMI_CC_PARM_OUT_OF_RANGE;
> +        rsp_buffer_set_error(rsp, IPMI_CC_PARM_OUT_OF_RANGE);
>           return;
>       }
>
> @@ -1228,7 +1233,7 @@ static void get_sdr(IPMIBmcSim *ibs,
>       }
>
>       if ((cmd[7] + rsp->len) > rsp->max_len) {
> -        rsp->buffer[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES;
> +        rsp_buffer_set_error(rsp, IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES);
>           return;
>       }
>
> @@ -1243,7 +1248,7 @@ static void add_sdr(IPMIBmcSim *ibs,
>       struct ipmi_sdr_header *sdrh = (struct ipmi_sdr_header *) cmd + 2;
>
>       if (sdr_add_entry(ibs, sdrh, cmd_len - 2, &recid)) {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>       rsp_buffer_push(rsp, recid & 0xff);
> @@ -1255,12 +1260,12 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>                             struct rsp_buffer *rsp)
>   {
>       if ((cmd[2] | (cmd[3] << 8)) != ibs->sdr.reservation) {
> -        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
>           return;
>       }
>
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>       if (cmd[7] == 0xaa) {
> @@ -1272,7 +1277,7 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>       } else if (cmd[7] == 0) {
>           rsp_buffer_push(rsp, 1); /* Erasure complete */
>       } else {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>   }
> @@ -1315,22 +1320,22 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>
>       if (cmd[6]) {
>           if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
> -            rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +            rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
>               return;
>           }
>       }
>       if (ibs->sel.next_free == 0) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       if (cmd[6] > 15) {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>       if (cmd[7] == 0xff) {
>           cmd[7] = 16;
>       } else if ((cmd[7] + cmd[6]) > 16) {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       } else {
>           cmd[7] += cmd[6];
> @@ -1340,7 +1345,7 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>       if (val == 0xffff) {
>           val = ibs->sel.next_free - 1;
>       } else if (val >= ibs->sel.next_free) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       if ((val + 1) == ibs->sel.next_free) {
> @@ -1360,7 +1365,7 @@ static void add_sel_entry(IPMIBmcSim *ibs,
>                             struct rsp_buffer *rsp)
>   {
>       if (sel_add_event(ibs, cmd + 2)) {
> -        rsp->buffer[2] = IPMI_CC_OUT_OF_SPACE;
> +        rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
>           return;
>       }
>       /* sel_add_event fills in the record number. */
> @@ -1373,12 +1378,12 @@ static void clear_sel(IPMIBmcSim *ibs,
>                         struct rsp_buffer *rsp)
>   {
>       if ((cmd[2] | (cmd[3] << 8)) != ibs->sel.reservation) {
> -        rsp->buffer[2] = IPMI_CC_INVALID_RESERVATION;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_RESERVATION);
>           return;
>       }
>
>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>       if (cmd[7] == 0xaa) {
> @@ -1390,7 +1395,7 @@ static void clear_sel(IPMIBmcSim *ibs,
>       } else if (cmd[7] == 0) {
>           rsp_buffer_push(rsp, 1); /* Erasure complete */
>       } else {
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>   }
> @@ -1430,7 +1435,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1466,7 +1471,7 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>           }
>           break;
>       case 3:
> -        rsp->buffer[2] = IPMI_CC_INVALID_DATA_FIELD;
> +        rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
>           return;
>       }
>       IPMI_SENSOR_SET_RET_STATUS(sens, cmd[3]);
> @@ -1480,7 +1485,7 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1499,7 +1504,7 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1519,7 +1524,7 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1539,7 +1544,7 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1560,7 +1565,7 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       sens = ibs->sensors + cmd[2];
> @@ -1577,7 +1582,7 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>
>       if ((cmd[2] >= MAX_SENSORS) ||
>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
> -        rsp->buffer[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
> +        rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
>           return;
>       }
>       sens = ibs->sensors + cmd[2];

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro
  2016-03-05 11:41   ` Corey Minyard
@ 2016-03-07 10:40     ` Cédric Le Goater
  2016-03-08 17:06       ` Cédric Le Goater
  0 siblings, 1 reply; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-07 10:40 UTC (permalink / raw)
  To: minyard, Corey Minyard; +Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/05/2016 12:41 PM, Corey Minyard wrote:
> On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
>> Most IPMI command handlers in the BMC simulator start with a call to
>> the macro IPMI_CHECK_CMD_LEN() which verifies that a minimal number of
>> arguments expected by the command are indeed available. To achieve
>> this task, the macro implicitly uses local variables which is
>> misleading in the code.
>>
>> This patch adds a 'cmd_len_min' attribute to the struct IPMICmdHandler
>> defining the minimal number of arguments expected by the command and
>> moves this check in the global command handler ipmi_sim_handle_command().
> 
> This is much better.  One style comment inline...
> 
> Acked-by: Corey Minyard <cminyard@mvista.com>
> 
>> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
>> ---
>>   hw/ipmi/ipmi_bmc_sim.c | 137 ++++++++++++++++++++++---------------------------
>>   1 file changed, 62 insertions(+), 75 deletions(-)
>>
>> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
>> index 51d234aa1bf2..30b9fb48ea2d 100644
>> --- a/hw/ipmi/ipmi_bmc_sim.c
>> +++ b/hw/ipmi/ipmi_bmc_sim.c
>> @@ -155,10 +155,15 @@ typedef struct IPMISensor {
>>   typedef struct IPMIBmcSim IPMIBmcSim;
>>
>>   #define MAX_NETFNS 64
>> -typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
>> -                               uint8_t *cmd, unsigned int cmd_len,
>> -                               uint8_t *rsp, unsigned int *rsp_len,
>> -                               unsigned int max_rsp_len);
>> +
>> +typedef struct IPMICmdHandler {
>> +    void (*cmd_handler)(IPMIBmcSim *s,
>> +                        uint8_t *cmd, unsigned int cmd_len,
>> +                        uint8_t *rsp, unsigned int *rsp_len,
>> +                        unsigned int max_rsp_len);
>> +    unsigned int cmd_len_min;
>> +} IPMICmdHandler;
>> +
>>   typedef struct IPMINetfn {
>>       unsigned int cmd_nums;
>>       const IPMICmdHandler *cmd_handlers;
>> @@ -269,13 +274,6 @@ struct IPMIBmcSim {
>>           rsp[(*rsp_len)++] = (b);                           \
>>       } while (0)
>>
>> -/* Verify that the received command is a certain length. */
>> -#define IPMI_CHECK_CMD_LEN(l) \
>> -    if (cmd_len < l) {                                     \
>> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;      \
>> -        return; \
>> -    }
>> -
>>   /* Check that the reservation in the command is valid. */
>>   #define IPMI_CHECK_RESERVATION(off, r) \
>>       do {                                                   \
>> @@ -623,14 +621,19 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>>
>>       /* Odd netfns are not valid, make sure the command is registered */
>>       if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>> -                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>> -                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
>> +        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>> +        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
>>           rsp[2] = IPMI_CC_INVALID_CMD;
>>           goto out;
> 
> I'm not sure of the qemu style here, but the above change makes the code hard to read.

Cleary. I was lazy. I will try to clarify what this code does with a helper
or some intermediate variables.

Thanks,

C.

> The qemu style really seems to be to not have big if statements like
> this, so maybe this crasy check should be moved to a separate function?
>
>>       }
>>
>> -    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
>> -                                                max_rsp_len);
>> +    if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>> +        goto out;
>> +    }
>> +
>> +    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
>> +                                                rsp, rsp_len, max_rsp_len);
>>
>>    out:
>>       k->handle_rsp(s, msg_id, rsp, *rsp_len);
>> @@ -737,7 +740,6 @@ static void chassis_control(IPMIBmcSim *ibs,
>>       IPMIInterface *s = ibs->parent.intf;
>>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>
>> -    IPMI_CHECK_CMD_LEN(3);
>>       switch (cmd[2] & 0xf) {
>>       case 0: /* power down */
>>           rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>> @@ -838,7 +840,6 @@ static void set_acpi_power_state(IPMIBmcSim *ibs,
>>                             uint8_t *rsp, unsigned int *rsp_len,
>>                             unsigned int max_rsp_len)
>>   {
>> -    IPMI_CHECK_CMD_LEN(4);
>>       ibs->acpi_power_state[0] = cmd[2];
>>       ibs->acpi_power_state[1] = cmd[3];
>>   }
>> @@ -869,7 +870,6 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs,
>>                                      uint8_t *rsp, unsigned int *rsp_len,
>>                                      unsigned int max_rsp_len)
>>   {
>> -    IPMI_CHECK_CMD_LEN(3);
>>       set_global_enables(ibs, cmd[2]);
>>   }
>>
>> @@ -889,7 +889,6 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>>       IPMIInterface *s = ibs->parent.intf;
>>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>
>> -    IPMI_CHECK_CMD_LEN(3);
>>       ibs->msg_flags &= ~cmd[2];
>>       k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
>>   }
>> @@ -976,15 +975,17 @@ static void send_msg(IPMIBmcSim *ibs,
>>       uint8_t *buf;
>>       uint8_t netfn, rqLun, rsLun, rqSeq;
>>
>> -    IPMI_CHECK_CMD_LEN(3);
>> -
>>       if (cmd[2] != 0) {
>>           /* We only handle channel 0 with no options */
>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>           return;
>>       }
>>
>> -    IPMI_CHECK_CMD_LEN(10);
>> +    if (cmd_len < 10) {
>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>> +        return;
>> +    }
>> +
>>       if (cmd[3] != 0x40) {
>>           /* We only emulate a MC at address 0x40. */
>>           rsp[2] = 0x83; /* NAK on write */
>> @@ -1092,7 +1093,6 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>       unsigned int val;
>>
>> -    IPMI_CHECK_CMD_LEN(8);
>>       val = cmd[2] & 0x7; /* Validate use */
>>       if (val == 0 || val > 5) {
>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> @@ -1217,7 +1217,6 @@ static void get_sdr(IPMIBmcSim *ibs,
>>       uint16_t nextrec;
>>       struct ipmi_sdr_header *sdrh;
>>
>> -    IPMI_CHECK_CMD_LEN(8);
>>       if (cmd[6]) {
>>           IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>       }
>> @@ -1271,7 +1270,6 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>>                             uint8_t *rsp, unsigned int *rsp_len,
>>                             unsigned int max_rsp_len)
>>   {
>> -    IPMI_CHECK_CMD_LEN(8);
>>       IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> @@ -1330,7 +1328,6 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>>   {
>>       unsigned int val;
>>
>> -    IPMI_CHECK_CMD_LEN(8);
>>       if (cmd[6]) {
>>           IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>       }
>> @@ -1375,7 +1372,6 @@ static void add_sel_entry(IPMIBmcSim *ibs,
>>                             uint8_t *rsp, unsigned int *rsp_len,
>>                             unsigned int max_rsp_len)
>>   {
>> -    IPMI_CHECK_CMD_LEN(18);
>>       if (sel_add_event(ibs, cmd + 2)) {
>>           rsp[2] = IPMI_CC_OUT_OF_SPACE;
>>           return;
>> @@ -1390,7 +1386,6 @@ static void clear_sel(IPMIBmcSim *ibs,
>>                         uint8_t *rsp, unsigned int *rsp_len,
>>                         unsigned int max_rsp_len)
>>   {
>> -    IPMI_CHECK_CMD_LEN(8);
>>       IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>> @@ -1434,7 +1429,6 @@ static void set_sel_time(IPMIBmcSim *ibs,
>>       uint32_t val;
>>       struct ipmi_time now;
>>
>> -    IPMI_CHECK_CMD_LEN(6);
>>       val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
>>       ipmi_gettime(&now);
>>       ibs->sel.time_offset = now.tv_sec - ((long) val);
>> @@ -1447,7 +1441,6 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>>   {
>>       IPMISensor *sens;
>>
>> -    IPMI_CHECK_CMD_LEN(4);
>>       if ((cmd[2] >= MAX_SENSORS) ||
>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> @@ -1499,7 +1492,6 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>>   {
>>       IPMISensor *sens;
>>
>> -    IPMI_CHECK_CMD_LEN(3);
>>       if ((cmd[2] >= MAX_SENSORS) ||
>>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> @@ -1520,7 +1512,6 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>>   {
>>       IPMISensor *sens;
>>
>> -    IPMI_CHECK_CMD_LEN(4);
>>       if ((cmd[2] >= MAX_SENSORS) ||
>>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> @@ -1542,7 +1533,6 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
>>   {
>>       IPMISensor *sens;
>>
>> -    IPMI_CHECK_CMD_LEN(3);
>>       if ((cmd[2] >= MAX_SENSORS) ||
>>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> @@ -1564,7 +1554,6 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
>>   {
>>       IPMISensor *sens;
>>
>> -    IPMI_CHECK_CMD_LEN(3);
>>       if ((cmd[2] >= MAX_SENSORS) ||
>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> @@ -1587,7 +1576,6 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>>       IPMISensor *sens;
>>
>>
>> -    IPMI_CHECK_CMD_LEN(5);
>>       if ((cmd[2] >= MAX_SENSORS) ||
>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> @@ -1606,7 +1594,6 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>       IPMISensor *sens;
>>
>>
>> -    IPMI_CHECK_CMD_LEN(3);
>>       if ((cmd[2] >= MAX_SENSORS) ||
>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>> @@ -1619,10 +1606,10 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>
>>
>>   static const IPMICmdHandler chassis_cmds[] = {
>> -    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
>> -    [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
>> -    [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
>> -    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
>> +    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
>> +    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
>> +    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
>> +    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
>>   };
>>   static const IPMINetfn chassis_netfn = {
>>       .cmd_nums = ARRAY_SIZE(chassis_cmds),
>> @@ -1630,13 +1617,13 @@ static const IPMINetfn chassis_netfn = {
>>   };
>>
>>   static const IPMICmdHandler sensor_event_cmds[] = {
>> -    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
>> -    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
>> -    [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
>> -    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
>> -    [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
>> -    [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
>> -    [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
>> +    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
>> +    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
>> +    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
>> +    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
>> +    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
>> +    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
>> +    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
>>   };
>>   static const IPMINetfn sensor_event_netfn = {
>>       .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
>> @@ -1644,22 +1631,22 @@ static const IPMINetfn sensor_event_netfn = {
>>   };
>>
>>   static const IPMICmdHandler app_cmds[] = {
>> -    [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
>> -    [IPMI_CMD_COLD_RESET] = cold_reset,
>> -    [IPMI_CMD_WARM_RESET] = warm_reset,
>> -    [IPMI_CMD_SET_ACPI_POWER_STATE] = set_acpi_power_state,
>> -    [IPMI_CMD_GET_ACPI_POWER_STATE] = get_acpi_power_state,
>> -    [IPMI_CMD_GET_DEVICE_GUID] = get_device_guid,
>> -    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
>> -    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
>> -    [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
>> -    [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
>> -    [IPMI_CMD_GET_MSG] = get_msg,
>> -    [IPMI_CMD_SEND_MSG] = send_msg,
>> -    [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
>> -    [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
>> -    [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
>> -    [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
>> +    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
>> +    [IPMI_CMD_COLD_RESET] = { cold_reset },
>> +    [IPMI_CMD_WARM_RESET] = { warm_reset },
>> +    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
>> +    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
>> +    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
>> +    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
>> +    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
>> +    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
>> +    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
>> +    [IPMI_CMD_GET_MSG] = { get_msg },
>> +    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
>> +    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
>> +    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
>> +    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
>> +    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
>>   };
>>   static const IPMINetfn app_netfn = {
>>       .cmd_nums = ARRAY_SIZE(app_cmds),
>> @@ -1667,18 +1654,18 @@ static const IPMINetfn app_netfn = {
>>   };
>>
>>   static const IPMICmdHandler storage_cmds[] = {
>> -    [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
>> -    [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
>> -    [IPMI_CMD_GET_SDR] = get_sdr,
>> -    [IPMI_CMD_ADD_SDR] = add_sdr,
>> -    [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
>> -    [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
>> -    [IPMI_CMD_RESERVE_SEL] = reserve_sel,
>> -    [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
>> -    [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
>> -    [IPMI_CMD_CLEAR_SEL] = clear_sel,
>> -    [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
>> -    [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
>> +    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
>> +    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
>> +    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
>> +    [IPMI_CMD_ADD_SDR] = { add_sdr },
>> +    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
>> +    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
>> +    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
>> +    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
>> +    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
>> +    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
>> +    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
>> +    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
>>   };
>>
>>   static const IPMINetfn storage_netfn = {
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro
  2016-03-07 10:40     ` Cédric Le Goater
@ 2016-03-08 17:06       ` Cédric Le Goater
  2016-03-09  4:07         ` Corey Minyard
  0 siblings, 1 reply; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-08 17:06 UTC (permalink / raw)
  To: minyard, Corey Minyard; +Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/07/2016 11:40 AM, Cédric Le Goater wrote:
> On 03/05/2016 12:41 PM, Corey Minyard wrote:
>> On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
>>> Most IPMI command handlers in the BMC simulator start with a call to
>>> the macro IPMI_CHECK_CMD_LEN() which verifies that a minimal number of
>>> arguments expected by the command are indeed available. To achieve
>>> this task, the macro implicitly uses local variables which is
>>> misleading in the code.
>>>
>>> This patch adds a 'cmd_len_min' attribute to the struct IPMICmdHandler
>>> defining the minimal number of arguments expected by the command and
>>> moves this check in the global command handler ipmi_sim_handle_command().
>>
>> This is much better.  One style comment inline...
>>
>> Acked-by: Corey Minyard <cminyard@mvista.com>
>>
>>> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
>>> ---
>>>   hw/ipmi/ipmi_bmc_sim.c | 137 ++++++++++++++++++++++---------------------------
>>>   1 file changed, 62 insertions(+), 75 deletions(-)
>>>
>>> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
>>> index 51d234aa1bf2..30b9fb48ea2d 100644
>>> --- a/hw/ipmi/ipmi_bmc_sim.c
>>> +++ b/hw/ipmi/ipmi_bmc_sim.c
>>> @@ -155,10 +155,15 @@ typedef struct IPMISensor {
>>>   typedef struct IPMIBmcSim IPMIBmcSim;
>>>
>>>   #define MAX_NETFNS 64
>>> -typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
>>> -                               uint8_t *cmd, unsigned int cmd_len,
>>> -                               uint8_t *rsp, unsigned int *rsp_len,
>>> -                               unsigned int max_rsp_len);
>>> +
>>> +typedef struct IPMICmdHandler {
>>> +    void (*cmd_handler)(IPMIBmcSim *s,
>>> +                        uint8_t *cmd, unsigned int cmd_len,
>>> +                        uint8_t *rsp, unsigned int *rsp_len,
>>> +                        unsigned int max_rsp_len);
>>> +    unsigned int cmd_len_min;
>>> +} IPMICmdHandler;
>>> +
>>>   typedef struct IPMINetfn {
>>>       unsigned int cmd_nums;
>>>       const IPMICmdHandler *cmd_handlers;
>>> @@ -269,13 +274,6 @@ struct IPMIBmcSim {
>>>           rsp[(*rsp_len)++] = (b);                           \
>>>       } while (0)
>>>
>>> -/* Verify that the received command is a certain length. */
>>> -#define IPMI_CHECK_CMD_LEN(l) \
>>> -    if (cmd_len < l) {                                     \
>>> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;      \
>>> -        return; \
>>> -    }
>>> -
>>>   /* Check that the reservation in the command is valid. */
>>>   #define IPMI_CHECK_RESERVATION(off, r) \
>>>       do {                                                   \
>>> @@ -623,14 +621,19 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>>>
>>>       /* Odd netfns are not valid, make sure the command is registered */
>>>       if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>>> -                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>>> -                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
>>> +        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>>> +        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
>>>           rsp[2] = IPMI_CC_INVALID_CMD;
>>>           goto out;
>>
>> I'm not sure of the qemu style here, but the above change makes the code hard to read.
> 
> Cleary. I was lazy. I will try to clarify what this code does with a helper
> or some intermediate variables.

How's that  ? 

@@ -591,6 +589,7 @@ static void ipmi_sim_handle_command(IPMI
     unsigned int rsp_len_holder = 0;
     unsigned int *rsp_len = &rsp_len_holder;
     unsigned int max_rsp_len = sizeof(rsp);
+    const IPMICmdHandler *hdl;
 
     /* Set up the response, set the low bit of NETFN. */
     /* Note that max_rsp_len must be at least 3 */
@@ -623,14 +622,23 @@ static void ipmi_sim_handle_command(IPMI
 
     /* Odd netfns are not valid, make sure the command is registered */
     if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
-                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
-                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
+        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums)) {
         rsp[2] = IPMI_CC_INVALID_CMD;
         goto out;
     }
 
-    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
-                                                max_rsp_len);
+    hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]];
+    if (!hdl->cmd_handler) {
+        rsp[2] = IPMI_CC_INVALID_CMD;
+        goto out;
+    }
+
+    if (cmd_len < hdl->cmd_len_min) {
+        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
+        goto out;
+    }
+
+    hdl->cmd_handler(ibs, cmd, cmd_len, rsp, rsp_len, max_rsp_len);
 
  out:
     k->handle_rsp(s, msg_id, rsp, *rsp_len);



The function still fits in one emacs page, so I think we are fine.

Just waiting a bit for Marcel to chime in before sending a v3.

Thanks,
 
C.

 
>> The qemu style really seems to be to not have big if statements like
>> this, so maybe this crasy check should be moved to a separate function?
>>
>>>       }
>>>
>>> -    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
>>> -                                                max_rsp_len);
>>> +    if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
>>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>> +        goto out;
>>> +    }
>>> +
>>> +    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
>>> +                                                rsp, rsp_len, max_rsp_len);
>>>
>>>    out:
>>>       k->handle_rsp(s, msg_id, rsp, *rsp_len);
>>> @@ -737,7 +740,6 @@ static void chassis_control(IPMIBmcSim *ibs,
>>>       IPMIInterface *s = ibs->parent.intf;
>>>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>
>>> -    IPMI_CHECK_CMD_LEN(3);
>>>       switch (cmd[2] & 0xf) {
>>>       case 0: /* power down */
>>>           rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>>> @@ -838,7 +840,6 @@ static void set_acpi_power_state(IPMIBmcSim *ibs,
>>>                             uint8_t *rsp, unsigned int *rsp_len,
>>>                             unsigned int max_rsp_len)
>>>   {
>>> -    IPMI_CHECK_CMD_LEN(4);
>>>       ibs->acpi_power_state[0] = cmd[2];
>>>       ibs->acpi_power_state[1] = cmd[3];
>>>   }
>>> @@ -869,7 +870,6 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs,
>>>                                      uint8_t *rsp, unsigned int *rsp_len,
>>>                                      unsigned int max_rsp_len)
>>>   {
>>> -    IPMI_CHECK_CMD_LEN(3);
>>>       set_global_enables(ibs, cmd[2]);
>>>   }
>>>
>>> @@ -889,7 +889,6 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>>>       IPMIInterface *s = ibs->parent.intf;
>>>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>
>>> -    IPMI_CHECK_CMD_LEN(3);
>>>       ibs->msg_flags &= ~cmd[2];
>>>       k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
>>>   }
>>> @@ -976,15 +975,17 @@ static void send_msg(IPMIBmcSim *ibs,
>>>       uint8_t *buf;
>>>       uint8_t netfn, rqLun, rsLun, rqSeq;
>>>
>>> -    IPMI_CHECK_CMD_LEN(3);
>>> -
>>>       if (cmd[2] != 0) {
>>>           /* We only handle channel 0 with no options */
>>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>           return;
>>>       }
>>>
>>> -    IPMI_CHECK_CMD_LEN(10);
>>> +    if (cmd_len < 10) {
>>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>> +        return;
>>> +    }
>>> +
>>>       if (cmd[3] != 0x40) {
>>>           /* We only emulate a MC at address 0x40. */
>>>           rsp[2] = 0x83; /* NAK on write */
>>> @@ -1092,7 +1093,6 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>>       IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>       unsigned int val;
>>>
>>> -    IPMI_CHECK_CMD_LEN(8);
>>>       val = cmd[2] & 0x7; /* Validate use */
>>>       if (val == 0 || val > 5) {
>>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>> @@ -1217,7 +1217,6 @@ static void get_sdr(IPMIBmcSim *ibs,
>>>       uint16_t nextrec;
>>>       struct ipmi_sdr_header *sdrh;
>>>
>>> -    IPMI_CHECK_CMD_LEN(8);
>>>       if (cmd[6]) {
>>>           IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>>       }
>>> @@ -1271,7 +1270,6 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>>>                             uint8_t *rsp, unsigned int *rsp_len,
>>>                             unsigned int max_rsp_len)
>>>   {
>>> -    IPMI_CHECK_CMD_LEN(8);
>>>       IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>> @@ -1330,7 +1328,6 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>>>   {
>>>       unsigned int val;
>>>
>>> -    IPMI_CHECK_CMD_LEN(8);
>>>       if (cmd[6]) {
>>>           IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>>       }
>>> @@ -1375,7 +1372,6 @@ static void add_sel_entry(IPMIBmcSim *ibs,
>>>                             uint8_t *rsp, unsigned int *rsp_len,
>>>                             unsigned int max_rsp_len)
>>>   {
>>> -    IPMI_CHECK_CMD_LEN(18);
>>>       if (sel_add_event(ibs, cmd + 2)) {
>>>           rsp[2] = IPMI_CC_OUT_OF_SPACE;
>>>           return;
>>> @@ -1390,7 +1386,6 @@ static void clear_sel(IPMIBmcSim *ibs,
>>>                         uint8_t *rsp, unsigned int *rsp_len,
>>>                         unsigned int max_rsp_len)
>>>   {
>>> -    IPMI_CHECK_CMD_LEN(8);
>>>       IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>>       if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>>           rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>> @@ -1434,7 +1429,6 @@ static void set_sel_time(IPMIBmcSim *ibs,
>>>       uint32_t val;
>>>       struct ipmi_time now;
>>>
>>> -    IPMI_CHECK_CMD_LEN(6);
>>>       val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
>>>       ipmi_gettime(&now);
>>>       ibs->sel.time_offset = now.tv_sec - ((long) val);
>>> @@ -1447,7 +1441,6 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>>>   {
>>>       IPMISensor *sens;
>>>
>>> -    IPMI_CHECK_CMD_LEN(4);
>>>       if ((cmd[2] >= MAX_SENSORS) ||
>>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>> @@ -1499,7 +1492,6 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>>>   {
>>>       IPMISensor *sens;
>>>
>>> -    IPMI_CHECK_CMD_LEN(3);
>>>       if ((cmd[2] >= MAX_SENSORS) ||
>>>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>> @@ -1520,7 +1512,6 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>>>   {
>>>       IPMISensor *sens;
>>>
>>> -    IPMI_CHECK_CMD_LEN(4);
>>>       if ((cmd[2] >= MAX_SENSORS) ||
>>>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>> @@ -1542,7 +1533,6 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
>>>   {
>>>       IPMISensor *sens;
>>>
>>> -    IPMI_CHECK_CMD_LEN(3);
>>>       if ((cmd[2] >= MAX_SENSORS) ||
>>>           !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>> @@ -1564,7 +1554,6 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
>>>   {
>>>       IPMISensor *sens;
>>>
>>> -    IPMI_CHECK_CMD_LEN(3);
>>>       if ((cmd[2] >= MAX_SENSORS) ||
>>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>> @@ -1587,7 +1576,6 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>>>       IPMISensor *sens;
>>>
>>>
>>> -    IPMI_CHECK_CMD_LEN(5);
>>>       if ((cmd[2] >= MAX_SENSORS) ||
>>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>> @@ -1606,7 +1594,6 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>>       IPMISensor *sens;
>>>
>>>
>>> -    IPMI_CHECK_CMD_LEN(3);
>>>       if ((cmd[2] >= MAX_SENSORS) ||
>>>               !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>           rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>> @@ -1619,10 +1606,10 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>>
>>>
>>>   static const IPMICmdHandler chassis_cmds[] = {
>>> -    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
>>> -    [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
>>> -    [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
>>> -    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
>>> +    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
>>> +    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
>>> +    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
>>> +    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
>>>   };
>>>   static const IPMINetfn chassis_netfn = {
>>>       .cmd_nums = ARRAY_SIZE(chassis_cmds),
>>> @@ -1630,13 +1617,13 @@ static const IPMINetfn chassis_netfn = {
>>>   };
>>>
>>>   static const IPMICmdHandler sensor_event_cmds[] = {
>>> -    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
>>> -    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
>>> -    [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
>>> -    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
>>> -    [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
>>> -    [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
>>> -    [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
>>> +    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
>>> +    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
>>> +    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
>>> +    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
>>> +    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
>>> +    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
>>> +    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
>>>   };
>>>   static const IPMINetfn sensor_event_netfn = {
>>>       .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
>>> @@ -1644,22 +1631,22 @@ static const IPMINetfn sensor_event_netfn = {
>>>   };
>>>
>>>   static const IPMICmdHandler app_cmds[] = {
>>> -    [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
>>> -    [IPMI_CMD_COLD_RESET] = cold_reset,
>>> -    [IPMI_CMD_WARM_RESET] = warm_reset,
>>> -    [IPMI_CMD_SET_ACPI_POWER_STATE] = set_acpi_power_state,
>>> -    [IPMI_CMD_GET_ACPI_POWER_STATE] = get_acpi_power_state,
>>> -    [IPMI_CMD_GET_DEVICE_GUID] = get_device_guid,
>>> -    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
>>> -    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
>>> -    [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
>>> -    [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
>>> -    [IPMI_CMD_GET_MSG] = get_msg,
>>> -    [IPMI_CMD_SEND_MSG] = send_msg,
>>> -    [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
>>> -    [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
>>> -    [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
>>> -    [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
>>> +    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
>>> +    [IPMI_CMD_COLD_RESET] = { cold_reset },
>>> +    [IPMI_CMD_WARM_RESET] = { warm_reset },
>>> +    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
>>> +    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
>>> +    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
>>> +    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
>>> +    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
>>> +    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
>>> +    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
>>> +    [IPMI_CMD_GET_MSG] = { get_msg },
>>> +    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
>>> +    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
>>> +    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
>>> +    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
>>> +    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
>>>   };
>>>   static const IPMINetfn app_netfn = {
>>>       .cmd_nums = ARRAY_SIZE(app_cmds),
>>> @@ -1667,18 +1654,18 @@ static const IPMINetfn app_netfn = {
>>>   };
>>>
>>>   static const IPMICmdHandler storage_cmds[] = {
>>> -    [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
>>> -    [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
>>> -    [IPMI_CMD_GET_SDR] = get_sdr,
>>> -    [IPMI_CMD_ADD_SDR] = add_sdr,
>>> -    [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
>>> -    [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
>>> -    [IPMI_CMD_RESERVE_SEL] = reserve_sel,
>>> -    [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
>>> -    [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
>>> -    [IPMI_CMD_CLEAR_SEL] = clear_sel,
>>> -    [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
>>> -    [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
>>> +    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
>>> +    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
>>> +    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
>>> +    [IPMI_CMD_ADD_SDR] = { add_sdr },
>>> +    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
>>> +    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
>>> +    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
>>> +    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
>>> +    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
>>> +    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
>>> +    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
>>> +    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
>>>   };
>>>
>>>   static const IPMINetfn storage_netfn = {
>>
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro
  2016-03-08 17:06       ` Cédric Le Goater
@ 2016-03-09  4:07         ` Corey Minyard
  2016-03-09  8:52           ` Cédric Le Goater
  0 siblings, 1 reply; 23+ messages in thread
From: Corey Minyard @ 2016-03-09  4:07 UTC (permalink / raw)
  To: Cédric Le Goater, Corey Minyard
  Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/09/2016 12:06 AM, Cédric Le Goater wrote:
> On 03/07/2016 11:40 AM, Cédric Le Goater wrote:
>> On 03/05/2016 12:41 PM, Corey Minyard wrote:
>>> On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
>>>> Most IPMI command handlers in the BMC simulator start with a call to
>>>> the macro IPMI_CHECK_CMD_LEN() which verifies that a minimal number of
>>>> arguments expected by the command are indeed available. To achieve
>>>> this task, the macro implicitly uses local variables which is
>>>> misleading in the code.
>>>>
>>>> This patch adds a 'cmd_len_min' attribute to the struct IPMICmdHandler
>>>> defining the minimal number of arguments expected by the command and
>>>> moves this check in the global command handler ipmi_sim_handle_command().
>>> This is much better.  One style comment inline...
>>>
>>> Acked-by: Corey Minyard <cminyard@mvista.com>
>>>
>>>> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
>>>> ---
>>>>    hw/ipmi/ipmi_bmc_sim.c | 137 ++++++++++++++++++++++---------------------------
>>>>    1 file changed, 62 insertions(+), 75 deletions(-)
>>>>
>>>> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
>>>> index 51d234aa1bf2..30b9fb48ea2d 100644
>>>> --- a/hw/ipmi/ipmi_bmc_sim.c
>>>> +++ b/hw/ipmi/ipmi_bmc_sim.c
>>>> @@ -155,10 +155,15 @@ typedef struct IPMISensor {
>>>>    typedef struct IPMIBmcSim IPMIBmcSim;
>>>>
>>>>    #define MAX_NETFNS 64
>>>> -typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
>>>> -                               uint8_t *cmd, unsigned int cmd_len,
>>>> -                               uint8_t *rsp, unsigned int *rsp_len,
>>>> -                               unsigned int max_rsp_len);
>>>> +
>>>> +typedef struct IPMICmdHandler {
>>>> +    void (*cmd_handler)(IPMIBmcSim *s,
>>>> +                        uint8_t *cmd, unsigned int cmd_len,
>>>> +                        uint8_t *rsp, unsigned int *rsp_len,
>>>> +                        unsigned int max_rsp_len);
>>>> +    unsigned int cmd_len_min;
>>>> +} IPMICmdHandler;
>>>> +
>>>>    typedef struct IPMINetfn {
>>>>        unsigned int cmd_nums;
>>>>        const IPMICmdHandler *cmd_handlers;
>>>> @@ -269,13 +274,6 @@ struct IPMIBmcSim {
>>>>            rsp[(*rsp_len)++] = (b);                           \
>>>>        } while (0)
>>>>
>>>> -/* Verify that the received command is a certain length. */
>>>> -#define IPMI_CHECK_CMD_LEN(l) \
>>>> -    if (cmd_len < l) {                                     \
>>>> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;      \
>>>> -        return; \
>>>> -    }
>>>> -
>>>>    /* Check that the reservation in the command is valid. */
>>>>    #define IPMI_CHECK_RESERVATION(off, r) \
>>>>        do {                                                   \
>>>> @@ -623,14 +621,19 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>>>>
>>>>        /* Odd netfns are not valid, make sure the command is registered */
>>>>        if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>>>> -                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>>>> -                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
>>>> +        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>>>> +        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
>>>>            rsp[2] = IPMI_CC_INVALID_CMD;
>>>>            goto out;
>>> I'm not sure of the qemu style here, but the above change makes the code hard to read.
>> Cleary. I was lazy. I will try to clarify what this code does with a helper
>> or some intermediate variables.
> How's that  ?
>
> @@ -591,6 +589,7 @@ static void ipmi_sim_handle_command(IPMI
>       unsigned int rsp_len_holder = 0;
>       unsigned int *rsp_len = &rsp_len_holder;
>       unsigned int max_rsp_len = sizeof(rsp);
> +    const IPMICmdHandler *hdl;
>   
>       /* Set up the response, set the low bit of NETFN. */
>       /* Note that max_rsp_len must be at least 3 */
> @@ -623,14 +622,23 @@ static void ipmi_sim_handle_command(IPMI
>   
>       /* Odd netfns are not valid, make sure the command is registered */
>       if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
> -                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
> -                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
> +        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums)) {
>           rsp[2] = IPMI_CC_INVALID_CMD;
>           goto out;
>       }
>   

This cleans things up a bit.  The curse of a 4 character indent is that
the line that follows a multi-line if statement is at the same indent as
the lines in the if statement, so it's hard to tell where the if statement
ends and where the code in the if statement begins.  This is not bad,
but if you have if statements like the gcc compiler (at least how the
gcc compiler used to be, haven't looked at it recently) it makes your
head hurt.

The Linux indent rule for this is that you indent the second and later
lines of an if statement way over, or you break it up.

I looked through a few of the major qemu files, and I couldn't find
a multi-line if statement, so it's hard to say.  That is perhaps telling :).

-corey

> -    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
> -                                                max_rsp_len);
> +    hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]];
> +    if (!hdl->cmd_handler) {
> +        rsp[2] = IPMI_CC_INVALID_CMD;
> +        goto out;
> +    }
> +
> +    if (cmd_len < hdl->cmd_len_min) {
> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
> +        goto out;
> +    }
> +
> +    hdl->cmd_handler(ibs, cmd, cmd_len, rsp, rsp_len, max_rsp_len);
>   
>    out:
>       k->handle_rsp(s, msg_id, rsp, *rsp_len);
>
>
>
> The function still fits in one emacs page, so I think we are fine.
>
> Just waiting a bit for Marcel to chime in before sending a v3.
>
> Thanks,
>   
> C.
>
>   
>>> The qemu style really seems to be to not have big if statements like
>>> this, so maybe this crasy check should be moved to a separate function?
>>>
>>>>        }
>>>>
>>>> -    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
>>>> -                                                max_rsp_len);
>>>> +    if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
>>>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>>> +        goto out;
>>>> +    }
>>>> +
>>>> +    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
>>>> +                                                rsp, rsp_len, max_rsp_len);
>>>>
>>>>     out:
>>>>        k->handle_rsp(s, msg_id, rsp, *rsp_len);
>>>> @@ -737,7 +740,6 @@ static void chassis_control(IPMIBmcSim *ibs,
>>>>        IPMIInterface *s = ibs->parent.intf;
>>>>        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>        switch (cmd[2] & 0xf) {
>>>>        case 0: /* power down */
>>>>            rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>>>> @@ -838,7 +840,6 @@ static void set_acpi_power_state(IPMIBmcSim *ibs,
>>>>                              uint8_t *rsp, unsigned int *rsp_len,
>>>>                              unsigned int max_rsp_len)
>>>>    {
>>>> -    IPMI_CHECK_CMD_LEN(4);
>>>>        ibs->acpi_power_state[0] = cmd[2];
>>>>        ibs->acpi_power_state[1] = cmd[3];
>>>>    }
>>>> @@ -869,7 +870,6 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs,
>>>>                                       uint8_t *rsp, unsigned int *rsp_len,
>>>>                                       unsigned int max_rsp_len)
>>>>    {
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>        set_global_enables(ibs, cmd[2]);
>>>>    }
>>>>
>>>> @@ -889,7 +889,6 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>>>>        IPMIInterface *s = ibs->parent.intf;
>>>>        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>        ibs->msg_flags &= ~cmd[2];
>>>>        k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
>>>>    }
>>>> @@ -976,15 +975,17 @@ static void send_msg(IPMIBmcSim *ibs,
>>>>        uint8_t *buf;
>>>>        uint8_t netfn, rqLun, rsLun, rqSeq;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>> -
>>>>        if (cmd[2] != 0) {
>>>>            /* We only handle channel 0 with no options */
>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>>            return;
>>>>        }
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(10);
>>>> +    if (cmd_len < 10) {
>>>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>>> +        return;
>>>> +    }
>>>> +
>>>>        if (cmd[3] != 0x40) {
>>>>            /* We only emulate a MC at address 0x40. */
>>>>            rsp[2] = 0x83; /* NAK on write */
>>>> @@ -1092,7 +1093,6 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>>>        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>>        unsigned int val;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>        val = cmd[2] & 0x7; /* Validate use */
>>>>        if (val == 0 || val > 5) {
>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>> @@ -1217,7 +1217,6 @@ static void get_sdr(IPMIBmcSim *ibs,
>>>>        uint16_t nextrec;
>>>>        struct ipmi_sdr_header *sdrh;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>        if (cmd[6]) {
>>>>            IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>>>        }
>>>> @@ -1271,7 +1270,6 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>>>>                              uint8_t *rsp, unsigned int *rsp_len,
>>>>                              unsigned int max_rsp_len)
>>>>    {
>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>        IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>>>        if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>> @@ -1330,7 +1328,6 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>>>>    {
>>>>        unsigned int val;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>        if (cmd[6]) {
>>>>            IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>>>        }
>>>> @@ -1375,7 +1372,6 @@ static void add_sel_entry(IPMIBmcSim *ibs,
>>>>                              uint8_t *rsp, unsigned int *rsp_len,
>>>>                              unsigned int max_rsp_len)
>>>>    {
>>>> -    IPMI_CHECK_CMD_LEN(18);
>>>>        if (sel_add_event(ibs, cmd + 2)) {
>>>>            rsp[2] = IPMI_CC_OUT_OF_SPACE;
>>>>            return;
>>>> @@ -1390,7 +1386,6 @@ static void clear_sel(IPMIBmcSim *ibs,
>>>>                          uint8_t *rsp, unsigned int *rsp_len,
>>>>                          unsigned int max_rsp_len)
>>>>    {
>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>        IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>>>        if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>> @@ -1434,7 +1429,6 @@ static void set_sel_time(IPMIBmcSim *ibs,
>>>>        uint32_t val;
>>>>        struct ipmi_time now;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(6);
>>>>        val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
>>>>        ipmi_gettime(&now);
>>>>        ibs->sel.time_offset = now.tv_sec - ((long) val);
>>>> @@ -1447,7 +1441,6 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>>>>    {
>>>>        IPMISensor *sens;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(4);
>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>> @@ -1499,7 +1492,6 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>>>>    {
>>>>        IPMISensor *sens;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>> @@ -1520,7 +1512,6 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>>>>    {
>>>>        IPMISensor *sens;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(4);
>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>> @@ -1542,7 +1533,6 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
>>>>    {
>>>>        IPMISensor *sens;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>> @@ -1564,7 +1554,6 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
>>>>    {
>>>>        IPMISensor *sens;
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>> @@ -1587,7 +1576,6 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>>>>        IPMISensor *sens;
>>>>
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(5);
>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>> @@ -1606,7 +1594,6 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>>>        IPMISensor *sens;
>>>>
>>>>
>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>> @@ -1619,10 +1606,10 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>>>
>>>>
>>>>    static const IPMICmdHandler chassis_cmds[] = {
>>>> -    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
>>>> -    [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
>>>> -    [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
>>>> -    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
>>>> +    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
>>>> +    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
>>>> +    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
>>>> +    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
>>>>    };
>>>>    static const IPMINetfn chassis_netfn = {
>>>>        .cmd_nums = ARRAY_SIZE(chassis_cmds),
>>>> @@ -1630,13 +1617,13 @@ static const IPMINetfn chassis_netfn = {
>>>>    };
>>>>
>>>>    static const IPMICmdHandler sensor_event_cmds[] = {
>>>> -    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
>>>> -    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
>>>> -    [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
>>>> -    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
>>>> -    [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
>>>> -    [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
>>>> -    [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
>>>> +    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
>>>> +    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
>>>> +    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
>>>> +    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
>>>> +    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
>>>> +    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
>>>> +    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
>>>>    };
>>>>    static const IPMINetfn sensor_event_netfn = {
>>>>        .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
>>>> @@ -1644,22 +1631,22 @@ static const IPMINetfn sensor_event_netfn = {
>>>>    };
>>>>
>>>>    static const IPMICmdHandler app_cmds[] = {
>>>> -    [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
>>>> -    [IPMI_CMD_COLD_RESET] = cold_reset,
>>>> -    [IPMI_CMD_WARM_RESET] = warm_reset,
>>>> -    [IPMI_CMD_SET_ACPI_POWER_STATE] = set_acpi_power_state,
>>>> -    [IPMI_CMD_GET_ACPI_POWER_STATE] = get_acpi_power_state,
>>>> -    [IPMI_CMD_GET_DEVICE_GUID] = get_device_guid,
>>>> -    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
>>>> -    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
>>>> -    [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
>>>> -    [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
>>>> -    [IPMI_CMD_GET_MSG] = get_msg,
>>>> -    [IPMI_CMD_SEND_MSG] = send_msg,
>>>> -    [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
>>>> -    [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
>>>> -    [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
>>>> -    [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
>>>> +    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
>>>> +    [IPMI_CMD_COLD_RESET] = { cold_reset },
>>>> +    [IPMI_CMD_WARM_RESET] = { warm_reset },
>>>> +    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
>>>> +    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
>>>> +    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
>>>> +    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
>>>> +    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
>>>> +    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
>>>> +    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
>>>> +    [IPMI_CMD_GET_MSG] = { get_msg },
>>>> +    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
>>>> +    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
>>>> +    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
>>>> +    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
>>>> +    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
>>>>    };
>>>>    static const IPMINetfn app_netfn = {
>>>>        .cmd_nums = ARRAY_SIZE(app_cmds),
>>>> @@ -1667,18 +1654,18 @@ static const IPMINetfn app_netfn = {
>>>>    };
>>>>
>>>>    static const IPMICmdHandler storage_cmds[] = {
>>>> -    [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
>>>> -    [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
>>>> -    [IPMI_CMD_GET_SDR] = get_sdr,
>>>> -    [IPMI_CMD_ADD_SDR] = add_sdr,
>>>> -    [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
>>>> -    [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
>>>> -    [IPMI_CMD_RESERVE_SEL] = reserve_sel,
>>>> -    [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
>>>> -    [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
>>>> -    [IPMI_CMD_CLEAR_SEL] = clear_sel,
>>>> -    [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
>>>> -    [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
>>>> +    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
>>>> +    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
>>>> +    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
>>>> +    [IPMI_CMD_ADD_SDR] = { add_sdr },
>>>> +    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
>>>> +    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
>>>> +    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
>>>> +    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
>>>> +    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
>>>> +    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
>>>> +    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
>>>> +    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
>>>>    };
>>>>
>>>>    static const IPMINetfn storage_netfn = {

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro
  2016-03-09  4:07         ` Corey Minyard
@ 2016-03-09  8:52           ` Cédric Le Goater
  0 siblings, 0 replies; 23+ messages in thread
From: Cédric Le Goater @ 2016-03-09  8:52 UTC (permalink / raw)
  To: minyard, Corey Minyard; +Cc: Marcel Apfelbaum, qemu-devel, Michael S. Tsirkin

On 03/09/2016 05:07 AM, Corey Minyard wrote:
> On 03/09/2016 12:06 AM, Cédric Le Goater wrote:
>> On 03/07/2016 11:40 AM, Cédric Le Goater wrote:
>>> On 03/05/2016 12:41 PM, Corey Minyard wrote:
>>>> On 03/02/2016 04:14 AM, Cédric Le Goater wrote:
>>>>> Most IPMI command handlers in the BMC simulator start with a call to
>>>>> the macro IPMI_CHECK_CMD_LEN() which verifies that a minimal number of
>>>>> arguments expected by the command are indeed available. To achieve
>>>>> this task, the macro implicitly uses local variables which is
>>>>> misleading in the code.
>>>>>
>>>>> This patch adds a 'cmd_len_min' attribute to the struct IPMICmdHandler
>>>>> defining the minimal number of arguments expected by the command and
>>>>> moves this check in the global command handler ipmi_sim_handle_command().
>>>> This is much better.  One style comment inline...
>>>>
>>>> Acked-by: Corey Minyard <cminyard@mvista.com>
>>>>
>>>>> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
>>>>> ---
>>>>>    hw/ipmi/ipmi_bmc_sim.c | 137 ++++++++++++++++++++++---------------------------
>>>>>    1 file changed, 62 insertions(+), 75 deletions(-)
>>>>>
>>>>> diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
>>>>> index 51d234aa1bf2..30b9fb48ea2d 100644
>>>>> --- a/hw/ipmi/ipmi_bmc_sim.c
>>>>> +++ b/hw/ipmi/ipmi_bmc_sim.c
>>>>> @@ -155,10 +155,15 @@ typedef struct IPMISensor {
>>>>>    typedef struct IPMIBmcSim IPMIBmcSim;
>>>>>
>>>>>    #define MAX_NETFNS 64
>>>>> -typedef void (*IPMICmdHandler)(IPMIBmcSim *s,
>>>>> -                               uint8_t *cmd, unsigned int cmd_len,
>>>>> -                               uint8_t *rsp, unsigned int *rsp_len,
>>>>> -                               unsigned int max_rsp_len);
>>>>> +
>>>>> +typedef struct IPMICmdHandler {
>>>>> +    void (*cmd_handler)(IPMIBmcSim *s,
>>>>> +                        uint8_t *cmd, unsigned int cmd_len,
>>>>> +                        uint8_t *rsp, unsigned int *rsp_len,
>>>>> +                        unsigned int max_rsp_len);
>>>>> +    unsigned int cmd_len_min;
>>>>> +} IPMICmdHandler;
>>>>> +
>>>>>    typedef struct IPMINetfn {
>>>>>        unsigned int cmd_nums;
>>>>>        const IPMICmdHandler *cmd_handlers;
>>>>> @@ -269,13 +274,6 @@ struct IPMIBmcSim {
>>>>>            rsp[(*rsp_len)++] = (b);                           \
>>>>>        } while (0)
>>>>>
>>>>> -/* Verify that the received command is a certain length. */
>>>>> -#define IPMI_CHECK_CMD_LEN(l) \
>>>>> -    if (cmd_len < l) {                                     \
>>>>> -        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;      \
>>>>> -        return; \
>>>>> -    }
>>>>> -
>>>>>    /* Check that the reservation in the command is valid. */
>>>>>    #define IPMI_CHECK_RESERVATION(off, r) \
>>>>>        do {                                                   \
>>>>> @@ -623,14 +621,19 @@ static void ipmi_sim_handle_command(IPMIBmc *b,
>>>>>
>>>>>        /* Odd netfns are not valid, make sure the command is registered */
>>>>>        if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>>>>> -                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>>>>> -                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
>>>>> +        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>>>>> +        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler)) {
>>>>>            rsp[2] = IPMI_CC_INVALID_CMD;
>>>>>            goto out;
>>>> I'm not sure of the qemu style here, but the above change makes the code hard to read.
>>> Cleary. I was lazy. I will try to clarify what this code does with a helper
>>> or some intermediate variables.
>> How's that  ?
>>
>> @@ -591,6 +589,7 @@ static void ipmi_sim_handle_command(IPMI
>>       unsigned int rsp_len_holder = 0;
>>       unsigned int *rsp_len = &rsp_len_holder;
>>       unsigned int max_rsp_len = sizeof(rsp);
>> +    const IPMICmdHandler *hdl;
>>         /* Set up the response, set the low bit of NETFN. */
>>       /* Note that max_rsp_len must be at least 3 */
>> @@ -623,14 +622,23 @@ static void ipmi_sim_handle_command(IPMI
>>         /* Odd netfns are not valid, make sure the command is registered */
>>       if ((netfn & 1) || !ibs->netfns[netfn / 2] ||
>> -                        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums) ||
>> -                        (!ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]])) {
>> +        (cmd[1] >= ibs->netfns[netfn / 2]->cmd_nums)) {
>>           rsp[2] = IPMI_CC_INVALID_CMD;
>>           goto out;
>>       }
>>   
> 
> This cleans things up a bit.  The curse of a 4 character indent is that
> the line that follows a multi-line if statement is at the same indent as
> the lines in the if statement, so it's hard to tell where the if statement
> ends and where the code in the if statement begins.  This is not bad,
> but if you have if statements like the gcc compiler (at least how the
> gcc compiler used to be, haven't looked at it recently) it makes your
> head hurt.
> 
> The Linux indent rule for this is that you indent the second and later
> lines of an if statement way over, or you break it up.

yeah and in that case, an extra routine would be better. I'll do what you 
first proposed. A check on netfn is also missing.

C.   
 
> I looked through a few of the major qemu files, and I couldn't find
> a multi-line if statement, so it's hard to say.  That is perhaps telling :).
>
> -corey
> 
>> -    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
>> -                                                max_rsp_len);
>> +    hdl = &ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]];
>> +    if (!hdl->cmd_handler) {
>> +        rsp[2] = IPMI_CC_INVALID_CMD;
>> +        goto out;
>> +    }
>> +
>> +    if (cmd_len < hdl->cmd_len_min) {
>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>> +        goto out;
>> +    }
>> +
>> +    hdl->cmd_handler(ibs, cmd, cmd_len, rsp, rsp_len, max_rsp_len);
>>      out:
>>       k->handle_rsp(s, msg_id, rsp, *rsp_len);
>>
>>
>>
>> The function still fits in one emacs page, so I think we are fine.
>>
>> Just waiting a bit for Marcel to chime in before sending a v3.
>>
>> Thanks,
>>   C.
>>
>>  
>>>> The qemu style really seems to be to not have big if statements like
>>>> this, so maybe this crasy check should be moved to a separate function?
>>>>
>>>>>        }
>>>>>
>>>>> -    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]](ibs, cmd, cmd_len, rsp, rsp_len,
>>>>> -                                                max_rsp_len);
>>>>> +    if (cmd_len < ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_len_min) {
>>>>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>>>> +        goto out;
>>>>> +    }
>>>>> +
>>>>> +    ibs->netfns[netfn / 2]->cmd_handlers[cmd[1]].cmd_handler(ibs, cmd, cmd_len,
>>>>> +                                                rsp, rsp_len, max_rsp_len);
>>>>>
>>>>>     out:
>>>>>        k->handle_rsp(s, msg_id, rsp, *rsp_len);
>>>>> @@ -737,7 +740,6 @@ static void chassis_control(IPMIBmcSim *ibs,
>>>>>        IPMIInterface *s = ibs->parent.intf;
>>>>>        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>>        switch (cmd[2] & 0xf) {
>>>>>        case 0: /* power down */
>>>>>            rsp[2] = k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0);
>>>>> @@ -838,7 +840,6 @@ static void set_acpi_power_state(IPMIBmcSim *ibs,
>>>>>                              uint8_t *rsp, unsigned int *rsp_len,
>>>>>                              unsigned int max_rsp_len)
>>>>>    {
>>>>> -    IPMI_CHECK_CMD_LEN(4);
>>>>>        ibs->acpi_power_state[0] = cmd[2];
>>>>>        ibs->acpi_power_state[1] = cmd[3];
>>>>>    }
>>>>> @@ -869,7 +870,6 @@ static void set_bmc_global_enables(IPMIBmcSim *ibs,
>>>>>                                       uint8_t *rsp, unsigned int *rsp_len,
>>>>>                                       unsigned int max_rsp_len)
>>>>>    {
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>>        set_global_enables(ibs, cmd[2]);
>>>>>    }
>>>>>
>>>>> @@ -889,7 +889,6 @@ static void clr_msg_flags(IPMIBmcSim *ibs,
>>>>>        IPMIInterface *s = ibs->parent.intf;
>>>>>        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>>        ibs->msg_flags &= ~cmd[2];
>>>>>        k->set_atn(s, attn_set(ibs), attn_irq_enabled(ibs));
>>>>>    }
>>>>> @@ -976,15 +975,17 @@ static void send_msg(IPMIBmcSim *ibs,
>>>>>        uint8_t *buf;
>>>>>        uint8_t netfn, rqLun, rsLun, rqSeq;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>> -
>>>>>        if (cmd[2] != 0) {
>>>>>            /* We only handle channel 0 with no options */
>>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>>>            return;
>>>>>        }
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(10);
>>>>> +    if (cmd_len < 10) {
>>>>> +        rsp[2] = IPMI_CC_REQUEST_DATA_LENGTH_INVALID;
>>>>> +        return;
>>>>> +    }
>>>>> +
>>>>>        if (cmd[3] != 0x40) {
>>>>>            /* We only emulate a MC at address 0x40. */
>>>>>            rsp[2] = 0x83; /* NAK on write */
>>>>> @@ -1092,7 +1093,6 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
>>>>>        IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>>>>>        unsigned int val;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>>        val = cmd[2] & 0x7; /* Validate use */
>>>>>        if (val == 0 || val > 5) {
>>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>>> @@ -1217,7 +1217,6 @@ static void get_sdr(IPMIBmcSim *ibs,
>>>>>        uint16_t nextrec;
>>>>>        struct ipmi_sdr_header *sdrh;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>>        if (cmd[6]) {
>>>>>            IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>>>>        }
>>>>> @@ -1271,7 +1270,6 @@ static void clear_sdr_rep(IPMIBmcSim *ibs,
>>>>>                              uint8_t *rsp, unsigned int *rsp_len,
>>>>>                              unsigned int max_rsp_len)
>>>>>    {
>>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>>        IPMI_CHECK_RESERVATION(2, ibs->sdr.reservation);
>>>>>        if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>>> @@ -1330,7 +1328,6 @@ static void get_sel_entry(IPMIBmcSim *ibs,
>>>>>    {
>>>>>        unsigned int val;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>>        if (cmd[6]) {
>>>>>            IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>>>>        }
>>>>> @@ -1375,7 +1372,6 @@ static void add_sel_entry(IPMIBmcSim *ibs,
>>>>>                              uint8_t *rsp, unsigned int *rsp_len,
>>>>>                              unsigned int max_rsp_len)
>>>>>    {
>>>>> -    IPMI_CHECK_CMD_LEN(18);
>>>>>        if (sel_add_event(ibs, cmd + 2)) {
>>>>>            rsp[2] = IPMI_CC_OUT_OF_SPACE;
>>>>>            return;
>>>>> @@ -1390,7 +1386,6 @@ static void clear_sel(IPMIBmcSim *ibs,
>>>>>                          uint8_t *rsp, unsigned int *rsp_len,
>>>>>                          unsigned int max_rsp_len)
>>>>>    {
>>>>> -    IPMI_CHECK_CMD_LEN(8);
>>>>>        IPMI_CHECK_RESERVATION(2, ibs->sel.reservation);
>>>>>        if (cmd[4] != 'C' || cmd[5] != 'L' || cmd[6] != 'R') {
>>>>>            rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
>>>>> @@ -1434,7 +1429,6 @@ static void set_sel_time(IPMIBmcSim *ibs,
>>>>>        uint32_t val;
>>>>>        struct ipmi_time now;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(6);
>>>>>        val = cmd[2] | (cmd[3] << 8) | (cmd[4] << 16) | (cmd[5] << 24);
>>>>>        ipmi_gettime(&now);
>>>>>        ibs->sel.time_offset = now.tv_sec - ((long) val);
>>>>> @@ -1447,7 +1441,6 @@ static void set_sensor_evt_enable(IPMIBmcSim *ibs,
>>>>>    {
>>>>>        IPMISensor *sens;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(4);
>>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>>> @@ -1499,7 +1492,6 @@ static void get_sensor_evt_enable(IPMIBmcSim *ibs,
>>>>>    {
>>>>>        IPMISensor *sens;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>>            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>>> @@ -1520,7 +1512,6 @@ static void rearm_sensor_evts(IPMIBmcSim *ibs,
>>>>>    {
>>>>>        IPMISensor *sens;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(4);
>>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>>            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>>> @@ -1542,7 +1533,6 @@ static void get_sensor_evt_status(IPMIBmcSim *ibs,
>>>>>    {
>>>>>        IPMISensor *sens;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>>            !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>>> @@ -1564,7 +1554,6 @@ static void get_sensor_reading(IPMIBmcSim *ibs,
>>>>>    {
>>>>>        IPMISensor *sens;
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>>> @@ -1587,7 +1576,6 @@ static void set_sensor_type(IPMIBmcSim *ibs,
>>>>>        IPMISensor *sens;
>>>>>
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(5);
>>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>>> @@ -1606,7 +1594,6 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>>>>        IPMISensor *sens;
>>>>>
>>>>>
>>>>> -    IPMI_CHECK_CMD_LEN(3);
>>>>>        if ((cmd[2] >= MAX_SENSORS) ||
>>>>>                !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
>>>>>            rsp[2] = IPMI_CC_REQ_ENTRY_NOT_PRESENT;
>>>>> @@ -1619,10 +1606,10 @@ static void get_sensor_type(IPMIBmcSim *ibs,
>>>>>
>>>>>
>>>>>    static const IPMICmdHandler chassis_cmds[] = {
>>>>> -    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = chassis_capabilities,
>>>>> -    [IPMI_CMD_GET_CHASSIS_STATUS] = chassis_status,
>>>>> -    [IPMI_CMD_CHASSIS_CONTROL] = chassis_control,
>>>>> -    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = chassis_get_sys_restart_cause
>>>>> +    [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
>>>>> +    [IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
>>>>> +    [IPMI_CMD_CHASSIS_CONTROL] = { chassis_control, 3 },
>>>>> +    [IPMI_CMD_GET_SYS_RESTART_CAUSE] = { chassis_get_sys_restart_cause }
>>>>>    };
>>>>>    static const IPMINetfn chassis_netfn = {
>>>>>        .cmd_nums = ARRAY_SIZE(chassis_cmds),
>>>>> @@ -1630,13 +1617,13 @@ static const IPMINetfn chassis_netfn = {
>>>>>    };
>>>>>
>>>>>    static const IPMICmdHandler sensor_event_cmds[] = {
>>>>> -    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = set_sensor_evt_enable,
>>>>> -    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = get_sensor_evt_enable,
>>>>> -    [IPMI_CMD_REARM_SENSOR_EVTS] = rearm_sensor_evts,
>>>>> -    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = get_sensor_evt_status,
>>>>> -    [IPMI_CMD_GET_SENSOR_READING] = get_sensor_reading,
>>>>> -    [IPMI_CMD_SET_SENSOR_TYPE] = set_sensor_type,
>>>>> -    [IPMI_CMD_GET_SENSOR_TYPE] = get_sensor_type,
>>>>> +    [IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
>>>>> +    [IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
>>>>> +    [IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
>>>>> +    [IPMI_CMD_GET_SENSOR_EVT_STATUS] = { get_sensor_evt_status, 3 },
>>>>> +    [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
>>>>> +    [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
>>>>> +    [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
>>>>>    };
>>>>>    static const IPMINetfn sensor_event_netfn = {
>>>>>        .cmd_nums = ARRAY_SIZE(sensor_event_cmds),
>>>>> @@ -1644,22 +1631,22 @@ static const IPMINetfn sensor_event_netfn = {
>>>>>    };
>>>>>
>>>>>    static const IPMICmdHandler app_cmds[] = {
>>>>> -    [IPMI_CMD_GET_DEVICE_ID] = get_device_id,
>>>>> -    [IPMI_CMD_COLD_RESET] = cold_reset,
>>>>> -    [IPMI_CMD_WARM_RESET] = warm_reset,
>>>>> -    [IPMI_CMD_SET_ACPI_POWER_STATE] = set_acpi_power_state,
>>>>> -    [IPMI_CMD_GET_ACPI_POWER_STATE] = get_acpi_power_state,
>>>>> -    [IPMI_CMD_GET_DEVICE_GUID] = get_device_guid,
>>>>> -    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = set_bmc_global_enables,
>>>>> -    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = get_bmc_global_enables,
>>>>> -    [IPMI_CMD_CLR_MSG_FLAGS] = clr_msg_flags,
>>>>> -    [IPMI_CMD_GET_MSG_FLAGS] = get_msg_flags,
>>>>> -    [IPMI_CMD_GET_MSG] = get_msg,
>>>>> -    [IPMI_CMD_SEND_MSG] = send_msg,
>>>>> -    [IPMI_CMD_READ_EVT_MSG_BUF] = read_evt_msg_buf,
>>>>> -    [IPMI_CMD_RESET_WATCHDOG_TIMER] = reset_watchdog_timer,
>>>>> -    [IPMI_CMD_SET_WATCHDOG_TIMER] = set_watchdog_timer,
>>>>> -    [IPMI_CMD_GET_WATCHDOG_TIMER] = get_watchdog_timer,
>>>>> +    [IPMI_CMD_GET_DEVICE_ID] = { get_device_id },
>>>>> +    [IPMI_CMD_COLD_RESET] = { cold_reset },
>>>>> +    [IPMI_CMD_WARM_RESET] = { warm_reset },
>>>>> +    [IPMI_CMD_SET_ACPI_POWER_STATE] = { set_acpi_power_state, 4 },
>>>>> +    [IPMI_CMD_GET_ACPI_POWER_STATE] = { get_acpi_power_state },
>>>>> +    [IPMI_CMD_GET_DEVICE_GUID] = { get_device_guid },
>>>>> +    [IPMI_CMD_SET_BMC_GLOBAL_ENABLES] = { set_bmc_global_enables, 3 },
>>>>> +    [IPMI_CMD_GET_BMC_GLOBAL_ENABLES] = { get_bmc_global_enables },
>>>>> +    [IPMI_CMD_CLR_MSG_FLAGS] = { clr_msg_flags, 3 },
>>>>> +    [IPMI_CMD_GET_MSG_FLAGS] = { get_msg_flags },
>>>>> +    [IPMI_CMD_GET_MSG] = { get_msg },
>>>>> +    [IPMI_CMD_SEND_MSG] = { send_msg, 3 },
>>>>> +    [IPMI_CMD_READ_EVT_MSG_BUF] = { read_evt_msg_buf },
>>>>> +    [IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
>>>>> +    [IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
>>>>> +    [IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
>>>>>    };
>>>>>    static const IPMINetfn app_netfn = {
>>>>>        .cmd_nums = ARRAY_SIZE(app_cmds),
>>>>> @@ -1667,18 +1654,18 @@ static const IPMINetfn app_netfn = {
>>>>>    };
>>>>>
>>>>>    static const IPMICmdHandler storage_cmds[] = {
>>>>> -    [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
>>>>> -    [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
>>>>> -    [IPMI_CMD_GET_SDR] = get_sdr,
>>>>> -    [IPMI_CMD_ADD_SDR] = add_sdr,
>>>>> -    [IPMI_CMD_CLEAR_SDR_REP] = clear_sdr_rep,
>>>>> -    [IPMI_CMD_GET_SEL_INFO] = get_sel_info,
>>>>> -    [IPMI_CMD_RESERVE_SEL] = reserve_sel,
>>>>> -    [IPMI_CMD_GET_SEL_ENTRY] = get_sel_entry,
>>>>> -    [IPMI_CMD_ADD_SEL_ENTRY] = add_sel_entry,
>>>>> -    [IPMI_CMD_CLEAR_SEL] = clear_sel,
>>>>> -    [IPMI_CMD_GET_SEL_TIME] = get_sel_time,
>>>>> -    [IPMI_CMD_SET_SEL_TIME] = set_sel_time,
>>>>> +    [IPMI_CMD_GET_SDR_REP_INFO] = { get_sdr_rep_info },
>>>>> +    [IPMI_CMD_RESERVE_SDR_REP] = { reserve_sdr_rep },
>>>>> +    [IPMI_CMD_GET_SDR] = { get_sdr, 8 },
>>>>> +    [IPMI_CMD_ADD_SDR] = { add_sdr },
>>>>> +    [IPMI_CMD_CLEAR_SDR_REP] = { clear_sdr_rep, 8 },
>>>>> +    [IPMI_CMD_GET_SEL_INFO] = { get_sel_info },
>>>>> +    [IPMI_CMD_RESERVE_SEL] = { reserve_sel },
>>>>> +    [IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
>>>>> +    [IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
>>>>> +    [IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
>>>>> +    [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
>>>>> +    [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
>>>>>    };
>>>>>
>>>>>    static const IPMINetfn storage_netfn = {
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2016-03-09  8:52 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-02 10:14 [Qemu-devel] [PATCH v2 00/10] ipmi: a couple of enhancements to the BMC simulator (round 2) Cédric Le Goater
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 01/10] ipmi: remove IPMI_CHECK_CMD_LEN() macro Cédric Le Goater
2016-03-05 11:41   ` Corey Minyard
2016-03-07 10:40     ` Cédric Le Goater
2016-03-08 17:06       ` Cédric Le Goater
2016-03-09  4:07         ` Corey Minyard
2016-03-09  8:52           ` Cédric Le Goater
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 02/10] ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers Cédric Le Goater
2016-03-02 10:25   ` Michael S. Tsirkin
2016-03-02 17:53     ` Cédric Le Goater
2016-03-02 18:02       ` Michael S. Tsirkin
2016-03-02 18:08         ` Cédric Le Goater
2016-03-05 11:41   ` Corey Minyard
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 03/10] ipmi: remove IPMI_CHECK_RESERVATION() macro Cédric Le Goater
2016-03-02 15:40   ` Corey Minyard
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 04/10] ipmi: add rsp_buffer_set_error() helper Cédric Le Goater
2016-03-05 11:42   ` Corey Minyard
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 05/10] ipmi: add a realize function to the device class Cédric Le Goater
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 06/10] ipmi: use a function to initialize the SDR table Cédric Le Goater
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 07/10] ipmi: remove the need of an ending record in " Cédric Le Goater
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 08/10] ipmi: add some local variables in ipmi_sdr_init Cédric Le Goater
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 09/10] ipmi: use a file to load SDRs Cédric Le Goater
2016-03-02 10:14 ` [Qemu-devel] [PATCH v2 10/10] ipmi: provide support for FRUs Cédric Le Goater

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.