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