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 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif /* HAVE_CONFIG_H */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #if STDC_HEADERS
26 #include <string.h>
27 #endif /* STDC_HEADERS */
28 #if HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif /* HAVE_UNISTD_H */
31 #include <assert.h>
32 #include <errno.h>
33 
34 #include "freeipmi/sdr/ipmi-sdr.h"
35 
36 #include "freeipmi/fiid/fiid.h"
37 #include "freeipmi/record-format/ipmi-sdr-record-format.h"
38 #include "freeipmi/spec/ipmi-sensor-units-spec.h"
39 #include "freeipmi/spec/ipmi-event-reading-type-code-spec.h"
40 #include "freeipmi/util/ipmi-sensor-util.h"
41 
42 #include "ipmi-sdr-common.h"
43 #include "ipmi-sdr-defs.h"
44 #include "ipmi-sdr-trace.h"
45 #include "ipmi-sdr-util.h"
46 
47 #include "libcommon/ipmi-fiid-util.h"
48 
49 #include "freeipmi-portability.h"
50 
51 #define IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD                          0x0001
52 #define IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD                       0x0002
53 #define IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD                           0x0004
54 #define IPMI_SDR_PARSE_RECORD_TYPE_ENTITY_ASSOCIATION_RECORD                   0x0008
55 #define IPMI_SDR_PARSE_RECORD_TYPE_DEVICE_RELATIVE_ENTITY_ASSOCIATION_RECORD   0x0010
56 #define IPMI_SDR_PARSE_RECORD_TYPE_GENERIC_DEVICE_LOCATOR_RECORD               0x0020
57 #define IPMI_SDR_PARSE_RECORD_TYPE_FRU_DEVICE_LOCATOR_RECORD                   0x0040
58 #define IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD 0x0080
59 #define IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_CONFIRMATION_RECORD   0x0100
60 #define IPMI_SDR_PARSE_RECORD_TYPE_BMC_MESSAGE_CHANNEL_INFO_RECORD             0x0200
61 #define IPMI_SDR_PARSE_RECORD_TYPE_OEM_RECORD                                  0x0400
62 
63 int
ipmi_sdr_parse_record_id_and_type(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint16_t * record_id,uint8_t * record_type)64 ipmi_sdr_parse_record_id_and_type (ipmi_sdr_ctx_t ctx,
65                                    const void *sdr_record,
66                                    unsigned int sdr_record_len,
67                                    uint16_t *record_id,
68                                    uint8_t *record_type)
69 {
70   uint8_t sdr_record_buf[IPMI_SDR_MAX_RECORD_LENGTH];
71   int sdr_record_buf_len;
72   fiid_obj_t obj_sdr_record_header = NULL;
73   int sdr_record_header_len;
74   void *sdr_record_to_use;
75   unsigned int sdr_record_len_to_use;
76   uint64_t val;
77   int rv = -1;
78 
79   if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
80     {
81       ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
82       return (-1);
83     }
84 
85   if (!sdr_record || !sdr_record_len)
86     {
87       if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE
88           && !sdr_record
89           && !sdr_record_len)
90         {
91           if ((sdr_record_buf_len = ipmi_sdr_cache_record_read (ctx,
92                                                                 sdr_record_buf,
93                                                                 IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
94             {
95               SDR_SET_INTERNAL_ERRNUM (ctx);
96               return (-1);
97             }
98           sdr_record_to_use = sdr_record_buf;
99           sdr_record_len_to_use = sdr_record_buf_len;
100         }
101       else
102         {
103           SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
104           return (-1);
105         }
106     }
107   else
108     {
109       sdr_record_to_use = (void *)sdr_record;
110       sdr_record_len_to_use = sdr_record_len;
111     }
112 
113   if ((sdr_record_header_len = fiid_template_len_bytes (tmpl_sdr_record_header)) < 0)
114     {
115       SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
116       goto cleanup;
117     }
118 
119   if (sdr_record_len_to_use < sdr_record_header_len)
120     {
121       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INCOMPLETE_SDR_RECORD);
122       goto cleanup;
123     }
124 
125   if (!(obj_sdr_record_header = fiid_obj_create (tmpl_sdr_record_header)))
126     {
127       SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
128       goto cleanup;
129     }
130 
131   if (fiid_obj_set_all (obj_sdr_record_header,
132                         sdr_record_to_use,
133                         sdr_record_header_len) < 0)
134     {
135       SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_header);
136       goto cleanup;
137     }
138 
139   if (record_id)
140     {
141       if (FIID_OBJ_GET (obj_sdr_record_header,
142                         "record_id",
143                         &val) < 0)
144         {
145           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_header);
146           goto cleanup;
147         }
148       *record_id = val;
149     }
150 
151   if (record_type)
152     {
153       if (FIID_OBJ_GET (obj_sdr_record_header,
154                         "record_type",
155                         &val) < 0)
156         {
157           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_header);
158           goto cleanup;
159         }
160       *record_type = val;
161     }
162 
163   sdr_check_read_status (ctx);
164 
165   rv = 0;
166   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
167  cleanup:
168   fiid_obj_destroy (obj_sdr_record_header);
169   return (rv);
170 }
171 
172 static fiid_obj_t
_sdr_record_get_common(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint32_t acceptable_record_types)173 _sdr_record_get_common (ipmi_sdr_ctx_t ctx,
174                         const void *sdr_record,
175                         unsigned int sdr_record_len,
176                         uint32_t acceptable_record_types)
177 {
178   uint8_t sdr_record_buf[IPMI_SDR_MAX_RECORD_LENGTH];
179   int sdr_record_buf_len;
180   void *sdr_record_to_use;
181   unsigned int sdr_record_len_to_use;
182   fiid_obj_t obj_sdr_record = NULL;
183   uint8_t record_type;
184 
185   assert (acceptable_record_types);
186 
187   if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
188     {
189       ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
190       goto cleanup;
191     }
192 
193   if (!sdr_record || !sdr_record_len)
194     {
195       if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE
196           && !sdr_record
197           && !sdr_record_len)
198         {
199           if ((sdr_record_buf_len = ipmi_sdr_cache_record_read (ctx,
200                                                                 sdr_record_buf,
201                                                                 IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
202             {
203               SDR_SET_INTERNAL_ERRNUM (ctx);
204               goto cleanup;
205             }
206           sdr_record_to_use = sdr_record_buf;
207           sdr_record_len_to_use = sdr_record_buf_len;
208         }
209       else
210         {
211           SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
212           goto cleanup;
213         }
214     }
215   else
216     {
217       sdr_record_to_use = (void *)sdr_record;
218       sdr_record_len_to_use = sdr_record_len;
219     }
220 
221   if (ipmi_sdr_parse_record_id_and_type (ctx,
222                                          sdr_record_to_use,
223                                          sdr_record_len_to_use,
224                                          NULL,
225                                          &record_type) < 0)
226     {
227       SDR_SET_INTERNAL_ERRNUM (ctx);
228       goto cleanup;
229     }
230 
231   if (!(((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD)
232          && record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD)
233         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD)
234             && record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD)
235         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD)
236             && record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD)
237         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_ENTITY_ASSOCIATION_RECORD)
238             && record_type == IPMI_SDR_FORMAT_ENTITY_ASSOCIATION_RECORD)
239         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_DEVICE_RELATIVE_ENTITY_ASSOCIATION_RECORD)
240             && record_type == IPMI_SDR_FORMAT_DEVICE_RELATIVE_ENTITY_ASSOCIATION_RECORD)
241 
242         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_GENERIC_DEVICE_LOCATOR_RECORD)
243             && record_type == IPMI_SDR_FORMAT_GENERIC_DEVICE_LOCATOR_RECORD)
244         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_FRU_DEVICE_LOCATOR_RECORD)
245             && record_type == IPMI_SDR_FORMAT_FRU_DEVICE_LOCATOR_RECORD)
246         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD)
247             && record_type == IPMI_SDR_FORMAT_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD)
248         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_CONFIRMATION_RECORD)
249             && record_type == IPMI_SDR_FORMAT_MANAGEMENT_CONTROLLER_CONFIRMATION_RECORD)
250         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_BMC_MESSAGE_CHANNEL_INFO_RECORD)
251             && record_type == IPMI_SDR_FORMAT_BMC_MESSAGE_CHANNEL_INFO_RECORD)
252         || ((acceptable_record_types & IPMI_SDR_PARSE_RECORD_TYPE_OEM_RECORD)
253             && record_type == IPMI_SDR_FORMAT_OEM_RECORD)
254         ))
255     {
256       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
257       goto cleanup;
258     }
259 
260   if (record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD)
261     {
262       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_full_sensor_record)))
263         {
264           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
265           goto cleanup;
266         }
267     }
268   else if (record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD)
269     {
270       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_compact_sensor_record)))
271         {
272           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
273           goto cleanup;
274         }
275     }
276   else if (record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD)
277     {
278       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_event_only_record)))
279         {
280           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
281           goto cleanup;
282         }
283     }
284   else if (record_type == IPMI_SDR_FORMAT_ENTITY_ASSOCIATION_RECORD)
285     {
286       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_entity_association_record)))
287         {
288           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
289           goto cleanup;
290         }
291     }
292   else if (record_type == IPMI_SDR_FORMAT_DEVICE_RELATIVE_ENTITY_ASSOCIATION_RECORD)
293     {
294       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_device_relative_entity_association_record)))
295         {
296           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
297           goto cleanup;
298         }
299     }
300   else if (record_type == IPMI_SDR_FORMAT_GENERIC_DEVICE_LOCATOR_RECORD)
301     {
302       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_generic_device_locator_record)))
303         {
304           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
305           goto cleanup;
306         }
307     }
308   else if (record_type == IPMI_SDR_FORMAT_FRU_DEVICE_LOCATOR_RECORD)
309     {
310       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_fru_device_locator_record)))
311         {
312           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
313           goto cleanup;
314         }
315     }
316   else if (record_type == IPMI_SDR_FORMAT_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD)
317     {
318       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_management_controller_device_locator_record)))
319         {
320           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
321           goto cleanup;
322         }
323     }
324   else if (record_type == IPMI_SDR_FORMAT_MANAGEMENT_CONTROLLER_CONFIRMATION_RECORD)
325     {
326       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_management_controller_confirmation_record)))
327         {
328           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
329           goto cleanup;
330         }
331     }
332   else if (record_type == IPMI_SDR_FORMAT_BMC_MESSAGE_CHANNEL_INFO_RECORD)
333     {
334       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_bmc_message_channel_info_record)))
335         {
336           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
337           goto cleanup;
338         }
339     }
340   else if (record_type == IPMI_SDR_FORMAT_OEM_RECORD)
341     {
342       if (!(obj_sdr_record = fiid_obj_create (tmpl_sdr_oem_record)))
343         {
344           SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
345           goto cleanup;
346         }
347     }
348 
349   if (fiid_obj_set_all (obj_sdr_record,
350                         sdr_record_to_use,
351                         sdr_record_len_to_use) < 0)
352     {
353       SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
354       goto cleanup;
355     }
356 
357   sdr_check_read_status (ctx);
358 
359   return (obj_sdr_record);
360 
361  cleanup:
362   fiid_obj_destroy (obj_sdr_record);
363   return (NULL);
364 }
365 
366 int
ipmi_sdr_parse_sensor_owner_id(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * sensor_owner_id_type,uint8_t * sensor_owner_id)367 ipmi_sdr_parse_sensor_owner_id (ipmi_sdr_ctx_t ctx,
368                                 const void *sdr_record,
369                                 unsigned int sdr_record_len,
370                                 uint8_t *sensor_owner_id_type,
371                                 uint8_t *sensor_owner_id)
372 {
373   fiid_obj_t obj_sdr_record = NULL;
374   uint32_t acceptable_record_types;
375   uint64_t val;
376   int rv = -1;
377 
378   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
379   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
380   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
381 
382   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
383                                                  sdr_record,
384                                                  sdr_record_len,
385                                                  acceptable_record_types)))
386     goto cleanup;
387 
388   if (sensor_owner_id_type)
389     {
390       if (FIID_OBJ_GET (obj_sdr_record,
391                         "sensor_owner_id.type",
392                         &val) < 0)
393         {
394           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
395           goto cleanup;
396         }
397       *sensor_owner_id_type = val;
398     }
399 
400   if (sensor_owner_id)
401     {
402       if (FIID_OBJ_GET (obj_sdr_record,
403                         "sensor_owner_id",
404                         &val) < 0)
405         {
406           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
407           goto cleanup;
408         }
409       *sensor_owner_id = val;
410     }
411 
412   rv = 0;
413   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
414  cleanup:
415   fiid_obj_destroy (obj_sdr_record);
416   return (rv);
417 }
418 
419 int
ipmi_sdr_parse_sensor_owner_lun(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * sensor_owner_lun,uint8_t * channel_number)420 ipmi_sdr_parse_sensor_owner_lun (ipmi_sdr_ctx_t ctx,
421                                  const void *sdr_record,
422                                  unsigned int sdr_record_len,
423                                  uint8_t *sensor_owner_lun,
424                                  uint8_t *channel_number)
425 {
426   fiid_obj_t obj_sdr_record = NULL;
427   uint32_t acceptable_record_types;
428   uint64_t val;
429   int rv = -1;
430 
431   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
432   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
433   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
434 
435   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
436                                                  sdr_record,
437                                                  sdr_record_len,
438                                                  acceptable_record_types)))
439     goto cleanup;
440 
441   if (sensor_owner_lun)
442     {
443       if (FIID_OBJ_GET (obj_sdr_record,
444                         "sensor_owner_lun",
445                         &val) < 0)
446         {
447           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
448           goto cleanup;
449         }
450       *sensor_owner_lun = val;
451     }
452 
453   if (channel_number)
454     {
455       if (FIID_OBJ_GET (obj_sdr_record,
456                         "channel_number",
457                         &val) < 0)
458         {
459           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
460           goto cleanup;
461         }
462       *channel_number = val;
463     }
464 
465   rv = 0;
466   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
467  cleanup:
468   fiid_obj_destroy (obj_sdr_record);
469   return (rv);
470 }
471 
472 int
ipmi_sdr_parse_sensor_number(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * sensor_number)473 ipmi_sdr_parse_sensor_number (ipmi_sdr_ctx_t ctx,
474                               const void *sdr_record,
475                               unsigned int sdr_record_len,
476                               uint8_t *sensor_number)
477 {
478   fiid_obj_t obj_sdr_record = NULL;
479   uint32_t acceptable_record_types;
480   uint64_t val;
481   int rv = -1;
482 
483   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
484   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
485   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
486 
487   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
488                                                  sdr_record,
489                                                  sdr_record_len,
490                                                  acceptable_record_types)))
491     goto cleanup;
492 
493   if (sensor_number)
494     {
495       if (FIID_OBJ_GET (obj_sdr_record,
496                         "sensor_number",
497                         &val) < 0)
498         {
499           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
500           goto cleanup;
501         }
502       *sensor_number = val;
503     }
504 
505   rv = 0;
506   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
507  cleanup:
508   fiid_obj_destroy (obj_sdr_record);
509   return (rv);
510 }
511 
512 int
ipmi_sdr_parse_entity_id_instance_type(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * entity_id,uint8_t * entity_instance,uint8_t * entity_instance_type)513 ipmi_sdr_parse_entity_id_instance_type (ipmi_sdr_ctx_t ctx,
514                                         const void *sdr_record,
515                                         unsigned int sdr_record_len,
516                                         uint8_t *entity_id,
517                                         uint8_t *entity_instance,
518                                         uint8_t *entity_instance_type)
519 {
520   fiid_obj_t obj_sdr_record = NULL;
521   uint32_t acceptable_record_types;
522   uint64_t val;
523   int rv = -1;
524 
525   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
526   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
527   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
528   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_GENERIC_DEVICE_LOCATOR_RECORD;
529   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD;
530 
531   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
532                                                  sdr_record,
533                                                  sdr_record_len,
534                                                  acceptable_record_types)))
535     goto cleanup;
536 
537   if (entity_id)
538     {
539       if (FIID_OBJ_GET (obj_sdr_record,
540                         "entity_id",
541                         &val) < 0)
542         {
543           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
544           goto cleanup;
545         }
546       *entity_id = val;
547     }
548   if (entity_instance)
549     {
550       if (FIID_OBJ_GET (obj_sdr_record,
551                         "entity_instance",
552                         &val) < 0)
553         {
554           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
555           goto cleanup;
556         }
557       *entity_instance = val;
558     }
559   if (entity_instance_type)
560     {
561       if (FIID_OBJ_GET (obj_sdr_record,
562                         "entity_instance.type",
563                         &val) < 0)
564         {
565           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
566           goto cleanup;
567         }
568       *entity_instance_type = val;
569     }
570 
571   rv = 0;
572   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
573  cleanup:
574   fiid_obj_destroy (obj_sdr_record);
575   return (rv);
576 }
577 
578 int
ipmi_sdr_parse_sensor_type(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * sensor_type)579 ipmi_sdr_parse_sensor_type (ipmi_sdr_ctx_t ctx,
580                             const void *sdr_record,
581                             unsigned int sdr_record_len,
582                             uint8_t *sensor_type)
583 {
584   fiid_obj_t obj_sdr_record = NULL;
585   uint32_t acceptable_record_types;
586   uint64_t val;
587   int rv = -1;
588 
589   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
590   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
591   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
592 
593   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
594                                                  sdr_record,
595                                                  sdr_record_len,
596                                                  acceptable_record_types)))
597     goto cleanup;
598 
599   if (sensor_type)
600     {
601       if (FIID_OBJ_GET (obj_sdr_record,
602                         "sensor_type",
603                         &val) < 0)
604         {
605           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
606           goto cleanup;
607         }
608       *sensor_type = val;
609     }
610 
611   rv = 0;
612   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
613  cleanup:
614   fiid_obj_destroy (obj_sdr_record);
615   return (rv);
616 }
617 
618 int
ipmi_sdr_parse_event_reading_type_code(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * event_reading_type_code)619 ipmi_sdr_parse_event_reading_type_code (ipmi_sdr_ctx_t ctx,
620                                         const void *sdr_record,
621                                         unsigned int sdr_record_len,
622                                         uint8_t *event_reading_type_code)
623 {
624   fiid_obj_t obj_sdr_record = NULL;
625   uint32_t acceptable_record_types;
626   uint64_t val;
627   int rv = -1;
628 
629   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
630   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
631   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
632 
633   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
634                                                  sdr_record,
635                                                  sdr_record_len,
636                                                  acceptable_record_types)))
637     goto cleanup;
638 
639   if (event_reading_type_code)
640     {
641       if (FIID_OBJ_GET (obj_sdr_record,
642                         "event_reading_type_code",
643                         &val) < 0)
644         {
645           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
646           goto cleanup;
647         }
648       *event_reading_type_code = val;
649     }
650 
651   rv = 0;
652   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
653  cleanup:
654   fiid_obj_destroy (obj_sdr_record);
655   return (rv);
656 }
657 
658 int
ipmi_sdr_parse_id_string(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,char * id_string,unsigned int id_string_len)659 ipmi_sdr_parse_id_string (ipmi_sdr_ctx_t ctx,
660                           const void *sdr_record,
661                           unsigned int sdr_record_len,
662                           char *id_string,
663                           unsigned int id_string_len)
664 {
665   fiid_obj_t obj_sdr_record = NULL;
666   uint32_t acceptable_record_types;
667   int len = 0;
668   int rv = -1;
669 
670   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
671   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
672   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
673 
674   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
675                                                  sdr_record,
676                                                  sdr_record_len,
677                                                  acceptable_record_types)))
678     goto cleanup;
679 
680   if (id_string && id_string_len)
681     {
682       if ((len = fiid_obj_get_data (obj_sdr_record,
683                                     "id_string",
684                                     id_string,
685                                     id_string_len)) < 0)
686         {
687           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
688           goto cleanup;
689         }
690     }
691 
692   rv = len;
693   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
694  cleanup:
695   fiid_obj_destroy (obj_sdr_record);
696   return (rv);
697 }
698 
699 int
ipmi_sdr_parse_sensor_units(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * sensor_units_percentage,uint8_t * sensor_units_modifier,uint8_t * sensor_units_rate,uint8_t * sensor_base_unit_type,uint8_t * sensor_modifier_unit_type)700 ipmi_sdr_parse_sensor_units (ipmi_sdr_ctx_t ctx,
701                              const void *sdr_record,
702                              unsigned int sdr_record_len,
703                              uint8_t *sensor_units_percentage,
704                              uint8_t *sensor_units_modifier,
705                              uint8_t *sensor_units_rate,
706                              uint8_t *sensor_base_unit_type,
707                              uint8_t *sensor_modifier_unit_type)
708 {
709   fiid_obj_t obj_sdr_record = NULL;
710   uint32_t acceptable_record_types;
711   uint64_t val;
712   int rv = -1;
713 
714   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
715   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
716 
717   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
718                                                  sdr_record,
719                                                  sdr_record_len,
720                                                  acceptable_record_types)))
721     goto cleanup;
722 
723   if (sensor_units_percentage)
724     {
725       if (FIID_OBJ_GET (obj_sdr_record,
726                         "sensor_unit1.percentage",
727                         &val) < 0)
728         {
729           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
730           goto cleanup;
731         }
732       *sensor_units_percentage = val;
733     }
734 
735   if (sensor_units_modifier)
736     {
737       if (FIID_OBJ_GET (obj_sdr_record,
738                         "sensor_unit1.modifier_unit",
739                         &val) < 0)
740         {
741           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
742           goto cleanup;
743         }
744       *sensor_units_modifier = val;
745     }
746 
747   if (sensor_units_rate)
748     {
749       if (FIID_OBJ_GET (obj_sdr_record,
750                         "sensor_unit1.rate_unit",
751                         &val) < 0)
752         {
753           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
754           goto cleanup;
755         }
756 
757       *sensor_units_rate = val;
758     }
759 
760   if (sensor_base_unit_type)
761     {
762       if (FIID_OBJ_GET (obj_sdr_record,
763                         "sensor_unit2.base_unit",
764                         &val) < 0)
765         {
766           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
767           goto cleanup;
768         }
769       *sensor_base_unit_type = val;
770 
771       if (!IPMI_SENSOR_UNIT_VALID (*sensor_base_unit_type))
772         *sensor_base_unit_type = IPMI_SENSOR_UNIT_UNSPECIFIED;
773     }
774 
775   if (sensor_modifier_unit_type)
776     {
777       if (FIID_OBJ_GET (obj_sdr_record,
778                         "sensor_unit3.modifier_unit",
779                         &val) < 0)
780         {
781           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
782           goto cleanup;
783         }
784       *sensor_modifier_unit_type = val;
785 
786       if (!IPMI_SENSOR_UNIT_VALID (*sensor_modifier_unit_type))
787         *sensor_modifier_unit_type = IPMI_SENSOR_UNIT_UNSPECIFIED;
788     }
789 
790   rv = 0;
791   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
792  cleanup:
793   fiid_obj_destroy (obj_sdr_record);
794   return (rv);
795 }
796 
797 int
ipmi_sdr_parse_sensor_capabilities(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * event_message_control_support,uint8_t * threshold_access_support,uint8_t * hysteresis_support,uint8_t * auto_re_arm_support,uint8_t * entity_ignore_support)798 ipmi_sdr_parse_sensor_capabilities (ipmi_sdr_ctx_t ctx,
799                                     const void *sdr_record,
800                                     unsigned int sdr_record_len,
801                                     uint8_t *event_message_control_support,
802                                     uint8_t *threshold_access_support,
803                                     uint8_t *hysteresis_support,
804                                     uint8_t *auto_re_arm_support,
805                                     uint8_t *entity_ignore_support)
806 {
807   fiid_obj_t obj_sdr_record = NULL;
808   uint32_t acceptable_record_types;
809   uint64_t val;
810   int rv = -1;
811 
812   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
813   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
814 
815   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
816                                                  sdr_record,
817                                                  sdr_record_len,
818                                                  acceptable_record_types)))
819     goto cleanup;
820 
821   if (event_message_control_support)
822     {
823       if (FIID_OBJ_GET (obj_sdr_record,
824                         "sensor_capabilities.event_message_control_support",
825                         &val) < 0)
826         {
827           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
828           goto cleanup;
829         }
830       *event_message_control_support = val;
831     }
832   if (threshold_access_support)
833     {
834       if (FIID_OBJ_GET (obj_sdr_record,
835                         "sensor_capabilities.threshold_access_support",
836                         &val) < 0)
837         {
838           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
839           goto cleanup;
840         }
841       *threshold_access_support = val;
842     }
843   if (hysteresis_support)
844     {
845       if (FIID_OBJ_GET (obj_sdr_record,
846                         "sensor_capabilities.hysteresis_support",
847                         &val) < 0)
848         {
849           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
850           goto cleanup;
851         }
852       *hysteresis_support = val;
853     }
854   if (auto_re_arm_support)
855     {
856       if (FIID_OBJ_GET (obj_sdr_record,
857                         "sensor_capabilities.auto_re_arm_support",
858                         &val) < 0)
859         {
860           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
861           goto cleanup;
862         }
863       *auto_re_arm_support = val;
864     }
865   if (entity_ignore_support)
866     {
867       if (FIID_OBJ_GET (obj_sdr_record,
868                         "sensor_capabilities.entity_ignore_support",
869                         &val) < 0)
870         {
871           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
872           goto cleanup;
873         }
874       *entity_ignore_support = val;
875     }
876 
877   rv = 0;
878   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
879  cleanup:
880   fiid_obj_destroy (obj_sdr_record);
881   return (rv);
882 }
883 
884 int
ipmi_sdr_parse_sensor_direction(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * sensor_direction)885 ipmi_sdr_parse_sensor_direction (ipmi_sdr_ctx_t ctx,
886                                  const void *sdr_record,
887                                  unsigned int sdr_record_len,
888                                  uint8_t *sensor_direction)
889 {
890   fiid_obj_t obj_sdr_record = NULL;
891   uint32_t acceptable_record_types;
892   uint64_t val;
893   int rv = -1;
894 
895   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
896   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
897 
898   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
899                                                  sdr_record,
900                                                  sdr_record_len,
901                                                  acceptable_record_types)))
902     goto cleanup;
903 
904   if (sensor_direction)
905     {
906       if (FIID_OBJ_GET (obj_sdr_record,
907                         "sensor_direction",
908                         &val) < 0)
909         {
910           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
911           goto cleanup;
912         }
913       *sensor_direction = val;
914     }
915 
916   rv = 0;
917   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
918  cleanup:
919   fiid_obj_destroy (obj_sdr_record);
920   return (rv);
921 }
922 
923 int
ipmi_sdr_parse_assertion_supported(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * event_state_0,uint8_t * event_state_1,uint8_t * event_state_2,uint8_t * event_state_3,uint8_t * event_state_4,uint8_t * event_state_5,uint8_t * event_state_6,uint8_t * event_state_7,uint8_t * event_state_8,uint8_t * event_state_9,uint8_t * event_state_10,uint8_t * event_state_11,uint8_t * event_state_12,uint8_t * event_state_13,uint8_t * event_state_14)924 ipmi_sdr_parse_assertion_supported (ipmi_sdr_ctx_t ctx,
925                                     const void *sdr_record,
926                                     unsigned int sdr_record_len,
927                                     uint8_t *event_state_0,
928                                     uint8_t *event_state_1,
929                                     uint8_t *event_state_2,
930                                     uint8_t *event_state_3,
931                                     uint8_t *event_state_4,
932                                     uint8_t *event_state_5,
933                                     uint8_t *event_state_6,
934                                     uint8_t *event_state_7,
935                                     uint8_t *event_state_8,
936                                     uint8_t *event_state_9,
937                                     uint8_t *event_state_10,
938                                     uint8_t *event_state_11,
939                                     uint8_t *event_state_12,
940                                     uint8_t *event_state_13,
941                                     uint8_t *event_state_14)
942 {
943   fiid_obj_t obj_sdr_record = NULL;
944   fiid_obj_t obj_sdr_record_discrete = NULL;
945   uint32_t acceptable_record_types;
946   uint8_t record_type;
947   uint8_t event_reading_type_code;
948   uint64_t val;
949   int rv = -1;
950 
951   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
952   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
953 
954   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
955                                                  sdr_record,
956                                                  sdr_record_len,
957                                                  acceptable_record_types)))
958     goto cleanup;
959 
960   if (ipmi_sdr_parse_event_reading_type_code (ctx,
961                                               sdr_record,
962                                               sdr_record_len,
963                                               &event_reading_type_code) < 0)
964     goto cleanup;
965 
966   if (!IPMI_EVENT_READING_TYPE_CODE_IS_GENERIC (event_reading_type_code)
967       && !IPMI_EVENT_READING_TYPE_CODE_IS_SENSOR_SPECIFIC (event_reading_type_code))
968     {
969       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
970       goto cleanup;
971     }
972 
973   /* convert obj_sdr_record to appropriate format we care about */
974   if (ipmi_sdr_parse_record_id_and_type (ctx,
975                                          sdr_record,
976                                          sdr_record_len,
977                                          NULL,
978                                          &record_type) < 0)
979     goto cleanup;
980 
981   if (record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD)
982     {
983       if (!(obj_sdr_record_discrete = fiid_obj_copy (obj_sdr_record,
984                                                      tmpl_sdr_full_sensor_record_non_threshold_based_sensors)))
985         {
986           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
987           goto cleanup;
988         }
989     }
990   else
991     {
992       if (!(obj_sdr_record_discrete = fiid_obj_copy (obj_sdr_record,
993                                                      tmpl_sdr_compact_sensor_record_non_threshold_based_sensors)))
994         {
995           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
996           goto cleanup;
997         }
998     }
999 
1000   if (event_state_0)
1001     {
1002       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1003                         "assertion_event_mask.event_offset_0",
1004                         &val) < 0)
1005         {
1006           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1007           goto cleanup;
1008         }
1009       *event_state_0 = val;
1010     }
1011 
1012   if (event_state_1)
1013     {
1014       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1015                         "assertion_event_mask.event_offset_1",
1016                         &val) < 0)
1017         {
1018           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1019           goto cleanup;
1020         }
1021       *event_state_1 = val;
1022     }
1023 
1024   if (event_state_2)
1025     {
1026       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1027                         "assertion_event_mask.event_offset_2",
1028                         &val) < 0)
1029         {
1030           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1031           goto cleanup;
1032         }
1033       *event_state_2 = val;
1034     }
1035 
1036   if (event_state_3)
1037     {
1038       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1039                         "assertion_event_mask.event_offset_3",
1040                         &val) < 0)
1041         {
1042           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1043           goto cleanup;
1044         }
1045       *event_state_3 = val;
1046     }
1047 
1048   if (event_state_4)
1049     {
1050       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1051                         "assertion_event_mask.event_offset_4",
1052                         &val) < 0)
1053         {
1054           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1055           goto cleanup;
1056         }
1057       *event_state_4 = val;
1058     }
1059 
1060   if (event_state_5)
1061     {
1062       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1063                         "assertion_event_mask.event_offset_5",
1064                         &val) < 0)
1065         {
1066           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1067           goto cleanup;
1068         }
1069       *event_state_5 = val;
1070     }
1071 
1072   if (event_state_6)
1073     {
1074       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1075                         "assertion_event_mask.event_offset_6",
1076                         &val) < 0)
1077         {
1078           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1079           goto cleanup;
1080         }
1081       *event_state_6 = val;
1082     }
1083 
1084   if (event_state_7)
1085     {
1086       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1087                         "assertion_event_mask.event_offset_7",
1088                         &val) < 0)
1089         {
1090           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1091           goto cleanup;
1092         }
1093       *event_state_7 = val;
1094     }
1095 
1096   if (event_state_8)
1097     {
1098       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1099                         "assertion_event_mask.event_offset_8",
1100                         &val) < 0)
1101         {
1102           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1103           goto cleanup;
1104         }
1105       *event_state_8 = val;
1106     }
1107 
1108   if (event_state_9)
1109     {
1110       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1111                         "assertion_event_mask.event_offset_9",
1112                         &val) < 0)
1113         {
1114           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1115           goto cleanup;
1116         }
1117       *event_state_9 = val;
1118     }
1119 
1120   if (event_state_10)
1121     {
1122       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1123                         "assertion_event_mask.event_offset_10",
1124                         &val) < 0)
1125         {
1126           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1127           goto cleanup;
1128         }
1129       *event_state_10 = val;
1130     }
1131 
1132   if (event_state_11)
1133     {
1134       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1135                         "assertion_event_mask.event_offset_11",
1136                         &val) < 0)
1137         {
1138           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1139           goto cleanup;
1140         }
1141       *event_state_11 = val;
1142     }
1143 
1144   if (event_state_12)
1145     {
1146       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1147                         "assertion_event_mask.event_offset_12",
1148                         &val) < 0)
1149         {
1150           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1151           goto cleanup;
1152         }
1153       *event_state_12 = val;
1154     }
1155 
1156   if (event_state_13)
1157     {
1158       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1159                         "assertion_event_mask.event_offset_13",
1160                         &val) < 0)
1161         {
1162           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1163           goto cleanup;
1164         }
1165       *event_state_13 = val;
1166     }
1167 
1168   if (event_state_14)
1169     {
1170       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1171                         "assertion_event_mask.event_offset_14",
1172                         &val) < 0)
1173         {
1174           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1175           goto cleanup;
1176         }
1177       *event_state_14 = val;
1178     }
1179 
1180   rv = 0;
1181   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
1182  cleanup:
1183   fiid_obj_destroy (obj_sdr_record);
1184   fiid_obj_destroy (obj_sdr_record_discrete);
1185   return (rv);
1186 }
1187 
1188 int
ipmi_sdr_parse_deassertion_supported(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * event_state_0,uint8_t * event_state_1,uint8_t * event_state_2,uint8_t * event_state_3,uint8_t * event_state_4,uint8_t * event_state_5,uint8_t * event_state_6,uint8_t * event_state_7,uint8_t * event_state_8,uint8_t * event_state_9,uint8_t * event_state_10,uint8_t * event_state_11,uint8_t * event_state_12,uint8_t * event_state_13,uint8_t * event_state_14)1189 ipmi_sdr_parse_deassertion_supported (ipmi_sdr_ctx_t ctx,
1190                                       const void *sdr_record,
1191                                       unsigned int sdr_record_len,
1192                                       uint8_t *event_state_0,
1193                                       uint8_t *event_state_1,
1194                                       uint8_t *event_state_2,
1195                                       uint8_t *event_state_3,
1196                                       uint8_t *event_state_4,
1197                                       uint8_t *event_state_5,
1198                                       uint8_t *event_state_6,
1199                                       uint8_t *event_state_7,
1200                                       uint8_t *event_state_8,
1201                                       uint8_t *event_state_9,
1202                                       uint8_t *event_state_10,
1203                                       uint8_t *event_state_11,
1204                                       uint8_t *event_state_12,
1205                                       uint8_t *event_state_13,
1206                                       uint8_t *event_state_14)
1207 {
1208   fiid_obj_t obj_sdr_record = NULL;
1209   fiid_obj_t obj_sdr_record_discrete = NULL;
1210   uint32_t acceptable_record_types;
1211   uint8_t record_type;
1212   uint8_t event_reading_type_code;
1213   uint64_t val;
1214   int rv = -1;
1215 
1216   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
1217   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
1218 
1219   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
1220                                                  sdr_record,
1221                                                  sdr_record_len,
1222                                                  acceptable_record_types)))
1223     goto cleanup;
1224 
1225   if (ipmi_sdr_parse_event_reading_type_code (ctx,
1226                                               sdr_record,
1227                                               sdr_record_len,
1228                                               &event_reading_type_code) < 0)
1229     goto cleanup;
1230 
1231   if (!IPMI_EVENT_READING_TYPE_CODE_IS_GENERIC (event_reading_type_code)
1232       && !IPMI_EVENT_READING_TYPE_CODE_IS_SENSOR_SPECIFIC (event_reading_type_code))
1233     {
1234       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
1235       goto cleanup;
1236     }
1237 
1238   /* convert obj_sdr_record to appropriate format we care about */
1239   if (ipmi_sdr_parse_record_id_and_type (ctx,
1240                                          sdr_record,
1241                                          sdr_record_len,
1242                                          NULL,
1243                                          &record_type) < 0)
1244     goto cleanup;
1245 
1246   if (record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD)
1247     {
1248       if (!(obj_sdr_record_discrete = fiid_obj_copy (obj_sdr_record,
1249                                                      tmpl_sdr_full_sensor_record_non_threshold_based_sensors)))
1250         {
1251           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
1252           goto cleanup;
1253         }
1254     }
1255   else
1256     {
1257       if (!(obj_sdr_record_discrete = fiid_obj_copy (obj_sdr_record,
1258                                                      tmpl_sdr_compact_sensor_record_non_threshold_based_sensors)))
1259         {
1260           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
1261           goto cleanup;
1262         }
1263     }
1264 
1265   if (event_state_0)
1266     {
1267       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1268                         "deassertion_event_mask.event_offset_0",
1269                         &val) < 0)
1270         {
1271           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1272           goto cleanup;
1273         }
1274       *event_state_0 = val;
1275     }
1276 
1277   if (event_state_1)
1278     {
1279       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1280                         "deassertion_event_mask.event_offset_1",
1281                         &val) < 0)
1282         {
1283           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1284           goto cleanup;
1285         }
1286       *event_state_1 = val;
1287     }
1288 
1289   if (event_state_2)
1290     {
1291       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1292                         "deassertion_event_mask.event_offset_2",
1293                         &val) < 0)
1294         {
1295           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1296           goto cleanup;
1297         }
1298       *event_state_2 = val;
1299     }
1300 
1301   if (event_state_3)
1302     {
1303       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1304                         "deassertion_event_mask.event_offset_3",
1305                         &val) < 0)
1306         {
1307           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1308           goto cleanup;
1309         }
1310       *event_state_3 = val;
1311     }
1312 
1313   if (event_state_4)
1314     {
1315       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1316                         "deassertion_event_mask.event_offset_4",
1317                         &val) < 0)
1318         {
1319           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1320           goto cleanup;
1321         }
1322       *event_state_4 = val;
1323     }
1324 
1325   if (event_state_5)
1326     {
1327       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1328                         "deassertion_event_mask.event_offset_5",
1329                         &val) < 0)
1330         {
1331           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1332           goto cleanup;
1333         }
1334       *event_state_5 = val;
1335     }
1336 
1337   if (event_state_6)
1338     {
1339       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1340                         "deassertion_event_mask.event_offset_6",
1341                         &val) < 0)
1342         {
1343           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1344           goto cleanup;
1345         }
1346       *event_state_6 = val;
1347     }
1348 
1349   if (event_state_7)
1350     {
1351       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1352                         "deassertion_event_mask.event_offset_7",
1353                         &val) < 0)
1354         {
1355           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1356           goto cleanup;
1357         }
1358       *event_state_7 = val;
1359     }
1360 
1361   if (event_state_8)
1362     {
1363       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1364                         "deassertion_event_mask.event_offset_8",
1365                         &val) < 0)
1366         {
1367           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1368           goto cleanup;
1369         }
1370       *event_state_8 = val;
1371     }
1372 
1373   if (event_state_9)
1374     {
1375       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1376                         "deassertion_event_mask.event_offset_9",
1377                         &val) < 0)
1378         {
1379           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1380           goto cleanup;
1381         }
1382       *event_state_9 = val;
1383     }
1384 
1385   if (event_state_10)
1386     {
1387       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1388                         "deassertion_event_mask.event_offset_10",
1389                         &val) < 0)
1390         {
1391           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1392           goto cleanup;
1393         }
1394       *event_state_10 = val;
1395     }
1396 
1397   if (event_state_11)
1398     {
1399       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1400                         "deassertion_event_mask.event_offset_11",
1401                         &val) < 0)
1402         {
1403           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1404           goto cleanup;
1405         }
1406       *event_state_11 = val;
1407     }
1408 
1409   if (event_state_12)
1410     {
1411       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1412                         "deassertion_event_mask.event_offset_12",
1413                         &val) < 0)
1414         {
1415           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1416           goto cleanup;
1417         }
1418       *event_state_12 = val;
1419     }
1420 
1421   if (event_state_13)
1422     {
1423       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1424                         "deassertion_event_mask.event_offset_13",
1425                         &val) < 0)
1426         {
1427           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1428           goto cleanup;
1429         }
1430       *event_state_13 = val;
1431     }
1432 
1433   if (event_state_14)
1434     {
1435       if (FIID_OBJ_GET (obj_sdr_record_discrete,
1436                         "deassertion_event_mask.event_offset_14",
1437                         &val) < 0)
1438         {
1439           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_discrete);
1440           goto cleanup;
1441         }
1442       *event_state_14 = val;
1443     }
1444 
1445   rv = 0;
1446   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
1447  cleanup:
1448   fiid_obj_destroy (obj_sdr_record);
1449   fiid_obj_destroy (obj_sdr_record_discrete);
1450   return (rv);
1451 }
1452 
1453 int
ipmi_sdr_parse_threshold_assertion_supported(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * lower_non_critical_going_low,uint8_t * lower_non_critical_going_high,uint8_t * lower_critical_going_low,uint8_t * lower_critical_going_high,uint8_t * lower_non_recoverable_going_low,uint8_t * lower_non_recoverable_going_high,uint8_t * upper_non_critical_going_low,uint8_t * upper_non_critical_going_high,uint8_t * upper_critical_going_low,uint8_t * upper_critical_going_high,uint8_t * upper_non_recoverable_going_low,uint8_t * upper_non_recoverable_going_high)1454 ipmi_sdr_parse_threshold_assertion_supported (ipmi_sdr_ctx_t ctx,
1455                                               const void *sdr_record,
1456                                               unsigned int sdr_record_len,
1457                                               uint8_t *lower_non_critical_going_low,
1458                                               uint8_t *lower_non_critical_going_high,
1459                                               uint8_t *lower_critical_going_low,
1460                                               uint8_t *lower_critical_going_high,
1461                                               uint8_t *lower_non_recoverable_going_low,
1462                                               uint8_t *lower_non_recoverable_going_high,
1463                                               uint8_t *upper_non_critical_going_low,
1464                                               uint8_t *upper_non_critical_going_high,
1465                                               uint8_t *upper_critical_going_low,
1466                                               uint8_t *upper_critical_going_high,
1467                                               uint8_t *upper_non_recoverable_going_low,
1468                                               uint8_t *upper_non_recoverable_going_high)
1469 {
1470   fiid_obj_t obj_sdr_record = NULL;
1471   fiid_obj_t obj_sdr_record_threshold = NULL;
1472   uint32_t acceptable_record_types;
1473   uint8_t event_reading_type_code;
1474   uint64_t val;
1475   int rv = -1;
1476 
1477   /* achu:
1478    *
1479    * Technically, the IPMI spec lists that compact record formats also
1480    * support settable thresholds.  However, since compact records
1481    * don't contain any information for interpreting threshold sensors
1482    * (e.g. R exponent) I don't know how they could be of any use.  No
1483    * vendor that I know of supports threshold sensors via a compact
1484    * record (excluding possible OEM ones).
1485    *
1486    * There's a part of me that believes the readable/setting
1487    * threshold masks for compact sensor records is a cut and paste
1488    * typo.  It shouldn't be there.
1489    */
1490 
1491   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
1492 
1493   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
1494                                                  sdr_record,
1495                                                  sdr_record_len,
1496                                                  acceptable_record_types)))
1497     goto cleanup;
1498 
1499   /* We don't want the generic sdr full record, we need the special
1500    * threshold one.
1501    */
1502 
1503   if (ipmi_sdr_parse_event_reading_type_code (ctx,
1504                                               sdr_record,
1505                                               sdr_record_len,
1506                                               &event_reading_type_code) < 0)
1507     goto cleanup;
1508 
1509   if (!IPMI_EVENT_READING_TYPE_CODE_IS_THRESHOLD (event_reading_type_code))
1510     {
1511       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
1512       goto cleanup;
1513     }
1514 
1515   if (!(obj_sdr_record_threshold = fiid_obj_copy (obj_sdr_record,
1516                                                   tmpl_sdr_full_sensor_record_threshold_based_sensors)))
1517     {
1518       SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
1519       goto cleanup;
1520     }
1521 
1522   if (lower_non_critical_going_low)
1523     {
1524       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1525                         "threshold_assertion_event_mask.lower_non_critical_going_low_supported",
1526                         &val) < 0)
1527         {
1528           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1529           goto cleanup;
1530         }
1531       *lower_non_critical_going_low = val;
1532     }
1533 
1534   if (lower_non_critical_going_high)
1535     {
1536       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1537                         "threshold_assertion_event_mask.lower_non_critical_going_high_supported",
1538                         &val) < 0)
1539         {
1540           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1541           goto cleanup;
1542         }
1543       *lower_non_critical_going_high = val;
1544     }
1545 
1546   if (lower_critical_going_low)
1547     {
1548       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1549                         "threshold_assertion_event_mask.lower_critical_going_low_supported",
1550                         &val) < 0)
1551         {
1552           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1553           goto cleanup;
1554         }
1555       *lower_critical_going_low = val;
1556     }
1557 
1558   if (lower_critical_going_high)
1559     {
1560       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1561                         "threshold_assertion_event_mask.lower_critical_going_high_supported",
1562                         &val) < 0)
1563         {
1564           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1565           goto cleanup;
1566         }
1567       *lower_critical_going_high = val;
1568     }
1569 
1570   if (lower_non_recoverable_going_low)
1571     {
1572       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1573                         "threshold_assertion_event_mask.lower_non_recoverable_going_low_supported",
1574                         &val) < 0)
1575         {
1576           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1577           goto cleanup;
1578         }
1579       *lower_non_recoverable_going_low = val;
1580     }
1581 
1582   if (lower_non_recoverable_going_high)
1583     {
1584       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1585                         "threshold_assertion_event_mask.lower_non_recoverable_going_high_supported",
1586                         &val) < 0)
1587         {
1588           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1589           goto cleanup;
1590         }
1591       *lower_non_recoverable_going_high = val;
1592     }
1593 
1594   if (upper_non_critical_going_low)
1595     {
1596       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1597                         "threshold_assertion_event_mask.upper_non_critical_going_low_supported",
1598                         &val) < 0)
1599         {
1600           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1601           goto cleanup;
1602         }
1603       *upper_non_critical_going_low = val;
1604     }
1605 
1606   if (upper_non_critical_going_high)
1607     {
1608       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1609                         "threshold_assertion_event_mask.upper_non_critical_going_high_supported",
1610                         &val) < 0)
1611         {
1612           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1613           goto cleanup;
1614         }
1615       *upper_non_critical_going_high = val;
1616     }
1617 
1618   if (upper_critical_going_low)
1619     {
1620       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1621                         "threshold_assertion_event_mask.upper_critical_going_low_supported",
1622                         &val) < 0)
1623         {
1624           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1625           goto cleanup;
1626         }
1627       *upper_critical_going_low = val;
1628     }
1629 
1630   if (upper_critical_going_high)
1631     {
1632       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1633                         "threshold_assertion_event_mask.upper_critical_going_high_supported",
1634                         &val) < 0)
1635         {
1636           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1637           goto cleanup;
1638         }
1639       *upper_critical_going_high = val;
1640     }
1641 
1642   if (upper_non_recoverable_going_low)
1643     {
1644       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1645                         "threshold_assertion_event_mask.upper_non_recoverable_going_low_supported",
1646                         &val) < 0)
1647         {
1648           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1649           goto cleanup;
1650         }
1651       *upper_non_recoverable_going_low = val;
1652     }
1653 
1654   if (upper_non_recoverable_going_high)
1655     {
1656       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1657                         "threshold_assertion_event_mask.upper_non_recoverable_going_high_supported",
1658                         &val) < 0)
1659         {
1660           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1661           goto cleanup;
1662         }
1663       *upper_non_recoverable_going_high = val;
1664     }
1665 
1666   rv = 0;
1667   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
1668  cleanup:
1669   fiid_obj_destroy (obj_sdr_record);
1670   fiid_obj_destroy (obj_sdr_record_threshold);
1671   return (rv);
1672 }
1673 
1674 int
ipmi_sdr_parse_threshold_deassertion_supported(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * lower_non_critical_going_low,uint8_t * lower_non_critical_going_high,uint8_t * lower_critical_going_low,uint8_t * lower_critical_going_high,uint8_t * lower_non_recoverable_going_low,uint8_t * lower_non_recoverable_going_high,uint8_t * upper_non_critical_going_low,uint8_t * upper_non_critical_going_high,uint8_t * upper_critical_going_low,uint8_t * upper_critical_going_high,uint8_t * upper_non_recoverable_going_low,uint8_t * upper_non_recoverable_going_high)1675 ipmi_sdr_parse_threshold_deassertion_supported (ipmi_sdr_ctx_t ctx,
1676                                                 const void *sdr_record,
1677                                                 unsigned int sdr_record_len,
1678                                                 uint8_t *lower_non_critical_going_low,
1679                                                 uint8_t *lower_non_critical_going_high,
1680                                                 uint8_t *lower_critical_going_low,
1681                                                 uint8_t *lower_critical_going_high,
1682                                                 uint8_t *lower_non_recoverable_going_low,
1683                                                 uint8_t *lower_non_recoverable_going_high,
1684                                                 uint8_t *upper_non_critical_going_low,
1685                                                 uint8_t *upper_non_critical_going_high,
1686                                                 uint8_t *upper_critical_going_low,
1687                                                 uint8_t *upper_critical_going_high,
1688                                                 uint8_t *upper_non_recoverable_going_low,
1689                                                 uint8_t *upper_non_recoverable_going_high)
1690 {
1691   fiid_obj_t obj_sdr_record = NULL;
1692   fiid_obj_t obj_sdr_record_threshold = NULL;
1693   uint32_t acceptable_record_types;
1694   uint8_t event_reading_type_code;
1695   uint64_t val;
1696   int rv = -1;
1697 
1698   /* achu:
1699    *
1700    * Technically, the IPMI spec lists that compact record formats also
1701    * support settable thresholds.  However, since compact records
1702    * don't contain any information for interpreting threshold sensors
1703    * (e.g. R exponent) I don't know how they could be of any use.  No
1704    * vendor that I know of supports threshold sensors via a compact
1705    * record (excluding possible OEM ones).
1706    *
1707    * There's a part of me that believes the readable/setting
1708    * threshold masks for compact sensor records is a cut and paste
1709    * typo.  It shouldn't be there.
1710    */
1711 
1712   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
1713 
1714   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
1715                                                  sdr_record,
1716                                                  sdr_record_len,
1717                                                  acceptable_record_types)))
1718     goto cleanup;
1719 
1720   /* We don't want the generic sdr full record, we need the special
1721    * threshold one.
1722    */
1723 
1724   if (ipmi_sdr_parse_event_reading_type_code (ctx,
1725                                               sdr_record,
1726                                               sdr_record_len,
1727                                               &event_reading_type_code) < 0)
1728     goto cleanup;
1729 
1730   if (!IPMI_EVENT_READING_TYPE_CODE_IS_THRESHOLD (event_reading_type_code))
1731     {
1732       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
1733       goto cleanup;
1734     }
1735 
1736   if (!(obj_sdr_record_threshold = fiid_obj_copy (obj_sdr_record,
1737                                                   tmpl_sdr_full_sensor_record_threshold_based_sensors)))
1738     {
1739       SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
1740       goto cleanup;
1741     }
1742 
1743   if (lower_non_critical_going_low)
1744     {
1745       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1746                         "threshold_deassertion_event_mask.lower_non_critical_going_low_supported",
1747                         &val) < 0)
1748         {
1749           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1750           goto cleanup;
1751         }
1752       *lower_non_critical_going_low = val;
1753     }
1754 
1755   if (lower_non_critical_going_high)
1756     {
1757       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1758                         "threshold_deassertion_event_mask.lower_non_critical_going_high_supported",
1759                         &val) < 0)
1760         {
1761           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1762           goto cleanup;
1763         }
1764       *lower_non_critical_going_high = val;
1765     }
1766 
1767   if (lower_critical_going_low)
1768     {
1769       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1770                         "threshold_deassertion_event_mask.lower_critical_going_low_supported",
1771                         &val) < 0)
1772         {
1773           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1774           goto cleanup;
1775         }
1776       *lower_critical_going_low = val;
1777     }
1778 
1779   if (lower_critical_going_high)
1780     {
1781       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1782                         "threshold_deassertion_event_mask.lower_critical_going_high_supported",
1783                         &val) < 0)
1784         {
1785           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1786           goto cleanup;
1787         }
1788       *lower_critical_going_high = val;
1789     }
1790 
1791   if (lower_non_recoverable_going_low)
1792     {
1793       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1794                         "threshold_deassertion_event_mask.lower_non_recoverable_going_low_supported",
1795                         &val) < 0)
1796         {
1797           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1798           goto cleanup;
1799         }
1800       *lower_non_recoverable_going_low = val;
1801     }
1802 
1803   if (lower_non_recoverable_going_high)
1804     {
1805       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1806                         "threshold_deassertion_event_mask.lower_non_recoverable_going_high_supported",
1807                         &val) < 0)
1808         {
1809           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1810           goto cleanup;
1811         }
1812       *lower_non_recoverable_going_high = val;
1813     }
1814 
1815   if (upper_non_critical_going_low)
1816     {
1817       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1818                         "threshold_deassertion_event_mask.upper_non_critical_going_low_supported",
1819                         &val) < 0)
1820         {
1821           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1822           goto cleanup;
1823         }
1824       *upper_non_critical_going_low = val;
1825     }
1826 
1827   if (upper_non_critical_going_high)
1828     {
1829       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1830                         "threshold_deassertion_event_mask.upper_non_critical_going_high_supported",
1831                         &val) < 0)
1832         {
1833           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1834           goto cleanup;
1835         }
1836       *upper_non_critical_going_high = val;
1837     }
1838 
1839   if (upper_critical_going_low)
1840     {
1841       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1842                         "threshold_deassertion_event_mask.upper_critical_going_low_supported",
1843                         &val) < 0)
1844         {
1845           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1846           goto cleanup;
1847         }
1848       *upper_critical_going_low = val;
1849     }
1850 
1851   if (upper_critical_going_high)
1852     {
1853       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1854                         "threshold_deassertion_event_mask.upper_critical_going_high_supported",
1855                         &val) < 0)
1856         {
1857           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1858           goto cleanup;
1859         }
1860       *upper_critical_going_high = val;
1861     }
1862 
1863   if (upper_non_recoverable_going_low)
1864     {
1865       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1866                         "threshold_deassertion_event_mask.upper_non_recoverable_going_low_supported",
1867                         &val) < 0)
1868         {
1869           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1870           goto cleanup;
1871         }
1872       *upper_non_recoverable_going_low = val;
1873     }
1874 
1875   if (upper_non_recoverable_going_high)
1876     {
1877       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1878                         "threshold_deassertion_event_mask.upper_non_recoverable_going_high_supported",
1879                         &val) < 0)
1880         {
1881           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1882           goto cleanup;
1883         }
1884       *upper_non_recoverable_going_high = val;
1885     }
1886 
1887   rv = 0;
1888   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
1889  cleanup:
1890   fiid_obj_destroy (obj_sdr_record);
1891   fiid_obj_destroy (obj_sdr_record_threshold);
1892   return (rv);
1893 }
1894 
1895 int
ipmi_sdr_parse_threshold_readable(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * lower_non_critical_threshold,uint8_t * lower_critical_threshold,uint8_t * lower_non_recoverable_threshold,uint8_t * upper_non_critical_threshold,uint8_t * upper_critical_threshold,uint8_t * upper_non_recoverable_threshold)1896 ipmi_sdr_parse_threshold_readable (ipmi_sdr_ctx_t ctx,
1897                                    const void *sdr_record,
1898                                    unsigned int sdr_record_len,
1899                                    uint8_t *lower_non_critical_threshold,
1900                                    uint8_t *lower_critical_threshold,
1901                                    uint8_t *lower_non_recoverable_threshold,
1902                                    uint8_t *upper_non_critical_threshold,
1903                                    uint8_t *upper_critical_threshold,
1904                                    uint8_t *upper_non_recoverable_threshold)
1905 {
1906   fiid_obj_t obj_sdr_record = NULL;
1907   fiid_obj_t obj_sdr_record_threshold = NULL;
1908   uint32_t acceptable_record_types;
1909   uint8_t event_reading_type_code;
1910   uint64_t val;
1911   int rv = -1;
1912 
1913   /* achu:
1914    *
1915    * Technically, the IPMI spec lists that compact record formats also
1916    * support settable thresholds.  However, since compact records
1917    * don't contain any information for interpreting threshold sensors
1918    * (e.g. R exponent) I don't know how they could be of any use.  No
1919    * vendor that I know of supports threshold sensors via a compact
1920    * record (excluding possible OEM ones).
1921    *
1922    * There's a part of me that believes the readable/setting
1923    * threshold masks for compact sensor records is a cut and paste
1924    * typo.  It shouldn't be there.
1925    */
1926 
1927   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
1928 
1929   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
1930                                                  sdr_record,
1931                                                  sdr_record_len,
1932                                                  acceptable_record_types)))
1933     goto cleanup;
1934 
1935   /* We don't want the generic sdr full record, we need the special
1936    * threshold one.
1937    */
1938 
1939   if (ipmi_sdr_parse_event_reading_type_code (ctx,
1940                                               sdr_record,
1941                                               sdr_record_len,
1942                                               &event_reading_type_code) < 0)
1943     goto cleanup;
1944 
1945   if (!IPMI_EVENT_READING_TYPE_CODE_IS_THRESHOLD (event_reading_type_code))
1946     {
1947       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
1948       goto cleanup;
1949     }
1950 
1951   if (!(obj_sdr_record_threshold = fiid_obj_copy (obj_sdr_record,
1952                                                   tmpl_sdr_full_sensor_record_threshold_based_sensors)))
1953     {
1954       SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
1955       goto cleanup;
1956     }
1957 
1958   if (lower_non_critical_threshold)
1959     {
1960       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1961                         "readable_threshold_mask.lower_non_critical_threshold_is_readable",
1962                         &val) < 0)
1963         {
1964           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1965           goto cleanup;
1966         }
1967       *lower_non_critical_threshold = val;
1968     }
1969 
1970   if (lower_critical_threshold)
1971     {
1972       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1973                         "readable_threshold_mask.lower_critical_threshold_is_readable",
1974                         &val) < 0)
1975         {
1976           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1977           goto cleanup;
1978         }
1979       *lower_critical_threshold = val;
1980     }
1981 
1982   if (lower_non_recoverable_threshold)
1983     {
1984       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1985                         "readable_threshold_mask.lower_non_recoverable_threshold_is_readable",
1986                         &val) < 0)
1987         {
1988           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
1989           goto cleanup;
1990         }
1991       *lower_non_recoverable_threshold = val;
1992     }
1993 
1994   if (upper_non_critical_threshold)
1995     {
1996       if (FIID_OBJ_GET (obj_sdr_record_threshold,
1997                         "readable_threshold_mask.upper_non_critical_threshold_is_readable",
1998                         &val) < 0)
1999         {
2000           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2001           goto cleanup;
2002         }
2003       *upper_non_critical_threshold = val;
2004     }
2005 
2006   if (upper_critical_threshold)
2007     {
2008       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2009                         "readable_threshold_mask.upper_critical_threshold_is_readable",
2010                         &val) < 0)
2011         {
2012           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2013           goto cleanup;
2014         }
2015       *upper_critical_threshold = val;
2016     }
2017 
2018   if (upper_non_recoverable_threshold)
2019     {
2020       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2021                         "readable_threshold_mask.upper_non_recoverable_threshold_is_readable",
2022                         &val) < 0)
2023         {
2024           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2025           goto cleanup;
2026         }
2027       *upper_non_recoverable_threshold = val;
2028     }
2029 
2030   rv = 0;
2031   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
2032  cleanup:
2033   fiid_obj_destroy (obj_sdr_record);
2034   fiid_obj_destroy (obj_sdr_record_threshold);
2035   return (rv);
2036 }
2037 
2038 int
ipmi_sdr_parse_threshold_settable(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * lower_non_critical_threshold,uint8_t * lower_critical_threshold,uint8_t * lower_non_recoverable_threshold,uint8_t * upper_non_critical_threshold,uint8_t * upper_critical_threshold,uint8_t * upper_non_recoverable_threshold)2039 ipmi_sdr_parse_threshold_settable (ipmi_sdr_ctx_t ctx,
2040                                    const void *sdr_record,
2041                                    unsigned int sdr_record_len,
2042                                    uint8_t *lower_non_critical_threshold,
2043                                    uint8_t *lower_critical_threshold,
2044                                    uint8_t *lower_non_recoverable_threshold,
2045                                    uint8_t *upper_non_critical_threshold,
2046                                    uint8_t *upper_critical_threshold,
2047                                    uint8_t *upper_non_recoverable_threshold)
2048 {
2049   fiid_obj_t obj_sdr_record = NULL;
2050   fiid_obj_t obj_sdr_record_threshold = NULL;
2051   uint32_t acceptable_record_types;
2052   uint8_t event_reading_type_code;
2053   uint64_t val;
2054   int rv = -1;
2055 
2056   /* achu:
2057    *
2058    * Technically, the IPMI spec lists that compact record formats also
2059    * support settable thresholds.  However, since compact records
2060    * don't contain any information for interpreting threshold sensors
2061    * (e.g. R exponent) I don't know how they could be of any use.  No
2062    * vendor that I know of supports threshold sensors via a compact
2063    * record (excluding possible OEM ones).
2064    *
2065    * There's a part of me that believes the readable/setting
2066    * threshold masks for compact sensor records is a cut and paste
2067    * typo.  It shouldn't be there.
2068    */
2069 
2070   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
2071 
2072   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
2073                                                  sdr_record,
2074                                                  sdr_record_len,
2075                                                  acceptable_record_types)))
2076     goto cleanup;
2077 
2078   /* We don't want the generic sdr full record, we need the special
2079    * threshold one.
2080    */
2081 
2082   if (ipmi_sdr_parse_event_reading_type_code (ctx,
2083                                               sdr_record,
2084                                               sdr_record_len,
2085                                               &event_reading_type_code) < 0)
2086     goto cleanup;
2087 
2088   if (!IPMI_EVENT_READING_TYPE_CODE_IS_THRESHOLD (event_reading_type_code))
2089     {
2090       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
2091       goto cleanup;
2092     }
2093 
2094   if (!(obj_sdr_record_threshold = fiid_obj_copy (obj_sdr_record,
2095                                                   tmpl_sdr_full_sensor_record_threshold_based_sensors)))
2096     {
2097       SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2098       goto cleanup;
2099     }
2100 
2101   if (lower_non_critical_threshold)
2102     {
2103       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2104                         "settable_threshold_mask.lower_non_critical_threshold_is_settable",
2105                         &val) < 0)
2106         {
2107           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2108           goto cleanup;
2109         }
2110       *lower_non_critical_threshold = val;
2111     }
2112 
2113   if (lower_critical_threshold)
2114     {
2115       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2116                         "settable_threshold_mask.lower_critical_threshold_is_settable",
2117                         &val) < 0)
2118         {
2119           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2120           goto cleanup;
2121         }
2122       *lower_critical_threshold = val;
2123     }
2124 
2125   if (lower_non_recoverable_threshold)
2126     {
2127       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2128                         "settable_threshold_mask.lower_non_recoverable_threshold_is_settable",
2129                         &val) < 0)
2130         {
2131           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2132           goto cleanup;
2133         }
2134       *lower_non_recoverable_threshold = val;
2135     }
2136 
2137   if (upper_non_critical_threshold)
2138     {
2139       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2140                         "settable_threshold_mask.upper_non_critical_threshold_is_settable",
2141                         &val) < 0)
2142         {
2143           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2144           goto cleanup;
2145         }
2146       *upper_non_critical_threshold = val;
2147     }
2148 
2149   if (upper_critical_threshold)
2150     {
2151       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2152                         "settable_threshold_mask.upper_critical_threshold_is_settable",
2153                         &val) < 0)
2154         {
2155           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2156           goto cleanup;
2157         }
2158       *upper_critical_threshold = val;
2159     }
2160 
2161   if (upper_non_recoverable_threshold)
2162     {
2163       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2164                         "settable_threshold_mask.upper_non_recoverable_threshold_is_settable",
2165                         &val) < 0)
2166         {
2167           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2168           goto cleanup;
2169         }
2170       *upper_non_recoverable_threshold = val;
2171     }
2172 
2173   rv = 0;
2174   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
2175  cleanup:
2176   fiid_obj_destroy (obj_sdr_record);
2177   fiid_obj_destroy (obj_sdr_record_threshold);
2178   return (rv);
2179 }
2180 
2181 int
ipmi_sdr_parse_sensor_decoding_data(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,int8_t * r_exponent,int8_t * b_exponent,int16_t * m,int16_t * b,uint8_t * linearization,uint8_t * analog_data_format)2182 ipmi_sdr_parse_sensor_decoding_data (ipmi_sdr_ctx_t ctx,
2183                                      const void *sdr_record,
2184                                      unsigned int sdr_record_len,
2185                                      int8_t *r_exponent,
2186                                      int8_t *b_exponent,
2187                                      int16_t *m,
2188                                      int16_t *b,
2189                                      uint8_t *linearization,
2190                                      uint8_t *analog_data_format)
2191 {
2192   fiid_obj_t obj_sdr_record = NULL;
2193   uint32_t acceptable_record_types;
2194   uint64_t val, val1, val2;
2195   int rv = -1;
2196 
2197   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
2198 
2199   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
2200                                                  sdr_record,
2201                                                  sdr_record_len,
2202                                                  acceptable_record_types)))
2203     goto cleanup;
2204 
2205   if (r_exponent)
2206     {
2207       if (FIID_OBJ_GET (obj_sdr_record,
2208                         "r_exponent",
2209                         &val) < 0)
2210         {
2211           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2212           goto cleanup;
2213         }
2214       *r_exponent = val;
2215       if (*r_exponent & 0x08)
2216         *r_exponent |= 0xF0;
2217     }
2218 
2219   if (b_exponent)
2220     {
2221       if (FIID_OBJ_GET (obj_sdr_record,
2222                         "b_exponent",
2223                         &val) < 0)
2224         {
2225           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2226           goto cleanup;
2227         }
2228       *b_exponent = val;
2229       if (*b_exponent & 0x08)
2230         *b_exponent |= 0xF0;
2231     }
2232 
2233   if (m)
2234     {
2235       if (FIID_OBJ_GET (obj_sdr_record,
2236                         "m_ls",
2237                         &val1) < 0)
2238         {
2239           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2240           goto cleanup;
2241         }
2242       if (FIID_OBJ_GET (obj_sdr_record,
2243                         "m_ms",
2244                         &val2) < 0)
2245         {
2246           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2247           goto cleanup;
2248         }
2249       *m = val1;
2250       *m |= (((int16_t)val2 & 0x3) << 8);
2251       if (*m & 0x200)
2252         *m |= 0xFE00;
2253     }
2254 
2255   if (b)
2256     {
2257       if (FIID_OBJ_GET (obj_sdr_record,
2258                         "b_ls",
2259                         &val1) < 0)
2260         {
2261           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2262           goto cleanup;
2263         }
2264       if (FIID_OBJ_GET (obj_sdr_record,
2265                         "b_ms",
2266                         &val2) < 0)
2267         {
2268           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2269           goto cleanup;
2270         }
2271       *b = val1;
2272       *b |= (((int16_t)val2 & 0x3) << 8);
2273       if (*b & 0x200)
2274         *b |= 0xFE00;
2275     }
2276 
2277   if (linearization)
2278     {
2279       if (FIID_OBJ_GET (obj_sdr_record,
2280                         "linearization",
2281                         &val) < 0)
2282         {
2283           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2284           goto cleanup;
2285         }
2286       (*linearization) = val;
2287     }
2288 
2289   if (analog_data_format)
2290     {
2291       if (FIID_OBJ_GET (obj_sdr_record,
2292                         "sensor_unit1.analog_data_format",
2293                         &val) < 0)
2294         {
2295           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2296           goto cleanup;
2297         }
2298       (*analog_data_format) = val;
2299     }
2300 
2301   rv = 0;
2302   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
2303  cleanup:
2304   fiid_obj_destroy (obj_sdr_record);
2305   return (rv);
2306 }
2307 
2308 static int
_sensor_decode_value(ipmi_sdr_ctx_t ctx,int8_t r_exponent,int8_t b_exponent,int16_t m,int16_t b,uint8_t linearization,uint8_t analog_data_format,uint8_t raw_data,double ** value_ptr)2309 _sensor_decode_value (ipmi_sdr_ctx_t ctx,
2310                       int8_t r_exponent,
2311                       int8_t b_exponent,
2312                       int16_t m,
2313                       int16_t b,
2314                       uint8_t linearization,
2315                       uint8_t analog_data_format,
2316                       uint8_t raw_data,
2317                       double **value_ptr)
2318 {
2319   double reading;
2320   int rv = -1;
2321 
2322   assert (ctx);
2323   assert (ctx->magic == IPMI_SDR_CTX_MAGIC);
2324   assert (value_ptr);
2325 
2326   *value_ptr = NULL;
2327 
2328   if (ipmi_sensor_decode_value (r_exponent,
2329                                 b_exponent,
2330                                 m,
2331                                 b,
2332                                 linearization,
2333                                 analog_data_format,
2334                                 raw_data,
2335                                 &reading) < 0)
2336     {
2337       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
2338       goto cleanup;
2339     }
2340 
2341   if (!((*value_ptr) = (double *)malloc (sizeof (double))))
2342     {
2343       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_OUT_OF_MEMORY);
2344       goto cleanup;
2345     }
2346   (**value_ptr) = reading;
2347 
2348   rv = 0;
2349  cleanup:
2350   return (rv);
2351 }
2352 
2353 int
ipmi_sdr_parse_sensor_reading_ranges_specified(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * nominal_reading_specified,uint8_t * normal_maximum_specified,uint8_t * normal_minimum_specified)2354 ipmi_sdr_parse_sensor_reading_ranges_specified (ipmi_sdr_ctx_t ctx,
2355                                                 const void *sdr_record,
2356                                                 unsigned int sdr_record_len,
2357                                                 uint8_t *nominal_reading_specified,
2358                                                 uint8_t *normal_maximum_specified,
2359                                                 uint8_t *normal_minimum_specified)
2360 {
2361   fiid_obj_t obj_sdr_record = NULL;
2362   uint32_t acceptable_record_types;
2363   uint64_t val;
2364   int rv = -1;
2365 
2366   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
2367 
2368   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
2369                                                  sdr_record,
2370                                                  sdr_record_len,
2371                                                  acceptable_record_types)))
2372     goto cleanup;
2373 
2374   if (nominal_reading_specified)
2375     {
2376       if (FIID_OBJ_GET (obj_sdr_record,
2377                         "analog_characteristics_flag.nominal_reading",
2378                         &val) < 0)
2379         {
2380           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2381           goto cleanup;
2382         }
2383       *nominal_reading_specified = val;
2384     }
2385 
2386   if (normal_maximum_specified)
2387     {
2388       if (FIID_OBJ_GET (obj_sdr_record,
2389                         "analog_characteristics_flag.normal_max",
2390                         &val) < 0)
2391         {
2392           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2393           goto cleanup;
2394         }
2395       *normal_maximum_specified = val;
2396     }
2397 
2398   if (normal_minimum_specified)
2399     {
2400       if (FIID_OBJ_GET (obj_sdr_record,
2401                         "analog_characteristics_flag.normal_min",
2402                         &val) < 0)
2403         {
2404           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2405           goto cleanup;
2406         }
2407       *normal_minimum_specified = val;
2408     }
2409 
2410   rv = 0;
2411   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
2412  cleanup:
2413   fiid_obj_destroy (obj_sdr_record);
2414   return (rv);
2415 }
2416 
2417 int
ipmi_sdr_parse_sensor_reading_ranges(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,double ** nominal_reading,double ** normal_maximum,double ** normal_minimum,double ** sensor_maximum_reading,double ** sensor_minimum_reading)2418 ipmi_sdr_parse_sensor_reading_ranges (ipmi_sdr_ctx_t ctx,
2419                                       const void *sdr_record,
2420                                       unsigned int sdr_record_len,
2421                                       double **nominal_reading,
2422                                       double **normal_maximum,
2423                                       double **normal_minimum,
2424                                       double **sensor_maximum_reading,
2425                                       double **sensor_minimum_reading)
2426 {
2427   fiid_obj_t obj_sdr_record = NULL;
2428   uint32_t acceptable_record_types;
2429   int8_t r_exponent, b_exponent;
2430   int16_t m, b;
2431   uint8_t reading_raw, linearization, analog_data_format;
2432   double *tmp_nominal_reading = NULL;
2433   double *tmp_normal_maximum = NULL;
2434   double *tmp_normal_minimum = NULL;
2435   double *tmp_sensor_maximum_reading = NULL;
2436   double *tmp_sensor_minimum_reading = NULL;
2437   uint64_t val;
2438   int rv = -1;
2439 
2440   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
2441 
2442   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
2443                                                  sdr_record,
2444                                                  sdr_record_len,
2445                                                  acceptable_record_types)))
2446     goto cleanup;
2447 
2448   if (nominal_reading)
2449     *nominal_reading = NULL;
2450   if (normal_maximum)
2451     *normal_maximum = NULL;
2452   if (normal_minimum)
2453     *normal_minimum = NULL;
2454   if (sensor_maximum_reading)
2455     *sensor_maximum_reading = NULL;
2456   if (sensor_minimum_reading)
2457     *sensor_minimum_reading = NULL;
2458 
2459   if (ipmi_sdr_parse_sensor_decoding_data (ctx,
2460                                            sdr_record,
2461                                            sdr_record_len,
2462                                            &r_exponent,
2463                                            &b_exponent,
2464                                            &m,
2465                                            &b,
2466                                            &linearization,
2467                                            &analog_data_format) < 0)
2468     goto cleanup;
2469 
2470   if (!IPMI_SDR_ANALOG_DATA_FORMAT_VALID (analog_data_format))
2471     {
2472       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_CANNOT_PARSE_OR_CALCULATE);
2473       goto cleanup;
2474     }
2475 
2476   if (!IPMI_SDR_LINEARIZATION_IS_LINEAR (linearization))
2477     {
2478       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_CANNOT_PARSE_OR_CALCULATE);
2479       goto cleanup;
2480     }
2481 
2482   if (nominal_reading)
2483     {
2484       if (FIID_OBJ_GET (obj_sdr_record,
2485                         "nominal_reading",
2486                         &val) < 0)
2487         {
2488           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2489           goto cleanup;
2490         }
2491       reading_raw = val;
2492 
2493       if (_sensor_decode_value (ctx,
2494                                 r_exponent,
2495                                 b_exponent,
2496                                 m,
2497                                 b,
2498                                 linearization,
2499                                 analog_data_format,
2500                                 reading_raw,
2501                                 &tmp_nominal_reading) < 0)
2502         goto cleanup;
2503     }
2504   if (normal_maximum)
2505     {
2506       if (FIID_OBJ_GET (obj_sdr_record,
2507                         "normal_maximum",
2508                         &val) < 0)
2509         {
2510           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2511           goto cleanup;
2512         }
2513       reading_raw = val;
2514 
2515       if (_sensor_decode_value (ctx,
2516                                 r_exponent,
2517                                 b_exponent,
2518                                 m,
2519                                 b,
2520                                 linearization,
2521                                 analog_data_format,
2522                                 reading_raw,
2523                                 &tmp_normal_maximum) < 0)
2524         goto cleanup;
2525     }
2526   if (normal_minimum)
2527     {
2528       if (FIID_OBJ_GET (obj_sdr_record,
2529                         "normal_minimum",
2530                         &val) < 0)
2531         {
2532           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2533           goto cleanup;
2534         }
2535       reading_raw = val;
2536 
2537       if (_sensor_decode_value (ctx,
2538                                 r_exponent,
2539                                 b_exponent,
2540                                 m,
2541                                 b,
2542                                 linearization,
2543                                 analog_data_format,
2544                                 reading_raw,
2545                                 &tmp_normal_minimum) < 0)
2546         goto cleanup;
2547     }
2548   if (sensor_maximum_reading)
2549     {
2550       if (FIID_OBJ_GET (obj_sdr_record,
2551                         "sensor_maximum_reading",
2552                         &val) < 0)
2553         {
2554           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2555           goto cleanup;
2556         }
2557       reading_raw = val;
2558 
2559       if (_sensor_decode_value (ctx,
2560                                 r_exponent,
2561                                 b_exponent,
2562                                 m,
2563                                 b,
2564                                 linearization,
2565                                 analog_data_format,
2566                                 reading_raw,
2567                                 &tmp_sensor_maximum_reading) < 0)
2568         goto cleanup;
2569     }
2570   if (sensor_minimum_reading)
2571     {
2572       if (FIID_OBJ_GET (obj_sdr_record,
2573                         "sensor_minimum_reading",
2574                         &val) < 0)
2575         {
2576           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2577           goto cleanup;
2578         }
2579       reading_raw = val;
2580 
2581       if (_sensor_decode_value (ctx,
2582                                 r_exponent,
2583                                 b_exponent,
2584                                 m,
2585                                 b,
2586                                 linearization,
2587                                 analog_data_format,
2588                                 reading_raw,
2589                                 &tmp_sensor_minimum_reading) < 0)
2590         goto cleanup;
2591     }
2592 
2593   if (nominal_reading)
2594     *nominal_reading = tmp_nominal_reading;
2595   if (normal_maximum)
2596     *normal_maximum = tmp_normal_maximum;
2597   if (normal_minimum)
2598     *normal_minimum = tmp_normal_minimum;
2599   if (sensor_maximum_reading)
2600     *sensor_maximum_reading = tmp_sensor_maximum_reading;
2601   if (sensor_minimum_reading)
2602     *sensor_minimum_reading = tmp_sensor_minimum_reading;
2603 
2604   rv = 0;
2605   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
2606  cleanup:
2607   fiid_obj_destroy (obj_sdr_record);
2608   if (rv < 0)
2609     {
2610       free (tmp_nominal_reading);
2611       free (tmp_normal_maximum);
2612       free (tmp_normal_minimum);
2613       free (tmp_sensor_maximum_reading);
2614       free (tmp_sensor_minimum_reading);
2615     }
2616   return (rv);
2617 }
2618 
2619 int
ipmi_sdr_parse_thresholds(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,double ** lower_non_critical_threshold,double ** lower_critical_threshold,double ** lower_non_recoverable_threshold,double ** upper_non_critical_threshold,double ** upper_critical_threshold,double ** upper_non_recoverable_threshold)2620 ipmi_sdr_parse_thresholds (ipmi_sdr_ctx_t ctx,
2621                            const void *sdr_record,
2622                            unsigned int sdr_record_len,
2623                            double **lower_non_critical_threshold,
2624                            double **lower_critical_threshold,
2625                            double **lower_non_recoverable_threshold,
2626                            double **upper_non_critical_threshold,
2627                            double **upper_critical_threshold,
2628                            double **upper_non_recoverable_threshold)
2629 {
2630   fiid_obj_t obj_sdr_record = NULL;
2631   uint32_t acceptable_record_types;
2632   int8_t r_exponent, b_exponent;
2633   int16_t m, b;
2634   uint8_t threshold_raw, linearization, analog_data_format;
2635   double *tmp_lower_non_critical_threshold = NULL;
2636   double *tmp_lower_critical_threshold = NULL;
2637   double *tmp_lower_non_recoverable_threshold = NULL;
2638   double *tmp_upper_non_critical_threshold = NULL;
2639   double *tmp_upper_critical_threshold = NULL;
2640   double *tmp_upper_non_recoverable_threshold = NULL;
2641   uint64_t val;
2642   int rv = -1;
2643 
2644   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
2645 
2646   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
2647                                                  sdr_record,
2648                                                  sdr_record_len,
2649                                                  acceptable_record_types)))
2650     goto cleanup;
2651 
2652   if (lower_non_critical_threshold)
2653     *lower_non_critical_threshold = NULL;
2654   if (lower_critical_threshold)
2655     *lower_critical_threshold = NULL;
2656   if (lower_non_recoverable_threshold)
2657     *lower_non_recoverable_threshold = NULL;
2658   if (upper_non_critical_threshold)
2659     *upper_non_critical_threshold = NULL;
2660   if (upper_critical_threshold)
2661     *upper_critical_threshold = NULL;
2662   if (upper_non_recoverable_threshold)
2663     *upper_non_recoverable_threshold = NULL;
2664 
2665   if (ipmi_sdr_parse_sensor_decoding_data (ctx,
2666                                            sdr_record,
2667                                            sdr_record_len,
2668                                            &r_exponent,
2669                                            &b_exponent,
2670                                            &m,
2671                                            &b,
2672                                            &linearization,
2673                                            &analog_data_format) < 0)
2674     goto cleanup;
2675 
2676   if (!IPMI_SDR_ANALOG_DATA_FORMAT_VALID (analog_data_format))
2677     {
2678       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_CANNOT_PARSE_OR_CALCULATE);
2679       goto cleanup;
2680     }
2681 
2682   if (!IPMI_SDR_LINEARIZATION_IS_LINEAR (linearization))
2683     {
2684       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_CANNOT_PARSE_OR_CALCULATE);
2685       goto cleanup;
2686     }
2687 
2688   if (lower_non_critical_threshold)
2689     {
2690       if (FIID_OBJ_GET (obj_sdr_record,
2691                         "lower_non_critical_threshold",
2692                         &val) < 0)
2693         {
2694           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2695           goto cleanup;
2696         }
2697       threshold_raw = val;
2698 
2699       if (_sensor_decode_value (ctx,
2700                                 r_exponent,
2701                                 b_exponent,
2702                                 m,
2703                                 b,
2704                                 linearization,
2705                                 analog_data_format,
2706                                 threshold_raw,
2707                                 &tmp_lower_non_critical_threshold) < 0)
2708         goto cleanup;
2709     }
2710   if (lower_critical_threshold)
2711     {
2712       if (FIID_OBJ_GET (obj_sdr_record,
2713                         "lower_critical_threshold",
2714                         &val) < 0)
2715         {
2716           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2717           goto cleanup;
2718         }
2719       threshold_raw = val;
2720 
2721       if (_sensor_decode_value (ctx,
2722                                 r_exponent,
2723                                 b_exponent,
2724                                 m,
2725                                 b,
2726                                 linearization,
2727                                 analog_data_format,
2728                                 threshold_raw,
2729                                 &tmp_lower_critical_threshold) < 0)
2730         goto cleanup;
2731     }
2732   if (lower_non_recoverable_threshold)
2733     {
2734       if (FIID_OBJ_GET (obj_sdr_record,
2735                         "lower_non_recoverable_threshold",
2736                         &val) < 0)
2737         {
2738           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2739           goto cleanup;
2740         }
2741       threshold_raw = val;
2742 
2743       if (_sensor_decode_value (ctx,
2744                                 r_exponent,
2745                                 b_exponent,
2746                                 m,
2747                                 b,
2748                                 linearization,
2749                                 analog_data_format,
2750                                 threshold_raw,
2751                                 &tmp_lower_non_recoverable_threshold) < 0)
2752         goto cleanup;
2753     }
2754   if (upper_non_critical_threshold)
2755     {
2756       if (FIID_OBJ_GET (obj_sdr_record,
2757                         "upper_non_critical_threshold",
2758                         &val) < 0)
2759         {
2760           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2761           goto cleanup;
2762         }
2763       threshold_raw = val;
2764 
2765       if (_sensor_decode_value (ctx,
2766                                 r_exponent,
2767                                 b_exponent,
2768                                 m,
2769                                 b,
2770                                 linearization,
2771                                 analog_data_format,
2772                                 threshold_raw,
2773                                 &tmp_upper_non_critical_threshold) < 0)
2774         goto cleanup;
2775     }
2776   if (upper_critical_threshold)
2777     {
2778       if (FIID_OBJ_GET (obj_sdr_record,
2779                         "upper_critical_threshold",
2780                         &val) < 0)
2781         {
2782           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2783           goto cleanup;
2784         }
2785       threshold_raw = val;
2786 
2787       if (_sensor_decode_value (ctx,
2788                                 r_exponent,
2789                                 b_exponent,
2790                                 m,
2791                                 b,
2792                                 linearization,
2793                                 analog_data_format,
2794                                 threshold_raw,
2795                                 &tmp_upper_critical_threshold) < 0)
2796         goto cleanup;
2797     }
2798   if (upper_non_recoverable_threshold)
2799     {
2800       if (FIID_OBJ_GET (obj_sdr_record,
2801                         "upper_non_recoverable_threshold",
2802                         &val) < 0)
2803         {
2804           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2805           goto cleanup;
2806         }
2807       threshold_raw = val;
2808 
2809       if (_sensor_decode_value (ctx,
2810                                 r_exponent,
2811                                 b_exponent,
2812                                 m,
2813                                 b,
2814                                 linearization,
2815                                 analog_data_format,
2816                                 threshold_raw,
2817                                 &tmp_upper_non_recoverable_threshold) < 0)
2818         goto cleanup;
2819     }
2820 
2821   if (lower_non_critical_threshold)
2822     *lower_non_critical_threshold = tmp_lower_non_critical_threshold;
2823   if (lower_critical_threshold)
2824     *lower_critical_threshold = tmp_lower_critical_threshold;
2825   if (lower_non_recoverable_threshold)
2826     *lower_non_recoverable_threshold = tmp_lower_non_recoverable_threshold;
2827   if (upper_non_critical_threshold)
2828     *upper_non_critical_threshold = tmp_upper_non_critical_threshold;
2829   if (upper_critical_threshold)
2830     *upper_critical_threshold = tmp_upper_critical_threshold;
2831   if (upper_non_recoverable_threshold)
2832     *upper_non_recoverable_threshold = tmp_upper_non_recoverable_threshold;
2833 
2834   rv = 0;
2835   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
2836  cleanup:
2837   fiid_obj_destroy (obj_sdr_record);
2838   if (rv < 0)
2839     {
2840       free (tmp_lower_non_critical_threshold);
2841       free (tmp_lower_critical_threshold);
2842       free (tmp_lower_non_recoverable_threshold);
2843       free (tmp_upper_non_critical_threshold);
2844       free (tmp_upper_critical_threshold);
2845       free (tmp_upper_non_recoverable_threshold);
2846     }
2847   return (rv);
2848 }
2849 
2850 int
ipmi_sdr_parse_thresholds_raw(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * lower_non_critical_threshold,uint8_t * lower_critical_threshold,uint8_t * lower_non_recoverable_threshold,uint8_t * upper_non_critical_threshold,uint8_t * upper_critical_threshold,uint8_t * upper_non_recoverable_threshold)2851 ipmi_sdr_parse_thresholds_raw (ipmi_sdr_ctx_t ctx,
2852                                const void *sdr_record,
2853                                unsigned int sdr_record_len,
2854                                uint8_t *lower_non_critical_threshold,
2855                                uint8_t *lower_critical_threshold,
2856                                uint8_t *lower_non_recoverable_threshold,
2857                                uint8_t *upper_non_critical_threshold,
2858                                uint8_t *upper_critical_threshold,
2859                                uint8_t *upper_non_recoverable_threshold)
2860 {
2861   fiid_obj_t obj_sdr_record = NULL;
2862   fiid_obj_t obj_sdr_record_threshold = NULL;
2863   uint32_t acceptable_record_types;
2864   uint8_t event_reading_type_code;
2865   uint64_t val;
2866   int rv = -1;
2867 
2868   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
2869 
2870   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
2871                                                  sdr_record,
2872                                                  sdr_record_len,
2873                                                  acceptable_record_types)))
2874     goto cleanup;
2875 
2876   /* We don't want the generic sdr full record, we need the special
2877    * threshold one.
2878    */
2879 
2880   if (ipmi_sdr_parse_event_reading_type_code (ctx,
2881                                               sdr_record,
2882                                               sdr_record_len,
2883                                               &event_reading_type_code) < 0)
2884     goto cleanup;
2885 
2886   if (!IPMI_EVENT_READING_TYPE_CODE_IS_THRESHOLD (event_reading_type_code))
2887     {
2888       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD);
2889       goto cleanup;
2890     }
2891 
2892   if (!(obj_sdr_record_threshold = fiid_obj_copy (obj_sdr_record,
2893                                                   tmpl_sdr_full_sensor_record_threshold_based_sensors)))
2894     {
2895       SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
2896       goto cleanup;
2897     }
2898 
2899   if (lower_non_critical_threshold)
2900     {
2901       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2902                         "lower_non_critical_threshold",
2903                         &val) < 0)
2904         {
2905           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2906           goto cleanup;
2907         }
2908       *lower_non_critical_threshold = val;
2909     }
2910 
2911   if (lower_critical_threshold)
2912     {
2913       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2914                         "lower_critical_threshold",
2915                         &val) < 0)
2916         {
2917           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2918           goto cleanup;
2919         }
2920       *lower_critical_threshold = val;
2921     }
2922 
2923   if (lower_non_recoverable_threshold)
2924     {
2925       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2926                         "lower_non_recoverable_threshold",
2927                         &val) < 0)
2928         {
2929           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2930           goto cleanup;
2931         }
2932       *lower_non_recoverable_threshold = val;
2933     }
2934 
2935   if (upper_non_critical_threshold)
2936     {
2937       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2938                         "upper_non_critical_threshold",
2939                         &val) < 0)
2940         {
2941           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2942           goto cleanup;
2943         }
2944       *upper_non_critical_threshold = val;
2945     }
2946 
2947   if (upper_critical_threshold)
2948     {
2949       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2950                         "upper_critical_threshold",
2951                         &val) < 0)
2952         {
2953           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2954           goto cleanup;
2955         }
2956       *upper_critical_threshold = val;
2957     }
2958 
2959   if (upper_non_recoverable_threshold)
2960     {
2961       if (FIID_OBJ_GET (obj_sdr_record_threshold,
2962                         "upper_non_recoverable_threshold",
2963                         &val) < 0)
2964         {
2965           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_threshold);
2966           goto cleanup;
2967         }
2968       *upper_non_recoverable_threshold = val;
2969     }
2970 
2971   rv = 0;
2972   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
2973  cleanup:
2974   fiid_obj_destroy (obj_sdr_record);
2975   fiid_obj_destroy (obj_sdr_record_threshold);
2976   return (rv);
2977 }
2978 
2979 int
ipmi_sdr_parse_tolerance(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,double ** tolerance)2980 ipmi_sdr_parse_tolerance (ipmi_sdr_ctx_t ctx,
2981                           const void *sdr_record,
2982                           unsigned int sdr_record_len,
2983                           double **tolerance)
2984 {
2985   fiid_obj_t obj_sdr_record = NULL;
2986   uint32_t acceptable_record_types;
2987   int8_t r_exponent;
2988   int16_t m;
2989   uint8_t tolerance_raw, linearization;
2990   double *tmp_tolerance = NULL;
2991   uint64_t val;
2992   int rv = -1;
2993 
2994   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
2995 
2996   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
2997                                                  sdr_record,
2998                                                  sdr_record_len,
2999                                                  acceptable_record_types)))
3000     goto cleanup;
3001 
3002   if (tolerance)
3003     *tolerance = NULL;
3004 
3005   if (ipmi_sdr_parse_sensor_decoding_data (ctx,
3006                                            sdr_record,
3007                                            sdr_record_len,
3008                                            &r_exponent,
3009                                            NULL,
3010                                            &m,
3011                                            NULL,
3012                                            &linearization,
3013                                            NULL) < 0)
3014     goto cleanup;
3015 
3016   if (!IPMI_SDR_LINEARIZATION_IS_LINEAR (linearization))
3017     {
3018       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_CANNOT_PARSE_OR_CALCULATE);
3019       goto cleanup;
3020     }
3021 
3022   if (tolerance)
3023     {
3024       double reading;
3025 
3026       if (FIID_OBJ_GET (obj_sdr_record,
3027                         "tolerance",
3028                         &val) < 0)
3029         {
3030           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3031           goto cleanup;
3032         }
3033       tolerance_raw = val;
3034 
3035       if (ipmi_sensor_decode_tolerance (r_exponent,
3036                                         m,
3037                                         linearization,
3038                                         tolerance_raw,
3039                                         &reading) < 0)
3040         {
3041           SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
3042           goto cleanup;
3043         }
3044 
3045       if (!(tmp_tolerance = (double *)malloc (sizeof (double))))
3046         {
3047           SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_OUT_OF_MEMORY);
3048           goto cleanup;
3049         }
3050       (*tmp_tolerance) = reading;
3051     }
3052 
3053   if (tolerance)
3054     *tolerance = tmp_tolerance;
3055 
3056   rv = 0;
3057   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3058  cleanup:
3059   fiid_obj_destroy (obj_sdr_record);
3060   if (rv < 0)
3061     free (tmp_tolerance);
3062   return (rv);
3063 }
3064 
3065 int
ipmi_sdr_parse_accuracy(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,double ** accuracy)3066 ipmi_sdr_parse_accuracy (ipmi_sdr_ctx_t ctx,
3067                          const void *sdr_record,
3068                          unsigned int sdr_record_len,
3069                          double **accuracy)
3070 {
3071   fiid_obj_t obj_sdr_record = NULL;
3072   uint32_t acceptable_record_types;
3073   uint16_t accuracy_raw;
3074   uint8_t accuracy_ls, accuracy_ms, accuracy_exp;
3075   double *tmp_accuracy = NULL;
3076   uint64_t val;
3077   int rv = -1;
3078 
3079   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
3080 
3081   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3082                                                  sdr_record,
3083                                                  sdr_record_len,
3084                                                  acceptable_record_types)))
3085     goto cleanup;
3086 
3087   if (accuracy)
3088     *accuracy = NULL;
3089 
3090   if (accuracy)
3091     {
3092       double reading;
3093 
3094       if (FIID_OBJ_GET (obj_sdr_record,
3095                         "accuracy_ls",
3096                         &val) < 0)
3097         {
3098           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3099           goto cleanup;
3100         }
3101       accuracy_ls = val;
3102 
3103       if (FIID_OBJ_GET (obj_sdr_record,
3104                         "accuracy_ms",
3105                         &val) < 0)
3106         {
3107           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3108           goto cleanup;
3109         }
3110       accuracy_ms = val;
3111 
3112       /* accuracy is unsigned, no need to sign extend */
3113       accuracy_raw = accuracy_ls | (((uint16_t)accuracy_ms) << 6);
3114 
3115       if (FIID_OBJ_GET (obj_sdr_record,
3116                         "accuracy_exp",
3117                         &val) < 0)
3118         {
3119           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3120           goto cleanup;
3121         }
3122       accuracy_exp = val;
3123 
3124       if (ipmi_sensor_decode_accuracy (accuracy_raw,
3125                                        accuracy_exp,
3126                                        &reading) < 0)
3127         {
3128           SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
3129           goto cleanup;
3130         }
3131 
3132       if (!(tmp_accuracy = (double *)malloc (sizeof (double))))
3133         {
3134           SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_OUT_OF_MEMORY);
3135           goto cleanup;
3136         }
3137       (*tmp_accuracy) = reading;
3138     }
3139 
3140   if (accuracy)
3141     *accuracy = tmp_accuracy;
3142 
3143   rv = 0;
3144   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3145  cleanup:
3146   fiid_obj_destroy (obj_sdr_record);
3147   if (rv < 0)
3148     free (tmp_accuracy);
3149   return (rv);
3150 }
3151 
3152 int
ipmi_sdr_parse_hysteresis(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * positive_going_threshold_hysteresis,uint8_t * negative_going_threshold_hysteresis)3153 ipmi_sdr_parse_hysteresis (ipmi_sdr_ctx_t ctx,
3154                            const void *sdr_record,
3155                            unsigned int sdr_record_len,
3156                            uint8_t *positive_going_threshold_hysteresis,
3157                            uint8_t *negative_going_threshold_hysteresis)
3158 {
3159   fiid_obj_t obj_sdr_record = NULL;
3160   uint32_t acceptable_record_types;
3161   uint64_t val;
3162   int rv = -1;
3163 
3164   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FULL_SENSOR_RECORD;
3165   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
3166 
3167   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3168                                                  sdr_record,
3169                                                  sdr_record_len,
3170                                                  acceptable_record_types)))
3171     goto cleanup;
3172 
3173   if (positive_going_threshold_hysteresis)
3174     {
3175       if (FIID_OBJ_GET (obj_sdr_record,
3176                         "positive_going_threshold_hysteresis",
3177                         &val) < 0)
3178         {
3179           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3180           goto cleanup;
3181         }
3182       *positive_going_threshold_hysteresis = val;
3183     }
3184   if (negative_going_threshold_hysteresis)
3185     {
3186       if (FIID_OBJ_GET (obj_sdr_record,
3187                         "negative_going_threshold_hysteresis",
3188                         &val) < 0)
3189         {
3190           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3191           goto cleanup;
3192         }
3193       *negative_going_threshold_hysteresis = val;
3194     }
3195   rv = 0;
3196   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3197  cleanup:
3198   fiid_obj_destroy (obj_sdr_record);
3199   return (rv);
3200 }
3201 
3202 int
ipmi_sdr_parse_sensor_record_sharing(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * share_count,uint8_t * id_string_instance_modifier_type,uint8_t * id_string_instance_modifier_offset,uint8_t * entity_instance_sharing)3203 ipmi_sdr_parse_sensor_record_sharing (ipmi_sdr_ctx_t ctx,
3204                                       const void *sdr_record,
3205                                       unsigned int sdr_record_len,
3206                                       uint8_t *share_count,
3207                                       uint8_t *id_string_instance_modifier_type,
3208                                       uint8_t *id_string_instance_modifier_offset,
3209                                       uint8_t *entity_instance_sharing)
3210 {
3211   fiid_obj_t obj_sdr_record = NULL;
3212   uint32_t acceptable_record_types;
3213   uint64_t val;
3214   int rv = -1;
3215 
3216   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_COMPACT_SENSOR_RECORD;
3217   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_EVENT_ONLY_RECORD;
3218 
3219   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3220                                                  sdr_record,
3221                                                  sdr_record_len,
3222                                                  acceptable_record_types)))
3223     goto cleanup;
3224 
3225   if (share_count)
3226     {
3227       if (FIID_OBJ_GET (obj_sdr_record,
3228                         "share_count",
3229                         &val) < 0)
3230         {
3231           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3232           goto cleanup;
3233         }
3234       *share_count = val;
3235     }
3236 
3237   if (id_string_instance_modifier_type)
3238     {
3239       if (FIID_OBJ_GET (obj_sdr_record,
3240                         "id_string_instance_modifier_type",
3241                         &val) < 0)
3242         {
3243           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3244           goto cleanup;
3245         }
3246       *id_string_instance_modifier_type = val;
3247     }
3248 
3249   if (id_string_instance_modifier_offset)
3250     {
3251       if (FIID_OBJ_GET (obj_sdr_record,
3252                         "id_string_instance_modifier_offset",
3253                         &val) < 0)
3254         {
3255           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3256           goto cleanup;
3257         }
3258       *id_string_instance_modifier_offset = val;
3259     }
3260 
3261   if (entity_instance_sharing)
3262     {
3263       if (FIID_OBJ_GET (obj_sdr_record,
3264                         "entity_instance_sharing",
3265                         &val) < 0)
3266         {
3267           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3268           goto cleanup;
3269         }
3270       *entity_instance_sharing = val;
3271     }
3272 
3273   rv = 0;
3274   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3275  cleanup:
3276   fiid_obj_destroy (obj_sdr_record);
3277   return (rv);
3278 }
3279 
3280 int
ipmi_sdr_parse_container_entity(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * container_entity_id,uint8_t * container_entity_instance)3281 ipmi_sdr_parse_container_entity (ipmi_sdr_ctx_t ctx,
3282                                  const void *sdr_record,
3283                                  unsigned int sdr_record_len,
3284                                  uint8_t *container_entity_id,
3285                                  uint8_t *container_entity_instance)
3286 {
3287   fiid_obj_t obj_sdr_record = NULL;
3288   uint32_t acceptable_record_types;
3289   uint64_t val;
3290   int rv = -1;
3291 
3292   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_ENTITY_ASSOCIATION_RECORD;
3293   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_DEVICE_RELATIVE_ENTITY_ASSOCIATION_RECORD;
3294 
3295   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3296                                                  sdr_record,
3297                                                  sdr_record_len,
3298                                                  acceptable_record_types)))
3299     goto cleanup;
3300 
3301   if (container_entity_id)
3302     {
3303       if (FIID_OBJ_GET (obj_sdr_record,
3304                         "container_entity_id",
3305                         &val) < 0)
3306         {
3307           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3308           goto cleanup;
3309         }
3310       *container_entity_id = val;
3311     }
3312 
3313   if (container_entity_instance)
3314     {
3315       if (FIID_OBJ_GET (obj_sdr_record,
3316                         "container_entity_instance",
3317                         &val) < 0)
3318         {
3319           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3320           goto cleanup;
3321         }
3322       *container_entity_instance = val;
3323     }
3324 
3325   rv = 0;
3326   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3327  cleanup:
3328   fiid_obj_destroy (obj_sdr_record);
3329   return (rv);
3330 }
3331 
3332 int
ipmi_sdr_parse_device_id_string(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,char * device_id_string,unsigned int device_id_string_len)3333 ipmi_sdr_parse_device_id_string (ipmi_sdr_ctx_t ctx,
3334                                  const void *sdr_record,
3335                                  unsigned int sdr_record_len,
3336                                  char *device_id_string,
3337                                  unsigned int device_id_string_len)
3338 {
3339   fiid_obj_t obj_sdr_record = NULL;
3340   uint32_t acceptable_record_types;
3341   int len = 0;
3342   int rv = -1;
3343 
3344   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_GENERIC_DEVICE_LOCATOR_RECORD;
3345   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_FRU_DEVICE_LOCATOR_RECORD;
3346   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD;
3347 
3348   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3349                                                  sdr_record,
3350                                                  sdr_record_len,
3351                                                  acceptable_record_types)))
3352     goto cleanup;
3353 
3354   if (device_id_string && device_id_string_len)
3355     {
3356       if ((len = fiid_obj_get_data (obj_sdr_record,
3357                                     "device_id_string",
3358                                     device_id_string,
3359                                     device_id_string_len)) < 0)
3360         {
3361           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3362           goto cleanup;
3363         }
3364     }
3365 
3366   rv = len;
3367   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3368  cleanup:
3369   fiid_obj_destroy (obj_sdr_record);
3370   return (rv);
3371 }
3372 
3373 int
ipmi_sdr_parse_device_type(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * device_type,uint8_t * device_type_modifier)3374 ipmi_sdr_parse_device_type (ipmi_sdr_ctx_t ctx,
3375                             const void *sdr_record,
3376                             unsigned int sdr_record_len,
3377                             uint8_t *device_type,
3378                             uint8_t *device_type_modifier)
3379 {
3380   fiid_obj_t obj_sdr_record = NULL;
3381   uint32_t acceptable_record_types;
3382   uint64_t val;
3383   int rv = -1;
3384 
3385   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_GENERIC_DEVICE_LOCATOR_RECORD;
3386   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_FRU_DEVICE_LOCATOR_RECORD;
3387 
3388   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3389                                                  sdr_record,
3390                                                  sdr_record_len,
3391                                                  acceptable_record_types)))
3392     goto cleanup;
3393 
3394   if (device_type)
3395     {
3396       if (FIID_OBJ_GET (obj_sdr_record,
3397                         "device_type",
3398                         &val) < 0)
3399         {
3400           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3401           goto cleanup;
3402         }
3403       *device_type = val;
3404     }
3405   if (device_type_modifier)
3406     {
3407       if (FIID_OBJ_GET (obj_sdr_record,
3408                         "device_type_modifier",
3409                         &val) < 0)
3410         {
3411           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3412           goto cleanup;
3413         }
3414       *device_type_modifier = val;
3415     }
3416 
3417   rv = 0;
3418   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3419  cleanup:
3420   fiid_obj_destroy (obj_sdr_record);
3421   return (rv);
3422 }
3423 
3424 int
ipmi_sdr_parse_generic_device_locator_parameters(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * device_access_address,uint8_t * channel_number,uint8_t * device_slave_address,uint8_t * private_bus_id,uint8_t * lun_for_master_write_read_command,uint8_t * address_span,uint8_t * oem)3425 ipmi_sdr_parse_generic_device_locator_parameters (ipmi_sdr_ctx_t ctx,
3426                                                   const void *sdr_record,
3427                                                   unsigned int sdr_record_len,
3428                                                   uint8_t *device_access_address,
3429                                                   uint8_t *channel_number,
3430                                                   uint8_t *device_slave_address,
3431                                                   uint8_t *private_bus_id,
3432                                                   uint8_t *lun_for_master_write_read_command,
3433                                                   uint8_t *address_span,
3434                                                   uint8_t *oem)
3435 {
3436   fiid_obj_t obj_sdr_record = NULL;
3437   uint32_t acceptable_record_types;
3438   uint64_t val1, val2;
3439   uint64_t val;
3440   int rv = -1;
3441 
3442   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_GENERIC_DEVICE_LOCATOR_RECORD;
3443 
3444   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3445                                                  sdr_record,
3446                                                  sdr_record_len,
3447                                                  acceptable_record_types)))
3448     goto cleanup;
3449 
3450   if (device_access_address)
3451     {
3452       if (FIID_OBJ_GET (obj_sdr_record,
3453                         "device_access_address",
3454                         &val) < 0)
3455         {
3456           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3457           goto cleanup;
3458         }
3459       *device_access_address = val;
3460     }
3461   if (channel_number)
3462     {
3463       if (FIID_OBJ_GET (obj_sdr_record,
3464                         "channel_number_ls",
3465                         &val1) < 0)
3466         {
3467           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3468           goto cleanup;
3469         }
3470       if (FIID_OBJ_GET (obj_sdr_record,
3471                         "channel_number_ms",
3472                         &val2) < 0)
3473         {
3474           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3475           goto cleanup;
3476         }
3477       *channel_number = ((uint8_t)val1 << 3) | (uint8_t)val2;
3478     }
3479   if (device_slave_address)
3480     {
3481       if (FIID_OBJ_GET (obj_sdr_record,
3482                         "device_slave_address",
3483                         &val) < 0)
3484         {
3485           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3486           goto cleanup;
3487         }
3488       *device_slave_address = val;
3489     }
3490   if (private_bus_id)
3491     {
3492       if (FIID_OBJ_GET (obj_sdr_record,
3493                         "private_bus_id",
3494                         &val) < 0)
3495         {
3496           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3497           goto cleanup;
3498         }
3499       *private_bus_id = val;
3500     }
3501   if (lun_for_master_write_read_command)
3502     {
3503       if (FIID_OBJ_GET (obj_sdr_record,
3504                         "lun_for_master_write_read_command",
3505                         &val) < 0)
3506         {
3507           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3508           goto cleanup;
3509         }
3510       *lun_for_master_write_read_command = val;
3511     }
3512   if (address_span)
3513     {
3514       if (FIID_OBJ_GET (obj_sdr_record,
3515                         "address_span",
3516                         &val) < 0)
3517         {
3518           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3519           goto cleanup;
3520         }
3521       *address_span = val;
3522     }
3523   if (oem)
3524     {
3525       if (FIID_OBJ_GET (obj_sdr_record,
3526                         "oem",
3527                         &val) < 0)
3528         {
3529           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3530           goto cleanup;
3531         }
3532       *oem = val;
3533     }
3534 
3535   rv = 0;
3536   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3537  cleanup:
3538   fiid_obj_destroy (obj_sdr_record);
3539   return (rv);
3540 }
3541 
3542 int
ipmi_sdr_parse_fru_device_locator_parameters(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * device_access_address,uint8_t * logical_fru_device_device_slave_address,uint8_t * private_bus_id,uint8_t * lun_for_master_write_read_fru_command,uint8_t * logical_physical_fru_device,uint8_t * channel_number)3543 ipmi_sdr_parse_fru_device_locator_parameters (ipmi_sdr_ctx_t ctx,
3544                                               const void *sdr_record,
3545                                               unsigned int sdr_record_len,
3546                                               uint8_t *device_access_address,
3547                                               uint8_t *logical_fru_device_device_slave_address,
3548                                               uint8_t *private_bus_id,
3549                                               uint8_t *lun_for_master_write_read_fru_command,
3550                                               uint8_t *logical_physical_fru_device,
3551                                               uint8_t *channel_number)
3552 {
3553   fiid_obj_t obj_sdr_record = NULL;
3554   uint32_t acceptable_record_types;
3555   uint64_t val;
3556   int rv = -1;
3557 
3558   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FRU_DEVICE_LOCATOR_RECORD;
3559 
3560   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3561                                                  sdr_record,
3562                                                  sdr_record_len,
3563                                                  acceptable_record_types)))
3564     goto cleanup;
3565 
3566   if (device_access_address)
3567     {
3568       if (FIID_OBJ_GET (obj_sdr_record,
3569                         "device_access_address",
3570                         &val) < 0)
3571         {
3572           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3573           goto cleanup;
3574         }
3575       *device_access_address = val;
3576     }
3577   if (logical_fru_device_device_slave_address)
3578     {
3579       if (FIID_OBJ_GET (obj_sdr_record,
3580                         "logical_fru_device_device_slave_address",
3581                         &val) < 0)
3582         {
3583           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3584           goto cleanup;
3585         }
3586       *logical_fru_device_device_slave_address = val;
3587     }
3588   if (private_bus_id)
3589     {
3590       if (FIID_OBJ_GET (obj_sdr_record,
3591                         "private_bus_id",
3592                         &val) < 0)
3593         {
3594           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3595           goto cleanup;
3596         }
3597       *private_bus_id = val;
3598     }
3599   if (lun_for_master_write_read_fru_command)
3600     {
3601       if (FIID_OBJ_GET (obj_sdr_record,
3602                         "lun_for_master_write_read_fru_command",
3603                         &val) < 0)
3604         {
3605           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3606           goto cleanup;
3607         }
3608       *lun_for_master_write_read_fru_command = val;
3609     }
3610   if (logical_physical_fru_device)
3611     {
3612       if (FIID_OBJ_GET (obj_sdr_record,
3613                         "logical_physical_fru_device",
3614                         &val) < 0)
3615         {
3616           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3617           goto cleanup;
3618         }
3619       *logical_physical_fru_device = val;
3620     }
3621   if (channel_number)
3622     {
3623       if (FIID_OBJ_GET (obj_sdr_record,
3624                         "channel_number",
3625                         &val) < 0)
3626         {
3627           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3628           goto cleanup;
3629         }
3630       *channel_number = val;
3631     }
3632 
3633   rv = 0;
3634   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3635  cleanup:
3636   fiid_obj_destroy (obj_sdr_record);
3637   return (rv);
3638 }
3639 
3640 int
ipmi_sdr_parse_fru_entity_id_and_instance(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * fru_entity_id,uint8_t * fru_entity_instance)3641 ipmi_sdr_parse_fru_entity_id_and_instance (ipmi_sdr_ctx_t ctx,
3642                                            const void *sdr_record,
3643                                            unsigned int sdr_record_len,
3644                                            uint8_t *fru_entity_id,
3645                                            uint8_t *fru_entity_instance)
3646 {
3647   fiid_obj_t obj_sdr_record = NULL;
3648   uint32_t acceptable_record_types;
3649   uint64_t val;
3650   int rv = -1;
3651 
3652   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_FRU_DEVICE_LOCATOR_RECORD;
3653 
3654   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3655                                                  sdr_record,
3656                                                  sdr_record_len,
3657                                                  acceptable_record_types)))
3658     goto cleanup;
3659 
3660   if (fru_entity_id)
3661     {
3662       if (FIID_OBJ_GET (obj_sdr_record,
3663                         "fru_entity_id",
3664                         &val) < 0)
3665         {
3666           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3667           goto cleanup;
3668         }
3669       *fru_entity_id = val;
3670     }
3671   if (fru_entity_instance)
3672     {
3673       if (FIID_OBJ_GET (obj_sdr_record,
3674                         "fru_entity_instance",
3675                         &val) < 0)
3676         {
3677           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3678           goto cleanup;
3679         }
3680       *fru_entity_instance = val;
3681     }
3682 
3683   rv = 0;
3684   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3685  cleanup:
3686   fiid_obj_destroy (obj_sdr_record);
3687   return (rv);
3688 }
3689 
3690 int
ipmi_sdr_parse_management_controller_device_locator_parameters(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint8_t * device_slave_address,uint8_t * channel_number,uint8_t * global_initialization_event_message_generation,uint8_t * global_initialization_log_initialization_agent_errors,uint8_t * global_initialization_controller_logs_initialization_agent_errors,uint8_t * power_state_notification_controller,uint8_t * power_state_notification_acpi_device_power_state_notification,uint8_t * power_state_notification_acpi_system_power_state_notification,uint8_t * device_capabilities_sensor_device,uint8_t * device_capabilities_sdr_repository_device,uint8_t * device_capabilities_sel_device,uint8_t * device_capabilities_fru_inventory_device,uint8_t * device_capabilities_ipmb_event_receiver,uint8_t * device_capabilities_ipmb_event_generator,uint8_t * device_capabilities_bridge,uint8_t * device_capabilities_chassis_device)3691 ipmi_sdr_parse_management_controller_device_locator_parameters (ipmi_sdr_ctx_t ctx,
3692                                                                 const void *sdr_record,
3693                                                                 unsigned int sdr_record_len,
3694                                                                 uint8_t *device_slave_address,
3695                                                                 uint8_t *channel_number,
3696                                                                 uint8_t *global_initialization_event_message_generation,
3697                                                                 uint8_t *global_initialization_log_initialization_agent_errors,
3698                                                                 uint8_t *global_initialization_controller_logs_initialization_agent_errors,
3699                                                                 uint8_t *power_state_notification_controller,
3700                                                                 uint8_t *power_state_notification_acpi_device_power_state_notification,
3701                                                                 uint8_t *power_state_notification_acpi_system_power_state_notification,
3702                                                                 uint8_t *device_capabilities_sensor_device,
3703                                                                 uint8_t *device_capabilities_sdr_repository_device,
3704                                                                 uint8_t *device_capabilities_sel_device,
3705                                                                 uint8_t *device_capabilities_fru_inventory_device,
3706                                                                 uint8_t *device_capabilities_ipmb_event_receiver,
3707                                                                 uint8_t *device_capabilities_ipmb_event_generator,
3708                                                                 uint8_t *device_capabilities_bridge,
3709                                                                 uint8_t *device_capabilities_chassis_device)
3710 {
3711   fiid_obj_t obj_sdr_record = NULL;
3712   uint32_t acceptable_record_types;
3713   uint64_t val;
3714   int rv = -1;
3715 
3716   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD;
3717 
3718   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3719                                                  sdr_record,
3720                                                  sdr_record_len,
3721                                                  acceptable_record_types)))
3722     goto cleanup;
3723 
3724   if (device_slave_address)
3725     {
3726       if (FIID_OBJ_GET (obj_sdr_record,
3727                         "device_slave_address",
3728                         &val) < 0)
3729         {
3730           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3731           goto cleanup;
3732         }
3733       *device_slave_address = val;
3734     }
3735   if (channel_number)
3736     {
3737       if (FIID_OBJ_GET (obj_sdr_record,
3738                         "channel_number",
3739                         &val) < 0)
3740         {
3741           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3742           goto cleanup;
3743         }
3744       *channel_number = val;
3745     }
3746   if (global_initialization_event_message_generation)
3747     {
3748       if (FIID_OBJ_GET (obj_sdr_record,
3749                         "global_initialization.event_message_generation",
3750                         &val) < 0)
3751         {
3752           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3753           goto cleanup;
3754         }
3755       *global_initialization_event_message_generation = val;
3756     }
3757   if (global_initialization_log_initialization_agent_errors)
3758     {
3759       if (FIID_OBJ_GET (obj_sdr_record,
3760                         "global_initialization.log_initialization_agent_errors",
3761                         &val) < 0)
3762         {
3763           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3764           goto cleanup;
3765         }
3766       *global_initialization_log_initialization_agent_errors = val;
3767     }
3768   if (global_initialization_controller_logs_initialization_agent_errors)
3769     {
3770       if (FIID_OBJ_GET (obj_sdr_record,
3771                         "global_initialization.controller_logs_initialization_agent_errors",
3772                         &val) < 0)
3773         {
3774           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3775           goto cleanup;
3776         }
3777       *global_initialization_controller_logs_initialization_agent_errors = val;
3778     }
3779   if (power_state_notification_controller)
3780     {
3781       if (FIID_OBJ_GET (obj_sdr_record,
3782                         "power_state_notification.controller",
3783                         &val) < 0)
3784         {
3785           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3786           goto cleanup;
3787         }
3788       *power_state_notification_controller = val;
3789     }
3790   if (power_state_notification_acpi_device_power_state_notification)
3791     {
3792       if (FIID_OBJ_GET (obj_sdr_record,
3793                         "power_state_notification.acpi_device_power_state_notification",
3794                         &val) < 0)
3795         {
3796           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3797           goto cleanup;
3798         }
3799       *power_state_notification_acpi_device_power_state_notification = val;
3800     }
3801   if (power_state_notification_acpi_system_power_state_notification)
3802     {
3803       if (FIID_OBJ_GET (obj_sdr_record,
3804                         "power_state_notification.acpi_system_power_state_notification",
3805                         &val) < 0)
3806         {
3807           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3808           goto cleanup;
3809         }
3810       *power_state_notification_acpi_system_power_state_notification = val;
3811     }
3812   if (device_capabilities_sensor_device)
3813     {
3814       if (FIID_OBJ_GET (obj_sdr_record,
3815                         "device_capabilities.sensor_device",
3816                         &val) < 0)
3817         {
3818           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3819           goto cleanup;
3820         }
3821       *device_capabilities_sensor_device = val;
3822     }
3823   if (device_capabilities_sdr_repository_device)
3824     {
3825       if (FIID_OBJ_GET (obj_sdr_record,
3826                         "device_capabilities.sdr_repository_device",
3827                         &val) < 0)
3828         {
3829           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3830           goto cleanup;
3831         }
3832       *device_capabilities_sdr_repository_device = val;
3833     }
3834   if (device_capabilities_sel_device)
3835     {
3836       if (FIID_OBJ_GET (obj_sdr_record,
3837                         "device_capabilities.sel_device",
3838                         &val) < 0)
3839         {
3840           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3841           goto cleanup;
3842         }
3843       *device_capabilities_sel_device = val;
3844     }
3845   if (device_capabilities_fru_inventory_device)
3846     {
3847       if (FIID_OBJ_GET (obj_sdr_record,
3848                         "device_capabilities.fru_inventory_device",
3849                         &val) < 0)
3850         {
3851           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3852           goto cleanup;
3853         }
3854       *device_capabilities_fru_inventory_device = val;
3855     }
3856   if (device_capabilities_ipmb_event_receiver)
3857     {
3858       if (FIID_OBJ_GET (obj_sdr_record,
3859                         "device_capabilities.ipmb_event_receiver",
3860                         &val) < 0)
3861         {
3862           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3863           goto cleanup;
3864         }
3865       *device_capabilities_ipmb_event_receiver = val;
3866     }
3867   if (device_capabilities_ipmb_event_generator)
3868     {
3869       if (FIID_OBJ_GET (obj_sdr_record,
3870                         "device_capabilities.ipmb_event_generator",
3871                         &val) < 0)
3872         {
3873           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3874           goto cleanup;
3875         }
3876       *device_capabilities_ipmb_event_generator = val;
3877     }
3878   if (device_capabilities_bridge)
3879     {
3880       if (FIID_OBJ_GET (obj_sdr_record,
3881                         "device_capabilities.bridge",
3882                         &val) < 0)
3883         {
3884           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3885           goto cleanup;
3886         }
3887       *device_capabilities_bridge = val;
3888     }
3889   if (device_capabilities_chassis_device)
3890     {
3891       if (FIID_OBJ_GET (obj_sdr_record,
3892                         "device_capabilities.chassis_device",
3893                         &val) < 0)
3894         {
3895           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3896           goto cleanup;
3897         }
3898       *device_capabilities_chassis_device = val;
3899     }
3900 
3901   rv = 0;
3902   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3903  cleanup:
3904   fiid_obj_destroy (obj_sdr_record);
3905   return (rv);
3906 }
3907 
3908 int
ipmi_sdr_parse_manufacturer_id(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint32_t * manufacturer_id)3909 ipmi_sdr_parse_manufacturer_id (ipmi_sdr_ctx_t ctx,
3910                                 const void *sdr_record,
3911                                 unsigned int sdr_record_len,
3912                                 uint32_t *manufacturer_id)
3913 {
3914   fiid_obj_t obj_sdr_record = NULL;
3915   uint32_t acceptable_record_types;
3916   uint64_t val;
3917   int rv = -1;
3918 
3919   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_CONFIRMATION_RECORD;
3920   acceptable_record_types |= IPMI_SDR_PARSE_RECORD_TYPE_OEM_RECORD;
3921 
3922   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3923                                                  sdr_record,
3924                                                  sdr_record_len,
3925                                                  acceptable_record_types)))
3926     goto cleanup;
3927 
3928   if (manufacturer_id)
3929     {
3930       if (FIID_OBJ_GET (obj_sdr_record,
3931                         "manufacturer_id",
3932                         &val) < 0)
3933         {
3934           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3935           goto cleanup;
3936         }
3937       *manufacturer_id = val;
3938     }
3939 
3940   rv = 0;
3941   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3942  cleanup:
3943   fiid_obj_destroy (obj_sdr_record);
3944   return (rv);
3945 }
3946 
3947 int
ipmi_sdr_parse_product_id(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,uint16_t * product_id)3948 ipmi_sdr_parse_product_id (ipmi_sdr_ctx_t ctx,
3949                            const void *sdr_record,
3950                            unsigned int sdr_record_len,
3951                            uint16_t *product_id)
3952 {
3953   fiid_obj_t obj_sdr_record = NULL;
3954   uint32_t acceptable_record_types;
3955   uint64_t val;
3956   int rv = -1;
3957 
3958   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_MANAGEMENT_CONTROLLER_CONFIRMATION_RECORD;
3959 
3960   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
3961                                                  sdr_record,
3962                                                  sdr_record_len,
3963                                                  acceptable_record_types)))
3964     goto cleanup;
3965 
3966   if (product_id)
3967     {
3968       if (FIID_OBJ_GET (obj_sdr_record,
3969                         "product_id",
3970                         &val) < 0)
3971         {
3972           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
3973           goto cleanup;
3974         }
3975       *product_id = val;
3976     }
3977 
3978   rv = 0;
3979   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
3980  cleanup:
3981   fiid_obj_destroy (obj_sdr_record);
3982   return (rv);
3983 }
3984 
3985 int
ipmi_sdr_parse_oem_data(ipmi_sdr_ctx_t ctx,const void * sdr_record,unsigned int sdr_record_len,void * oem_data,unsigned int oem_data_len)3986 ipmi_sdr_parse_oem_data (ipmi_sdr_ctx_t ctx,
3987                          const void *sdr_record,
3988                          unsigned int sdr_record_len,
3989                          void *oem_data,
3990                          unsigned int oem_data_len)
3991 {
3992   fiid_obj_t obj_sdr_record = NULL;
3993   uint32_t acceptable_record_types;
3994   int len = 0;
3995   int rv = -1;
3996 
3997   acceptable_record_types = IPMI_SDR_PARSE_RECORD_TYPE_OEM_RECORD;
3998 
3999   if (!(obj_sdr_record = _sdr_record_get_common (ctx,
4000                                                  sdr_record,
4001                                                  sdr_record_len,
4002                                                  acceptable_record_types)))
4003     goto cleanup;
4004 
4005   if (oem_data && oem_data_len)
4006     {
4007       if ((len = fiid_obj_get_data (obj_sdr_record,
4008                                     "oem_data",
4009                                     oem_data,
4010                                     oem_data_len)) < 0)
4011         {
4012           SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record);
4013           goto cleanup;
4014         }
4015     }
4016 
4017   rv = len;
4018   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
4019  cleanup:
4020   fiid_obj_destroy (obj_sdr_record);
4021   return (rv);
4022 }
4023