freeipmi-devel
[Top][All Lists]
Advanced

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

[Freeipmi-devel] New FreeIPMI byte-array/FIID model


From: Anand Babu
Subject: [Freeipmi-devel] New FreeIPMI byte-array/FIID model
Date: Thu, 18 Dec 2003 15:49:21 -0800
User-agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3 (gnu/linux)

Just finished byte-array/FIID (FreeIPMI Interface Definition) model.
Currently porting the rest of the framework to this new interface.
Tomorrow you will release a copy of bmc-config utility with all the
required functionalities based on FIID model.

After trying marco pre-processors, lex parsers and complex definition
formats, Finally got a clean and easy interface to work. This new FIID
model was jointly developed by Me and Balamurugan. Bala will soon be a
full-time developer for LLNL activities.

FIID Model:

Let us take the most complex packet structure:

typedef struct ipmi_cmd_get_dev_id_rs
{
  u_int8_t cmd;
  u_int8_t comp_code;
  struct {
    u_int8_t dev_id;
    struct {
      u_int8_t rev:4; /* binary encoded */
      u_int8_t reserved1:3;
      u_int8_t sdr_support:1;
    } dev_rev;
    struct {
      u_int8_t major_rev:7; /* binary encoded */
      u_int8_t dev_available:1;
    } firmware_rev1;
    struct {
      u_int8_t minor_rev; /* BCD encoded */
    } firmware_rev2;
    struct {
      u_int8_t ms_bits:4;
      u_int8_t ls_bits:4;
    } ipmi_ver; /* BCD encoded */
    struct {
      u_int8_t sensor_dev:1;
      u_int8_t sdr_repo_dev:1;
      u_int8_t sel_dev:1;
      u_int8_t fru_inventory_dev:1;
      u_int8_t ipmb_evnt_receiver:1;
      u_int8_t ipmb_evnt_generator:1;
      u_int8_t bridge:1;
      u_int8_t chassis_dev:1;
    } additional_dev_support;
    struct {
      u_int32_t id:20;
      u_int8_t reserved1:4;
    } manf_id;
    u_int16_t prod_id;
    u_int32_t aux_firmware_rev_info;
  } data;
} ipmi_cmd_get_dev_id_rs_t;

This gets translated to a C array (no need of lex parsers :)

fiid_obj_t fiid_cmd_get_dev_id_rs =
{
  {8,  "cmd"},
  {8,  "comp_code"},
  {8,  "data.dev_id"}, 
  {4,  "data.dev_rev.rev"}, /* binary encoded */
  {3,  "data.dev_rev.reserved1"},
  {1,  "data.dev_rev.sdr_support"},
  {7,  "data.firmware_rev1.major_rev"},
  {1,  "data.firmware_rev1.dev_available"},
  {8,  "data.firmware_rev2.minor_rev"}, /* BCD encoded */
  {4,  "data.ipmi_ver.ms_bits"},
  {4,  "data.ipmi_ver.ls_bits"},
  {1,  "data.additional_dev_support.sensor_dev"},
  {1,  "data.additional_dev_support.sdr_repo_dev"},
  {1,  "data.additional_dev_support.sel_dev"},
  {1,  "data.additional_dev_support.fru_inventory_dev"},
  {1,  "data.additional_dev_support.ipmb_evnt_receiver"},
  {1,  "data.additional_dev_support.ipmb_evnt_generator"},
  {1,  "data.additional_dev_support.bridge"},
  {1,  "data.additional_dev_support.chassis_dev"},
  {20, "data.manf_id.id"},
  {4,  "data.manf_id.reserved1"},
  {16, "data.prod_id"},
  {32, "data.aux_firmware_rev_info"},
  {0,  ""}
};

Then you have FIID calls to work on top of a byte-array using this
interface definition:

int32_t fiid_obj_len (fiid_obj_t obj);
int32_t fiid_obj_len_bytes (fiid_obj_t obj);
int32_t fiid_obj_field_start_end (fiid_obj_t obj, u_int8_t *field, u_int32_t 
*start, u_int32_t *end);
int32_t fiid_obj_field_start (fiid_obj_t obj, u_int8_t *field);
int32_t fiid_obj_field_end (fiid_obj_t obj, u_int8_t *field);
int32_t fiid_obj_field_len (fiid_obj_t obj, u_int8_t *field);
int32_t fiid_obj_field_len_bytes (fiid_obj_t obj, u_int8_t *field);
int8_t fiid_obj_set (u_int8_t *bytes, u_int32_t len, fiid_obj_t obj, u_int8_t 
*field, u_int64_t val);
u_int32_t fiid_obj_get (u_int8_t *bytes, u_int32_t len, fiid_obj_t obj, 
u_int8_t *field, u_int64_t *val);
int8_t fiid_obj_dump (int fd, fiid_obj_t obj, u_int8_t *data, u_int32_t len)
#define FIID_OBJ_SET(bytes, len, obj, field, val)            \
do {                                                         \
    if (fiid_obj_set (bytes, len, obj, field, val) == -1)    \
      err (1, "fiid_obj_set (%p, %d, %p, \"%s\", %X) error", \
           bytes, len, obj, field, val);                     \
} while (0)

