1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <libipmi.h> 29 #include <stdio.h> 30 #include <string.h> 31 32 #include "ipmi_impl.h" 33 34 ipmi_deviceid_t * 35 ipmi_get_deviceid(ipmi_handle_t *ihp) 36 { 37 ipmi_cmd_t cmd, *resp; 38 uint16_t id_prod; 39 40 if (ihp->ih_deviceid != NULL) 41 return (ihp->ih_deviceid); 42 43 cmd.ic_netfn = IPMI_NETFN_APP; 44 cmd.ic_lun = 0; 45 cmd.ic_cmd = IPMI_CMD_GET_DEVICEID; 46 cmd.ic_data = NULL; 47 cmd.ic_dlen = 0; 48 49 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 50 return (NULL); 51 52 if (resp->ic_dlen < sizeof (ipmi_deviceid_t)) { 53 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 54 return (NULL); 55 } 56 57 /* 58 * The devid response data may include additional data beyond the end of 59 * the normal structure, so we copy the entire response. 60 */ 61 if ((ihp->ih_deviceid = ipmi_alloc(ihp, resp->ic_dlen)) == NULL) 62 return (NULL); 63 64 (void) memcpy(ihp->ih_deviceid, resp->ic_data, resp->ic_dlen); 65 id_prod = LE_IN16(&ihp->ih_deviceid->id_product); 66 (void) memcpy(&ihp->ih_deviceid->id_product, &id_prod, 67 sizeof (id_prod)); 68 ihp->ih_deviceid_len = resp->ic_dlen; 69 70 return (ihp->ih_deviceid); 71 } 72 73 /* 74 * Returns the firmware revision as a string. This does the work of converting 75 * the deviceid data into a human readable string (decoding the BCD values). 76 * It also encodes the fact that Sun ILOM includes the additional micro revision 77 * at the end of the deviceid information. 78 */ 79 const char * 80 ipmi_firmware_version(ipmi_handle_t *ihp) 81 { 82 ipmi_deviceid_t *dp; 83 uint8_t *auxrev; 84 size_t len; 85 char rev[128]; 86 int i; 87 88 if (ihp->ih_firmware_rev != NULL) 89 return (ihp->ih_firmware_rev); 90 91 if ((dp = ipmi_get_deviceid(ihp)) == NULL) 92 return (NULL); 93 94 /* 95 * Start with the major an minor revision numbers 96 */ 97 (void) snprintf(rev, sizeof (rev), "%d.%d", dp->id_firm_major, 98 ipmi_convert_bcd(dp->id_firm_minor)); 99 100 if (ipmi_is_sun_ilom(dp) && 101 ihp->ih_deviceid_len >= sizeof (ipmi_deviceid_t) + 4) { 102 /* 103 * With Sun ILOM we have the micro revision at the end of the 104 * deviceid. The first two bytes of the aux revision field are 105 * the platform version and release version. 106 */ 107 auxrev = (uint8_t *)dp + sizeof (ipmi_deviceid_t); 108 for (i = 0; i < 2; i++) { 109 if (auxrev[i] == 0) 110 continue; 111 112 len = strlen(rev); 113 (void) snprintf(rev + len, sizeof (rev) - len, ".%u", 114 auxrev[i]); 115 } 116 } 117 118 if ((ihp->ih_firmware_rev = ipmi_strdup(ihp, rev)) == NULL) 119 return (NULL); 120 121 return (ihp->ih_firmware_rev); 122 } 123