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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_LIBIPMI_H
27 #define	_LIBIPMI_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #include <sys/bmc_intf.h>
32 #include <sys/byteorder.h>
33 
34 /*
35  * Private interfaces for communicating with attached services over IPMI.  This
36  * library is designed for system software communicating with Sun-supported
37  * service processors over /dev/bmc.  It is not a generic IPMI library.
38  *
39  * Documentation references refer to "Intelligent Platform Management Interface
40  * Specification Second Generation v2.0", document revision 1.0 with Februrary
41  * 15, 2006 Markup from "IPMI v2.0 Addenda, Errata, and Clarifications Revision
42  * 3".
43  */
44 
45 #ifdef	__cplusplus
46 extern "C" {
47 #endif
48 
49 typedef struct ipmi_handle ipmi_handle_t;
50 
51 #if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL)
52 #error  One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
53 #endif
54 
55 #pragma pack(1)
56 
57 /*
58  * Basic netfn definitions.  See section 5.1.
59  */
60 #define	IPMI_NETFN_APP			BMC_NETFN_APP
61 #define	IPMI_NETFN_STORAGE		BMC_NETFN_STORAGE
62 #define	IPMI_NETFN_SE			BMC_NETFN_SE
63 #define	IPMI_NETFN_OEM			0x2e
64 
65 /*
66  * Error definitions
67  */
68 #define	EIPMI_BASE	2000
69 
70 enum {
71 	EIPMI_NOMEM = EIPMI_BASE,	/* memory allocation failure */
72 	EIPMI_BMC_OPEN_FAILED,		/* failed to open /dev/bmc */
73 	EIPMI_BMC_PUTMSG,		/* putmsg() failed */
74 	EIPMI_BMC_GETMSG,		/* getmsg() failed */
75 	EIPMI_BMC_RESPONSE,		/* response from /dev/bmc failed */
76 	EIPMI_INVALID_COMMAND,		/* invalid command */
77 	EIPMI_COMMAND_TIMEOUT,		/* command timeout */
78 	EIPMI_DATA_LENGTH_EXCEEDED,	/* maximum data length exceeded */
79 	EIPMI_SEND_FAILED,		/* failed to send BMC request */
80 	EIPMI_UNSPECIFIED,		/* unspecified error */
81 	EIPMI_UNKNOWN,			/* unknown error */
82 	EIPMI_BAD_RESPONSE,		/* received unexpected response */
83 	EIPMI_BAD_RESPONSE_LENGTH,	/* unexpected response length */
84 	EIPMI_INVALID_RESERVATION,	/* invalid reservation */
85 	EIPMI_NOT_PRESENT,		/* requested entity not present */
86 	EIPMI_INVALID_REQUEST,		/* malformed request */
87 	EIPMI_BUSY,			/* SP is busy */
88 	EIPMI_NOSPACE,			/* SP is out of space */
89 	EIPMI_UNAVAILABLE,		/* SP is present but unavailable */
90 	EIPMI_ACCESS			/* insufficient privileges */
91 };
92 
93 /*
94  * Basic library functions.
95  *
96  * The ipmi_handle is the primary interface to the library.  The library itself
97  * is not MT-safe, but it is safe within a single handle.  Multithreaded clients
98  * should either open multiple handles, or otherwise synchronize access to the
99  * same handle.
100  *
101  * There is a single command response buffer that is stored with the handle, to
102  * simplify memory management in the caller.  The memory referenced by a command
103  * response is only valid until the next command is issued.  The caller is
104  * responsible for making a copy of the response if it is needed.
105  */
106 extern ipmi_handle_t *ipmi_open(int *, char **);
107 extern void ipmi_close(ipmi_handle_t *);
108 
109 extern int ipmi_errno(ipmi_handle_t *);
110 extern const char *ipmi_errmsg(ipmi_handle_t *);
111 
112 /*
113  * Raw requests.  See section 5.
114  */
115 typedef struct ipmi_cmd {
116 	uint8_t		ic_netfn:6;
117 	uint8_t		ic_lun:2;
118 	uint8_t		ic_cmd;
119 	uint16_t	ic_dlen;
120 	void		*ic_data;
121 } ipmi_cmd_t;
122 
123 extern ipmi_cmd_t *ipmi_send(ipmi_handle_t *, ipmi_cmd_t *);
124 
125 /*
126  * Retrieve basic information about the IPMI device.  See section 20.1 "Get
127  * Device ID Command".
128  */
129 #define	IPMI_CMD_GET_DEVICEID		0x01
130 
131 typedef struct ipmi_deviceid {
132 	uint8_t		id_devid;
133 #if defined(_BIT_FIELDS_LTOH)
134 	uint8_t		id_dev_rev:4;
135 	uint8_t		__reserved:3;
136 	uint8_t		id_dev_sdrs:1;
137 #else
138 	uint8_t		id_dev_sdrs:1;
139 	uint8_t		__reserved:3;
140 	uint8_t		id_dev_rev:4;
141 #endif
142 #if defined(_BIT_FIELD_LTOH)
143 	uint8_t		id_firm_major:7;
144 	uint8_t		id_dev_available:1;
145 #else
146 	uint8_t		id_dev_available:1;
147 	uint8_t		id_firm_major:7;
148 #endif
149 	uint8_t		id_firm_minor;
150 	uint8_t		id_ipmi_rev;
151 	uint8_t		id_dev_support;
152 	uint8_t		id_manufacturer[3];
153 	uint16_t	id_product;
154 } ipmi_deviceid_t;
155 
156 #define	IPMI_OEM_SUN	0x2a
157 
158 ipmi_deviceid_t *ipmi_get_deviceid(ipmi_handle_t *);
159 
160 #define	ipmi_devid_manufacturer(dp)		\
161 	((dp)->id_manufacturer[0] |		\
162 	((dp)->id_manufacturer[1] << 8) |	\
163 	((dp)->id_manufacturer[2] << 16))
164 
165 /*
166  * SDR (Sensor Device Record) requests.  A cache of the current SDR repository
167  * is kept as part of the IPMI handle and updated when necessary.  Routines to
168  * access the raw SDR repository are also provided.
169  */
170 
171 /*
172  * Reserve repository command.  See section 33.11.
173  */
174 #define	IPMI_CMD_RESERVE_SDR_REPOSITORY	0x22
175 
176 /*
177  * Get SDR command.  See section 33.12.  This command accesses the raw SDR
178  * repository.  Clients can also use the lookup functions to retrieve a
179  * particular SDR record by name.
180  *
181  * The list of possible types is indicated in the sub-chapters of section 43.
182  */
183 typedef struct ipmi_sdr {
184 	uint16_t	is_id;
185 	uint8_t		is_version;
186 	uint8_t		is_type;
187 	uint8_t		is_length;
188 	uint8_t		is_record[1];
189 } ipmi_sdr_t;
190 #define	IPMI_CMD_GET_SDR		0x23
191 
192 #define	IPMI_SDR_FIRST			0x0000
193 #define	IPMI_SDR_LAST			0xFFFF
194 
195 extern ipmi_sdr_t *ipmi_sdr_get(ipmi_handle_t *, uint16_t, uint16_t *);
196 
197 /*
198  * Generic Device Locator Record.  See section 43.7.
199  */
200 
201 #define	IPMI_SDR_TYPE_GENERIC_LOCATOR		0x10
202 
203 typedef struct ipmi_sdr_generic_locator {
204 	/* RECORD KEY BYTES */
205 #if defined(_BIT_FIELDS_LTOH)
206 	uint8_t		__reserved1:1;
207 	uint8_t		is_gl_accessaddr:7;
208 	uint8_t		is_gl_channel_msb:1;
209 	uint8_t		is_gl_slaveaddr:7;
210 	uint8_t		is_gl_bus:3;
211 	uint8_t		is_gl_lun:2;
212 	uint8_t		is_gl_channel:3;
213 #else
214 	uint8_t		is_gl_accessaddr:7;
215 	uint8_t		__reserved1:1;
216 	uint8_t		is_gl_slaveaddr:7;
217 	uint8_t		is_gl_channel_msb:1;
218 	uint8_t		is_gl_channel:3;
219 	uint8_t		is_gl_lun:2;
220 	uint8_t		is_gl_bus:3;
221 #endif
222 	/* RECORD BODY BYTES */
223 #if defined(_BIT_FIELDS_LTOH)
224 	uint8_t		is_gl_span:3;
225 	uint8_t		__reserved2:5;
226 #else
227 	uint8_t		__reserved2:5;
228 	uint8_t		is_gl_span:3;
229 #endif
230 	uint8_t		__reserved3;
231 	uint8_t		is_gl_type;
232 	uint8_t		is_gl_modifier;
233 	uint8_t		is_gl_entity;
234 	uint8_t		is_gl_instance;
235 	uint8_t		is_gl_oem;
236 #if defined(_BIT_FIELDS_LTOH)
237 	uint8_t		is_gl_idlen:6;
238 	uint8_t		is_gl_idtype:2;
239 #else
240 	uint8_t		is_gl_idtype:2;
241 	uint8_t		is_gl_idlen:6;
242 #endif
243 	char		is_gl_idstring[1];
244 } ipmi_sdr_generic_locator_t;
245 
246 /*
247  * FRU Device Locator Record.  See section 43.8.
248  */
249 
250 #define	IPMI_SDR_TYPE_FRU_LOCATOR		0x11
251 
252 typedef struct ipmi_sdr_fru_locator {
253 	/* RECORD KEY BYTES */
254 #if defined(_BIT_FIELDS_LTOH)
255 	uint8_t		__reserved1:1;
256 	uint8_t		is_fl_accessaddr:7;
257 #else
258 	uint8_t		is_fl_accessaddr:7;
259 	uint8_t		__reserved1:1;
260 #endif
261 	union {
262 		struct {
263 			uint8_t	_is_fl_devid;
264 		} _logical;
265 		struct {
266 #if defined(_BIT_FIELDS_LTOH)
267 			uint8_t	__reserved:1;
268 			uint8_t	_is_fl_slaveaddr:7;
269 #else
270 			uint8_t	_is_fl_slaveaddr:7;
271 			uint8_t	__reserved:1;
272 #endif
273 		} _nonintelligent;
274 	} _devid_or_slaveaddr;
275 #if defined(_BIT_FIELDS_LTOH)
276 	uint8_t		is_fl_bus:3;
277 	uint8_t		is_fl_lun:2;
278 	uint8_t		__reserved2:2;
279 	uint8_t		is_fl_logical:1;
280 	uint8_t		__reserved3:4;
281 	uint8_t		is_fl_channel:4;
282 #else
283 	uint8_t		is_fl_logical:1;
284 	uint8_t		__reserved2:2;
285 	uint8_t		is_fl_lun:2;
286 	uint8_t		is_fl_bus:3;
287 	uint8_t		is_fl_channel:4;
288 	uint8_t		__reserved3:4;
289 #endif
290 	/* RECORD BODY BYTES */
291 	uint8_t		__reserved4;
292 	uint8_t		is_fl_type;
293 	uint8_t		is_fl_modifier;
294 	uint8_t		is_fl_entity;
295 	uint8_t		is_fl_instance;
296 	uint8_t		is_fl_oem;
297 #if defined(_BIT_FIELDS_LTOH)
298 	uint8_t		is_fl_idlen:6;
299 	uint8_t		is_fl_idtype:2;
300 #else
301 	uint8_t		is_fl_idtype:2;
302 	uint8_t		is_fl_idlen:6;
303 #endif
304 	char		is_fl_idstring[1];
305 } ipmi_sdr_fru_locator_t;
306 
307 #define	is_fl_devid	_devid_or_slaveaddr._logical._is_fl_devid
308 #define	is_fl_slaveaddr	_devid_or_slaveaddr._nonintelligent._is_fl_slaveaddr
309 
310 /*
311  * The remaining SDR types do not have an associated structure, yet.
312  */
313 #define	IPMI_SDR_TYPE_FULL_SENSOR		0x01
314 #define	IPMI_SDR_TYPE_COMPACT_SENSOR		0x02
315 #define	IPMI_SDR_TYPE_EVENT_ONLY		0x03
316 #define	IPMI_SDR_TYPE_ENTITY_ASSOCIATION	0x08
317 #define	IPMI_SDR_TYPE_DEVICE_RELATIVE		0x09
318 #define	IPMI_SDR_TYPE_MANAGEMENT_DEVICE		0x12
319 #define	IPMI_SDR_TYPE_MANAGEMENT_CONFIRMATION	0x13
320 #define	IPMI_SDR_TYPE_BMC_MESSAGE_CHANNEL	0x14
321 #define	IPMI_SDR_TYPE_OEM			0xC0
322 
323 /*
324  * Lookup the given sensor type by name.  These functions automatically read in
325  * and cache the complete SDR repository.
326  */
327 extern ipmi_sdr_fru_locator_t *ipmi_sdr_lookup_fru(ipmi_handle_t *,
328     const char *);
329 extern ipmi_sdr_generic_locator_t *ipmi_sdr_lookup_generic(ipmi_handle_t *,
330     const char *);
331 
332 /*
333  * Get Sensor Reading.  See section 35.14.
334  */
335 
336 #define	IPMI_CMD_GET_SENSOR_READING	0x2d
337 
338 typedef struct ipmi_sensor_reading {
339 	uint8_t		isr_reading;
340 #if defined(_BIT_FIELDS_LTOH)
341 	uint8_t		__reserved1:5;
342 	uint8_t		isr_state_unavailable:1;
343 	uint8_t		isr_scanning_disabled:1;
344 	uint8_t		isr_event_disabled:1;
345 #else
346 	uint8_t		isr_event_disabled:1;
347 	uint8_t		isr_scanning_disabled:1;
348 	uint8_t		isr_state_unavailable:1;
349 	uint8_t		__reserved1:5;
350 #endif
351 	uint16_t	isr_state;
352 } ipmi_sensor_reading_t;
353 
354 extern ipmi_sensor_reading_t *ipmi_get_sensor_reading(ipmi_handle_t *, uint8_t);
355 
356 /*
357  * Set Sensor Reading.  See section 35.14.
358  */
359 #define	IPMI_CMD_SET_SENSOR_READING	0x30
360 
361 #define	IPMI_SENSOR_OP_CLEAR	0x3	/* clear '0' bits */
362 #define	IPMI_SENSOR_OP_SET	0x2	/* set '1' bits */
363 #define	IPMI_SENSOR_OP_EXACT	0x1	/* set bits exactly */
364 
365 typedef struct ipmi_set_sensor_reading {
366 	uint8_t		iss_id;
367 #if defined(_BIT_FIELDS_LTOH)
368 	uint8_t		iss_set_reading:1;
369 	uint8_t		__reserved:1;
370 	uint8_t		iss_deassrt_op:2;
371 	uint8_t		iss_assert_op:2;
372 	uint8_t		iss_data_bytes:2;
373 #else
374 	uint8_t		iss_data_bytes:2;
375 	uint8_t		iss_assert_op:2;
376 	uint8_t		iss_deassrt_op:2;
377 	uint8_t		__reserved:1;
378 	uint8_t		iss_set_reading:1;
379 #endif
380 	uint8_t		iss_sensor_reading;
381 	uint16_t	iss_assert_state;	/* optional */
382 	uint16_t	iss_deassert_state;	/* optional */
383 	uint8_t		iss_event_data1;	/* optional */
384 	uint8_t		iss_event_data2;	/* optional */
385 	uint8_t		iss_event_data3;	/* optional */
386 } ipmi_set_sensor_reading_t;
387 
388 extern int ipmi_set_sensor_reading(ipmi_handle_t *,
389     ipmi_set_sensor_reading_t *);
390 
391 /*
392  * The remaining functions are private to the implementation of the Sun ILOM
393  * service processor.  These function first check the manufacturer from the IPMI
394  * device ID, and will return EIPMI_NOT_SUPPORTED if attempted for non-Sun
395  * devices.
396  */
397 
398 /*
399  * Sun OEM LED requests.
400  */
401 
402 #define	IPMI_CMD_SUNOEM_LED_GET		0x21
403 #define	IPMI_CMD_SUNOEM_LED_SET		0x22
404 
405 typedef struct ipmi_cmd_sunoem_led_set {
406 	uint8_t		ic_sls_devaddr;		/* device slave address */
407 	uint8_t		ic_sls_type;		/* led type */
408 	uint8_t		ic_sls_ctladdr;		/* controller address */
409 	uint8_t		ic_sls_hwinfo;		/* OEM hardware info */
410 	uint8_t		ic_sls_mode;		/* LED mode */
411 	uint8_t		ic_sls_force;		/* force direct access */
412 	uint8_t		ic_sls_role;		/* BMC authorization */
413 } ipmi_cmd_sunoem_led_set_t;
414 
415 typedef struct ipmi_cmd_sunoem_led_get {
416 	uint8_t		ic_slg_devaddr;		/* device slave address */
417 	uint8_t		ic_slg_type;		/* led type */
418 	uint8_t		ic_slg_ctladdr;		/* controller address */
419 	uint8_t		ic_slg_hwinfo;		/* OEM hardware info */
420 	uint8_t		ic_slg_force;		/* force direct access */
421 } ipmi_cmd_sunoem_led_get_t;
422 
423 #define	IPMI_SUNOEM_LED_TYPE_OK2RM	0
424 #define	IPMI_SUNOEM_LED_TYPE_SERVICE	1
425 #define	IPMI_SUNOEM_LED_TYPE_ACT	2
426 #define	IPMI_SUNOEM_LED_TYPE_LOCATE	3
427 #define	IPMI_SUNOEM_LED_TYPE_ANY	0xFF
428 
429 #define	IPMI_SUNOEM_LED_MODE_OFF	0
430 #define	IPMI_SUNOEM_LED_MODE_ON		1
431 #define	IPMI_SUNOEM_LED_MODE_STANDBY	2
432 #define	IPMI_SUNOEM_LED_MODE_SLOW	3
433 #define	IPMI_SUNOEM_LED_MODE_FAST	4
434 
435 /*
436  * These functions take a SDR record and construct the appropriate form of the
437  * above commands.
438  */
439 extern int ipmi_sunoem_led_set(ipmi_handle_t *,
440     ipmi_sdr_generic_locator_t *, uint8_t);
441 extern int ipmi_sunoem_led_get(ipmi_handle_t *,
442     ipmi_sdr_generic_locator_t *, uint8_t *);
443 
444 /*
445  * Sun OEM uptime.  Note that the underlying command returns the uptime in big
446  * endian form.  This wrapper automatically converts to the appropriate native
447  * form.
448  */
449 
450 #define	IPMI_CMD_SUNOEM_UPTIME		0x08
451 
452 extern int ipmi_sunoem_uptime(ipmi_handle_t *, uint32_t *, uint32_t *);
453 
454 /*
455  * Sun OEM FRU update.  The FRU information is managed through a generic
456  * identifier, and then a type-specific data portion.  The wrapper function will
457  * automatically fill in the data length field according to which type is
458  * specified.
459  */
460 
461 #define	IPMI_CMD_SUNOEM_FRU_UPDATE	0x16
462 
463 #define	IPMI_SUNOEM_FRU_DIMM	0x00
464 #define	IPMI_SUNOEM_FRU_CPU	0x01
465 #define	IPMI_SUNOEM_FRU_BIOS	0x02
466 #define	IPMI_SUNOEM_FRU_DISK	0x03
467 
468 typedef struct ipmi_sunoem_fru {
469 	uint8_t				isf_type;
470 	uint8_t				isf_id;
471 	uint8_t				isf_datalen;
472 	union {
473 		struct {
474 			uint8_t		isf_data[128];
475 		} dimm;
476 		struct {
477 			uint32_t	isf_thermtrip;
478 			uint32_t	isf_eax;
479 			char		isf_product[48];
480 		} cpu;
481 		struct {
482 			char		isf_part[16];
483 			char		isf_version[16];
484 		} bios;
485 		struct {
486 			char		isf_manufacturer[16];
487 			char		isf_model[28];
488 			char		isf_serial[20];
489 			char		isf_version[8];
490 			char		isf_capacity[16];
491 		} disk;
492 	} isf_data;
493 } ipmi_sunoem_fru_t;
494 
495 int ipmi_sunoem_update_fru(ipmi_handle_t *, ipmi_sunoem_fru_t *);
496 
497 #pragma pack()
498 
499 #ifdef	__cplusplus
500 }
501 #endif
502 
503 #endif	/* _LIBIPMI_H */
504