[Top][All Lists]
[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>
- [Freeipmi-devel] New FreeIPMI byte-array/FIID model,
Anand Babu <=