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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <libipmi.h>
28 #include <stddef.h>
29
30 #include "ipmi_impl.h"
31
32 #define IPMI_CMD_SUNOEM_LED_GET 0x21
33 #define IPMI_CMD_SUNOEM_LED_SET 0x22
34
35 typedef struct ipmi_cmd_sunoem_led_set {
36 DECL_BITFIELD2(
37 ic_sls_channel_msb :1, /* device slave address */
38 ic_sls_slaveaddr :7); /* (from SDR record) */
39 uint8_t ic_sls_type; /* led type */
40 DECL_BITFIELD2(
41 __reserved :1, /* device access address */
42 ic_sls_accessaddr :7); /* (from SDR record */
43 uint8_t ic_sls_hwinfo; /* OEM hardware info */
44 uint8_t ic_sls_mode; /* LED mode */
45 uint8_t ic_sls_eid; /* entity ID */
46 uint8_t ic_sls_einst; /* entity instance */
47 uint8_t ic_sls_force; /* force direct access */
48 uint8_t ic_sls_role; /* BMC authorization */
49 } ipmi_cmd_sunoem_led_set_t;
50
51 typedef struct ipmi_cmd_sunoem_led_get {
52 DECL_BITFIELD2(
53 ic_slg_channel_msb :1, /* device slave address */
54 ic_slg_slaveaddr :7); /* (from SDR record) */
55 uint8_t ic_slg_type; /* led type */
56 DECL_BITFIELD2(
57 __reserved :1, /* device access address */
58 ic_slg_accessaddr :7); /* (from SDR record */
59 uint8_t ic_slg_hwinfo; /* OEM hardware info */
60 uint8_t ic_slg_eid; /* entity ID */
61 uint8_t ic_slg_einst; /* entity instance */
62 uint8_t ic_slg_force; /* force direct access */
63 } ipmi_cmd_sunoem_led_get_t;
64
65 #define IPMI_SUNOEM_LED_TYPE_OK2RM 0
66 #define IPMI_SUNOEM_LED_TYPE_SERVICE 1
67 #define IPMI_SUNOEM_LED_TYPE_ACT 2
68 #define IPMI_SUNOEM_LED_TYPE_LOCATE 3
69 #define IPMI_SUNOEM_LED_TYPE_ANY 0xFF
70
71 boolean_t
ipmi_is_sun_ilom(ipmi_deviceid_t * dp)72 ipmi_is_sun_ilom(ipmi_deviceid_t *dp)
73 {
74 return (ipmi_devid_manufacturer(dp) == IPMI_OEM_SUN &&
75 ipmi_devid_product(dp) == IPMI_PROD_SUN_ILOM);
76 }
77
78 static int
check_sunoem(ipmi_handle_t * ihp)79 check_sunoem(ipmi_handle_t *ihp)
80 {
81 ipmi_deviceid_t *devid;
82
83 if ((devid = ipmi_get_deviceid(ihp)) == NULL)
84 return (-1);
85
86 if (!ipmi_is_sun_ilom(devid))
87 return (ipmi_set_error(ihp, EIPMI_INVALID_COMMAND, NULL));
88
89 return (0);
90 }
91
92 static int
ipmi_send_sunoem_led_set(ipmi_handle_t * ihp,ipmi_cmd_sunoem_led_set_t * req)93 ipmi_send_sunoem_led_set(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_set_t *req)
94 {
95 ipmi_cmd_t cmd, *resp;
96
97 cmd.ic_netfn = IPMI_NETFN_OEM;
98 cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_SET;
99 cmd.ic_lun = 0;
100 cmd.ic_data = req;
101 cmd.ic_dlen = sizeof (*req);
102
103 if ((resp = ipmi_send(ihp, &cmd)) == NULL)
104 return (-1);
105
106 if (resp->ic_dlen != 0)
107 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
108
109 return (0);
110 }
111
112 static int
ipmi_send_sunoem_led_get(ipmi_handle_t * ihp,ipmi_cmd_sunoem_led_get_t * req,uint8_t * result)113 ipmi_send_sunoem_led_get(ipmi_handle_t *ihp, ipmi_cmd_sunoem_led_get_t *req,
114 uint8_t *result)
115 {
116 ipmi_cmd_t cmd, *resp;
117
118 cmd.ic_netfn = IPMI_NETFN_OEM;
119 cmd.ic_cmd = IPMI_CMD_SUNOEM_LED_GET;
120 cmd.ic_lun = 0;
121 cmd.ic_data = req;
122 cmd.ic_dlen = sizeof (*req);
123
124 if ((resp = ipmi_send(ihp, &cmd)) == NULL)
125 return (-1);
126
127 if (resp->ic_dlen != 1)
128 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
129
130 *result = *((uint8_t *)resp->ic_data);
131 return (0);
132 }
133
134 int
ipmi_sunoem_led_set(ipmi_handle_t * ihp,ipmi_sdr_generic_locator_t * dev,uint8_t mode)135 ipmi_sunoem_led_set(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev,
136 uint8_t mode)
137 {
138 ipmi_cmd_sunoem_led_set_t cmd = { 0 };
139
140 if (check_sunoem(ihp) != 0)
141 return (-1);
142
143 cmd.ic_sls_slaveaddr = dev->is_gl_slaveaddr;
144 cmd.ic_sls_channel_msb = dev->is_gl_channel_msb;
145 cmd.ic_sls_type = dev->is_gl_oem;
146 cmd.ic_sls_accessaddr = dev->is_gl_accessaddr;
147 cmd.ic_sls_hwinfo = dev->is_gl_oem;
148 cmd.ic_sls_mode = mode;
149 cmd.ic_sls_eid = dev->is_gl_entity;
150 cmd.ic_sls_einst = dev->is_gl_instance;
151
152 return (ipmi_send_sunoem_led_set(ihp, &cmd));
153 }
154
155 int
ipmi_sunoem_led_get(ipmi_handle_t * ihp,ipmi_sdr_generic_locator_t * dev,uint8_t * mode)156 ipmi_sunoem_led_get(ipmi_handle_t *ihp, ipmi_sdr_generic_locator_t *dev,
157 uint8_t *mode)
158 {
159 ipmi_cmd_sunoem_led_get_t cmd = { 0 };
160
161 if (check_sunoem(ihp) != 0)
162 return (-1);
163
164 cmd.ic_slg_slaveaddr = dev->is_gl_slaveaddr;
165 cmd.ic_slg_channel_msb = dev->is_gl_channel_msb;
166 cmd.ic_slg_type = dev->is_gl_oem;
167 cmd.ic_slg_accessaddr = dev->is_gl_accessaddr;
168 cmd.ic_slg_hwinfo = dev->is_gl_oem;
169 cmd.ic_slg_eid = dev->is_gl_entity;
170 cmd.ic_slg_einst = dev->is_gl_instance;
171
172 return (ipmi_send_sunoem_led_get(ihp, &cmd, mode));
173 }
174
175 int
ipmi_sunoem_uptime(ipmi_handle_t * ihp,uint32_t * uptime,uint32_t * gen)176 ipmi_sunoem_uptime(ipmi_handle_t *ihp, uint32_t *uptime, uint32_t *gen)
177 {
178 ipmi_cmd_t cmd, *resp;
179 uint8_t unused;
180
181 if (check_sunoem(ihp) != 0)
182 return (-1);
183
184 cmd.ic_netfn = IPMI_NETFN_OEM;
185 cmd.ic_lun = 0;
186 cmd.ic_cmd = IPMI_CMD_SUNOEM_UPTIME;
187 cmd.ic_dlen = sizeof (unused);
188 cmd.ic_data = &unused;
189
190 if ((resp = ipmi_send(ihp, &cmd)) == NULL)
191 return (-1);
192
193 if (resp->ic_dlen != 2 * sizeof (uint32_t))
194 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
195
196 if (uptime)
197 *uptime = BE_IN32(&((uint32_t *)resp->ic_data)[0]);
198 if (gen)
199 *gen = BE_IN32(&((uint32_t *)resp->ic_data)[1]);
200
201 return (0);
202 }
203
204 int
ipmi_sunoem_update_fru(ipmi_handle_t * ihp,ipmi_sunoem_fru_t * req)205 ipmi_sunoem_update_fru(ipmi_handle_t *ihp, ipmi_sunoem_fru_t *req)
206 {
207 ipmi_cmd_t cmd, *resp;
208
209 if (check_sunoem(ihp) != 0)
210 return (-1);
211
212 switch (req->isf_type) {
213 case IPMI_SUNOEM_FRU_DIMM:
214 req->isf_datalen = sizeof (req->isf_data.dimm);
215 break;
216
217 case IPMI_SUNOEM_FRU_CPU:
218 req->isf_datalen = sizeof (req->isf_data.cpu);
219 break;
220
221 case IPMI_SUNOEM_FRU_BIOS:
222 req->isf_datalen = sizeof (req->isf_data.bios);
223 break;
224
225 case IPMI_SUNOEM_FRU_DISK:
226 req->isf_datalen = sizeof (req->isf_data.disk);
227 break;
228 }
229
230 cmd.ic_netfn = IPMI_NETFN_OEM;
231 cmd.ic_cmd = IPMI_CMD_SUNOEM_FRU_UPDATE;
232 cmd.ic_lun = 0;
233 cmd.ic_dlen = offsetof(ipmi_sunoem_fru_t, isf_data) +
234 req->isf_datalen;
235 cmd.ic_data = req;
236
237 if ((resp = ipmi_send(ihp, &cmd)) == NULL)
238 return (-1);
239
240 if (resp->ic_dlen != 0)
241 return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
242
243 return (0);
244 }
245