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