view usr/src/lib/libipmi/common/libipmi.h @ 5068:06d88145c7f7

6492246 x64 cpu/mem topology/diagnosis should include FRU labels 6552234 Add propset/propmethod/propmap support to topology XML schema and libtopo parsing engine 6562046 libtopo dcmds cause mdb crash 6577125 fmtopo coredumps in print_fmri_props 6577127 wrong topo_method_invoke return code when method versions mismatch 6578581 using fmsim in root account. The fmsim can not be started. 6601280 add interfaces to libipmi to simplify access to fru inventory
author robj
date Mon, 17 Sep 2007 12:24:38 -0700
parents 5cd7916484a5
children 44060de1d838
line wrap: on
line source

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_LIBIPMI_H
#define	_LIBIPMI_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/bmc_intf.h>
#include <sys/byteorder.h>

/*
 * Private interfaces for communicating with attached services over IPMI.  This
 * library is designed for system software communicating with Sun-supported
 * service processors over /dev/bmc.  It is not a generic IPMI library.
 *
 * Documentation references refer to "Intelligent Platform Management Interface
 * Specification Second Generation v2.0", document revision 1.0 with Februrary
 * 15, 2006 Markup from "IPMI v2.0 Addenda, Errata, and Clarifications Revision
 * 3".
 */

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct ipmi_handle ipmi_handle_t;

#if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL)
#error  One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
#endif

#pragma pack(1)

/*
 * Basic netfn definitions.  See section 5.1.
 */
#define	IPMI_NETFN_APP			BMC_NETFN_APP
#define	IPMI_NETFN_STORAGE		BMC_NETFN_STORAGE
#define	IPMI_NETFN_SE			BMC_NETFN_SE
#define	IPMI_NETFN_OEM			0x2e

/*
 * Error definitions
 */
#define	EIPMI_BASE	2000

enum {
	EIPMI_NOMEM = EIPMI_BASE,	/* memory allocation failure */
	EIPMI_BMC_OPEN_FAILED,		/* failed to open /dev/bmc */
	EIPMI_BMC_PUTMSG,		/* putmsg() failed */
	EIPMI_BMC_GETMSG,		/* getmsg() failed */
	EIPMI_BMC_RESPONSE,		/* response from /dev/bmc failed */
	EIPMI_INVALID_COMMAND,		/* invalid command */
	EIPMI_COMMAND_TIMEOUT,		/* command timeout */
	EIPMI_DATA_LENGTH_EXCEEDED,	/* maximum data length exceeded */
	EIPMI_SEND_FAILED,		/* failed to send BMC request */
	EIPMI_UNSPECIFIED,		/* unspecified error */
	EIPMI_UNKNOWN,			/* unknown error */
	EIPMI_BAD_RESPONSE,		/* received unexpected response */
	EIPMI_BAD_RESPONSE_LENGTH,	/* unexpected response length */
	EIPMI_INVALID_RESERVATION,	/* invalid reservation */
	EIPMI_NOT_PRESENT,		/* requested entity not present */
	EIPMI_INVALID_REQUEST,		/* malformed request */
	EIPMI_BUSY,			/* SP is busy */
	EIPMI_NOSPACE,			/* SP is out of space */
	EIPMI_UNAVAILABLE,		/* SP is present but unavailable */
	EIPMI_ACCESS			/* insufficient privileges */
};

/*
 * Basic library functions.
 *
 * The ipmi_handle is the primary interface to the library.  The library itself
 * is not MT-safe, but it is safe within a single handle.  Multithreaded clients
 * should either open multiple handles, or otherwise synchronize access to the
 * same handle.
 *
 * There is a single command response buffer that is stored with the handle, to
 * simplify memory management in the caller.  The memory referenced by a command
 * response is only valid until the next command is issued.  The caller is
 * responsible for making a copy of the response if it is needed.
 */
extern ipmi_handle_t *ipmi_open(int *, char **);
extern void ipmi_close(ipmi_handle_t *);

extern int ipmi_errno(ipmi_handle_t *);
extern const char *ipmi_errmsg(ipmi_handle_t *);

/*
 * Raw requests.  See section 5.
 */
typedef struct ipmi_cmd {
	uint8_t		ic_netfn:6;
	uint8_t		ic_lun:2;
	uint8_t		ic_cmd;
	uint16_t	ic_dlen;
	void		*ic_data;
} ipmi_cmd_t;

