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