1 /*
2  * mc.c
3  *
4  * MontaVista IPMI code for handling management controllers
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2002,2003 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #include <stdio.h>
35 #include <string.h>
36 #include <errno.h>
37 
38 #include <OpenIPMI/ipmiif.h>
39 #include <OpenIPMI/ipmi_sdr.h>
40 #include <OpenIPMI/ipmi_msgbits.h>
41 #include <OpenIPMI/ipmi_err.h>
42 #include <OpenIPMI/ipmi_user.h>
43 #include <OpenIPMI/ipmi_mc.h>
44 
45 #include <OpenIPMI/internal/locked_list.h>
46 #include <OpenIPMI/internal/opq.h>
47 #include <OpenIPMI/internal/ipmi_domain.h>
48 #include <OpenIPMI/internal/ipmi_mc.h>
49 #include <OpenIPMI/internal/ipmi_sel.h>
50 #include <OpenIPMI/internal/ipmi_oem.h>
51 #include <OpenIPMI/internal/ipmi_int.h>
52 
53 #define MAX_SEL_TIME_SET_RETRIES 10
54 
55 #undef DEBUG_INFO_TRACKING
56 
57 /* Timer structure for rereading the SEL. */
58 typedef struct mc_reread_sel_s
59 {
60     char                name[IPMI_MC_NAME_LEN+1];
61     int                 timer_running;
62     ipmi_lock_t         *lock;
63     int                 cancelled;
64     ipmi_mc_t           *mc;
65     ipmi_mcid_t         mc_id;
66     ipmi_sels_fetched_t handler;
67     void                *cb_data;
68     os_handler_t        *os_hnd;
69     os_hnd_timer_id_t   *sel_timer;
70 
71     int                 timer_should_run;
72     unsigned int        retries;
73     int                 sel_time_set;
74     int                 processing;
75 
76     ipmi_mc_ptr_cb sels_first_read_handler;
77     void           *sels_first_read_cb_data;
78 
79 #ifdef DEBUG_INFO_TRACKING
80 #define DIT_SIZE 100
81 #define DIT_LAST (DIT_SIZE-1)
82     struct {
83 	int            line;
84 	const char     *filename;
85 	const char     *function;
86     } last[DIT_SIZE];
87 #define DEBUG_INFO(info) (memcpy(info->last, info->last+1,	\
88 				 sizeof(info->last[0]) * (DIT_LAST)),	\
89 			  info->last[DIT_LAST].filename = __FILE__,	\
90 			  info->last[DIT_LAST].line = __LINE__,	\
91 			  info->last[DIT_LAST].function = __FUNCTION__)
92 #else
93 #define DEBUG_INFO(info)
94 #endif
95 } mc_reread_sel_t;
96 
97 
98 typedef struct mc_devid_data_s
99 {
100     uint8_t device_id;
101 
102     uint8_t device_revision;
103 
104     unsigned int provides_device_sdrs : 1;
105     unsigned int device_available : 1;
106 
107     unsigned int chassis_support : 1;
108     unsigned int bridge_support : 1;
109     unsigned int IPMB_event_generator_support : 1;
110     unsigned int IPMB_event_receiver_support : 1;
111     unsigned int FRU_inventory_support : 1;
112     unsigned int SEL_device_support : 1;
113     unsigned int SDR_repository_support : 1;
114     unsigned int sensor_device_support : 1;
115 
116     uint8_t major_fw_revision;
117     uint8_t minor_fw_revision;
118 
119     uint8_t major_version;
120     uint8_t minor_version;
121 
122     uint32_t manufacturer_id;
123     uint16_t product_id;
124 
125     uint8_t  aux_fw_revision[4];
126 } mc_devid_data_t;
127 
128 /*
129  * The MC follows a state machine for it's status to keep reporting of
130  * active/inactive/fully up sane.  It is driven by the following inputs:
131  *
132  * i_ipmi_mc_handle_new - function call from domain code when MC is detected
133  * i_ipmi_cleanup_mc - function call from domain code when MC removal is
134  *	detected
135  * put_done - When the i_ipmi_mc_put() calls cause the count to go to 0
136  * startup_get - When a startup operation starts
137  * startup_done - When a startup operation completes
138  *
139  * It has the following states:
140  *
141  * MC_INACTIVE - startup state
142  *  i_ipmi_mc_handle_new
143  *	state = MC_INACTIVE_PEND_STARTUP
144  *  i_ipmi_cleanup_mc
145  *	nil
146  *  put_done
147  *	nil
148  *  startup_get
149  *	nil
150  *  startup_done
151  *	nil
152  *
153  * MC_INACTIVE_PEND_STARTUP - A startup has been requested.  Wait for the
154  * mc to be put_done and start up the MC.
155  *  i_ipmi_mc_handle_new
156  *	nil
157  *  i_ipmi_cleanup_mc
158  *	state = MC_INACTIVE
159  *  put_done
160  *	state = MC_ACTIVE_IN_STARTUP
161  *	startup MC
162  *      startup_count = 1
163  *      startup_called = False
164  *      active = 1
165  *      call active handlers
166  *  startup_get
167  *	nil
168  *  startup_done
169  *	nil
170  *
171  * MC_ACTIVE_IN_STARTUP - MC is startup up
172  *  i_ipmi_mc_handle_new
173  *	nil
174  *  i_ipmi_cleanup_mc
175  *	state = MC_ACTIVE_PENDING_CLEANUP
176  *  put_done
177  *	nil
178  *  startup_get
179  *	startup_count++
180  *  startup_done
181  *	startup_count--
182  *      if (startup_count == 0 and NOT startup_called)
183  *        startup_called = True
184  *	  state = MC_ACTIVE_PENDING_FULLY_UP
185  *
186  * MC_ACTIVE_PEND_FULLY_UP - We have gone fully up, waiting for
187  * put_done to go to active and report fully up
188  *  i_ipmi_mc_handle_new
189  *	nil
190  *  i_ipmi_cleanup_mc
191  *	state = MC_ACTIVE_PENDING_CLEANUP
192  *  put_done
193  *	state = MC_ACTIVE
194  *      call fully up handlers
195  *  startup_get
196  *	nil
197  *  startup_done
198  *	nil
199  *
200  * MC_ACTIVE - MC is fully operational
201  *  i_ipmi_mc_handle_new
202  *	nil
203  *  i_ipmi_cleanup_mc
204  *	state = MC_ACTIVE_PENDING_CLEANUP
205  *  put_done
206  *	nil
207  *  startup_get
208  *	nil
209  *  startup_done
210  *	nil
211  *
212  * MC_ACTIVE_PEND_CLEANUP - A cleanup has been requested, pending for
213  * the startup_count to go to zero in a put_done.
214  *  i_ipmi_mc_handle_new
215  *	state = MC_ACTIVE_PEND_CLEANUP_PEND_STARTUP
216  *  i_ipmi_cleanup_mc
217  *	nil
218  *  put_done
219  *	if (startup_count == 0)
220  *        state = MC_INACTIVE
221  *	  active = 0
222  *	  cleanup MC
223  *        call active handlers
224  *  startup_get
225  *	startup_count++
226  *  startup_done
227  *	startup_count--
228  *
229  * MC_ACTIVE_PEND_CLEANUP_PEND_STARTUP - When we were pending close, an
230  * i_ipmi_mc_handle_new event came in.  We need to finish cleaning up
231  * before we restart the MC.
232  *  i_ipmi_mc_handle_new
233  *	nil
234  *  i_ipmi_cleanup_mc
235  *	state = MC_ACTIVE_PENDING_CLEANUP
236  *  put_done
237  *	if (startup_count == 0)
238  *        state = MC_INACTIVE
239  *	  active = 0
240  *	  cleanup MC
241  *        call active handlers
242  *        state = MC_ACTIVE_IN_STARTUP
243  *	  active = 0
244  *	  startup MC
245  *        startup_count = True
246  *        startup_called = False
247  *        active = 1
248  *        call active handlers
249  *  startup_get
250  *	startup_count++
251  *  startup_done
252  *	startup_count--
253  *
254  * A few notes:
255  *
256  * We don't do anything in the startup_get and startup_put operations
257  * because the caller must be holding an mc and we want to wait until
258  * the put operation to do anything.
259  *
260  * Same with the handle_new and cleanup calls
261  *
262  * For the user, you will never get a fully_up call while the MC is
263  * inactive.
264  */
265 typedef enum {
266     MC_INACTIVE,
267     MC_INACTIVE_PEND_STARTUP,
268     MC_ACTIVE_IN_STARTUP,
269     MC_ACTIVE_PEND_FULLY_UP,
270     MC_ACTIVE,
271     MC_ACTIVE_PEND_CLEANUP,
272     MC_ACTIVE_PEND_CLEANUP_PEND_STARTUP
273 } mc_state_e;
274 
275 struct ipmi_mc_s
276 {
277     unsigned int usecount;
278     ipmi_lock_t *lock;
279 
280     int           in_destroy;
281 
282     ipmi_domain_t *domain;
283     long          seq;
284     ipmi_addr_t   addr;
285     int           addr_len;
286 
287     mc_state_e state;
288 
289     /* How many startup items are pending? */
290     unsigned int startup_count;
291     int startup_reported;
292 
293     /* If we have any external users that do not have direct
294        references, we increment the usercount.  This is primarily the
295        internal uses in the active_handlers list, but we cannot use
296        that list being empty because it also may have external
297        users. */
298     int usercount;
299 
300     /* If the MC is known to be good in the system, then active is
301        true.  If active is false, that means that there are sensors
302        that refer to this MC, but the MC is not currently in the
303        system. */
304     int active;
305 
306     /* Used to generate unique numbers for the MC. */
307     unsigned int uniq_num;
308 
309     /* The device SDRs on the MC. */
310     ipmi_sdr_info_t *sdrs;
311 
312     /* The sensors that came from the device SDR on this MC. */
313     ipmi_sensor_t **sensors_in_my_sdr;
314     unsigned int  sensors_in_my_sdr_count;
315 
316     /* The entities that came from the device SDR on this MC are
317        somehow stored in this data structure. */
318     void *entities_in_my_sdr;
319 
320     /* Sensors that this MC owns (you message this MC to talk to this
321        sensor, and events report the MC as the owner. */
322     ipmi_sensor_info_t  *sensors;
323 
324     ipmi_control_info_t *controls;
325 
326     unsigned int in_domain_list : 1; /* Tells if we are in the list of
327 					our domain yet. */
328 
329     /* The system event log, for querying and storing events. */
330     ipmi_sel_info_t *sel;
331 
332     /* The handler to call for add/delete event operations.  This is NULL
333        normally and is only used if the MC has a special delete event
334        handler. */
335     ipmi_mc_del_event_cb sel_del_event_handler;
336     ipmi_mc_add_event_cb sel_add_event_handler;
337     ipmi_mc_del_event_cb sel_clear_handler;
338 
339     /* Timer for rescanning the sel periodically. */
340     mc_reread_sel_t   *sel_timer_info;
341     unsigned int      sel_scan_interval; /* seconds between SEL scans */
342 
343     /* Is the global events enable for the MC enabled? */
344     int events_enabled;
345 
346     /* The SEL time when the connection first came up.  Only used at
347        startup, after the SEL has been read the first time this will
348        be set to zero. */
349     ipmi_time_t startup_SEL_time;
350 
351     /* The MC's GUID. */
352     unsigned int  guid_set : 1;
353     unsigned char guid[16];
354 
355     void *oem_data;
356 
357     ipmi_mc_oem_fixup_sdrs_cb fixup_sdrs_handler;
358     void                      *fixup_sdrs_cb_data;
359 
360     ipmi_mc_oem_new_sensor_cb new_sensor_handler;
361     void                      *new_sensor_cb_data;
362 
363     ipmi_oem_event_handler_cb oem_event_handler;
364     void                      *oem_event_cb_data;
365 
366     ipmi_oem_event_handler_cb sel_oem_event_handler;
367     void                      *sel_oem_event_cb_data;
368 
369     ipmi_mc_ptr_cb sdrs_first_read_handler;
370     void           *sdrs_first_read_cb_data;
371 
372     /* Call these when the MC is destroyed. */
373     locked_list_t *removed_handlers;
374 
375     /* Call these when the MC changes from active to inactive. */
376     locked_list_t *active_handlers, *active_handlers_cl;
377 
378     /* Called after going active when the MC is fully up. */
379     locked_list_t *fully_up_handlers, *fully_up_handlers_cl;
380 
381     /* Set if we are treating main SDRs like device SDRs. */
382     int treat_main_as_device_sdrs;
383 
384     /* The rest is the actual data from the get device id and SDRs.
385        There's the normal version, the pending version, and the
386        version.  The real version is the one from the get device id
387        response, and normal version may have been adjusted by the OEM
388        code.  The pending version is used to hold the data until the
389        usecount goes to 0; we don't change the user data until no one
390        else is using it. */
391 
392     mc_devid_data_t devid;
393     mc_devid_data_t real_devid;
394     mc_devid_data_t pending_devid;
395     int pending_devid_data;
396     int pending_new_mc;
397 
398     /* Name used for reporting.  We add a ' ' onto the end, thus
399        the +1. */
400     char name[IPMI_MC_NAME_LEN+1];
401 };
402 
403 /* Can the MC do normal operations like check SDRs, fetch the SEL,
404    etc?  Must be called with the MC lock held. */
405 #define mc_op_ready(mc) \
406     (((mc)->state == MC_ACTIVE_IN_STARTUP) \
407      || ((mc)->state == MC_ACTIVE_PEND_FULLY_UP) \
408      || ((mc)->state == MC_ACTIVE))
409 
410 static void mc_sel_new_event_handler(ipmi_sel_info_t *sel,
411 				     ipmi_mc_t       *mc,
412 				     ipmi_event_t    *event,
413 				     void            *cb_data);
414 
415 static void sels_start_timer(mc_reread_sel_t *info);
416 static void start_sel_time_set(ipmi_mc_t *mc, mc_reread_sel_t *info);
417 
418 static void call_active_handlers(ipmi_mc_t *mc);
419 static void call_fully_up_handlers(ipmi_mc_t *mc);
420 
421 /***********************************************************************
422  *
423  * Routines for creating and destructing MCs.
424  *
425  **********************************************************************/
426 
427 static void
mc_set_name(ipmi_mc_t * mc)428 mc_set_name(ipmi_mc_t *mc)
429 {
430     int         length;
431     ipmi_mcid_t id = ipmi_mc_convert_to_id(mc);
432 
433     ipmi_lock(mc->lock);
434     length = ipmi_domain_get_name(mc->domain, mc->name, sizeof(mc->name)-3);
435     mc->name[length] = '(';
436     length++;
437     length += snprintf(mc->name+length, IPMI_MC_NAME_LEN-length-3, "%x.%x",
438 		       id.channel, id.mc_num);
439     mc->name[length] = ')';
440     length++;
441     mc->name[length] = ' ';
442     length++;
443     mc->name[length] = '\0';
444     length++;
445     ipmi_unlock(mc->lock);
446 }
447 
448 int
ipmi_mc_get_name(ipmi_mc_t * mc,char * name,int length)449 ipmi_mc_get_name(ipmi_mc_t *mc, char *name, int length)
450 {
451     int  slen;
452 
453     if (length <= 0)
454 	return 0;
455 
456     /* Never changes, no lock needed. */
457     slen = strlen(mc->name);
458     if (slen == 0) {
459 	if (name)
460 	    *name = '\0';
461 	goto out;
462     }
463 
464     slen -= 1; /* Remove the trailing ' ' */
465     if (slen >= length)
466 	slen = length - 1;
467 
468     if (name) {
469 	memcpy(name, mc->name, slen);
470 	name[slen] = '\0';
471     }
472  out:
473     return slen;
474 }
475 
476 const char *
i_ipmi_mc_name(const ipmi_mc_t * mc)477 i_ipmi_mc_name(const ipmi_mc_t *mc)
478 {
479     return mc->name;
480 }
481 
482 static os_handler_t *
mc_get_os_hnd(ipmi_mc_t * mc)483 mc_get_os_hnd(ipmi_mc_t *mc)
484 {
485     ipmi_domain_t *domain = mc->domain;
486     return ipmi_domain_get_os_hnd(domain);
487 }
488 
489 typedef struct fully_up_cl_info_s
490 {
491     ipmi_mc_ptr_cb handler;
492     void           *handler_data;
493 } fully_up_cl_info_t;
494 
495 static int
iterate_fully_up_cl(void * cb_data,void * item1,void * item2)496 iterate_fully_up_cl(void *cb_data, void *item1, void *item2)
497 {
498     fully_up_cl_info_t     *info = cb_data;
499     ipmi_mc_fully_up_cl_cb handler = item1;
500 
501     handler(info->handler, info->handler_data, item2);
502     return LOCKED_LIST_ITER_CONTINUE;
503 }
504 
505 static int
fully_up_cleanup(void * cb_data,void * item1,void * item2)506 fully_up_cleanup(void *cb_data, void *item1, void *item2)
507 {
508     ipmi_mc_t *mc = cb_data;
509     fully_up_cl_info_t info;
510 
511     info.handler = item1;
512     info.handler_data = item2;
513     locked_list_iterate(mc->fully_up_handlers_cl, iterate_fully_up_cl, &info);
514     return LOCKED_LIST_ITER_CONTINUE;
515 }
516 
517 typedef struct active_cl_info_s
518 {
519     ipmi_mc_active_cb handler;
520     void              *handler_data;
521 } active_cl_info_t;
522 
523 static int
iterate_active_cl(void * cb_data,void * item1,void * item2)524 iterate_active_cl(void *cb_data, void *item1, void *item2)
525 {
526     active_cl_info_t     *info = cb_data;
527     ipmi_mc_active_cl_cb handler = item1;
528 
529     handler(info->handler, info->handler_data, item2);
530     return LOCKED_LIST_ITER_CONTINUE;
531 }
532 
533 static int
active_cleanup(void * cb_data,void * item1,void * item2)534 active_cleanup(void *cb_data, void *item1, void *item2)
535 {
536     ipmi_mc_t *mc = cb_data;
537     active_cl_info_t info;
538 
539     info.handler = item1;
540     info.handler_data = item2;
541     locked_list_iterate(mc->active_handlers_cl, iterate_active_cl, &info);
542     return LOCKED_LIST_ITER_CONTINUE;
543 }
544 
545 static int
check_mc_destroy(ipmi_mc_t * mc)546 check_mc_destroy(ipmi_mc_t *mc)
547 {
548     ipmi_domain_t *domain = mc->domain;
549     os_handler_t  *os_hnd = mc_get_os_hnd(mc);
550     int           rv;
551 
552     if ((mc->state == MC_INACTIVE)
553 	&& (ipmi_controls_get_count(mc->controls) == 0)
554 	&& (ipmi_sensors_get_count(mc->sensors) == 0)
555 	&& (mc->usercount == 0))
556     {
557 	mc->in_destroy = 1;
558 	ipmi_unlock(mc->lock);
559 
560 	/* There are no sensors associated with this MC, so it's safe
561            to delete it.  If there are sensors that still reference
562            this MC (such as from another MC's SDR repository, or the
563            main SDR repository) we have to leave it inactive but not
564            delete it.  The active handlers come from MCDLR and FRUDLR
565            SDRs that monitor the MC. */
566 	i_ipmi_remove_mc_from_domain(domain, mc);
567 
568 	if (mc->sel_timer_info) {
569 	    if (mc->sel_timer_info->lock) {
570 		ipmi_lock(mc->sel_timer_info->lock);
571 		if (mc->sel_timer_info->timer_running) {
572 		    mc->sel_timer_info->cancelled = 1;
573 		    rv = os_hnd->stop_timer(os_hnd,
574 					    mc->sel_timer_info->sel_timer);
575 		    ipmi_unlock(mc->sel_timer_info->lock);
576 		    if (!rv) {
577 			/* If we can stop the timer, free it and it's info.
578 			   If we can't stop the timer, that means that the
579 			   code is currently in the timer handler, so we let
580 			   the "cancelled" value do this for us. */
581 			ipmi_destroy_lock(mc->sel_timer_info->lock);
582 			os_hnd->free_timer(os_hnd,
583 					   mc->sel_timer_info->sel_timer);
584 			ipmi_mem_free(mc->sel_timer_info);
585 		    }
586 		} else {
587 		    ipmi_unlock(mc->sel_timer_info->lock);
588 		    ipmi_destroy_lock(mc->sel_timer_info->lock);
589 		    os_hnd->free_timer(os_hnd, mc->sel_timer_info->sel_timer);
590 		    ipmi_mem_free(mc->sel_timer_info);
591 		}
592 	    } else {
593 		/* Timer wasn't completely created. */
594 		if (mc->sel_timer_info->sel_timer)
595 		    os_hnd->free_timer(os_hnd, mc->sel_timer_info->sel_timer);
596 		ipmi_mem_free(mc->sel_timer_info);
597 	    }
598 	}
599 
600 	if (mc->removed_handlers)
601 	    locked_list_destroy(mc->removed_handlers);
602     	if (mc->active_handlers) {
603 	    locked_list_iterate(mc->active_handlers, active_cleanup, mc);
604 	    locked_list_destroy(mc->active_handlers);
605 	}
606     	if (mc->active_handlers_cl)
607 	    locked_list_destroy(mc->active_handlers_cl);
608     	if (mc->fully_up_handlers) {
609 	    locked_list_iterate(mc->fully_up_handlers, fully_up_cleanup, mc);
610 	    locked_list_destroy(mc->fully_up_handlers);
611 	}
612     	if (mc->fully_up_handlers_cl)
613 	    locked_list_destroy(mc->fully_up_handlers_cl);
614 	if (mc->sensors)
615 	    ipmi_sensors_destroy(mc->sensors);
616 	if (mc->controls)
617 	    ipmi_controls_destroy(mc->controls);
618 	if (mc->sdrs)
619 	    ipmi_sdr_info_destroy(mc->sdrs, NULL, NULL);
620 	if (mc->sel)
621 	    ipmi_sel_destroy(mc->sel, NULL, NULL);
622 	if (mc->lock)
623 	    ipmi_destroy_lock(mc->lock);
624 
625 	ipmi_mem_free(mc);
626 	return 1;
627     }
628     return 0;
629 }
630 
631 int
i_ipmi_create_mc(ipmi_domain_t * domain,ipmi_addr_t * addr,unsigned int addr_len,ipmi_mc_t ** new_mc)632 i_ipmi_create_mc(ipmi_domain_t *domain,
633 		ipmi_addr_t   *addr,
634 		unsigned int  addr_len,
635 		ipmi_mc_t     **new_mc)
636 {
637     ipmi_mc_t    *mc;
638     int          rv = 0;
639     os_handler_t *os_hnd = ipmi_domain_get_os_hnd(domain);
640 
641     if (addr_len > sizeof(ipmi_addr_t))
642 	return EINVAL;
643 
644     mc = ipmi_mem_alloc(sizeof(*mc));
645     if (!mc)
646 	return ENOMEM;
647     memset(mc, 0, sizeof(*mc));
648 
649     mc->state = MC_INACTIVE;
650 
651     mc->usecount = 1; /* Require a release */
652 
653     mc->domain = domain;
654 
655     mc->seq = ipmi_get_seq();
656 
657     mc->events_enabled = 1;
658 
659     mc->active = 0; /* Start assuming inactive. */
660 
661     mc->sensors = NULL;
662     mc->sensors_in_my_sdr = NULL;
663     mc->sensors_in_my_sdr_count = 0;
664     mc->entities_in_my_sdr = NULL;
665     mc->controls = NULL;
666     mc->new_sensor_handler = NULL;
667     rv = ipmi_create_lock(domain, &mc->lock);
668     if (rv)
669 	goto out_err;
670     mc->removed_handlers = locked_list_alloc(os_hnd);
671     if (!mc->removed_handlers) {
672 	rv = ENOMEM;
673 	goto out_err;
674     }
675 
676     mc->active_handlers_cl = locked_list_alloc(os_hnd);
677     if (!mc->active_handlers_cl) {
678 	rv = ENOMEM;
679 	goto out_err;
680     }
681 
682     mc->active_handlers = locked_list_alloc(os_hnd);
683     if (!mc->active_handlers) {
684 	rv = ENOMEM;
685 	goto out_err;
686     }
687 
688     mc->fully_up_handlers_cl = locked_list_alloc(os_hnd);
689     if (!mc->fully_up_handlers_cl) {
690 	rv = ENOMEM;
691 	goto out_err;
692     }
693     mc->fully_up_handlers = locked_list_alloc(os_hnd);
694     if (!mc->fully_up_handlers) {
695 	rv = ENOMEM;
696 	goto out_err;
697     }
698 
699     mc->sel = NULL;
700     mc->sel_scan_interval = ipmi_domain_get_sel_rescan_time(domain);
701 
702     memcpy(&(mc->addr), addr, addr_len);
703     mc->addr_len = addr_len;
704     mc->sdrs = NULL;
705 
706     rv = ipmi_sensors_alloc(mc, &(mc->sensors));
707     if (rv)
708 	goto out_err;
709 
710     rv = ipmi_controls_alloc(mc, &(mc->controls));
711     if (rv)
712 	goto out_err;
713 
714     mc_set_name(mc);
715 
716     rv = ipmi_sel_alloc(mc, 0, &(mc->sel));
717     if (rv)
718 	goto out_err;
719 
720     mc->sel_timer_info = ipmi_mem_alloc(sizeof(*mc->sel_timer_info));
721     if (!mc->sel_timer_info) {
722 	rv = ENOMEM;
723 	goto out_err;
724     }
725     memset(mc->sel_timer_info, 0, sizeof(*mc->sel_timer_info));
726     strncpy(mc->sel_timer_info->name, mc->name,
727 	    sizeof(mc->sel_timer_info->name) - 1);
728     mc->sel_timer_info->mc_id = ipmi_mc_convert_to_id(mc);
729     mc->sel_timer_info->mc = mc;
730     mc->sel_timer_info->os_hnd = os_hnd;
731     rv = os_hnd->alloc_timer(os_hnd, &mc->sel_timer_info->sel_timer);
732     if (rv)
733 	goto out_err;
734 
735     rv = ipmi_create_lock(domain, &mc->sel_timer_info->lock);
736     if (rv)
737 	goto out_err;
738 
739     rv = ipmi_sdr_info_alloc(domain, mc, 0, 1, &(mc->sdrs));
740     if (rv)
741 	goto out_err;
742 
743     /* When we get new logs, handle them. */
744     ipmi_sel_set_new_event_handler(mc->sel,
745 				   mc_sel_new_event_handler,
746 				   domain);
747 
748  out_err:
749     if (rv)
750 	check_mc_destroy(mc);
751     else
752 	*new_mc = mc;
753 
754     return rv;
755 }
756 
757 static int
call_removed_handler(void * cb_data,void * item1,void * item2)758 call_removed_handler(void *cb_data, void *item1, void *item2)
759 {
760     ipmi_mc_oem_removed_cb handler = item1;
761     ipmi_mc_t              *mc = cb_data;
762 
763     ipmi_mc_remove_oem_removed_handler(mc, handler, item2);
764     handler(mc->domain, mc, item2);
765     return LOCKED_LIST_ITER_CONTINUE;
766 }
767 
768 /* Must be called with the mc lock held. */
769 static void
mc_stop_timer(ipmi_mc_t * mc)770 mc_stop_timer(ipmi_mc_t *mc)
771 {
772     os_handler_t *os_hnd = mc_get_os_hnd(mc);
773     int          rv;
774 
775     /* Make sure the timer stops. */
776     ipmi_lock(mc->sel_timer_info->lock);
777     mc->sel_timer_info->timer_should_run = 0;
778     if (mc->sel_timer_info->timer_running) {
779 	rv = os_hnd->stop_timer(os_hnd, mc->sel_timer_info->sel_timer);
780 	if (!rv) {
781 	    mc->sel_timer_info->timer_running = 0;
782 	    mc->sel_timer_info->processing = 0;
783 	}
784     }
785     if ((mc->startup_count > 0) && !mc->sel_timer_info->processing)
786 	/* Hack: If we are processing, we will fail the processing or
787 	   it will complete later and finish.  If we were not
788 	   processing, then we were just waiting on the timer that was
789 	   just cancelled.  We decrement if we were waiting on the
790 	   timer. */
791 	mc->startup_count--;
792     ipmi_unlock(mc->sel_timer_info->lock);
793 }
794 
795 static void
mc_cleanup(ipmi_mc_t * mc)796 mc_cleanup(ipmi_mc_t *mc)
797 {
798     unsigned int  i;
799     ipmi_domain_t *domain = mc->domain;
800 
801     /* Call the OEM handlers for removal, if it has been registered. */
802     locked_list_iterate(mc->removed_handlers, call_removed_handler, mc);
803 
804     /* First the device SDR sensors, since they can be there for any
805        MC. */
806     if (mc->sensors_in_my_sdr) {
807 	for (i=0; i<mc->sensors_in_my_sdr_count; i++) {
808 	    ipmi_sensor_t *sensor;
809 	    i_ipmi_domain_entity_lock(domain);
810 	    sensor = mc->sensors_in_my_sdr[i];
811 	    if (sensor) {
812 		ipmi_entity_t *entity = ipmi_sensor_get_entity(sensor);
813 		i_ipmi_entity_get(entity);
814 		i_ipmi_sensor_get(sensor);
815 		i_ipmi_domain_entity_unlock(domain);
816 		ipmi_sensor_destroy(mc->sensors_in_my_sdr[i]);
817 		i_ipmi_sensor_put(sensor);
818 		i_ipmi_entity_put(entity);
819 	    } else {
820 		i_ipmi_domain_entity_unlock(domain);
821 	    }
822 	}
823 	ipmi_mem_free(mc->sensors_in_my_sdr);
824 	mc->sensors_in_my_sdr = NULL;
825     }
826 
827     if (mc->entities_in_my_sdr) {
828 	ipmi_sdr_entity_destroy(mc->entities_in_my_sdr);
829 	mc->entities_in_my_sdr = NULL;
830     }
831 
832     if (mc->sdrs)
833 	ipmi_sdr_clean_out_sdrs(mc->sdrs);
834 }
835 
836 /***********************************************************************
837  *
838  * Reset routines for MCs.
839  *
840  **********************************************************************/
841 
842 typedef struct mc_reset_info_s
843 {
844     ipmi_mc_done_cb done;
845     void            *cb_data;
846 } mc_reset_info_t;
847 
848 static void
mc_reset_done(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)849 mc_reset_done(ipmi_mc_t  *mc,
850 	      ipmi_msg_t *rsp,
851 	      void       *rsp_data)
852 {
853     int             err = 0;
854     mc_reset_info_t *info = rsp_data;
855 
856     if (rsp->data[0] != 0)
857 	err = IPMI_IPMI_ERR_VAL(rsp->data[0]);
858 
859     if (info->done)
860 	info->done(mc, err, info->cb_data);
861 
862     ipmi_mem_free(info);
863 }
864 
865 int
ipmi_mc_reset(ipmi_mc_t * mc,int reset_type,ipmi_mc_done_cb done,void * cb_data)866 ipmi_mc_reset(ipmi_mc_t       *mc,
867 	      int             reset_type,
868 	      ipmi_mc_done_cb done,
869 	      void            *cb_data)
870 {
871     int             rv;
872     ipmi_msg_t      msg;
873     mc_reset_info_t *info;
874 
875     CHECK_MC_LOCK(mc);
876 
877     if (reset_type == IPMI_MC_RESET_COLD)
878 	msg.cmd = IPMI_COLD_RESET_CMD;
879     else if (reset_type == IPMI_MC_RESET_WARM)
880 	msg.cmd = IPMI_WARM_RESET_CMD;
881     else
882 	return EINVAL;
883 
884     info = ipmi_mem_alloc(sizeof(*info));
885     if (!info)
886 	return ENOMEM;
887     info->done = done;
888     info->cb_data = cb_data;
889 
890     msg.netfn = IPMI_APP_NETFN;
891     msg.data = NULL;
892     msg.data_len = 0;
893     rv = ipmi_mc_send_command(mc, 0, &msg, mc_reset_done, info);
894     if (rv)
895 	ipmi_mem_free(info);
896 
897     return rv;
898 }
899 
900 /***********************************************************************
901  *
902  * Event handling.
903  *
904  **********************************************************************/
905 
906 /* Got a new event in the system event log that we didn't have before. */
907 static void
mc_sel_new_event_handler(ipmi_sel_info_t * sel,ipmi_mc_t * mc,ipmi_event_t * event,void * cb_data)908 mc_sel_new_event_handler(ipmi_sel_info_t *sel,
909 			 ipmi_mc_t       *mc,
910 			 ipmi_event_t    *event,
911 			 void            *cb_data)
912 {
913     i_ipmi_domain_system_event_handler(cb_data, mc, event);
914 }
915 
916 int
i_ipmi_mc_check_oem_event_handler(ipmi_mc_t * mc,ipmi_event_t * event)917 i_ipmi_mc_check_oem_event_handler(ipmi_mc_t *mc, ipmi_event_t *event)
918 {
919     if (mc->oem_event_handler)
920 	return (mc->oem_event_handler(mc, event, mc->oem_event_cb_data));
921     else
922 	return 0;
923 }
924 
925 int
i_ipmi_mc_check_sel_oem_event_handler(ipmi_mc_t * mc,ipmi_event_t * event)926 i_ipmi_mc_check_sel_oem_event_handler(ipmi_mc_t *mc, ipmi_event_t *event)
927 {
928     if (mc->sel_oem_event_handler)
929 	return (mc->sel_oem_event_handler(mc, event,
930 					  mc->sel_oem_event_cb_data));
931     else
932 	return 0;
933 }
934 
935 
936 /***********************************************************************
937  *
938  * SEL handling.
939  *
940  **********************************************************************/
941 
942 int
i_ipmi_mc_sel_event_add(ipmi_mc_t * mc,ipmi_event_t * event)943 i_ipmi_mc_sel_event_add(ipmi_mc_t *mc, ipmi_event_t *event)
944 {
945     return ipmi_sel_event_add(mc->sel, event);
946 }
947 
948 ipmi_time_t
ipmi_mc_get_startup_SEL_time(ipmi_mc_t * mc)949 ipmi_mc_get_startup_SEL_time(ipmi_mc_t *mc)
950 {
951     return mc->startup_SEL_time;
952 }
953 
954 void
ipmi_mc_set_del_event_handler(ipmi_mc_t * mc,ipmi_mc_del_event_cb handler)955 ipmi_mc_set_del_event_handler(ipmi_mc_t            *mc,
956 			      ipmi_mc_del_event_cb handler)
957 {
958     mc->sel_del_event_handler = handler;
959 }
960 
961 void
ipmi_mc_set_add_event_handler(ipmi_mc_t * mc,ipmi_mc_add_event_cb handler)962 ipmi_mc_set_add_event_handler(ipmi_mc_t            *mc,
963 			      ipmi_mc_add_event_cb handler)
964 {
965     mc->sel_add_event_handler = handler;
966 }
967 
968 void
ipmi_mc_set_sel_clear_handler(ipmi_mc_t * mc,ipmi_mc_del_event_cb handler)969 ipmi_mc_set_sel_clear_handler(ipmi_mc_t            *mc,
970 			      ipmi_mc_del_event_cb handler)
971 {
972     mc->sel_clear_handler = handler;
973 }
974 
975 void
ipmi_mc_set_sel_rescan_time(ipmi_mc_t * mc,unsigned int seconds)976 ipmi_mc_set_sel_rescan_time(ipmi_mc_t *mc, unsigned int seconds)
977 {
978     unsigned int old_time;
979     CHECK_MC_LOCK(mc);
980 
981     if (mc->sel_scan_interval == seconds)
982 	return;
983 
984     old_time = mc->sel_scan_interval;
985 
986     mc->sel_scan_interval = seconds;
987     if (old_time == 0) {
988 	/* The old time was zero, so we must restart the timer. */
989 	ipmi_lock(mc->sel_timer_info->lock);
990 	sels_start_timer(mc->sel_timer_info);
991 	ipmi_unlock(mc->sel_timer_info->lock);
992     }
993 }
994 
995 unsigned int
ipmi_mc_get_sel_rescan_time(ipmi_mc_t * mc)996 ipmi_mc_get_sel_rescan_time(ipmi_mc_t *mc)
997 {
998     CHECK_MC_LOCK(mc);
999 
1000     return mc->sel_scan_interval;
1001 }
1002 
1003 typedef struct sel_op_done_info_s
1004 {
1005     ipmi_mc_t       *mc;
1006     ipmi_mc_done_cb done;
1007     void            *cb_data;
1008 } sel_op_done_info_t;
1009 
1010 static void
sel_op_done(ipmi_sel_info_t * sel,void * cb_data,int err)1011 sel_op_done(ipmi_sel_info_t *sel,
1012 	    void            *cb_data,
1013 	    int             err)
1014 {
1015     sel_op_done_info_t *info = cb_data;
1016 
1017     /* No need to refcount, the domain/mc should already be locked. */
1018     if (info->done)
1019         info->done(info->mc, err, info->cb_data);
1020     ipmi_mem_free(info);
1021 }
1022 
1023 int
ipmi_mc_del_event(ipmi_mc_t * mc,ipmi_event_t * event,ipmi_mc_del_event_done_cb handler,void * cb_data)1024 ipmi_mc_del_event(ipmi_mc_t                 *mc,
1025 		  ipmi_event_t              *event,
1026 		  ipmi_mc_del_event_done_cb handler,
1027 		  void                      *cb_data)
1028 {
1029     sel_op_done_info_t *sel_info;
1030     int                rv;
1031 
1032     if (!mc->devid.SEL_device_support)
1033 	return EINVAL;
1034 
1035     /* If we have an OEM handler, call it instead. */
1036     if (mc->sel_del_event_handler) {
1037 	rv = mc->sel_del_event_handler(mc, event, handler, cb_data);
1038 	return rv;
1039     }
1040 
1041     sel_info = ipmi_mem_alloc(sizeof(*sel_info));
1042     if (!sel_info)
1043 	return ENOMEM;
1044 
1045     sel_info->mc = mc;
1046     sel_info->done = handler;
1047     sel_info->cb_data = cb_data;
1048 
1049     rv = ipmi_sel_del_event(mc->sel, event, sel_op_done, sel_info);
1050     if (rv)
1051 	ipmi_mem_free(sel_info);
1052 
1053     return rv;
1054 }
1055 
1056 int
ipmi_mc_sel_clear(ipmi_mc_t * mc,ipmi_event_t * last_event,ipmi_mc_del_event_done_cb handler,void * cb_data)1057 ipmi_mc_sel_clear(ipmi_mc_t                 *mc,
1058 		  ipmi_event_t              *last_event,
1059 		  ipmi_mc_del_event_done_cb handler,
1060 		  void                      *cb_data)
1061 {
1062     sel_op_done_info_t *sel_info;
1063     int                rv;
1064 
1065     if (!mc->devid.SEL_device_support)
1066 	return EINVAL;
1067 
1068     /* If we have an OEM handler, call it instead. */
1069     if (mc->sel_clear_handler) {
1070 	rv = mc->sel_clear_handler(mc, last_event, handler, cb_data);
1071 	return rv;
1072     }
1073 
1074     sel_info = ipmi_mem_alloc(sizeof(*sel_info));
1075     if (!sel_info)
1076 	return ENOMEM;
1077 
1078     sel_info->mc = mc;
1079     sel_info->done = handler;
1080     sel_info->cb_data = cb_data;
1081 
1082     rv = ipmi_sel_clear(mc->sel, last_event, sel_op_done, sel_info);
1083     if (rv)
1084 	ipmi_mem_free(sel_info);
1085 
1086     return rv;
1087 }
1088 
1089 typedef struct sel_add_op_done_info_s
1090 {
1091     ipmi_mc_t                 *mc;
1092     ipmi_mc_add_event_done_cb done;
1093     void                      *cb_data;
1094 } sel_add_op_done_info_t;
1095 
sel_add_op_done(ipmi_sel_info_t * sel,void * cb_data,int err,unsigned int record_id)1096 static void sel_add_op_done(ipmi_sel_info_t *sel,
1097 			    void            *cb_data,
1098 			    int             err,
1099 			    unsigned int    record_id)
1100 {
1101     sel_add_op_done_info_t *info = cb_data;
1102 
1103     /* No need to lock, the domain/mc should already be locked. */
1104     if (info->done)
1105         info->done(info->mc, record_id, err, info->cb_data);
1106     ipmi_mem_free(info);
1107 }
1108 
1109 int
ipmi_mc_add_event_to_sel(ipmi_mc_t * mc,ipmi_event_t * event,ipmi_mc_add_event_done_cb handler,void * cb_data)1110 ipmi_mc_add_event_to_sel(ipmi_mc_t                 *mc,
1111 			 ipmi_event_t              *event,
1112 			 ipmi_mc_add_event_done_cb handler,
1113 			 void                      *cb_data)
1114 {
1115     sel_add_op_done_info_t *sel_info;
1116     int                    rv;
1117 
1118     if (!mc->devid.SEL_device_support)
1119 	return EINVAL;
1120 
1121     /* If we have an OEM handler, call it instead. */
1122     if (mc->sel_add_event_handler) {
1123 	rv = mc->sel_add_event_handler(mc, event, handler, cb_data);
1124 	return rv;
1125     }
1126 
1127     sel_info = ipmi_mem_alloc(sizeof(*sel_info));
1128     if (!sel_info)
1129 	return ENOMEM;
1130 
1131     sel_info->mc = mc;
1132     sel_info->done = handler;
1133     sel_info->cb_data = cb_data;
1134 
1135     rv = ipmi_sel_add_event_to_sel(mc->sel, event, sel_add_op_done, sel_info);
1136     if (rv)
1137 	ipmi_mem_free(sel_info);
1138 
1139     return rv;
1140 }
1141 
1142 ipmi_event_t *
ipmi_mc_next_event(ipmi_mc_t * mc,const ipmi_event_t * event)1143 ipmi_mc_next_event(ipmi_mc_t *mc, const ipmi_event_t *event)
1144 {
1145     return ipmi_sel_get_next_event(mc->sel, event);
1146 }
1147 
1148 ipmi_event_t *
ipmi_mc_prev_event(ipmi_mc_t * mc,const ipmi_event_t * event)1149 ipmi_mc_prev_event(ipmi_mc_t *mc, const ipmi_event_t *event)
1150 {
1151     return ipmi_sel_get_prev_event(mc->sel, event);
1152 }
1153 
1154 ipmi_event_t *
ipmi_mc_last_event(ipmi_mc_t * mc)1155 ipmi_mc_last_event(ipmi_mc_t *mc)
1156 {
1157     return ipmi_sel_get_last_event(mc->sel);
1158 }
1159 
1160 ipmi_event_t *
ipmi_mc_first_event(ipmi_mc_t * mc)1161 ipmi_mc_first_event(ipmi_mc_t *mc)
1162 {
1163     return ipmi_sel_get_first_event(mc->sel);
1164 }
1165 
1166 ipmi_event_t *
ipmi_mc_event_by_recid(ipmi_mc_t * mc,unsigned int record_id)1167 ipmi_mc_event_by_recid(ipmi_mc_t    *mc,
1168                        unsigned int record_id)
1169 {
1170     return ipmi_sel_get_event_by_recid(mc->sel, record_id);
1171 }
1172 
1173 int
ipmi_mc_sel_count(ipmi_mc_t * mc)1174 ipmi_mc_sel_count(ipmi_mc_t *mc)
1175 {
1176     unsigned int val = 0;
1177 
1178     ipmi_get_sel_count(mc->sel, &val);
1179     return val;
1180 }
1181 
1182 int
ipmi_mc_sel_entries_used(ipmi_mc_t * mc)1183 ipmi_mc_sel_entries_used(ipmi_mc_t *mc)
1184 {
1185     unsigned int val = 0;
1186 
1187     ipmi_get_sel_entries_used(mc->sel, &val);
1188     return val;
1189 }
1190 
1191 int
ipmi_mc_sel_get_major_version(ipmi_mc_t * mc)1192 ipmi_mc_sel_get_major_version(ipmi_mc_t *mc)
1193 {
1194     int val = 0;
1195 
1196     ipmi_sel_get_major_version(mc->sel, &val);
1197     return val;
1198 }
1199 
1200 int
ipmi_mc_sel_get_minor_version(ipmi_mc_t * mc)1201 ipmi_mc_sel_get_minor_version(ipmi_mc_t *mc)
1202 {
1203     int val = 0;
1204 
1205     ipmi_sel_get_minor_version(mc->sel, &val);
1206     return val;
1207 }
1208 
1209 int
ipmi_mc_sel_get_num_entries(ipmi_mc_t * mc)1210 ipmi_mc_sel_get_num_entries(ipmi_mc_t *mc)
1211 {
1212     int val = 0;
1213 
1214     ipmi_sel_get_num_entries(mc->sel, &val);
1215     return val;
1216 }
1217 
1218 int
ipmi_mc_sel_get_free_bytes(ipmi_mc_t * mc)1219 ipmi_mc_sel_get_free_bytes(ipmi_mc_t *mc)
1220 {
1221     int val = 0;
1222 
1223     ipmi_sel_get_free_bytes(mc->sel, &val);
1224     return val;
1225 }
1226 
1227 int
ipmi_mc_sel_get_overflow(ipmi_mc_t * mc)1228 ipmi_mc_sel_get_overflow(ipmi_mc_t *mc)
1229 {
1230     int val = 0;
1231 
1232     ipmi_sel_get_overflow(mc->sel, &val);
1233     return val;
1234 }
1235 
1236 int
ipmi_mc_sel_get_supports_delete_sel(ipmi_mc_t * mc)1237 ipmi_mc_sel_get_supports_delete_sel(ipmi_mc_t *mc)
1238 {
1239     int val = 0;
1240 
1241     ipmi_sel_get_supports_delete_sel(mc->sel, &val);
1242     return val;
1243 }
1244 
1245 int
ipmi_mc_sel_get_supports_partial_add_sel(ipmi_mc_t * mc)1246 ipmi_mc_sel_get_supports_partial_add_sel(ipmi_mc_t *mc)
1247 {
1248     int val = 0;
1249 
1250     ipmi_sel_get_supports_partial_add_sel(mc->sel, &val);
1251     return val;
1252 }
1253 
1254 int
ipmi_mc_sel_get_supports_reserve_sel(ipmi_mc_t * mc)1255 ipmi_mc_sel_get_supports_reserve_sel(ipmi_mc_t *mc)
1256 {
1257     int val = 0;
1258 
1259     ipmi_sel_get_supports_reserve_sel(mc->sel, &val);
1260     return val;
1261 }
1262 
1263 int
ipmi_mc_sel_get_supports_get_sel_allocation(ipmi_mc_t * mc)1264 ipmi_mc_sel_get_supports_get_sel_allocation(ipmi_mc_t *mc)
1265 {
1266     int val = 0;
1267 
1268     ipmi_sel_get_supports_get_sel_allocation(mc->sel, &val);
1269     return val;
1270 }
1271 
1272 int
ipmi_mc_sel_get_last_addition_timestamp(ipmi_mc_t * mc)1273 ipmi_mc_sel_get_last_addition_timestamp(ipmi_mc_t *mc)
1274 {
1275     int val = 0;
1276 
1277     ipmi_sel_get_last_addition_timestamp(mc->sel, &val);
1278     return val;
1279 }
1280 
1281 int
ipmi_mc_set_oem_event_handler(ipmi_mc_t * mc,ipmi_oem_event_handler_cb handler,void * cb_data)1282 ipmi_mc_set_oem_event_handler(ipmi_mc_t                 *mc,
1283 			      ipmi_oem_event_handler_cb handler,
1284 			      void                      *cb_data)
1285 {
1286     mc->oem_event_handler = handler;
1287     mc->oem_event_cb_data = cb_data;
1288     return 0;
1289 }
1290 
1291 int
ipmi_mc_set_sel_oem_event_handler(ipmi_mc_t * mc,ipmi_oem_event_handler_cb handler,void * cb_data)1292 ipmi_mc_set_sel_oem_event_handler(ipmi_mc_t                 *mc,
1293 				  ipmi_oem_event_handler_cb handler,
1294 				  void                      *cb_data)
1295 {
1296     mc->sel_oem_event_handler = handler;
1297     mc->sel_oem_event_cb_data = cb_data;
1298     return 0;
1299 }
1300 
1301 static void mc_reread_sel_timeout(void *cb_data, os_hnd_timer_id_t *id);
1302 
1303 /* Must be called with the info lock held. */
1304 static void
sels_start_timer(mc_reread_sel_t * info)1305 sels_start_timer(mc_reread_sel_t *info)
1306 {
1307     DEBUG_INFO(info);
1308     info->processing = 0;
1309     if (info->mc->sel_scan_interval != 0) {
1310 	os_handler_t   *os_hnd = info->os_hnd;
1311 	struct timeval timeout;
1312 
1313 	timeout.tv_sec = info->mc->sel_scan_interval;
1314 	timeout.tv_usec = 0;
1315 	info->timer_running = 1;
1316 	os_hnd->start_timer(os_hnd,
1317 			    info->sel_timer,
1318 			    &timeout,
1319 			    mc_reread_sel_timeout,
1320 			    info);
1321     } else {
1322 	info->timer_running = 0;
1323     }
1324 }
1325 
1326 /* Must be called with the info lock held, will release the lock. */
1327 static void
sels_fetched_call_handler(mc_reread_sel_t * info,int err,int changed,int count)1328 sels_fetched_call_handler(mc_reread_sel_t *info, int err, int changed,
1329 			  int count)
1330 {
1331     ipmi_sels_fetched_t handler = NULL;
1332     void                *cb_data = NULL;
1333     ipmi_mc_ptr_cb      handler2 = NULL;
1334     void                *cb_data2 = NULL;
1335 
1336     DEBUG_INFO(info);
1337     if (info->handler) {
1338 	handler = info->handler;
1339 	cb_data = info->cb_data;
1340 	info->handler = NULL;
1341     }
1342     if (info->sels_first_read_handler) {
1343 	handler2 = info->sels_first_read_handler;
1344 	cb_data2 = info->sels_first_read_cb_data;
1345 	info->sels_first_read_handler = NULL;
1346     }
1347     ipmi_unlock(info->lock);
1348 
1349     if (handler2)
1350 	handler2(info->mc, cb_data2);
1351 
1352     if (handler)
1353 	handler(info->mc->sel, err, changed, count, cb_data);
1354 }
1355 
1356 static void
sels_restart(mc_reread_sel_t * info)1357 sels_restart(mc_reread_sel_t *info)
1358 {
1359     /* After the first SEL fetch, disable looking at the timestamp, in
1360        case someone messes with the SEL time. */
1361     DEBUG_INFO(info);
1362     info->mc->startup_SEL_time = 0;
1363     info->sel_time_set = 1;
1364 
1365     sels_start_timer(info);
1366 }
1367 
1368 static void
sels_fetched_start_timer(ipmi_sel_info_t * sel,int err,int changed,unsigned int count,void * cb_data)1369 sels_fetched_start_timer(ipmi_sel_info_t *sel,
1370 			 int             err,
1371 			 int             changed,
1372 			 unsigned int    count,
1373 			 void            *cb_data)
1374 {
1375     mc_reread_sel_t *info = cb_data;
1376 
1377     ipmi_lock(info->lock);
1378     DEBUG_INFO(info);
1379     if (info->cancelled) {
1380 	DEBUG_INFO(info);
1381 	ipmi_unlock(info->lock);
1382 	info->os_hnd->free_timer(info->os_hnd, info->sel_timer);
1383 	ipmi_destroy_lock(info->lock);
1384 	ipmi_mem_free(info);
1385 	return;
1386     } else if (! info->timer_should_run) {
1387 	DEBUG_INFO(info);
1388 	info->processing = 0;
1389 	info->timer_running = 0;
1390 	sels_fetched_call_handler(info, ECANCELED, 0, 0);
1391 	return;
1392     }
1393 
1394     /* After the first SEL fetch, disable looking at the timestamp, in
1395        case someone messes with the SEL time. */
1396     info->mc->startup_SEL_time = 0;
1397 
1398     sels_start_timer(info);
1399     sels_fetched_call_handler(info, err, changed, count);
1400 }
1401 
1402 static void
mc_reread_sel_timeout_cb(ipmi_mc_t * mc,void * cb_data)1403 mc_reread_sel_timeout_cb(ipmi_mc_t *mc, void *cb_data)
1404 {
1405     mc_reread_sel_t *info = cb_data;
1406     int             rv = EINVAL;
1407 
1408     DEBUG_INFO(info);
1409     info->processing = 1;
1410     if (! info->sel_time_set) {
1411 	DEBUG_INFO(mc->sel_timer_info);
1412 	start_sel_time_set(mc, info);
1413     } else {
1414 	/* Only fetch the SEL if we know the connection is up. */
1415 	if (ipmi_domain_con_up(mc->domain)) {
1416 	    DEBUG_INFO(mc->sel_timer_info);
1417 	    rv = ipmi_sel_get(mc->sel, sels_fetched_start_timer, info);
1418 	}
1419 
1420 	/* If we couldn't run the SEL get, then restart the timer now. */
1421 	if (rv) {
1422 	    DEBUG_INFO(mc->sel_timer_info);
1423 	    sels_start_timer(info);
1424 	}
1425     }
1426 
1427     /* Have to unlock here, because the MC put processing may claim
1428        this lock. */
1429     ipmi_unlock(info->lock);
1430 }
1431 
1432 static void
mc_reread_sel_timeout(void * cb_data,os_hnd_timer_id_t * id)1433 mc_reread_sel_timeout(void *cb_data, os_hnd_timer_id_t *id)
1434 {
1435     mc_reread_sel_t *info = cb_data;
1436     ipmi_mcid_t     mc_id;
1437     int             rv;
1438 
1439     ipmi_lock(info->lock);
1440     DEBUG_INFO(info);
1441     if (info->cancelled) {
1442 	DEBUG_INFO(info);
1443 	ipmi_unlock(info->lock);
1444 	info->os_hnd->free_timer(info->os_hnd, info->sel_timer);
1445 	ipmi_destroy_lock(info->lock);
1446 	ipmi_mem_free(info);
1447 	return;
1448     } else if (! info->timer_should_run) {
1449 	DEBUG_INFO(info);
1450 	info->processing = 0;
1451 	info->timer_running = 0;
1452 	sels_fetched_call_handler(info, ECANCELED, 0, 0);
1453 	return;
1454     }
1455 
1456     mc_id = info->mc_id;
1457 
1458     rv = ipmi_mc_pointer_cb(mc_id, mc_reread_sel_timeout_cb, info);
1459     if (rv) {
1460 	/* Strange, but correct.  If we get here but the MC no longer
1461 	   exists, we raced with it's destroy.  We still hold the info
1462 	   lock, so just don't start the timer and everything should
1463 	   be happy. */
1464 	DEBUG_INFO(info);
1465 	info->processing = 0;
1466 	info->timer_running = 0;
1467 	ipmi_unlock(info->lock);
1468     }
1469 }
1470 
1471 typedef struct sel_reread_s
1472 {
1473     ipmi_mc_done_cb handler;
1474     void            *cb_data;
1475     ipmi_mcid_t     mcid;
1476     int             err;
1477 } sel_reread_t;
1478 
1479 static void
mc_reread_sel_cb(ipmi_mc_t * mc,void * cb_data)1480 mc_reread_sel_cb(ipmi_mc_t *mc, void *cb_data)
1481 {
1482     sel_reread_t *info = cb_data;
1483 
1484     info->handler(mc, info->err, info->cb_data);
1485 }
1486 
1487 static void
reread_sel_done(ipmi_sel_info_t * sel,int err,int changed,unsigned int count,void * cb_data)1488 reread_sel_done(ipmi_sel_info_t *sel,
1489 		int             err,
1490 		int             changed,
1491 		unsigned int    count,
1492 		void            *cb_data)
1493 {
1494     sel_reread_t *info = cb_data;
1495     int          rv;
1496 
1497     if (info->handler) {
1498 	if (!sel) {
1499 	    info->handler(NULL, ECANCELED, info->cb_data);
1500 	    goto out;
1501 	}
1502 
1503 	rv = ipmi_mc_pointer_cb(info->mcid, mc_reread_sel_cb, info);
1504 	if (rv) {
1505 	    info->handler(NULL, ECANCELED, info->cb_data);
1506 	    goto out;
1507 	}
1508     }
1509  out:
1510     ipmi_mem_free(info);
1511 }
1512 
1513 static int start_sel_ops(ipmi_mc_t           *mc,
1514 			 int                 fail_if_down,
1515 			 ipmi_sels_fetched_t handler,
1516 			 void                *cb_data);
1517 
1518 int
ipmi_mc_reread_sel(ipmi_mc_t * mc,ipmi_mc_done_cb handler,void * cb_data)1519 ipmi_mc_reread_sel(ipmi_mc_t       *mc,
1520 		   ipmi_mc_done_cb handler,
1521 		   void            *cb_data)
1522 {
1523     sel_reread_t        *info = NULL;
1524     ipmi_sels_fetched_t cb = NULL;
1525     int                 rv;
1526 
1527     if (handler) {
1528 	info = ipmi_mem_alloc(sizeof(*info));
1529 	if (!info)
1530 	    return ENOMEM;
1531 
1532 	info->handler = handler;
1533 	info->cb_data = cb_data;
1534 	info->mcid = ipmi_mc_convert_to_id(mc);
1535 	info->err = 0;
1536 	cb = reread_sel_done;
1537     }
1538 
1539     ipmi_lock(mc->lock);
1540     if (! mc_op_ready(mc)) {
1541 	rv = ECANCELED;
1542     } else if (mc->sel_timer_info) {
1543 	/* SEL is already set up, just do a request. */
1544 	rv = ipmi_sel_get(mc->sel, cb, info);
1545     } else {
1546 	/* SEL is not set up, start it. */
1547 	rv = start_sel_ops(mc, 1, cb, info);
1548     }
1549     ipmi_unlock(mc->lock);
1550 
1551     if (rv && info) {
1552 	ipmi_mem_free(info);
1553     }
1554 
1555     return rv;
1556 }
1557 
1558 typedef struct sel_get_time_s
1559 {
1560     sel_get_time_cb handler;
1561     void            *cb_data;
1562     char            name[IPMI_MC_NAME_LEN];
1563 } sel_get_time_t;
1564 
1565 static void
get_sel_time(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)1566 get_sel_time(ipmi_mc_t  *mc,
1567 	     ipmi_msg_t *rsp,
1568 	     void       *rsp_data)
1569 {
1570     sel_get_time_t *info = rsp_data;
1571 
1572     if (!mc) {
1573 	/* The MC went away, deliver an error. */
1574 	ipmi_log(IPMI_LOG_ERR_INFO,
1575 		 "%smc.c(get_sel_time): "
1576 		 "MC went away during SEL time fetch.",
1577 		 info->name);
1578 	if (info->handler)
1579 	    info->handler(mc, ECANCELED, 0, info->cb_data);
1580 	goto out;
1581     }
1582 
1583     if (rsp->data[0] != 0) {
1584 	/* Error setting the event receiver, report it. */
1585 	ipmi_log(IPMI_LOG_ERR_INFO,
1586 		 "%smc.c(get_sel_time): "
1587 		 "Could not get SEL time for MC at 0x%x",
1588 		 mc->name, ipmi_addr_get_slave_addr(&mc->addr));
1589 	if (info->handler)
1590 	    info->handler(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), 0,
1591 			  info->cb_data);
1592 	goto out;
1593     }
1594 
1595     if (rsp->data_len < 5) {
1596 	/* Not enough data? */
1597 	ipmi_log(IPMI_LOG_ERR_INFO,
1598 		 "%smc.c(get_sel_time): "
1599 		 "Get SEL time response too short for MC at 0x%x",
1600 		 mc->name, ipmi_addr_get_slave_addr(&mc->addr));
1601 	if (info->handler)
1602 	    info->handler(mc, EINVAL, 0, info->cb_data);
1603 	goto out;
1604     }
1605 
1606     if (info->handler)
1607 	info->handler(mc, 0, ipmi_get_uint32(rsp->data+1), info->cb_data);
1608 
1609  out:
1610     ipmi_mem_free(info);
1611 }
1612 
1613 int
ipmi_mc_get_current_sel_time(ipmi_mc_t * mc,sel_get_time_cb handler,void * cb_data)1614 ipmi_mc_get_current_sel_time(ipmi_mc_t       *mc,
1615 			     sel_get_time_cb handler,
1616 			     void            *cb_data)
1617 {
1618     ipmi_msg_t     msg;
1619     sel_get_time_t *info;
1620     int            rv;
1621 
1622     info = ipmi_mem_alloc(sizeof(*info));
1623     if (!info)
1624 	return ENOMEM;
1625 
1626     info->handler = handler;
1627     info->cb_data = cb_data;
1628     strncpy(info->name, mc->name, sizeof(info->name) - 1);
1629     info->name[sizeof(info->name) - 1] = '\0';
1630 
1631     msg.netfn = IPMI_STORAGE_NETFN;
1632     msg.cmd = IPMI_GET_SEL_TIME_CMD;
1633     msg.data = NULL;
1634     msg.data_len = 0;
1635     rv = ipmi_mc_send_command(mc, 0, &msg, get_sel_time, info);
1636     if (rv)
1637 	ipmi_mem_free(info);
1638     return rv;
1639 }
1640 
1641 typedef struct set_sel_time_s
1642 {
1643     ipmi_mc_done_cb handler;
1644     void            *cb_data;
1645     char            name[IPMI_MC_NAME_LEN];
1646 } set_sel_time_t;
1647 
1648 static void
set_sel_time(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)1649 set_sel_time(ipmi_mc_t  *mc,
1650 	     ipmi_msg_t *rsp,
1651 	     void       *rsp_data)
1652 {
1653     set_sel_time_t *info = rsp_data;
1654 
1655     if (!mc) {
1656 	/* The MC went away, deliver an error. */
1657 	ipmi_log(IPMI_LOG_ERR_INFO,
1658 		 "%smc.c(set_sel_time): "
1659 		 "MC went away during SEL time fetch.",
1660 		 info->name);
1661 	if (info->handler)
1662 	    info->handler(mc, ECANCELED, info->cb_data);
1663 	goto out;
1664     }
1665 
1666     if (rsp->data[0] != 0) {
1667 	/* Error setting the event receiver, report it. */
1668 	ipmi_log(IPMI_LOG_ERR_INFO,
1669 		 "%smc.c(set_sel_time): "
1670 		 "Could not get SEL time for MC at 0x%x",
1671 		 mc->name, ipmi_addr_get_slave_addr(&mc->addr));
1672 	if (info->handler)
1673 	    info->handler(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), info->cb_data);
1674 	goto out;
1675     }
1676 
1677     if (info->handler)
1678 	info->handler(mc, 0, info->cb_data);
1679 
1680  out:
1681     ipmi_mem_free(info);
1682 }
1683 
1684 int
ipmi_mc_set_current_sel_time(ipmi_mc_t * mc,const struct timeval * time,ipmi_mc_done_cb handler,void * cb_data)1685 ipmi_mc_set_current_sel_time(ipmi_mc_t             *mc,
1686 			     const struct timeval  *time,
1687 			     ipmi_mc_done_cb       handler,
1688 			     void                  *cb_data)
1689 {
1690     ipmi_msg_t     msg;
1691     int            rv;
1692     unsigned char  data[4];
1693     set_sel_time_t *info;
1694 
1695 
1696     info = ipmi_mem_alloc(sizeof(*info));
1697     if (!info)
1698 	return ENOMEM;
1699 
1700     info->handler = handler;
1701     info->cb_data = cb_data;
1702     strncpy(info->name, mc->name, sizeof(info->name) - 1);
1703     info->name[sizeof(info->name) - 1] = '\0';
1704 
1705     msg.netfn = IPMI_STORAGE_NETFN;
1706     msg.cmd = IPMI_SET_SEL_TIME_CMD;
1707     msg.data = data;
1708     msg.data_len = 4;
1709     ipmi_set_uint32(data, time->tv_sec);
1710     rv = ipmi_mc_send_command(mc, 0, &msg, set_sel_time, info);
1711     if (rv)
1712 	ipmi_mem_free(info);
1713     return rv;
1714 }
1715 
1716 
1717 /***********************************************************************
1718  *
1719  * Handling startup of a new MC
1720  *
1721  **********************************************************************/
1722 
1723 typedef struct set_event_rcvr_info_s
1724 {
1725     ipmi_mc_done_cb done;
1726     void            *cb_data;
1727 } set_event_rcvr_info_t;
1728 
1729 static void
set_event_rcvr_done(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)1730 set_event_rcvr_done(ipmi_mc_t  *mc,
1731 		    ipmi_msg_t *rsp,
1732 		    void       *rsp_data)
1733 {
1734     ipmi_mc_done_cb done = NULL;
1735     void            *cb_data = NULL;
1736     int             rv = 0;
1737 
1738     if (rsp_data) {
1739 	set_event_rcvr_info_t *info = rsp_data;
1740 	done = info->done;
1741 	cb_data = info->cb_data;
1742 	ipmi_mem_free(info);
1743     }
1744 
1745     if (!mc) {
1746 	rv = ECANCELED;
1747 	goto out; /* The MC went away, no big deal. */
1748     }
1749 
1750     if (rsp->data[0] != 0) {
1751 	/* Error setting the event receiver, report it. */
1752 	ipmi_log(IPMI_LOG_WARNING,
1753 		 "%smc.c(set_event_rcvr_done): "
1754 		 "Could not set event receiver for MC at 0x%x",
1755 		 mc->name, ipmi_addr_get_slave_addr(&mc->addr));
1756 	rv = IPMI_IPMI_ERR_VAL(rsp->data[0]);
1757     }
1758 
1759  out:
1760     if (done)
1761 	done(mc, rv, cb_data);
1762 }
1763 
1764 static int
send_set_event_rcvr(ipmi_mc_t * mc,unsigned int addr,ipmi_mc_done_cb done,void * cb_data)1765 send_set_event_rcvr(ipmi_mc_t       *mc,
1766 		    unsigned int    addr,
1767 		    ipmi_mc_done_cb done,
1768 		    void            *cb_data)
1769 {
1770     ipmi_msg_t            msg;
1771     unsigned char         data[2];
1772     set_event_rcvr_info_t *info = NULL;
1773 
1774     if (done) {
1775 	info = ipmi_mem_alloc(sizeof(*info));
1776 	if (!info)
1777 	    return ENOMEM;
1778 	info->done = done;
1779 	info->cb_data = cb_data;
1780     }
1781 
1782     msg.netfn = IPMI_SENSOR_EVENT_NETFN;
1783     msg.cmd = IPMI_SET_EVENT_RECEIVER_CMD;
1784     msg.data = data;
1785     msg.data_len = 2;
1786     data[0] = addr;
1787     data[1] = 0; /* LUN is 0 per the spec (section 7.2 of 1.5 spec). */
1788     return ipmi_mc_send_command(mc, 0, &msg, set_event_rcvr_done, info);
1789     /* No care about return values, if this fails it will be done
1790        again later. */
1791 }
1792 
1793 static void
get_event_rcvr_done(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)1794 get_event_rcvr_done(ipmi_mc_t  *mc,
1795 		    ipmi_msg_t *rsp,
1796 		    void       *rsp_data)
1797 {
1798     if (!mc)
1799 	return; /* The MC went away, no big deal. */
1800 
1801     if (rsp->data[0] != 0) {
1802 	/* Error getting the event receiver, report it. */
1803 	ipmi_log(IPMI_LOG_WARNING,
1804 		 "%smc.c(get_event_rcvr_done): "
1805 		 "Could not get event receiver for MC at 0x%x",
1806 		 mc->name, ipmi_addr_get_slave_addr(&mc->addr));
1807     } else if (rsp->data_len < 2) {
1808 	ipmi_log(IPMI_LOG_WARNING,
1809 		 "%smc.c(get_event_rcvr_done): "
1810 		 "Get event receiver length invalid for MC at 0x%x",
1811 		 mc->name, ipmi_addr_get_slave_addr(&mc->addr));
1812     } else if ((rsp->data[1] == 0) && (!mc->events_enabled))  {
1813 	/* Nothing to do, our event receiver is disabled. */
1814     } else {
1815 	ipmi_domain_t    *domain = ipmi_mc_get_domain(mc);
1816 	ipmi_mc_t        *destmc;
1817 	ipmi_ipmb_addr_t ipmb;
1818 
1819 	ipmb.addr_type = IPMI_IPMB_ADDR_TYPE;
1820 	ipmb.channel = ipmi_mc_get_channel(mc);
1821 	ipmb.slave_addr = rsp->data[1];
1822 	ipmb.lun = 0;
1823 
1824 	if (mc->events_enabled) {
1825 	    destmc = i_ipmi_find_mc_by_addr(domain, (ipmi_addr_t *) &ipmb,
1826 					    sizeof(ipmb));
1827 	    if (!destmc || !ipmi_mc_ipmb_event_receiver_support(destmc)) {
1828 		/* The current event receiver doesn't exist or cannot
1829 		   receive events, change it. */
1830 		unsigned int event_rcvr = ipmi_domain_get_event_rcvr(mc->domain);
1831 		if (event_rcvr)
1832 		    send_set_event_rcvr(mc, event_rcvr, NULL, NULL);
1833 	    }
1834 	    if (destmc)
1835 		i_ipmi_mc_put(destmc);
1836 	} else {
1837 	    send_set_event_rcvr(mc, 0, NULL, NULL);
1838 	}
1839     }
1840 }
1841 
1842 static void
send_get_event_rcvr(ipmi_mc_t * mc)1843 send_get_event_rcvr(ipmi_mc_t *mc)
1844 {
1845     ipmi_msg_t    msg;
1846 
1847     msg.netfn = IPMI_SENSOR_EVENT_NETFN;
1848     msg.cmd = IPMI_GET_EVENT_RECEIVER_CMD;
1849     msg.data = NULL;
1850     msg.data_len = 0;
1851     ipmi_mc_send_command(mc, 0, &msg, get_event_rcvr_done, NULL);
1852     /* No care about return values, if this fails it will be done
1853        again later. */
1854 }
1855 
1856 void
i_ipmi_mc_check_event_rcvr(ipmi_mc_t * mc)1857 i_ipmi_mc_check_event_rcvr(ipmi_mc_t *mc)
1858 {
1859     if (mc && mc->devid.IPMB_event_generator_support
1860 	&& ipmi_option_set_event_rcvr(mc->domain))
1861     {
1862 	/* We have an MC that is live (or still live) and generates
1863 	   events, make sure the event receiver is set properly. */
1864 	unsigned int event_rcvr = ipmi_domain_get_event_rcvr(mc->domain);
1865 
1866 	/* Don't bother if we have no possible event receivers.*/
1867 	if (event_rcvr) {
1868 	    send_get_event_rcvr(mc);
1869 	}
1870     }
1871 }
1872 
1873 static void
startup_set_sel_time(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)1874 startup_set_sel_time(ipmi_mc_t  *mc,
1875 		     ipmi_msg_t *rsp,
1876 		     void       *rsp_data)
1877 {
1878     mc_reread_sel_t *info = rsp_data;
1879     int             rv;
1880 
1881     ipmi_lock(info->lock);
1882     DEBUG_INFO(info);
1883     if (info->cancelled) {
1884 	DEBUG_INFO(info);
1885 	ipmi_unlock(info->lock);
1886 	info->os_hnd->free_timer(info->os_hnd, info->sel_timer);
1887 	ipmi_destroy_lock(info->lock);
1888 	ipmi_mem_free(info);
1889 	return;
1890     } else if (! info->timer_should_run) {
1891 	DEBUG_INFO(info);
1892 	info->processing = 0;
1893 	info->timer_running = 0;
1894 	sels_fetched_call_handler(info, ECANCELED, 0, 0);
1895 	return;
1896     }
1897 
1898     mc = info->mc;
1899 
1900     if (rsp->data[0] != 0) {
1901 	info->retries++;
1902 	if (info->retries > MAX_SEL_TIME_SET_RETRIES) {
1903 	    DEBUG_INFO(mc->sel_timer_info);
1904 	    ipmi_log(IPMI_LOG_ERR_INFO,
1905 		     "%smc.c(startup_set_sel_time): "
1906 		     "Unable to set the SEL time due to error: %x, aborting",
1907 		     mc->name, rsp->data[0]);
1908 	    mc->startup_SEL_time = 0;
1909 	    info->sel_time_set = 1;
1910 	    sels_restart(info);
1911 	} else {
1912 	    DEBUG_INFO(mc->sel_timer_info);
1913 	    ipmi_log(IPMI_LOG_ERR_INFO,
1914 		     "%smc.c(startup_set_sel_time): "
1915 		     "Unable to set the SEL time due to error: %x, retrying",
1916 		     mc->name, rsp->data[0]);
1917 	    sels_start_timer(info);
1918 	}
1919 	goto out;
1920     }
1921 
1922     info->sel_time_set = 1;
1923 
1924     rv = ipmi_sel_get(mc->sel, sels_fetched_start_timer, mc->sel_timer_info);
1925     if (rv) {
1926 	DEBUG_INFO(mc->sel_timer_info);
1927 	ipmi_log(IPMI_LOG_WARNING,
1928 		 "%smc.c(startup_set_sel_time): "
1929 		 "Unable to start an SEL get due to error: %x",
1930 		 mc->name, rsp->data[0]);
1931 	sels_restart(info);
1932     }
1933 
1934  out:
1935     ipmi_unlock(info->lock);
1936 }
1937 
1938 static void
do_sel_time_set(ipmi_mc_t * mc,mc_reread_sel_t * info)1939 do_sel_time_set(ipmi_mc_t *mc, mc_reread_sel_t *info)
1940 {
1941     ipmi_msg_t     msg;
1942     int            rv;
1943     unsigned char  data[4];
1944     struct timeval now;
1945 
1946     DEBUG_INFO(info);
1947     /* Set the current system event log time.  We do this here so
1948        we can be sure that the entities are all there before
1949        reporting events. */
1950     msg.netfn = IPMI_STORAGE_NETFN;
1951     msg.cmd = IPMI_SET_SEL_TIME_CMD;
1952     msg.data = data;
1953     msg.data_len = 4;
1954     info->os_hnd->get_monotonic_time(info->os_hnd, &now);
1955     ipmi_set_uint32(data, now.tv_sec);
1956     mc->startup_SEL_time = ipmi_seconds_to_time(now.tv_sec);
1957     rv = ipmi_mc_send_command(mc, 0, &msg, startup_set_sel_time, info);
1958     if (rv) {
1959 	info->retries++;
1960 	if (info->retries > MAX_SEL_TIME_SET_RETRIES) {
1961 	    DEBUG_INFO(mc->sel_timer_info);
1962 	    ipmi_log(IPMI_LOG_ERR_INFO,
1963 		     "%smc.c(first_sel_op): "
1964 		     "Unable to start SEL time set due to error: %x, aborting",
1965 		     mc->name, rv);
1966 	    mc->startup_SEL_time = 0;
1967 	    sels_restart(info);
1968 	} else {
1969 	    DEBUG_INFO(mc->sel_timer_info);
1970 	    ipmi_log(IPMI_LOG_ERR_INFO,
1971 		     "%smc.c(first_sel_op): "
1972 		     "Unable to start SEL time set due to error: %x, retrying",
1973 		     mc->name, rv);
1974 	    sels_start_timer(info);
1975 	}
1976     }
1977 }
1978 
1979 static void
startup_got_sel_time(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)1980 startup_got_sel_time(ipmi_mc_t  *mc,
1981 		     ipmi_msg_t *rsp,
1982 		     void       *rsp_data)
1983 {
1984     mc_reread_sel_t *info = rsp_data;
1985     struct timeval  now;
1986     uint32_t        time;
1987     int             rv;
1988 
1989     ipmi_lock(info->lock);
1990     DEBUG_INFO(info);
1991     if (info->cancelled) {
1992 	DEBUG_INFO(info);
1993 	ipmi_unlock(info->lock);
1994 	info->os_hnd->free_timer(info->os_hnd, info->sel_timer);
1995 	ipmi_destroy_lock(info->lock);
1996 	ipmi_mem_free(info);
1997 	return;
1998     } else if (! info->timer_should_run) {
1999 	DEBUG_INFO(info);
2000 	info->processing = 0;
2001 	info->timer_running = 0;
2002 	sels_fetched_call_handler(info, ECANCELED, 0, 0);
2003 	return;
2004     }
2005 
2006     /* MC must be valid if we are not cancelled. */
2007     mc = info->mc;
2008 
2009     if (rsp->data[0] != 0) {
2010 	info->retries++;
2011 	if (info->retries > MAX_SEL_TIME_SET_RETRIES) {
2012 	    DEBUG_INFO(mc->sel_timer_info);
2013 	    ipmi_log(IPMI_LOG_WARNING,
2014 		     "%smc.c(startup_set_sel_time): "
2015 		     "Unable to get the SEL time due to error: %x, aborting",
2016 		     mc->name, rsp->data[0]);
2017 	    mc->startup_SEL_time = 0;
2018 	    sels_restart(info);
2019 	} else {
2020 	    DEBUG_INFO(mc->sel_timer_info);
2021 	    ipmi_log(IPMI_LOG_ERR_INFO,
2022 		     "%smc.c(startup_set_sel_time): "
2023 		     "Unable to get the SEL time due to error: %x, retrying",
2024 		     mc->name, rsp->data[0]);
2025 	    sels_start_timer(info);
2026 	}
2027 	goto out;
2028     }
2029 
2030     if (rsp->data_len < 5) {
2031 	info->retries++;
2032 	if (info->retries > MAX_SEL_TIME_SET_RETRIES) {
2033 	    DEBUG_INFO(mc->sel_timer_info);
2034 	    ipmi_log(IPMI_LOG_WARNING,
2035 		     "%smc.c(startup_got_sel_time): "
2036 		     "Get SEL time response too short for MC at 0x%x,"
2037 		     " aborting",
2038 		     mc->name, ipmi_addr_get_slave_addr(&mc->addr));
2039 	    mc->startup_SEL_time = 0;
2040 	    sels_restart(info);
2041 	} else {
2042 	    DEBUG_INFO(mc->sel_timer_info);
2043 	    ipmi_log(IPMI_LOG_WARNING,
2044 		     "%smc.c(startup_got_sel_time): "
2045 		     "Get SEL time response too short for MC at 0x%x,"
2046 		     " retrying",
2047 		     mc->name, ipmi_addr_get_slave_addr(&mc->addr));
2048 	    sels_start_timer(info);
2049 	}
2050 	goto out;
2051     }
2052 
2053     info->os_hnd->get_monotonic_time(info->os_hnd, &now);
2054     time = ipmi_get_uint32(rsp->data+1);
2055 
2056     if ((time < (uint32_t)now.tv_sec) && ipmi_option_set_sel_time(mc->domain)) {
2057 	/* Time is in the past and setting time is requested, move it
2058 	   forward. */
2059 	DEBUG_INFO(mc->sel_timer_info);
2060 	do_sel_time_set(mc, info);
2061     } else {
2062 	struct timeval tv;
2063 	/* Time is current or in the future, don't move it backwards
2064 	   as that may mess other things up. */
2065 	DEBUG_INFO(mc->sel_timer_info);
2066 	tv.tv_sec = time;
2067 	tv.tv_usec = 0;
2068 	mc->startup_SEL_time = ipmi_timeval_to_time(tv);
2069 	info->sel_time_set = 1;
2070 
2071 	rv = ipmi_sel_get(mc->sel, sels_fetched_start_timer,
2072 			  mc->sel_timer_info);
2073 	if (rv) {
2074 	    DEBUG_INFO(mc->sel_timer_info);
2075 	    ipmi_log(IPMI_LOG_WARNING,
2076 		     "%smc.c(startup_got_sel_time): "
2077 		     "Unable to start SEL fetch due to error 0x%x",
2078 		     mc->name, rv);
2079 	    sels_restart(info);
2080 	}
2081     }
2082 
2083  out:
2084     ipmi_unlock(info->lock);
2085 }
2086 
2087 static void
start_sel_time_set(ipmi_mc_t * mc,mc_reread_sel_t * info)2088 start_sel_time_set(ipmi_mc_t *mc, mc_reread_sel_t *info)
2089 {
2090     ipmi_msg_t      msg;
2091     int             rv;
2092 
2093     DEBUG_INFO(info);
2094     /* Set the current system event log time.  We do this here so we
2095        can be sure that the entities are all there before reporting
2096        events.  But first we fetch it to make sure it needs to be
2097        changed. */
2098     msg.netfn = IPMI_STORAGE_NETFN;
2099     msg.cmd = IPMI_GET_SEL_TIME_CMD;
2100     msg.data = NULL;
2101     msg.data_len = 0;
2102     rv = ipmi_mc_send_command(mc, 0, &msg, startup_got_sel_time, info);
2103     if (rv) {
2104 	DEBUG_INFO(mc->sel_timer_info);
2105 	info->retries++;
2106 	if (info->retries > MAX_SEL_TIME_SET_RETRIES) {
2107 	    ipmi_log(IPMI_LOG_WARNING,
2108 		     "%smc.c(start_sel_time_set): "
2109 		     "Unable to start SEL time set due to error: %x, aborting",
2110 		     mc->name, rv);
2111 	    sels_restart(info);
2112 	} else {
2113 	    ipmi_log(IPMI_LOG_ERR_INFO,
2114 		     "%smc.c(start_sel_time_set): "
2115 		     "Unable to start SEL time set due to error: %x, retrying",
2116 		     mc->name, rv);
2117 	    sels_start_timer(info);
2118 	}
2119     }
2120 }
2121 
2122 static int
start_sel_ops(ipmi_mc_t * mc,int fail_if_down,ipmi_sels_fetched_t handler,void * cb_data)2123 start_sel_ops(ipmi_mc_t           *mc,
2124 	      int                 fail_if_down,
2125 	      ipmi_sels_fetched_t handler,
2126 	      void                *cb_data)
2127 {
2128     ipmi_domain_t   *domain = ipmi_mc_get_domain(mc);
2129     mc_reread_sel_t *info = mc->sel_timer_info;
2130     int             rv = 0;
2131 
2132     ipmi_lock(info->lock);
2133     DEBUG_INFO(info);
2134     if (info->timer_should_run) {
2135 	DEBUG_INFO(info);
2136 	ipmi_unlock(info->lock);
2137 	return EBUSY; /* Already started. */
2138     }
2139 
2140     info->timer_should_run = 1;
2141     info->retries = 0;
2142     info->sel_time_set = 0;
2143 
2144     info->handler = handler;
2145     info->cb_data = cb_data;
2146 
2147     if (ipmi_domain_con_up(domain)) {
2148 	/* The domain is already up, just start the process. */
2149 	DEBUG_INFO(info);
2150 	info->processing = 1;
2151 	start_sel_time_set(mc, info);
2152 	ipmi_unlock(info->lock);
2153     } else if (fail_if_down) {
2154 	ipmi_mc_ptr_cb  handler2 = NULL;
2155 	void            *cb_data2 = NULL;
2156 	DEBUG_INFO(info);
2157 	rv = EAGAIN;
2158 	info->timer_should_run = 0;
2159 	info->processing = 0;
2160 	/* SELs not started, just call the handler. */
2161 	if (mc->sel_timer_info->sels_first_read_handler) {
2162 	    handler2 = mc->sel_timer_info->sels_first_read_handler;
2163 	    cb_data2 = mc->sel_timer_info->sels_first_read_cb_data;
2164 	    mc->sel_timer_info->sels_first_read_handler = NULL;
2165 	}
2166 	ipmi_unlock(info->lock);
2167 
2168 	if (handler2)
2169 	    handler2(info->mc, cb_data2);
2170     } else {
2171 	/* The domain is not up yet, wait for it to come up then start
2172            the process. */
2173 	DEBUG_INFO(info);
2174 	sels_start_timer(info);
2175 	ipmi_unlock(info->lock);
2176     }
2177     return rv;
2178 }
2179 
2180 void
i_ipmi_mc_startup_get(ipmi_mc_t * mc,char * name)2181 i_ipmi_mc_startup_get(ipmi_mc_t *mc, char *name)
2182 {
2183     ipmi_lock(mc->lock);
2184     mc->startup_count++;
2185     ipmi_unlock(mc->lock);
2186 }
2187 
2188 void
i_ipmi_mc_startup_put(ipmi_mc_t * mc,char * name)2189 i_ipmi_mc_startup_put(ipmi_mc_t *mc, char *name)
2190 {
2191     ipmi_lock(mc->lock);
2192     DEBUG_INFO(mc->sel_timer_info);
2193     mc->sel_timer_info->processing = 0;
2194     mc->startup_count--;
2195     if (mc->startup_reported || (mc->startup_count > 0)) {
2196 	ipmi_unlock(mc->lock);
2197 	return;
2198     }
2199     mc->startup_reported = 1;
2200     if (mc->state == MC_ACTIVE_IN_STARTUP)
2201 	mc->state = MC_ACTIVE_PEND_FULLY_UP;
2202     ipmi_unlock(mc->lock);
2203     i_ipmi_put_domain_fully_up(mc->domain, "i_ipmi_mc_startup_put");
2204 }
2205 
2206 static void
mc_first_sels_read(ipmi_sel_info_t * sel,int err,int changed,unsigned int count,void * cb_data)2207 mc_first_sels_read(ipmi_sel_info_t *sel,
2208 		   int             err,
2209 		   int             changed,
2210 		   unsigned int    count,
2211 		   void            *cb_data)
2212 {
2213     ipmi_mc_t *mc = cb_data;
2214 
2215     i_ipmi_mc_startup_put(mc, "mc_first_sels_read");
2216 }
2217 
2218 /* This is called after the first sensor scan for the MC, we start up
2219    timers and things like that here. */
2220 static void
sensors_reread(ipmi_mc_t * mc,int err,void * cb_data)2221 sensors_reread(ipmi_mc_t *mc, int err, void *cb_data)
2222 {
2223     unsigned int event_rcvr = 0;
2224 
2225     if (!mc) {
2226 	/* MC data is still valid, but the MC is not good any more.
2227 	   We saved it in rsp_data. */
2228         mc = cb_data;
2229 	DEBUG_INFO(mc->sel_timer_info);
2230 	i_ipmi_mc_startup_put(mc, "sensors_reread(3)");
2231 	return; /* domain went away while processing. */
2232     }
2233 
2234     DEBUG_INFO(mc->sel_timer_info);
2235     /* See if any presence has changed with the new sensors. */
2236     ipmi_detect_domain_presence_changes(mc->domain, 0);
2237 
2238     /* We set the event receiver here, so that we know all the SDRs
2239        are installed.  That way any incoming events from the device
2240        will have the proper sensor set. */
2241     if (mc->devid.IPMB_event_generator_support
2242 	&& ipmi_option_set_event_rcvr(mc->domain))
2243     {
2244 	event_rcvr = ipmi_domain_get_event_rcvr(mc->domain);
2245     }
2246 
2247     if (event_rcvr)
2248 	send_set_event_rcvr(mc, event_rcvr, NULL, NULL);
2249 
2250     ipmi_lock(mc->lock);
2251     if (mc->sdrs_first_read_handler) {
2252 	ipmi_mc_ptr_cb handler = mc->sdrs_first_read_handler;
2253 	void           *cb_data = mc->sdrs_first_read_cb_data;
2254 	mc->sdrs_first_read_handler = NULL;
2255 	ipmi_unlock(mc->lock);
2256 	handler(mc, cb_data);
2257     } else
2258 	ipmi_unlock(mc->lock);
2259 
2260     if (mc->devid.SEL_device_support && ipmi_option_SEL(mc->domain)) {
2261 	int rv;
2262 	/* If the MC supports an SEL, start scanning its SEL. */
2263 	DEBUG_INFO(mc->sel_timer_info);
2264 	ipmi_lock(mc->lock);
2265 	rv = start_sel_ops(mc, 0, mc_first_sels_read, mc);
2266 	ipmi_unlock(mc->lock);
2267 	if (rv) {
2268 	    DEBUG_INFO(mc->sel_timer_info);
2269 	    i_ipmi_mc_startup_put(mc, "sensors_reread(2)");
2270 	}
2271     } else {
2272 	DEBUG_INFO(mc->sel_timer_info);
2273 	i_ipmi_mc_startup_put(mc, "sensors_reread");
2274     }
2275 }
2276 
2277 static void
got_guid(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)2278 got_guid(ipmi_mc_t  *mc,
2279 	 ipmi_msg_t *rsp,
2280 	 void       *rsp_data)
2281 {
2282     int rv;
2283 
2284     if (!mc) {
2285 	/* MC data is still valid, but the MC is not good any more.
2286 	   We saved it in rsp_data. */
2287         mc = rsp_data;
2288 	i_ipmi_mc_startup_put(mc, "got_guid");
2289 	return; /* domain went away while processing. */
2290     }
2291 
2292     DEBUG_INFO(mc->sel_timer_info);
2293     if ((rsp->data[0] == 0) && (rsp->data_len >= 17)) {
2294 	/* We have a GUID, save it */
2295 	ipmi_mc_set_guid(mc, rsp->data+1);
2296     }
2297 
2298     if (((mc->devid.provides_device_sdrs) || (mc->treat_main_as_device_sdrs))
2299 	&& ipmi_option_SDRs(ipmi_mc_get_domain(mc)))
2300     {
2301 	DEBUG_INFO(mc->sel_timer_info);
2302 	rv = ipmi_mc_reread_sensors(mc, sensors_reread, mc);
2303 	if (rv) {
2304 	    DEBUG_INFO(mc->sel_timer_info);
2305 	    sensors_reread(mc, 0, NULL);
2306 	}
2307     } else {
2308 	DEBUG_INFO(mc->sel_timer_info);
2309 	sensors_reread(mc, 0, NULL);
2310     }
2311 }
2312 
2313 static void
mc_startup(ipmi_mc_t * mc)2314 mc_startup(ipmi_mc_t *mc)
2315 {
2316     ipmi_msg_t msg;
2317     int        rv = 0;
2318 
2319     DEBUG_INFO(mc->sel_timer_info);
2320     mc->sel_timer_info->processing = 1;
2321     mc->startup_count = 1;
2322     mc->startup_reported = 0;
2323 
2324     if (mc->devid.chassis_support) {
2325 	unsigned char instance = ipmi_mc_get_address(mc);
2326         if (instance == 0x20)
2327 	    instance = 1;
2328         rv = i_ipmi_chassis_create_controls(mc, instance);
2329 	if (rv) {
2330 	    ipmi_log(IPMI_LOG_SEVERE,
2331 		     "%smc.c(ipmi_mc_setup_new): "
2332 		     "Unable to create chassis controls.",
2333 		     mc->name);
2334 	    i_ipmi_mc_startup_put(mc, "mc_startup(2)");
2335 	    return;
2336 	}
2337     }
2338 
2339     /* FIXME - handle errors setting up OEM comain information.
2340        Handle errors so they get retried. */
2341 
2342     msg.netfn = IPMI_APP_NETFN;
2343     msg.cmd = IPMI_GET_DEVICE_GUID_CMD;
2344     msg.data_len = 0;
2345     msg.data = NULL;
2346 
2347     rv = ipmi_mc_send_command(mc, 0, &msg, got_guid, mc);
2348     if (rv) {
2349 	DEBUG_INFO(mc->sel_timer_info);
2350 	ipmi_log(IPMI_LOG_SEVERE,
2351 		 "%smc.c(ipmi_mc_setup_new): "
2352 		 "Unable to send get guid command.",
2353 		 mc->name);
2354 	i_ipmi_mc_startup_put(mc, "mc_startup");
2355     }
2356 }
2357 
2358 /***********************************************************************
2359  *
2360  * MC ID and state handling
2361  *
2362  **********************************************************************/
2363 
2364 void
i_ipmi_mc_use(ipmi_mc_t * mc)2365 i_ipmi_mc_use(ipmi_mc_t *mc)
2366 {
2367     CHECK_MC_LOCK(mc);
2368     mc->usercount++;
2369 }
2370 
2371 void
i_ipmi_mc_release(ipmi_mc_t * mc)2372 i_ipmi_mc_release(ipmi_mc_t *mc)
2373 {
2374     CHECK_MC_LOCK(mc);
2375     mc->usercount--;
2376 }
2377 
2378 /* Must be holding the domain->mc_lock to call these. */
2379 int
i_ipmi_mc_get(ipmi_mc_t * mc)2380 i_ipmi_mc_get(ipmi_mc_t *mc)
2381 {
2382     mc->usecount++;
2383     return 0;
2384 }
2385 
2386 static void
mc_apply_pending(ipmi_mc_t * mc)2387 mc_apply_pending(ipmi_mc_t *mc)
2388 {
2389     if (mc->pending_devid_data) {
2390 	mc->devid = mc->pending_devid;
2391 	mc->pending_devid_data = 0;
2392 	if (mc->pending_new_mc) {
2393 	    i_ipmi_mc_handle_new(mc);
2394 	    mc->pending_new_mc = 0;
2395 	}
2396     }
2397 }
2398 
2399 void
i_ipmi_mc_put(ipmi_mc_t * mc)2400 i_ipmi_mc_put(ipmi_mc_t *mc)
2401 {
2402     i_ipmi_domain_mc_lock(mc->domain);
2403     if (mc->usecount == 1) {
2404 	/* Make sure this code cannot run when we release the lock. */
2405 	mc->usecount++;
2406 	ipmi_lock(mc->lock);
2407 	switch (mc->state) {
2408 	case MC_INACTIVE_PEND_STARTUP:
2409 	    mc->state = MC_ACTIVE_IN_STARTUP;
2410 	    mc->active = 1;
2411 	    mc_apply_pending(mc);
2412 	    ipmi_unlock(mc->lock);
2413 	    i_ipmi_domain_mc_unlock(mc->domain);
2414 	    mc_startup(mc);
2415 	    call_active_handlers(mc);
2416 	    i_ipmi_domain_mc_lock(mc->domain);
2417 	    break;
2418 
2419 	case MC_ACTIVE_PEND_FULLY_UP:
2420 	    mc->state = MC_ACTIVE;
2421 	    ipmi_unlock(mc->lock);
2422 	    i_ipmi_domain_mc_unlock(mc->domain);
2423 	    call_fully_up_handlers(mc);
2424 	    i_ipmi_domain_mc_lock(mc->domain);
2425 	    break;
2426 
2427 	case MC_ACTIVE_PEND_CLEANUP:
2428 	    mc_stop_timer(mc);
2429 	    if (mc->startup_count > 0) {
2430 		ipmi_unlock(mc->lock);
2431 		goto still_in_startup;
2432 	    }
2433 	    mc->state = MC_INACTIVE;
2434 	    mc->active = 0;
2435 	    ipmi_unlock(mc->lock);
2436 	    i_ipmi_domain_mc_unlock(mc->domain);
2437 	    mc_cleanup(mc);
2438 	    call_active_handlers(mc);
2439 	    i_ipmi_domain_mc_lock(mc->domain);
2440 	    break;
2441 
2442 	case MC_ACTIVE_PEND_CLEANUP_PEND_STARTUP:
2443 	    mc_stop_timer(mc);
2444 	    if (mc->startup_count > 0) {
2445 		ipmi_unlock(mc->lock);
2446 		goto still_in_startup;
2447 	    }
2448 	    mc->state = MC_INACTIVE;
2449 	    mc->active = 0;
2450 	    ipmi_unlock(mc->lock);
2451 	    i_ipmi_domain_mc_unlock(mc->domain);
2452 	    mc_cleanup(mc);
2453 	    call_active_handlers(mc);
2454 	    i_ipmi_domain_mc_lock(mc->domain);
2455 	    ipmi_lock(mc->lock);
2456 	    mc->state = MC_ACTIVE_IN_STARTUP;
2457 	    mc->active = 1;
2458 	    mc_apply_pending(mc);
2459 	    ipmi_unlock(mc->lock);
2460 	    i_ipmi_domain_mc_unlock(mc->domain);
2461 	    mc_startup(mc);
2462 	    call_active_handlers(mc);
2463 	    i_ipmi_domain_mc_lock(mc->domain);
2464 	    break;
2465 
2466 	default:
2467 	    ipmi_unlock(mc->lock);
2468 	    break;
2469 	}
2470     still_in_startup:
2471 	mc->usecount--;
2472 
2473 	/* Only attempt the destroy if no one else has gotten the MC
2474 	   while we were holding it. */
2475 	if (mc->usecount == 1) {
2476 	    ipmi_lock(mc->lock);
2477 	    if (check_mc_destroy(mc))
2478 		return;
2479 	    ipmi_unlock(mc->lock);
2480 	}
2481     }
2482     mc->usecount--;
2483     i_ipmi_domain_mc_unlock(mc->domain);
2484 }
2485 
2486 int
i_ipmi_mc_handle_new(ipmi_mc_t * mc)2487 i_ipmi_mc_handle_new(ipmi_mc_t *mc)
2488 {
2489     ipmi_lock(mc->lock);
2490     switch (mc->state) {
2491     case MC_INACTIVE:
2492 	i_ipmi_get_domain_fully_up(mc->domain, "i_ipmi_mc_handle_new");
2493 	mc->state = MC_INACTIVE_PEND_STARTUP;
2494 	break;
2495     case MC_ACTIVE_PEND_CLEANUP:
2496 	i_ipmi_get_domain_fully_up(mc->domain, "i_ipmi_mc_handle_new");
2497 	mc->state = MC_ACTIVE_PEND_CLEANUP_PEND_STARTUP;
2498 	break;
2499     default:
2500 	break;
2501     }
2502     ipmi_unlock(mc->lock);
2503     return 0;
2504 }
2505 
2506 void
i_ipmi_cleanup_mc(ipmi_mc_t * mc)2507 i_ipmi_cleanup_mc(ipmi_mc_t *mc)
2508 {
2509     ipmi_lock(mc->lock);
2510     switch (mc->state) {
2511     case MC_INACTIVE_PEND_STARTUP:
2512 	i_ipmi_put_domain_fully_up(mc->domain, "i_ipmi_cleanup_mc");
2513 	mc->state = MC_INACTIVE;
2514 	break;
2515     case MC_ACTIVE_IN_STARTUP:
2516 	mc->state = MC_ACTIVE_PEND_CLEANUP;
2517 	ipmi_unlock(mc->lock);
2518 	ipmi_sdr_cleanout_timer(mc->sdrs);
2519 	/* FIXME - shut down startup code */
2520 	goto out;
2521     case MC_ACTIVE:
2522     case MC_ACTIVE_PEND_FULLY_UP:
2523 	mc->state = MC_ACTIVE_PEND_CLEANUP;
2524 	ipmi_unlock(mc->lock);
2525 	ipmi_sdr_cleanout_timer(mc->sdrs);
2526 	goto out;
2527     case MC_ACTIVE_PEND_CLEANUP_PEND_STARTUP:
2528 	i_ipmi_put_domain_fully_up(mc->domain, "i_ipmi_cleanup_mc");
2529 	mc->state = MC_ACTIVE_PEND_CLEANUP;
2530 	break;
2531     default:
2532 	break;
2533     }
2534     ipmi_unlock(mc->lock);
2535  out:
2536     return;
2537 }
2538 
2539 ipmi_mcid_t
ipmi_mc_convert_to_id(ipmi_mc_t * mc)2540 ipmi_mc_convert_to_id(ipmi_mc_t *mc)
2541 {
2542     ipmi_mcid_t val;
2543 
2544     CHECK_MC_LOCK(mc);
2545 
2546     val.domain_id = ipmi_domain_convert_to_id(mc->domain);
2547     val.mc_num = ipmi_mc_get_address(mc);
2548     val.channel = ipmi_mc_get_channel(mc);
2549     val.seq = mc->seq;
2550     return val;
2551 }
2552 
2553 typedef struct mc_ptr_info_s
2554 {
2555     int            err;
2556     int            cmp_seq;
2557     ipmi_mcid_t    id;
2558     ipmi_mc_ptr_cb handler;
2559     void           *cb_data;
2560 } mc_ptr_info_t;
2561 
2562 static void
mc_ptr_cb(ipmi_domain_t * domain,void * cb_data)2563 mc_ptr_cb(ipmi_domain_t *domain, void *cb_data)
2564 {
2565     mc_ptr_info_t *info = cb_data;
2566     char          addr_data[sizeof(ipmi_addr_t)];
2567     ipmi_addr_t   *addr = (ipmi_addr_t *) addr_data;
2568     unsigned int  addr_len;
2569     ipmi_mc_t     *mc;
2570 
2571     if (info->id.channel == IPMI_BMC_CHANNEL) {
2572 	ipmi_system_interface_addr_t *si = (void *) addr;
2573 
2574 	si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2575 	si->channel = info->id.mc_num;
2576 	si->lun = 0;
2577 	addr_len = sizeof(*si);
2578     } else {
2579 	ipmi_ipmb_addr_t *ipmb = (void *) addr;
2580 
2581 	ipmb->addr_type = IPMI_IPMB_ADDR_TYPE;
2582 	ipmb->channel = info->id.channel;
2583 	ipmb->slave_addr = info->id.mc_num;
2584 	ipmb->lun = 0;
2585 	addr_len = sizeof(*ipmb);
2586     }
2587 
2588     mc = i_ipmi_find_mc_by_addr(domain, addr, addr_len);
2589     if (mc) {
2590 	if (info->cmp_seq && (mc->seq != info->id.seq)) {
2591 	    i_ipmi_mc_put(mc);
2592 	    return;
2593 	}
2594 
2595 	info->err = 0;
2596 	info->handler(mc, info->cb_data);
2597 	i_ipmi_mc_put(mc);
2598     }
2599 }
2600 
2601 int
ipmi_mc_pointer_cb(ipmi_mcid_t id,ipmi_mc_ptr_cb handler,void * cb_data)2602 ipmi_mc_pointer_cb(ipmi_mcid_t id, ipmi_mc_ptr_cb handler, void *cb_data)
2603 {
2604     int           rv;
2605     mc_ptr_info_t info;
2606 
2607     info.err = EINVAL;
2608     info.id = id;
2609     info.handler = handler;
2610     info.cb_data = cb_data;
2611     info.cmp_seq = 1;
2612     rv = ipmi_domain_pointer_cb(id.domain_id, mc_ptr_cb, &info);
2613     if (!rv)
2614 	rv = info.err;
2615     return rv;
2616 }
2617 
2618 int
ipmi_mc_pointer_noseq_cb(ipmi_mcid_t id,ipmi_mc_ptr_cb handler,void * cb_data)2619 ipmi_mc_pointer_noseq_cb(ipmi_mcid_t    id,
2620 			 ipmi_mc_ptr_cb handler,
2621 			 void           *cb_data)
2622 {
2623     int           rv;
2624     mc_ptr_info_t info;
2625 
2626     info.err = EINVAL;
2627     info.id = id;
2628     info.handler = handler;
2629     info.cb_data = cb_data;
2630     info.cmp_seq = 0;
2631     rv = ipmi_domain_pointer_cb(id.domain_id, mc_ptr_cb, &info);
2632     if (!rv)
2633 	rv = info.err;
2634     return rv;
2635 }
2636 
2637 int
ipmi_cmp_mc_id_noseq(ipmi_mcid_t id1,ipmi_mcid_t id2)2638 ipmi_cmp_mc_id_noseq(ipmi_mcid_t id1, ipmi_mcid_t id2)
2639 {
2640     int d;
2641 
2642     d = ipmi_cmp_domain_id(id1.domain_id, id2.domain_id);
2643     if (d)
2644 	return d;
2645 
2646     if (id1.mc_num > id2.mc_num)
2647 	return 1;
2648     if (id1.mc_num < id2.mc_num)
2649 	return -1;
2650     if (id1.channel > id2.channel)
2651 	return 1;
2652     if (id1.channel < id2.channel)
2653 	return -1;
2654     return 0;
2655 }
2656 
2657 int
ipmi_cmp_mc_id(ipmi_mcid_t id1,ipmi_mcid_t id2)2658 ipmi_cmp_mc_id(ipmi_mcid_t id1, ipmi_mcid_t id2)
2659 {
2660     int d;
2661 
2662     d = ipmi_cmp_mc_id_noseq(id1, id2);
2663     if (d)
2664 	return d;
2665 
2666     if (id1.seq > id2.seq)
2667 	return 1;
2668     if (id1.seq < id2.seq)
2669 	return -1;
2670     return 0;
2671 }
2672 
2673 void
ipmi_mc_id_set_invalid(ipmi_mcid_t * id)2674 ipmi_mc_id_set_invalid(ipmi_mcid_t *id)
2675 {
2676     memset(id, 0, sizeof(*id));
2677 }
2678 
2679 int
ipmi_mc_id_is_invalid(ipmi_mcid_t * id)2680 ipmi_mc_id_is_invalid(ipmi_mcid_t *id)
2681 {
2682     return (id->domain_id.domain == NULL);
2683 }
2684 
2685 /***********************************************************************
2686  *
2687  * Handle sending commands and getting responses.
2688  *
2689  **********************************************************************/
2690 
2691 static int
addr_rsp_handler(ipmi_domain_t * domain,ipmi_msgi_t * rspi)2692 addr_rsp_handler(ipmi_domain_t *domain, ipmi_msgi_t *rspi)
2693 {
2694     ipmi_addr_t                *addr = &rspi->addr;
2695     unsigned int               addr_len = rspi->addr_len;
2696     ipmi_msg_t                 *msg = &rspi->msg;
2697     ipmi_mc_response_handler_t rsp_handler = rspi->data2;
2698     ipmi_mc_t                  *mc;
2699 
2700     if (rsp_handler) {
2701 	if (domain)
2702 	    mc = i_ipmi_find_mc_by_addr(domain, addr, addr_len);
2703 	else
2704 	    mc = NULL;
2705 	rsp_handler(mc, msg, rspi->data1);
2706 	if (mc)
2707 	    i_ipmi_mc_put(mc);
2708     }
2709     return IPMI_MSG_ITEM_NOT_USED;
2710 }
2711 
2712 int
ipmi_mc_send_command(ipmi_mc_t * mc,unsigned int lun,const ipmi_msg_t * msg,ipmi_mc_response_handler_t rsp_handler,void * rsp_data)2713 ipmi_mc_send_command(ipmi_mc_t                  *mc,
2714 		     unsigned int               lun,
2715 		     const ipmi_msg_t           *msg,
2716 		     ipmi_mc_response_handler_t rsp_handler,
2717 		     void                       *rsp_data)
2718 {
2719     int           rv;
2720     ipmi_addr_t   addr = mc->addr;
2721     ipmi_domain_t *domain;
2722 
2723     CHECK_MC_LOCK(mc);
2724 
2725     rv = ipmi_addr_set_lun(&addr, lun);
2726     if (rv)
2727 	return rv;
2728 
2729     domain = ipmi_mc_get_domain(mc);
2730 
2731     rv = ipmi_send_command_addr(domain,
2732 				&addr, mc->addr_len,
2733 				msg,
2734 				addr_rsp_handler,
2735 				rsp_data,
2736 				rsp_handler);
2737     return rv;
2738 }
2739 
2740 int
ipmi_mc_send_command_sideeff(ipmi_mc_t * mc,unsigned int lun,const ipmi_msg_t * msg,ipmi_mc_response_handler_t rsp_handler,void * rsp_data)2741 ipmi_mc_send_command_sideeff(ipmi_mc_t                  *mc,
2742 			     unsigned int               lun,
2743 			     const ipmi_msg_t           *msg,
2744 			     ipmi_mc_response_handler_t rsp_handler,
2745 			     void                       *rsp_data)
2746 {
2747     int           rv;
2748     ipmi_addr_t   addr = mc->addr;
2749     ipmi_domain_t *domain;
2750 
2751     CHECK_MC_LOCK(mc);
2752 
2753     rv = ipmi_addr_set_lun(&addr, lun);
2754     if (rv)
2755 	return rv;
2756 
2757     domain = ipmi_mc_get_domain(mc);
2758 
2759     rv = ipmi_send_command_addr_sideeff(domain,
2760 					&addr, mc->addr_len,
2761 					msg,
2762 					addr_rsp_handler,
2763 					rsp_data,
2764 					rsp_handler);
2765     return rv;
2766 }
2767 
2768 /***********************************************************************
2769  *
2770  * Handle global OEM callbacks for new MCs.
2771  *
2772  **********************************************************************/
2773 
2774 typedef struct oem_handlers_s {
2775     unsigned int                 manufacturer_id;
2776     unsigned int                 first_product_id;
2777     unsigned int                 last_product_id;
2778     ipmi_oem_mc_match_handler_cb handler;
2779     ipmi_oem_shutdown_handler_cb shutdown;
2780     void                         *cb_data;
2781 } oem_handlers_t;
2782 
2783 static locked_list_t *oem_handlers;
2784 
2785 int
ipmi_register_oem_handler(unsigned int manufacturer_id,unsigned int product_id,ipmi_oem_mc_match_handler_cb handler,ipmi_oem_shutdown_handler_cb shutdown,void * cb_data)2786 ipmi_register_oem_handler(unsigned int                 manufacturer_id,
2787 			  unsigned int                 product_id,
2788 			  ipmi_oem_mc_match_handler_cb handler,
2789 			  ipmi_oem_shutdown_handler_cb shutdown,
2790 			  void                         *cb_data)
2791 {
2792     oem_handlers_t *new_item;
2793     int            rv;
2794 
2795     /* This might be called before initialization, so be 100% sure. */
2796     rv = i_ipmi_mc_init();
2797     if (rv)
2798 	return rv;
2799 
2800     new_item = ipmi_mem_alloc(sizeof(*new_item));
2801     if (!new_item)
2802 	return ENOMEM;
2803 
2804     new_item->manufacturer_id = manufacturer_id;
2805     new_item->first_product_id = product_id;
2806     new_item->last_product_id = product_id;
2807     new_item->handler = handler;
2808     new_item->shutdown = shutdown;
2809     new_item->cb_data = cb_data;
2810 
2811     if (! locked_list_add(oem_handlers, new_item, NULL)) {
2812 	ipmi_mem_free(new_item);
2813 	return ENOMEM;
2814     }
2815 
2816     return 0;
2817 }
2818 
2819 int
ipmi_register_oem_handler_range(unsigned int manufacturer_id,unsigned int first_product_id,unsigned int last_product_id,ipmi_oem_mc_match_handler_cb handler,ipmi_oem_shutdown_handler_cb shutdown,void * cb_data)2820 ipmi_register_oem_handler_range(unsigned int                 manufacturer_id,
2821 				unsigned int                 first_product_id,
2822 				unsigned int                 last_product_id,
2823 				ipmi_oem_mc_match_handler_cb handler,
2824 				ipmi_oem_shutdown_handler_cb shutdown,
2825 				void                         *cb_data)
2826 {
2827     oem_handlers_t *new_item;
2828     int            rv;
2829 
2830     /* This might be called before initialization, so be 100% sure. */
2831     rv = i_ipmi_mc_init();
2832     if (rv)
2833 	return rv;
2834 
2835     new_item = ipmi_mem_alloc(sizeof(*new_item));
2836     if (!new_item)
2837 	return ENOMEM;
2838 
2839     new_item->manufacturer_id = manufacturer_id;
2840     new_item->first_product_id = first_product_id;
2841     new_item->last_product_id = last_product_id;
2842     new_item->handler = handler;
2843     new_item->shutdown = shutdown;
2844     new_item->cb_data = cb_data;
2845 
2846     if (! locked_list_add(oem_handlers, new_item, NULL)) {
2847 	ipmi_mem_free(new_item);
2848 	return ENOMEM;
2849     }
2850 
2851     return 0;
2852 }
2853 
2854 typedef struct handler_cmp_s
2855 {
2856     int          rv;
2857     unsigned int manufacturer_id;
2858     unsigned int first_product_id;
2859     unsigned int last_product_id;
2860     ipmi_mc_t    *mc;
2861 } handler_cmp_t;
2862 
2863 static int
oem_handler_cmp_dereg(void * cb_data,void * item1,void * item2)2864 oem_handler_cmp_dereg(void *cb_data, void *item1, void *item2)
2865 {
2866     oem_handlers_t *hndlr = item1;
2867     handler_cmp_t  *cmp = cb_data;
2868 
2869     if ((hndlr->manufacturer_id == cmp->manufacturer_id)
2870 	&& (hndlr->first_product_id <= cmp->first_product_id)
2871 	&& (hndlr->last_product_id >= cmp->last_product_id))
2872     {
2873 	cmp->rv = 0;
2874 	locked_list_remove(oem_handlers, item1, item2);
2875 	ipmi_mem_free(hndlr);
2876 	return LOCKED_LIST_ITER_STOP;
2877     }
2878     return LOCKED_LIST_ITER_CONTINUE;
2879 }
2880 
2881 int
ipmi_deregister_oem_handler(unsigned int manufacturer_id,unsigned int product_id)2882 ipmi_deregister_oem_handler(unsigned int manufacturer_id,
2883 			    unsigned int product_id)
2884 {
2885     handler_cmp_t  tmp;
2886 
2887     tmp.rv = ENOENT;
2888     tmp.manufacturer_id = manufacturer_id;
2889     tmp.first_product_id = product_id;
2890     tmp.last_product_id = product_id;
2891     locked_list_iterate(oem_handlers, oem_handler_cmp_dereg, &tmp);
2892     return tmp.rv;
2893 }
2894 
2895 int
ipmi_deregister_oem_handler_range(unsigned int manufacturer_id,unsigned int first_product_id,unsigned int last_product_id)2896 ipmi_deregister_oem_handler_range(unsigned int manufacturer_id,
2897 				  unsigned int first_product_id,
2898 				  unsigned int last_product_id)
2899 {
2900     handler_cmp_t  tmp;
2901 
2902     tmp.rv = ENOENT;
2903     tmp.manufacturer_id = manufacturer_id;
2904     tmp.first_product_id = first_product_id;
2905     tmp.last_product_id = last_product_id;
2906     locked_list_iterate(oem_handlers, oem_handler_cmp_dereg, &tmp);
2907     return tmp.rv;
2908 }
2909 
2910 static int
oem_handler_call(void * cb_data,void * item1,void * item2)2911 oem_handler_call(void *cb_data, void *item1, void *item2)
2912 {
2913     oem_handlers_t *hndlr = item1;
2914     handler_cmp_t  *cmp = cb_data;
2915 
2916     if ((hndlr->manufacturer_id == cmp->manufacturer_id)
2917 	&& (hndlr->first_product_id <= cmp->first_product_id)
2918 	&& (hndlr->last_product_id >= cmp->last_product_id))
2919     {
2920 	cmp->rv = hndlr->handler(cmp->mc, hndlr->cb_data);
2921 	return LOCKED_LIST_ITER_STOP;
2922     }
2923     return LOCKED_LIST_ITER_CONTINUE;
2924 }
2925 
2926 static int
check_oem_handlers(ipmi_mc_t * mc)2927 check_oem_handlers(ipmi_mc_t *mc)
2928 {
2929     handler_cmp_t  tmp;
2930 
2931     tmp.rv = 0;
2932     tmp.manufacturer_id = mc->pending_devid.manufacturer_id;
2933     tmp.first_product_id = mc->pending_devid.product_id;
2934     tmp.last_product_id = mc->pending_devid.product_id;
2935     tmp.mc = mc;
2936     locked_list_iterate(oem_handlers, oem_handler_call, &tmp);
2937     return tmp.rv;
2938 }
2939 
2940 
2941 /***********************************************************************
2942  *
2943  * device SDR handling.
2944  *
2945  **********************************************************************/
2946 
2947 typedef struct sdr_fetch_info_s
2948 {
2949     ipmi_domain_t    *domain;
2950     ipmi_mcid_t      source_mc; /* This is used to scan the SDRs. */
2951     ipmi_mc_done_cb  done;
2952     void             *done_data;
2953     int              err;
2954     int              changed;
2955     ipmi_sdr_info_t  *sdrs;
2956 } sdr_fetch_info_t;
2957 
2958 int
ipmi_mc_set_main_sdrs_as_device(ipmi_mc_t * mc)2959 ipmi_mc_set_main_sdrs_as_device(ipmi_mc_t *mc)
2960 {
2961     int             rv;
2962     ipmi_sdr_info_t *new_sdrs;
2963 
2964     rv = ipmi_sdr_info_alloc(ipmi_mc_get_domain(mc), mc, 0, 0, &new_sdrs);
2965     if (rv)
2966 	return rv;
2967 
2968     mc->treat_main_as_device_sdrs = 1;
2969     if (mc->sdrs)
2970 	ipmi_sdr_info_destroy(mc->sdrs, NULL, NULL);
2971     mc->sdrs = new_sdrs;
2972 
2973     /* Note that we don't reread the sensors, so this must be done
2974        before the sensor read operation. */
2975     return 0;
2976 }
2977 
2978 static void
sdr_reread_done(sdr_fetch_info_t * info,ipmi_mc_t * mc,int err)2979 sdr_reread_done(sdr_fetch_info_t *info, ipmi_mc_t *mc, int err)
2980 {
2981     if (info->done)
2982 	info->done(mc, err, info->done_data);
2983     ipmi_mem_free(info);
2984 }
2985 
2986 static void
sdrs_fetched_mc_cb(ipmi_mc_t * mc,void * cb_data)2987 sdrs_fetched_mc_cb(ipmi_mc_t *mc, void *cb_data)
2988 {
2989     sdr_fetch_info_t *info = (sdr_fetch_info_t *) cb_data;
2990     int              rv = 0;
2991     ipmi_domain_t    *domain = info->domain;
2992 
2993     if (info->err) {
2994 	sdr_reread_done(info, mc, info->err);
2995 	return;
2996     }
2997 
2998     if (mc->fixup_sdrs_handler)
2999 	mc->fixup_sdrs_handler(mc, info->sdrs, mc->fixup_sdrs_cb_data);
3000 
3001     if (info->changed) {
3002 	ipmi_entity_scan_sdrs(domain, mc,
3003 			      ipmi_domain_get_entities(domain),
3004 			      info->sdrs);
3005 	rv = ipmi_sensor_handle_sdrs(domain, mc, info->sdrs);
3006 
3007 	if (!rv)
3008 	    ipmi_detect_domain_presence_changes(domain, 0);
3009 
3010 	i_ipmi_entities_report_sdrs_read(ipmi_domain_get_entities(domain));
3011     }
3012 
3013     sdr_reread_done(info, mc, rv);
3014 }
3015 
3016 static void
sdrs_fetched(ipmi_sdr_info_t * sdrs,int err,int changed,unsigned int count,void * cb_data)3017 sdrs_fetched(ipmi_sdr_info_t *sdrs,
3018 	     int             err,
3019 	     int             changed,
3020 	     unsigned int    count,
3021 	     void            *cb_data)
3022 {
3023     sdr_fetch_info_t *info = (sdr_fetch_info_t *) cb_data;
3024     int              rv = 0;
3025 
3026     info->err = err;
3027     info->changed = changed;
3028     info->sdrs = sdrs;
3029     rv = ipmi_mc_pointer_cb(info->source_mc, sdrs_fetched_mc_cb, info);
3030     if (rv)
3031 	sdr_reread_done(info, NULL, ECANCELED);
3032 }
3033 
3034 int
ipmi_mc_reread_sensors(ipmi_mc_t * mc,ipmi_mc_done_cb done,void * done_data)3035 ipmi_mc_reread_sensors(ipmi_mc_t       *mc,
3036 		       ipmi_mc_done_cb done,
3037 		       void            *done_data)
3038 {
3039     sdr_fetch_info_t   *info;
3040     int                rv = 0;
3041 
3042     CHECK_MC_LOCK(mc);
3043 
3044     info = ipmi_mem_alloc(sizeof(*info));
3045     if (!info)
3046 	return ENOMEM;
3047 
3048     info->source_mc = ipmi_mc_convert_to_id(mc);
3049     info->domain = ipmi_mc_get_domain(mc);
3050     info->done = done;
3051     info->done_data = done_data;
3052 
3053     ipmi_lock(mc->lock);
3054     if (! mc_op_ready(mc)) {
3055 	ipmi_unlock(mc->lock);
3056 	rv = ECANCELED;
3057     } else {
3058 	ipmi_unlock(mc->lock);
3059 	rv = ipmi_sdr_fetch(ipmi_mc_get_sdrs(mc), sdrs_fetched, info);
3060     }
3061     if (rv)
3062 	ipmi_mem_free(info);
3063 
3064     return rv;
3065 }
3066 
3067 /***********************************************************************
3068  *
3069  * Checking for the validity and currentness of MC data.
3070  *
3071  **********************************************************************/
3072 
3073 /* Check the MC, we reread the SDRs and check the event receiver. */
3074 void
i_ipmi_mc_check_mc(ipmi_mc_t * mc)3075 i_ipmi_mc_check_mc(ipmi_mc_t *mc)
3076 {
3077     if ((mc->devid.provides_device_sdrs) || (mc->treat_main_as_device_sdrs))
3078 	ipmi_mc_reread_sensors(mc, NULL, NULL);
3079     i_ipmi_mc_check_event_rcvr(mc);
3080 }
3081 
3082 
3083 
3084 /***********************************************************************
3085  *
3086  * Handle the boatloads of information from a get device id.
3087  *
3088  **********************************************************************/
3089 
3090 int
i_ipmi_mc_get_device_id_data_from_rsp(ipmi_mc_t * mc,ipmi_msg_t * rsp)3091 i_ipmi_mc_get_device_id_data_from_rsp(ipmi_mc_t *mc, ipmi_msg_t *rsp)
3092 {
3093     unsigned char *rsp_data = rsp->data;
3094     int           rv = 0;
3095 
3096     if (rsp_data[0] != 0) {
3097 	return IPMI_IPMI_ERR_VAL(rsp_data[0]);
3098     }
3099 
3100     if (rsp->data_len < 12) {
3101 	if ((rsp->data[0] == 0) && (rsp->data_len >= 6)) {
3102 	    int major_version = rsp->data[5] & 0xf;
3103 	    int minor_version = (rsp->data[5] >> 4) & 0xf;
3104 
3105 	    if (major_version < 1) {
3106 		ipmi_log(IPMI_LOG_ERR_INFO,
3107 			 "%smc.c(i_ipmi_mc_get_device_id_data_from_rsp): "
3108 			 "IPMI version of the MC at address 0x%2.2x is %d.%d,"
3109 			 " which is older than OpenIPMI supports",
3110 			 mc->name, ipmi_addr_get_slave_addr(&mc->addr),
3111 			 major_version, minor_version);
3112 		return EINVAL;
3113 	    }
3114 	}
3115 	ipmi_log(IPMI_LOG_ERR_INFO,
3116 		 "%smc.c(i_ipmi_mc_get_device_id_data_from_rsp): "
3117 		 "Invalid return from IPMI Get Device ID from address 0x%2.2x,"
3118 		 " something is seriously wrong with the MC, length is %d",
3119 		 mc->name, ipmi_addr_get_slave_addr(&mc->addr), rsp->data_len);
3120 	return EINVAL;
3121     }
3122 
3123     ipmi_lock(mc->lock);
3124 
3125     /* Pend these to be installed when nobody is using them. */
3126     mc->pending_devid.device_id = rsp_data[1];
3127     mc->pending_devid.device_revision = rsp_data[2] & 0xf;
3128     mc->pending_devid.provides_device_sdrs = (rsp_data[2] & 0x80) == 0x80;
3129     mc->pending_devid.device_available = (rsp_data[3] & 0x80) == 0x80;
3130     mc->pending_devid.major_fw_revision = rsp_data[3] & 0x7f;
3131     mc->pending_devid.minor_fw_revision = rsp_data[4];
3132     mc->pending_devid.major_version = rsp_data[5] & 0xf;
3133     mc->pending_devid.minor_version = (rsp_data[5] >> 4) & 0xf;
3134     mc->pending_devid.chassis_support = (rsp_data[6] & 0x80) == 0x80;
3135     mc->pending_devid.bridge_support = (rsp_data[6] & 0x40) == 0x40;
3136     mc->pending_devid.IPMB_event_generator_support
3137 	= (rsp_data[6] & 0x20) == 0x20;
3138     mc->pending_devid.IPMB_event_receiver_support
3139 	= (rsp_data[6] & 0x10) == 0x10;
3140     mc->pending_devid.FRU_inventory_support = (rsp_data[6] & 0x08) == 0x08;
3141     mc->pending_devid.SEL_device_support = (rsp_data[6] & 0x04) == 0x04;
3142     mc->pending_devid.SDR_repository_support = (rsp_data[6] & 0x02) == 0x02;
3143     mc->pending_devid.sensor_device_support = (rsp_data[6] & 0x01) == 0x01;
3144     mc->pending_devid.manufacturer_id = (rsp_data[7]
3145 				 | (rsp_data[8] << 8)
3146 				 | (rsp_data[9] << 16));
3147     mc->pending_devid.product_id = rsp_data[10] | (rsp_data[11] << 8);
3148 
3149     if (rsp->data_len < 16) {
3150 	/* no aux revision. */
3151 	memset(mc->pending_devid.aux_fw_revision, 0, 4);
3152     } else {
3153 	memcpy(mc->pending_devid.aux_fw_revision, rsp_data + 12, 4);
3154     }
3155 
3156     /* Copy these to the version we use for comparison. */
3157     mc->real_devid = mc->pending_devid;
3158 
3159     /* Either copy it or mark it to be copied. */
3160     if (mc->usecount == 1) {
3161 	mc->devid = mc->pending_devid;
3162 	mc->pending_devid_data = 0;
3163 	mc->pending_new_mc = 0;
3164 	ipmi_unlock(mc->lock);
3165 
3166 	/* OEM handlers set the pending data. */
3167 	rv = check_oem_handlers(mc);
3168     } else {
3169 	mc->pending_devid_data = 1;
3170 	mc->pending_new_mc = 1;
3171 	rv = EAGAIN; /* Tell the user that they must call the OEM
3172 			handlers check later when the MC is
3173 			released. */
3174 	ipmi_unlock(mc->lock);
3175     }
3176 
3177     return rv;
3178 }
3179 
3180 int
i_ipmi_mc_device_data_compares(ipmi_mc_t * mc,ipmi_msg_t * rsp)3181 i_ipmi_mc_device_data_compares(ipmi_mc_t  *mc,
3182 			       ipmi_msg_t *rsp)
3183 {
3184     unsigned char *rsp_data = rsp->data;
3185 
3186     if (rsp->data_len < 12) {
3187 	return EINVAL;
3188     }
3189 
3190     if (mc->real_devid.device_id != rsp_data[1])
3191 	return 0;
3192 
3193     if (mc->real_devid.device_revision != (rsp_data[2] & 0xf))
3194 	return 0;
3195 
3196     if (mc->real_devid.provides_device_sdrs != ((rsp_data[2] & 0x80) == 0x80))
3197 	return 0;
3198 
3199     if (mc->real_devid.device_available != ((rsp_data[3] & 0x80) == 0x80))
3200 	return 0;
3201 
3202     if (mc->real_devid.major_fw_revision != (rsp_data[3] & 0x7f))
3203 	return 0;
3204 
3205     if (mc->real_devid.minor_fw_revision != (rsp_data[4]))
3206 	return 0;
3207 
3208     if (mc->real_devid.major_version != (rsp_data[5] & 0xf))
3209 	return 0;
3210 
3211     if (mc->real_devid.minor_version != ((rsp_data[5] >> 4) & 0xf))
3212 	return 0;
3213 
3214     if (mc->real_devid.chassis_support != ((rsp_data[6] & 0x80) == 0x80))
3215 	return 0;
3216 
3217     if (mc->real_devid.bridge_support != ((rsp_data[6] & 0x40) == 0x40))
3218 	return 0;
3219 
3220     if (mc->real_devid.IPMB_event_generator_support
3221 	!= ((rsp_data[6] & 0x20)==0x20))
3222 	return 0;
3223 
3224     if (mc->real_devid.IPMB_event_receiver_support
3225 	!= ((rsp_data[6] & 0x10) == 0x10))
3226 	return 0;
3227 
3228     if (mc->real_devid.FRU_inventory_support != ((rsp_data[6] & 0x08) == 0x08))
3229 	return 0;
3230 
3231     if (mc->real_devid.SEL_device_support != ((rsp_data[6] & 0x04) == 0x04))
3232 	return 0;
3233 
3234     if (mc->real_devid.SDR_repository_support
3235 	!= ((rsp_data[6] & 0x02) == 0x02))
3236 	return 0;
3237 
3238     if (mc->real_devid.sensor_device_support != ((rsp_data[6] & 0x01) == 0x01))
3239 	return 0;
3240 
3241     if (mc->real_devid.manufacturer_id != (uint32_t) (rsp_data[7]
3242 						      | (rsp_data[8] << 8)
3243 						      | (rsp_data[9] << 16)))
3244 	return 0;
3245 
3246     if (mc->real_devid.product_id != (rsp_data[10] | (rsp_data[11] << 8)))
3247 	return 0;
3248 
3249     if (rsp->data_len < 16) {
3250 	/* no aux revision, it should be all zeros. */
3251 	if ((mc->real_devid.aux_fw_revision[0] != 0)
3252 	    || (mc->real_devid.aux_fw_revision[1] != 0)
3253 	    || (mc->real_devid.aux_fw_revision[2] != 0)
3254 	    || (mc->real_devid.aux_fw_revision[3] != 0))
3255 	    return 0;
3256     } else {
3257 	if (memcmp(mc->real_devid.aux_fw_revision, rsp_data + 12, 4) != 0)
3258 	    return 0;
3259     }
3260 
3261     /* Everything's the same. */
3262     return 1;
3263 }
3264 
3265 /***********************************************************************
3266  *
3267  * Get/set the information for an MC.
3268  *
3269  **********************************************************************/
3270 
3271 void
i_ipmi_mc_get_sdr_sensors(ipmi_mc_t * mc,ipmi_sensor_t *** sensors,unsigned int * count)3272 i_ipmi_mc_get_sdr_sensors(ipmi_mc_t     *mc,
3273 			  ipmi_sensor_t ***sensors,
3274 			  unsigned int  *count)
3275 {
3276     *sensors = mc->sensors_in_my_sdr;
3277     *count = mc->sensors_in_my_sdr_count;
3278 }
3279 
3280 void
i_ipmi_mc_set_sdr_sensors(ipmi_mc_t * mc,ipmi_sensor_t ** sensors,unsigned int count)3281 i_ipmi_mc_set_sdr_sensors(ipmi_mc_t     *mc,
3282 			  ipmi_sensor_t **sensors,
3283 			  unsigned int  count)
3284 {
3285     mc->sensors_in_my_sdr = sensors;
3286     mc->sensors_in_my_sdr_count = count;
3287 }
3288 
3289 void *
i_ipmi_mc_get_sdr_entities(ipmi_mc_t * mc)3290 i_ipmi_mc_get_sdr_entities(ipmi_mc_t *mc)
3291 {
3292     return mc->entities_in_my_sdr;
3293 }
3294 
3295 void
i_ipmi_mc_set_sdr_entities(ipmi_mc_t * mc,void * entities)3296 i_ipmi_mc_set_sdr_entities(ipmi_mc_t *mc, void *entities)
3297 {
3298     mc->entities_in_my_sdr = entities;
3299 }
3300 
3301 int
ipmi_mc_provides_device_sdrs(ipmi_mc_t * mc)3302 ipmi_mc_provides_device_sdrs(ipmi_mc_t *mc)
3303 {
3304     CHECK_MC_LOCK(mc);
3305     return mc->devid.provides_device_sdrs;
3306 }
3307 
3308 int
ipmi_mc_set_sdrs_first_read_handler(ipmi_mc_t * mc,ipmi_mc_ptr_cb handler,void * cb_data)3309 ipmi_mc_set_sdrs_first_read_handler(ipmi_mc_t      *mc,
3310 				    ipmi_mc_ptr_cb handler,
3311 				    void           *cb_data)
3312 {
3313     CHECK_MC_LOCK(mc);
3314     ipmi_lock(mc->lock);
3315     mc->sdrs_first_read_handler = handler;
3316     mc->sdrs_first_read_cb_data = cb_data;
3317     ipmi_unlock(mc->lock);
3318     return 0;
3319 }
3320 
ipmi_mc_set_sels_first_read_handler(ipmi_mc_t * mc,ipmi_mc_ptr_cb handler,void * cb_data)3321 int ipmi_mc_set_sels_first_read_handler(ipmi_mc_t      *mc,
3322 					ipmi_mc_ptr_cb handler,
3323 					void           *cb_data)
3324 {
3325     CHECK_MC_LOCK(mc);
3326     ipmi_lock(mc->sel_timer_info->lock);
3327     mc->sel_timer_info->sels_first_read_handler = handler;
3328     mc->sel_timer_info->sels_first_read_cb_data = cb_data;
3329     ipmi_unlock(mc->sel_timer_info->lock);
3330     return 0;
3331 }
3332 
3333 static int
call_active_handler(void * cb_data,void * item1,void * item2)3334 call_active_handler(void *cb_data, void *item1, void *item2)
3335 {
3336     ipmi_mc_active_cb handler = item1;
3337     ipmi_mc_t         *mc = cb_data;
3338 
3339     handler(mc, mc->active, item2);
3340     return LOCKED_LIST_ITER_CONTINUE;
3341 }
3342 
3343 static void
call_active_handlers(ipmi_mc_t * mc)3344 call_active_handlers(ipmi_mc_t *mc)
3345 {
3346     locked_list_iterate(mc->active_handlers, call_active_handler, mc);
3347 }
3348 
3349 int
ipmi_mc_add_active_handler(ipmi_mc_t * mc,ipmi_mc_active_cb handler,void * cb_data)3350 ipmi_mc_add_active_handler(ipmi_mc_t         *mc,
3351 			   ipmi_mc_active_cb handler,
3352 			   void              *cb_data)
3353 {
3354     CHECK_MC_LOCK(mc);
3355 
3356     if (locked_list_add(mc->active_handlers, handler, cb_data))
3357 	return 0;
3358     else
3359 	return ENOMEM;
3360 }
3361 
3362 int
ipmi_mc_remove_active_handler(ipmi_mc_t * mc,ipmi_mc_active_cb handler,void * cb_data)3363 ipmi_mc_remove_active_handler(ipmi_mc_t         *mc,
3364 			      ipmi_mc_active_cb handler,
3365 			      void              *cb_data)
3366 {
3367     CHECK_MC_LOCK(mc);
3368 
3369     if (locked_list_remove(mc->active_handlers, handler, cb_data))
3370 	return 0;
3371     else
3372 	return EINVAL;
3373 }
3374 
3375 int
ipmi_mc_add_active_handler_cl(ipmi_mc_t * mc,ipmi_mc_active_cl_cb handler,void * cb_data)3376 ipmi_mc_add_active_handler_cl(ipmi_mc_t            *mc,
3377 			      ipmi_mc_active_cl_cb handler,
3378 			      void                 *cb_data)
3379 {
3380     CHECK_MC_LOCK(mc);
3381 
3382     if (locked_list_add(mc->active_handlers_cl, handler, cb_data))
3383 	return 0;
3384     else
3385 	return ENOMEM;
3386 }
3387 
3388 int
ipmi_mc_remove_active_handler_cl(ipmi_mc_t * mc,ipmi_mc_active_cl_cb handler,void * cb_data)3389 ipmi_mc_remove_active_handler_cl(ipmi_mc_t            *mc,
3390 				 ipmi_mc_active_cl_cb handler,
3391 				 void                 *cb_data)
3392 {
3393     CHECK_MC_LOCK(mc);
3394 
3395     if (locked_list_remove(mc->active_handlers_cl, handler, cb_data))
3396 	return 0;
3397     else
3398 	return EINVAL;
3399 }
3400 
3401 int
ipmi_mc_is_active(ipmi_mc_t * mc)3402 ipmi_mc_is_active(ipmi_mc_t *mc)
3403 {
3404     return mc->active;
3405 }
3406 
3407 void
i_ipmi_mc_force_active(ipmi_mc_t * mc,int val)3408 i_ipmi_mc_force_active(ipmi_mc_t *mc, int val)
3409 {
3410     ipmi_lock(mc->lock);
3411     mc->active = val;
3412     ipmi_unlock(mc->lock);
3413 }
3414 
3415 static int
call_fully_up_handler(void * cb_data,void * item1,void * item2)3416 call_fully_up_handler(void *cb_data, void *item1, void *item2)
3417 {
3418     ipmi_mc_ptr_cb handler = item1;
3419     ipmi_mc_t      *mc = cb_data;
3420 
3421     handler(mc, item2);
3422     return LOCKED_LIST_ITER_CONTINUE;
3423 }
3424 
3425 static void
call_fully_up_handlers(ipmi_mc_t * mc)3426 call_fully_up_handlers(ipmi_mc_t *mc)
3427 {
3428     locked_list_iterate(mc->fully_up_handlers, call_fully_up_handler, mc);
3429 }
3430 
3431 int
ipmi_mc_add_fully_up_handler(ipmi_mc_t * mc,ipmi_mc_ptr_cb handler,void * cb_data)3432 ipmi_mc_add_fully_up_handler(ipmi_mc_t      *mc,
3433 			     ipmi_mc_ptr_cb handler,
3434 			     void           *cb_data)
3435 {
3436     CHECK_MC_LOCK(mc);
3437 
3438     if (locked_list_add(mc->fully_up_handlers, handler, cb_data))
3439 	return 0;
3440     else
3441 	return ENOMEM;
3442 }
3443 
3444 int
ipmi_mc_remove_fully_up_handler(ipmi_mc_t * mc,ipmi_mc_ptr_cb handler,void * cb_data)3445 ipmi_mc_remove_fully_up_handler(ipmi_mc_t      *mc,
3446 				ipmi_mc_ptr_cb handler,
3447 				void           *cb_data)
3448 {
3449     CHECK_MC_LOCK(mc);
3450 
3451     if (locked_list_remove(mc->fully_up_handlers, handler, cb_data))
3452 	return 0;
3453     else
3454 	return EINVAL;
3455 }
3456 
3457 int
ipmi_mc_add_fully_up_handler_cl(ipmi_mc_t * mc,ipmi_mc_fully_up_cl_cb handler,void * cb_data)3458 ipmi_mc_add_fully_up_handler_cl(ipmi_mc_t              *mc,
3459 				ipmi_mc_fully_up_cl_cb handler,
3460 				void                   *cb_data)
3461 {
3462     CHECK_MC_LOCK(mc);
3463 
3464     if (locked_list_add(mc->fully_up_handlers_cl, handler, cb_data))
3465 	return 0;
3466     else
3467 	return ENOMEM;
3468 }
3469 
3470 int
ipmi_mc_remove_fully_up_handler_cl(ipmi_mc_t * mc,ipmi_mc_fully_up_cl_cb handler,void * cb_data)3471 ipmi_mc_remove_fully_up_handler_cl(ipmi_mc_t              *mc,
3472 				   ipmi_mc_fully_up_cl_cb handler,
3473 				   void                   *cb_data)
3474 {
3475     CHECK_MC_LOCK(mc);
3476 
3477     if (locked_list_remove(mc->fully_up_handlers_cl, handler, cb_data))
3478 	return 0;
3479     else
3480 	return EINVAL;
3481 }
3482 
3483 void
ipmi_mc_set_provides_device_sdrs(ipmi_mc_t * mc,int val)3484 ipmi_mc_set_provides_device_sdrs(ipmi_mc_t *mc, int val)
3485 {
3486     CHECK_MC_LOCK(mc);
3487     ipmi_lock(mc->lock);
3488     mc->pending_devid.provides_device_sdrs = val;
3489     mc->pending_devid_data = 1;
3490     ipmi_unlock(mc->lock);
3491 }
3492 
3493 int
ipmi_mc_device_available(ipmi_mc_t * mc)3494 ipmi_mc_device_available(ipmi_mc_t *mc)
3495 {
3496     CHECK_MC_LOCK(mc);
3497     return mc->devid.device_available;
3498 }
3499 
3500 void
ipmi_mc_set_device_available(ipmi_mc_t * mc,int val)3501 ipmi_mc_set_device_available(ipmi_mc_t *mc, int val)
3502 {
3503     CHECK_MC_LOCK(mc);
3504     ipmi_lock(mc->lock);
3505     mc->pending_devid.device_available = val;
3506     mc->pending_devid_data = 1;
3507     ipmi_unlock(mc->lock);
3508 }
3509 
3510 int
ipmi_mc_chassis_support(ipmi_mc_t * mc)3511 ipmi_mc_chassis_support(ipmi_mc_t *mc)
3512 {
3513     CHECK_MC_LOCK(mc);
3514     return mc->devid.chassis_support;
3515 }
3516 
3517 void
ipmi_mc_set_chassis_support(ipmi_mc_t * mc,int val)3518 ipmi_mc_set_chassis_support(ipmi_mc_t *mc, int val)
3519 {
3520     CHECK_MC_LOCK(mc);
3521     ipmi_lock(mc->lock);
3522     mc->pending_devid.chassis_support = val;
3523     mc->pending_devid_data = 1;
3524     ipmi_unlock(mc->lock);
3525 }
3526 
3527 int
ipmi_mc_bridge_support(ipmi_mc_t * mc)3528 ipmi_mc_bridge_support(ipmi_mc_t *mc)
3529 {
3530     CHECK_MC_LOCK(mc);
3531     return mc->devid.bridge_support;
3532 }
3533 
3534 void
ipmi_mc_set_bridge_support(ipmi_mc_t * mc,int val)3535 ipmi_mc_set_bridge_support(ipmi_mc_t *mc, int val)
3536 {
3537     CHECK_MC_LOCK(mc);
3538     ipmi_lock(mc->lock);
3539     mc->pending_devid.bridge_support = val;
3540     mc->pending_devid_data = 1;
3541     ipmi_unlock(mc->lock);
3542 }
3543 
3544 int
ipmi_mc_ipmb_event_generator_support(ipmi_mc_t * mc)3545 ipmi_mc_ipmb_event_generator_support(ipmi_mc_t *mc)
3546 {
3547     CHECK_MC_LOCK(mc);
3548     return mc->devid.IPMB_event_generator_support;
3549 }
3550 
3551 void
ipmi_mc_set_ipmb_event_generator_support(ipmi_mc_t * mc,int val)3552 ipmi_mc_set_ipmb_event_generator_support(ipmi_mc_t *mc, int val)
3553 {
3554     CHECK_MC_LOCK(mc);
3555     ipmi_lock(mc->lock);
3556     mc->pending_devid.IPMB_event_generator_support = val;
3557     mc->pending_devid_data = 1;
3558     ipmi_unlock(mc->lock);
3559 }
3560 
3561 int
ipmi_mc_ipmb_event_receiver_support(ipmi_mc_t * mc)3562 ipmi_mc_ipmb_event_receiver_support(ipmi_mc_t *mc)
3563 {
3564     CHECK_MC_LOCK(mc);
3565     return mc->devid.IPMB_event_receiver_support;
3566 }
3567 
3568 void
ipmi_mc_set_ipmb_event_receiver_support(ipmi_mc_t * mc,int val)3569 ipmi_mc_set_ipmb_event_receiver_support(ipmi_mc_t *mc, int val)
3570 {
3571     CHECK_MC_LOCK(mc);
3572     ipmi_lock(mc->lock);
3573     mc->pending_devid.IPMB_event_receiver_support = val;
3574     mc->pending_devid_data = 1;
3575     ipmi_unlock(mc->lock);
3576 }
3577 
3578 int
ipmi_mc_fru_inventory_support(ipmi_mc_t * mc)3579 ipmi_mc_fru_inventory_support(ipmi_mc_t *mc)
3580 {
3581     CHECK_MC_LOCK(mc);
3582     return mc->devid.FRU_inventory_support;
3583 }
3584 
3585 void
ipmi_mc_set_fru_inventory_support(ipmi_mc_t * mc,int val)3586 ipmi_mc_set_fru_inventory_support(ipmi_mc_t *mc, int val)
3587 {
3588     CHECK_MC_LOCK(mc);
3589     ipmi_lock(mc->lock);
3590     mc->pending_devid.FRU_inventory_support = val;
3591     mc->pending_devid_data = 1;
3592     ipmi_unlock(mc->lock);
3593 }
3594 
3595 int
ipmi_mc_sel_device_support(ipmi_mc_t * mc)3596 ipmi_mc_sel_device_support(ipmi_mc_t *mc)
3597 {
3598     CHECK_MC_LOCK(mc);
3599     return mc->devid.SEL_device_support;
3600 }
3601 
3602 void
ipmi_mc_set_sel_device_support(ipmi_mc_t * mc,int val)3603 ipmi_mc_set_sel_device_support(ipmi_mc_t *mc, int val)
3604 {
3605     CHECK_MC_LOCK(mc);
3606     ipmi_lock(mc->lock);
3607     mc->pending_devid.SEL_device_support = val;
3608     mc->pending_devid_data = 1;
3609     ipmi_unlock(mc->lock);
3610 }
3611 
3612 int
ipmi_mc_sdr_repository_support(ipmi_mc_t * mc)3613 ipmi_mc_sdr_repository_support(ipmi_mc_t *mc)
3614 {
3615     CHECK_MC_LOCK(mc);
3616     return mc->devid.SDR_repository_support;
3617 }
3618 
3619 void
ipmi_mc_set_sdr_repository_support(ipmi_mc_t * mc,int val)3620 ipmi_mc_set_sdr_repository_support(ipmi_mc_t *mc, int val)
3621 {
3622     CHECK_MC_LOCK(mc);
3623     ipmi_lock(mc->lock);
3624     mc->pending_devid.SDR_repository_support = val;
3625     mc->pending_devid_data = 1;
3626     ipmi_unlock(mc->lock);
3627 }
3628 
3629 int
ipmi_mc_sensor_device_support(ipmi_mc_t * mc)3630 ipmi_mc_sensor_device_support(ipmi_mc_t *mc)
3631 {
3632     CHECK_MC_LOCK(mc);
3633     return mc->devid.sensor_device_support;
3634 }
3635 
3636 void
ipmi_mc_set_sensor_device_support(ipmi_mc_t * mc,int val)3637 ipmi_mc_set_sensor_device_support(ipmi_mc_t *mc, int val)
3638 {
3639     CHECK_MC_LOCK(mc);
3640     ipmi_lock(mc->lock);
3641     mc->pending_devid.sensor_device_support = val;
3642     mc->pending_devid_data = 1;
3643     ipmi_unlock(mc->lock);
3644 }
3645 
3646 int
ipmi_mc_device_id(ipmi_mc_t * mc)3647 ipmi_mc_device_id(ipmi_mc_t *mc)
3648 {
3649     CHECK_MC_LOCK(mc);
3650     return mc->devid.device_id;
3651 }
3652 
3653 int
ipmi_mc_device_revision(ipmi_mc_t * mc)3654 ipmi_mc_device_revision(ipmi_mc_t *mc)
3655 {
3656     CHECK_MC_LOCK(mc);
3657     return mc->devid.device_revision;
3658 }
3659 
3660 int
ipmi_mc_major_fw_revision(ipmi_mc_t * mc)3661 ipmi_mc_major_fw_revision(ipmi_mc_t *mc)
3662 {
3663     CHECK_MC_LOCK(mc);
3664     return mc->devid.major_fw_revision;
3665 }
3666 
3667 int
ipmi_mc_minor_fw_revision(ipmi_mc_t * mc)3668 ipmi_mc_minor_fw_revision(ipmi_mc_t *mc)
3669 {
3670     CHECK_MC_LOCK(mc);
3671     return mc->devid.minor_fw_revision;
3672 }
3673 
3674 int
ipmi_mc_major_version(ipmi_mc_t * mc)3675 ipmi_mc_major_version(ipmi_mc_t *mc)
3676 {
3677     CHECK_MC_LOCK(mc);
3678     return mc->devid.major_version;
3679 }
3680 
3681 int
ipmi_mc_minor_version(ipmi_mc_t * mc)3682 ipmi_mc_minor_version(ipmi_mc_t *mc)
3683 {
3684     CHECK_MC_LOCK(mc);
3685     return mc->devid.minor_version;
3686 }
3687 
3688 int
ipmi_mc_manufacturer_id(ipmi_mc_t * mc)3689 ipmi_mc_manufacturer_id(ipmi_mc_t *mc)
3690 {
3691     CHECK_MC_LOCK(mc);
3692     return mc->devid.manufacturer_id;
3693 }
3694 
3695 int
ipmi_mc_product_id(ipmi_mc_t * mc)3696 ipmi_mc_product_id(ipmi_mc_t *mc)
3697 {
3698     CHECK_MC_LOCK(mc);
3699     return mc->devid.product_id;
3700 }
3701 
3702 void
ipmi_mc_aux_fw_revision(ipmi_mc_t * mc,unsigned char val[])3703 ipmi_mc_aux_fw_revision(ipmi_mc_t *mc, unsigned char val[])
3704 {
3705     CHECK_MC_LOCK(mc);
3706     memcpy(val, mc->devid.aux_fw_revision, sizeof(mc->devid.aux_fw_revision));
3707 }
3708 
3709 int
ipmi_mc_get_guid(ipmi_mc_t * mc,unsigned char * guid)3710 ipmi_mc_get_guid(ipmi_mc_t *mc, unsigned char *guid)
3711 {
3712     CHECK_MC_LOCK(mc);
3713     if (!mc->guid_set)
3714 	return ENOSYS;
3715     memcpy(guid, mc->guid, 16);
3716     return 0;
3717 }
3718 
3719 void
ipmi_mc_set_guid(ipmi_mc_t * mc,unsigned char * data)3720 ipmi_mc_set_guid(ipmi_mc_t *mc, unsigned char *data)
3721 {
3722     memcpy(mc->guid, data, 16);
3723     mc->guid_set = 1;
3724 }
3725 
3726 void
ipmi_mc_set_oem_data(ipmi_mc_t * mc,void * data)3727 ipmi_mc_set_oem_data(ipmi_mc_t *mc, void *data)
3728 {
3729     CHECK_MC_LOCK(mc);
3730     mc->oem_data = data;
3731 }
3732 
3733 void *
ipmi_mc_get_oem_data(ipmi_mc_t * mc)3734 ipmi_mc_get_oem_data(ipmi_mc_t *mc)
3735 {
3736     CHECK_MC_LOCK(mc);
3737     return mc->oem_data;
3738 }
3739 
3740 ipmi_sensor_info_t *
i_ipmi_mc_get_sensors(ipmi_mc_t * mc)3741 i_ipmi_mc_get_sensors(ipmi_mc_t *mc)
3742 {
3743     CHECK_MC_LOCK(mc);
3744     return mc->sensors;
3745 }
3746 
3747 ipmi_control_info_t *
i_ipmi_mc_get_controls(ipmi_mc_t * mc)3748 i_ipmi_mc_get_controls(ipmi_mc_t *mc)
3749 {
3750     CHECK_MC_LOCK(mc);
3751     return mc->controls;
3752 }
3753 
3754 ipmi_sdr_info_t *
ipmi_mc_get_sdrs(ipmi_mc_t * mc)3755 ipmi_mc_get_sdrs(ipmi_mc_t *mc)
3756 {
3757     CHECK_MC_LOCK(mc);
3758     return mc->sdrs;
3759 }
3760 
3761 unsigned int
ipmi_mc_get_address(ipmi_mc_t * mc)3762 ipmi_mc_get_address(ipmi_mc_t *mc)
3763 {
3764     CHECK_MC_LOCK(mc);
3765     if (mc->addr.addr_type == IPMI_IPMB_ADDR_TYPE) {
3766 	ipmi_ipmb_addr_t *ipmb = (ipmi_ipmb_addr_t *) &(mc->addr);
3767 	return ipmb->slave_addr;
3768     } else if (mc->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
3769 	ipmi_system_interface_addr_t *si = (void *) &(mc->addr);
3770 	return si->channel;
3771     }
3772 
3773     /* Address is ignore for other types. */
3774     return 0;
3775 }
3776 
3777 void
ipmi_mc_get_ipmi_address(ipmi_mc_t * mc,ipmi_addr_t * addr,unsigned int * addr_len)3778 ipmi_mc_get_ipmi_address(ipmi_mc_t    *mc,
3779 			 ipmi_addr_t  *addr,
3780 			 unsigned int *addr_len)
3781 {
3782     /* We don't check the lock here because this is used as part of
3783        the lock grabbing. */
3784     if (addr)
3785 	memcpy(addr, &mc->addr, mc->addr_len);
3786     if (addr_len)
3787 	*addr_len = mc->addr_len;
3788 }
3789 
3790 unsigned int
ipmi_mc_get_channel(ipmi_mc_t * mc)3791 ipmi_mc_get_channel(ipmi_mc_t *mc)
3792 {
3793     CHECK_MC_LOCK(mc);
3794     if (mc->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
3795 	return IPMI_BMC_CHANNEL;
3796     else
3797 	return mc->addr.channel;
3798 }
3799 
ipmi_mc_get_domain(ipmi_mc_t * mc)3800 ipmi_domain_t *ipmi_mc_get_domain(ipmi_mc_t *mc)
3801 {
3802     return mc->domain;
3803 }
3804 
3805 unsigned int
ipmi_mc_get_unique_num(ipmi_mc_t * mc)3806 ipmi_mc_get_unique_num(ipmi_mc_t *mc)
3807 {
3808     unsigned int rv;
3809 
3810     ipmi_lock(mc->lock);
3811     rv = mc->uniq_num;
3812     mc->uniq_num++;
3813     ipmi_unlock(mc->lock);
3814     return rv;
3815 }
3816 
3817 int
i_ipmi_mc_new_sensor(ipmi_mc_t * mc,ipmi_entity_t * ent,ipmi_sensor_t * sensor,void * link)3818 i_ipmi_mc_new_sensor(ipmi_mc_t     *mc,
3819 		     ipmi_entity_t *ent,
3820 		     ipmi_sensor_t *sensor,
3821 		     void          *link)
3822 {
3823     int rv = 0;
3824 
3825     CHECK_MC_LOCK(mc);
3826 
3827     if (mc->new_sensor_handler)
3828 	rv = mc->new_sensor_handler(mc, ent, sensor, link,
3829 				    mc->new_sensor_cb_data);
3830     return rv;
3831 }
3832 
3833 int
ipmi_mc_set_oem_new_sensor_handler(ipmi_mc_t * mc,ipmi_mc_oem_new_sensor_cb handler,void * cb_data)3834 ipmi_mc_set_oem_new_sensor_handler(ipmi_mc_t                 *mc,
3835 				   ipmi_mc_oem_new_sensor_cb handler,
3836 				   void                      *cb_data)
3837 {
3838     CHECK_MC_LOCK(mc);
3839     mc->new_sensor_handler = handler;
3840     mc->new_sensor_cb_data = cb_data;
3841     return 0;
3842 }
3843 
3844 int
ipmi_mc_set_sdrs_fixup_handler(ipmi_mc_t * mc,ipmi_mc_oem_fixup_sdrs_cb handler,void * cb_data)3845 ipmi_mc_set_sdrs_fixup_handler(ipmi_mc_t                 *mc,
3846 			       ipmi_mc_oem_fixup_sdrs_cb handler,
3847 			       void                      *cb_data)
3848 {
3849     CHECK_MC_LOCK(mc);
3850     mc->fixup_sdrs_handler = handler;
3851     mc->fixup_sdrs_cb_data = cb_data;
3852     return 0;
3853 }
3854 
3855 int
ipmi_mc_add_oem_removed_handler(ipmi_mc_t * mc,ipmi_mc_oem_removed_cb handler,void * cb_data)3856 ipmi_mc_add_oem_removed_handler(ipmi_mc_t              *mc,
3857 				ipmi_mc_oem_removed_cb handler,
3858 				void                   *cb_data)
3859 {
3860     CHECK_MC_LOCK(mc);
3861 
3862     if (locked_list_add(mc->removed_handlers, handler, cb_data))
3863 	return 0;
3864     else
3865 	return ENOMEM;
3866 }
3867 
3868 int
ipmi_mc_remove_oem_removed_handler(ipmi_mc_t * mc,ipmi_mc_oem_removed_cb handler,void * cb_data)3869 ipmi_mc_remove_oem_removed_handler(ipmi_mc_t              *mc,
3870 				   ipmi_mc_oem_removed_cb handler,
3871 				   void                   *cb_data)
3872 {
3873     CHECK_MC_LOCK(mc);
3874 
3875     if (locked_list_remove(mc->removed_handlers, handler, cb_data))
3876 	return 0;
3877     else
3878 	return EINVAL;
3879 }
3880 
3881 int
ipmi_mc_get_events_enable(ipmi_mc_t * mc)3882 ipmi_mc_get_events_enable(ipmi_mc_t *mc)
3883 {
3884     CHECK_MC_LOCK(mc);
3885 
3886     return mc->events_enabled;
3887 }
3888 
3889 int
ipmi_mc_set_events_enable(ipmi_mc_t * mc,int val,ipmi_mc_done_cb done,void * cb_data)3890 ipmi_mc_set_events_enable(ipmi_mc_t       *mc,
3891 			  int             val,
3892 			  ipmi_mc_done_cb done,
3893 			  void            *cb_data)
3894 {
3895     int rv;
3896 
3897     CHECK_MC_LOCK(mc);
3898 
3899     if (!ipmi_mc_ipmb_event_generator_support(mc))
3900 	return ENOSYS;
3901 
3902     val = val != 0;
3903 
3904     ipmi_lock(mc->lock);
3905     if (val == mc->events_enabled) {
3906 	/* Didn't changed, just finish the operation. */
3907 	ipmi_unlock(mc->lock);
3908 	if (done)
3909 	    done(mc, 0, cb_data);
3910 	return 0;
3911     }
3912 
3913     mc->events_enabled = val;
3914 
3915     if (val) {
3916 	unsigned int event_rcvr = ipmi_domain_get_event_rcvr(mc->domain);
3917 	rv = send_set_event_rcvr(mc, event_rcvr, done, cb_data);
3918     } else {
3919 	rv = send_set_event_rcvr(mc, 0, done, cb_data);
3920     }
3921     ipmi_unlock(mc->lock);
3922 
3923     return rv;
3924 }
3925 
3926 typedef struct ipmi_get_event_log_info_s
3927 {
3928     ipmi_mc_data_done_cb done;
3929     void                 *cb_data;
3930 } ipmi_get_event_log_info_t;
3931 
3932 static void
got_event_log_enable(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)3933 got_event_log_enable(ipmi_mc_t  *mc,
3934 		     ipmi_msg_t *rsp,
3935 		     void       *cb_data)
3936 {
3937     ipmi_get_event_log_info_t *info = cb_data;
3938 
3939     if (rsp->data[0] != 0) {
3940 	info->done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), 0, info->cb_data);
3941 	goto out;
3942     }
3943 
3944     if (rsp->data_len < 2) {
3945 	ipmi_log(IPMI_LOG_ERR_INFO,
3946 		 "%smc.c(got_event_log_enable): response too small",
3947 		 mc->name);
3948 	info->done(mc, EINVAL, 0, info->cb_data);
3949 	goto out;
3950     }
3951 
3952     info->done(mc, 0, (rsp->data[1] >> 3) & 1, info->cb_data);
3953 
3954  out:
3955     ipmi_mem_free(info);
3956 }
3957 
3958 int
ipmi_mc_get_event_log_enable(ipmi_mc_t * mc,ipmi_mc_data_done_cb done,void * cb_data)3959 ipmi_mc_get_event_log_enable(ipmi_mc_t            *mc,
3960 			     ipmi_mc_data_done_cb done,
3961 			     void                 *cb_data)
3962 {
3963     int                       rv;
3964     ipmi_msg_t                msg;
3965     ipmi_get_event_log_info_t *info;
3966 
3967     info = ipmi_mem_alloc(sizeof(*info));
3968     if(!info)
3969 	return ENOMEM;
3970 
3971     info->done = done;
3972     info->cb_data = cb_data;
3973 
3974     msg.netfn = IPMI_APP_NETFN;
3975     msg.cmd = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
3976     msg.data = NULL;
3977     msg.data_len = 0;
3978 
3979     rv = ipmi_mc_send_command(mc, 0, &msg, got_event_log_enable, info);
3980     if (rv)
3981 	ipmi_mem_free(info);
3982     return rv;
3983 }
3984 
3985 typedef struct ipmi_set_event_log_info_s
3986 {
3987     ipmi_mc_done_cb done;
3988     void            *cb_data;
3989     int             val;
3990 } ipmi_set_event_log_info_t;
3991 
3992 static void
set_event_log_enable_2(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)3993 set_event_log_enable_2(ipmi_mc_t  *mc,
3994 		       ipmi_msg_t *rsp,
3995 		       void       *cb_data)
3996 {
3997     ipmi_set_event_log_info_t *info = cb_data;
3998 
3999 
4000     if (rsp->data[0] != 0) {
4001 	if (info->done)
4002 	    info->done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), info->cb_data);
4003 	goto out;
4004     }
4005 
4006     if (info->done)
4007 	info->done(mc, 0, info->cb_data);
4008  out:
4009     ipmi_mem_free(info);
4010 }
4011 
4012 static void
set_event_log_enable(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4013 set_event_log_enable(ipmi_mc_t  *mc,
4014 		     ipmi_msg_t *rsp,
4015 		     void       *cb_data)
4016 {
4017     ipmi_set_event_log_info_t *info = cb_data;
4018     int                       rv;
4019     ipmi_msg_t                msg;
4020     unsigned char             data[1];
4021 
4022 
4023     if (rsp->data[0] != 0) {
4024 	if (info->done)
4025 	    info->done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), info->cb_data);
4026 	goto out_err;
4027     }
4028 
4029     if (rsp->data_len < 2) {
4030 	ipmi_log(IPMI_LOG_ERR_INFO,
4031 		 "%smc.c(set_event_log_enable): response too small",
4032 		 mc->name);
4033 	if (info->done)
4034 	    info->done(mc, EINVAL, info->cb_data);
4035 	goto out_err;
4036     }
4037 
4038     data[0] = (rsp->data[1] & ~0x08) | (info->val << 3);
4039     msg.netfn = IPMI_APP_NETFN;
4040     msg.cmd = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
4041     msg.data = data;
4042     msg.data_len = 1;
4043 
4044     rv = ipmi_mc_send_command(mc, 0, &msg, set_event_log_enable_2, info);
4045     if (rv) {
4046 	ipmi_log(IPMI_LOG_ERR_INFO,
4047 		 "%smc.c(set_event_log_enable): Can't send set: 0x%x",
4048 		 mc->name, rv);
4049 	if (info->done)
4050 	    info->done(mc, rv, info->cb_data);
4051 	goto out_err;
4052     }
4053     return;
4054 
4055  out_err:
4056     ipmi_mem_free(info);
4057 }
4058 
4059 int
ipmi_mc_set_event_log_enable(ipmi_mc_t * mc,int val,ipmi_mc_done_cb done,void * cb_data)4060 ipmi_mc_set_event_log_enable(ipmi_mc_t       *mc,
4061 			     int             val,
4062 			     ipmi_mc_done_cb done,
4063 			     void            *cb_data)
4064 {
4065     int                       rv;
4066     ipmi_msg_t                msg;
4067     ipmi_set_event_log_info_t *info;
4068 
4069     info = ipmi_mem_alloc(sizeof(*info));
4070     if(!info)
4071 	return ENOMEM;
4072 
4073     info->done = done;
4074     info->cb_data = cb_data;
4075     info->val = val != 0;
4076 
4077     msg.netfn = IPMI_APP_NETFN;
4078     msg.cmd = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
4079     msg.data = NULL;
4080     msg.data_len = 0;
4081 
4082     rv = ipmi_mc_send_command(mc, 0, &msg, set_event_log_enable, info);
4083     if (rv)
4084 	ipmi_mem_free(info);
4085     return rv;
4086 }
4087 
4088 /***********************************************************************
4089  *
4090  * Global initialization and shutdown
4091  *
4092  **********************************************************************/
4093 
4094 static int mc_initialized = 0;
4095 
4096 int
i_ipmi_mc_init(void)4097 i_ipmi_mc_init(void)
4098 {
4099     if (mc_initialized)
4100 	return 0;
4101 
4102     oem_handlers = locked_list_alloc(ipmi_get_global_os_handler());
4103     if (!oem_handlers)
4104 	return ENOMEM;
4105 
4106     mc_initialized = 1;
4107 
4108     return 0;
4109 }
4110 
4111 static int
oem_handler_free(void * cb_data,void * item1,void * item2)4112 oem_handler_free(void *cb_data, void *item1, void *item2)
4113 {
4114     oem_handlers_t *hndlr = item1;
4115 
4116     locked_list_remove(oem_handlers, item1, item2);
4117     ipmi_mem_free(hndlr);
4118     return LOCKED_LIST_ITER_CONTINUE;
4119 }
4120 
4121 void
i_ipmi_mc_shutdown(void)4122 i_ipmi_mc_shutdown(void)
4123 {
4124     if (mc_initialized) {
4125 	/* Destroy the members of the OEM list. */
4126 	locked_list_iterate(oem_handlers, oem_handler_free, NULL);
4127 	locked_list_destroy(oem_handlers);
4128 	oem_handlers = NULL;
4129 	mc_initialized = 0;
4130     }
4131 }
4132 
4133 /***********************************************************************
4134  *
4135  * Lock checking
4136  *
4137  **********************************************************************/
4138 
4139 void
i__ipmi_check_mc_lock(const ipmi_mc_t * mc)4140 i__ipmi_check_mc_lock(const ipmi_mc_t *mc)
4141 {
4142     if (!mc)
4143 	return;
4144 
4145     if (!DEBUG_LOCKS)
4146 	return;
4147 
4148     if (mc->usecount == 0)
4149 	ipmi_report_lock_error(ipmi_domain_get_os_hnd(mc->domain),
4150 			       "MC not locked when it should have been");
4151 
4152 }
4153 
4154 /***********************************************************************
4155  *
4156  * Channel handling
4157  *
4158  **********************************************************************/
4159 
4160 struct ipmi_channel_info_s
4161 {
4162     unsigned int channel : 4;
4163     unsigned int medium : 7;
4164     unsigned int protocol : 5;
4165     unsigned int session_support : 2;
4166     unsigned char vendor_id[3];
4167     unsigned char aux_info[2];
4168 
4169     ipmi_channel_info_cb handler;
4170     void                 *cb_data;
4171 };
4172 
4173 static void
got_chan_info(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4174 got_chan_info(ipmi_mc_t  *mc,
4175 	      ipmi_msg_t *rsp,
4176 	      void       *cb_data)
4177 {
4178     ipmi_channel_info_t *info = cb_data;
4179 
4180     if (rsp->data[0] != 0) {
4181 	info->handler(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), info,
4182 		      info->cb_data);
4183 	goto out;
4184     }
4185 
4186     if (rsp->data_len < 10) {
4187 	ipmi_log(IPMI_LOG_ERR_INFO,
4188 		 "%smc.c(got_chan_info): Channel info response too small",
4189 		 mc->name);
4190 	info->handler(mc, EINVAL, info, info->cb_data);
4191 	goto out;
4192     }
4193 
4194     info->channel = rsp->data[1] & 0xf;
4195     info->medium = rsp->data[2] & 0x7f;
4196     info->protocol = rsp->data[3] & 0x1f;
4197     info->session_support = rsp->data[4] >> 6;
4198     memcpy(info->vendor_id, rsp->data+5, 3);
4199     memcpy(info->aux_info, rsp->data+8, 2);
4200     info->handler(mc, 0, info, info->cb_data);
4201 
4202  out:
4203     ipmi_mem_free(info);
4204 }
4205 
4206 int
ipmi_mc_channel_get_info(ipmi_mc_t * mc,unsigned int channel,ipmi_channel_info_cb handler,void * cb_data)4207 ipmi_mc_channel_get_info(ipmi_mc_t            *mc,
4208 			 unsigned int         channel,
4209 			 ipmi_channel_info_cb handler,
4210 			 void                 *cb_data)
4211 {
4212     int                 rv;
4213     ipmi_msg_t          msg;
4214     unsigned char       data[1];
4215     ipmi_channel_info_t *info;
4216 
4217     if (channel > 15)
4218 	return EINVAL;
4219 
4220     info = ipmi_mem_alloc(sizeof(*info));
4221     if (!info)
4222 	return ENOMEM;
4223     memset(info, 0, sizeof(*info));
4224 
4225     info->handler = handler;
4226     info->cb_data = cb_data;
4227 
4228     data[0] = channel & 0xf;
4229     msg.netfn = IPMI_APP_NETFN;
4230     msg.cmd = IPMI_GET_CHANNEL_INFO_CMD;
4231     msg.data = data;
4232     msg.data_len = 1;
4233 
4234     rv = ipmi_mc_send_command(mc, 0, &msg, got_chan_info, info);
4235     if (rv)
4236 	ipmi_mem_free(info);
4237     return rv;
4238 }
4239 
4240 ipmi_channel_info_t *
ipmi_channel_info_copy(ipmi_channel_info_t * info)4241 ipmi_channel_info_copy(ipmi_channel_info_t *info)
4242 {
4243     ipmi_channel_info_t *rv = ipmi_mem_alloc(sizeof(*rv));
4244     if (!rv)
4245 	return NULL;
4246     memcpy(rv, info, sizeof(*rv));
4247     return rv;
4248 }
4249 
4250 void
ipmi_channel_info_free(ipmi_channel_info_t * info)4251 ipmi_channel_info_free(ipmi_channel_info_t *info)
4252 {
4253     ipmi_mem_free(info);
4254 }
4255 
4256 int
ipmi_channel_info_get_channel(ipmi_channel_info_t * info,unsigned int * channel)4257 ipmi_channel_info_get_channel(ipmi_channel_info_t *info,
4258 			      unsigned int        *channel)
4259 {
4260     *channel = info->channel;
4261     return 0;
4262 }
4263 
4264 int
ipmi_channel_info_get_medium(ipmi_channel_info_t * info,unsigned int * medium)4265 ipmi_channel_info_get_medium(ipmi_channel_info_t *info,
4266 			     unsigned int        *medium)
4267 {
4268     *medium = info->medium;
4269     return 0;
4270 }
4271 
4272 int
ipmi_channel_info_get_protocol_type(ipmi_channel_info_t * info,unsigned int * prot_type)4273 ipmi_channel_info_get_protocol_type(ipmi_channel_info_t *info,
4274 				    unsigned int        *prot_type)
4275 {
4276     *prot_type = info->protocol;
4277     return 0;
4278 }
4279 
4280 int
ipmi_channel_info_get_session_support(ipmi_channel_info_t * info,unsigned int * sup)4281 ipmi_channel_info_get_session_support(ipmi_channel_info_t *info,
4282 				      unsigned int        *sup)
4283 {
4284     *sup = info->session_support;
4285     return 0;
4286 }
4287 
4288 int
ipmi_channel_info_get_vendor_id(ipmi_channel_info_t * info,unsigned char * data)4289 ipmi_channel_info_get_vendor_id(ipmi_channel_info_t *info,
4290 				unsigned char       *data)
4291 {
4292     memcpy(data, info->vendor_id, 3);
4293     return 0;
4294 }
4295 
4296 int
ipmi_channel_info_get_aux_info(ipmi_channel_info_t * info,unsigned char * data)4297 ipmi_channel_info_get_aux_info(ipmi_channel_info_t *info,
4298 			       unsigned char *data)
4299 {
4300     memcpy(data, info->aux_info, 2);
4301     return 0;
4302 }
4303 
4304 struct ipmi_channel_access_s
4305 {
4306     unsigned int channel : 4;
4307     unsigned int alert_set : 1;
4308     unsigned int alert_val : 1;
4309     unsigned int msg_auth_set : 1;
4310     unsigned int msg_auth_val : 1;
4311     unsigned int user_auth_set : 1;
4312     unsigned int user_auth_val : 1;
4313     unsigned int access_mode_set : 1;
4314     unsigned int access_mode_val : 3;
4315     unsigned int privilege_set : 1;
4316     unsigned int privilege_val : 4;
4317 
4318     ipmi_channel_access_cb handler;
4319     ipmi_mc_done_cb        done;
4320     void                   *cb_data;
4321 };
4322 
4323 static void
got_chan_access(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4324 got_chan_access(ipmi_mc_t  *mc,
4325 		ipmi_msg_t *rsp,
4326 		void       *cb_data)
4327 {
4328     ipmi_channel_access_t *info = cb_data;
4329 
4330     if (rsp->data[0] != 0) {
4331 	info->handler(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), info,
4332 		      info->cb_data);
4333 	goto out;
4334     }
4335 
4336     if (rsp->data_len < 3) {
4337 	ipmi_log(IPMI_LOG_ERR_INFO,
4338 		 "%smc.c(got_chan_info): Channel access response too small",
4339 		 mc->name);
4340 	info->handler(mc, EINVAL, info, info->cb_data);
4341 	goto out;
4342     }
4343 
4344     /* For these, the values in the message are the inverse of their
4345        boolean value. */
4346     info->alert_val = !((rsp->data[1] >> 5) & 1);
4347     info->msg_auth_val = !((rsp->data[1] >> 4) & 1);
4348     info->user_auth_val = !((rsp->data[1] >> 3) & 1);
4349 
4350     info->access_mode_val = rsp->data[1] & 0x7;
4351     info->privilege_val = rsp->data[2] & 0xf;
4352     info->handler(mc, 0, info, info->cb_data);
4353  out:
4354     ipmi_mem_free(info);
4355 }
4356 
4357 int
ipmi_mc_channel_get_access(ipmi_mc_t * mc,unsigned int channel,enum ipmi_set_dest_e dest,ipmi_channel_access_cb handler,void * cb_data)4358 ipmi_mc_channel_get_access(ipmi_mc_t              *mc,
4359 			   unsigned int           channel,
4360 			   enum ipmi_set_dest_e   dest,
4361 			   ipmi_channel_access_cb handler,
4362 			   void                   *cb_data)
4363 {
4364     int                   rv;
4365     ipmi_msg_t            msg;
4366     unsigned char         data[2];
4367     ipmi_channel_access_t *info;
4368 
4369     if (channel > 15)
4370 	return EINVAL;
4371     if ((dest < IPMI_SET_DEST_NON_VOLATILE) || (dest > IPMI_SET_DEST_VOLATILE))
4372 	return EINVAL;
4373 
4374     info = ipmi_mem_alloc(sizeof(*info));
4375     if (!info)
4376 	return ENOMEM;
4377     memset(info, 0, sizeof(*info));
4378 
4379     info->channel = channel;
4380     info->handler = handler;
4381     info->cb_data = cb_data;
4382 
4383     data[0] = channel & 0xf;
4384     data[1] = dest << 6;
4385     msg.netfn = IPMI_APP_NETFN;
4386     msg.cmd = IPMI_GET_CHANNEL_ACCESS_CMD;
4387     msg.data = data;
4388     msg.data_len = 2;
4389 
4390     rv = ipmi_mc_send_command(mc, 0, &msg, got_chan_access, info);
4391     if (rv)
4392 	ipmi_mem_free(info);
4393     return rv;
4394 }
4395 
4396 static void
set_chan_access(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4397 set_chan_access(ipmi_mc_t  *mc,
4398 		ipmi_msg_t *rsp,
4399 		void       *cb_data)
4400 {
4401     ipmi_channel_access_t *info = cb_data;
4402 
4403     if (rsp->data[0] != 0) {
4404 	if (info->done)
4405 	    info->done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), info->cb_data);
4406 	goto out;
4407     }
4408 
4409     if (info->done)
4410 	info->done(mc, 0, info->cb_data);
4411 
4412  out:
4413     ipmi_mem_free(info);
4414 }
4415 
4416 int
ipmi_mc_channel_set_access(ipmi_mc_t * mc,unsigned int channel,enum ipmi_set_dest_e dest,ipmi_channel_access_t * access,ipmi_mc_done_cb handler,void * cb_data)4417 ipmi_mc_channel_set_access(ipmi_mc_t             *mc,
4418 			   unsigned int           channel,
4419 			   enum ipmi_set_dest_e  dest,
4420 			   ipmi_channel_access_t *access,
4421 			   ipmi_mc_done_cb       handler,
4422 			   void                  *cb_data)
4423 {
4424     ipmi_channel_access_t *info;
4425     ipmi_msg_t            msg;
4426     unsigned char         data[3];
4427     int                   rv;
4428 
4429 
4430     if (channel > 15)
4431 	return EINVAL;
4432     if ((dest < IPMI_SET_DEST_NON_VOLATILE) || (dest > IPMI_SET_DEST_VOLATILE))
4433 	return EINVAL;
4434 
4435     info = ipmi_mem_alloc(sizeof(*info));
4436     if (!info)
4437 	return EINVAL;
4438 
4439     memcpy(info, access, sizeof(*info));
4440     info->channel = channel;
4441     info->done = handler;
4442     info->cb_data = cb_data;
4443 
4444     data[0] = channel & 0xf;
4445 
4446     data[1] = ((!info->alert_val << 5)
4447 	       | (!info->msg_auth_val << 4)
4448 	       | (!info->user_auth_val << 3)
4449 	       | info->access_mode_val);
4450     if (info->alert_set || info->msg_auth_set || info->user_auth_set
4451 	|| info->access_mode_set)
4452     {
4453 	data[1] |= dest << 6;
4454     }
4455 
4456     data[2] = info->privilege_val;
4457     if (info->privilege_set)
4458 	data[2] |= dest << 6;
4459 
4460     msg.netfn = IPMI_APP_NETFN;
4461     msg.cmd = IPMI_SET_CHANNEL_ACCESS_CMD;
4462     msg.data = data;
4463     msg.data_len = 3;
4464 
4465     rv = ipmi_mc_send_command(mc, 0, &msg, set_chan_access, info);
4466     if (rv)
4467 	ipmi_mem_free(info);
4468 
4469     return rv;
4470 }
4471 
4472 ipmi_channel_access_t *
ipmi_channel_access_copy(ipmi_channel_access_t * access)4473 ipmi_channel_access_copy(ipmi_channel_access_t *access)
4474 {
4475     ipmi_channel_access_t *rv = ipmi_mem_alloc(sizeof(*rv));
4476     if (!rv)
4477 	return NULL;
4478     memcpy(rv, access, sizeof(*rv));
4479     return rv;
4480 }
4481 
4482 void
ipmi_channel_access_free(ipmi_channel_access_t * access)4483 ipmi_channel_access_free(ipmi_channel_access_t *access)
4484 {
4485     ipmi_mem_free(access);
4486 }
4487 
4488 int
ipmi_channel_access_get_channel(ipmi_channel_access_t * info,unsigned int * channel)4489 ipmi_channel_access_get_channel(ipmi_channel_access_t *info,
4490 				unsigned int          *channel)
4491 {
4492     *channel = info->channel;
4493     return 0;
4494 }
4495 
4496 int
ipmi_channel_access_get_alerting_enabled(ipmi_channel_access_t * info,unsigned int * enab)4497 ipmi_channel_access_get_alerting_enabled(ipmi_channel_access_t *info,
4498 					 unsigned int          *enab)
4499 {
4500     *enab = info->alert_val;
4501     return 0;
4502 }
4503 
4504 int
ipmi_channel_access_set_alerting_enabled(ipmi_channel_access_t * info,unsigned int enab)4505 ipmi_channel_access_set_alerting_enabled(ipmi_channel_access_t *info,
4506 					 unsigned int          enab)
4507 {
4508     info->alert_val = enab;
4509     info->alert_set = 1;
4510     return 0;
4511 }
4512 
4513 int
ipmi_channel_access_get_per_msg_auth(ipmi_channel_access_t * info,unsigned int * msg_auth)4514 ipmi_channel_access_get_per_msg_auth(ipmi_channel_access_t *info,
4515 				     unsigned int          *msg_auth)
4516 {
4517     *msg_auth = info->msg_auth_val;
4518     return 0;
4519 }
4520 
4521 int
ipmi_channel_access_set_per_msg_auth(ipmi_channel_access_t * info,unsigned int msg_auth)4522 ipmi_channel_access_set_per_msg_auth(ipmi_channel_access_t *info,
4523 				     unsigned int          msg_auth)
4524 {
4525     info->msg_auth_val = msg_auth;
4526     info->msg_auth_set = 1;
4527     return 0;
4528 }
4529 
4530 int
ipmi_channel_access_get_user_auth(ipmi_channel_access_t * info,unsigned int * user_auth)4531 ipmi_channel_access_get_user_auth(ipmi_channel_access_t *info,
4532 				  unsigned int          *user_auth)
4533 {
4534     *user_auth = info->user_auth_val;
4535     return 0;
4536 }
4537 
4538 int
ipmi_channel_access_set_user_auth(ipmi_channel_access_t * info,unsigned int user_auth)4539 ipmi_channel_access_set_user_auth(ipmi_channel_access_t *info,
4540 				  unsigned int          user_auth)
4541 {
4542     info->user_auth_val = user_auth;
4543     info->user_auth_set = 1;
4544     return 0;
4545 }
4546 
4547 int
ipmi_channel_access_get_access_mode(ipmi_channel_access_t * info,unsigned int * access_mode)4548 ipmi_channel_access_get_access_mode(ipmi_channel_access_t *info,
4549 				    unsigned int          *access_mode)
4550 {
4551     *access_mode = info->access_mode_val;
4552     return 0;
4553 }
4554 
4555 int
ipmi_channel_access_set_access_mode(ipmi_channel_access_t * info,unsigned int access_mode)4556 ipmi_channel_access_set_access_mode(ipmi_channel_access_t *info,
4557 				    unsigned int          access_mode)
4558 {
4559     info->access_mode_val = access_mode;
4560     info->access_mode_set = 1;
4561     return 0;
4562 }
4563 
4564 int
ipmi_channel_access_get_priv_limit(ipmi_channel_access_t * info,unsigned int * priv_limit)4565 ipmi_channel_access_get_priv_limit(ipmi_channel_access_t *info,
4566 				   unsigned int          *priv_limit)
4567 {
4568     *priv_limit = info->privilege_val;
4569     return 0;
4570 }
4571 
4572 int
ipmi_channel_access_set_priv_limit(ipmi_channel_access_t * info,unsigned int priv_limit)4573 ipmi_channel_access_set_priv_limit(ipmi_channel_access_t *info,
4574 				   unsigned int          priv_limit)
4575 {
4576     info->privilege_val = priv_limit;
4577     info->privilege_set = 1;
4578     return 0;
4579 }
4580 
4581 int
ipmi_channel_access_setall(ipmi_channel_access_t * info)4582 ipmi_channel_access_setall(ipmi_channel_access_t *info)
4583 {
4584     info->alert_set = 1;
4585     info->msg_auth_set = 1;
4586     info->user_auth_set = 1;
4587     info->access_mode_set = 1;
4588     info->privilege_set = 1;
4589     return 0;
4590 }
4591 
4592 /***********************************************************************
4593  *
4594  * User management
4595  *
4596  **********************************************************************/
4597 
4598 struct ipmi_user_s
4599 {
4600     int  num;
4601     unsigned int link_enabled_set : 1;
4602     unsigned int link_enabled : 1;
4603     unsigned int msg_enabled_set : 1;
4604     unsigned int msg_enabled : 1;
4605     unsigned int privilege_limit_set : 1;
4606     unsigned int privilege_limit : 4;
4607     unsigned int cb_only_set : 1;
4608     unsigned int cb_only : 1;
4609     unsigned int session_limit_set : 1;
4610     unsigned int session_limit_read : 1;
4611     unsigned int session_limit : 4;
4612     unsigned int enable_set : 1;
4613     unsigned int enable_read : 1;
4614     unsigned int enable : 4;
4615     unsigned int name_set : 1;
4616     char name[17];
4617     unsigned int pw_set : 1;
4618     unsigned int pw2_set : 1;
4619     unsigned int can_use_pw2 : 1;
4620     char pw[20];
4621 
4622     unsigned int channel : 4;
4623     ipmi_mc_done_cb handler;
4624     void            *cb_data;
4625 };
4626 
4627 struct ipmi_user_list_s
4628 {
4629     unsigned int      channel;
4630     unsigned int      curr;
4631     unsigned int      idx;
4632     unsigned int      max;
4633     unsigned int      enabled;
4634     unsigned int      fixed;
4635     ipmi_user_t       *users;
4636     int               supports_rmcpp;
4637 
4638     ipmi_user_list_cb handler;
4639     void              *cb_data;
4640 };
4641 
4642 ipmi_user_list_t *
ipmi_user_list_copy(ipmi_user_list_t * list)4643 ipmi_user_list_copy(ipmi_user_list_t *list)
4644 {
4645     ipmi_user_list_t *rv;
4646 
4647     rv = ipmi_mem_alloc(sizeof(*rv));
4648     if (!rv)
4649 	return NULL;
4650     memcpy(rv, list, sizeof(*rv));
4651     rv->users = ipmi_mem_alloc(sizeof(ipmi_user_t) * list->idx);
4652     if (!rv->users) {
4653 	ipmi_mem_free(rv);
4654 	return NULL;
4655     }
4656     memcpy(rv->users, list->users, sizeof(ipmi_user_t) * list->idx);
4657     return rv;
4658 }
4659 
4660 void
ipmi_user_list_free(ipmi_user_list_t * list)4661 ipmi_user_list_free(ipmi_user_list_t *list)
4662 {
4663     if (list->users)
4664 	ipmi_mem_free(list->users);
4665     ipmi_mem_free(list);
4666 }
4667 
4668 unsigned int
ipmi_user_list_get_user_count(ipmi_user_list_t * list)4669 ipmi_user_list_get_user_count(ipmi_user_list_t *list)
4670 {
4671   return list->idx;
4672 }
4673 
4674 ipmi_user_t *
ipmi_user_list_get_user(ipmi_user_list_t * list,unsigned int idx)4675 ipmi_user_list_get_user(ipmi_user_list_t *list,
4676 			unsigned int     idx)
4677 {
4678   if (idx >= list->idx)
4679       return NULL;
4680   return ipmi_user_copy(&list->users[idx]);
4681 }
4682 
4683 int
ipmi_user_list_get_channel(ipmi_user_list_t * list,unsigned int * channel)4684 ipmi_user_list_get_channel(ipmi_user_list_t *list, unsigned int *channel)
4685 {
4686     *channel = list->channel;
4687     return 0;
4688 }
4689 
4690 int
ipmi_user_list_get_max_user(ipmi_user_list_t * list,unsigned int * max)4691 ipmi_user_list_get_max_user(ipmi_user_list_t *list, unsigned int *max)
4692 {
4693     *max = list->max;
4694     return 0;
4695 }
4696 
4697 int
ipmi_user_list_get_enabled_users(ipmi_user_list_t * list,unsigned int * e)4698 ipmi_user_list_get_enabled_users(ipmi_user_list_t *list, unsigned int *e)
4699 {
4700     *e = list->enabled;
4701     return 0;
4702 }
4703 
4704 int
ipmi_user_list_get_fixed_users(ipmi_user_list_t * list,unsigned int * f)4705 ipmi_user_list_get_fixed_users(ipmi_user_list_t *list, unsigned int *f)
4706 {
4707     *f = list->fixed;
4708     return 0;
4709 }
4710 
4711 
4712 static int list_next_user(ipmi_mc_t *mc, ipmi_user_list_t *list);
4713 
4714 static void
user_list_done(ipmi_mc_t * mc,ipmi_user_list_t * list)4715 user_list_done(ipmi_mc_t *mc, ipmi_user_list_t *list)
4716 {
4717     list->handler(mc, 0, list, list->cb_data);
4718     ipmi_user_list_free(list);
4719 }
4720 
4721 static void
got_user2(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4722 got_user2(ipmi_mc_t  *mc,
4723 	  ipmi_msg_t *rsp,
4724 	  void       *cb_data)
4725 {
4726     ipmi_user_list_t *list = cb_data;
4727     int              rv;
4728 
4729     if (rsp->data[0] != 0) {
4730 	list->handler(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), list,
4731 		      list->cb_data);
4732 	goto out_err;
4733     }
4734 
4735     if (rsp->data_len < 17) {
4736 	ipmi_log(IPMI_LOG_ERR_INFO,
4737 		 "%smc.c(got_chan_info): user name response too small",
4738 		 mc->name);
4739 	list->handler(mc, EINVAL, list, list->cb_data);
4740 	goto out_err;
4741     }
4742 
4743     memcpy(list->users[list->idx].name, rsp->data+1, 16);
4744     list->users[list->idx].name[16] = '\0';
4745     list->idx++;
4746 
4747     if (list->curr >= list->max)
4748 	user_list_done(mc, list);
4749     else {
4750 	list->curr++;
4751 	rv = list_next_user(mc, list);
4752 	if (rv) {
4753 	    list->handler(mc, rv, list, list->cb_data);
4754 	    goto out_err;
4755 	}
4756     }
4757     return;
4758 
4759  out_err:
4760     ipmi_user_list_free(list);
4761 }
4762 
4763 static void
got_user1(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4764 got_user1(ipmi_mc_t  *mc,
4765 	  ipmi_msg_t *rsp,
4766 	  void       *cb_data)
4767 {
4768     ipmi_user_list_t *list = cb_data;
4769     int              rv;
4770     int              idx;
4771     ipmi_msg_t       msg;
4772     unsigned char    data[1];
4773 
4774 
4775     if (rsp->data[0] != 0) {
4776 	list->handler(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), list,
4777 		      list->cb_data);
4778 	goto out_err;
4779     }
4780 
4781     if (rsp->data_len < 5) {
4782 	ipmi_log(IPMI_LOG_ERR_INFO,
4783 		 "%smc.c(got_chan_info): user access response too small",
4784 		 mc->name);
4785 	list->handler(mc, EINVAL, list, list->cb_data);
4786 	goto out_err;
4787     }
4788 
4789     if (! list->users) {
4790 	if (list->max == 0) {
4791 	    list->max = rsp->data[1] & 0x3f;
4792 	    list->enabled = rsp->data[2] & 0x3f;
4793 	    list->fixed = rsp->data[3] & 0x3f;
4794 	}
4795 	if (list->max < 1) {
4796 	    ipmi_log(IPMI_LOG_ERR_INFO,
4797 		     "%smc.c(got_chan_info): user access num uses is < 1",
4798 		     mc->name);
4799 	    list->handler(mc, EINVAL, list, list->cb_data);
4800 	    goto out_err;
4801 	}
4802 	list->users = ipmi_mem_alloc(sizeof(ipmi_user_t)
4803 				     * (list->max - list->curr + 1));
4804 	if (!list->users) {
4805 	    list->handler(mc, EINVAL, list, list->cb_data);
4806 	    goto out_err;
4807 	}
4808 	memset(list->users, 0,
4809 	       sizeof(ipmi_user_t) * (list->max - list->curr + 1));
4810     }
4811 
4812     idx = list->idx;
4813     list->users[idx].num = list->curr;
4814     list->users[idx].cb_only = (rsp->data[4] >> 6) & 1;
4815     list->users[idx].link_enabled = (rsp->data[4] >> 5) & 1;
4816     list->users[idx].msg_enabled = (rsp->data[4] >> 4) & 1;
4817     list->users[idx].privilege_limit = rsp->data[4] & 0x0f;
4818     list->users[idx].channel = list->channel;
4819     list->users[idx].can_use_pw2 = list->supports_rmcpp;
4820 
4821     if (list->curr == 1) {
4822 	/* User 1 does not have a name, don't try to fetch it. */
4823 	memset(list->users[list->idx].name, 0, 17);
4824 	list->idx++;
4825 	if (list->curr >= list->max) {
4826 	    user_list_done(mc, list);
4827 	    rv = 0;
4828 	} else {
4829 	    list->curr++;
4830 	    rv = list_next_user(mc, list);
4831 	}
4832     } else {
4833 	msg.netfn = IPMI_APP_NETFN;
4834 	msg.cmd = IPMI_GET_USER_NAME_CMD;
4835 	msg.data = data;
4836 	msg.data_len = 1;
4837 	data[0] = list->curr;
4838 
4839 	rv = ipmi_mc_send_command(mc, 0, &msg, got_user2, list);
4840     }
4841     if (rv) {
4842 	list->handler(mc, rv, list, list->cb_data);
4843 	goto out_err;
4844     }
4845 
4846     return;
4847 
4848  out_err:
4849     ipmi_user_list_free(list);
4850 }
4851 
4852 static int
list_next_user(ipmi_mc_t * mc,ipmi_user_list_t * info)4853 list_next_user(ipmi_mc_t *mc, ipmi_user_list_t *info)
4854 {
4855     ipmi_msg_t      msg;
4856     unsigned char   data[2];
4857 
4858     if ((info->curr > 0x3f) || (info->curr < 1))
4859 	return EINVAL;
4860 
4861     msg.netfn = IPMI_APP_NETFN;
4862     msg.cmd = IPMI_GET_USER_ACCESS_CMD;
4863     msg.data = data;
4864     msg.data_len = 2;
4865     data[0] = info->channel & 0xf;
4866     data[1] = info->curr;
4867 
4868     return ipmi_mc_send_command(mc, 0, &msg, got_user1, info);
4869 }
4870 
4871 static void
got_user0(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4872 got_user0(ipmi_mc_t  *mc,
4873 	  ipmi_msg_t *rsp,
4874 	  void       *cb_data)
4875 {
4876     ipmi_user_list_t *list = cb_data;
4877     int              rv;
4878 
4879     if (rsp->data[0] != 0) {
4880 	/* We possibly have 2.0 support. */
4881 	 list->supports_rmcpp
4882 	     = ((rsp->data[2] & (1 << 7)) /* Supports 2.0 capabilities */
4883 		&& (rsp->data[4] & (1 << 1))); /* 2.0 connection support */
4884     }
4885 
4886     rv = list_next_user(mc, list);
4887     if (rv) {
4888 	list->handler(mc, rv, list, list->cb_data);
4889 	ipmi_mem_free(list);
4890     }
4891 }
4892 
4893 int
ipmi_mc_get_users(ipmi_mc_t * mc,unsigned int channel,unsigned int user,ipmi_user_list_cb handler,void * cb_data)4894 ipmi_mc_get_users(ipmi_mc_t         *mc,
4895 		  unsigned int      channel,
4896 		  unsigned int      user,
4897 		  ipmi_user_list_cb handler,
4898 		  void              *cb_data)
4899 {
4900     int              rv;
4901     ipmi_user_list_t *list = NULL;
4902     ipmi_msg_t       msg;
4903     unsigned char    data[2];
4904 
4905     if (channel > 15)
4906 	return EINVAL;
4907     if (user > 0x3f)
4908 	return EINVAL;
4909 
4910     list = ipmi_mem_alloc(sizeof(*list));
4911     if (!list)
4912 	return ENOMEM;
4913     memset(list, 0, sizeof(*list));
4914 
4915     list->channel = channel;
4916     list->handler = handler;
4917     list->cb_data = cb_data;
4918     if (user) {
4919 	list->curr = user;
4920 	list->max = user;
4921     } else {
4922 	list->curr = 1;
4923 	list->max = 0;
4924     }
4925 
4926     /* First determine if we have 2.0 (RMCP+) support. */
4927     msg.netfn = IPMI_APP_NETFN;
4928     msg.cmd = IPMI_GET_CHANNEL_AUTH_CAPABILITIES_CMD;
4929     msg.data = data;
4930     msg.data_len = 2;
4931     data[0] = (channel & 0xf) | (1 << 7); /* Request IPMI 2.0 data */
4932     data[1] = 2; /* Request user level access */
4933 
4934     rv = ipmi_mc_send_command(mc, 0, &msg, got_user0, list);
4935     if (rv)
4936 	ipmi_mem_free(list);
4937     return rv;
4938 }
4939 
4940 ipmi_user_t *
ipmi_user_copy(ipmi_user_t * user)4941 ipmi_user_copy(ipmi_user_t *user)
4942 {
4943     ipmi_user_t *rv;
4944 
4945     rv = ipmi_mem_alloc(sizeof(*rv));
4946     if (rv)
4947 	memcpy(rv, user, sizeof(*rv));
4948     return rv;
4949 }
4950 
4951 void
ipmi_user_free(ipmi_user_t * user)4952 ipmi_user_free(ipmi_user_t *user)
4953 {
4954     ipmi_mem_free(user);
4955 }
4956 
4957 static void
set_user_done(ipmi_mc_t * mc,int err,ipmi_user_t * user)4958 set_user_done(ipmi_mc_t *mc, int err, ipmi_user_t *user)
4959 {
4960     if (user->handler)
4961 	user->handler(mc, err, user->cb_data);
4962     ipmi_user_free(user);
4963 }
4964 
4965 static void
set_user5(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)4966 set_user5(ipmi_mc_t  *mc,
4967 	  ipmi_msg_t *rsp,
4968 	  void       *cb_data)
4969 {
4970     ipmi_user_t     *user = cb_data;
4971 
4972     if (rsp->data[0] != 0) {
4973 	set_user_done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), user);
4974 	return;
4975     }
4976 
4977     set_user_done(mc, 0, user);
4978 }
4979 
set_enable(ipmi_mc_t * mc,ipmi_user_t * user)4980 static int set_enable(ipmi_mc_t *mc, ipmi_user_t *user)
4981 {
4982     ipmi_msg_t      msg;
4983     unsigned char   data[2];
4984 
4985     msg.netfn = IPMI_APP_NETFN;
4986     msg.cmd = IPMI_SET_USER_PASSWORD_CMD;
4987     msg.data = data;
4988     msg.data_len = 2;
4989 
4990 
4991     data[0] = user->num;
4992     if (user->enable)
4993 	data[1] = 0x01; /* enable */
4994     else
4995 	data[1] = 0x00; /* disable */
4996 
4997     return ipmi_mc_send_command(mc, 0, &msg, set_user5, user);
4998 }
4999 
5000 static void
set_user4(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)5001 set_user4(ipmi_mc_t  *mc,
5002 	  ipmi_msg_t *rsp,
5003 	  void       *cb_data)
5004 {
5005     ipmi_user_t *user = cb_data;
5006     int         rv = 0;
5007 
5008     if (rsp->data[0] != 0) {
5009 	set_user_done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), user);
5010 	return;
5011     }
5012 
5013     if (user->enable_set)
5014 	rv = set_enable(mc, user);
5015     else
5016 	set_user_done(mc, 0, user);
5017 
5018     if (rv)
5019 	set_user_done(mc, rv, user);
5020 }
5021 
set_pw(ipmi_mc_t * mc,ipmi_user_t * user)5022 static int set_pw(ipmi_mc_t *mc, ipmi_user_t *user)
5023 {
5024     ipmi_msg_t      msg;
5025     unsigned char   data[22];
5026 
5027     msg.netfn = IPMI_APP_NETFN;
5028     msg.cmd = IPMI_SET_USER_PASSWORD_CMD;
5029     msg.data = data;
5030 
5031 
5032     data[0] = user->num;
5033     data[1] = 0x02; /* set password */
5034     if (user->pw2_set) {
5035 	msg.data_len = 22;
5036 	memcpy(data+2, user->pw, 20);
5037 	data[0] |= 0x80;
5038     } else {
5039 	msg.data_len = 18;
5040 	memcpy(data+2, user->pw, 16);
5041     }
5042 
5043     return ipmi_mc_send_command(mc, 0, &msg, set_user4, user);
5044 }
5045 
5046 static void
set_user3(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)5047 set_user3(ipmi_mc_t  *mc,
5048 	  ipmi_msg_t *rsp,
5049 	  void       *cb_data)
5050 {
5051     ipmi_user_t     *user = cb_data;
5052     int             rv = 0;
5053 
5054     if (rsp->data[0] != 0) {
5055 	set_user_done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), user);
5056 	return;
5057     }
5058 
5059     if (user->pw_set || user->pw2_set)
5060 	rv = set_pw(mc, user);
5061     else if (user->enable_set)
5062 	rv = set_enable(mc, user);
5063     else
5064 	set_user_done(mc, 0, user);
5065 
5066     if (rv)
5067 	set_user_done(mc, rv, user);
5068 }
5069 
set_name(ipmi_mc_t * mc,ipmi_user_t * user)5070 static int set_name(ipmi_mc_t *mc, ipmi_user_t *user)
5071 {
5072     ipmi_msg_t      msg;
5073     unsigned char   data[17];
5074 
5075     msg.netfn = IPMI_APP_NETFN;
5076     msg.cmd = IPMI_SET_USER_NAME_CMD;
5077     msg.data = data;
5078     msg.data_len = 17;
5079 
5080 
5081     data[0] = user->num;
5082     memcpy(data+1, user->name, 16);
5083 
5084     return ipmi_mc_send_command(mc, 0, &msg, set_user3, user);
5085 }
5086 
5087 static void
set_user2(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * cb_data)5088 set_user2(ipmi_mc_t  *mc,
5089 	  ipmi_msg_t *rsp,
5090 	  void       *cb_data)
5091 {
5092     ipmi_user_t     *user = cb_data;
5093     int             rv = 0;
5094 
5095     if (rsp->data[0] != 0) {
5096 	set_user_done(mc, IPMI_IPMI_ERR_VAL(rsp->data[0]), user);
5097 	return;
5098     }
5099 
5100     if (user->name_set)
5101 	rv = set_name(mc, user);
5102     else if (user->pw_set || user->pw2_set)
5103 	rv = set_pw(mc, user);
5104     else if (user->enable_set)
5105 	rv = set_enable(mc, user);
5106     else
5107 	set_user_done(mc, 0, user);
5108 
5109     if (rv)
5110 	set_user_done(mc, rv, user);
5111 }
5112 
5113 static int
set_user_access(ipmi_mc_t * mc,ipmi_user_t * user)5114 set_user_access(ipmi_mc_t *mc, ipmi_user_t *user)
5115 {
5116     ipmi_msg_t      msg;
5117     unsigned char   data[4];
5118 
5119     msg.netfn = IPMI_APP_NETFN;
5120     msg.cmd = IPMI_SET_USER_ACCESS_CMD;
5121     msg.data = data;
5122     msg.data_len = 3;
5123 
5124     data[0] = user->channel;
5125     if (user->cb_only_set || user->link_enabled_set || user->msg_enabled_set) {
5126 	data[0] |= user->channel;
5127 	data[0] |= user->cb_only << 6;
5128 	data[0] |= user->link_enabled << 5;
5129 	data[0] |= user->msg_enabled << 4;
5130 	data[0] |= 0x80;
5131     }
5132     data[1] = user->num;
5133     data[2] = user->privilege_limit;
5134     if (user->session_limit_set) {
5135 	/* Optional value, afaict there is no way to get this value. */
5136 	data[3] = user->session_limit;
5137 	msg.data_len++;
5138     }
5139 
5140     return ipmi_mc_send_command(mc, 0, &msg, set_user2, user);
5141 }
5142 
5143 int
ipmi_mc_set_user(ipmi_mc_t * mc,unsigned int channel,unsigned int num,ipmi_user_t * iuser,ipmi_mc_done_cb handler,void * cb_data)5144 ipmi_mc_set_user(ipmi_mc_t       *mc,
5145 		 unsigned int    channel,
5146 		 unsigned int    num,
5147 		 ipmi_user_t     *iuser,
5148 		 ipmi_mc_done_cb handler,
5149 		 void            *cb_data)
5150 {
5151     int             rv = 0;
5152     ipmi_user_t     *user;
5153 
5154     if (channel > 15)
5155 	return EINVAL;
5156     if (num > 0x3f)
5157 	return EINVAL;
5158 
5159     user = ipmi_user_copy(iuser);
5160     if (!user)
5161 	return ENOMEM;
5162     user->num = num;
5163     user->channel = channel;
5164     user->handler = handler;
5165     user->cb_data = cb_data;
5166 
5167     if (user->cb_only_set || user->link_enabled_set || user->msg_enabled_set
5168 	|| user->privilege_limit_set || user->session_limit_set)
5169     	rv = set_user_access(mc, user);
5170     else if (user->name_set)
5171 	rv = set_name(mc, user);
5172     else if (user->pw_set || user->pw2_set)
5173 	rv = set_pw(mc, user);
5174     else if (user->enable_set)
5175 	rv = set_enable(mc, user);
5176     else {
5177 	/* Nothing to do. */
5178 	if (handler)
5179 	    handler(mc, 0, cb_data);
5180 	ipmi_user_free(user);
5181     }
5182 
5183     if (rv)
5184 	ipmi_user_free(user);
5185 
5186     return rv;
5187 }
5188 
5189 int
ipmi_user_get_channel(ipmi_user_t * user,unsigned int * channel)5190 ipmi_user_get_channel(ipmi_user_t *user, unsigned int *channel)
5191 {
5192     *channel = user->channel;
5193     return 0;
5194 }
5195 
5196 int
ipmi_user_get_num(ipmi_user_t * user,unsigned int * num)5197 ipmi_user_get_num(ipmi_user_t *user, unsigned int *num)
5198 {
5199     *num = user->num;
5200     return 0;
5201 }
5202 
5203 int
ipmi_user_set_num(ipmi_user_t * user,unsigned int num)5204 ipmi_user_set_num(ipmi_user_t *user, unsigned int num)
5205 {
5206     if (num > 0x3f)
5207 	return EINVAL;
5208     user->num = num;
5209     return 0;
5210 }
5211 
5212 int
ipmi_user_get_name_len(ipmi_user_t * user,unsigned int * len)5213 ipmi_user_get_name_len(ipmi_user_t *user, unsigned int *len)
5214 {
5215     *len = 16;
5216     return 0;
5217 }
5218 
5219 int
ipmi_user_get_name(ipmi_user_t * user,char * name,unsigned int * len)5220 ipmi_user_get_name(ipmi_user_t *user, char *name, unsigned int *len)
5221 {
5222     if (*len > 17)
5223 	*len = 17;
5224     memcpy(name, user->name, *len);
5225     return 0;
5226 }
5227 
5228 int
ipmi_user_set_name(ipmi_user_t * user,char * name,unsigned int len)5229 ipmi_user_set_name(ipmi_user_t *user, char *name, unsigned int len)
5230 {
5231     if (len > 16)
5232 	return EINVAL;
5233     memcpy(user->name, name, len);
5234     user->name_set = 1;
5235     return 0;
5236 }
5237 
5238 int
ipmi_user_set_password(ipmi_user_t * user,char * pw,unsigned int len)5239 ipmi_user_set_password(ipmi_user_t *user, char *pw, unsigned int len)
5240 {
5241     if (len > 16)
5242 	return EINVAL;
5243     memcpy(user->pw, pw, len);
5244     user->pw_set = 1;
5245     return 0;
5246 }
5247 
5248 int
ipmi_user_set_password2(ipmi_user_t * user,char * pw,unsigned int len)5249 ipmi_user_set_password2(ipmi_user_t *user, char *pw, unsigned int len)
5250 {
5251     if (! user->can_use_pw2)
5252 	return ENOSYS;
5253     if (len > 20)
5254 	return EINVAL;
5255     memcpy(user->pw, pw, len);
5256     user->pw2_set = 1;
5257     return 0;
5258 }
5259 
5260 int
ipmi_user_get_link_auth_enabled(ipmi_user_t * user,unsigned int * val)5261 ipmi_user_get_link_auth_enabled(ipmi_user_t *user, unsigned int *val)
5262 {
5263     *val = user->link_enabled;
5264     return 0;
5265 }
5266 
5267 int
ipmi_user_set_link_auth_enabled(ipmi_user_t * user,unsigned int val)5268 ipmi_user_set_link_auth_enabled(ipmi_user_t *user, unsigned int val)
5269 {
5270     user->link_enabled = val;
5271     user->link_enabled_set = 1;
5272     return 0;
5273 }
5274 
5275 int
ipmi_user_get_msg_auth_enabled(ipmi_user_t * user,unsigned int * val)5276 ipmi_user_get_msg_auth_enabled(ipmi_user_t *user, unsigned int *val)
5277 {
5278     *val = user->msg_enabled;
5279     return 0;
5280 }
5281 
5282 int
ipmi_user_set_msg_auth_enabled(ipmi_user_t * user,unsigned int val)5283 ipmi_user_set_msg_auth_enabled(ipmi_user_t *user, unsigned int val)
5284 {
5285     user->msg_enabled = val;
5286     user->msg_enabled_set = 1;
5287     return 0;
5288 }
5289 
5290 int
ipmi_user_get_access_cb_only(ipmi_user_t * user,unsigned int * val)5291 ipmi_user_get_access_cb_only(ipmi_user_t *user, unsigned int *val)
5292 {
5293     *val = user->cb_only;
5294     return 0;
5295 }
5296 
5297 int
ipmi_user_set_access_cb_only(ipmi_user_t * user,unsigned int val)5298 ipmi_user_set_access_cb_only(ipmi_user_t *user, unsigned int val)
5299 {
5300     user->cb_only = val;
5301     user->cb_only_set = 1;
5302     return 0;
5303 }
5304 
5305 int
ipmi_user_get_privilege_limit(ipmi_user_t * user,unsigned int * val)5306 ipmi_user_get_privilege_limit(ipmi_user_t *user, unsigned int *val)
5307 {
5308     *val = user->privilege_limit;
5309     return 0;
5310 }
5311 
5312 int
ipmi_user_set_privilege_limit(ipmi_user_t * user,unsigned int val)5313 ipmi_user_set_privilege_limit(ipmi_user_t *user, unsigned int val)
5314 {
5315     user->privilege_limit = val;
5316     user->privilege_limit_set = 1;
5317     return 0;
5318 }
5319 
5320 int
ipmi_user_get_session_limit(ipmi_user_t * user,unsigned int * val)5321 ipmi_user_get_session_limit(ipmi_user_t *user, unsigned int *val)
5322 {
5323     if (!user->session_limit_read)
5324 	return ENOSYS;
5325     *val = user->session_limit;
5326     return 0;
5327 }
5328 
5329 int
ipmi_user_set_session_limit(ipmi_user_t * user,unsigned int val)5330 ipmi_user_set_session_limit(ipmi_user_t *user, unsigned int val)
5331 {
5332     user->session_limit = val;
5333     user->session_limit_set = 1;
5334     user->session_limit_read = 1;
5335     return 0;
5336 }
5337 
5338 int
ipmi_user_get_enable(ipmi_user_t * user,unsigned int * val)5339 ipmi_user_get_enable(ipmi_user_t *user, unsigned int *val)
5340 {
5341     if (!user->enable_read)
5342 	return ENOSYS;
5343     *val = user->enable;
5344     return 0;
5345 }
5346 
5347 int
ipmi_user_set_enable(ipmi_user_t * user,unsigned int val)5348 ipmi_user_set_enable(ipmi_user_t *user, unsigned int val)
5349 {
5350     user->enable = val;
5351     user->enable_set = 1;
5352     user->enable_read = 1;
5353     return 0;
5354 }
5355 
5356 int
ipmi_user_set_all(ipmi_user_t * user)5357 ipmi_user_set_all(ipmi_user_t *user)
5358 {
5359     user->cb_only_set = 1;
5360     user->link_enabled_set = 1;
5361     user->msg_enabled_set = 1;
5362     user->privilege_limit_set = 1;
5363     user->session_limit_set = user->session_limit_read;
5364     user->enable_set = user->enable_read;
5365     user->name_set = 1;
5366     return 0;
5367 }
5368 
5369