extern ipmi_cmd_t *ipmi_send(ipmi_handle_t *, ipmi_cmd_t *);

/*
 * Retrieve basic information about the IPMI device.  See section 20.1 "Get
 * Device ID Command".
 */
#define	IPMI_CMD_GET_DEVICEID		0x01

typedef struct ipmi_deviceid {
	uint8_t		id_devid;
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		id_dev_rev:4;
	uint8_t		__reserved:3;
	uint8_t		id_dev_sdrs:1;
#else
	uint8_t		id_dev_sdrs:1;
	uint8_t		__reserved:3;
	uint8_t		id_dev_rev:4;
#endif
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		id_firm_major:7;
	uint8_t		id_dev_available:1;
#else
	uint8_t		id_dev_available:1;
	uint8_t		id_firm_major:7;
#endif
	uint8_t		id_firm_minor;
	uint8_t		id_ipmi_rev;
	uint8_t		id_dev_support;
	uint8_t		id_manufacturer[3];
	uint16_t	id_product;
} ipmi_deviceid_t;

#define	IPMI_OEM_SUN	0x2a

ipmi_deviceid_t *ipmi_get_deviceid(ipmi_handle_t *);

#define	ipmi_devid_manufacturer(dp)		\
	((dp)->id_manufacturer[0] |		\
	((dp)->id_manufacturer[1] << 8) |	\
	((dp)->id_manufacturer[2] << 16))

/*
 * SDR (Sensor Device Record) requests.  A cache of the current SDR repository
 * is kept as part of the IPMI handle and updated when necessary.  Routines to
 * access the raw SDR repository are also provided.
 */

/*
 * Reserve repository command.  See section 33.11.
 */
#define	IPMI_CMD_RESERVE_SDR_REPOSITORY	0x22

/*
 * Get SDR command.  See section 33.12.  This command accesses the raw SDR
 * repository.  Clients can also use the lookup functions to retrieve a
 * particular SDR record by name.
 *
 * The list of possible types is indicated in the sub-chapters of section 43.
 */
typedef struct ipmi_sdr {
	uint16_t	is_id;
	uint8_t		is_version;
	uint8_t		is_type;
	uint8_t		is_length;
	uint8_t		is_record[1];
} ipmi_sdr_t;
#define	IPMI_CMD_GET_SDR		0x23

#define	IPMI_SDR_FIRST			0x0000
#define	IPMI_SDR_LAST			0xFFFF

extern ipmi_sdr_t *ipmi_sdr_get(ipmi_handle_t *, uint16_t, uint16_t *);

/*
 * Generic Device Locator Record.  See section 43.7.
 */

#define	IPMI_SDR_TYPE_GENERIC_LOCATOR		0x10

typedef struct ipmi_sdr_generic_locator {
	/* RECORD KEY BYTES */
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		__reserved1:1;
	uint8_t		is_gl_accessaddr:7;
	uint8_t		is_gl_channel_msb:1;
	uint8_t		is_gl_slaveaddr:7;
	uint8_t		is_gl_bus:3;
	uint8_t		is_gl_lun:2;
	uint8_t		is_gl_channel:3;
#else
	uint8_t		is_gl_accessaddr:7;
	uint8_t		__reserved1:1;
	uint8_t		is_gl_slaveaddr:7;
	uint8_t		is_gl_channel_msb:1;
	uint8_t		is_gl_channel:3;
	uint8_t		is_gl_lun:2;
	uint8_t		is_gl_bus:3;
#endif
	/* RECORD BODY BYTES */
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		is_gl_span:3;
	uint8_t		__reserved2:5;
#else
	uint8_t		__reserved2:5;
	uint8_t		is_gl_span:3;
#endif
	uint8_t		__reserved3;
	uint8_t		is_gl_type;
	uint8_t		is_gl_modifier;
	uint8_t		is_gl_entity;
	uint8_t		is_gl_instance;
	uint8_t		is_gl_oem;
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		is_gl_idlen:6;
	uint8_t		is_gl_idtype:2;
#else
	uint8_t		is_gl_idtype:2;
	uint8_t		is_gl_idlen:6;
#endif
	char		is_gl_idstring[1];
} ipmi_sdr_generic_locator_t;

/*
 * FRU Device Locator Record.  See section 43.8.
 */

#define	IPMI_SDR_TYPE_FRU_LOCATOR		0x11

