1 /* 2 * Copyright (C) 2003-2015 FreeIPMI Core Team 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 */ 18 19 #ifndef IPMI_SEL_H 20 #define IPMI_SEL_H 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 #include <stdint.h> 27 #include <freeipmi/api/ipmi-api.h> 28 #include <freeipmi/cmds/ipmi-sel-cmds.h> 29 #include <freeipmi/interpret/ipmi-interpret.h> 30 #include <freeipmi/sdr/ipmi-sdr.h> 31 32 #define IPMI_SEL_ERR_SUCCESS 0 33 #define IPMI_SEL_ERR_CONTEXT_NULL 1 34 #define IPMI_SEL_ERR_CONTEXT_INVALID 2 35 #define IPMI_SEL_ERR_PARAMETERS 3 36 #define IPMI_SEL_ERR_OUT_OF_MEMORY 4 37 #define IPMI_SEL_ERR_SDR_CACHE_ERROR 5 38 #define IPMI_SEL_ERR_SEL_ENTRIES_NOT_LOADED 6 39 #define IPMI_SEL_ERR_NO_SEL_ENTRIES 7 40 #define IPMI_SEL_ERR_SEL_ENTRIES_LIST_END 8 41 #define IPMI_SEL_ERR_INVALID_SEL_ENTRY 9 42 #define IPMI_SEL_ERR_NOT_FOUND 10 43 #define IPMI_SEL_ERR_RESERVATION_CANCELED 11 44 #define IPMI_SEL_ERR_INTERPRET_ERROR 12 45 #define IPMI_SEL_ERR_CALLBACK_ERROR 13 46 #define IPMI_SEL_ERR_IPMI_ERROR 14 47 #define IPMI_SEL_ERR_SYSTEM_ERROR 15 48 #define IPMI_SEL_ERR_OVERFLOW 16 49 #define IPMI_SEL_ERR_INTERNAL_ERROR 17 50 #define IPMI_SEL_ERR_ERRNUMRANGE 18 51 52 #define IPMI_SEL_FLAGS_DEFAULT 0x0000 53 #define IPMI_SEL_FLAGS_DEBUG_DUMP 0x0001 54 #define IPMI_SEL_FLAGS_ASSUME_SYTEM_EVENT_RECORDS 0x0002 55 56 #define IPMI_SEL_PARAMETER_INTERPRET_CONTEXT 0x0001 57 #define IPMI_SEL_PARAMETER_UTC_OFFSET 0x0002 58 59 #define IPMI_SEL_STRING_FLAGS_DEFAULT 0x0000 60 #define IPMI_SEL_STRING_FLAGS_VERBOSE 0x0001 61 #define IPMI_SEL_STRING_FLAGS_IGNORE_UNAVAILABLE_FIELD 0x0002 62 #define IPMI_SEL_STRING_FLAGS_OUTPUT_NOT_AVAILABLE 0x0004 63 #define IPMI_SEL_STRING_FLAGS_DATE_USE_SLASH 0x0008 64 #define IPMI_SEL_STRING_FLAGS_DATE_MONTH_STRING 0x0010 65 #define IPMI_SEL_STRING_FLAGS_NON_ABBREVIATED_UNITS 0x0020 66 #define IPMI_SEL_STRING_FLAGS_ENTITY_SENSOR_NAMES 0x0040 67 #define IPMI_SEL_STRING_FLAGS_INTERPRET_OEM_DATA 0x0100 68 /* Timestamps are defined as localtime. If there are UTC and 69 * one wishes to output in localtime, this flag will do so. 70 */ 71 #define IPMI_SEL_STRING_FLAGS_UTC_TO_LOCALTIME 0x0200 72 /* Convert localtimes to UTC times, as it may be convenient 73 * for certain purposes. 74 */ 75 #define IPMI_SEL_STRING_FLAGS_LOCALTIME_TO_UTC 0x0400 76 #define IPMI_SEL_STRING_FLAGS_LEGACY 0x1000 77 78 #define IPMI_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD 0x0 79 #define IPMI_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD 0x1 80 #define IPMI_SEL_RECORD_TYPE_CLASS_NON_TIMESTAMPED_OEM_RECORD 0x2 81 #define IPMI_SEL_RECORD_TYPE_CLASS_UNKNOWN 0x3 82 83 #define IPMI_SEL_RECORD_ID_FIRST IPMI_SEL_GET_RECORD_ID_FIRST_ENTRY 84 #define IPMI_SEL_RECORD_ID_LAST IPMI_SEL_GET_RECORD_ID_LAST_ENTRY 85 86 typedef struct ipmi_sel_ctx *ipmi_sel_ctx_t; 87 88 typedef int (*Ipmi_Sel_Parse_Callback)(ipmi_sel_ctx_t ctx, void *callback_data); 89 90 /* 91 * SEL Context Functions 92 */ 93 94 /* ipmi_sel_ctx_create 95 * - if specified, ipmi_ctx must be open and ready to go 96 * - if NULL ipmi_ctx, SEL ctx cannot be used for SEL reading, only parsing records 97 * - if specified, sdr_ctx cache must be open and ready for reading 98 * - if NULL sdr_ctx, sdr won't be used 99 */ 100 ipmi_sel_ctx_t ipmi_sel_ctx_create (ipmi_ctx_t ipmi_ctx, ipmi_sdr_ctx_t sdr_ctx); 101 void ipmi_sel_ctx_destroy (ipmi_sel_ctx_t ctx); 102 int ipmi_sel_ctx_errnum (ipmi_sel_ctx_t ctx); 103 char * ipmi_sel_ctx_strerror (int errnum); 104 char * ipmi_sel_ctx_errormsg (ipmi_sel_ctx_t ctx); 105 106 /* SEL Parse flag functions and settings functions */ 107 int ipmi_sel_ctx_get_flags (ipmi_sel_ctx_t ctx, unsigned int *flags); 108 int ipmi_sel_ctx_set_flags (ipmi_sel_ctx_t ctx, unsigned int flags); 109 110 /* for use w/ string parsing w/ IPMI_SEL_STRING_FLAGS_INTERPRET_OEM_DATA */ 111 int ipmi_sel_ctx_get_manufacturer_id (ipmi_sel_ctx_t ctx, uint32_t *manufacturer_id); 112 int ipmi_sel_ctx_set_manufacturer_id (ipmi_sel_ctx_t ctx, uint32_t manufacturer_id); 113 int ipmi_sel_ctx_get_product_id (ipmi_sel_ctx_t ctx, uint16_t *product_id); 114 int ipmi_sel_ctx_set_product_id (ipmi_sel_ctx_t ctx, uint16_t product_id); 115 int ipmi_sel_ctx_get_ipmi_version (ipmi_sel_ctx_t ctx, 116 uint8_t *ipmi_version_major, 117 uint8_t *ipmi_vesion_minor); 118 int ipmi_sel_ctx_set_ipmi_version (ipmi_sel_ctx_t ctx, 119 uint8_t ipmi_version_major, 120 uint8_t ipmi_version_minor); 121 /* get/set parameters 122 * 123 * For misc uses. 124 * 125 * INTERPRET_CONTEXT - for use with %I - see below. interpret_ctx 126 * assumed loaded with whatever config desired for interpretation 127 * 128 * UTC_OFFSET - specific UTC offset to apply to timestamps (int) 129 */ 130 int ipmi_sel_ctx_get_parameter (ipmi_sel_ctx_t ctx, 131 unsigned int parameter, 132 void *ptr); 133 134 /* Pass NULL as ptr for default value */ 135 int ipmi_sel_ctx_set_parameter (ipmi_sel_ctx_t ctx, 136 unsigned int parameter, 137 const void *ptr); 138 139 char *ipmi_sel_ctx_get_debug_prefix (ipmi_sel_ctx_t ctx); 140 int ipmi_sel_ctx_set_debug_prefix (ipmi_sel_ctx_t ctx, const char *debug_prefix); 141 142 /* determines separator between fields in string functions 143 * 144 * defaults to " | " 145 */ 146 char *ipmi_sel_ctx_get_separator (ipmi_sel_ctx_t ctx); 147 int ipmi_sel_ctx_set_separator (ipmi_sel_ctx_t ctx, const char *separator); 148 149 /* register/clear a reservation ID 150 * - Almost all SEL operations use a reservation ID. Generally 151 * speaking, it can be considered an advisory lock. The same 152 * reservation ID can be used for all "read" operations and will only 153 * be canceled when some "write" operation has occurred on the SEL. 154 * This "write" operation could be a new SEL event, a SEL event that 155 * was deleted, etc. 156 * - Normally, it is no big deal for a reservation ID to be canceled. 157 * The most normal circumstance is a new SEL event has been generated 158 * while reading the current list of SEL records. Therefore, under 159 * most circumstances, this library will simple re-retrieve a 160 * reservation ID once it has noticed one has been canceled. 161 * - These functions allow you to override the default functionality. 162 * You may inform the library to register a specific reservation ID 163 * and continue to use it for all SEL operations. In the event that 164 * it has been canceled, a IPMI_SEL_ERR_RESERVATION_CANCELED 165 * errnum will be returned. 166 * - These functions are predominantly useful for doing a set of 167 * operations and wanting to be informed of a possible race 168 * condition occurring. For example, perhaps you wish to read all 169 * the SEL records, log them, then clear them. There is a small 170 * window where a new SEL event could be generated, then cleared 171 * without the user knowing it ever existed. Use of a fixed 172 * reservation ID would be a mechanism to notice this. 173 * - In the event a reservation ID is canceled, it is up to the user 174 * to re-register a reservation ID, otherwise SEL operations will 175 * continue to default to grab its own reservation ID. 176 * - In ipmi_sel_ctx_register_reservation_id(), an optional 177 * reservation_id can be passed to see what reservation ID was 178 * specifically registered. 179 */ 180 int ipmi_sel_ctx_register_reservation_id (ipmi_sel_ctx_t ctx, uint16_t *reservation_id); 181 int ipmi_sel_ctx_clear_reservation_id (ipmi_sel_ctx_t ctx); 182 183 /* 184 * SEL Parse Functions 185 */ 186 187 /* ipmi_sel_parse and ipmi_sel_parse_record_ids 188 * - callback is called after each SEL entry is parsed 189 * - Returns the number of entries parsed 190 */ 191 int ipmi_sel_parse (ipmi_sel_ctx_t ctx, 192 uint16_t record_id_start, 193 uint16_t record_id_last, 194 Ipmi_Sel_Parse_Callback callback, 195 void *callback_data); 196 197 int ipmi_sel_parse_record_ids (ipmi_sel_ctx_t ctx, 198 uint16_t *record_ids, 199 unsigned int record_ids_len, 200 Ipmi_Sel_Parse_Callback callback, 201 void *callback_data); 202 203 /* SEL data retrieval functions after SEL is parsed 204 * 205 * seek_record_id moves the iterator to the closest record_id >= record_id 206 * search_record_id finds the record id, will return NOT_FOUND if it can't be found 207 */ 208 int ipmi_sel_parse_first (ipmi_sel_ctx_t ctx); 209 int ipmi_sel_parse_next (ipmi_sel_ctx_t ctx); 210 int ipmi_sel_parse_sel_entry_count (ipmi_sel_ctx_t ctx); 211 int ipmi_sel_parse_seek_record_id (ipmi_sel_ctx_t ctx, uint16_t record_id); 212 int ipmi_sel_parse_search_record_id (ipmi_sel_ctx_t ctx, uint16_t record_id); 213 214 /* return length of data read into buffer on success, -1 on error */ 215 int ipmi_sel_parse_read_record (ipmi_sel_ctx_t ctx, 216 void *buf, 217 unsigned int buflen); 218 219 /* SEL record parsing functions 220 * 221 * - if a sel_record is passed in, that sel_record is used for 222 * reading/parsing 223 * 224 * - if the sel_record is NULL sel_record_len is 0, the current sel 225 * parsed after ipmi_sel_parse() or ipmi_sel_parse_record_ids() is 226 * used. It can be the record used within the iterator functions 227 * (i.e. ipmi_sel_parse_next()) or in callbacks. 228 * 229 * - will return IPMI_SEL_ERR_INVALID_SEL_ENTRY if current sel 230 * entry is not appropriate for data requested. 231 */ 232 233 /* record_id & record_type - works with all SEL record types */ 234 int ipmi_sel_parse_read_record_id (ipmi_sel_ctx_t ctx, 235 const void *sel_record, 236 unsigned int sel_record_len, 237 uint16_t *record_id); 238 239 int ipmi_sel_parse_read_record_type (ipmi_sel_ctx_t ctx, 240 const void *sel_record, 241 unsigned int sel_record_len, 242 uint8_t *record_type); 243 244 /* timetamp - works with sel event and timestamped OEM record types */ 245 int ipmi_sel_parse_read_timestamp (ipmi_sel_ctx_t ctx, 246 const void *sel_record, 247 unsigned int sel_record_len, 248 uint32_t *timestamp); 249 250 /* generator_id, event message format version, sensor type, sensor 251 * number, event direction, event type code, and event data available 252 * form system event record type 253 */ 254 int ipmi_sel_parse_read_generator_id (ipmi_sel_ctx_t ctx, 255 const void *sel_record, 256 unsigned int sel_record_len, 257 uint8_t *generator_id); 258 259 int ipmi_sel_parse_read_ipmb_device_lun (ipmi_sel_ctx_t ctx, 260 const void *sel_record, 261 unsigned int sel_record_len, 262 uint8_t *ipmb_device_lun); 263 264 int ipmi_sel_parse_read_channel_number (ipmi_sel_ctx_t ctx, 265 const void *sel_record, 266 unsigned int sel_record_len, 267 uint8_t *channel_number); 268 269 int ipmi_sel_parse_read_event_message_format_version (ipmi_sel_ctx_t ctx, 270 const void *sel_record, 271 unsigned int sel_record_len, 272 uint8_t *event_message_format_version); 273 274 int ipmi_sel_parse_read_sensor_type (ipmi_sel_ctx_t ctx, 275 const void *sel_record, 276 unsigned int sel_record_len, 277 uint8_t *sensor_type); 278 279 int ipmi_sel_parse_read_sensor_number (ipmi_sel_ctx_t ctx, 280 const void *sel_record, 281 unsigned int sel_record_len, 282 uint8_t *sensor_number); 283 284 int ipmi_sel_parse_read_event_direction (ipmi_sel_ctx_t ctx, 285 const void *sel_record, 286 unsigned int sel_record_len, 287 uint8_t *event_direction); 288 289 int ipmi_sel_parse_read_event_type_code (ipmi_sel_ctx_t ctx, 290 const void *sel_record, 291 unsigned int sel_record_len, 292 uint8_t *event_type_code); 293 294 int ipmi_sel_parse_read_event_data1 (ipmi_sel_ctx_t ctx, 295 const void *sel_record, 296 unsigned int sel_record_len, 297 uint8_t *event_data1); 298 299 int ipmi_sel_parse_read_event_data1_offset_from_event_reading_type_code (ipmi_sel_ctx_t ctx, 300 const void *sel_record, 301 unsigned int sel_record_len, 302 uint8_t *event_data1_offset); 303 304 int ipmi_sel_parse_read_event_data1_event_data2_flag (ipmi_sel_ctx_t ctx, 305 const void *sel_record, 306 unsigned int sel_record_len, 307 uint8_t *event_data2_flag); 308 309 int ipmi_sel_parse_read_event_data1_event_data3_flag (ipmi_sel_ctx_t ctx, 310 const void *sel_record, 311 unsigned int sel_record_len, 312 uint8_t *event_data3_flag); 313 314 int ipmi_sel_parse_read_event_data2 (ipmi_sel_ctx_t ctx, 315 const void *sel_record, 316 unsigned int sel_record_len, 317 uint8_t *event_data2); 318 319 int ipmi_sel_parse_read_event_data3 (ipmi_sel_ctx_t ctx, 320 const void *sel_record, 321 unsigned int sel_record_len, 322 uint8_t *event_data3); 323 324 /* manufacturer_id - works with sel timestamped OEM record types */ 325 int ipmi_sel_parse_read_manufacturer_id (ipmi_sel_ctx_t ctx, 326 const void *sel_record, 327 unsigned int sel_record_len, 328 uint32_t *manufacturer_id); 329 330 /* oem - works with sel timestamped and non-timestamped OEM record types */ 331 /* return length of data read into buffer on success, -1 on error */ 332 int ipmi_sel_parse_read_oem (ipmi_sel_ctx_t ctx, 333 const void *sel_record, 334 unsigned int sel_record_len, 335 void *buf, 336 unsigned int buflen); 337 338 /* 339 * create a string output of the SEL entry. 340 * 341 * String format - availability for output dependent on SEL record 342 * type. 343 * 344 * Available in all SEL record types 345 * 346 * %i - record ID in decimal 347 * %I - event nominal vs. warning vs. critical interpretation [1] 348 * 349 * [1] - see libfreeipmi interpret library for information. See 350 * ipmi_sel_ctx_set_interpret_ctx(). If interpret context not 351 * available, returns INTERPRET_ERROR. 352 * 353 * Available in SEL event and timestamped OEM SEL records 354 * 355 * %t - time in format H:M:S using 24 hour clock 356 * %d - date in format D-M-YEAR 357 * 358 * Available in SEL event records 359 * 360 * %T - sensor type 361 * %s - sensor name 362 * %e - event data 1 string (usually offset from event/reading code type string) 363 * %f - event data 2 string [2] 364 * %h - event data 3 string 365 * %c - combined event data 2 and event data 3 string [3] 366 * %p - event data 2 previous state string [4] 367 * %S - event data 2 severity string [4] 368 * %E - combined event data 1, 2, and 3 string [5] 369 * %k - event direction 370 * 371 * [2] - if a previous state and a severity state string are available 372 * from a discrete sensor, they are concatenated with the defined 373 * separator in between. 374 * 375 * [3] - for events where both event data 2 and event data 3 hold data 376 * that must be combined for an effective output. As an example, data 377 * 2 holds a minor version number and data 3 holds a major version 378 * number. The combined output might print out "Version 1.2" instead 379 * of a separated "Major Version 1 ; Minor Version 2" if you did them 380 * separately. If a combined output is not available or not 381 * reasonable, event data 2 and event data 3 output will be output 382 * separately with the defined separator between them 383 * (e.g. effectively "%f ; %h"). 384 * 385 * [4] - if event type code indicates a discrete sensor and event data 2 386 * flag indicates a previous state and/or severity state is available. 387 * 388 * [5] - this can be loosely considered the equivalent of "%e" and 389 * "%c" concatenated with the defined separator between them. 390 * However, various corner cases will be handled for the user to 391 * create a nicer output. For example, "Foo ; NA" will never be 392 * output. This will be condensed into just "Foo". 393 * 394 * Available in timestamped OEM SEL records 395 * 396 * %m - manufacturer id 397 * 398 * Available in SEL timestamped and non-timestamped OEM record types 399 * 400 * %o - oem data in hex (or strings if interpreted OEM available) 401 * 402 * Available in all record types for certain manufacturers 403 * 404 * %O - output an OEM supplied string describing the event. [6] 405 * 406 * [6] On some motherboards, the vendor is capable of supplying a full 407 * string describing the event data, in particular supplying strings 408 * for OEM records and OEM event extensions. Under the right 409 * conditions, this output option may be used as a potential 410 * replacement for %e, %f, %h, %c, and/or %E. If an OEM supplied string 411 * is not available, nothing will be output (with the exception of N/A 412 * if the OUTPUT_NOT_AVAILABLE flag is set). Currently, this output 413 * option supports Fujitsu systems with iRMC S1/iRMC S2. 414 * 415 * Misc 416 * 417 * %% - percent sign 418 * 419 * flags 420 * 421 * VERBOSE 422 * 423 * Output slightly more verbose text for selected fields. For example: 424 * 425 * - If a sensor does not have a name, output sensor number and 426 * generator id instead of just sensor number. 427 * - If an event data string cannot be determined (i.e. it is OEM or 428 * not defined by IPMI), output both the data and event type code 429 * instead of just the event data. 430 * 431 * IGNORE_UNAVAILABLE_FIELD 432 * 433 * If a field is not available for output (for example, a timestamp field 434 * in a SEL entry w/o a timestamp field), do not return an error. Output 435 * nothing. 436 * 437 * OUTPUT_NOT_AVAILABLE 438 * 439 * If a field is not available, do not output an empty string, output 440 * "N/A" (sometimes must have IGNORE_UNAVAILABLE_FIELD set) 441 * 442 * DATE_USE_SLASH 443 * 444 * Use a '/' instead of hyphens when outputting the date. 445 * 446 * DATE_MONTH_STRING 447 * 448 * Output a month name (Jan, Feb, Mar, etc.) instead of the month 449 * number when outputting the date. 450 * 451 * LEGACY 452 * 453 * Output strings in legacy format. 454 * 455 * Returns length of data written to buffer. If >= buflen, no null 456 * termination exists in buffer. 457 */ 458 int ipmi_sel_parse_read_record_string (ipmi_sel_ctx_t ctx, 459 const char *fmt, 460 const void *sel_record, 461 unsigned int sel_record_len, 462 char *buf, 463 unsigned int buflen, 464 unsigned int flags); 465 466 /* 467 * SEL Utility functions 468 */ 469 int ipmi_sel_clear_sel (ipmi_sel_ctx_t ctx); 470 471 int ipmi_sel_delete_sel_entry (ipmi_sel_ctx_t ctx, uint16_t record_id); 472 473 int ipmi_sel_record_type_class (uint8_t record_type); 474 475 #ifdef __cplusplus 476 } 477 #endif 478 479 #endif /* IPMI_SEL_H */ 480