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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include "ipmi_impl.h"
37 * Extracts bits between index h (high, inclusive) and l (low, exclusive) from
38 * u, which must be an unsigned integer.
40 #define BITX(u, h, l) (((u) >> (l)) & ((1LU << ((h) - (l) + 1LU)) - 1LU))
46 ipmi_set_error(ipmi_handle_t
*ihp
, int error
, const char *fmt
, ...)
52 ihp
->ih_errno
= error
;
54 ihp
->ih_errmsg
[0] = '\0';
56 (void) vsnprintf(ihp
->ih_errmsg
, sizeof (ihp
->ih_errmsg
),
64 ipmi_errno(ipmi_handle_t
*ihp
)
66 return (ihp
->ih_errno
);
71 ipmi_errmsg(ipmi_handle_t
*ihp
)
77 for (i
= 0; ipmi_errno_table
[i
].int_name
!= NULL
; i
++) {
78 if (ipmi_errno_table
[i
].int_value
== ihp
->ih_errno
) {
79 str
= ipmi_errno_table
[i
].int_name
;
84 if (str
== NULL
&& (str
= strerror(ihp
->ih_errno
)) == NULL
)
85 str
= "unknown failure";
87 if (ihp
->ih_errmsg
[0] == '\0')
90 (void) snprintf(ihp
->ih_errbuf
, sizeof (ihp
->ih_errbuf
),
91 "%s: %s", str
, ihp
->ih_errmsg
);
92 return (ihp
->ih_errbuf
);
99 ipmi_alloc(ipmi_handle_t
*ihp
, size_t size
)
103 if ((ptr
= malloc(size
)) == NULL
)
104 (void) ipmi_set_error(ihp
, EIPMI_NOMEM
, NULL
);
110 ipmi_zalloc(ipmi_handle_t
*ihp
, size_t size
)
114 if ((ptr
= calloc(size
, 1)) == NULL
)
115 (void) ipmi_set_error(ihp
, EIPMI_NOMEM
, NULL
);
121 ipmi_strdup(ipmi_handle_t
*ihp
, const char *str
)
125 if ((ptr
= strdup(str
)) == NULL
)
126 (void) ipmi_set_error(ihp
, EIPMI_NOMEM
, NULL
);
133 ipmi_free(ipmi_handle_t
*ihp
, void *ptr
)
139 * Translation between #defines and strings.
142 ipmi_entity_name(uint8_t id
, char *buf
, size_t len
)
144 ipmi_name_trans_t
*ntp
;
146 for (ntp
= &ipmi_entity_table
[0]; ntp
->int_name
!= NULL
; ntp
++) {
147 if (ntp
->int_value
== id
) {
148 (void) strlcpy(buf
, ntp
->int_name
, len
);
153 (void) snprintf(buf
, len
, "0x%02x", id
);
157 ipmi_sensor_type_name(uint8_t type
, char *buf
, size_t len
)
159 ipmi_name_trans_t
*ntp
;
161 for (ntp
= &ipmi_sensor_type_table
[0]; ntp
->int_name
!= NULL
; ntp
++) {
162 if (ntp
->int_value
== type
) {
163 (void) strlcpy(buf
, ntp
->int_name
, len
);
168 (void) snprintf(buf
, len
, "0x%02x", type
);
172 ipmi_sensor_units_name(uint8_t type
, char *buf
, size_t len
)
174 ipmi_name_trans_t
*ntp
;
176 for (ntp
= &ipmi_units_type_table
[0]; ntp
->int_name
!= NULL
; ntp
++) {
177 if (ntp
->int_value
== type
) {
178 (void) strlcpy(buf
, ntp
->int_name
, len
);
183 (void) snprintf(buf
, len
, "0x%02x", type
);
187 ipmi_sensor_reading_name(uint8_t sensor_type
, uint8_t reading_type
,
188 char *buf
, size_t len
)
191 ipmi_name_trans_t
*ntp
;
193 if (reading_type
== IPMI_RT_SPECIFIC
) {
195 ntp
= &ipmi_sensor_type_table
[0];
198 ntp
= &ipmi_reading_type_table
[0];
201 for (; ntp
->int_name
!= NULL
; ntp
++) {
202 if (ntp
->int_value
== val
) {
203 (void) strlcpy(buf
, ntp
->int_name
, len
);
208 if (reading_type
== IPMI_RT_SPECIFIC
)
209 (void) snprintf(buf
, len
, "%02x/%02x", reading_type
,
212 (void) snprintf(buf
, len
, "%02x", reading_type
);
216 * Converts a BCD decimal value to an integer.
219 ipmi_convert_bcd(int value
)
225 for (i
= 7; i
>= 0; i
--) {
226 digit
= ((value
& (0xf << (i
* 4))) >> (i
* 4));
227 ret
+= digit
* 10 * i
;
234 * See sections 43.15 and 43.16
236 * This is a utility function for decoding the strings that are packed into
237 * sensor data records. If the type is 6-bit packed ASCII, then it converts
238 * the string to an 8-bit ASCII string and copies that into the suuplied buffer.
239 * If it is 8-bit ASCII, it copies the string into the supplied buffer as-is.
242 ipmi_decode_string(uint8_t type
, uint8_t len
, char *data
, char *buf
)
244 int i
, j
= 0, chunks
, leftovers
;
252 * If the type is 8-bit ASCII, we can simply copy the string and return
255 (void) strncpy(buf
, data
, len
);
258 } else if (type
== 0x1 || type
== 0x0) {
260 * Yuck - they either used BCD plus encoding, which we don't
261 * currently handle, or they used an unspecified encoding type.
262 * In these cases we'll set buf to an empty string. We still
263 * need to return the length so that we can get to the next
271 * Otherwise, it's 6-bit packed ASCII, so we have to convert the
278 * First we decode the 6-bit string in chunks of 3 bytes as far as
281 for (i
= 0; i
< chunks
; i
++) {
282 tmp
= BITX(*(data
+j
), 5, 0);
283 *buf
++ = (char)(tmp
+ 32);
285 lo
= BITX(*(data
+j
++), 7, 6);
286 tmp
= BITX(*(data
+j
), 3, 0);
287 tmp
= (tmp
<< 2) | lo
;
288 *buf
++ = (char)(tmp
+ 32);
290 lo
= BITX(*(data
+j
++), 7, 4);
291 tmp
= BITX(*(data
+j
), 1, 0);
292 tmp
= (tmp
<< 4) | lo
;
293 *buf
++ = (char)(tmp
+ 32);
295 tmp
= BITX(*(data
+j
++), 7, 2);
296 *buf
++ = (char)(tmp
+ 32);
300 tmp
= BITX(*(data
+j
), 5, 0);
301 *buf
++ = (char)(tmp
+ 32);
304 tmp
= BITX(*(data
+j
), 5, 0);
305 *buf
++ = (char)(tmp
+ 32);
307 lo
= BITX(*(data
+j
++), 7, 6);
308 tmp
= BITX(*(data
+j
), 3, 0);
309 tmp
= (tmp
<< 2) | lo
;
310 *buf
++ = (char)(tmp
+ 32);