typedef struct ipmi_sdr_fru_locator {
	/* RECORD KEY BYTES */
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		__reserved1:1;
	uint8_t		is_fl_accessaddr:7;
#else
	uint8_t		is_fl_accessaddr:7;
	uint8_t		__reserved1:1;
#endif
	union {
		struct {
			uint8_t	_is_fl_devid;
		} _logical;
		struct {
#if defined(_BIT_FIELDS_LTOH)
			uint8_t	__reserved:1;
			uint8_t	_is_fl_slaveaddr:7;
#else
			uint8_t	_is_fl_slaveaddr:7;
			uint8_t	__reserved:1;
#endif
		} _nonintelligent;
	} _devid_or_slaveaddr;
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		is_fl_bus:3;
	uint8_t		is_fl_lun:2;
	uint8_t		__reserved2:2;
	uint8_t		is_fl_logical:1;
	uint8_t		__reserved3:4;
	uint8_t		is_fl_channel:4;
#else
	uint8_t		is_fl_logical:1;
	uint8_t		__reserved2:2;
	uint8_t		is_fl_lun:2;
	uint8_t		is_fl_bus:3;
	uint8_t		is_fl_channel:4;
	uint8_t		__reserved3:4;
#endif
	/* RECORD BODY BYTES */
	uint8_t		__reserved4;
	uint8_t		is_fl_type;
	uint8_t		is_fl_modifier;
	uint8_t		is_fl_entity;
	uint8_t		is_fl_instance;
	uint8_t		is_fl_oem;
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		is_fl_idlen:6;
	uint8_t		is_fl_idtype:2;
#else
	uint8_t		is_fl_idtype:2;
	uint8_t		is_fl_idlen:6;
#endif
	char		is_fl_idstring[1];
} ipmi_sdr_fru_locator_t;

#define	is_fl_devid	_devid_or_slaveaddr._logical._is_fl_devid
#define	is_fl_slaveaddr	_devid_or_slaveaddr._nonintelligent._is_fl_slaveaddr

/*
 * The remaining SDR types do not have an associated structure, yet.
 */
#define	IPMI_SDR_TYPE_FULL_SENSOR		0x01
#define	IPMI_SDR_TYPE_COMPACT_SENSOR		0x02
#define	IPMI_SDR_TYPE_EVENT_ONLY		0x03
#define	IPMI_SDR_TYPE_ENTITY_ASSOCIATION	0x08
#define	IPMI_SDR_TYPE_DEVICE_RELATIVE		0x09
#define	IPMI_SDR_TYPE_MANAGEMENT_DEVICE		0x12
#define	IPMI_SDR_TYPE_MANAGEMENT_CONFIRMATION	0x13
#define	IPMI_SDR_TYPE_BMC_MESSAGE_CHANNEL	0x14
#define	IPMI_SDR_TYPE_OEM			0xC0

/*
 * Lookup the given sensor type by name.  These functions automatically read in
 * and cache the complete SDR repository.
 */
extern ipmi_sdr_fru_locator_t *ipmi_sdr_lookup_fru(ipmi_handle_t *,
    const char *);
extern ipmi_sdr_generic_locator_t *ipmi_sdr_lookup_generic(ipmi_handle_t *,
    const char *);

/*
 * Get Sensor Reading.  See section 35.14.
 */

#define	IPMI_CMD_GET_SENSOR_READING	0x2d

typedef struct ipmi_sensor_reading {
	uint8_t		isr_reading;
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		__reserved1:5;
	uint8_t		isr_state_unavailable:1;
	uint8_t		isr_scanning_disabled:1;
	uint8_t		isr_event_disabled:1;
#else
	uint8_t		isr_event_disabled:1;
	uint8_t		isr_scanning_disabled:1;
	uint8_t		isr_state_unavailable:1;
	uint8_t		__reserved1:5;
#endif
	uint16_t	isr_state;
} ipmi_sensor_reading_t;

extern ipmi_sensor_reading_t *ipmi_get_sensor_reading(ipmi_handle_t *, uint8_t);

/*
 * Set Sensor Reading.  See section 35.14.
 */
#define	IPMI_CMD_SET_SENSOR_READING	0x30

#define	IPMI_SENSOR_OP_CLEAR	0x3	/* clear '0' bits */
#define	IPMI_SENSOR_OP_SET	0x2	/* set '1' bits */
#define	IPMI_SENSOR_OP_EXACT	0x1	/* set bits exactly */

