13798Seschrock /* 23798Seschrock * CDDL HEADER START 33798Seschrock * 43798Seschrock * The contents of this file are subject to the terms of the 53798Seschrock * Common Development and Distribution License (the "License"). 63798Seschrock * You may not use this file except in compliance with the License. 73798Seschrock * 83798Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93798Seschrock * or http://www.opensolaris.org/os/licensing. 103798Seschrock * See the License for the specific language governing permissions 113798Seschrock * and limitations under the License. 123798Seschrock * 133798Seschrock * When distributing Covered Code, include this CDDL HEADER in each 143798Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153798Seschrock * If applicable, add the following below this CDDL HEADER, with the 163798Seschrock * fields enclosed by brackets "[]" replaced with your own identifying 173798Seschrock * information: Portions Copyright [yyyy] [name of copyright owner] 183798Seschrock * 193798Seschrock * CDDL HEADER END 203798Seschrock */ 213798Seschrock /* 226070Srobj * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233798Seschrock * Use is subject to license terms. 243798Seschrock */ 253798Seschrock 263798Seschrock #pragma ident "%Z%%M% %I% %E% SMI" 273798Seschrock 283798Seschrock #include <libipmi.h> 296070Srobj #include <stdio.h> 303798Seschrock #include <string.h> 313798Seschrock 323798Seschrock #include "ipmi_impl.h" 333798Seschrock 343798Seschrock ipmi_deviceid_t * 353798Seschrock ipmi_get_deviceid(ipmi_handle_t *ihp) 363798Seschrock { 373798Seschrock ipmi_cmd_t cmd, *resp; 38*6360Srobj uint16_t id_prod; 393798Seschrock 406070Srobj if (ihp->ih_deviceid != NULL) 416070Srobj return (ihp->ih_deviceid); 423798Seschrock 433798Seschrock cmd.ic_netfn = IPMI_NETFN_APP; 443798Seschrock cmd.ic_lun = 0; 453798Seschrock cmd.ic_cmd = IPMI_CMD_GET_DEVICEID; 463798Seschrock cmd.ic_data = NULL; 473798Seschrock cmd.ic_dlen = 0; 483798Seschrock 493798Seschrock if ((resp = ipmi_send(ihp, &cmd)) == NULL) 503798Seschrock return (NULL); 513798Seschrock 523798Seschrock if (resp->ic_dlen < sizeof (ipmi_deviceid_t)) { 533798Seschrock (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 543798Seschrock return (NULL); 553798Seschrock } 563798Seschrock 576070Srobj /* 586070Srobj * The devid response data may include additional data beyond the end of 596070Srobj * the normal structure, so we copy the entire response. 606070Srobj */ 616070Srobj if ((ihp->ih_deviceid = ipmi_alloc(ihp, resp->ic_dlen)) == NULL) 626070Srobj return (NULL); 636070Srobj 646070Srobj (void) memcpy(ihp->ih_deviceid, resp->ic_data, resp->ic_dlen); 65*6360Srobj id_prod = LE_IN16(&ihp->ih_deviceid->id_product); 66*6360Srobj (void) memcpy(&id_prod, &ihp->ih_deviceid->id_product, 67*6360Srobj sizeof (id_prod)); 686070Srobj ihp->ih_deviceid_len = resp->ic_dlen; 696070Srobj 706070Srobj return (ihp->ih_deviceid); 716070Srobj } 726070Srobj 736070Srobj /* 746070Srobj * Returns the firmware revision as a string. This does the work of converting 756070Srobj * the deviceid data into a human readable string (decoding the BCD values). 766070Srobj * It also encodes the fact that Sun ILOM includes the additional micro revision 776070Srobj * at the end of the deviceid information. 786070Srobj */ 796070Srobj const char * 806070Srobj ipmi_firmware_version(ipmi_handle_t *ihp) 816070Srobj { 826070Srobj ipmi_deviceid_t *dp; 836070Srobj uint8_t *auxrev; 846070Srobj size_t len; 856070Srobj char rev[128]; 866070Srobj int i; 876070Srobj 886070Srobj if (ihp->ih_firmware_rev != NULL) 896070Srobj return (ihp->ih_firmware_rev); 903798Seschrock 916070Srobj if ((dp = ipmi_get_deviceid(ihp)) == NULL) 926070Srobj return (NULL); 936070Srobj 946070Srobj /* 956070Srobj * Start with the major an minor revision numbers 966070Srobj */ 976070Srobj (void) snprintf(rev, sizeof (rev), "%d.%d", dp->id_firm_major, 986070Srobj ipmi_convert_bcd(dp->id_firm_minor)); 996070Srobj 1006070Srobj if (ipmi_is_sun_ilom(dp) && 1016070Srobj ihp->ih_deviceid_len >= sizeof (ipmi_deviceid_t) + 4) { 1026070Srobj /* 1036070Srobj * With Sun ILOM we have the micro revision at the end of the 1046070Srobj * deviceid. The first two bytes of the aux revision field are 1056070Srobj * the platform version and release version. 1066070Srobj */ 1076070Srobj auxrev = (uint8_t *)dp + sizeof (ipmi_deviceid_t); 1086070Srobj for (i = 0; i < 2; i++) { 1096070Srobj if (auxrev[i] == 0) 1106070Srobj continue; 1116070Srobj 1126070Srobj len = strlen(rev); 1136070Srobj (void) snprintf(rev + len, sizeof (rev) - len, ".%u", 1146070Srobj auxrev[i]); 1156070Srobj } 1166070Srobj } 1176070Srobj 1186070Srobj if ((ihp->ih_firmware_rev = ipmi_strdup(ihp, rev)) == NULL) 1196070Srobj return (NULL); 1206070Srobj 1216070Srobj return (ihp->ih_firmware_rev); 1223798Seschrock } 123