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_FIELDS_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 * These IPMI message id/opcodes are documented in Appendix G in the IPMI spec. 393 * 394 * Payloads for these two commands are described in Sections 34.1 and 34.2 of 395 * the spec, respectively. 396 */ 397 #define IPMI_CMD_GET_FRU_INV_AREA 0x10 398 #define IPMI_CMD_READ_FRU_DATA 0x11 399 400 /* 401 * Structs to hold the FRU Common Header and the FRU Product Info Area, as 402 * described in the IPMI Platform Management FRU Information Storage 403 * Definition (v1.1). 404 */ 405 typedef struct ipmi_fru_hdr 406 { 407 uint8_t ifh_format; 408 uint8_t ifh_int_use_off; 409 uint8_t ifh_chassis_info_off; 410 uint8_t ifh_board_info_off; 411 uint8_t ifh_product_info_off; 412 uint8_t ifh_multi_rec_off; 413 uint8_t ifh_pad; 414 uint8_t ifh_chksum; 415 } ipmi_fru_hdr_t; 416 417 /* 418 * Because only 6 bits are used to specify the length of each field in the FRU 419 * product and board info areas, the biggest string we would ever need to hold 420 * would be 63 chars plus a NULL. 421 */ 422 #define FRU_INFO_MAXLEN 64 423 424 typedef struct ipmi_fru_brd_info 425 { 426 char ifbi_manuf_date[3]; 427 char ifbi_manuf_name[FRU_INFO_MAXLEN]; 428 char ifbi_board_name[FRU_INFO_MAXLEN]; 429 char ifbi_product_serial[FRU_INFO_MAXLEN]; 430 char ifbi_part_number[FRU_INFO_MAXLEN]; 431 } ipmi_fru_brd_info_t; 432 433 typedef struct ipmi_fru_prod_info 434 { 435 char ifpi_manuf_name[FRU_INFO_MAXLEN]; 436 char ifpi_product_name[FRU_INFO_MAXLEN]; 437 char ifpi_part_number[FRU_INFO_MAXLEN]; 438 char ifpi_product_version[FRU_INFO_MAXLEN]; 439 char ifpi_product_serial[FRU_INFO_MAXLEN]; 440 char ifpi_asset_tag[FRU_INFO_MAXLEN]; 441 } ipmi_fru_prod_info_t; 442 443 int ipmi_fru_read(ipmi_handle_t *, ipmi_sdr_fru_locator_t *, char **); 444 int ipmi_fru_parse_board(ipmi_handle_t *, char *, ipmi_fru_brd_info_t *); 445 int ipmi_fru_parse_product(ipmi_handle_t *, char *, ipmi_fru_prod_info_t *); 446 447 /* 448 * The remaining functions are private to the implementation of the Sun ILOM 449 * service processor. These function first check the manufacturer from the IPMI 450 * device ID, and will return EIPMI_NOT_SUPPORTED if attempted for non-Sun 451 * devices. 452 */ 453 454 /* 455 * Sun OEM LED requests. 456 */ 457 458 #define IPMI_CMD_SUNOEM_LED_GET 0x21 459 #define IPMI_CMD_SUNOEM_LED_SET 0x22 460 461 typedef struct ipmi_cmd_sunoem_led_set { 462 #if defined(_BIT_FIELDS_LTOH) 463 uint8_t ic_sls_channel_msb:1; /* device slave address */ 464 uint8_t ic_sls_slaveaddr:7; /* (from SDR record) */ 465 #else 466 uint8_t ic_sls_slaveaddr:7; 467 uint8_t ic_sls_channel_msb:1; 468 #endif 469 uint8_t ic_sls_type; /* led type */ 470 #if defined(_BIT_FIELDS_LTOH) 471 uint8_t __reserved:1; /* device access address */ 472 uint8_t ic_sls_accessaddr:7; /* (from SDR record) */ 473 #else 474 uint8_t ic_sls_accessaddr:7; 475 uint8_t __reserved:1; 476 #endif 477 uint8_t ic_sls_hwinfo; /* OEM hardware info */ 478 uint8_t ic_sls_mode; /* LED mode */ 479 uint8_t ic_sls_force; /* force direct access */ 480 uint8_t ic_sls_role; /* BMC authorization */ 481 } ipmi_cmd_sunoem_led_set_t; 482 483 typedef struct ipmi_cmd_sunoem_led_get { 484 #if defined(_BIT_FIELDS_LTOH) 485 uint8_t ic_slg_channel_msb:1; /* device slave address */ 486 uint8_t ic_slg_slaveaddr:7; /* (from SDR record) */ 487 #else 488 uint8_t ic_slg_slaveaddr:7; 489 uint8_t ic_slg_channel_msb:1; 490 #endif 491 uint8_t ic_slg_type; /* led type */ 492 #if defined(_BIT_FIELDS_LTOH) 493 uint8_t __reserved:1; /* device access address */ 494 uint8_t ic_slg_accessaddr:7; /* (from SDR record) */ 495 #else 496 uint8_t ic_slg_accessaddr:7; 497 uint8_t __reserved:1; 498 #endif 499 uint8_t ic_slg_hwinfo; /* OEM hardware info */ 500 uint8_t ic_slg_force; /* force direct access */ 501 } ipmi_cmd_sunoem_led_get_t; 502 503 #define IPMI_SUNOEM_LED_TYPE_OK2RM 0 504 #define IPMI_SUNOEM_LED_TYPE_SERVICE 1 505 #define IPMI_SUNOEM_LED_TYPE_ACT 2 506 #define IPMI_SUNOEM_LED_TYPE_LOCATE 3 507 #define IPMI_SUNOEM_LED_TYPE_ANY 0xFF 508 509 #define IPMI_SUNOEM_LED_MODE_OFF 0 510 #define IPMI_SUNOEM_LED_MODE_ON 1 511 #define IPMI_SUNOEM_LED_MODE_STANDBY 2 512 #define IPMI_SUNOEM_LED_MODE_SLOW 3 513 #define IPMI_SUNOEM_LED_MODE_FAST 4 514 515 /* 516 * These functions take a SDR record and construct the appropriate form of the 517 * above commands. 518 */ 519 extern int ipmi_sunoem_led_set(ipmi_handle_t *, 520 ipmi_sdr_generic_locator_t *, uint8_t); 521 extern int ipmi_sunoem_led_get(ipmi_handle_t *, 522 ipmi_sdr_generic_locator_t *, uint8_t *); 523 524 /* 525 * Sun OEM uptime. Note that the underlying command returns the uptime in big 526 * endian form. This wrapper automatically converts to the appropriate native 527 * form. 528 */ 529 530 #define IPMI_CMD_SUNOEM_UPTIME 0x08 531 532 extern int ipmi_sunoem_uptime(ipmi_handle_t *, uint32_t *, uint32_t *); 533 534 /* 535 * Sun OEM FRU update. The FRU information is managed through a generic 536 * identifier, and then a type-specific data portion. The wrapper function will 537 * automatically fill in the data length field according to which type is 538 * specified. 539 */ 540 541 #define IPMI_CMD_SUNOEM_FRU_UPDATE 0x16 542 543 #define IPMI_SUNOEM_FRU_DIMM 0x00 544 #define IPMI_SUNOEM_FRU_CPU 0x01 545 #define IPMI_SUNOEM_FRU_BIOS 0x02 546 #define IPMI_SUNOEM_FRU_DISK 0x03 547 548 typedef struct ipmi_sunoem_fru { 549 uint8_t isf_type; 550 uint8_t isf_id; 551 uint8_t isf_datalen; 552 union { 553 struct { 554 uint8_t isf_data[128]; 555 } dimm; 556 struct { 557 uint32_t isf_thermtrip; 558 uint32_t isf_eax; 559 char isf_product[48]; 560 } cpu; 561 struct { 562 char isf_part[16]; 563 char isf_version[16]; 564 } bios; 565 struct { 566 char isf_manufacturer[16]; 567 char isf_model[28]; 568 char isf_serial[20]; 569 char isf_version[8]; 570 char isf_capacity[16]; 571 } disk; 572 } isf_data; 573 } ipmi_sunoem_fru_t; 574 575 int ipmi_sunoem_update_fru(ipmi_handle_t *, ipmi_sunoem_fru_t *); 576 577 #pragma pack() 578 579 #ifdef __cplusplus 580 } 581 #endif 582 583 #endif /* _LIBIPMI_H */ 584