typedef struct ipmi_set_sensor_reading {
	uint8_t		iss_id;
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		iss_set_reading:1;
	uint8_t		__reserved:1;
	uint8_t		iss_deassrt_op:2;
	uint8_t		iss_assert_op:2;
	uint8_t		iss_data_bytes:2;
#else
	uint8_t		iss_data_bytes:2;
	uint8_t		iss_assert_op:2;
	uint8_t		iss_deassrt_op:2;
	uint8_t		__reserved:1;
	uint8_t		iss_set_reading:1;
#endif
	uint8_t		iss_sensor_reading;
	uint16_t	iss_assert_state;	/* optional */
	uint16_t	iss_deassert_state;	/* optional */
	uint8_t		iss_event_data1;	/* optional */
	uint8_t		iss_event_data2;	/* optional */
	uint8_t		iss_event_data3;	/* optional */
} ipmi_set_sensor_reading_t;

extern int ipmi_set_sensor_reading(ipmi_handle_t *,
    ipmi_set_sensor_reading_t *);

/*
 * These IPMI message id/opcodes are documented in Appendix G in the IPMI spec.
 *
 * Payloads for these two commands are described in Sections 34.1 and 34.2 of
 * the spec, respectively.
 */
#define	IPMI_CMD_GET_FRU_INV_AREA	0x10
#define	IPMI_CMD_READ_FRU_DATA		0x11

/*
 * Structs to hold the FRU Common Header and the FRU Product Info Area, as
 * described in the IPMI Platform Management FRU Information Storage
 * Definition (v1.1).
 */
typedef struct ipmi_fru_hdr
{
	uint8_t		ifh_format;
	uint8_t		ifh_int_use_off;
	uint8_t		ifh_chassis_info_off;
	uint8_t		ifh_board_info_off;
	uint8_t		ifh_product_info_off;
	uint8_t		ifh_multi_rec_off;
	uint8_t		ifh_pad;
	uint8_t		ifh_chksum;
} ipmi_fru_hdr_t;

/*
 * Because only 6 bits are used to specify the length of each field in the FRU
 * product and board info areas, the biggest string we would ever need to hold
 * would be 63 chars plus a NULL.
 */
#define	FRU_INFO_MAXLEN	64

typedef struct ipmi_fru_brd_info
{
	char	ifbi_manuf_date[3];
	char	ifbi_manuf_name[FRU_INFO_MAXLEN];
	char	ifbi_board_name[FRU_INFO_MAXLEN];
	char	ifbi_product_serial[FRU_INFO_MAXLEN];
	char	ifbi_part_number[FRU_INFO_MAXLEN];
} ipmi_fru_brd_info_t;

typedef struct ipmi_fru_prod_info
{
	char	ifpi_manuf_name[FRU_INFO_MAXLEN];
	char	ifpi_product_name[FRU_INFO_MAXLEN];
	char	ifpi_part_number[FRU_INFO_MAXLEN];
	char	ifpi_product_version[FRU_INFO_MAXLEN];
	char	ifpi_product_serial[FRU_INFO_MAXLEN];
	char	ifpi_asset_tag[FRU_INFO_MAXLEN];
} ipmi_fru_prod_info_t;

int ipmi_fru_read(ipmi_handle_t *, ipmi_sdr_fru_locator_t *, char **);
int ipmi_fru_parse_board(ipmi_handle_t *, char *, ipmi_fru_brd_info_t *);
int ipmi_fru_parse_product(ipmi_handle_t *, char *, ipmi_fru_prod_info_t *);

/*
 * The remaining functions are private to the implementation of the Sun ILOM
 * service processor.  These function first check the manufacturer from the IPMI
 * device ID, and will return EIPMI_NOT_SUPPORTED if attempted for non-Sun
 * devices.
 */

/*
 * Sun OEM LED requests.
 */

#define	IPMI_CMD_SUNOEM_LED_GET		0x21
#define	IPMI_CMD_SUNOEM_LED_SET		0x22

