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 /* 22*6070Srobj * 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> 29*6070Srobj #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; 383798Seschrock 39*6070Srobj if (ihp->ih_deviceid != NULL) 40*6070Srobj return (ihp->ih_deviceid); 413798Seschrock 423798Seschrock cmd.ic_netfn = IPMI_NETFN_APP; 433798Seschrock cmd.ic_lun = 0; 443798Seschrock cmd.ic_cmd = IPMI_CMD_GET_DEVICEID; 453798Seschrock cmd.ic_data = NULL; 463798Seschrock cmd.ic_dlen = 0; 473798Seschrock 483798Seschrock if ((resp = ipmi_send(ihp, &cmd)) == NULL) 493798Seschrock return (NULL); 503798Seschrock 513798Seschrock if (resp->ic_dlen < sizeof (ipmi_deviceid_t)) { 523798Seschrock (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 533798Seschrock return (NULL); 543798Seschrock } 553798Seschrock 56*6070Srobj /* 57*6070Srobj * The devid response data may include additional data beyond the end of 58*6070Srobj * the normal structure, so we copy the entire response. 59*6070Srobj */ 60*6070Srobj if ((ihp->ih_deviceid = ipmi_alloc(ihp, resp->ic_dlen)) == NULL) 61*6070Srobj return (NULL); 62*6070Srobj 63*6070Srobj (void) memcpy(ihp->ih_deviceid, resp->ic_data, resp->ic_dlen); 64*6070Srobj ihp->ih_deviceid->id_product = LE_16(ihp->ih_deviceid->id_product); 65*6070Srobj ihp->ih_deviceid_len = resp->ic_dlen; 66*6070Srobj 67*6070Srobj return (ihp->ih_deviceid); 68*6070Srobj } 69*6070Srobj 70*6070Srobj /* 71*6070Srobj * Returns the firmware revision as a string. This does the work of converting 72*6070Srobj * the deviceid data into a human readable string (decoding the BCD values). 73*6070Srobj * It also encodes the fact that Sun ILOM includes the additional micro revision 74*6070Srobj * at the end of the deviceid information. 75*6070Srobj */ 76*6070Srobj const char * 77*6070Srobj ipmi_firmware_version(ipmi_handle_t *ihp) 78*6070Srobj { 79*6070Srobj ipmi_deviceid_t *dp; 80*6070Srobj uint8_t *auxrev; 81*6070Srobj size_t len; 82*6070Srobj char rev[128]; 83*6070Srobj int i; 84*6070Srobj 85*6070Srobj if (ihp->ih_firmware_rev != NULL) 86*6070Srobj return (ihp->ih_firmware_rev); 873798Seschrock 88*6070Srobj if ((dp = ipmi_get_deviceid(ihp)) == NULL) 89*6070Srobj return (NULL); 90*6070Srobj 91*6070Srobj /* 92*6070Srobj * Start with the major an minor revision numbers 93*6070Srobj */ 94*6070Srobj (void) snprintf(rev, sizeof (rev), "%d.%d", dp->id_firm_major, 95*6070Srobj ipmi_convert_bcd(dp->id_firm_minor)); 96*6070Srobj 97*6070Srobj if (ipmi_is_sun_ilom(dp) && 98*6070Srobj ihp->ih_deviceid_len >= sizeof (ipmi_deviceid_t) + 4) { 99*6070Srobj /* 100*6070Srobj * With Sun ILOM we have the micro revision at the end of the 101*6070Srobj * deviceid. The first two bytes of the aux revision field are 102*6070Srobj * the platform version and release version. 103*6070Srobj */ 104*6070Srobj auxrev = (uint8_t *)dp + sizeof (ipmi_deviceid_t); 105*6070Srobj for (i = 0; i < 2; i++) { 106*6070Srobj if (auxrev[i] == 0) 107*6070Srobj continue; 108*6070Srobj 109*6070Srobj len = strlen(rev); 110*6070Srobj (void) snprintf(rev + len, sizeof (rev) - len, ".%u", 111*6070Srobj auxrev[i]); 112*6070Srobj } 113*6070Srobj } 114*6070Srobj 115*6070Srobj if ((ihp->ih_firmware_rev = ipmi_strdup(ihp, rev)) == NULL) 116*6070Srobj return (NULL); 117*6070Srobj 118*6070Srobj return (ihp->ih_firmware_rev); 1193798Seschrock } 120