#define FIID_OBJ_GET(bytes, len, obj, field, val)            \
do {                                                         \
    if (fiid_obj_get (bytes, len, obj, field, val) == -1)    \
      err (1, "fiid_obj_get (%p, %d, %p, \"%s\", %p) error", \
           bytes, len, obj, field, val);                     \
} while (0)


Most importantly all we care about is get, set, dump and len_bytes.

We also have a whole  bunch of bit manipulators.

#define BIT_0 0x01  
#define BIT_1 0x02  
#define BIT_2 0x04  
#define BIT_3 0x08  
#define BIT_4 0x10  
#define BIT_5 0x20  
#define BIT_6 0x40
#define BIT_7 0x80
#define BIT(n) ((u_int64_t) powl(2, n))

#define TOBOOL(arg) (!(!(arg)))
#define BIT_SET(arg, posn) (arg | (1L << posn))
#define BIT_CLR(arg, posn) (arg & ~(1L << posn))
#define BIT_FLP(arg, posn) (arg ^ (1L << posn))
#define BIT_TST(arg, posn) TOBOOL ((arg) & (1L << posn))

#define BITS_ZERO(arg) (arg ^ arg)
#define BITS_0(arg)    (bits_extract (arg,  0 , 8))
#define BITS_1(arg)    (bits_extract (arg,  8, 16))
#define BITS_2(arg)    (bits_extract (arg, 16, 24))
#define BITS_3(arg)    (bits_extract (arg, 24, 33))
#define BITS_4(arg)    (bits_extract (arg, 32, 40))
#define BITS_5(arg)    (bits_extract (arg, 40, 48))
#define BITS_6(arg)    (bits_extract (arg, 48, 56))
#define BITS_7(arg)    (bits_extract (arg, 56, 64))
#define BITS_SET(arg, bits) (arg | (bits))
#define BITS_CLR(arg, bits) (arg & ~(bits))
#define BITS_ROUND_BYTES(bits_count) ((bits_count / 8) + ((bits_count % 8) ? 1 
: 0))


typedef u_int8_t bitstr_t;
#define _BITSTR_BYTE(bit) \
#define _BITSTR_MASK(bit) \
#define BITSTR_SIZE(nbits) \
#define BITSTR_ALLOC(nbits) \
#define BITSTR_DECL(name, nbits) \
#define BITSTR_TEST(name, bit) \
#define BITSTR_SET(name, bit) \
#define BITSTR_CLEAR(name, bit) \
#define BITSTR_NCLEAR(name, start, stop) { \
#define BITSTR_NSET(name, start, stop) { \
#define BITSTR_FFC(name, nbits, value) { \
#define BITSTR_FFS(name, nbits, value) { \
u_int64_t bits_extract (u_int64_t bits, u_int8_t start, u_int8_t end);
u_int64_t bits_merge (u_int64_t bits, u_int8_t start, u_int8_t end, u_int64_t 
val);

This new interface seems to work great. All the complex bit level
manipulations are completely hidden in a portable fashion.

The code seems to shrink a lot now with this new interface.
Even for dumping the packet, just one generic function will do.

fiid_obj_dump (1, fiid_cmd_get_dev_id_rs, cmd_rs, sizeof(cmd_rs))
yields
================================================================
[ VALUE               TAG NAME:LENGTH                          ]
================================================================
[               1h] = cmd[ 8b]
[               0h] = comp_code[ 8b]
[              20h] = data.dev_id[ 8b]
[               1h] = data.dev_rev.rev[ 4b]
[               0h] = data.dev_rev.reserved1[ 3b]
[               1h] = data.dev_rev.sdr_support[ 1b]
[               0h] = data.firmware_rev1.major_rev[ 7b]
[               0h] = data.firmware_rev1.dev_available[ 1b]
[              20h] = data.firmware_rev2.minor_rev[ 8b]
[               1h] = data.ipmi_ver.ms_bits[ 4b]
[               5h] = data.ipmi_ver.ls_bits[ 4b]
[               1h] = data.additional_dev_support.sensor_dev[ 1b]
[               1h] = data.additional_dev_support.sdr_repo_dev[ 1b]
[               1h] = data.additional_dev_support.sel_dev[ 1b]
[               1h] = data.additional_dev_support.fru_inventory_dev[1b]
[               1h] = data.additional_dev_support.ipmb_evnt_receiver[1b]
[               0h] = data.additional_dev_support.ipmb_evnt_generator[1b]
[               0h] = data.additional_dev_support.bridge[ 1b]
[               1h] = data.additional_dev_support.chassis_dev[ 1b]
[             157h] = data.manf_id.id[20b]
[               0h] = data.manf_id.reserved1[ 4b]
[             100h] = data.prod_id[16b]
[        20011300h] = data.aux_firmware_rev_info[32b]
================================================================

There are simple strategies to handle variable / optional fields in a
packet, just the we handle them with struct. More later.

I will upload the new FreeIPMI code tomorrow along with bmc-config
utility.


-- 
Anand Babu
CaliforniaDigital.com
Office# +1-510-687-7045
Cell# +1-510-396-0717
Home# +1-510-894-0586

Free as in Freedom <www.gnu.org>




reply via email to

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