qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 4/8] ipmi: add FRU support


From: Corey Minyard
Subject: Re: [Qemu-devel] [PATCH 4/8] ipmi: add FRU support
Date: Fri, 8 Jan 2016 13:41:26 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.4.0

On 01/05/2016 11:29 AM, Cédric Le Goater wrote:
This patch provides a simplistic FRU support for the IPMI BMC
simulator.  The FRU area contains 32 entries * 256 bytes which should
be enough to start some simulation.

Signed-off-by: Cédric Le Goater <address@hidden>
---
  hw/ipmi/ipmi_bmc_sim.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 119 insertions(+)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 5db94491b130..60586a67104e 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -81,6 +81,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
@@ -123,6 +126,14 @@ typedef struct IPMISdr {
      uint8_t overflow;
  } IPMISdr;
+/* theoretically, the offset being 16bits, it should be 65536 */
+#define MAX_FRU_SIZE 256
+#define MAX_FRU_ID 32
+
+typedef struct IPMIFru {
+    uint8_t data[MAX_FRU_SIZE][MAX_FRU_ID];
+} IPMIFru;

Instead of a static table like this, I think it would be better to make this configurable somehow. I say this because I've never seen a system with 32 FRU devices on a BMC, but I've seen plenty with FRU data larger than 256 bytes. By default, 1 FRU device with 2048 bytes is pretty reasonable, I think.

I'm not exactly sure the best way to make it configurable. I assume that you need your platform code to be able to provide that information, and it could be passed in as BMC configuration parameters. The ability to load the FRU data at startup is probably also necessary.

-corey

+
  typedef struct IPMISensor {
      uint8_t status;
      uint8_t reading;
@@ -206,6 +217,7 @@ struct IPMIBmcSim {
IPMISel sel;
      IPMISdr sdr;
+    IPMIFru fru;
      IPMISensor sensors[MAX_SENSORS];
/* Odd netfns are for responses, so we only need the even ones. */
@@ -1305,6 +1317,110 @@ static void get_sel_info(IPMIBmcSim *ibs,
      return;
  }
+static void get_fru_area_info(IPMIBmcSim *ibs,
+                         uint8_t *cmd, unsigned int cmd_len,
+                         uint8_t *rsp, unsigned int *rsp_len,
+                         unsigned int max_rsp_len)
+{
+    uint8_t fruid;
+    uint16_t fru_entry_size;
+
+    IPMI_CHECK_CMD_LEN(3);
+
+    fruid = cmd[2];
+
+    if (fruid > MAX_FRU_ID) {
+        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        goto out;
+    }
+
+    fru_entry_size = MAX_FRU_SIZE;
+
+    IPMI_ADD_RSP_DATA(fru_entry_size & 0xff);
+    IPMI_ADD_RSP_DATA(fru_entry_size >> 8 & 0xff);
+    IPMI_ADD_RSP_DATA(0x0);
+out:
+    return;
+}
+
+#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,
+                         uint8_t *rsp, unsigned int *rsp_len,
+                         unsigned int max_rsp_len)
+{
+    uint8_t fruid;
+    uint16_t offset;
+    int i;
+    uint8_t *fru_entry;
+    unsigned int count;
+
+    IPMI_CHECK_CMD_LEN(5);
+
+    fruid = cmd[2];
+    offset = (cmd[3] | cmd[4] << 8);
+
+    if (fruid > MAX_FRU_ID) {
+        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        goto out;
+    }
+
+    if (offset >= MAX_FRU_SIZE - 1) {
+        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        goto out;
+    }
+
+    fru_entry = ibs->fru.data[fruid];
+
+    count = min(cmd[5], MAX_FRU_SIZE - offset);
+
+    IPMI_ADD_RSP_DATA(count & 0xff);
+    for (i = 0; i < count; i++) {
+        IPMI_ADD_RSP_DATA(fru_entry[offset + i]);
+    }
+
+ out:
+    return;
+}
+
+static void write_fru_data(IPMIBmcSim *ibs,
+                         uint8_t *cmd, unsigned int cmd_len,
+                         uint8_t *rsp, unsigned int *rsp_len,
+                         unsigned int max_rsp_len)
+{
+    uint8_t fruid;
+    uint16_t offset;
+    uint8_t *fru_entry;
+    unsigned int count;
+
+    IPMI_CHECK_CMD_LEN(5);
+
+    fruid = cmd[2];
+    offset = (cmd[3] | cmd[4] << 8);
+
+    if (fruid > MAX_FRU_ID) {
+        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        goto out;
+    }
+
+    if (offset >= MAX_FRU_SIZE - 1) {
+        rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+        goto out;
+    }
+
+    fru_entry = ibs->fru.data[fruid];
+
+    count = min(cmd_len - 5, MAX_FRU_SIZE - offset);
+
+    memcpy(fru_entry + offset, cmd + 5, count);
+
+    IPMI_ADD_RSP_DATA(count & 0xff);
+ out:
+    return;
+}
+
  static void reserve_sel(IPMIBmcSim *ibs,
                          uint8_t *cmd, unsigned int cmd_len,
                          uint8_t *rsp, unsigned int *rsp_len,
@@ -1682,6 +1798,9 @@ static const IPMINetfn app_netfn = {
  };
static const IPMICmdHandler storage_cmds[IPMI_NETFN_STORAGE_MAXCMD] = {
+    [IPMI_CMD_GET_FRU_AREA_INFO] = get_fru_area_info,
+    [IPMI_CMD_READ_FRU_DATA] = read_fru_data,
+    [IPMI_CMD_WRITE_FRU_DATA] = write_fru_data,
      [IPMI_CMD_GET_SDR_REP_INFO] = get_sdr_rep_info,
      [IPMI_CMD_RESERVE_SDR_REP] = reserve_sdr_rep,
      [IPMI_CMD_GET_SDR] = get_sdr,




reply via email to

[Prev in Thread] Current Thread [Next in Thread]