1 /*
2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistribution of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistribution in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * Neither the name of Sun Microsystems, Inc. or the names of
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * This software is provided "AS IS," without a warranty of any kind.
20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 */
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <time.h>
37
38 #include <ipmitool/bswap.h>
39 #include <ipmitool/helper.h>
40 #include <ipmitool/ipmi.h>
41 #include <ipmitool/log.h>
42 #include <ipmitool/ipmi_intf.h>
43 #include <ipmitool/ipmi_strings.h>
44 #include <ipmitool/ipmi_chassis.h>
45
46 extern int verbose;
47
48 int
ipmi_chassis_power_status(struct ipmi_intf * intf)49 ipmi_chassis_power_status(struct ipmi_intf * intf)
50 {
51 struct ipmi_rs * rsp;
52 struct ipmi_rq req;
53
54 memset(&req, 0, sizeof(req));
55 req.msg.netfn = IPMI_NETFN_CHASSIS;
56 req.msg.cmd = 0x1;
57 req.msg.data_len = 0;
58
59 rsp = intf->sendrecv(intf, &req);
60 if (rsp == NULL) {
61 lprintf(LOG_ERR, "Unable to get Chassis Power Status");
62 return -1;
63 }
64 if (rsp->ccode > 0) {
65 lprintf(LOG_ERR, "Get Chassis Power Status failed: %s",
66 val2str(rsp->ccode, completion_code_vals));
67 return -1;
68 }
69
70 return rsp->data[0] & 1;
71 }
72
73 static int
ipmi_chassis_print_power_status(struct ipmi_intf * intf)74 ipmi_chassis_print_power_status(struct ipmi_intf * intf)
75 {
76 int ps = ipmi_chassis_power_status(intf);
77
78 if (ps < 0)
79 return -1;
80
81 printf("Chassis Power is %s\n", ps ? "on" : "off");
82
83 return 0;
84 }
85
86 int
ipmi_chassis_power_control(struct ipmi_intf * intf,uint8_t ctl)87 ipmi_chassis_power_control(struct ipmi_intf * intf, uint8_t ctl)
88 {
89 struct ipmi_rs * rsp;
90 struct ipmi_rq req;
91
92 memset(&req, 0, sizeof(req));
93 req.msg.netfn = IPMI_NETFN_CHASSIS;
94 req.msg.cmd = 0x2;
95 req.msg.data = &ctl;
96 req.msg.data_len = 1;
97
98 rsp = intf->sendrecv(intf, &req);
99 if (rsp == NULL) {
100 lprintf(LOG_ERR, "Unable to set Chassis Power Control to %s",
101 val2str(ctl, ipmi_chassis_power_control_vals));
102 return -1;
103 }
104 if (rsp->ccode > 0) {
105 lprintf(LOG_ERR, "Set Chassis Power Control to %s failed: %s",
106 val2str(ctl, ipmi_chassis_power_control_vals),
107 val2str(rsp->ccode, completion_code_vals));
108 return -1;
109 }
110
111 printf("Chassis Power Control: %s\n",
112 val2str(ctl, ipmi_chassis_power_control_vals));
113
114 #if 0 /* this can cause sessions to hang around after power commands */
115 /* sessions often get lost when changing chassis power */
116 intf->abort = 1;
117 #endif
118
119 return 0;
120 }
121
122 static int
ipmi_chassis_identify(struct ipmi_intf * intf,char * arg)123 ipmi_chassis_identify(struct ipmi_intf * intf, char * arg)
124 {
125 struct ipmi_rq req;
126 struct ipmi_rs * rsp;
127 int rc = (-3);
128
129 struct {
130 uint8_t interval;
131 uint8_t force_on;
132 } identify_data = { .interval = 0, .force_on = 0 };
133
134 memset(&req, 0, sizeof(req));
135 req.msg.netfn = IPMI_NETFN_CHASSIS;
136 req.msg.cmd = 0x4;
137
138 if (arg != NULL) {
139 if (strncmp(arg, "force", 5) == 0) {
140 identify_data.force_on = 1;
141 } else {
142 if ( (rc = str2uchar(arg, &identify_data.interval)) != 0) {
143 if (rc == (-2)) {
144 lprintf(LOG_ERR, "Invalid interval given.");
145 } else {
146 lprintf(LOG_ERR, "Given interval is too big.");
147 }
148 return (-1);
149 }
150 }
151 req.msg.data = (uint8_t *)&identify_data;
152 /* The Force Identify On byte is optional and not
153 * supported by all devices-- if force is not specified,
154 * we pass only one data byte; if specified, we pass two
155 * data bytes and check for an error completion code
156 */
157 req.msg.data_len = (identify_data.force_on) ? 2 : 1;
158 }
159
160 rsp = intf->sendrecv(intf, &req);
161 if (rsp == NULL) {
162 lprintf(LOG_ERR, "Unable to set Chassis Identify");
163 return -1;
164 }
165 if (rsp->ccode > 0) {
166 lprintf(LOG_ERR, "Set Chassis Identify failed: %s",
167 val2str(rsp->ccode, completion_code_vals));
168 if (identify_data.force_on != 0) {
169 /* Intel SE7501WV2 F/W 1.2 returns CC 0xC7, but
170 * the IPMI v1.5 spec does not standardize a CC
171 * if unsupported, so we warn
172 */
173 lprintf(LOG_WARNING, "Chassis may not support Force Identify On\n");
174 }
175 return -1;
176 }
177
178 printf("Chassis identify interval: ");
179 if (arg == NULL) {
180 printf("default (15 seconds)\n");
181 } else {
182 if (identify_data.force_on != 0) {
183 printf("indefinite\n");
184 } else {
185 if (identify_data.interval == 0)
186 printf("off\n");
187 else
188 printf("%i seconds\n", identify_data.interval);
189 }
190 }
191 return 0;
192 }
193
194 static int
ipmi_chassis_poh(struct ipmi_intf * intf)195 ipmi_chassis_poh(struct ipmi_intf * intf)
196 {
197 struct ipmi_rs * rsp;
198 struct ipmi_rq req;
199 uint8_t mins_per_count;
200 uint32_t count;
201 float minutes;
202 uint32_t days, hours;
203
204 memset(&req, 0, sizeof(req));
205 req.msg.netfn = IPMI_NETFN_CHASSIS;
206 req.msg.cmd = 0xf;
207
208 rsp = intf->sendrecv(intf, &req);
209 if (rsp == NULL) {
210 lprintf(LOG_ERR, "Unable to get Chassis Power-On-Hours");
211 return -1;
212 }
213 if (rsp->ccode > 0) {
214 lprintf(LOG_ERR, "Get Chassis Power-On-Hours failed: %s",
215 val2str(rsp->ccode, completion_code_vals));
216 return -1;
217 }
218
219 mins_per_count = rsp->data[0];
220 memcpy(&count, rsp->data+1, 4);
221 #if WORDS_BIGENDIAN
222 count = BSWAP_32(count);
223 #endif
224
225 minutes = (float)count * mins_per_count;
226 days = minutes / 1440;
227 minutes -= (float)days * 1440;
228 hours = minutes / 60;
229 minutes -= hours * 60;
230
231 if (mins_per_count < 60) {
232 printf("POH Counter : %i days, %i hours, %li minutes\n",
233 days, hours, (long)minutes);
234 } else {
235 printf("POH Counter : %i days, %i hours\n", days, hours);
236 }
237
238 return 0;
239 }
240
241 static int
ipmi_chassis_restart_cause(struct ipmi_intf * intf)242 ipmi_chassis_restart_cause(struct ipmi_intf * intf)
243 {
244 struct ipmi_rs * rsp;
245 struct ipmi_rq req;
246
247 memset(&req, 0, sizeof(req));
248 req.msg.netfn = IPMI_NETFN_CHASSIS;
249 req.msg.cmd = 0x7;
250
251 rsp = intf->sendrecv(intf, &req);
252 if (rsp == NULL) {
253 lprintf(LOG_ERR, "Unable to get Chassis Restart Cause");
254 return -1;
255 }
256 if (rsp->ccode > 0) {
257 lprintf(LOG_ERR, "Get Chassis Restart Cause failed: %s",
258 val2str(rsp->ccode, completion_code_vals));
259 return -1;
260 }
261
262 printf("System restart cause: ");
263
264 switch (rsp->data[0] & 0xf) {
265 case 0:
266 printf("unknown\n");
267 break;
268 case 1:
269 printf("chassis power control command\n");
270 break;
271 case 2:
272 printf("reset via pushbutton\n");
273 break;
274 case 3:
275 printf("power-up via pushbutton\n");
276 break;
277 case 4:
278 printf("watchdog expired\n");
279 break;
280 case 5:
281 printf("OEM\n");
282 break;
283 case 6:
284 printf("power-up due to always-restore power policy\n");
285 break;
286 case 7:
287 printf("power-up due to restore-previous power policy\n");
288 break;
289 case 8:
290 printf("reset via PEF\n");
291 break;
292 case 9:
293 printf("power-cycle via PEF\n");
294 break;
295 default:
296 printf("invalid\n");
297 }
298
299 return 0;
300 }
301
302 int
ipmi_chassis_status(struct ipmi_intf * intf)303 ipmi_chassis_status(struct ipmi_intf * intf)
304 {
305 struct ipmi_rs * rsp;
306 struct ipmi_rq req;
307
308 memset(&req, 0, sizeof(req));
309 req.msg.netfn = IPMI_NETFN_CHASSIS;
310 req.msg.cmd = 0x1;
311
312 rsp = intf->sendrecv(intf, &req);
313 if (rsp == NULL) {
314 lprintf(LOG_ERR, "Error sending Chassis Status command");
315 return -1;
316 }
317 if (rsp->ccode > 0) {
318 lprintf(LOG_ERR, "Error sending Chassis Status command: %s",
319 val2str(rsp->ccode, completion_code_vals));
320 return -1;
321 }
322
323 /* byte 1 */
324 printf("System Power : %s\n", (rsp->data[0] & 0x1) ? "on" : "off");
325 printf("Power Overload : %s\n", (rsp->data[0] & 0x2) ? "true" : "false");
326 printf("Power Interlock : %s\n", (rsp->data[0] & 0x4) ? "active" : "inactive");
327 printf("Main Power Fault : %s\n", (rsp->data[0] & 0x8) ? "true" : "false");
328 printf("Power Control Fault : %s\n", (rsp->data[0] & 0x10) ? "true" : "false");
329 printf("Power Restore Policy : ");
330 switch ((rsp->data[0] & 0x60) >> 5) {
331 case 0x0:
332 printf("always-off\n");
333 break;
334 case 0x1:
335 printf("previous\n");
336 break;
337 case 0x2:
338 printf("always-on\n");
339 break;
340 case 0x3:
341 default:
342 printf("unknown\n");
343 }
344
345 /* byte 2 */
346 printf("Last Power Event : ");
347 if (rsp->data[1] & 0x1)
348 printf("ac-failed ");
349 if (rsp->data[1] & 0x2)
350 printf("overload ");
351 if (rsp->data[1] & 0x4)
352 printf("interlock ");
353 if (rsp->data[1] & 0x8)
354 printf("fault ");
355 if (rsp->data[1] & 0x10)
356 printf("command");
357 printf("\n");
358
359 /* byte 3 */
360 printf("Chassis Intrusion : %s\n", (rsp->data[2] & 0x1) ? "active" : "inactive");
361 printf("Front-Panel Lockout : %s\n", (rsp->data[2] & 0x2) ? "active" : "inactive");
362 printf("Drive Fault : %s\n", (rsp->data[2] & 0x4) ? "true" : "false");
363 printf("Cooling/Fan Fault : %s\n", (rsp->data[2] & 0x8) ? "true" : "false");
364
365 if (rsp->data_len > 3) {
366 /* optional byte 4 */
367 if (rsp->data[3] == 0) {
368 printf("Front Panel Control : none\n");
369 } else {
370 printf("Sleep Button Disable : %s\n", (rsp->data[3] & 0x80) ? "allowed" : "not allowed");
371 printf("Diag Button Disable : %s\n", (rsp->data[3] & 0x40) ? "allowed" : "not allowed");
372 printf("Reset Button Disable : %s\n", (rsp->data[3] & 0x20) ? "allowed" : "not allowed");
373 printf("Power Button Disable : %s\n", (rsp->data[3] & 0x10) ? "allowed" : "not allowed");
374 printf("Sleep Button Disabled: %s\n", (rsp->data[3] & 0x08) ? "true" : "false");
375 printf("Diag Button Disabled : %s\n", (rsp->data[3] & 0x04) ? "true" : "false");
376 printf("Reset Button Disabled: %s\n", (rsp->data[3] & 0x02) ? "true" : "false");
377 printf("Power Button Disabled: %s\n", (rsp->data[3] & 0x01) ? "true" : "false");
378 }
379 }
380
381 return 0;
382 }
383
384
385 static int
ipmi_chassis_selftest(struct ipmi_intf * intf)386 ipmi_chassis_selftest(struct ipmi_intf * intf)
387 {
388 struct ipmi_rs * rsp;
389 struct ipmi_rq req;
390
391 memset(&req, 0, sizeof(req));
392 req.msg.netfn = IPMI_NETFN_APP;
393 req.msg.cmd = 0x4;
394
395 rsp = intf->sendrecv(intf, &req);
396 if (rsp == NULL) {
397 lprintf(LOG_ERR, "Error sending Get Self Test command");
398 return -1;
399 }
400 if (rsp->ccode > 0) {
401 lprintf(LOG_ERR, "Error sending Get Self Test command: %s",
402 val2str(rsp->ccode, completion_code_vals));
403 return -1;
404 }
405
406 printf("Self Test Results : ");
407 switch (rsp->data[0]) {
408 case 0x55:
409 printf("passed\n");
410 break;
411
412 case 0x56:
413 printf("not implemented\n");
414 break;
415
416 case 0x57:
417 {
418 int i;
419 const struct valstr broken_dev_vals[] = {
420 { 0, "firmware corrupted" },
421 { 1, "boot block corrupted" },
422 { 2, "FRU Internal Use Area corrupted" },
423 { 3, "SDR Repository empty" },
424 { 4, "IPMB not responding" },
425 { 5, "cannot access BMC FRU" },
426 { 6, "cannot access SDR Repository" },
427 { 7, "cannot access SEL Device" },
428 { 0xff, NULL },
429 };
430 printf("device error\n");
431 for (i=0; i<8; i++) {
432 if (rsp->data[1] & (1<<i)) {
433 printf(" [%s]\n",
434 val2str(i, broken_dev_vals));
435 }
436 }
437 }
438 break;
439
440 case 0x58:
441 printf("Fatal hardware error: %02xh\n", rsp->data[1]);
442 break;
443
444 default:
445 printf("Device-specific failure %02xh:%02xh\n",
446 rsp->data[0], rsp->data[1]);
447 break;
448 }
449
450 return 0;
451 }
452
453 static int
ipmi_chassis_set_bootparam(struct ipmi_intf * intf,uint8_t param,uint8_t * data,int len)454 ipmi_chassis_set_bootparam(struct ipmi_intf * intf, uint8_t param, uint8_t * data, int len)
455 {
456 struct ipmi_rs * rsp;
457 struct ipmi_rq req;
458 uint8_t msg_data[16];
459
460 memset(msg_data, 0, 16);
461 msg_data[0] = param & 0x7f;
462 memcpy(msg_data+1, data, len);
463
464 memset(&req, 0, sizeof(req));
465 req.msg.netfn = IPMI_NETFN_CHASSIS;
466 req.msg.cmd = 0x8;
467 req.msg.data = msg_data;
468 req.msg.data_len = len + 1;
469
470 rsp = intf->sendrecv(intf, &req);
471 if (rsp == NULL) {
472 lprintf(LOG_ERR, "Error setting Chassis Boot Parameter %d", param);
473 return -1;
474 }
475 if (rsp->ccode > 0) {
476 if (param != 0) {
477 lprintf(LOG_ERR, "Set Chassis Boot Parameter %d failed: %s",
478 param, val2str(rsp->ccode, completion_code_vals));
479 }
480 return -1;
481 }
482
483 lprintf(LOG_DEBUG, "Chassis Set Boot Parameter %d to %s", param, buf2str(data, len));
484 return 0;
485 }
486
487 static int
ipmi_chassis_get_bootparam(struct ipmi_intf * intf,char * arg)488 ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
489 {
490 struct ipmi_rs * rsp;
491 struct ipmi_rq req;
492 uint8_t msg_data[3];
493 uint8_t param_id = 0;
494
495 if (arg == NULL)
496 return -1;
497
498 if (str2uchar(arg, ¶m_id) != 0) {
499 lprintf(LOG_ERR, "Invalid parameter '%s' given instead of bootparam.",
500 arg);
501 return (-1);
502 }
503
504 memset(msg_data, 0, 3);
505
506 msg_data[0] = param_id & 0x7f;
507 msg_data[1] = 0;
508 msg_data[2] = 0;
509
510 memset(&req, 0, sizeof(req));
511 req.msg.netfn = IPMI_NETFN_CHASSIS;
512 req.msg.cmd = 0x9;
513 req.msg.data = msg_data;
514 req.msg.data_len = 3;
515
516 rsp = intf->sendrecv(intf, &req);
517 if (rsp == NULL) {
518 lprintf(LOG_ERR, "Error Getting Chassis Boot Parameter %s", arg);
519 return -1;
520 }
521 if (rsp->ccode > 0) {
522 lprintf(LOG_ERR, "Get Chassis Boot Parameter %s failed: %s",
523 arg, val2str(rsp->ccode, completion_code_vals));
524 return -1;
525 }
526
527 if (verbose > 2)
528 printbuf(rsp->data, rsp->data_len, "Boot Option");
529
530 param_id = 0;
531 param_id = (rsp->data[1] & 0x7f);
532
533 printf("Boot parameter version: %d\n", rsp->data[0]);
534 printf("Boot parameter %d is %s\n", rsp->data[1] & 0x7f,
535 (rsp->data[1] & 0x80) ? "invalid/locked" : "valid/unlocked");
536 printf("Boot parameter data: %s\n", buf2str(rsp->data+2, rsp->data_len - 2));
537
538 switch(param_id)
539 {
540 case 0:
541 {
542 printf(" Set In Progress : ");
543 switch((rsp->data[2]) &0x03)
544 {
545 case 0: printf("set complete\n"); break;
546 case 1: printf("set in progress\n"); break;
547 case 2: printf("commit write\n"); break;
548 default: printf("error, reserved bit\n"); break;
549 }
550 }
551 break;
552 case 1:
553 {
554 printf(" Service Partition Selector : ");
555 if((rsp->data[2]) == 0)
556 {
557 printf("unspecified\n");
558 }
559 else
560 {
561 printf("%d\n",(rsp->data[2]));
562 }
563 }
564 break;
565 case 2:
566 {
567 printf( " Service Partition Scan :\n");
568 if((rsp->data[2]&0x03) != 0)
569 {
570 if((rsp->data[2]&0x01) == 0x01)
571 printf(" - Request BIOS to scan\n");
572 if((rsp->data[2]&0x02) == 0x02)
573 printf(" - Service Partition Discovered\n");
574 }
575 else
576 {
577 printf(" No flag set\n");
578 }
579 }
580 break;
581 case 3:
582 {
583 printf( " BMC boot flag valid bit clearing :\n");
584 if((rsp->data[2]&0x1f) != 0)
585 {
586 if((rsp->data[2]&0x10) == 0x10)
587 printf(" - Don't clear valid bit on reset/power cycle cause by PEF\n");
588 if((rsp->data[2]&0x08) == 0x08)
589 printf(" - Don't automatically clear boot flag valid bit on timeout\n");
590 if((rsp->data[2]&0x04) == 0x04)
591 printf(" - Don't clear valid bit on reset/power cycle cause by watchdog\n");
592 if((rsp->data[2]&0x02) == 0x02)
593 printf(" - Don't clear valid bit on push button reset // soft reset\n");
594 if((rsp->data[2]&0x01) == 0x01)
595 printf(" - Don't clear valid bit on power up via power push button or wake event\n");
596 }
597 else
598 {
599 printf(" No flag set\n");
600 }
601 }
602 break;
603 case 4:
604 {
605 printf( " Boot Info Acknowledge :\n");
606 if((rsp->data[3]&0x1f) != 0)
607 {
608 if((rsp->data[3]&0x10) == 0x10)
609 printf(" - OEM has handled boot info\n");
610 if((rsp->data[3]&0x08) == 0x08)
611 printf(" - SMS has handled boot info\n");
612 if((rsp->data[3]&0x04) == 0x04)
613 printf(" - OS // service partition has handled boot info\n");
614 if((rsp->data[3]&0x02) == 0x02)
615 printf(" - OS Loader has handled boot info\n");
616 if((rsp->data[3]&0x01) == 0x01)
617 printf(" - BIOS/POST has handled boot info\n");
618 }
619 else
620 {
621 printf(" No flag set\n");
622 }
623 }
624 break;
625 case 5:
626 {
627 printf( " Boot Flags :\n");
628
629 if((rsp->data[2]&0x80) == 0x80)
630 printf(" - Boot Flag Valid\n");
631 else
632 printf(" - Boot Flag Invalid\n");
633
634 if((rsp->data[2]&0x40) == 0x40)
635 printf(" - Options apply to all future boots\n");
636 else
637 printf(" - Options apply to only next boot\n");
638
639 if((rsp->data[2]&0x20) == 0x20)
640 printf(" - BIOS EFI boot \n");
641 else
642 printf(" - BIOS PC Compatible (legacy) boot \n");
643
644 if((rsp->data[3]&0x80) == 0x80)
645 printf(" - CMOS Clear\n");
646 if((rsp->data[3]&0x40) == 0x40)
647 printf(" - Lock Keyboard\n");
648 printf(" - Boot Device Selector : ");
649 switch( ((rsp->data[3]>>2)&0x0f))
650 {
651 case 0: printf("No override\n"); break;
652 case 1: printf("Force PXE\n"); break;
653 case 2: printf("Force Boot from default Hard-Drive\n"); break;
654 case 3: printf("Force Boot from default Hard-Drive, request Safe-Mode\n"); break;
655 case 4: printf("Force Boot from Diagnostic Partition\n"); break;
656 case 5: printf("Force Boot from CD/DVD\n"); break;
657 case 6: printf("Force Boot into BIOS Setup\n"); break;
658 case 15: printf("Force Boot from Floppy/primary removable media\n"); break;
659 default: printf("Flag error\n"); break;
660 }
661 if((rsp->data[3]&0x02) == 0x02)
662 printf(" - Screen blank\n");
663 if((rsp->data[3]&0x01) == 0x01)
664 printf(" - Lock out Reset buttons\n");
665
666 if((rsp->data[4]&0x80) == 0x80)
667 printf(" - Lock out (power off/sleep request) vi Power Button\n");
668 printf(" - Console Redirection control : ");
669 switch( ((rsp->data[4]>>5)&0x03))
670 {
671 case 0: printf("System Default\n"); break;
672 case 1: printf("Request Quiet Display\n"); break;
673 case 2: printf("Request Verbose Display\n"); break;
674 default: printf("Flag error\n"); break;
675 }
676 if((rsp->data[4]&0x10) == 0x10)
677 printf(" - Force progress event traps\n");
678 if((rsp->data[4]&0x08) == 0x08)
679 printf(" - User password bypass\n");
680 if((rsp->data[4]&0x04) == 0x04)
681 printf(" - Lock Out Sleep Button\n");
682 if((rsp->data[4]&0x02) == 0x02)
683 printf(" - Lock Out Sleep Button\n");
684 printf(" - BIOS verbosity : ");
685 switch( ((rsp->data[4]>>0)&0x03))
686 {
687 case 0: printf("Console redirection occurs per BIOS configuration setting (default)\n"); break;
688 case 1: printf("Suppress (skip) console redirection if enabled\n"); break;
689 case 2: printf("Request console redirection be enabled\n"); break;
690 default: printf("Flag error\n"); break;
691 }
692
693 if((rsp->data[5]&0x08) == 0x08)
694 printf(" - BIOS Shared Mode Override\n");
695 printf(" - BIOS Mux Control Override : ");
696 switch( ((rsp->data[5]>>0)&0x07))
697 {
698 case 0: printf("BIOS uses recommended setting of the mux at the end of POST\n"); break;
699 case 1: printf("Requests BIOS to force mux to BMC at conclusion of POST/start of OS boot\n"); break;
700 case 2: printf("Requests BIOS to force mux to system at conclusion of POST/start of OS boot\n"); break;
701 default: printf("Flag error\n"); break;
702 }
703 }
704 break;
705 case 6:
706 {
707 unsigned long session_id;
708 unsigned long timestamp;
709 char time_buf[40];
710 time_t out_time;
711
712 session_id = ((unsigned long) rsp->data[3]);
713 session_id |= (((unsigned long) rsp->data[4])<<8);
714 session_id |= (((unsigned long) rsp->data[5])<<16);
715 session_id |= (((unsigned long) rsp->data[6])<<24);
716
717 timestamp = ((unsigned long) rsp->data[7]);
718 timestamp |= (((unsigned long) rsp->data[8])<<8);
719 timestamp |= (((unsigned long) rsp->data[9])<<16);
720 timestamp |= (((unsigned long) rsp->data[10])<<24);
721
722 memset(time_buf, 0, 40);
723 strftime(
724 time_buf,
725 sizeof(time_buf),
726 "%m/%d/%Y %H:%M:%S", localtime(&out_time)
727 );
728
729 printf(" Boot Initiator Info :\n");
730 printf(" Channel Number : %d\n", (rsp->data[2] & 0x0f));
731 printf(" Session Id : %08lXh\n",session_id);
732 if(timestamp != 0)
733 {
734 printf(" Timestamp : %08lXh, %s\n",timestamp,time_buf);
735 }
736 else
737 {
738 printf(" Timestamp : %08lXh, undefined\n",timestamp);
739 }
740
741 }
742 break;
743 case 7:
744 {
745 printf(" Selector : %d\n", rsp->data[2] );
746 printf(" Block Data : %s\n", buf2str(rsp->data+3, rsp->data_len - 2));
747 }
748 break;
749 default:
750 printf(" Undefined byte\n");
751 break;
752 }
753
754 return 0;
755 }
756
757 static int
get_bootparam_options(char * optstring,unsigned char * set_flag,unsigned char * clr_flag)758 get_bootparam_options(char *optstring,
759 unsigned char *set_flag, unsigned char *clr_flag)
760 {
761 char *token;
762 char *saveptr = NULL;
763 int optionError = 0;
764 *set_flag = 0;
765 *clr_flag = 0;
766 static struct {
767 char *name;
768 unsigned char value;
769 char *desc;
770 } options[] = {
771 {"PEF", 0x10,
772 "Clear valid bit on reset/power cycle cause by PEF"},
773 {"timeout", 0x08,
774 "Automatically clear boot flag valid bit on timeout"},
775 {"watchdog", 0x04,
776 "Clear valid bit on reset/power cycle cause by watchdog"},
777 {"reset", 0x02,
778 "Clear valid bit on push button reset/soft reset"},
779 {"power", 0x01,
780 "Clear valid bit on power up via power push button or wake event"},
781
782 {NULL} /* End marker */
783 }, *op;
784
785 if (strncmp(optstring, "options=", 8) != 0) {
786 lprintf(LOG_ERR, "No options= keyword found \"%s\"", optstring);
787 return -1;
788 }
789 token = strtok_r(optstring + 8, ",", &saveptr);
790 while (token != NULL) {
791 int setbit = 0;
792 if (strcmp(token, "help") == 0) {
793 optionError = 1;
794 break;
795 }
796 if (strncmp(token, "no-", 3) == 0) {
797 setbit = 1;
798 token += 3;
799 }
800 for (op = options; op->name != NULL; ++op) {
801 if (strncmp(token, op->name, strlen(op->name)) == 0) {
802 if (setbit) {
803 *set_flag |= op->value;
804 } else {
805 *clr_flag |= op->value;
806 }
807 break;
808 }
809 }
810 if (op->name == NULL) {
811 /* Option not found */
812 optionError = 1;
813 if (setbit) {
814 token -=3;
815 }
816 lprintf(LOG_ERR, "Invalid option: %s", token);
817 }
818 token = strtok_r(NULL, ",", &saveptr);
819 }
820 if (optionError) {
821 lprintf(LOG_NOTICE, " Legal options are:");
822 lprintf(LOG_NOTICE, " %-8s: print this message", "help");
823 for (op = options; op->name != NULL; ++op) {
824 lprintf(LOG_NOTICE, " %-8s: %s", op->name, op->desc);
825 }
826 lprintf(LOG_NOTICE, " Any Option may be prepended with no-"
827 " to invert sense of operation\n");
828 return (-1);
829 }
830 return (0);
831 }
832
833 static int
ipmi_chassis_get_bootvalid(struct ipmi_intf * intf)834 ipmi_chassis_get_bootvalid(struct ipmi_intf * intf)
835 {
836 struct ipmi_rs * rsp;
837 struct ipmi_rq req;
838 uint8_t msg_data[3];
839 uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID;
840 memset(msg_data, 0, 3);
841
842 msg_data[0] = param_id & 0x7f;
843 msg_data[1] = 0;
844 msg_data[2] = 0;
845
846 memset(&req, 0, sizeof(req));
847 req.msg.netfn = IPMI_NETFN_CHASSIS;
848 req.msg.cmd = 0x9;
849 req.msg.data = msg_data;
850 req.msg.data_len = 3;
851
852 rsp = intf->sendrecv(intf, &req);
853 if (rsp == NULL) {
854 lprintf(LOG_ERR,
855 "Error Getting Chassis Boot Parameter %d", param_id);
856 return -1;
857 }
858 if (rsp->ccode > 0) {
859 lprintf(LOG_ERR, "Get Chassis Boot Parameter %d failed: %s",
860 param_id, val2str(rsp->ccode, completion_code_vals));
861 return -1;
862 }
863
864 if (verbose > 2)
865 printbuf(rsp->data, rsp->data_len, "Boot Option");
866
867 return(rsp->data[2]);
868 }
869
870 static int
ipmi_chassis_set_bootvalid(struct ipmi_intf * intf,uint8_t set_flag,uint8_t clr_flag)871 ipmi_chassis_set_bootvalid(struct ipmi_intf *intf, uint8_t set_flag, uint8_t clr_flag)
872 {
873 int bootvalid;
874 uint8_t flags[5];
875 int rc = 0;
876 int use_progress = 1;
877 uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID;
878
879 if (use_progress) {
880 /* set set-in-progress flag */
881 memset(flags, 0, 5);
882 flags[0] = 0x01;
883 rc = ipmi_chassis_set_bootparam(intf,
884 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1);
885 if (rc < 0)
886 use_progress = 0;
887 }
888
889 memset(flags, 0, 5);
890 flags[0] = 0x01;
891 flags[1] = 0x01;
892 rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
893 flags, 2);
894
895 if (rc < 0) {
896 if (use_progress) {
897 /* set-in-progress = set-complete */
898 memset(flags, 0, 5);
899 ipmi_chassis_set_bootparam(intf,
900 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
901 flags, 1);
902 }
903 return -1;
904 }
905
906 bootvalid = ipmi_chassis_get_bootvalid(intf);
907
908 if (bootvalid < 0) {
909 if (use_progress) {
910 /* set-in-progress = set-complete */
911 memset(flags, 0, 5);
912 ipmi_chassis_set_bootparam(intf,
913 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
914 flags, 1);
915 }
916 return -1;
917 }
918 flags[0] = (bootvalid & ~clr_flag) | set_flag;
919
920 rc = ipmi_chassis_set_bootparam(intf, param_id, flags, 1);
921
922 if (rc == 0) {
923 if (use_progress) {
924 /* set-in-progress = commit-write */
925 memset(flags, 0, 5);
926 flags[0] = 0x02;
927 ipmi_chassis_set_bootparam(intf,
928 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
929 flags, 1);
930 }
931 }
932
933 if (use_progress) {
934 /* set-in-progress = set-complete */
935 memset(flags, 0, 5);
936 ipmi_chassis_set_bootparam(intf,
937 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
938 flags, 1);
939 }
940
941 return rc;
942 }
943
944 static int
ipmi_chassis_set_bootdev(struct ipmi_intf * intf,char * arg,uint8_t * iflags)945 ipmi_chassis_set_bootdev(struct ipmi_intf * intf, char * arg, uint8_t *iflags)
946 {
947 uint8_t flags[5];
948 int rc = 0;
949 int use_progress = 1;
950
951 if (use_progress) {
952 /* set set-in-progress flag */
953 memset(flags, 0, 5);
954 flags[0] = 0x01;
955 rc = ipmi_chassis_set_bootparam(intf,
956 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1);
957 if (rc < 0)
958 use_progress = 0;
959 }
960
961 memset(flags, 0, 5);
962 flags[0] = 0x01;
963 flags[1] = 0x01;
964 rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
965 flags, 2);
966
967 if (rc < 0) {
968 if (use_progress) {
969 /* set-in-progress = set-complete */
970 memset(flags, 0, 5);
971 ipmi_chassis_set_bootparam(intf,
972 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
973 flags, 1);
974 }
975 return -1;
976 }
977
978 if (iflags == NULL)
979 memset(flags, 0, 5);
980 else
981 memcpy(flags, iflags, sizeof (flags));
982
983 if (arg == NULL)
984 flags[1] |= 0x00;
985 else if (strncmp(arg, "none", 4) == 0)
986 flags[1] |= 0x00;
987 else if (strncmp(arg, "pxe", 3) == 0 ||
988 strncmp(arg, "force_pxe", 9) == 0)
989 flags[1] |= 0x04;
990 else if (strncmp(arg, "disk", 4) == 0 ||
991 strncmp(arg, "force_disk", 10) == 0)
992 flags[1] |= 0x08;
993 else if (strncmp(arg, "safe", 4) == 0 ||
994 strncmp(arg, "force_safe", 10) == 0)
995 flags[1] |= 0x0c;
996 else if (strncmp(arg, "diag", 4) == 0 ||
997 strncmp(arg, "force_diag", 10) == 0)
998 flags[1] |= 0x10;
999 else if (strncmp(arg, "cdrom", 5) == 0 ||
1000 strncmp(arg, "force_cdrom", 11) == 0)
1001 flags[1] |= 0x14;
1002 else if (strncmp(arg, "floppy", 6) == 0 ||
1003 strncmp(arg, "force_floppy", 12) == 0)
1004 flags[1] |= 0x3c;
1005 else if (strncmp(arg, "bios", 4) == 0 ||
1006 strncmp(arg, "force_bios", 10) == 0)
1007 flags[1] |= 0x18;
1008 else {
1009 lprintf(LOG_ERR, "Invalid argument: %s", arg);
1010 if (use_progress) {
1011 /* set-in-progress = set-complete */
1012 memset(flags, 0, 5);
1013 ipmi_chassis_set_bootparam(intf,
1014 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
1015 flags, 1);
1016 }
1017 return -1;
1018 }
1019
1020 /* set flag valid bit */
1021 flags[0] |= 0x80;
1022
1023 rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_BOOT_FLAGS,
1024 flags, 5);
1025 if (rc == 0) {
1026 if (use_progress) {
1027 /* set-in-progress = commit-write */
1028 memset(flags, 0, 5);
1029 flags[0] = 0x02;
1030 ipmi_chassis_set_bootparam(intf,
1031 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
1032 flags, 1);
1033 }
1034
1035 printf("Set Boot Device to %s\n", arg);
1036 }
1037
1038 if (use_progress) {
1039 /* set-in-progress = set-complete */
1040 memset(flags, 0, 5);
1041 ipmi_chassis_set_bootparam(intf,
1042 IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
1043 flags, 1);
1044 }
1045
1046 return rc;
1047 }
1048
1049 static int
ipmi_chassis_power_policy(struct ipmi_intf * intf,uint8_t policy)1050 ipmi_chassis_power_policy(struct ipmi_intf * intf, uint8_t policy)
1051 {
1052 struct ipmi_rs * rsp;
1053 struct ipmi_rq req;
1054
1055 memset(&req, 0, sizeof(req));
1056 req.msg.netfn = IPMI_NETFN_CHASSIS;
1057 req.msg.cmd = 0x6;
1058 req.msg.data = &policy;
1059 req.msg.data_len = 1;
1060
1061 rsp = intf->sendrecv(intf, &req);
1062 if (rsp == NULL) {
1063 lprintf(LOG_ERR, "Error in Power Restore Policy command");
1064 return -1;
1065 }
1066 if (rsp->ccode > 0) {
1067 lprintf(LOG_ERR, "Power Restore Policy command failed: %s",
1068 val2str(rsp->ccode, completion_code_vals));
1069 return -1;
1070 }
1071
1072 if (policy == IPMI_CHASSIS_POLICY_NO_CHANGE) {
1073 printf("Supported chassis power policy: ");
1074 if (rsp->data[0] & (1<<IPMI_CHASSIS_POLICY_ALWAYS_OFF))
1075 printf("always-off ");
1076 if (rsp->data[0] & (1<<IPMI_CHASSIS_POLICY_ALWAYS_ON))
1077 printf("always-on ");
1078 if (rsp->data[0] & (1<<IPMI_CHASSIS_POLICY_PREVIOUS))
1079 printf("previous");
1080 printf("\n");
1081 }
1082 else {
1083 printf("Set chassis power restore policy to ");
1084 switch (policy) {
1085 case IPMI_CHASSIS_POLICY_ALWAYS_ON:
1086 printf("always-on\n");
1087 break;
1088 case IPMI_CHASSIS_POLICY_ALWAYS_OFF:
1089 printf("always-off\n");
1090 break;
1091 case IPMI_CHASSIS_POLICY_PREVIOUS:
1092 printf("previous\n");
1093 break;
1094 default:
1095 printf("unknown\n");
1096 }
1097 }
1098 return 0;
1099 }
1100
1101 int
ipmi_power_main(struct ipmi_intf * intf,int argc,char ** argv)1102 ipmi_power_main(struct ipmi_intf * intf, int argc, char ** argv)
1103 {
1104 int rc = 0;
1105 uint8_t ctl = 0;
1106
1107 if ((argc < 1) || (strncmp(argv[0], "help", 4) == 0)) {
1108 lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft");
1109 return 0;
1110 }
1111 if (strncmp(argv[0], "status", 6) == 0) {
1112 rc = ipmi_chassis_print_power_status(intf);
1113 return rc;
1114 }
1115 if ((strncmp(argv[0], "up", 2) == 0) || (strncmp(argv[0], "on", 2) == 0))
1116 ctl = IPMI_CHASSIS_CTL_POWER_UP;
1117 else if ((strncmp(argv[0], "down", 4) == 0) || (strncmp(argv[0], "off", 3) == 0))
1118 ctl = IPMI_CHASSIS_CTL_POWER_DOWN;
1119 else if (strncmp(argv[0], "cycle", 5) == 0)
1120 ctl = IPMI_CHASSIS_CTL_POWER_CYCLE;
1121 else if (strncmp(argv[0], "reset", 5) == 0)
1122 ctl = IPMI_CHASSIS_CTL_HARD_RESET;
1123 else if (strncmp(argv[0], "diag", 4) == 0)
1124 ctl = IPMI_CHASSIS_CTL_PULSE_DIAG;
1125 else if ((strncmp(argv[0], "acpi", 4) == 0) || (strncmp(argv[0], "soft", 4) == 0))
1126 ctl = IPMI_CHASSIS_CTL_ACPI_SOFT;
1127 else {
1128 lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[0]);
1129 return -1;
1130 }
1131
1132 rc = ipmi_chassis_power_control(intf, ctl);
1133 return rc;
1134 }
1135
1136 void
ipmi_chassis_set_bootflag_help()1137 ipmi_chassis_set_bootflag_help()
1138 {
1139 unsigned char set_flag;
1140 unsigned char clr_flag;
1141 lprintf(LOG_NOTICE, "bootparam set bootflag <device> [options=...]");
1142 lprintf(LOG_NOTICE, " Legal devices are:");
1143 lprintf(LOG_NOTICE, " none : No override");
1144 lprintf(LOG_NOTICE, " force_pxe : Force PXE boot");
1145 lprintf(LOG_NOTICE, " force_disk : Force boot from default Hard-drive");
1146 lprintf(LOG_NOTICE, " force_safe : Force boot from default Hard-drive, request Safe Mode");
1147 lprintf(LOG_NOTICE, " force_diag : Force boot from Diagnostic Partition");
1148 lprintf(LOG_NOTICE, " force_cdrom : Force boot from CD/DVD");
1149 lprintf(LOG_NOTICE, " force_bios : Force boot into BIOS Setup");
1150 get_bootparam_options("options=help", &set_flag, &clr_flag);
1151 }
1152
1153 int
ipmi_chassis_main(struct ipmi_intf * intf,int argc,char ** argv)1154 ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
1155 {
1156 int rc = 0;
1157
1158 if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
1159 lprintf(LOG_NOTICE, "Chassis Commands: status, power, identify, policy, restart_cause, poh, bootdev, bootparam, selftest");
1160 }
1161 else if (strncmp(argv[0], "status", 6) == 0) {
1162 rc = ipmi_chassis_status(intf);
1163 }
1164 else if (strncmp(argv[0], "selftest", 8) == 0) {
1165 rc = ipmi_chassis_selftest(intf);
1166 }
1167 else if (strncmp(argv[0], "power", 5) == 0) {
1168 uint8_t ctl = 0;
1169
1170 if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
1171 lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft");
1172 return 0;
1173 }
1174 if (strncmp(argv[1], "status", 6) == 0) {
1175 rc = ipmi_chassis_print_power_status(intf);
1176 return rc;
1177 }
1178 if ((strncmp(argv[1], "up", 2) == 0) || (strncmp(argv[1], "on", 2) == 0))
1179 ctl = IPMI_CHASSIS_CTL_POWER_UP;
1180 else if ((strncmp(argv[1], "down", 4) == 0) || (strncmp(argv[1], "off", 3) == 0))
1181 ctl = IPMI_CHASSIS_CTL_POWER_DOWN;
1182 else if (strncmp(argv[1], "cycle", 5) == 0)
1183 ctl = IPMI_CHASSIS_CTL_POWER_CYCLE;
1184 else if (strncmp(argv[1], "reset", 5) == 0)
1185 ctl = IPMI_CHASSIS_CTL_HARD_RESET;
1186 else if (strncmp(argv[1], "diag", 4) == 0)
1187 ctl = IPMI_CHASSIS_CTL_PULSE_DIAG;
1188 else if ((strncmp(argv[1], "acpi", 4) == 0) || (strncmp(argv[1], "soft", 4) == 0))
1189 ctl = IPMI_CHASSIS_CTL_ACPI_SOFT;
1190 else {
1191 lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[1]);
1192 return -1;
1193 }
1194
1195 rc = ipmi_chassis_power_control(intf, ctl);
1196 }
1197 else if (strncmp(argv[0], "identify", 8) == 0) {
1198 if (argc < 2) {
1199 rc = ipmi_chassis_identify(intf, NULL);
1200 }
1201 else if (strncmp(argv[1], "help", 4) == 0) {
1202 lprintf(LOG_NOTICE, "chassis identify <interval>");
1203 lprintf(LOG_NOTICE, " default is 15 seconds");
1204 lprintf(LOG_NOTICE, " 0 to turn off");
1205 lprintf(LOG_NOTICE, " force to turn on indefinitely");
1206 } else {
1207 rc = ipmi_chassis_identify(intf, argv[1]);
1208 }
1209 }
1210 else if (strncmp(argv[0], "poh", 3) == 0) {
1211 rc = ipmi_chassis_poh(intf);
1212 }
1213 else if (strncmp(argv[0], "restart_cause", 13) == 0) {
1214 rc = ipmi_chassis_restart_cause(intf);
1215 }
1216 else if (strncmp(argv[0], "policy", 4) == 0) {
1217 if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
1218 lprintf(LOG_NOTICE, "chassis policy <state>");
1219 lprintf(LOG_NOTICE, " list : return supported policies");
1220 lprintf(LOG_NOTICE, " always-on : turn on when power is restored");
1221 lprintf(LOG_NOTICE, " previous : return to previous state when power is restored");
1222 lprintf(LOG_NOTICE, " always-off : stay off after power is restored");
1223 } else {
1224 uint8_t ctl;
1225 if (strncmp(argv[1], "list", 4) == 0)
1226 ctl = IPMI_CHASSIS_POLICY_NO_CHANGE;
1227 else if (strncmp(argv[1], "always-on", 9) == 0)
1228 ctl = IPMI_CHASSIS_POLICY_ALWAYS_ON;
1229 else if (strncmp(argv[1], "previous", 8) == 0)
1230 ctl = IPMI_CHASSIS_POLICY_PREVIOUS;
1231 else if (strncmp(argv[1], "always-off", 10) == 0)
1232 ctl = IPMI_CHASSIS_POLICY_ALWAYS_OFF;
1233 else {
1234 lprintf(LOG_ERR, "Invalid chassis policy: %s", argv[1]);
1235 return -1;
1236 }
1237 rc = ipmi_chassis_power_policy(intf, ctl);
1238 }
1239 }
1240 else if (strncmp(argv[0], "bootparam", 9) == 0) {
1241 if ((argc < 3) || (strncmp(argv[1], "help", 4) == 0)) {
1242 lprintf(LOG_NOTICE, "bootparam get <param #>");
1243 ipmi_chassis_set_bootflag_help();
1244 }
1245 else {
1246 if (strncmp(argv[1], "get", 3) == 0) {
1247 rc = ipmi_chassis_get_bootparam(intf, argv[2]);
1248 }
1249 else if (strncmp(argv[1], "set", 3) == 0) {
1250 unsigned char set_flag=0;
1251 unsigned char clr_flag=0;
1252 if (strncmp(argv[2], "help", 4) == 0 ||
1253 argc < 4 || (argc >= 4 &&
1254 strncmp(argv[2], "bootflag", 8) != 0)) {
1255 ipmi_chassis_set_bootflag_help();
1256 } else {
1257 if (argc == 5) {
1258 get_bootparam_options(argv[4], &set_flag, &clr_flag);
1259 }
1260 rc = ipmi_chassis_set_bootdev(intf, argv[3], NULL);
1261 if (argc == 5 && (set_flag != 0 || clr_flag != 0)) {
1262 rc = ipmi_chassis_set_bootvalid(intf, set_flag, clr_flag);
1263 }
1264 }
1265 }
1266 else
1267 lprintf(LOG_NOTICE, "bootparam get|set <option> [value ...]");
1268 }
1269 }
1270 else if (strncmp(argv[0], "bootdev", 7) == 0) {
1271 if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
1272 lprintf(LOG_NOTICE, "bootdev <device> [clear-cmos=yes|no]");
1273 lprintf(LOG_NOTICE, "bootdev <device> [options=help,...]");
1274 lprintf(LOG_NOTICE, " none : Do not change boot device order");
1275 lprintf(LOG_NOTICE, " pxe : Force PXE boot");
1276 lprintf(LOG_NOTICE, " disk : Force boot from default Hard-drive");
1277 lprintf(LOG_NOTICE, " safe : Force boot from default Hard-drive, request Safe Mode");
1278 lprintf(LOG_NOTICE, " diag : Force boot from Diagnostic Partition");
1279 lprintf(LOG_NOTICE, " cdrom : Force boot from CD/DVD");
1280 lprintf(LOG_NOTICE, " bios : Force boot into BIOS Setup");
1281 lprintf(LOG_NOTICE, " floppy: Force boot from Floppy/primary removable media");
1282 } else {
1283 if (argc < 3)
1284 rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
1285 else if (strncmp(argv[2], "clear-cmos=", 11) == 0) {
1286 if (strncmp(argv[2]+11, "yes", 3) == 0) {
1287 uint8_t flags[5] = {0, (1<<7), 0, 0, 0};
1288 rc = ipmi_chassis_set_bootdev(intf, argv[1], flags);
1289 } else
1290 rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
1291 }
1292 else if (strncmp(argv[2], "options=", 8) == 0) {
1293 char *token;
1294 char *saveptr = NULL;
1295 int optionError = 0;
1296 unsigned char flags[5];
1297 static struct {
1298 char *name;
1299 int i;
1300 unsigned char mask;
1301 unsigned char value;
1302 char *desc;
1303 } options[] = {
1304 /* data 1 */
1305 {"valid", 0, (1<<7), (1<<7),
1306 "Boot flags valid"},
1307 {"persistent", 0, (1<<6), (1<<6),
1308 "Changes are persistent for all future boots"},
1309 {"efiboot", 0, (1<<5), (1<<5),
1310 "Extensible Firmware Interface Boot (EFI)"},
1311 /* data 2 */
1312 {"clear-cmos", 1, (1<<7), (1<<7),
1313 "CMOS clear"},
1314 {"lockkbd", 1, (1<<6), (1<<6),
1315 "Lock Keyboard"},
1316 /* data2[5:2] is parsed elsewhere */
1317 {"screenblank", 1, (1<<1), (1<<1),
1318 "Screen Blank"},
1319 {"lockoutreset", 1, (1<<0), (1<<0),
1320 "Lock out Resetbuttons"},
1321 /* data 3 */
1322 {"lockout_power", 2, (1<<7), (1<<7),
1323 "Lock out (power off/sleep request) via Power Button"},
1324 {"verbose=default", 2, (3<<5), (0<<5),
1325 "Request quiet BIOS display"},
1326 {"verbose=no", 2, (3<<5), (1<<5),
1327 "Request quiet BIOS display"},
1328 {"verbose=yes", 2, (3<<5), (2<<5),
1329 "Request verbose BIOS display"},
1330 {"force_pet", 2, (1<<4), (1<<4),
1331 "Force progress event traps"},
1332 {"upw_bypass", 2, (1<<3), (1<<3),
1333 "User password bypass"},
1334 {"lockout_sleep", 2, (1<<2), (1<<2),
1335 "Log Out Sleep Button"},
1336 {"cons_redirect=default", 2, (3<<0), (0<<0),
1337 "Console redirection occurs per BIOS configuration setting"},
1338 {"cons_redirect=skip", 2, (3<<0), (1<<0),
1339 "Suppress (skip) console redirection if enabled"},
1340 {"cons_redirect=enable", 2, (3<<0), (2<<0),
1341 "Suppress (skip) console redirection if enabled"},
1342 /* data 4 */
1343 /* data4[7:4] reserved */
1344 /* data4[3] BIOS Shared Mode Override, not implemented here */
1345 /* data4[2:0] BIOS Mux Control Override, not implemented here */
1346
1347 /* data5 reserved */
1348
1349 {NULL} /* End marker */
1350 }, *op;
1351
1352 memset(&flags[0], 0, sizeof(flags));
1353 token = strtok_r(argv[2] + 8, ",", &saveptr);
1354 while (token != NULL) {
1355 if (strcmp(token, "help") == 0) {
1356 optionError = 1;
1357 break;
1358 }
1359 for (op = options; op->name != NULL; ++op) {
1360 if (strcmp(token, op->name) == 0) {
1361 flags[op->i] &= op->mask;
1362 flags[op->i] |= op->value;
1363 break;
1364 }
1365 }
1366 if (op->name == NULL) {
1367 /* Option not found */
1368 optionError = 1;
1369 lprintf(LOG_ERR, "Invalid option: %s", token);
1370 }
1371 token = strtok_r(NULL, ",", &saveptr);
1372 }
1373 if (optionError) {
1374 lprintf(LOG_NOTICE, "Legal options settings are:");
1375 lprintf(LOG_NOTICE, "\thelp:\tprint this message");
1376 for (op = options; op->name != NULL; ++op) {
1377 lprintf(LOG_NOTICE, "\t%s:\t%s", op->name, op->desc);
1378 }
1379 return (-1);
1380 }
1381 rc = ipmi_chassis_set_bootdev(intf, argv[1], flags);
1382 }
1383 else
1384 rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
1385 }
1386 }
1387 else {
1388 lprintf(LOG_ERR, "Invalid Chassis command: %s", argv[0]);
1389 return -1;
1390 }
1391
1392 return rc;
1393 }
1394