typedef struct ipmi_cmd_sunoem_led_set {
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		ic_sls_channel_msb:1;	/* device slave address */
	uint8_t		ic_sls_slaveaddr:7;	/* (from SDR record) */
#else
	uint8_t		ic_sls_slaveaddr:7;
	uint8_t		ic_sls_channel_msb:1;
#endif
	uint8_t		ic_sls_type;		/* led type */
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		__reserved:1;		/* device access address */
	uint8_t		ic_sls_accessaddr:7;	/* (from SDR record) */
#else
	uint8_t		ic_sls_accessaddr:7;
	uint8_t		__reserved:1;
#endif
	uint8_t		ic_sls_hwinfo;		/* OEM hardware info */
	uint8_t		ic_sls_mode;		/* LED mode */
	uint8_t		ic_sls_force;		/* force direct access */
	uint8_t		ic_sls_role;		/* BMC authorization */
} ipmi_cmd_sunoem_led_set_t;

typedef struct ipmi_cmd_sunoem_led_get {
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		ic_slg_channel_msb:1;	/* device slave address */
	uint8_t		ic_slg_slaveaddr:7;	/* (from SDR record) */
#else
	uint8_t		ic_slg_slaveaddr:7;
	uint8_t		ic_slg_channel_msb:1;
#endif
	uint8_t		ic_slg_type;		/* led type */
#if defined(_BIT_FIELDS_LTOH)
	uint8_t		__reserved:1;		/* device access address */
	uint8_t		ic_slg_accessaddr:7;	/* (from SDR record) */
#else
	uint8_t		ic_slg_accessaddr:7;
	uint8_t		__reserved:1;
#endif
	uint8_t		ic_slg_hwinfo;		/* OEM hardware info */
	uint8_t		ic_slg_force;		/* force direct access */
} ipmi_cmd_sunoem_led_get_t;

#define	IPMI_SUNOEM_LED_TYPE_OK2RM	0
#define	IPMI_SUNOEM_LED_TYPE_SERVICE	1
#define	IPMI_SUNOEM_LED_TYPE_ACT	2
#define	IPMI_SUNOEM_LED_TYPE_LOCATE	3
#define	IPMI_SUNOEM_LED_TYPE_ANY	0xFF

#define	IPMI_SUNOEM_LED_MODE_OFF	0
#define	IPMI_SUNOEM_LED_MODE_ON		1
#define	IPMI_SUNOEM_LED_MODE_STANDBY	2
#define	IPMI_SUNOEM_LED_MODE_SLOW	3
#define	IPMI_SUNOEM_LED_MODE_FAST	4

/*
 * These functions take a SDR record and construct the appropriate form of the
 * above commands.
 */
extern int ipmi_sunoem_led_set(ipmi_handle_t *,
    ipmi_sdr_generic_locator_t *, uint8_t);
extern int ipmi_sunoem_led_get(ipmi_handle_t *,
    ipmi_sdr_generic_locator_t *, uint8_t *);

/*
 * Sun OEM uptime.  Note that the underlying command returns the uptime in big
 * endian form.  This wrapper automatically converts to the appropriate native
 * form.
 */

#define	IPMI_CMD_SUNOEM_UPTIME		0x08

extern int ipmi_sunoem_uptime(ipmi_handle_t *, uint32_t *, uint32_t *);

/*
 * Sun OEM FRU update.  The FRU information is managed through a generic
 * identifier, and then a type-specific data portion.  The wrapper function will
 * automatically fill in the data length field according to which type is
 * specified.
 */

#define	IPMI_CMD_SUNOEM_FRU_UPDATE	0x16

#define	IPMI_SUNOEM_FRU_DIMM	0x00
#define	IPMI_SUNOEM_FRU_CPU	0x01
#define	IPMI_SUNOEM_FRU_BIOS	0x02
#define	IPMI_SUNOEM_FRU_DISK	0x03

typedef struct ipmi_sunoem_fru {
	uint8_t				isf_type;
	uint8_t				isf_id;
	uint8_t				isf_datalen;
	union {
		struct {
			uint8_t		isf_data[128];
		} dimm;
		struct {
			uint32_t	isf_thermtrip;
			uint32_t	isf_eax;
			char		isf_product[48];
		} cpu;
		struct {
			char		isf_part[16];
			char		isf_version[16];
		} bios;
		struct {
			char		isf_manufacturer[16];
			char		isf_model[28];
			char		isf_serial[20];
			char		isf_version[8];
			char		isf_capacity[16];
		} disk;
	} isf_data;
} ipmi_sunoem_fru_t;

int ipmi_sunoem_update_fru(ipmi_handle_t *, ipmi_sunoem_fru_t *);

#pragma pack()

#ifdef	__cplusplus
}
#endif

#endif	/* _LIBIPMI_H */