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