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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <libipmi.h>
30 #include <stddef.h>
31 #include <string.h>
32 #include <strings.h>
33 
34 #include "ipmi_impl.h"
35 
36 /*
37  * 31.2 Get SEL Info Command.
38  */
39 ipmi_sel_info_t *
40 ipmi_sel_get_info(ipmi_handle_t *ihp)
41 {
42 	ipmi_cmd_t cmd, *rsp;
43 	ipmi_sel_info_t *ip;
44 
45 	cmd.ic_netfn = IPMI_NETFN_STORAGE;
46 	cmd.ic_lun = 0;
47 	cmd.ic_cmd = IPMI_CMD_GET_SEL_INFO;
48 	cmd.ic_dlen = 0;
49 	cmd.ic_data = NULL;
50 
51 	if ((rsp = ipmi_send(ihp, &cmd)) == NULL)
52 		return (NULL);
53 
54 	ip = (ipmi_sel_info_t *)rsp->ic_data;
55 
56 	ip->isel_entries = LE_16(ip->isel_entries);
57 	ip->isel_free = LE_16(ip->isel_free);
58 	ip->isel_add_ts = LE_32(ip->isel_add_ts);
59 	ip->isel_erase_ts = LE_32(ip->isel_erase_ts);
60 
61 	return (ip);
62 }
63 
64 typedef struct ipmi_cmd_get_sel_entry {
65 	uint16_t	ic_sel_ent_resid;
66 	uint16_t	ic_sel_ent_recid;
67 	uint8_t		ic_sel_ent_offset;
68 	uint8_t		ic_sel_ent_bytes;
69 } ipmi_cmd_get_sel_entry_t;
70 
71 ipmi_sel_event_t *
72 ipmi_sel_get_entry(ipmi_handle_t *ihp, uint16_t id)
73 {
74 	ipmi_cmd_t cmd, *rsp;
75 	ipmi_sel_event_t *evp;
76 	ipmi_cmd_get_sel_entry_t data;
77 
78 	data.ic_sel_ent_resid = 0;
79 	data.ic_sel_ent_recid = LE_16(id);
80 	data.ic_sel_ent_offset = 0;
81 	data.ic_sel_ent_bytes = 0xFF;
82 
83 	cmd.ic_netfn = IPMI_NETFN_STORAGE;
84 	cmd.ic_lun = 0;
85 	cmd.ic_cmd = IPMI_CMD_GET_SEL_ENTRY;
86 	cmd.ic_dlen = sizeof (data);
87 	cmd.ic_data = &data;
88 
89 	if ((rsp = ipmi_send(ihp, &cmd)) == NULL)
90 		return (NULL);
91 
92 	if (rsp->ic_dlen < sizeof (ipmi_sel_event_t)) {
93 		(void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL);
94 		return (NULL);
95 	}
96 
97 	evp = (ipmi_sel_event_t *)rsp->ic_data;
98 
99 	evp->isel_ev_next = LE_16(evp->isel_ev_next);
100 	evp->isel_ev_recid = LE_16(evp->isel_ev_recid);
101 	if (evp->isel_ev_rectype == IPMI_SEL_SYSTEM ||
102 	    evp->isel_ev_rectype >= IPMI_SEL_OEM_LO)
103 		evp->isel_ev_ts = LE_32(evp->isel_ev_ts);
104 
105 	return (evp);
106 }
107 
108 /*
109  * SEL time management.  For the purposes of libipmi we assume that the SDR
110  * repository and SEL share the same timebase, even though the spec allows for
111  * separate time sources.  Hence no function to set the SDR repository time.
112  */
113 int
114 ipmi_sel_get_time(ipmi_handle_t *ihp, uint32_t *tp)
115 {
116 	ipmi_cmd_t cmd, *rsp;
117 
118 	cmd.ic_netfn = IPMI_NETFN_STORAGE;
119 	cmd.ic_lun = 0;
120 	cmd.ic_cmd = IPMI_CMD_GET_SEL_TIME;
121 	cmd.ic_dlen = 0;
122 	cmd.ic_data = NULL;
123 
124 	if ((rsp = ipmi_send(ihp, &cmd)) == NULL)
125 		return (-1);
126 
127 	if (rsp->ic_dlen < sizeof (uint32_t))
128 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
129 
130 	*tp = LE_32(*((uint32_t *)rsp->ic_data));
131 
132 	return (0);
133 }
134 
135 int
136 ipmi_sel_set_time(ipmi_handle_t *ihp, uint32_t t)
137 {
138 	ipmi_cmd_t cmd;
139 
140 	t = LE_32(t);
141 
142 	cmd.ic_netfn = IPMI_NETFN_STORAGE;
143 	cmd.ic_lun = 0;
144 	cmd.ic_cmd = IPMI_CMD_SET_SEL_TIME;
145 	cmd.ic_dlen = sizeof (t);
146 	cmd.ic_data = &t;
147 
148 	if (ipmi_send(ihp, &cmd) == NULL)
149 		return (-1);
150 
151 	return (0);
152 }
153 
154 int
155 ipmi_sel_get_utc_offset(ipmi_handle_t *ihp, int *offp)
156 {
157 	ipmi_cmd_t cmd, *rsp;
158 	int16_t off16;
159 
160 	cmd.ic_netfn = IPMI_NETFN_STORAGE;
161 	cmd.ic_lun = 0;
162 	cmd.ic_cmd = IPMI_CMD_GET_SEL_UTC_OFFSET;
163 	cmd.ic_dlen = 0;
164 	cmd.ic_data = NULL;
165 
166 	if ((rsp = ipmi_send(ihp, &cmd)) == NULL)
167 		return (-1);
168 
169 	if (rsp->ic_dlen < sizeof (uint16_t))
170 		return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
171 
172 	off16 = LE_16(*((int16_t *)rsp->ic_data));
173 	*offp = off16;
174 
175 	return (0);
176 }
177 
178 int
179 ipmi_sel_set_utc_offset(ipmi_handle_t *ihp, int off)
180 {
181 	ipmi_cmd_t cmd;
182 	int16_t off16 = off;
183 
184 	off16 = LE_16(off16);
185 
186 	cmd.ic_netfn = IPMI_NETFN_STORAGE;
187 	cmd.ic_lun = 0;
188 	cmd.ic_cmd = IPMI_CMD_SET_SEL_UTC_OFFSET;
189 	cmd.ic_dlen = sizeof (off16);
190 	cmd.ic_data = &off16;
191 
192 	if (ipmi_send(ihp, &cmd) == NULL)
193 		return (-1);
194 
195 	return (0);
196 }
197