30
30
#include <string.h>
31
#include <stdio.h> /* for sprintf */
31
32
#include <OpenIPMI/internal/ipmi_fru.h>
32
33
#include <OpenIPMI/internal/ipmi_int.h>
34
35
/***********************************************************************
36
* FRU Multi-record decoding
38
**********************************************************************/
41
convert_int_to_fru_int(const char *name,
44
enum ipmi_fru_data_type_e *dtype,
50
*dtype = IPMI_FRU_DATA_INT;
57
convert_str_to_fru_str(const char *name,
58
enum ipmi_str_type_e type,
62
enum ipmi_fru_data_type_e *dtype,
70
case IPMI_ASCII_STR: *dtype = IPMI_FRU_DATA_ASCII; break;
71
case IPMI_UNICODE_STR: *dtype = IPMI_FRU_DATA_BINARY; break;
72
case IPMI_BINARY_STR: *dtype = IPMI_FRU_DATA_UNICODE; break;
78
if (type == IPMI_ASCII_STR)
82
*data = ipmi_mem_alloc(len);
85
if (type == IPMI_ASCII_STR) {
86
memcpy(*data, raw_data, len-1);
87
(*data)[len-1] = '\0';
89
memcpy(*data, raw_data, len);
94
typedef struct atca_p2p_cr_desc_s
96
unsigned char channel_type;
97
unsigned char slot_address;
98
unsigned char channel_count;
100
} atca_p2p_cr_desc_t;
102
typedef struct atca_p2p_cr_s
104
unsigned char version;
105
unsigned int desc_count;
106
atca_p2p_cr_desc_t *descs;
110
static void atca_p2p_cleanup_rec(atca_p2p_cr_t *rec)
115
for (i=0; i<rec->desc_count; i++) {
116
if (rec->descs[i].chans)
117
ipmi_mem_free(rec->descs[i].chans);
119
ipmi_mem_free(rec->descs);
125
atca_p2p_root_destroy(ipmi_fru_node_t *node)
127
atca_p2p_cr_t *rec = _ipmi_fru_node_get_data(node);
128
ipmi_fru_deref(rec->fru);
129
atca_p2p_cleanup_rec(rec);
133
atca_p2p_sub_destroy(ipmi_fru_node_t *node)
135
ipmi_fru_node_t *root_node = _ipmi_fru_node_get_data2(node);
136
ipmi_fru_put_node(root_node);
140
atca_p2p_desc_entry_get_field(ipmi_fru_node_t *pnode,
143
enum ipmi_fru_data_type_e *dtype,
148
unsigned int *data_len,
149
ipmi_fru_node_t **sub_node)
151
uint32_t rec = *((uint32_t *) _ipmi_fru_node_get_data(pnode));
156
rv = convert_int_to_fru_int("remote slot", rec & 0xff,
157
name, dtype, intval);
161
rv = convert_int_to_fru_int("remote channel", (rec >> 8) & 0x1f,
162
name, dtype, intval);
166
rv = convert_int_to_fru_int("local channel", (rec >> 13) & 0x1f,
167
name, dtype, intval);
178
atca_p2p_desc_entry_array_get_field(ipmi_fru_node_t *pnode,
181
enum ipmi_fru_data_type_e *dtype,
186
unsigned int *data_len,
187
ipmi_fru_node_t **sub_node)
189
atca_p2p_cr_desc_t *rec = _ipmi_fru_node_get_data(pnode);
190
ipmi_fru_node_t *rnode = _ipmi_fru_node_get_data2(pnode);
191
atca_p2p_cr_t *rrec = _ipmi_fru_node_get_data(rnode);
192
ipmi_fru_node_t *node;
194
if (index >= rec->channel_count)
198
*name = NULL; /* We are an array */
200
*dtype = IPMI_FRU_DATA_SUB_NODE;
202
*intval = -1; /* Sub element is not an array */
204
node = _ipmi_fru_node_alloc(rrec->fru);
208
ipmi_fru_get_node(rnode);
209
_ipmi_fru_node_set_data(node, rec->chans + index);
210
_ipmi_fru_node_set_data2(node, rnode);
211
_ipmi_fru_node_set_get_field(node, atca_p2p_desc_entry_get_field);
212
_ipmi_fru_node_set_destructor(node, atca_p2p_sub_destroy);
221
atca_p2p_desc_get_field(ipmi_fru_node_t *pnode,
224
enum ipmi_fru_data_type_e *dtype,
229
unsigned int *data_len,
230
ipmi_fru_node_t **sub_node)
232
atca_p2p_cr_desc_t *rec = _ipmi_fru_node_get_data(pnode);
233
ipmi_fru_node_t *rnode = _ipmi_fru_node_get_data2(pnode);
234
atca_p2p_cr_t *rrec = _ipmi_fru_node_get_data(rnode);
235
ipmi_fru_node_t *node;
240
rv = convert_int_to_fru_int("channel type", rec->channel_type,
241
name, dtype, intval);
245
rv = convert_int_to_fru_int("slot address", rec->slot_address,
246
name, dtype, intval);
253
*dtype = IPMI_FRU_DATA_SUB_NODE;
255
*intval = rec->channel_count;
257
node = _ipmi_fru_node_alloc(rrec->fru);
260
ipmi_fru_get_node(rnode);
261
_ipmi_fru_node_set_data(node, rec);
262
_ipmi_fru_node_set_data2(node, rnode);
263
_ipmi_fru_node_set_get_field(node,
264
atca_p2p_desc_entry_array_get_field);
265
_ipmi_fru_node_set_destructor(node, atca_p2p_sub_destroy);
278
atca_p2p_desc_array_get_field(ipmi_fru_node_t *pnode,
281
enum ipmi_fru_data_type_e *dtype,
286
unsigned int *data_len,
287
ipmi_fru_node_t **sub_node)
289
atca_p2p_cr_t *rec = _ipmi_fru_node_get_data(pnode);
290
ipmi_fru_node_t *rnode = _ipmi_fru_node_get_data2(pnode);
291
atca_p2p_cr_t *rrec = _ipmi_fru_node_get_data(rnode);
292
ipmi_fru_node_t *node;
294
if (index >= rec->desc_count)
298
*name = NULL; /* We are an array */
300
*dtype = IPMI_FRU_DATA_SUB_NODE;
302
*intval = -1; /* Sub element is not an array */
304
node = _ipmi_fru_node_alloc(rrec->fru);
308
ipmi_fru_get_node(rnode);
309
_ipmi_fru_node_set_data(node, rec->descs + index);
310
_ipmi_fru_node_set_data2(node, rnode);
311
_ipmi_fru_node_set_get_field(node, atca_p2p_desc_get_field);
312
_ipmi_fru_node_set_destructor(node, atca_p2p_sub_destroy);
320
atca_p2p_root_get_field(ipmi_fru_node_t *rnode,
323
enum ipmi_fru_data_type_e *dtype,
328
unsigned int *data_len,
329
ipmi_fru_node_t **sub_node)
331
atca_p2p_cr_t *rec = _ipmi_fru_node_get_data(rnode);
332
ipmi_fru_node_t *node;
337
rv = convert_int_to_fru_int("version", rec->version,
338
name, dtype, intval);
343
*name = "descriptors";
345
*dtype = IPMI_FRU_DATA_SUB_NODE;
347
*intval = rec->desc_count;
349
node = _ipmi_fru_node_alloc(rec->fru);
352
ipmi_fru_get_node(rnode);
353
_ipmi_fru_node_set_data(node, rec);
354
_ipmi_fru_node_set_data2(node, rnode);
355
_ipmi_fru_node_set_get_field(node, atca_p2p_desc_array_get_field);
356
_ipmi_fru_node_set_destructor(node, atca_p2p_sub_destroy);
369
atca_root_mr_p2p_cr(ipmi_fru_t *fru,
370
unsigned char *mr_data,
371
unsigned int mr_data_len,
373
ipmi_fru_node_t **rnode)
376
atca_p2p_cr_desc_t *drec;
380
ipmi_fru_node_t *node;
386
if (mr_data_len == 0)
389
if (mr_data[0] != 0) /* Only support version 0 */
392
rec = ipmi_mem_alloc(sizeof(*rec));
395
memset(rec, 0, sizeof(*rec));
397
rec->version = mr_data[0];
407
if ((unsigned int) (p[2] * 3) > left)
413
rec->descs = ipmi_mem_alloc(sizeof(atca_p2p_cr_desc_t) * rec->desc_count);
416
memset(rec->descs, 0, sizeof(atca_p2p_cr_desc_t) * rec->desc_count);
422
drec = &(rec->descs[i]);
423
drec->channel_type = p[0];
424
drec->slot_address = p[1];
425
drec->channel_count = p[2];
426
drec->chans = ipmi_mem_alloc(sizeof(uint32_t) * p[2]);
431
for (j=0; j<drec->channel_count; j++) {
432
drec->chans[j] = p[0] | (p[1] << 8) | (p[2] << 16);
439
node = _ipmi_fru_node_alloc(fru);
446
_ipmi_fru_node_set_data(node, rec);
447
_ipmi_fru_node_set_get_field(node, atca_p2p_root_get_field);
448
_ipmi_fru_node_set_destructor(node, atca_p2p_root_destroy);
453
*name = "Point-to-Point Connectivity Record";
466
atca_p2p_cleanup_rec(rec);
470
typedef struct atca_addr_tab_desc_s
472
unsigned char hw_addr;
473
unsigned char site_number;
474
unsigned char site_type;
475
} atca_addr_tab_desc_t;
477
typedef struct atca_addr_tab_s
479
unsigned char version;
480
unsigned int shelf_addr_len;
481
enum ipmi_str_type_e shelf_addr_type;
483
unsigned char addr_count;
484
atca_addr_tab_desc_t *addrs;
488
static void atca_addr_tab_cleanup_rec(atca_addr_tab_t *rec)
491
ipmi_mem_free(rec->addrs);
496
atca_addr_tab_root_destroy(ipmi_fru_node_t *node)
498
atca_addr_tab_t *rec = _ipmi_fru_node_get_data(node);
499
ipmi_fru_deref(rec->fru);
500
atca_addr_tab_cleanup_rec(rec);
504
atca_addr_tab_sub_destroy(ipmi_fru_node_t *node)
506
ipmi_fru_node_t *root_node = _ipmi_fru_node_get_data2(node);
507
ipmi_fru_put_node(root_node);
511
atca_addr_tab_desc_get_field(ipmi_fru_node_t *pnode,
514
enum ipmi_fru_data_type_e *dtype,
519
unsigned int *data_len,
520
ipmi_fru_node_t **sub_node)
522
atca_addr_tab_desc_t *rec = _ipmi_fru_node_get_data(pnode);
527
rv = convert_int_to_fru_int("hardware address", rec->hw_addr,
528
name, dtype, intval);
532
rv = convert_int_to_fru_int("site number", rec->site_number,
533
name, dtype, intval);
537
rv = convert_int_to_fru_int("site type", rec->site_type,
538
name, dtype, intval);
549
atca_addr_tab_desc_array_get_field(ipmi_fru_node_t *pnode,
552
enum ipmi_fru_data_type_e *dtype,
557
unsigned int *data_len,
558
ipmi_fru_node_t **sub_node)
560
atca_addr_tab_t *rec = _ipmi_fru_node_get_data(pnode);
561
ipmi_fru_node_t *rnode = _ipmi_fru_node_get_data2(pnode);
562
atca_addr_tab_t *rrec = _ipmi_fru_node_get_data(rnode);
563
ipmi_fru_node_t *node;
565
if (index >= rec->addr_count)
569
*name = NULL; /* We are an array */
571
*dtype = IPMI_FRU_DATA_SUB_NODE;
573
*intval = -1; /* Sub element is not an array */
575
node = _ipmi_fru_node_alloc(rrec->fru);
579
ipmi_fru_get_node(rnode);
580
_ipmi_fru_node_set_data(node, rec->addrs + index);
581
_ipmi_fru_node_set_data2(node, rnode);
582
_ipmi_fru_node_set_get_field(node, atca_addr_tab_desc_get_field);
583
_ipmi_fru_node_set_destructor(node, atca_addr_tab_sub_destroy);
590
atca_addr_tab_root_get_field(ipmi_fru_node_t *rnode,
593
enum ipmi_fru_data_type_e *dtype,
598
unsigned int *data_len,
599
ipmi_fru_node_t **sub_node)
601
atca_addr_tab_t *rec = _ipmi_fru_node_get_data(rnode);
602
ipmi_fru_node_t *node;
607
rv = convert_int_to_fru_int("version", rec->version,
608
name, dtype, intval);
612
rv = convert_str_to_fru_str("shelf address", rec->shelf_addr_type,
615
name, dtype, intval, data);
622
*dtype = IPMI_FRU_DATA_SUB_NODE;
624
*intval = rec->addr_count;
626
node = _ipmi_fru_node_alloc(rec->fru);
629
ipmi_fru_get_node(rnode);
630
_ipmi_fru_node_set_data(node, rec);
631
_ipmi_fru_node_set_data2(node, rnode);
632
_ipmi_fru_node_set_get_field(node,
633
atca_addr_tab_desc_array_get_field);
634
_ipmi_fru_node_set_destructor(node, atca_addr_tab_sub_destroy);
647
atca_root_mr_addr_tab(ipmi_fru_t *fru,
648
unsigned char *mr_data,
649
unsigned int mr_data_len,
651
ipmi_fru_node_t **rnode)
653
atca_addr_tab_t *rec;
656
ipmi_fru_node_t *node;
662
/* Room for the version, shelf address, and address table entry count */
663
if (mr_data_len < 23)
666
if (mr_data[0] != 0) /* Only support version 0 */
669
rec = ipmi_mem_alloc(sizeof(*rec));
672
memset(rec, 0, sizeof(*rec));
674
rec->version = mr_data[0];
679
rv = ipmi_get_device_string(&p, mr_data_len,
681
IPMI_STR_FRU_SEMANTICS, 0,
682
&rec->shelf_addr_type,
683
sizeof(rec->shelf_addr),
684
&rec->shelf_addr_len);
687
if ((p - mr_data) > 21)
692
rec->addr_count = mr_data[0];
696
if ((unsigned int) (rec->addr_count * 3) > mr_data_len)
699
rec->addrs = ipmi_mem_alloc(sizeof(*(rec->addrs)) * rec->addr_count);
703
for (i=0; i<rec->addr_count; i++) {
704
rec->addrs[i].hw_addr = mr_data[0];
705
rec->addrs[i].site_number = mr_data[1];
706
rec->addrs[i].site_type = mr_data[2];
711
node = _ipmi_fru_node_alloc(fru);
718
_ipmi_fru_node_set_data(node, rec);
719
_ipmi_fru_node_set_get_field(node, atca_addr_tab_root_get_field);
720
_ipmi_fru_node_set_destructor(node, atca_addr_tab_root_destroy);
724
*name = "Address Table";
737
atca_addr_tab_cleanup_rec(rec);
37
* Point-to-point connectivity record
39
**********************************************************************/
41
static ipmi_mr_item_layout_t p2p_cr_desc_ent_items[] = {
42
{ .name = "remote slot", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
43
.start = 0, .length = 8,
44
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
45
{ .name = "remote channel", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
46
.start = 8, .length = 5,
47
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
48
{ .name = "local channel ", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
49
.start = 13, .length = 5,
50
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field }
52
static ipmi_mr_struct_layout_t p2p_cr_desc_ent = {
53
.name = NULL, .length = 3,
54
.item_count = 3, .items = p2p_cr_desc_ent_items,
55
.array_count = 0, .arrays = NULL,
56
.cleanup = ipmi_mr_struct_cleanup
58
static ipmi_mr_item_layout_t p2p_cr_desc_items[] = {
59
{ .name = "channel type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
60
.start = 0, .length = 1,
61
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
62
{ .name = "slot address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
63
.start = 1, .length = 1,
64
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
66
static ipmi_mr_array_layout_t p2p_cr_desc_arys[] = {
67
{ .name = "channels", .has_count = 1, .min_elem_size = 3, .settable = 1,
68
.elem_layout = &p2p_cr_desc_ent,
69
.elem_check = ipmi_mr_struct_elem_check,
70
.elem_decode = ipmi_mr_struct_decode,
71
.cleanup = ipmi_mr_struct_array_cleanup,
72
.get_field = ipmi_mr_struct_array_get_field,
73
.set_field = ipmi_mr_struct_array_set_field }
75
static ipmi_mr_struct_layout_t p2p_cr_desc = {
76
.name = NULL, .length = 2,
77
.item_count = 2, .items = p2p_cr_desc_items,
78
.array_count = 1, .arrays = p2p_cr_desc_arys,
79
.cleanup = ipmi_mr_struct_cleanup
81
static ipmi_mr_item_layout_t p2p_cr_items[] = {
82
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
83
.start = 0, .length = 1,
84
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
86
static ipmi_mr_array_layout_t p2p_cr_arys[] = {
87
{ .name = "descriptors", .has_count = 0, .min_elem_size = 3, .settable = 1,
88
.elem_layout = &p2p_cr_desc,
89
.elem_check = ipmi_mr_struct_elem_check, .elem_decode = ipmi_mr_struct_decode,
90
.cleanup = ipmi_mr_struct_array_cleanup,
91
.get_field = ipmi_mr_struct_array_get_field,
92
.set_field = ipmi_mr_struct_array_set_field }
94
static ipmi_mr_struct_layout_t p2p_cr = {
95
.name = "Point-to-Point Connectivity Record", .length = 1,
96
.item_count = 1, .items = p2p_cr_items,
97
.array_count = 1, .arrays = p2p_cr_arys,
98
.cleanup = ipmi_mr_struct_cleanup
102
/***********************************************************************
104
* Address table descriptor record
106
**********************************************************************/
108
static ipmi_mr_item_layout_t addr_tab_ent[] = {
109
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
110
.start = 0, .length = 1,
111
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
112
{ .name = "site_number", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
113
.start = 1, .length = 1,
114
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
115
{ .name = "site_type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
116
.start = 2, .length = 1,
117
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
119
static ipmi_mr_struct_layout_t addr_tab_ents = {
120
.name = NULL, .length = 3,
121
.item_count = 3, .items = addr_tab_ent,
122
.array_count = 0, .arrays = NULL,
123
.cleanup = ipmi_mr_struct_cleanup
125
static ipmi_mr_item_layout_t addr_tab_items[] = {
126
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
127
.start = 0, .length = 1,
128
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
129
{ .name = "shelf address", .dtype = IPMI_FRU_DATA_ASCII, .settable = 1,
130
.start = 1, .length = 21,
131
.set_field = ipmi_mr_str_set_field, .get_field = ipmi_mr_str_get_field },
133
static ipmi_mr_array_layout_t addr_tab_arys[] = {
134
{ .name = "addresses", .has_count = 1, .min_elem_size = 3, .settable = 1,
135
.elem_layout = &addr_tab_ents,
136
.elem_check = ipmi_mr_struct_elem_check, .elem_decode = ipmi_mr_struct_decode,
137
.cleanup = ipmi_mr_struct_array_cleanup,
138
.get_field = ipmi_mr_struct_array_get_field,
139
.set_field = ipmi_mr_struct_array_set_field }
141
static ipmi_mr_struct_layout_t addr_tab = {
142
.name = "Address Table", .length = 22,
143
.item_count = 2, .items = addr_tab_items,
144
.array_count = 1, .arrays = addr_tab_arys,
145
.cleanup = ipmi_mr_struct_cleanup
149
/***********************************************************************
151
* Shelf power distribution record
153
**********************************************************************/
155
static ipmi_mr_item_layout_t pow_dist_f2f_items[] = {
156
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
157
.start = 0, .length = 1,
158
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
159
{ .name = "FRU device id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
160
.start = 1, .length = 1,
161
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
163
static ipmi_mr_struct_layout_t pow_dist_f2f = {
164
.name = NULL, .length = 2,
165
.item_count = 2, .items = pow_dist_f2f_items,
166
.array_count = 0, .arrays = NULL,
167
.cleanup = ipmi_mr_struct_cleanup
169
static ipmi_mr_item_layout_t pow_dist_maps_items[] = {
170
{ .name = "max extern avail current", .dtype = IPMI_FRU_DATA_FLOAT,
172
.start = 0, .length = 2,
174
.set_field = ipmi_mr_intfloat_set_field,
175
.get_field = ipmi_mr_intfloat_get_field },
176
{ .name = "max internal current", .dtype = IPMI_FRU_DATA_FLOAT,
178
.start = 2, .length = 2,
180
.set_field = ipmi_mr_intfloat_set_field,
181
.get_field = ipmi_mr_intfloat_get_field },
182
{ .name = "min operating voltage", .dtype = IPMI_FRU_DATA_FLOAT,
184
.start = 2, .length = 2,
186
.set_field = ipmi_mr_intfloat_set_field,
187
.get_field = ipmi_mr_intfloat_get_field }
189
static ipmi_mr_array_layout_t pow_dist_maps_arys[] = {
190
{ .name = "feed to frus", .has_count = 1, .min_elem_size = 6,
192
.elem_layout = &pow_dist_f2f,
193
.elem_check = ipmi_mr_struct_elem_check,
194
.elem_decode = ipmi_mr_struct_decode,
195
.cleanup = ipmi_mr_struct_array_cleanup,
196
.get_field = ipmi_mr_struct_array_get_field,
197
.set_field = ipmi_mr_struct_array_set_field }
199
static ipmi_mr_struct_layout_t pow_dist_maps = {
200
.name = NULL, .length = 5,
201
.item_count = 3, .items = pow_dist_maps_items,
202
.array_count = 1, .arrays = pow_dist_maps_arys,
203
.cleanup = ipmi_mr_struct_cleanup
205
static ipmi_mr_item_layout_t pow_dist_items[] = {
206
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
207
.start = 0, .length = 1,
208
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
210
static ipmi_mr_array_layout_t pow_dist_arys[] = {
211
{ .name = "power feeds", .has_count = 1, .min_elem_size = 3, .settable = 1,
212
.elem_layout = &pow_dist_maps,
213
.elem_check = ipmi_mr_struct_elem_check,
214
.elem_decode = ipmi_mr_struct_decode,
215
.cleanup = ipmi_mr_struct_array_cleanup,
216
.get_field = ipmi_mr_struct_array_get_field,
217
.set_field = ipmi_mr_struct_array_set_field }
219
static ipmi_mr_struct_layout_t pow_dist = {
220
.name = "Shelf Power Distribution", .length = 1,
221
.item_count = 1, .items = pow_dist_items,
222
.array_count = 1, .arrays = pow_dist_arys,
223
.cleanup = ipmi_mr_struct_cleanup
227
/***********************************************************************
229
* Shelf activation and power management record
231
**********************************************************************/
233
static ipmi_mr_item_layout_t act_pm_desc[] = {
234
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
235
.start = 0, .length = 1,
236
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
237
{ .name = "FRU device id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
238
.start = 1, .length = 1,
239
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
240
{ .name = "max FRU power", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
241
.start = 2, .length = 2,
242
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
243
{ .name = "shelf manager activation", .dtype = IPMI_FRU_DATA_BOOLEAN,
245
.start = 38, .length = 1,
246
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
247
{ .name = "delay before next power on", .dtype = IPMI_FRU_DATA_INT,
249
.start = 32, .length = 6,
250
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field }
252
static ipmi_mr_struct_layout_t act_pm_descs = {
253
.name = NULL, .length = 5,
254
.item_count = 5, .items = act_pm_desc,
255
.array_count = 0, .arrays = NULL,
256
.cleanup = ipmi_mr_struct_cleanup
258
static ipmi_mr_item_layout_t act_pm_items[] = {
259
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
260
.start = 0, .length = 1,
261
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
262
{ .name = "allowance for activation readiness", .dtype = IPMI_FRU_DATA_INT,
264
.start = 1, .length = 1,
265
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
267
static ipmi_mr_array_layout_t act_pm_arys[] = {
268
{ .name = "activation power descriptors", .has_count = 1, .settable = 1,
270
.elem_layout = &act_pm_descs,
271
.elem_check = ipmi_mr_struct_elem_check, .elem_decode = ipmi_mr_struct_decode,
272
.cleanup = ipmi_mr_struct_array_cleanup,
273
.get_field = ipmi_mr_struct_array_get_field,
274
.set_field = ipmi_mr_struct_array_set_field }
276
static ipmi_mr_struct_layout_t act_pm = {
277
.name = "Shelf Activation and Power Management", .length = 2,
278
.item_count = 1, .items = act_pm_items,
279
.array_count = 1, .arrays = act_pm_arys,
280
.cleanup = ipmi_mr_struct_cleanup
284
/***********************************************************************
286
* Shelf manager IP connection record
288
**********************************************************************/
290
static ipmi_mr_item_layout_t ip_conn0_items[] = {
291
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
292
.start = 0, .length = 1,
293
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
294
{ .name = "ip address", .dtype = IPMI_FRU_DATA_ASCII,
296
.start = 1, .length = 4,
297
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field }
299
static ipmi_mr_struct_layout_t ip_conn0 = {
300
.name = "Shelf Manager IP Connection", .length = 5,
301
.item_count = 2, .items = ip_conn0_items,
302
.array_count = 0, .arrays = NULL,
303
.cleanup = ipmi_mr_struct_cleanup
306
static ipmi_mr_item_layout_t ip_conn1_items[] = {
307
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
308
.start = 0, .length = 1,
309
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
310
{ .name = "ip address", .dtype = IPMI_FRU_DATA_ASCII,
312
.start = 1, .length = 4,
313
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field },
314
{ .name = "gateway address", .dtype = IPMI_FRU_DATA_ASCII,
316
.start = 5, .length = 4,
317
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field },
318
{ .name = "subnet mask", .dtype = IPMI_FRU_DATA_ASCII,
320
.start = 9, .length = 4,
321
.set_field = ipmi_mr_ip_set_field, .get_field = ipmi_mr_ip_get_field }
323
static ipmi_mr_struct_layout_t ip_conn1 = {
324
.name = "Shelf Manager IP Connection", .length = 13,
325
.item_count = 4, .items = ip_conn1_items,
326
.array_count = 0, .arrays = NULL,
327
.cleanup = ipmi_mr_struct_cleanup
331
atca_root_ipmi_mr_shelf_mgr_ip_conn(ipmi_fru_t *fru,
332
unsigned int mr_rec_num,
333
unsigned char *mr_data,
334
unsigned int mr_data_len,
336
ipmi_fru_node_t **node)
338
ipmi_mr_struct_layout_t *layout;
342
switch (mr_data[4]) {
343
case 0: layout = &ip_conn0; break;
344
case 1: layout = &ip_conn1; break;
348
return ipmi_mr_struct_root(fru, mr_rec_num, mr_data+4, mr_data_len-4,
352
/***********************************************************************
354
* Board point-to-point Connectivity record
356
**********************************************************************/
358
static ipmi_mr_item_layout_t guid_elem = {
359
.name = "GUID", .dtype = IPMI_FRU_DATA_BINARY, .settable = 1,
360
.start = 0, .length = 16,
361
.set_field = ipmi_mr_binary_set_field,
362
.get_field = ipmi_mr_binary_get_field
364
static ipmi_mr_tab_item_t link_if_tab = {
366
.table = { "base", "fabric", "update channel" }
368
static ipmi_mr_item_layout_t link_desc[] = {
369
{ .name = "link grouping id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
370
.start = 24, .length = 8,
371
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
372
{ .name = "link type extension", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
373
.start = 20, .length = 4,
374
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
375
{ .name = "link type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
376
.start = 12, .length = 8,
377
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
378
{ .name = "port 3 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
379
.start = 11, .length = 1,
380
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
381
{ .name = "port 2 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
382
.start = 10, .length = 1,
383
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
384
{ .name = "port 1 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
385
.start = 9, .length = 1,
386
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
387
{ .name = "port 0 included", .dtype = IPMI_FRU_DATA_BOOLEAN, .settable = 1,
388
.start = 8, .length = 1,
389
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field },
390
{ .name = "interface", .dtype = IPMI_FRU_DATA_ASCII, .settable = 1,
391
.start = 6, .length = 2,
392
.u.tab_data = &link_if_tab,
393
.set_field = ipmi_mr_bitvaltab_set_field,
394
.get_field = ipmi_mr_bitvaltab_get_field,
395
.get_enum = ipmi_mr_bitvaltab_get_enum },
396
{ .name = "channel number", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
397
.start = 0, .length = 6,
398
.set_field = ipmi_mr_bitint_set_field, .get_field = ipmi_mr_bitint_get_field }
400
static ipmi_mr_struct_layout_t link_descs = {
401
.name = NULL, .length = 4,
402
.item_count = 9, .items = link_desc,
403
.array_count = 0, .arrays = NULL,
404
.cleanup = ipmi_mr_struct_cleanup
406
static ipmi_mr_item_layout_t bp2p_conn_items[] = {
407
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
408
.start = 0, .length = 1,
409
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
411
static ipmi_mr_array_layout_t bp2p_conn_arys[] = {
412
{ .name = "OEM GUIDs", .has_count = 1, .settable = 1,
414
.elem_layout = &guid_elem,
415
.elem_check = ipmi_mr_item_elem_check,
416
.elem_decode = ipmi_mr_item_decode,
417
.cleanup = ipmi_mr_item_array_cleanup,
418
.get_field = ipmi_mr_item_array_get_field,
419
.set_field = ipmi_mr_item_array_set_field },
420
{ .name = "Link Descriptors", .has_count = 0,
422
.elem_layout = &link_descs,
423
.elem_check = ipmi_mr_struct_elem_check,
424
.elem_decode = ipmi_mr_struct_decode,
425
.cleanup = ipmi_mr_struct_array_cleanup,
426
.get_field = ipmi_mr_struct_array_get_field,
427
.set_field = ipmi_mr_struct_array_set_field }
429
static ipmi_mr_struct_layout_t bp2p_conn = {
430
.name = "Board P2P Connectivity", .length = 1,
431
.item_count = 1, .items = bp2p_conn_items,
432
.array_count = 2, .arrays = bp2p_conn_arys,
433
.cleanup = ipmi_mr_struct_cleanup
437
/***********************************************************************
439
* Radial IPMB-0 Link Mapping
441
**********************************************************************/
443
static ipmi_mr_item_layout_t ipmb_link_mapping[] = {
444
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
445
.start = 0, .length = 1,
446
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
447
{ .name = "IPMB-0 link entry", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
448
.start = 1, .length = 1,
449
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
451
static ipmi_mr_struct_layout_t ipmb_link_mappings = {
452
.name = NULL, .length = 2,
453
.item_count = 2, .items = ipmb_link_mapping,
454
.array_count = 0, .arrays = NULL,
455
.cleanup = ipmi_mr_struct_cleanup
457
static ipmi_mr_tab_item_t hub_info_if_tab = {
459
.table = { NULL, "IPMB-A only", "IPMB-B only", "IPMB-A and IPMB-B" }
461
static ipmi_mr_item_layout_t hub_desc_items[] = {
462
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
463
.start = 0, .length = 1,
464
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
465
{ .name = "bus coverage", .dtype = IPMI_FRU_DATA_ASCII, .settable = 1,
466
.start = 8, .length = 2,
467
.u.tab_data = &hub_info_if_tab,
468
.set_field = ipmi_mr_bitvaltab_set_field,
469
.get_field = ipmi_mr_bitvaltab_get_field,
470
.get_enum = ipmi_mr_bitvaltab_get_enum }
472
static ipmi_mr_array_layout_t hub_desc_arys[] = {
473
{ .name = "IPMB-0 link mappings", .has_count = 1, .settable = 1,
475
.elem_layout = &ipmb_link_mappings,
476
.elem_check = ipmi_mr_struct_elem_check,
477
.elem_decode = ipmi_mr_struct_decode,
478
.cleanup = ipmi_mr_struct_array_cleanup,
479
.get_field = ipmi_mr_struct_array_get_field,
480
.set_field = ipmi_mr_struct_array_set_field }
482
static ipmi_mr_struct_layout_t hub_descs = {
483
.name = NULL, .length = 2,
484
.item_count = 2, .items = hub_desc_items,
485
.array_count = 1, .arrays = hub_desc_arys,
486
.cleanup = ipmi_mr_struct_cleanup
488
static ipmi_mr_item_layout_t rad_ipmb_items[] = {
489
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
490
.start = 0, .length = 1,
491
.set_field = NULL, .get_field = ipmi_mr_int_get_field },
492
{ .name = "connecter definer", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
493
.start = 1, .length = 3,
494
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
495
{ .name = "connecter version", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
496
.start = 4, .length = 2,
497
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
499
static ipmi_mr_array_layout_t rad_ipmb_arys[] = {
500
{ .name = "hub descriptors", .has_count = 1, .settable = 1,
502
.elem_layout = &hub_descs,
503
.elem_check = ipmi_mr_struct_elem_check,
504
.elem_decode = ipmi_mr_struct_decode,
505
.cleanup = ipmi_mr_struct_array_cleanup,
506
.get_field = ipmi_mr_struct_array_get_field,
507
.set_field = ipmi_mr_struct_array_set_field }
509
static ipmi_mr_struct_layout_t rad_ipmb = {
510
.name = "Radial IPMB-0 Link Mapping", .length = 6,
511
.item_count = 3, .items = rad_ipmb_items,
512
.array_count = 1, .arrays = rad_ipmb_arys,
513
.cleanup = ipmi_mr_struct_cleanup
516
/***********************************************************************
518
* Shelf fan geography record
520
**********************************************************************/
522
static ipmi_mr_item_layout_t fan_to_frus_items[] = {
523
{ .name = "hardware address", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
524
.start = 0, .length = 1,
525
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
526
{ .name = "FRU device id", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
527
.start = 1, .length = 1,
528
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
529
{ .name = "site number", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
530
.start = 2, .length = 1,
531
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field },
532
{ .name = "site type", .dtype = IPMI_FRU_DATA_INT, .settable = 1,
533
.start = 3, .length = 1,
534
.set_field = ipmi_mr_int_set_field, .get_field = ipmi_mr_int_get_field }
536
static ipmi_mr_struct_layout_t fan_to_frus = {
537
.name = NULL, .length = 4,
538
.item_count = 4, .items = fan_to_frus_items,
539
.array_count = 0, .arrays = NULL,
540
.cleanup = ipmi_mr_struct_cleanup
542
static ipmi_mr_item_layout_t fan_geog_items[] = {
543
{ .name = "version", .dtype = IPMI_FRU_DATA_INT, .settable = 0,
544
.start = 0, .length = 1,
545
.set_field = NULL, .get_field = ipmi_mr_int_get_field }
547
static ipmi_mr_array_layout_t fan_geog_arys[] = {
548
{ .name = "fan to frus", .has_count = 1, .settable = 1,
550
.elem_layout = &fan_to_frus,
551
.elem_check = ipmi_mr_struct_elem_check,
552
.elem_decode = ipmi_mr_struct_decode,
553
.cleanup = ipmi_mr_struct_array_cleanup,
554
.get_field = ipmi_mr_struct_array_get_field,
555
.set_field = ipmi_mr_struct_array_set_field }
557
static ipmi_mr_struct_layout_t fan_geog = {
558
.name = "Shelf Fan Geography", .length = 1,
559
.item_count = 1, .items = fan_geog_items,
560
.array_count = 1, .arrays = fan_geog_arys,
561
.cleanup = ipmi_mr_struct_cleanup
565
/***********************************************************************
567
* Initialization code
569
**********************************************************************/
742
_ipmi_atca_fru_get_mr_root(ipmi_fru_t *fru,
743
unsigned int manufacturer_id,
744
unsigned char record_type_id,
745
unsigned char *mr_data,
746
unsigned int mr_data_len,
749
ipmi_fru_node_t **node)
572
_ipmi_atca_fru_get_mr_root(ipmi_fru_t *fru,
573
unsigned int mr_rec_num,
574
unsigned int manufacturer_id,
575
unsigned char record_type_id,
576
unsigned char *mr_data,
577
unsigned int mr_data_len,
580
ipmi_fru_node_t **node)
751
582
/* A record type and version number. */
752
583
if (mr_data_len < 5)