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 /*
223798Seschrock  * Copyright 2007 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>
293798Seschrock #include <stdio.h>
303798Seschrock #include <stdlib.h>
313798Seschrock #include <string.h>
323798Seschrock #include <stdarg.h>
333798Seschrock 
343798Seschrock #include "ipmi_impl.h"
353798Seschrock 
363798Seschrock /*
373798Seschrock  * Error handling
383798Seschrock  */
393798Seschrock int
403798Seschrock ipmi_set_error(ipmi_handle_t *ihp, int error, const char *fmt, ...)
413798Seschrock {
423798Seschrock 	va_list ap;
433798Seschrock 
443798Seschrock 	va_start(ap, fmt);
453798Seschrock 
463798Seschrock 	ihp->ih_errno = error;
473798Seschrock 	if (fmt == NULL)
483798Seschrock 		ihp->ih_errmsg[0] = '\0';
493798Seschrock 	else
503798Seschrock 		(void) vsnprintf(ihp->ih_errmsg, sizeof (ihp->ih_errmsg),
513798Seschrock 		    fmt, ap);
523798Seschrock 	va_end(ap);
533798Seschrock 
543798Seschrock 	return (-1);
553798Seschrock }
563798Seschrock 
573798Seschrock int
583798Seschrock ipmi_errno(ipmi_handle_t *ihp)
593798Seschrock {
603798Seschrock 	return (ihp->ih_errno);
613798Seschrock }
623798Seschrock 
633798Seschrock static struct {
643798Seschrock 	int		err;
653798Seschrock 	const char	*msg;
663798Seschrock } errno_table[] = {
673798Seschrock 	{ EIPMI_NOMEM,			"memory allocation failure" },
683798Seschrock 	{ EIPMI_BMC_OPEN_FAILED,	"failed to open /dev/bmc" },
693798Seschrock 	{ EIPMI_BMC_PUTMSG,		"failed to send message to /dev/bmc" },
703798Seschrock 	{ EIPMI_BMC_GETMSG,
713798Seschrock 	    "failed to read response from /dev/bmc" },
723798Seschrock 	{ EIPMI_BMC_RESPONSE,
733798Seschrock 	    "failed to read response from /dev/bmc" },
743798Seschrock 	{ EIPMI_INVALID_COMMAND,	"invalid command" },
753798Seschrock 	{ EIPMI_COMMAND_TIMEOUT,	"command timed out" },
763798Seschrock 	{ EIPMI_DATA_LENGTH_EXCEEDED,	"maximum data length exceeded" },
773798Seschrock 	{ EIPMI_SEND_FAILED,		"failed to send BMC request" },
783798Seschrock 	{ EIPMI_UNSPECIFIED,		"unspecified BMC error" },
793798Seschrock 	{ EIPMI_BAD_RESPONSE_LENGTH,
803798Seschrock 	    "unexpected command response data length" },
813798Seschrock 	{ EIPMI_INVALID_RESERVATION,	"invalid or cancelled reservation" },
823798Seschrock 	{ EIPMI_NOT_PRESENT,		"request entity not present" },
833798Seschrock 	{ EIPMI_INVALID_REQUEST,	"malformed request data" },
843798Seschrock 	{ EIPMI_BUSY,			"service processor is busy" },
853798Seschrock 	{ EIPMI_NOSPACE,		"service processor is out of space" },
863798Seschrock 	{ EIPMI_UNAVAILABLE,		"service processor is unavailable" },
873798Seschrock 	{ EIPMI_ACCESS,			"insufficient privileges" }
883798Seschrock };
893798Seschrock 
903798Seschrock /* ARGSUSED */
913798Seschrock const char *
923798Seschrock ipmi_errmsg(ipmi_handle_t *ihp)
933798Seschrock {
943798Seschrock 	int i;
953798Seschrock 	const char *str;
963798Seschrock 
973798Seschrock 	str = NULL;
983798Seschrock 	for (i = 0; i < sizeof (errno_table) / sizeof (errno_table[0]); i++) {
993798Seschrock 		if (errno_table[i].err == ihp->ih_errno) {
1003798Seschrock 			str = errno_table[i].msg;
1013798Seschrock 			break;
1023798Seschrock 		}
1033798Seschrock 	}
1043798Seschrock 
1053798Seschrock 	if (str == NULL && (str = strerror(ihp->ih_errno)) == NULL)
1063798Seschrock 		str = "unknown failure";
1073798Seschrock 
1083798Seschrock 	if (ihp->ih_errmsg[0] == '\0')
1093798Seschrock 		return (str);
1103798Seschrock 
1113798Seschrock 	(void) snprintf(ihp->ih_errbuf, sizeof (ihp->ih_errbuf),
1123798Seschrock 	    "%s: %s", str, ihp->ih_errmsg);
1133798Seschrock 	return (ihp->ih_errbuf);
1143798Seschrock }
1153798Seschrock 
1163798Seschrock /*
1173798Seschrock  * Memory allocation
1183798Seschrock  */
1193798Seschrock 
1203798Seschrock void *
1213798Seschrock ipmi_alloc(ipmi_handle_t *ihp, size_t size)
1223798Seschrock {
1233798Seschrock 	void *ptr;
1243798Seschrock 
1253798Seschrock 	if ((ptr = malloc(size)) == NULL)
1263798Seschrock 		(void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
1273798Seschrock 
1283798Seschrock 	return (ptr);
1293798Seschrock }
1303798Seschrock 
1313798Seschrock void *
1323798Seschrock ipmi_zalloc(ipmi_handle_t *ihp, size_t size)
1333798Seschrock {
1343798Seschrock 	void *ptr;
1353798Seschrock 
1363798Seschrock 	if ((ptr = calloc(size, 1)) == NULL)
1373798Seschrock 		(void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
1383798Seschrock 
1393798Seschrock 	return (ptr);
1403798Seschrock }
1413798Seschrock 
142*5345Seschrock char *
143*5345Seschrock ipmi_strdup(ipmi_handle_t *ihp, const char *str)
144*5345Seschrock {
145*5345Seschrock 	char *ptr;
146*5345Seschrock 
147*5345Seschrock 	if ((ptr = strdup(str)) == NULL)
148*5345Seschrock 		(void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
149*5345Seschrock 
150*5345Seschrock 	return (ptr);
151*5345Seschrock }
152*5345Seschrock 
1533798Seschrock /* ARGSUSED */
1543798Seschrock void
1553798Seschrock ipmi_free(ipmi_handle_t *ihp, void *ptr)
1563798Seschrock {
1573798Seschrock 	free(ptr);
1583798Seschrock }
159