handle errors gracefully,

check values before malloc,
add external function for entity association lookups
This commit is contained in:
Duncan Laurie 2004-11-17 23:16:44 +00:00
parent 7723fb41b3
commit a87957ac7f

View File

@ -76,6 +76,8 @@ static char * get_fru_area_str(unsigned char * data, int * offset)
size = len; /* (no length adjustment) */ size = len; /* (no length adjustment) */
} }
if (size < 1)
return NULL;
str = malloc(size+1); str = malloc(size+1);
if (!str) if (!str)
return NULL; return NULL;
@ -85,7 +87,7 @@ static char * get_fru_area_str(unsigned char * data, int * offset)
else { else {
switch(k) { switch(k) {
case 0: case 0:
strcpy(str, buf2str(&data[off], len)); strncpy(str, buf2str(&data[off], len));
break; break;
case 1: case 1:
@ -140,9 +142,20 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, unsigned char id,
struct ipmi_rq req; struct ipmi_rq req;
unsigned char msg_data[4]; unsigned char msg_data[4];
finish = offset + length; if (offset > fru->size) {
if (finish > fru->size) if (verbose)
printf("Read FRU Area offset incorrect: %d > %d\n",
offset, fru->size);
return -1; return -1;
}
finish = offset + length;
if (finish > fru->size) {
finish = fru->size;
if (verbose)
printf("Read FRU Area length %d too large, adjusting to %d\n",
offset + length, finish - offset);
}
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.netfn = IPMI_NETFN_STORAGE;
@ -155,7 +168,7 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, unsigned char id,
do { do {
tmp = fru->access ? off >> 1 : off; tmp = fru->access ? off >> 1 : off;
msg_data[0] = id; msg_data[0] = id;
msg_data[1] = (unsigned char)tmp; msg_data[1] = (unsigned char)(tmp & 0xff);
msg_data[2] = (unsigned char)(tmp >> 8); msg_data[2] = (unsigned char)(tmp >> 8);
tmp = finish - off; tmp = finish - off;
if (tmp > fru_data_rqst_size) if (tmp > fru_data_rqst_size)
@ -164,12 +177,23 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, unsigned char id,
msg_data[3] = (unsigned char)tmp; msg_data[3] = (unsigned char)tmp;
rsp = intf->sendrecv(intf, &req); rsp = intf->sendrecv(intf, &req);
if (!rsp) if (!rsp) {
if (verbose)
printf("FRU Read failed\n");
break; break;
if ((rsp->ccode==0xc7 || rsp->ccode==0xc8) && --fru_data_rqst_size > 8) }
if (rsp->ccode) {
if (verbose)
printf("FRU Read failed: %s\n",
val2str(rsp->ccode, completion_code_vals));
if ((rsp->ccode==0xc7 || rsp->ccode==0xc8) && --fru_data_rqst_size > 8) {
if (verbose)
printf("Retrying FRU read with request size %d\n",
fru_data_rqst_size);
continue; continue;
if (rsp->ccode) }
break; break;
}
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0]; tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
memcpy((frubuf + off), rsp->data + 1, tmp); memcpy((frubuf + off), rsp->data + 1, tmp);
@ -179,7 +203,7 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, unsigned char id,
return (off >= finish); return (off >= finish);
} }
static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id) static void __ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
{ {
struct ipmi_rs * rsp; struct ipmi_rs * rsp;
struct ipmi_rq req; struct ipmi_rq req;
@ -212,13 +236,13 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
req.msg.data_len = 1; req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req); rsp = intf->sendrecv(intf, &req);
if (!rsp) if (!rsp) {
printf(" Device not present (No Response)\n");
return; return;
}
if(rsp->ccode) if(rsp->ccode) {
{ printf(" Device not present (%s)\n",
if (rsp->ccode == 0xc3) val2str(rsp->ccode, completion_code_vals));
printf (" Timeout accessing FRU info. (Device not present?)\n");
return; return;
} }
fru.size = (rsp->data[1] << 8) | rsp->data[0]; fru.size = (rsp->data[1] << 8) | rsp->data[0];
@ -227,8 +251,10 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
if (verbose > 1) if (verbose > 1)
printf("fru.size = %d bytes (accessed by %s)\n", printf("fru.size = %d bytes (accessed by %s)\n",
fru.size, fru.access ? "words" : "bytes"); fru.size, fru.access ? "words" : "bytes");
if (!fru.size) if (!fru.size) {
printf(" FRU size is zero!\n");
return; return;
}
msg_data[0] = id; msg_data[0] = id;
msg_data[1] = 0; msg_data[1] = 0;
@ -246,10 +272,13 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
if (!rsp) if (!rsp)
return; return;
if(rsp->ccode) if (!rsp) {
{ printf(" Device not present (No Response)\n");
if (rsp->ccode == 0xc3) return;
printf (" Timeout while reading FRU data. (Device not present?)\n"); }
if(rsp->ccode) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
return; return;
} }
@ -279,6 +308,8 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
printf("fru.header.offset.multi: 0x%x\n", area_offsets[OFF_MULTI]); printf("fru.header.offset.multi: 0x%x\n", area_offsets[OFF_MULTI]);
} }
if (fru.size < 1)
return;
fru_data = malloc(fru.size+1); fru_data = malloc(fru.size+1);
if (!fru_data) if (!fru_data)
return; return;
@ -303,7 +334,9 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
chassis.serial = get_fru_area_str(fru_data, &i); chassis.serial = get_fru_area_str(fru_data, &i);
printf(" Chassis Type : %s\n", chassis_type_desc[chassis.type]); printf(" Chassis Type : %s\n", chassis_type_desc[chassis.type]);
printf(" Chassis Part : %s\n", chassis.part); if (strlen(chassis.part) > 0)
printf(" Chassis Part Number : %s\n", chassis.part);
if (strlen(chassis.serial) > 0)
printf(" Chassis Serial : %s\n", chassis.serial); printf(" Chassis Serial : %s\n", chassis.serial);
while (fru_data[i] != 0xc1 && i < area_offsets[OFF_CHASSIS] + chassis.area_len) while (fru_data[i] != 0xc1 && i < area_offsets[OFF_CHASSIS] + chassis.area_len)
@ -340,12 +373,16 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
board.part = get_fru_area_str(fru_data, &i); board.part = get_fru_area_str(fru_data, &i);
board.fru = get_fru_area_str(fru_data, &i); board.fru = get_fru_area_str(fru_data, &i);
printf(" Board Mfg : %s\n", board.mfg); if (strlen(board.mfg) > 0)
printf(" Board Manufacturer : %s\n", board.mfg);
if (strlen(board.prod) > 0)
printf(" Board Product : %s\n", board.prod); printf(" Board Product : %s\n", board.prod);
if (strlen(board.serial) > 0)
printf(" Board Serial : %s\n", board.serial); printf(" Board Serial : %s\n", board.serial);
printf(" Board Part : %s\n", board.part); if (strlen(board.part) > 0)
printf(" Board Part Number : %s\n", board.part);
if (verbose > 0) if ((verbose > 0) && (strlen(board.fru) > 0))
printf(" Board FRU ID : %s\n", board.fru); printf(" Board FRU ID : %s\n", board.fru);
while (fru_data[i] != 0xc1 && i < area_offsets[OFF_BOARD] + board.area_len) while (fru_data[i] != 0xc1 && i < area_offsets[OFF_BOARD] + board.area_len)
@ -386,14 +423,20 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
product.asset = get_fru_area_str(fru_data, &i); product.asset = get_fru_area_str(fru_data, &i);
product.fru = get_fru_area_str(fru_data, &i); product.fru = get_fru_area_str(fru_data, &i);
printf(" Product Mfg : %s\n", product.mfg); if (strlen(product.mfg) > 0)
printf(" Product Manufacturer : %s\n", product.mfg);
if (strlen(product.name) > 0)
printf(" Product Name : %s\n", product.name); printf(" Product Name : %s\n", product.name);
printf(" Product Part : %s\n", product.part); if (strlen(product.part) > 0)
printf(" Product Part Number : %s\n", product.part);
if (strlen(product.version) > 0)
printf(" Product Version : %s\n", product.version); printf(" Product Version : %s\n", product.version);
if (strlen(product.serial) > 0)
printf(" Product Serial : %s\n", product.serial); printf(" Product Serial : %s\n", product.serial);
printf(" Product Asset : %s\n", product.asset); if (strlen(product.asset) > 0)
printf(" Product Asset Tag : %s\n", product.asset);
if (verbose > 0) if ((verbose > 0) && (strlen(product.fru) > 0))
printf(" Product FRU ID : %s\n", product.fru); printf(" Product FRU ID : %s\n", product.fru);
while (fru_data[i] != 0xc1 && i < area_offsets[OFF_PRODUCT] + product.area_len) while (fru_data[i] != 0xc1 && i < area_offsets[OFF_PRODUCT] + product.area_len)
@ -443,7 +486,7 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
if (read_fru_area(intf, &fru, id, last_off, len, fru_data) > 0) if (read_fru_area(intf, &fru, id, last_off, len, fru_data) > 0)
last_off += len; last_off += len;
else { else {
printf("ERROR: reading FRU data\n"); printf("ERROR: reading FRU multirecord data\n");
break; break;
} }
} }
@ -548,16 +591,66 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
free(fru_data); free(fru_data);
} }
void ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
{
char desc[17];
unsigned char sav_addr;
if (!fru) {
__ipmi_fru_print(intf, 0);
return;
}
if (fru->dev_type != 0x10 &&
(fru->dev_type_modifier != 0x02 ||
fru->dev_type < 0x08 || fru->dev_type > 0x0f))
return;
memset(desc, 0, sizeof(desc));
memcpy(desc, fru->id_string, fru->id_code & 0x01f);
desc[fru->id_code & 0x01f] = 0;
printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
switch (fru->dev_type_modifier) {
case 0x00:
case 0x02:
sav_addr = intf->target_addr;
intf->target_addr = fru->dev_slave_addr;
if (intf->target_addr == IPMI_BMC_SLAVE_ADDR &&
fru->device_id == 0)
printf(" (Builtin FRU device)\n");
else
__ipmi_fru_print(intf, fru->device_id);
intf->target_addr = sav_addr;
break;
case 0x01:
ipmi_spd_print(intf, fru->device_id);
break;
default:
if (verbose)
printf(" Unsupported device 0x%02x "
"type 0x%02x with modifier 0x%02x\n",
fru->device_id, fru->dev_type,
fru->dev_type_modifier);
else
printf(" Unsupported device\n");
}
printf("\n");
}
static void ipmi_fru_print_all(struct ipmi_intf * intf) static void ipmi_fru_print_all(struct ipmi_intf * intf)
{ {
struct ipmi_sdr_iterator * itr; struct ipmi_sdr_iterator * itr;
struct sdr_get_rs * header; struct sdr_get_rs * header;
struct sdr_record_fru_device_locator * fru; struct sdr_record_fru_locator * fru;
char desc[17]; char desc[17];
unsigned char sav_addr; unsigned char sav_addr;
printf ("Builtin FRU device\n"); printf("FRU Device Description : Builtin FRU Device (ID 0)\n");
ipmi_fru_print(intf, 0); /* TODO: Figure out if FRU device 0 may show up in SDR records. */ ipmi_fru_print(intf, NULL); /* TODO: Figure out if FRU device 0 may show up in SDR records. */
printf("\n");
if (!(itr = ipmi_sdr_start(intf))) if (!(itr = ipmi_sdr_start(intf)))
return; return;
@ -567,47 +660,10 @@ static void ipmi_fru_print_all(struct ipmi_intf * intf)
if (header->type != SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR) if (header->type != SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR)
continue; continue;
fru = (struct sdr_record_fru_device_locator *) ipmi_sdr_get_record(intf, header, itr); fru = (struct sdr_record_fru_locator *)ipmi_sdr_get_record(intf, header, itr);
if (!fru) if (!fru)
continue; continue;
if (fru->device_type != 0x10 ipmi_fru_print(intf, fru);
&& (fru->device_type_modifier != 0x02
|| fru->device_type < 0x08 || fru->device_type > 0x0f))
continue;
memset(desc, 0, sizeof(desc));
memcpy(desc, fru->id_string, fru->id_code & 0x01f);
desc[fru->id_code & 0x01f] = 0;
printf("\nFRU Device Description: %s Device ID: %d\n", desc, fru->keys.fru_device_id);
switch (fru->device_type_modifier) {
case 0x00:
case 0x02:
sav_addr = intf->target_addr;
intf->target_addr = ((fru->keys.dev_access_addr << 1)
| (fru->keys.__reserved2 << 7));
if (intf->target_addr == IPMI_BMC_SLAVE_ADDR
&& fru->keys.fru_device_id == 0)
printf(" (Builtin FRU device)\n");
else
ipmi_fru_print(intf, fru->keys.fru_device_id);
intf->target_addr = sav_addr;
break;
case 0x01:
ipmi_spd_print(intf, fru->keys.fru_device_id);
break;
default:
if (verbose)
printf(" Unsupported device 0x%02x "
"type 0x%02x with modifier 0x%02x\n",
fru->keys.fru_device_id, fru->device_type,
fru->device_type_modifier);
else
printf(" Unsupported device\n");
}
free(fru); free(fru);
} }