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