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 <strings.h>
36 #include <stdio.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/select.h>
40 #include <sys/time.h>
41 #include <signal.h>
42 #include <unistd.h>
43
44
45 #include <termios.h>
46
47 #include <ipmitool/helper.h>
48 #include <ipmitool/log.h>
49 #include <ipmitool/ipmi.h>
50 #include <ipmitool/ipmi_strings.h>
51 #include <ipmitool/ipmi_intf.h>
52 #include <ipmitool/ipmi_isol.h>
53
54 static struct termios _saved_tio;
55 static int _in_raw_mode = 0;
56
57 extern int verbose;
58
59 #define ISOL_ESCAPE_CHARACTER '~'
60
61 /*
62 * ipmi_get_isol_info
63 */
ipmi_get_isol_info(struct ipmi_intf * intf,struct isol_config_parameters * params)64 static int ipmi_get_isol_info(struct ipmi_intf * intf,
65 struct isol_config_parameters * params)
66 {
67 struct ipmi_rs * rsp;
68 struct ipmi_rq req;
69 unsigned char data[6];
70
71 memset(&req, 0, sizeof(req));
72 req.msg.netfn = IPMI_NETFN_ISOL;
73 req.msg.cmd = GET_ISOL_CONFIG;
74 req.msg.data = data;
75 req.msg.data_len = 4;
76
77 /* GET ISOL ENABLED CONFIG */
78
79 memset(data, 0, 6);
80 data[0] = 0x00;
81 data[1] = ISOL_ENABLE_PARAM;
82 data[2] = 0x00; /* block */
83 data[3] = 0x00; /* selector */
84
85 rsp = intf->sendrecv(intf, &req);
86 if (rsp == NULL) {
87 lprintf(LOG_ERR, "Error in Get ISOL Config Command");
88 return -1;
89 }
90 if (rsp->ccode == 0xc1) {
91 lprintf(LOG_ERR, "IPMI v1.5 Serial Over Lan (ISOL) not supported!");
92 return -1;
93 }
94 if (rsp->ccode > 0) {
95 lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
96 val2str(rsp->ccode, completion_code_vals));
97 return -1;
98 }
99 params->enabled = rsp->data[1];
100
101 /* GET ISOL AUTHENTICATON CONFIG */
102
103 memset(data, 0, 6);
104 data[0] = 0x00;
105 data[1] = ISOL_AUTHENTICATION_PARAM;
106 data[2] = 0x00; /* block */
107 data[3] = 0x00; /* selector */
108
109 rsp = intf->sendrecv(intf, &req);
110 if (rsp == NULL) {
111 lprintf(LOG_ERR, "Error in Get ISOL Config Command");
112 return -1;
113 }
114 if (rsp->ccode > 0) {
115 lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
116 val2str(rsp->ccode, completion_code_vals));
117 return -1;
118 }
119 params->privilege_level = rsp->data[1];
120
121 /* GET ISOL BAUD RATE CONFIG */
122
123 memset(data, 0, 6);
124 data[0] = 0x00;
125 data[1] = ISOL_BAUD_RATE_PARAM;
126 data[2] = 0x00; /* block */
127 data[3] = 0x00; /* selector */
128
129 rsp = intf->sendrecv(intf, &req);
130 if (rsp == NULL) {
131 lprintf(LOG_ERR, "Error in Get ISOL Config Command");
132 return -1;
133 }
134 if (rsp->ccode > 0) {
135 lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
136 val2str(rsp->ccode, completion_code_vals));
137 return -1;
138 }
139 params->bit_rate = rsp->data[1];
140
141 return 0;
142 }
143
ipmi_print_isol_info(struct ipmi_intf * intf)144 static int ipmi_print_isol_info(struct ipmi_intf * intf)
145 {
146 struct isol_config_parameters params = {0};
147 if (ipmi_get_isol_info(intf, ¶ms))
148 return -1;
149
150 if (csv_output)
151 {
152 printf("%s,", (params.enabled & 0x1)?"true": "false");
153 printf("%s,",
154 val2str((params.privilege_level & 0xf), ipmi_privlvl_vals));
155 printf("%s,",
156 val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals));
157 }
158 else
159 {
160 printf("Enabled : %s\n",
161 (params.enabled & 0x1)?"true": "false");
162 printf("Privilege Level : %s\n",
163 val2str((params.privilege_level & 0xf), ipmi_privlvl_vals));
164 printf("Bit Rate (kbps) : %s\n",
165 val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals));
166 }
167
168 return 0;
169 }
170
ipmi_isol_set_param(struct ipmi_intf * intf,const char * param,const char * value)171 static int ipmi_isol_set_param(struct ipmi_intf * intf,
172 const char *param,
173 const char *value)
174 {
175 struct ipmi_rs * rsp;
176 struct ipmi_rq req;
177 unsigned char data[6];
178 struct isol_config_parameters params = {0};
179
180 /* We need other values to complete the request */
181 if (ipmi_get_isol_info(intf, ¶ms))
182 return -1;
183
184 memset(&req, 0, sizeof(req));
185 req.msg.netfn = IPMI_NETFN_ISOL;
186 req.msg.cmd = SET_ISOL_CONFIG;
187 req.msg.data = data;
188 req.msg.data_len = 3;
189
190 memset(data, 0, 6);
191
192 /*
193 * enabled
194 */
195 if (strcmp(param, "enabled") == 0)
196 {
197 data[1] = ISOL_ENABLE_PARAM;
198 if (strcmp(value, "true") == 0)
199 data[2] = 0x01;
200 else if (strcmp(value, "false") == 0)
201 data[2] = 0x00;
202 else {
203 lprintf(LOG_ERR, "Invalid value %s for parameter %s",
204 value, param);
205 lprintf(LOG_ERR, "Valid values are true and false");
206 return -1;
207 }
208 }
209
210 /*
211 * privilege-level
212 */
213 else if (strcmp(param, "privilege-level") == 0)
214 {
215 data[1] = ISOL_AUTHENTICATION_PARAM;
216 if (! strcmp(value, "user"))
217 data[2] = 0x02;
218 else if (! strcmp(value, "operator"))
219 data[2] = 0x03;
220 else if (! strcmp(value, "admin"))
221 data[2] = 0x04;
222 else if (! strcmp(value, "oem"))
223 data[2] = 0x05;
224 else
225 {
226 lprintf(LOG_ERR, "Invalid value %s for parameter %s",
227 value, param);
228 lprintf(LOG_ERR, "Valid values are user, operator, admin, and oem");
229 return -1;
230 }
231 /* We need to mask bit7 from the fetched value */
232 data[2] |= (params.privilege_level & 0x80) ? 0x80 : 0x00;
233 }
234
235 /*
236 * bit-rate
237 */
238 else if (strcmp(param, "bit-rate") == 0)
239 {
240 data[1] = ISOL_BAUD_RATE_PARAM;
241 if (strncmp(value, "9.6", 3) == 0) {
242 data[2] = 0x06;
243 }
244 else if (strncmp(value, "19.2", 4) == 0) {
245 data[2] = 0x07;
246 }
247 else if (strncmp(value, "38.4", 4) == 0) {
248 data[2] = 0x08;
249 }
250 else if (strncmp(value, "57.6", 4) == 0) {
251 data[2] = 0x09;
252 }
253 else if (strncmp(value, "115.2", 5) == 0) {
254 data[2] = 0x0A;
255 }
256 else {
257 lprintf(LOG_ERR, "ISOL - Unsupported baud rate: %s", value);
258 lprintf(LOG_ERR, "Valid values are 9.6, 19.2, 38.4, 57.6 and 115.2");
259 return -1;
260 }
261 }
262 else
263 {
264 lprintf(LOG_ERR, "Error: invalid ISOL parameter %s", param);
265 return -1;
266 }
267
268
269 /*
270 * Execute the request
271 */
272
273 rsp = intf->sendrecv(intf, &req);
274 if (rsp == NULL) {
275 lprintf(LOG_ERR, "Error setting ISOL parameter '%s'", param);
276 return -1;
277 }
278 if (rsp->ccode > 0) {
279 lprintf(LOG_ERR, "Error setting ISOL parameter '%s': %s",
280 param, val2str(rsp->ccode, completion_code_vals));
281 return -1;
282 }
283
284 return 0;
285 }
286
287 static void
leave_raw_mode(void)288 leave_raw_mode(void)
289 {
290 if (!_in_raw_mode)
291 return;
292 if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1)
293 perror("tcsetattr");
294 else
295 _in_raw_mode = 0;
296 }
297
298
299
300 static void
enter_raw_mode(void)301 enter_raw_mode(void)
302 {
303 struct termios tio;
304 if (tcgetattr(fileno(stdin), &tio) == -1) {
305 perror("tcgetattr");
306 return;
307 }
308 _saved_tio = tio;
309 tio.c_iflag |= IGNPAR;
310 tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF)\
311 ;
312 tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
313 // #ifdef IEXTEN
314 tio.c_lflag &= ~IEXTEN;
315 // #endif
316 tio.c_oflag &= ~OPOST;
317 tio.c_cc[VMIN] = 1;
318 tio.c_cc[VTIME] = 0;
319 if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1)
320 perror("tcsetattr");
321 else
322 _in_raw_mode = 1;
323 }
324
325
326 static void
sendBreak(struct ipmi_intf * intf)327 sendBreak(struct ipmi_intf * intf)
328 {
329 struct ipmi_v2_payload v2_payload;
330
331 memset(&v2_payload, 0, sizeof(v2_payload));
332
333 v2_payload.payload.sol_packet.character_count = 0;
334 v2_payload.payload.sol_packet.generate_break = 1;
335
336 intf->send_sol(intf, &v2_payload);
337 }
338
339 /*
340 * suspendSelf
341 *
342 * Put ourself in the background
343 *
344 * param bRestoreTty specifies whether we will put our self back
345 * in raw mode when we resume
346 */
347 static void
suspendSelf(int bRestoreTty)348 suspendSelf(int bRestoreTty)
349 {
350 leave_raw_mode();
351 kill(getpid(), SIGTSTP);
352
353 if (bRestoreTty)
354 enter_raw_mode();
355 }
356
357
358
359 /*
360 * printiSolEscapeSequences
361 *
362 * Send some useful documentation to the user
363 */
364 static void
printiSolEscapeSequences(void)365 printiSolEscapeSequences(void)
366 {
367 printf(
368 "%c?\n\
369 Supported escape sequences:\n\
370 %c. - terminate connection\n\
371 %c^Z - suspend ipmitool\n\
372 %c^X - suspend ipmitool, but don't restore tty on restart\n\
373 %cB - send break\n\
374 %c? - this message\n\
375 %c%c - send the escape character by typing it twice\n\
376 (Note that escapes are only recognized immediately after newline.)\n",
377 ISOL_ESCAPE_CHARACTER,
378 ISOL_ESCAPE_CHARACTER,
379 ISOL_ESCAPE_CHARACTER,
380 ISOL_ESCAPE_CHARACTER,
381 ISOL_ESCAPE_CHARACTER,
382 ISOL_ESCAPE_CHARACTER,
383 ISOL_ESCAPE_CHARACTER,
384 ISOL_ESCAPE_CHARACTER);
385 }
386
387
388
389 /*
390 * output
391 *
392 * Send the specified data to stdout
393 */
394 static void
output(struct ipmi_rs * rsp)395 output(struct ipmi_rs * rsp)
396 {
397 if (rsp)
398 {
399 int i;
400 for (i = 0; i < rsp->data_len; ++i)
401 putc(rsp->data[i], stdout);
402
403 fflush(stdout);
404 }
405 }
406
407 /*
408 * ipmi_isol_deactivate
409 */
410 static int
ipmi_isol_deactivate(struct ipmi_intf * intf)411 ipmi_isol_deactivate(struct ipmi_intf * intf)
412 {
413 struct ipmi_rs * rsp;
414 struct ipmi_rq req;
415 uint8_t data[6];
416
417 memset(&req, 0, sizeof(req));
418 req.msg.netfn = IPMI_NETFN_ISOL;
419 req.msg.cmd = ACTIVATE_ISOL;
420 req.msg.data = data;
421 req.msg.data_len = 5;
422
423 memset(data, 0, 6);
424 data[0] = 0x00; /* Deactivate */
425 data[1] = 0x00;
426 data[2] = 0x00;
427 data[3] = 0x00;
428 data[5] = 0x00;
429
430 rsp = intf->sendrecv(intf, &req);
431 if (rsp == NULL) {
432 lprintf(LOG_ERR, "Error deactivating ISOL");
433 return -1;
434 }
435 if (rsp->ccode > 0) {
436 lprintf(LOG_ERR, "Error deactivating ISOL: %s",
437 val2str(rsp->ccode, completion_code_vals));
438 return -1;
439 }
440 /* response contain 4 additional bytes : 80 00 32 ff
441 Don't know what to use them for yet... */
442 return 0;
443 }
444
445 /*
446 * processiSolUserInput
447 *
448 * Act on user input into the ISOL session. The only reason this
449 * is complicated is that we have to process escape sequences.
450 *
451 * return 0 on success
452 * 1 if we should exit
453 * < 0 on error (BMC probably closed the session)
454 */
455 static int
processiSolUserInput(struct ipmi_intf * intf,uint8_t * input,uint16_t buffer_length)456 processiSolUserInput(struct ipmi_intf * intf,
457 uint8_t * input,
458 uint16_t buffer_length)
459 {
460 static int escape_pending = 0;
461 static int last_was_cr = 1;
462 struct ipmi_v2_payload v2_payload;
463 int length = 0;
464 int retval = 0;
465 char ch;
466 int i;
467
468 memset(&v2_payload, 0, sizeof(v2_payload));
469
470 /*
471 * Our first order of business is to check the input for escape
472 * sequences to act on.
473 */
474 for (i = 0; i < buffer_length; ++i)
475 {
476 ch = input[i];
477
478 if (escape_pending){
479 escape_pending = 0;
480
481 /*
482 * Process a possible escape sequence.
483 */
484 switch (ch) {
485 case '.':
486 printf("%c. [terminated ipmitool]\n", ISOL_ESCAPE_CHARACTER);
487 retval = 1;
488 break;
489 case 'Z' - 64:
490 printf("%c^Z [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER);
491 suspendSelf(1); /* Restore tty back to raw */
492 continue;
493
494 case 'X' - 64:
495 printf("%c^X [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER);
496 suspendSelf(0); /* Don't restore to raw mode */
497 continue;
498
499 case 'B':
500 printf("%cb [send break]\n", ISOL_ESCAPE_CHARACTER);
501 sendBreak(intf);
502 continue;
503
504 case '?':
505 printiSolEscapeSequences();
506 continue;
507 default:
508 if (ch != ISOL_ESCAPE_CHARACTER)
509 v2_payload.payload.sol_packet.data[length++] =
510 ISOL_ESCAPE_CHARACTER;
511 v2_payload.payload.sol_packet.data[length++] = ch;
512 }
513 }
514
515 else
516 {
517 if (last_was_cr && (ch == ISOL_ESCAPE_CHARACTER)) {
518 escape_pending = 1;
519 continue;
520 }
521
522 v2_payload.payload.sol_packet.data[length++] = ch;
523 }
524
525
526 /*
527 * Normal character. Record whether it was a newline.
528 */
529 last_was_cr = (ch == '\r' || ch == '\n');
530 }
531
532 /*
533 * If there is anything left to process we dispatch it to the BMC,
534 * send intf->session->sol_data.max_outbound_payload_size bytes
535 * at a time.
536 */
537 if (length)
538 {
539 struct ipmi_rs * rsp;
540
541 v2_payload.payload.sol_packet.flush_outbound = 1; /* Not sure if necessary ? */
542 v2_payload.payload.sol_packet.character_count = length;
543 rsp = intf->send_sol(intf, &v2_payload);
544
545 if (! rsp) {
546 lprintf(LOG_ERR, "Error sending SOL data");
547 retval = -1;
548 }
549
550 /* If the sequence number is set we know we have new data */
551 else if ((rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) &&
552 (rsp->payload.sol_packet.packet_sequence_number))
553 output(rsp);
554 }
555 return retval;
556 }
557
558 /*
559 * ipmi_isol_red_pill
560 */
561 static int
ipmi_isol_red_pill(struct ipmi_intf * intf)562 ipmi_isol_red_pill(struct ipmi_intf * intf)
563 {
564 char * buffer;
565 int numRead;
566 int bShouldExit = 0;
567 int bBmcClosedSession = 0;
568 fd_set read_fds;
569 struct timeval tv;
570 int retval;
571 int buffer_size = 255;
572 int timedout = 0;
573
574 buffer = (char*)malloc(buffer_size);
575 if (buffer == NULL) {
576 lprintf(LOG_ERR, "ipmitool: malloc failure");
577 return -1;
578 }
579
580 enter_raw_mode();
581
582 while (! bShouldExit)
583 {
584 FD_ZERO(&read_fds);
585 FD_SET(0, &read_fds);
586 FD_SET(intf->fd, &read_fds);
587
588 /* Wait up to half a second */
589 tv.tv_sec = 0;
590 tv.tv_usec = 500000;
591
592 retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv);
593
594 if (retval)
595 {
596 if (retval == -1)
597 {
598 /* ERROR */
599 perror("select");
600 return -1;
601 }
602
603 timedout = 0;
604
605 /*
606 * Process input from the user
607 */
608 if (FD_ISSET(0, &read_fds))
609 {
610 memset(buffer, 0, buffer_size);
611 numRead = read(fileno(stdin),
612 buffer,
613 buffer_size);
614
615 if (numRead > 0)
616 {
617 int rc = processiSolUserInput(intf, buffer, numRead);
618
619 if (rc)
620 {
621 if (rc < 0)
622 bShouldExit = bBmcClosedSession = 1;
623 else
624 bShouldExit = 1;
625 }
626 }
627 else
628 {
629 bShouldExit = 1;
630 }
631 }
632
633
634 /*
635 * Process input from the BMC
636 */
637 else if (FD_ISSET(intf->fd, &read_fds))
638 {
639 struct ipmi_rs * rs = intf->recv_sol(intf);
640 if (! rs)
641 {
642 bShouldExit = bBmcClosedSession = 1;
643 }
644 else
645 output(rs);
646 }
647
648
649 /*
650 * ERROR in select
651 */
652 else
653 {
654 lprintf(LOG_ERR, "Error: Select returned with nothing to read");
655 bShouldExit = 1;
656 }
657 }
658 else
659 {
660 if ((++timedout) == 20) /* Every 10 seconds we send a keepalive */
661 {
662 intf->keepalive(intf);
663 timedout = 0;
664 }
665 }
666 }
667
668 leave_raw_mode();
669
670 if (bBmcClosedSession)
671 {
672 lprintf(LOG_ERR, "SOL session closed by BMC");
673 }
674 else
675 ipmi_isol_deactivate(intf);
676
677 return 0;
678 }
679
680 /*
681 * ipmi_isol_activate
682 */
683 static int
ipmi_isol_activate(struct ipmi_intf * intf)684 ipmi_isol_activate(struct ipmi_intf * intf)
685 {
686 struct ipmi_rs * rsp;
687 struct ipmi_rq req;
688 uint8_t data[6];
689 struct isol_config_parameters params;
690
691 if (ipmi_get_isol_info(intf, ¶ms))
692 return -1;
693
694 if (!(params.enabled & 0x1)) {
695 lprintf(LOG_ERR, "ISOL is not enabled!");
696 return -1;
697 }
698
699 /*
700 * Setup a callback so that the lanplus processing knows what
701 * to do with packets that come unexpectedly (while waiting for
702 * an ACK, perhaps.
703 */
704 intf->session->sol_data.sol_input_handler = output;
705
706 memset(&req, 0, sizeof(req));
707 req.msg.netfn = IPMI_NETFN_ISOL;
708 req.msg.cmd = ACTIVATE_ISOL;
709 req.msg.data = data;
710 req.msg.data_len = 5;
711
712 memset(data, 0, 6);
713 data[0] = 0x01;
714 data[1] = 0x00;
715 data[2] = 0x00;
716 data[3] = 0x00;
717 data[5] = 0x00;
718
719 rsp = intf->sendrecv(intf, &req);
720 if (NULL != rsp) {
721 switch (rsp->ccode) {
722 case 0x00:
723 if (rsp->data_len == 4) {
724 break;
725 } else {
726 lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
727 "in ISOL activation response",
728 rsp->data_len);
729 return -1;
730 }
731 break;
732 case 0x80:
733 lprintf(LOG_ERR, "Info: ISOL already active on another session");
734 return -1;
735 case 0x81:
736 lprintf(LOG_ERR, "Info: ISOL disabled");
737 return -1;
738 case 0x82:
739 lprintf(LOG_ERR, "Info: ISOL activation limit reached");
740 return -1;
741 default:
742 lprintf(LOG_ERR, "Error activating ISOL: %s",
743 val2str(rsp->ccode, completion_code_vals));
744 return -1;
745 }
746 } else {
747 lprintf(LOG_ERR, "Error: No response activating ISOL");
748 return -1;
749 }
750
751 /* response contain 4 additional bytes : 80 01 32 ff
752 Don't know what to use them for yet... */
753
754 printf("[SOL Session operational. Use %c? for help]\n",
755 ISOL_ESCAPE_CHARACTER);
756
757 /*
758 * At this point we are good to go with our SOL session. We
759 * need to listen to
760 * 1) STDIN for user input
761 * 2) The FD for incoming SOL packets
762 */
763 if (ipmi_isol_red_pill(intf)) {
764 lprintf(LOG_ERR, "Error in SOL session");
765 return -1;
766 }
767
768 return 0;
769 }
770
print_isol_set_usage(void)771 static void print_isol_set_usage(void) {
772 lprintf(LOG_NOTICE, "\nISOL set parameters and values: \n");
773 lprintf(LOG_NOTICE, " enabled true | false");
774 lprintf(LOG_NOTICE, " privilege-level user | operator | admin | oem");
775 lprintf(LOG_NOTICE, " bit-rate "
776 "9.6 | 19.2 | 38.4 | 57.6 | 115.2");
777 lprintf(LOG_NOTICE, "");
778 }
779
print_isol_usage(void)780 static void print_isol_usage(void) {
781 lprintf(LOG_NOTICE, "ISOL Commands: info");
782 lprintf(LOG_NOTICE, " set <parameter> <setting>");
783 lprintf(LOG_NOTICE, " activate");
784 }
785
ipmi_isol_main(struct ipmi_intf * intf,int argc,char ** argv)786 int ipmi_isol_main(struct ipmi_intf * intf, int argc, char ** argv)
787 {
788 int ret = 0;
789
790 /*
791 * Help
792 */
793 if (!argc || !strncmp(argv[0], "help", 4))
794 print_isol_usage();
795
796 /*
797 * Info
798 */
799 else if (!strncmp(argv[0], "info", 4)) {
800 ret = ipmi_print_isol_info(intf);
801 }
802
803 /*
804 * Set a parameter value
805 */
806 else if (!strncmp(argv[0], "set", 3)) {
807 if (argc < 3) {
808 print_isol_set_usage();
809 return -1;
810 }
811 ret = ipmi_isol_set_param(intf, argv[1], argv[2]);
812 }
813
814 /*
815 * Activate
816 */
817 else if (!strncmp(argv[0], "activate", 8)) {
818 ret = ipmi_isol_activate(intf);
819 }
820
821 else {
822 print_isol_usage();
823 ret = -1;
824 }
825
826 return ret;
827 }
828