1*3798Seschrock /*
2*3798Seschrock  * CDDL HEADER START
3*3798Seschrock  *
4*3798Seschrock  * The contents of this file are subject to the terms of the
5*3798Seschrock  * Common Development and Distribution License (the "License").
6*3798Seschrock  * You may not use this file except in compliance with the License.
7*3798Seschrock  *
8*3798Seschrock  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3798Seschrock  * or http://www.opensolaris.org/os/licensing.
10*3798Seschrock  * See the License for the specific language governing permissions
11*3798Seschrock  * and limitations under the License.
12*3798Seschrock  *
13*3798Seschrock  * When distributing Covered Code, include this CDDL HEADER in each
14*3798Seschrock  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3798Seschrock  * If applicable, add the following below this CDDL HEADER, with the
16*3798Seschrock  * fields enclosed by brackets "[]" replaced with your own identifying
17*3798Seschrock  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3798Seschrock  *
19*3798Seschrock  * CDDL HEADER END
20*3798Seschrock  */
21*3798Seschrock /*
22*3798Seschrock  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*3798Seschrock  * Use is subject to license terms.
24*3798Seschrock  */
25*3798Seschrock 
26*3798Seschrock #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*3798Seschrock 
28*3798Seschrock #include <libipmi.h>
29*3798Seschrock #include <stdio.h>
30*3798Seschrock #include <stdlib.h>
31*3798Seschrock #include <string.h>
32*3798Seschrock #include <stdarg.h>
33*3798Seschrock 
34*3798Seschrock #include "ipmi_impl.h"
35*3798Seschrock 
36*3798Seschrock /*
37*3798Seschrock  * Error handling
38*3798Seschrock  */
39*3798Seschrock int
40*3798Seschrock ipmi_set_error(ipmi_handle_t *ihp, int error, const char *fmt, ...)
41*3798Seschrock {
42*3798Seschrock 	va_list ap;
43*3798Seschrock 
44*3798Seschrock 	va_start(ap, fmt);
45*3798Seschrock 
46*3798Seschrock 	ihp->ih_errno = error;
47*3798Seschrock 	if (fmt == NULL)
48*3798Seschrock 		ihp->ih_errmsg[0] = '\0';
49*3798Seschrock 	else
50*3798Seschrock 		(void) vsnprintf(ihp->ih_errmsg, sizeof (ihp->ih_errmsg),
51*3798Seschrock 		    fmt, ap);
52*3798Seschrock 	va_end(ap);
53*3798Seschrock 
54*3798Seschrock 	return (-1);
55*3798Seschrock }
56*3798Seschrock 
57*3798Seschrock int
58*3798Seschrock ipmi_errno(ipmi_handle_t *ihp)
59*3798Seschrock {
60*3798Seschrock 	return (ihp->ih_errno);
61*3798Seschrock }
62*3798Seschrock 
63*3798Seschrock static struct {
64*3798Seschrock 	int		err;
65*3798Seschrock 	const char	*msg;
66*3798Seschrock } errno_table[] = {
67*3798Seschrock 	{ EIPMI_NOMEM,			"memory allocation failure" },
68*3798Seschrock 	{ EIPMI_BMC_OPEN_FAILED,	"failed to open /dev/bmc" },
69*3798Seschrock 	{ EIPMI_BMC_PUTMSG,		"failed to send message to /dev/bmc" },
70*3798Seschrock 	{ EIPMI_BMC_GETMSG,
71*3798Seschrock 	    "failed to read response from /dev/bmc" },
72*3798Seschrock 	{ EIPMI_BMC_RESPONSE,
73*3798Seschrock 	    "failed to read response from /dev/bmc" },
74*3798Seschrock 	{ EIPMI_INVALID_COMMAND,	"invalid command" },
75*3798Seschrock 	{ EIPMI_COMMAND_TIMEOUT,	"command timed out" },
76*3798Seschrock 	{ EIPMI_DATA_LENGTH_EXCEEDED,	"maximum data length exceeded" },
77*3798Seschrock 	{ EIPMI_SEND_FAILED,		"failed to send BMC request" },
78*3798Seschrock 	{ EIPMI_UNSPECIFIED,		"unspecified BMC error" },
79*3798Seschrock 	{ EIPMI_BAD_RESPONSE_LENGTH,
80*3798Seschrock 	    "unexpected command response data length" },
81*3798Seschrock 	{ EIPMI_INVALID_RESERVATION,	"invalid or cancelled reservation" },
82*3798Seschrock 	{ EIPMI_NOT_PRESENT,		"request entity not present" },
83*3798Seschrock 	{ EIPMI_INVALID_REQUEST,	"malformed request data" },
84*3798Seschrock 	{ EIPMI_BUSY,			"service processor is busy" },
85*3798Seschrock 	{ EIPMI_NOSPACE,		"service processor is out of space" },
86*3798Seschrock 	{ EIPMI_UNAVAILABLE,		"service processor is unavailable" },
87*3798Seschrock 	{ EIPMI_ACCESS,			"insufficient privileges" }
88*3798Seschrock };
89*3798Seschrock 
90*3798Seschrock /* ARGSUSED */
91*3798Seschrock const char *
92*3798Seschrock ipmi_errmsg(ipmi_handle_t *ihp)
93*3798Seschrock {
94*3798Seschrock 	int i;
95*3798Seschrock 	const char *str;
96*3798Seschrock 
97*3798Seschrock 	str = NULL;
98*3798Seschrock 	for (i = 0; i < sizeof (errno_table) / sizeof (errno_table[0]); i++) {
99*3798Seschrock 		if (errno_table[i].err == ihp->ih_errno) {
100*3798Seschrock 			str = errno_table[i].msg;
101*3798Seschrock 			break;
102*3798Seschrock 		}
103*3798Seschrock 	}
104*3798Seschrock 
105*3798Seschrock 	if (str == NULL && (str = strerror(ihp->ih_errno)) == NULL)
106*3798Seschrock 		str = "unknown failure";
107*3798Seschrock 
108*3798Seschrock 	if (ihp->ih_errmsg[0] == '\0')
109*3798Seschrock 		return (str);
110*3798Seschrock 
111*3798Seschrock 	(void) snprintf(ihp->ih_errbuf, sizeof (ihp->ih_errbuf),
112*3798Seschrock 	    "%s: %s", str, ihp->ih_errmsg);
113*3798Seschrock 	return (ihp->ih_errbuf);
114*3798Seschrock }
115*3798Seschrock 
116*3798Seschrock /*
117*3798Seschrock  * Memory allocation
118*3798Seschrock  */
119*3798Seschrock 
120*3798Seschrock void *
121*3798Seschrock ipmi_alloc(ipmi_handle_t *ihp, size_t size)
122*3798Seschrock {
123*3798Seschrock 	void *ptr;
124*3798Seschrock 
125*3798Seschrock 	if ((ptr = malloc(size)) == NULL)
126*3798Seschrock 		(void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
127*3798Seschrock 
128*3798Seschrock 	return (ptr);
129*3798Seschrock }
130*3798Seschrock 
131*3798Seschrock void *
132*3798Seschrock ipmi_zalloc(ipmi_handle_t *ihp, size_t size)
133*3798Seschrock {
134*3798Seschrock 	void *ptr;
135*3798Seschrock 
136*3798Seschrock 	if ((ptr = calloc(size, 1)) == NULL)
137*3798Seschrock 		(void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
138*3798Seschrock 
139*3798Seschrock 	return (ptr);
140*3798Seschrock }
141*3798Seschrock 
142*3798Seschrock /* ARGSUSED */
143*3798Seschrock void
144*3798Seschrock ipmi_free(ipmi_handle_t *ihp, void *ptr)
145*3798Seschrock {
146*3798Seschrock 	free(ptr);
147*3798Seschrock }
148