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 #include <libipmi.h> 27 #include <stdio.h> 28 #include <string.h> 29 30 #include "ipmi_impl.h" 31 32 ipmi_deviceid_t * 33 ipmi_get_deviceid(ipmi_handle_t *ihp) 34 { 35 ipmi_cmd_t cmd, *resp; 36 uint16_t id_prod; 37 38 if (ihp->ih_deviceid != NULL) 39 return (ihp->ih_deviceid); 40 41 cmd.ic_netfn = IPMI_NETFN_APP; 42 cmd.ic_lun = 0; 43 cmd.ic_cmd = IPMI_CMD_GET_DEVICEID; 44 cmd.ic_data = NULL; 45 cmd.ic_dlen = 0; 46 47 if ((resp = ipmi_send(ihp, &cmd)) == NULL) 48 return (NULL); 49 50 if (resp->ic_dlen < sizeof (ipmi_deviceid_t)) { 51 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 52 return (NULL); 53 } 54 55 /* 56 * The devid response data may include additional data beyond the end of 57 * the normal structure, so we copy the entire response. 58 */ 59 if ((ihp->ih_deviceid = ipmi_alloc(ihp, resp->ic_dlen)) == NULL) 60 return (NULL); 61 62 (void) memcpy(ihp->ih_deviceid, resp->ic_data, resp->ic_dlen); 63 id_prod = LE_IN16(&ihp->ih_deviceid->id_product); 64 (void) memcpy(&ihp->ih_deviceid->id_product, &id_prod, 65 sizeof (id_prod)); 66 ihp->ih_deviceid_len = resp->ic_dlen; 67 68 return (ihp->ih_deviceid); 69 } 70 71 /* 72 * Returns the firmware revision as a string. This does the work of converting 73 * the deviceid data into a human readable string (decoding the BCD values). 74 * It also encodes the fact that Sun ILOM includes the additional micro revision 75 * at the end of the deviceid information. 76 */ 77 const char * 78 ipmi_firmware_version(ipmi_handle_t *ihp) 79 { 80 ipmi_deviceid_t *dp; 81 uint8_t *auxrev; 82 size_t len; 83 char rev[128]; 84 int i; 85 86 if (ihp->ih_firmware_rev != NULL) 87 return (ihp->ih_firmware_rev); 88 89 if ((dp = ipmi_get_deviceid(ihp)) == NULL) 90 return (NULL); 91 92 /* 93 * Start with the major an minor revision numbers 94 */ 95 (void) snprintf(rev, sizeof (rev), "%d.%d", dp->id_firm_major, 96 ipmi_convert_bcd(dp->id_firm_minor)); 97 98 if (ipmi_is_sun_ilom(dp) && 99 ihp->ih_deviceid_len >= sizeof (ipmi_deviceid_t) + 4) { 100 /* 101 * With Sun ILOM we have the micro revision at the end of the 102 * deviceid. The first two bytes of the aux revision field are 103 * the platform version and release version. 104 */ 105 auxrev = (uint8_t *)dp + sizeof (ipmi_deviceid_t); 106 for (i = 0; i < 2; i++) { 107 if (auxrev[i] == 0) 108 continue; 109 110 len = strlen(rev); 111 (void) snprintf(rev + len, sizeof (rev) - len, ".%u", 112 auxrev[i]); 113 } 114 } 115 116 if ((ihp->ih_firmware_rev = ipmi_strdup(ihp, rev)) == NULL) 117 return (NULL); 118 119 return (ihp->ih_firmware_rev); 120 } 121 122 ipmi_channel_info_t * 123 ipmi_get_channel_info(ipmi_handle_t *ihp, int number) 124 { 125 ipmi_cmd_t cmd, *rsp; 126 uint8_t channel; 127 128 if (number > 0xF) { 129 (void) ipmi_set_error(ihp, EIPMI_INVALID_REQUEST, NULL); 130 return (NULL); 131 } 132 133 channel = (uint8_t)number; 134 135 cmd.ic_netfn = IPMI_NETFN_APP; 136 cmd.ic_lun = 0; 137 cmd.ic_cmd = IPMI_CMD_GET_CHANNEL_INFO; 138 cmd.ic_data = &channel; 139 cmd.ic_dlen = sizeof (channel); 140 141 if ((rsp = ipmi_send(ihp, &cmd)) == NULL) 142 return (NULL); 143 144 if (rsp->ic_dlen < sizeof (ipmi_channel_info_t)) { 145 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL); 146 return (NULL); 147 } 148 149 return (rsp->ic_data); 150 } 151