xref: /openbmc/ipmitool/lib/ipmi_sol.c (revision 2d79e69f)
1c18ec02fSPetter Reinholdtsen /*
2c18ec02fSPetter Reinholdtsen  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3c18ec02fSPetter Reinholdtsen  *
4c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
5c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
6c18ec02fSPetter Reinholdtsen  * are met:
7c18ec02fSPetter Reinholdtsen  *
8c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
9c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
10c18ec02fSPetter Reinholdtsen  *
11c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
12c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
13c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
14c18ec02fSPetter Reinholdtsen  *
15c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
16c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
17c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
18c18ec02fSPetter Reinholdtsen  *
19c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
20c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31c18ec02fSPetter Reinholdtsen  */
32c18ec02fSPetter Reinholdtsen 
33c18ec02fSPetter Reinholdtsen #include <stdlib.h>
34c18ec02fSPetter Reinholdtsen #include <string.h>
35c18ec02fSPetter Reinholdtsen #include <strings.h>
36c18ec02fSPetter Reinholdtsen #include <stdio.h>
37c18ec02fSPetter Reinholdtsen #include <sys/types.h>
38c18ec02fSPetter Reinholdtsen #include <sys/stat.h>
39c18ec02fSPetter Reinholdtsen #include <sys/select.h>
40c18ec02fSPetter Reinholdtsen #include <sys/time.h>
41c18ec02fSPetter Reinholdtsen #include <time.h>
42c18ec02fSPetter Reinholdtsen #include <signal.h>
43c18ec02fSPetter Reinholdtsen #include <unistd.h>
44c18ec02fSPetter Reinholdtsen 
45c18ec02fSPetter Reinholdtsen #if defined(HAVE_CONFIG_H)
46c18ec02fSPetter Reinholdtsen # include <config.h>
47c18ec02fSPetter Reinholdtsen #endif
48c18ec02fSPetter Reinholdtsen 
49c18ec02fSPetter Reinholdtsen #if defined(HAVE_TERMIOS_H)
50c18ec02fSPetter Reinholdtsen # include <termios.h>
51c18ec02fSPetter Reinholdtsen #elif defined (HAVE_SYS_TERMIOS_H)
52c18ec02fSPetter Reinholdtsen # include <sys/termios.h>
53c18ec02fSPetter Reinholdtsen #endif
54c18ec02fSPetter Reinholdtsen 
55c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
56c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
57c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
58c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
59c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sol.h>
60c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
61c18ec02fSPetter Reinholdtsen #include <ipmitool/bswap.h>
62c18ec02fSPetter Reinholdtsen 
63c18ec02fSPetter Reinholdtsen 
64c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SET_IN_PROGRESS           0x00
65c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SOL_ENABLE                0x01
66c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SOL_AUTHENTICATION        0x02
67c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_CHARACTER_INTERVAL        0x03
68c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SOL_RETRY                 0x04
69c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE 0x05
70c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SOL_VOLATILE_BIT_RATE     0x06
71c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SOL_PAYLOAD_CHANNEL       0x07
72c18ec02fSPetter Reinholdtsen #define SOL_PARAMETER_SOL_PAYLOAD_PORT          0x08
73c18ec02fSPetter Reinholdtsen 
74c18ec02fSPetter Reinholdtsen #define MAX_SOL_RETRY 6
75c18ec02fSPetter Reinholdtsen 
76c18ec02fSPetter Reinholdtsen const struct valstr sol_parameter_vals[] = {
77c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SET_IN_PROGRESS,           "Set In Progress (0)" },
78c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SOL_ENABLE,                "Enable (1)" },
79c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SOL_AUTHENTICATION,        "Authentication (2)" },
80c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_CHARACTER_INTERVAL,        "Character Interval (3)" },
81c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SOL_RETRY,                 "Retry (4)" },
82c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE, "Nonvolatile Bitrate (5)" },
83c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SOL_VOLATILE_BIT_RATE,     "Volatile Bitrate (6)" },
84c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SOL_PAYLOAD_CHANNEL,       "Payload Channel (7)" },
85c18ec02fSPetter Reinholdtsen 	{ SOL_PARAMETER_SOL_PAYLOAD_PORT,          "Payload Port (8)" },
86c18ec02fSPetter Reinholdtsen 	{ 0x00, NULL },
87c18ec02fSPetter Reinholdtsen };
88c18ec02fSPetter Reinholdtsen 
89c18ec02fSPetter Reinholdtsen 
90c18ec02fSPetter Reinholdtsen static struct timeval _start_keepalive;
91c18ec02fSPetter Reinholdtsen static struct termios _saved_tio;
92c18ec02fSPetter Reinholdtsen static int            _in_raw_mode = 0;
93c18ec02fSPetter Reinholdtsen static int            _disable_keepalive = 0;
94c18ec02fSPetter Reinholdtsen static int            _use_sol_for_keepalive = 0;
95c18ec02fSPetter Reinholdtsen static int            _keepalive_retries = 0;
96c18ec02fSPetter Reinholdtsen 
97c18ec02fSPetter Reinholdtsen extern int verbose;
98c18ec02fSPetter Reinholdtsen 
99c18ec02fSPetter Reinholdtsen /*
100c18ec02fSPetter Reinholdtsen  * ipmi_sol_payload_access
101c18ec02fSPetter Reinholdtsen  */
102c18ec02fSPetter Reinholdtsen int
ipmi_sol_payload_access(struct ipmi_intf * intf,uint8_t channel,uint8_t userid,int enable)103c18ec02fSPetter Reinholdtsen ipmi_sol_payload_access(struct ipmi_intf * intf, uint8_t channel,
104c18ec02fSPetter Reinholdtsen 		uint8_t userid, int enable)
105c18ec02fSPetter Reinholdtsen {
106c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
107c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
108c18ec02fSPetter Reinholdtsen 	int rc = (-1);
109c18ec02fSPetter Reinholdtsen 	uint8_t data[6];
110c18ec02fSPetter Reinholdtsen 
111c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
112c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
113c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_SET_USER_PAYLOAD_ACCESS;
114c18ec02fSPetter Reinholdtsen 	req.msg.data = data;
115c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 6;
116c18ec02fSPetter Reinholdtsen 
117c18ec02fSPetter Reinholdtsen 	memset(data, 0, 6);
118c18ec02fSPetter Reinholdtsen 	/* channel */
119c18ec02fSPetter Reinholdtsen 	data[0] = channel & 0xf;
120c18ec02fSPetter Reinholdtsen 	/* user id */
121c18ec02fSPetter Reinholdtsen 	data[1] = userid & 0x3f;
122c18ec02fSPetter Reinholdtsen 	if (!enable) {
123c18ec02fSPetter Reinholdtsen 		/* disable */
124c18ec02fSPetter Reinholdtsen 		data[1] |= 0x40;
125c18ec02fSPetter Reinholdtsen 	}
126c18ec02fSPetter Reinholdtsen 	/* payload 1 is SOL */
127c18ec02fSPetter Reinholdtsen 	data[2] = 0x02;
128c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
129c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
130c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error %sabling SOL payload for user %d on channel %d",
131c18ec02fSPetter Reinholdtsen 				enable ? "en" : "dis", userid, channel);
132c18ec02fSPetter Reinholdtsen 		rc = (-1);
133c18ec02fSPetter Reinholdtsen 	} else if (rsp->ccode != 0) {
134c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error %sabling SOL payload for user %d on channel %d: %s",
135c18ec02fSPetter Reinholdtsen 				enable ? "en" : "dis", userid, channel,
136c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
137c18ec02fSPetter Reinholdtsen 		rc = (-1);
138c18ec02fSPetter Reinholdtsen 	} else {
139c18ec02fSPetter Reinholdtsen 		rc = 0;
140c18ec02fSPetter Reinholdtsen 	}
141c18ec02fSPetter Reinholdtsen 	return rc;
142c18ec02fSPetter Reinholdtsen }
143c18ec02fSPetter Reinholdtsen 
144c18ec02fSPetter Reinholdtsen int
ipmi_sol_payload_access_status(struct ipmi_intf * intf,uint8_t channel,uint8_t userid)145c18ec02fSPetter Reinholdtsen ipmi_sol_payload_access_status(struct ipmi_intf * intf,
146c18ec02fSPetter Reinholdtsen 				uint8_t channel,
147c18ec02fSPetter Reinholdtsen 				uint8_t userid)
148c18ec02fSPetter Reinholdtsen {
149c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
150c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
151c18ec02fSPetter Reinholdtsen 	uint8_t data[2];
152c18ec02fSPetter Reinholdtsen 
153c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
154c18ec02fSPetter Reinholdtsen 	req.msg.netfn    = IPMI_NETFN_APP;
155c18ec02fSPetter Reinholdtsen 	req.msg.cmd      = IPMI_GET_USER_PAYLOAD_ACCESS;
156c18ec02fSPetter Reinholdtsen 	req.msg.data     = data;
157c18ec02fSPetter Reinholdtsen 	req.msg.data_len = sizeof(data);
158c18ec02fSPetter Reinholdtsen 
159c18ec02fSPetter Reinholdtsen 	data[0] = channel & 0xf;	/* channel */
160c18ec02fSPetter Reinholdtsen 	data[1] = userid & 0x3f;	/* user id */
161c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
162c18ec02fSPetter Reinholdtsen 
163c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
164c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error. No valid response received.");
165c18ec02fSPetter Reinholdtsen 		return -1;
166c18ec02fSPetter Reinholdtsen 	}
167c18ec02fSPetter Reinholdtsen 
168c18ec02fSPetter Reinholdtsen 	switch(rsp->ccode) {
169c18ec02fSPetter Reinholdtsen 		case 0x00:
170c18ec02fSPetter Reinholdtsen 			if (rsp->data_len != 4) {
171c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error parsing SOL payload status for user %d on channel %d",
172c18ec02fSPetter Reinholdtsen 					userid, channel);
173c18ec02fSPetter Reinholdtsen 				return -1;
174c18ec02fSPetter Reinholdtsen 			}
175c18ec02fSPetter Reinholdtsen 
176c18ec02fSPetter Reinholdtsen 			printf("User %d on channel %d is %sabled\n",
177c18ec02fSPetter Reinholdtsen 				userid, channel, (rsp->data[0] & 0x02) ? "en":"dis");
178c18ec02fSPetter Reinholdtsen 			return 0;
179c18ec02fSPetter Reinholdtsen 
180c18ec02fSPetter Reinholdtsen 		default:
181c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error getting SOL payload status for user %d on channel %d: %s",
182c18ec02fSPetter Reinholdtsen 				userid, channel,
183c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
184c18ec02fSPetter Reinholdtsen 			return -1;
185c18ec02fSPetter Reinholdtsen 	}
186c18ec02fSPetter Reinholdtsen }
187c18ec02fSPetter Reinholdtsen 
188c18ec02fSPetter Reinholdtsen 
189c18ec02fSPetter Reinholdtsen /*
190c18ec02fSPetter Reinholdtsen  * ipmi_get_sol_info
191c18ec02fSPetter Reinholdtsen  */
192c18ec02fSPetter Reinholdtsen int
ipmi_get_sol_info(struct ipmi_intf * intf,uint8_t channel,struct sol_config_parameters * params)193c18ec02fSPetter Reinholdtsen ipmi_get_sol_info(
194c18ec02fSPetter Reinholdtsen 				  struct ipmi_intf * intf,
195c18ec02fSPetter Reinholdtsen 				  uint8_t channel,
196c18ec02fSPetter Reinholdtsen 				  struct sol_config_parameters * params)
197c18ec02fSPetter Reinholdtsen {
198c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
199c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
200c18ec02fSPetter Reinholdtsen 	uint8_t data[4];
201c18ec02fSPetter Reinholdtsen 
202c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
203c18ec02fSPetter Reinholdtsen 	req.msg.netfn    = IPMI_NETFN_TRANSPORT;
204c18ec02fSPetter Reinholdtsen 	req.msg.cmd      = IPMI_GET_SOL_CONFIG_PARAMETERS;
205c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4;
206c18ec02fSPetter Reinholdtsen 	req.msg.data     = data;
207c18ec02fSPetter Reinholdtsen 
208c18ec02fSPetter Reinholdtsen 	/*
209c18ec02fSPetter Reinholdtsen 	 * set in progress
210c18ec02fSPetter Reinholdtsen 	 */
211c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
212c18ec02fSPetter Reinholdtsen 	data[0] = channel;                       /* channel number     */
213c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SET_IN_PROGRESS; /* parameter selector */
214c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                          /* set selector       */
215c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                          /* block selector     */
216c18ec02fSPetter Reinholdtsen 
217c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
218c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
219c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
220c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
221c18ec02fSPetter Reinholdtsen 		return (-1);
222c18ec02fSPetter Reinholdtsen 	}
223c18ec02fSPetter Reinholdtsen 
224c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
225c18ec02fSPetter Reinholdtsen 		case 0x00:
226c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 2) {
227c18ec02fSPetter Reinholdtsen 				params->set_in_progress = rsp->data[1];
228c18ec02fSPetter Reinholdtsen 			} else {
229c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
230c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
231c18ec02fSPetter Reinholdtsen 						rsp->data_len,
232c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
233c18ec02fSPetter Reinholdtsen 			}
234c18ec02fSPetter Reinholdtsen 			break;
235c18ec02fSPetter Reinholdtsen 		case 0x80:
236c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
237c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals));
238c18ec02fSPetter Reinholdtsen 			break;
239c18ec02fSPetter Reinholdtsen 		default:
240c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
241c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
242c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
243c18ec02fSPetter Reinholdtsen 			return (-1);
244c18ec02fSPetter Reinholdtsen 	}
245c18ec02fSPetter Reinholdtsen 
246c18ec02fSPetter Reinholdtsen 	/*
247c18ec02fSPetter Reinholdtsen 	 * SOL enable
248c18ec02fSPetter Reinholdtsen 	 */
249c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
250c18ec02fSPetter Reinholdtsen 	data[0] = channel;                  /* channel number     */
251c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SOL_ENABLE; /* parameter selector */
252c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                     /* set selector       */
253c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                     /* block selector     */
254c18ec02fSPetter Reinholdtsen 
255c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
256c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
257c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
258c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
259c18ec02fSPetter Reinholdtsen 		return (-1);
260c18ec02fSPetter Reinholdtsen 	}
261c18ec02fSPetter Reinholdtsen 
262c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
263c18ec02fSPetter Reinholdtsen 		case 0x00:
264c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 2) {
265c18ec02fSPetter Reinholdtsen 				params->enabled = rsp->data[1];
266c18ec02fSPetter Reinholdtsen 			} else {
267c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
268c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
269c18ec02fSPetter Reinholdtsen 						rsp->data_len,
270c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
271c18ec02fSPetter Reinholdtsen 			}
272c18ec02fSPetter Reinholdtsen 			break;
273c18ec02fSPetter Reinholdtsen 		case 0x80:
274c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
275c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals));
276c18ec02fSPetter Reinholdtsen 			break;
277c18ec02fSPetter Reinholdtsen 		default:
278c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
279c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
280c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
281c18ec02fSPetter Reinholdtsen 			return (-1);
282c18ec02fSPetter Reinholdtsen 	}
283c18ec02fSPetter Reinholdtsen 
284c18ec02fSPetter Reinholdtsen 	/*
285c18ec02fSPetter Reinholdtsen 	 * SOL authentication
286c18ec02fSPetter Reinholdtsen 	 */
287c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
288c18ec02fSPetter Reinholdtsen 	data[0] = channel;                          /* channel number     */
289c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SOL_AUTHENTICATION; /* parameter selector */
290c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                             /* set selector       */
291c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                             /* block selector     */
292c18ec02fSPetter Reinholdtsen 
293c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
294c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
295c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
296c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
297c18ec02fSPetter Reinholdtsen 		return (-1);
298c18ec02fSPetter Reinholdtsen 	}
299c18ec02fSPetter Reinholdtsen 
300c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
301c18ec02fSPetter Reinholdtsen 		case 0x00:
302c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 2) {
303c18ec02fSPetter Reinholdtsen 				params->force_encryption     = ((rsp->data[1] & 0x80)? 1 : 0);
304c18ec02fSPetter Reinholdtsen 				params->force_authentication = ((rsp->data[1] & 0x40)? 1 : 0);
305c18ec02fSPetter Reinholdtsen 				params->privilege_level      = rsp->data[1] & 0x0F;
306c18ec02fSPetter Reinholdtsen 			} else {
307c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
308c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
309c18ec02fSPetter Reinholdtsen 						rsp->data_len,
310c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
311c18ec02fSPetter Reinholdtsen 			}
312c18ec02fSPetter Reinholdtsen 			break;
313c18ec02fSPetter Reinholdtsen 		case 0x80:
314c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
315c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals));
316c18ec02fSPetter Reinholdtsen 			break;
317c18ec02fSPetter Reinholdtsen 		default:
318c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
319c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
320c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
321c18ec02fSPetter Reinholdtsen 			return (-1);
322c18ec02fSPetter Reinholdtsen 	}
323c18ec02fSPetter Reinholdtsen 
324c18ec02fSPetter Reinholdtsen 	/*
325c18ec02fSPetter Reinholdtsen 	 * Character accumulate interval and character send interval
326c18ec02fSPetter Reinholdtsen 	 */
327c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
328c18ec02fSPetter Reinholdtsen 	data[0] = channel;                          /* channel number     */
329c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_CHARACTER_INTERVAL; /* parameter selector */
330c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                             /* set selector       */
331c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                             /* block selector     */
332c18ec02fSPetter Reinholdtsen 
333c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
334c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
335c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
336c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
337c18ec02fSPetter Reinholdtsen 		return (-1);
338c18ec02fSPetter Reinholdtsen 	}
339c18ec02fSPetter Reinholdtsen 
340c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
341c18ec02fSPetter Reinholdtsen 		case 0x00:
342c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 3) {
343c18ec02fSPetter Reinholdtsen 				params->character_accumulate_level = rsp->data[1];
344c18ec02fSPetter Reinholdtsen 				params->character_send_threshold   = rsp->data[2];
345c18ec02fSPetter Reinholdtsen 			} else {
346c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
347c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
348c18ec02fSPetter Reinholdtsen 						rsp->data_len,
349c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
350c18ec02fSPetter Reinholdtsen 			}
351c18ec02fSPetter Reinholdtsen 			break;
352c18ec02fSPetter Reinholdtsen 		case 0x80:
353c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
354c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals));
355c18ec02fSPetter Reinholdtsen 			break;
356c18ec02fSPetter Reinholdtsen 		default:
357c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
358c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
359c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
360c18ec02fSPetter Reinholdtsen 			return (-1);
361c18ec02fSPetter Reinholdtsen 	}
362c18ec02fSPetter Reinholdtsen 
363c18ec02fSPetter Reinholdtsen 	/*
364c18ec02fSPetter Reinholdtsen 	 * SOL retry
365c18ec02fSPetter Reinholdtsen 	 */
366c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
367c18ec02fSPetter Reinholdtsen 	data[0] = channel;                 /* channel number     */
368c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SOL_RETRY; /* parameter selector */
369c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                    /* set selector       */
370c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                    /* block selector     */
371c18ec02fSPetter Reinholdtsen 
372c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
373c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
374c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
375c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
376c18ec02fSPetter Reinholdtsen 		return (-1);
377c18ec02fSPetter Reinholdtsen 	}
378c18ec02fSPetter Reinholdtsen 
379c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
380c18ec02fSPetter Reinholdtsen 		case 0x00:
381c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 3) {
382c18ec02fSPetter Reinholdtsen 				params->retry_count    = rsp->data[1];
383c18ec02fSPetter Reinholdtsen 				params->retry_interval = rsp->data[2];
384c18ec02fSPetter Reinholdtsen 			} else {
385c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
386c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
387c18ec02fSPetter Reinholdtsen 						rsp->data_len,
388c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
389c18ec02fSPetter Reinholdtsen 			}
390c18ec02fSPetter Reinholdtsen 			break;
391c18ec02fSPetter Reinholdtsen 		case 0x80:
392c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
393c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals));
394c18ec02fSPetter Reinholdtsen 			break;
395c18ec02fSPetter Reinholdtsen 		default:
396c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
397c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
398c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
399c18ec02fSPetter Reinholdtsen 			return (-1);
400c18ec02fSPetter Reinholdtsen 	}
401c18ec02fSPetter Reinholdtsen 
402c18ec02fSPetter Reinholdtsen 	/*
403c18ec02fSPetter Reinholdtsen 	 * SOL non-volatile bit rate
404c18ec02fSPetter Reinholdtsen 	 */
405c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
406c18ec02fSPetter Reinholdtsen 	data[0] = channel;                                 /* channel number     */
407c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE; /* parameter selector */
408c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                                    /* set selector       */
409c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                                    /* block selector     */
410c18ec02fSPetter Reinholdtsen 
411c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
412c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
413c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
414c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
415c18ec02fSPetter Reinholdtsen 		return (-1);
416c18ec02fSPetter Reinholdtsen 	}
417c18ec02fSPetter Reinholdtsen 
418c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
419c18ec02fSPetter Reinholdtsen 		case 0x00:
420c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 2) {
421c18ec02fSPetter Reinholdtsen 				params->non_volatile_bit_rate = rsp->data[1] & 0x0F;
422c18ec02fSPetter Reinholdtsen 			} else {
423c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
424c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
425c18ec02fSPetter Reinholdtsen 						rsp->data_len,
426c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
427c18ec02fSPetter Reinholdtsen 			}
428c18ec02fSPetter Reinholdtsen 			break;
429c18ec02fSPetter Reinholdtsen 		case 0x80:
430c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
431c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals));
432c18ec02fSPetter Reinholdtsen 			break;
433c18ec02fSPetter Reinholdtsen 		default:
434c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
435c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
436c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
437c18ec02fSPetter Reinholdtsen 			return (-1);
438c18ec02fSPetter Reinholdtsen 	}
439c18ec02fSPetter Reinholdtsen 
440c18ec02fSPetter Reinholdtsen 	/*
441c18ec02fSPetter Reinholdtsen 	 * SOL volatile bit rate
442c18ec02fSPetter Reinholdtsen 	 */
443c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
444c18ec02fSPetter Reinholdtsen 	data[0] = channel;                             /* channel number     */
445c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SOL_VOLATILE_BIT_RATE; /* parameter selector */
446c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                                /* set selector       */
447c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                                /* block selector     */
448c18ec02fSPetter Reinholdtsen 
449c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
450c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
451c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
452c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
453c18ec02fSPetter Reinholdtsen 		return (-1);
454c18ec02fSPetter Reinholdtsen 	}
455c18ec02fSPetter Reinholdtsen 
456c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
457c18ec02fSPetter Reinholdtsen 		case 0x00:
458c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 2) {
459c18ec02fSPetter Reinholdtsen 				params->volatile_bit_rate = rsp->data[1] & 0x0F;
460c18ec02fSPetter Reinholdtsen 			} else {
461c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
462c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
463c18ec02fSPetter Reinholdtsen 						rsp->data_len,
464c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
465c18ec02fSPetter Reinholdtsen 			}
466c18ec02fSPetter Reinholdtsen 			break;
467c18ec02fSPetter Reinholdtsen 		case 0x80:
468c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
469c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals));
470c18ec02fSPetter Reinholdtsen 			break;
471c18ec02fSPetter Reinholdtsen 		default:
472c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
473c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
474c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
475c18ec02fSPetter Reinholdtsen 			return (-1);
476c18ec02fSPetter Reinholdtsen 	}
477c18ec02fSPetter Reinholdtsen 
478c18ec02fSPetter Reinholdtsen 	/*
479c18ec02fSPetter Reinholdtsen 	 * SOL payload channel
480c18ec02fSPetter Reinholdtsen 	 */
481c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
482c18ec02fSPetter Reinholdtsen 	data[0] = channel;                           /* channel number     */
483c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SOL_PAYLOAD_CHANNEL; /* parameter selector */
484c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                              /* set selector       */
485c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                              /* block selector     */
486c18ec02fSPetter Reinholdtsen 
487c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
488c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
489c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
490c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
491c18ec02fSPetter Reinholdtsen 		return (-1);
492c18ec02fSPetter Reinholdtsen 	}
493c18ec02fSPetter Reinholdtsen 
494c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
495c18ec02fSPetter Reinholdtsen 		case 0x00:
496c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 2) {
497c18ec02fSPetter Reinholdtsen 				params->payload_channel = rsp->data[1];
498c18ec02fSPetter Reinholdtsen 			} else {
499c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
500c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
501c18ec02fSPetter Reinholdtsen 						rsp->data_len,
502c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
503c18ec02fSPetter Reinholdtsen 			}
504c18ec02fSPetter Reinholdtsen 			break;
505c18ec02fSPetter Reinholdtsen 		case 0x80:
506c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to 0x%02x",
507c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals), channel);
508c18ec02fSPetter Reinholdtsen 			params->payload_channel = channel;
509c18ec02fSPetter Reinholdtsen 			break;
510c18ec02fSPetter Reinholdtsen 		default:
511c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
512c18ec02fSPetter Reinholdtsen 					val2str(data[1], sol_parameter_vals),
513c18ec02fSPetter Reinholdtsen 					val2str(rsp->ccode, completion_code_vals));
514c18ec02fSPetter Reinholdtsen 			return (-1);
515c18ec02fSPetter Reinholdtsen 	}
516c18ec02fSPetter Reinholdtsen 
517c18ec02fSPetter Reinholdtsen 	/*
518c18ec02fSPetter Reinholdtsen 	 * SOL payload port
519c18ec02fSPetter Reinholdtsen 	 */
520c18ec02fSPetter Reinholdtsen 	memset(data, 0, sizeof(data));
521c18ec02fSPetter Reinholdtsen 	data[0] = channel;                        /* channel number     */
522c18ec02fSPetter Reinholdtsen 	data[1] = SOL_PARAMETER_SOL_PAYLOAD_PORT; /* parameter selector */
523c18ec02fSPetter Reinholdtsen 	data[2] = 0x00;                           /* set selector       */
524c18ec02fSPetter Reinholdtsen 	data[3] = 0x00;                           /* block selector     */
525c18ec02fSPetter Reinholdtsen 
526c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
527c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
528c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
529c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals));
530c18ec02fSPetter Reinholdtsen 		return (-1);
531c18ec02fSPetter Reinholdtsen 	}
532c18ec02fSPetter Reinholdtsen 
533c18ec02fSPetter Reinholdtsen 	switch (rsp->ccode) {
534c18ec02fSPetter Reinholdtsen 		case 0x00:
535c18ec02fSPetter Reinholdtsen 			if (rsp->data_len == 3) {
536c18ec02fSPetter Reinholdtsen 				params->payload_port = (rsp->data[1]) | (rsp->data[2] << 8);
537c18ec02fSPetter Reinholdtsen 			} else {
538c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
539c18ec02fSPetter Reinholdtsen 						"for SOL parameter '%s'",
540c18ec02fSPetter Reinholdtsen 						rsp->data_len,
541c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
542c18ec02fSPetter Reinholdtsen 			}
543c18ec02fSPetter Reinholdtsen 			break;
544c18ec02fSPetter Reinholdtsen 		case 0x80:
545c18ec02fSPetter Reinholdtsen 			if( intf->session != NULL ) {
546c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to %d",
547*eb541367SZdenek Styblik 						val2str(data[1], sol_parameter_vals), intf->ssn_params.port);
548*eb541367SZdenek Styblik 				params->payload_port = intf->ssn_params.port;
549c18ec02fSPetter Reinholdtsen 			} else {
550c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR,
551c18ec02fSPetter Reinholdtsen 						"Info: SOL parameter '%s' not supported - can't determine which "
552c18ec02fSPetter Reinholdtsen 						"payload port to use on NULL session",
553c18ec02fSPetter Reinholdtsen 						val2str(data[1], sol_parameter_vals));
554c18ec02fSPetter Reinholdtsen 						return (-1);
555c18ec02fSPetter Reinholdtsen 			}
556c18ec02fSPetter Reinholdtsen 			break;
557c18ec02fSPetter Reinholdtsen 		default:
558c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
559c18ec02fSPetter Reinholdtsen 				val2str(data[1], sol_parameter_vals),
560c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
561c18ec02fSPetter Reinholdtsen 			return (-1);
562c18ec02fSPetter Reinholdtsen 	}
563c18ec02fSPetter Reinholdtsen 
564c18ec02fSPetter Reinholdtsen 	return 0;
565c18ec02fSPetter Reinholdtsen }
566c18ec02fSPetter Reinholdtsen 
567c18ec02fSPetter Reinholdtsen 
568c18ec02fSPetter Reinholdtsen 
569c18ec02fSPetter Reinholdtsen /*
570c18ec02fSPetter Reinholdtsen  * ipmi_print_sol_info
571c18ec02fSPetter Reinholdtsen  */
572c18ec02fSPetter Reinholdtsen static int
ipmi_print_sol_info(struct ipmi_intf * intf,uint8_t channel)573c18ec02fSPetter Reinholdtsen ipmi_print_sol_info(struct ipmi_intf * intf, uint8_t channel)
574c18ec02fSPetter Reinholdtsen {
575c18ec02fSPetter Reinholdtsen 	struct sol_config_parameters params = {0};
576c18ec02fSPetter Reinholdtsen 	if (ipmi_get_sol_info(intf, channel, &params))
577c18ec02fSPetter Reinholdtsen 		return -1;
578c18ec02fSPetter Reinholdtsen 
579c18ec02fSPetter Reinholdtsen 	if (csv_output)
580c18ec02fSPetter Reinholdtsen 	{
581c18ec02fSPetter Reinholdtsen 		printf("%s,",
582c18ec02fSPetter Reinholdtsen 			   val2str(params.set_in_progress & 0x03,
583c18ec02fSPetter Reinholdtsen 					   ipmi_set_in_progress_vals));
584c18ec02fSPetter Reinholdtsen 		printf("%s,", params.enabled?"true": "false");
585c18ec02fSPetter Reinholdtsen 		printf("%s,", params.force_encryption?"true":"false");
586c18ec02fSPetter Reinholdtsen 		printf("%s,", params.force_encryption?"true":"false");
587c18ec02fSPetter Reinholdtsen 		printf("%s,",
588c18ec02fSPetter Reinholdtsen 			   val2str(params.privilege_level, ipmi_privlvl_vals));
589c18ec02fSPetter Reinholdtsen 		printf("%d,", params.character_accumulate_level * 5);
590c18ec02fSPetter Reinholdtsen 		printf("%d,", params.character_send_threshold);
591c18ec02fSPetter Reinholdtsen 		printf("%d,", params.retry_count);
592c18ec02fSPetter Reinholdtsen 		printf("%d,", params.retry_interval * 10);
593c18ec02fSPetter Reinholdtsen 
594c18ec02fSPetter Reinholdtsen 		printf("%s,",
595c18ec02fSPetter Reinholdtsen 			   val2str(params.volatile_bit_rate, ipmi_bit_rate_vals));
596c18ec02fSPetter Reinholdtsen 
597c18ec02fSPetter Reinholdtsen 		printf("%s,",
598c18ec02fSPetter Reinholdtsen 			   val2str(params.non_volatile_bit_rate, ipmi_bit_rate_vals));
599c18ec02fSPetter Reinholdtsen 
600c18ec02fSPetter Reinholdtsen 		printf("%d,", params.payload_channel);
601c18ec02fSPetter Reinholdtsen 		printf("%d\n", params.payload_port);
602c18ec02fSPetter Reinholdtsen 	}
603c18ec02fSPetter Reinholdtsen 	else
604c18ec02fSPetter Reinholdtsen 	{
605c18ec02fSPetter Reinholdtsen 		printf("Set in progress                 : %s\n",
606c18ec02fSPetter Reinholdtsen 			   val2str(params.set_in_progress & 0x03,
607c18ec02fSPetter Reinholdtsen 					   ipmi_set_in_progress_vals));
608c18ec02fSPetter Reinholdtsen 		printf("Enabled                         : %s\n",
609c18ec02fSPetter Reinholdtsen 			   params.enabled?"true": "false");
610c18ec02fSPetter Reinholdtsen 		printf("Force Encryption                : %s\n",
611c18ec02fSPetter Reinholdtsen 			   params.force_encryption?"true":"false");
612c18ec02fSPetter Reinholdtsen 		printf("Force Authentication            : %s\n",
613c18ec02fSPetter Reinholdtsen 			   params.force_authentication?"true":"false");
614c18ec02fSPetter Reinholdtsen 		printf("Privilege Level                 : %s\n",
615c18ec02fSPetter Reinholdtsen 			   val2str(params.privilege_level, ipmi_privlvl_vals));
616c18ec02fSPetter Reinholdtsen 		printf("Character Accumulate Level (ms) : %d\n",
617c18ec02fSPetter Reinholdtsen 			   params.character_accumulate_level * 5);
618c18ec02fSPetter Reinholdtsen 		printf("Character Send Threshold        : %d\n",
619c18ec02fSPetter Reinholdtsen 			   params.character_send_threshold);
620c18ec02fSPetter Reinholdtsen 		printf("Retry Count                     : %d\n",
621c18ec02fSPetter Reinholdtsen 			   params.retry_count);
622c18ec02fSPetter Reinholdtsen 		printf("Retry Interval (ms)             : %d\n",
623c18ec02fSPetter Reinholdtsen 			   params.retry_interval * 10);
624c18ec02fSPetter Reinholdtsen 
625c18ec02fSPetter Reinholdtsen 		printf("Volatile Bit Rate (kbps)        : %s\n",
626c18ec02fSPetter Reinholdtsen 			   val2str(params.volatile_bit_rate, ipmi_bit_rate_vals));
627c18ec02fSPetter Reinholdtsen 
628c18ec02fSPetter Reinholdtsen 		printf("Non-Volatile Bit Rate (kbps)    : %s\n",
629c18ec02fSPetter Reinholdtsen 			   val2str(params.non_volatile_bit_rate, ipmi_bit_rate_vals));
630c18ec02fSPetter Reinholdtsen 
631c18ec02fSPetter Reinholdtsen 		printf("Payload Channel                 : %d (0x%02x)\n",
632c18ec02fSPetter Reinholdtsen 			   params.payload_channel, params.payload_channel);
633c18ec02fSPetter Reinholdtsen 		printf("Payload Port                    : %d\n",
634c18ec02fSPetter Reinholdtsen 			   params.payload_port);
635c18ec02fSPetter Reinholdtsen 	}
636c18ec02fSPetter Reinholdtsen 
637c18ec02fSPetter Reinholdtsen 	return 0;
638c18ec02fSPetter Reinholdtsen }
639c18ec02fSPetter Reinholdtsen 
640c18ec02fSPetter Reinholdtsen 
641c18ec02fSPetter Reinholdtsen 
642c18ec02fSPetter Reinholdtsen /*
643c18ec02fSPetter Reinholdtsen  * Small function to validate that user-supplied SOL
644c18ec02fSPetter Reinholdtsen  * configuration parameter values we store in uint8_t
645c18ec02fSPetter Reinholdtsen  * data type falls within valid range.  With minval
646c18ec02fSPetter Reinholdtsen  * and maxval parameters we can use the same function
647c18ec02fSPetter Reinholdtsen  * to validate parameters that have different ranges
648c18ec02fSPetter Reinholdtsen  * of values.
649c18ec02fSPetter Reinholdtsen  *
650c18ec02fSPetter Reinholdtsen  * function will return -1 if value is not valid, or
651c18ec02fSPetter Reinholdtsen  * will return 0 if valid.
652c18ec02fSPetter Reinholdtsen  */
ipmi_sol_set_param_isvalid_uint8_t(const char * strval,const char * name,int base,uint8_t minval,uint8_t maxval,uint8_t * out_value)653c18ec02fSPetter Reinholdtsen int ipmi_sol_set_param_isvalid_uint8_t( const char *strval,
654c18ec02fSPetter Reinholdtsen 					const char *name,
655c18ec02fSPetter Reinholdtsen 					int base,
656c18ec02fSPetter Reinholdtsen 					uint8_t minval,
657c18ec02fSPetter Reinholdtsen 					uint8_t maxval,
658c18ec02fSPetter Reinholdtsen 					uint8_t *out_value)
659c18ec02fSPetter Reinholdtsen {
660c18ec02fSPetter Reinholdtsen 	if (str2uchar(strval, out_value) != 0 || (*out_value < minval)
661c18ec02fSPetter Reinholdtsen 			|| (*out_value > maxval)) {
662c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid value %s for parameter %s",
663c18ec02fSPetter Reinholdtsen 			strval, name);
664c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Valid values are %d-%d", minval, maxval);
665c18ec02fSPetter Reinholdtsen 		return -1;
666c18ec02fSPetter Reinholdtsen 	}
667c18ec02fSPetter Reinholdtsen 	return 0;
668c18ec02fSPetter Reinholdtsen }
669c18ec02fSPetter Reinholdtsen 
670c18ec02fSPetter Reinholdtsen 
671c18ec02fSPetter Reinholdtsen /*
672c18ec02fSPetter Reinholdtsen  * ipmi_sol_set_param
673c18ec02fSPetter Reinholdtsen  *
674c18ec02fSPetter Reinholdtsen  * Set the specified Serial Over LAN value to the specified
675c18ec02fSPetter Reinholdtsen  * value
676c18ec02fSPetter Reinholdtsen  *
677c18ec02fSPetter Reinholdtsen  * return 0 on success,
678c18ec02fSPetter Reinholdtsen  *        -1 on failure
679c18ec02fSPetter Reinholdtsen  */
680c18ec02fSPetter Reinholdtsen static int
ipmi_sol_set_param(struct ipmi_intf * intf,uint8_t channel,const char * param,const char * value,uint8_t guarded)681c18ec02fSPetter Reinholdtsen ipmi_sol_set_param(struct ipmi_intf * intf,
682c18ec02fSPetter Reinholdtsen 		   uint8_t            channel,
683c18ec02fSPetter Reinholdtsen 		   const char       * param,
684c18ec02fSPetter Reinholdtsen 		   const char       * value,
685c18ec02fSPetter Reinholdtsen 		   uint8_t            guarded)
686c18ec02fSPetter Reinholdtsen {
687c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
688c18ec02fSPetter Reinholdtsen 	struct ipmi_rq   req;
689c18ec02fSPetter Reinholdtsen 	uint8_t          data[4];
690c18ec02fSPetter Reinholdtsen 	int              bGuarded = guarded; /* Use set-in-progress indicator? */
691c18ec02fSPetter Reinholdtsen 
692c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
693c18ec02fSPetter Reinholdtsen 	req.msg.netfn    = IPMI_NETFN_TRANSPORT;           /* 0x0c */
694c18ec02fSPetter Reinholdtsen 	req.msg.cmd      = IPMI_SET_SOL_CONFIG_PARAMETERS; /* 0x21 */
695c18ec02fSPetter Reinholdtsen 	req.msg.data     = data;
696c18ec02fSPetter Reinholdtsen 
697c18ec02fSPetter Reinholdtsen 	data[0] = channel;
698c18ec02fSPetter Reinholdtsen 
699c18ec02fSPetter Reinholdtsen 	/*
700c18ec02fSPetter Reinholdtsen 	 * set-in-progress
701c18ec02fSPetter Reinholdtsen 	 */
702c18ec02fSPetter Reinholdtsen 	if (! strcmp(param, "set-in-progress"))
703c18ec02fSPetter Reinholdtsen 	{
704c18ec02fSPetter Reinholdtsen 		bGuarded = 0; /* We _ARE_ the set-in-progress indicator */
705c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 3;
706c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SET_IN_PROGRESS;
707c18ec02fSPetter Reinholdtsen 
708c18ec02fSPetter Reinholdtsen 		if (! strcmp(value, "set-complete"))
709c18ec02fSPetter Reinholdtsen 			data[2] = 0x00;
710c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "set-in-progress"))
711c18ec02fSPetter Reinholdtsen 			data[2] = 0x01;
712c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "commit-write"))
713c18ec02fSPetter Reinholdtsen 			data[2] = 0x02;
714c18ec02fSPetter Reinholdtsen 		else
715c18ec02fSPetter Reinholdtsen 		{
716c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
717c18ec02fSPetter Reinholdtsen 				   value, param);
718c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Valid values are set-complete, set-in-progress "
719c18ec02fSPetter Reinholdtsen 				   "and commit-write");
720c18ec02fSPetter Reinholdtsen 			return -1;
721c18ec02fSPetter Reinholdtsen 		}
722c18ec02fSPetter Reinholdtsen 	}
723c18ec02fSPetter Reinholdtsen 
724c18ec02fSPetter Reinholdtsen 
725c18ec02fSPetter Reinholdtsen 	/*
726c18ec02fSPetter Reinholdtsen 	 * enabled
727c18ec02fSPetter Reinholdtsen 	 */
728c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "enabled"))
729c18ec02fSPetter Reinholdtsen 	{
730c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 3;
731c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_ENABLE;
732c18ec02fSPetter Reinholdtsen 
733c18ec02fSPetter Reinholdtsen 		if (! strcmp(value, "true"))
734c18ec02fSPetter Reinholdtsen 			data[2] = 0x01;
735c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "false"))
736c18ec02fSPetter Reinholdtsen 			data[2] = 0x00;
737c18ec02fSPetter Reinholdtsen 		else
738c18ec02fSPetter Reinholdtsen 		{
739c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
740c18ec02fSPetter Reinholdtsen 				   value, param);
741c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Valid values are true and false");
742c18ec02fSPetter Reinholdtsen 			return -1;
743c18ec02fSPetter Reinholdtsen 		}
744c18ec02fSPetter Reinholdtsen 	}
745c18ec02fSPetter Reinholdtsen 
746c18ec02fSPetter Reinholdtsen 
747c18ec02fSPetter Reinholdtsen 	/*
748c18ec02fSPetter Reinholdtsen 	 * force-payload-encryption
749c18ec02fSPetter Reinholdtsen 	 */
750c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "force-encryption"))
751c18ec02fSPetter Reinholdtsen 	{
752c18ec02fSPetter Reinholdtsen 		struct sol_config_parameters params;
753c18ec02fSPetter Reinholdtsen 
754c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 3;
755c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_AUTHENTICATION;
756c18ec02fSPetter Reinholdtsen 
757c18ec02fSPetter Reinholdtsen 		if (! strcmp(value, "true"))
758c18ec02fSPetter Reinholdtsen 			data[2] = 0x80;
759c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "false"))
760c18ec02fSPetter Reinholdtsen 			data[2] = 0x00;
761c18ec02fSPetter Reinholdtsen 		else
762c18ec02fSPetter Reinholdtsen 		{
763c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
764c18ec02fSPetter Reinholdtsen 				   value, param);
765c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Valid values are true and false");
766c18ec02fSPetter Reinholdtsen 			return -1;
767c18ec02fSPetter Reinholdtsen 		}
768c18ec02fSPetter Reinholdtsen 
769c18ec02fSPetter Reinholdtsen 
770c18ec02fSPetter Reinholdtsen 		/* We need other values to complete the request */
771c18ec02fSPetter Reinholdtsen 		if (ipmi_get_sol_info(intf, channel, &params))
772c18ec02fSPetter Reinholdtsen 		{
773c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
774c18ec02fSPetter Reinholdtsen 				   param);
775c18ec02fSPetter Reinholdtsen 			return -1;
776c18ec02fSPetter Reinholdtsen 		}
777c18ec02fSPetter Reinholdtsen 
778c18ec02fSPetter Reinholdtsen 		data[2] |= params.force_authentication? 0x40 : 0x00;
779c18ec02fSPetter Reinholdtsen 		data[2] |= params.privilege_level;
780c18ec02fSPetter Reinholdtsen 	}
781c18ec02fSPetter Reinholdtsen 
782c18ec02fSPetter Reinholdtsen 
783c18ec02fSPetter Reinholdtsen 	/*
784c18ec02fSPetter Reinholdtsen 	 * force-payload-authentication
785c18ec02fSPetter Reinholdtsen 	 */
786c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "force-authentication"))
787c18ec02fSPetter Reinholdtsen 	{
788c18ec02fSPetter Reinholdtsen 		struct sol_config_parameters params;
789c18ec02fSPetter Reinholdtsen 
790c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 3;
791c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_AUTHENTICATION;
792c18ec02fSPetter Reinholdtsen 
793c18ec02fSPetter Reinholdtsen 		if (! strcmp(value, "true"))
794c18ec02fSPetter Reinholdtsen 			data[2] = 0x40;
795c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "false"))
796c18ec02fSPetter Reinholdtsen 			data[2] = 0x00;
797c18ec02fSPetter Reinholdtsen 		else
798c18ec02fSPetter Reinholdtsen 		{
799c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
800c18ec02fSPetter Reinholdtsen 				   value, param);
801c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Valid values are true and false");
802c18ec02fSPetter Reinholdtsen 			return -1;
803c18ec02fSPetter Reinholdtsen 		}
804c18ec02fSPetter Reinholdtsen 
805c18ec02fSPetter Reinholdtsen 
806c18ec02fSPetter Reinholdtsen 		/* We need other values to complete the request */
807c18ec02fSPetter Reinholdtsen 		if (ipmi_get_sol_info(intf, channel, &params))
808c18ec02fSPetter Reinholdtsen 		{
809c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
810c18ec02fSPetter Reinholdtsen 				   param);
811c18ec02fSPetter Reinholdtsen 			return -1;
812c18ec02fSPetter Reinholdtsen 		}
813c18ec02fSPetter Reinholdtsen 
814c18ec02fSPetter Reinholdtsen 		data[2] |= params.force_encryption? 0x80 : 0x00;
815c18ec02fSPetter Reinholdtsen 		data[2] |= params.privilege_level;
816c18ec02fSPetter Reinholdtsen 	}
817c18ec02fSPetter Reinholdtsen 
818c18ec02fSPetter Reinholdtsen 
819c18ec02fSPetter Reinholdtsen 	/*
820c18ec02fSPetter Reinholdtsen 	 * privilege-level
821c18ec02fSPetter Reinholdtsen 	 */
822c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "privilege-level"))
823c18ec02fSPetter Reinholdtsen 	{
824c18ec02fSPetter Reinholdtsen 		struct sol_config_parameters params;
825c18ec02fSPetter Reinholdtsen 
826c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 3;
827c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_AUTHENTICATION;
828c18ec02fSPetter Reinholdtsen 
829c18ec02fSPetter Reinholdtsen 		if (! strcmp(value, "user"))
830c18ec02fSPetter Reinholdtsen 			data[2] = 0x02;
831c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "operator"))
832c18ec02fSPetter Reinholdtsen 			data[2] = 0x03;
833c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "admin"))
834c18ec02fSPetter Reinholdtsen 			data[2] = 0x04;
835c18ec02fSPetter Reinholdtsen 		else if (! strcmp(value, "oem"))
836c18ec02fSPetter Reinholdtsen 			data[2] = 0x05;
837c18ec02fSPetter Reinholdtsen 		else
838c18ec02fSPetter Reinholdtsen 		{
839c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
840c18ec02fSPetter Reinholdtsen 				   value, param);
841c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Valid values are user, operator, admin, and oem");
842c18ec02fSPetter Reinholdtsen 			return -1;
843c18ec02fSPetter Reinholdtsen 		}
844c18ec02fSPetter Reinholdtsen 
845c18ec02fSPetter Reinholdtsen 
846c18ec02fSPetter Reinholdtsen 		/* We need other values to complete the request */
847c18ec02fSPetter Reinholdtsen 		if (ipmi_get_sol_info(intf, channel, &params))
848c18ec02fSPetter Reinholdtsen 		{
849c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
850c18ec02fSPetter Reinholdtsen 				   param);
851c18ec02fSPetter Reinholdtsen 			return -1;
852c18ec02fSPetter Reinholdtsen 		}
853c18ec02fSPetter Reinholdtsen 
854c18ec02fSPetter Reinholdtsen 		data[2] |= params.force_encryption?     0x80 : 0x00;
855c18ec02fSPetter Reinholdtsen 		data[2] |= params.force_authentication? 0x40 : 0x00;
856c18ec02fSPetter Reinholdtsen 	}
857c18ec02fSPetter Reinholdtsen 
858c18ec02fSPetter Reinholdtsen 
859c18ec02fSPetter Reinholdtsen 	/*
860c18ec02fSPetter Reinholdtsen 	 * character-accumulate-level
861c18ec02fSPetter Reinholdtsen 	 */
862c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "character-accumulate-level"))
863c18ec02fSPetter Reinholdtsen 	{
864c18ec02fSPetter Reinholdtsen 		struct sol_config_parameters params;
865c18ec02fSPetter Reinholdtsen 
866c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 4;
867c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_CHARACTER_INTERVAL;
868c18ec02fSPetter Reinholdtsen 
869c18ec02fSPetter Reinholdtsen 		/* validate user-supplied input */
870c18ec02fSPetter Reinholdtsen 		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 1, 255, &data[2]))
871c18ec02fSPetter Reinholdtsen 			return -1;
872c18ec02fSPetter Reinholdtsen 
873c18ec02fSPetter Reinholdtsen 		/* We need other values to complete the request */
874c18ec02fSPetter Reinholdtsen 		if (ipmi_get_sol_info(intf, channel, &params))
875c18ec02fSPetter Reinholdtsen 		{
876c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
877c18ec02fSPetter Reinholdtsen 				   param);
878c18ec02fSPetter Reinholdtsen 			return -1;
879c18ec02fSPetter Reinholdtsen 		}
880c18ec02fSPetter Reinholdtsen 
881c18ec02fSPetter Reinholdtsen 		data[3] = params.character_send_threshold;
882c18ec02fSPetter Reinholdtsen 	}
883c18ec02fSPetter Reinholdtsen 
884c18ec02fSPetter Reinholdtsen 
885c18ec02fSPetter Reinholdtsen 	/*
886c18ec02fSPetter Reinholdtsen 	 * character-send-threshold
887c18ec02fSPetter Reinholdtsen 	 */
888c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "character-send-threshold"))
889c18ec02fSPetter Reinholdtsen 	{
890c18ec02fSPetter Reinholdtsen 		struct sol_config_parameters params;
891c18ec02fSPetter Reinholdtsen 
892c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 4;
893c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_CHARACTER_INTERVAL;
894c18ec02fSPetter Reinholdtsen 
895c18ec02fSPetter Reinholdtsen 		/* validate user-supplied input */
896c18ec02fSPetter Reinholdtsen 		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 0, 255, &data[3]))
897c18ec02fSPetter Reinholdtsen 			return -1;
898c18ec02fSPetter Reinholdtsen 
899c18ec02fSPetter Reinholdtsen 		/* We need other values to complete the request */
900c18ec02fSPetter Reinholdtsen 		if (ipmi_get_sol_info(intf, channel, &params))
901c18ec02fSPetter Reinholdtsen 		{
902c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
903c18ec02fSPetter Reinholdtsen 				   param);
904c18ec02fSPetter Reinholdtsen 			return -1;
905c18ec02fSPetter Reinholdtsen 		}
906c18ec02fSPetter Reinholdtsen 
907c18ec02fSPetter Reinholdtsen 		data[2] = params.character_accumulate_level;
908c18ec02fSPetter Reinholdtsen 	}
909c18ec02fSPetter Reinholdtsen 
910c18ec02fSPetter Reinholdtsen 
911c18ec02fSPetter Reinholdtsen 	/*
912c18ec02fSPetter Reinholdtsen 	 * retry-count
913c18ec02fSPetter Reinholdtsen 	 */
914c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "retry-count"))
915c18ec02fSPetter Reinholdtsen 	{
916c18ec02fSPetter Reinholdtsen 		struct sol_config_parameters params;
917c18ec02fSPetter Reinholdtsen 
918c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 4;
919c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_RETRY;
920c18ec02fSPetter Reinholdtsen 
921c18ec02fSPetter Reinholdtsen 		/* validate user input, 7 is max value */
922c18ec02fSPetter Reinholdtsen 		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 0, 7, &data[2]))
923c18ec02fSPetter Reinholdtsen 			return -1;
924c18ec02fSPetter Reinholdtsen 
925c18ec02fSPetter Reinholdtsen 		/* We need other values to complete the request */
926c18ec02fSPetter Reinholdtsen 		if (ipmi_get_sol_info(intf, channel, &params))
927c18ec02fSPetter Reinholdtsen 		{
928c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
929c18ec02fSPetter Reinholdtsen 				   param);
930c18ec02fSPetter Reinholdtsen 			return -1;
931c18ec02fSPetter Reinholdtsen 		}
932c18ec02fSPetter Reinholdtsen 
933c18ec02fSPetter Reinholdtsen 		data[3] = params.retry_interval;
934c18ec02fSPetter Reinholdtsen 	}
935c18ec02fSPetter Reinholdtsen 
936c18ec02fSPetter Reinholdtsen 
937c18ec02fSPetter Reinholdtsen 	/*
938c18ec02fSPetter Reinholdtsen 	 * retry-interval
939c18ec02fSPetter Reinholdtsen 	 */
940c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "retry-interval"))
941c18ec02fSPetter Reinholdtsen 	{
942c18ec02fSPetter Reinholdtsen 		struct sol_config_parameters params;
943c18ec02fSPetter Reinholdtsen 
944c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 4;
945c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_RETRY;
946c18ec02fSPetter Reinholdtsen 
947c18ec02fSPetter Reinholdtsen 		/* validate user-supplied input */
948c18ec02fSPetter Reinholdtsen 		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 0, 255, &data[3]))
949c18ec02fSPetter Reinholdtsen 			return -1;
950c18ec02fSPetter Reinholdtsen 
951c18ec02fSPetter Reinholdtsen 		/* We need other values to complete the request */
952c18ec02fSPetter Reinholdtsen 		if (ipmi_get_sol_info(intf, channel, &params))
953c18ec02fSPetter Reinholdtsen 		{
954c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
955c18ec02fSPetter Reinholdtsen 				   param);
956c18ec02fSPetter Reinholdtsen 			return -1;
957c18ec02fSPetter Reinholdtsen 		}
958c18ec02fSPetter Reinholdtsen 
959c18ec02fSPetter Reinholdtsen 		data[2] = params.retry_count;
960c18ec02fSPetter Reinholdtsen 	}
961c18ec02fSPetter Reinholdtsen 
962c18ec02fSPetter Reinholdtsen 
963c18ec02fSPetter Reinholdtsen 	/*
964c18ec02fSPetter Reinholdtsen 	 * non-volatile-bit-rate
965c18ec02fSPetter Reinholdtsen 	 */
966c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "non-volatile-bit-rate"))
967c18ec02fSPetter Reinholdtsen 	{
968c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 3;
969c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE;
970c18ec02fSPetter Reinholdtsen 
971c18ec02fSPetter Reinholdtsen 		if (!strcmp(value, "serial"))
972c18ec02fSPetter Reinholdtsen 		{
973c18ec02fSPetter Reinholdtsen 			data[2] = 0x00;
974c18ec02fSPetter Reinholdtsen 		}
975c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "9.6"))
976c18ec02fSPetter Reinholdtsen 		{
977c18ec02fSPetter Reinholdtsen 			data[2] = 0x06;
978c18ec02fSPetter Reinholdtsen 		}
979c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "19.2"))
980c18ec02fSPetter Reinholdtsen 		{
981c18ec02fSPetter Reinholdtsen 			data[2] = 0x07;
982c18ec02fSPetter Reinholdtsen 		}
983c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "38.4"))
984c18ec02fSPetter Reinholdtsen 		{
985c18ec02fSPetter Reinholdtsen 			data[2] = 0x08;
986c18ec02fSPetter Reinholdtsen 		}
987c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "57.6"))
988c18ec02fSPetter Reinholdtsen 		{
989c18ec02fSPetter Reinholdtsen 			data[2] = 0x09;
990c18ec02fSPetter Reinholdtsen 		}
991c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "115.2"))
992c18ec02fSPetter Reinholdtsen 		{
993c18ec02fSPetter Reinholdtsen 			data[2] = 0x0A;
994c18ec02fSPetter Reinholdtsen 		}
995c18ec02fSPetter Reinholdtsen 		else
996c18ec02fSPetter Reinholdtsen 		{
997c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid value \"%s\" for parameter \"%s\"",
998c18ec02fSPetter Reinholdtsen 				   value,
999c18ec02fSPetter Reinholdtsen 				   param);
1000c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Valid values are serial, 9.6 19.2, 38.4, 57.6 and 115.2");
1001c18ec02fSPetter Reinholdtsen 			return -1;
1002c18ec02fSPetter Reinholdtsen 		}
1003c18ec02fSPetter Reinholdtsen 	}
1004c18ec02fSPetter Reinholdtsen 
1005c18ec02fSPetter Reinholdtsen 
1006c18ec02fSPetter Reinholdtsen 	/*
1007c18ec02fSPetter Reinholdtsen 	 * volatile-bit-rate
1008c18ec02fSPetter Reinholdtsen 	 */
1009c18ec02fSPetter Reinholdtsen 	else if (! strcmp(param, "volatile-bit-rate"))
1010c18ec02fSPetter Reinholdtsen 	{
1011c18ec02fSPetter Reinholdtsen 		req.msg.data_len = 3;
1012c18ec02fSPetter Reinholdtsen 		data[1] = SOL_PARAMETER_SOL_VOLATILE_BIT_RATE;
1013c18ec02fSPetter Reinholdtsen 
1014c18ec02fSPetter Reinholdtsen 		if (!strcmp(value, "serial"))
1015c18ec02fSPetter Reinholdtsen 		{
1016c18ec02fSPetter Reinholdtsen 			data[2] = 0x00;
1017c18ec02fSPetter Reinholdtsen 		}
1018c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "9.6"))
1019c18ec02fSPetter Reinholdtsen 		{
1020c18ec02fSPetter Reinholdtsen 			data[2] = 0x06;
1021c18ec02fSPetter Reinholdtsen 		}
1022c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "19.2"))
1023c18ec02fSPetter Reinholdtsen 		{
1024c18ec02fSPetter Reinholdtsen 			data[2] = 0x07;
1025c18ec02fSPetter Reinholdtsen 		}
1026c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "38.4"))
1027c18ec02fSPetter Reinholdtsen 		{
1028c18ec02fSPetter Reinholdtsen 			data[2] = 0x08;
1029c18ec02fSPetter Reinholdtsen 		}
1030c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "57.6"))
1031c18ec02fSPetter Reinholdtsen 		{
1032c18ec02fSPetter Reinholdtsen 			data[2] = 0x09;
1033c18ec02fSPetter Reinholdtsen 		}
1034c18ec02fSPetter Reinholdtsen 		else if (!strcmp(value, "115.2"))
1035c18ec02fSPetter Reinholdtsen 		{
1036c18ec02fSPetter Reinholdtsen 			data[2] = 0x0A;
1037c18ec02fSPetter Reinholdtsen 		}
1038c18ec02fSPetter Reinholdtsen 		else
1039c18ec02fSPetter Reinholdtsen 		{
1040c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid value \"%s\" for parameter \"%s\"",
1041c18ec02fSPetter Reinholdtsen 				   value,
1042c18ec02fSPetter Reinholdtsen 				   param);
1043c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Valid values are serial, 9.6 19.2, 38.4, 57.6 and 115.2");
1044c18ec02fSPetter Reinholdtsen 			return -1;
1045c18ec02fSPetter Reinholdtsen 		}
1046c18ec02fSPetter Reinholdtsen 	}
1047c18ec02fSPetter Reinholdtsen 	else
1048c18ec02fSPetter Reinholdtsen 	{
1049c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: invalid SOL parameter %s", param);
1050c18ec02fSPetter Reinholdtsen 		return -1;
1051c18ec02fSPetter Reinholdtsen 	}
1052c18ec02fSPetter Reinholdtsen 
1053c18ec02fSPetter Reinholdtsen 
1054c18ec02fSPetter Reinholdtsen 	/*
1055c18ec02fSPetter Reinholdtsen 	 * Execute the request
1056c18ec02fSPetter Reinholdtsen 	 */
1057c18ec02fSPetter Reinholdtsen 	if (bGuarded &&
1058c18ec02fSPetter Reinholdtsen 		(ipmi_sol_set_param(intf,
1059c18ec02fSPetter Reinholdtsen 				    channel,
1060c18ec02fSPetter Reinholdtsen 				    "set-in-progress",
1061c18ec02fSPetter Reinholdtsen 				    "set-in-progress",
1062c18ec02fSPetter Reinholdtsen 				    bGuarded)))
1063c18ec02fSPetter Reinholdtsen 	{
1064c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: set of parameter \"%s\" failed", param);
1065c18ec02fSPetter Reinholdtsen 		return -1;
1066c18ec02fSPetter Reinholdtsen 	}
1067c18ec02fSPetter Reinholdtsen 
1068c18ec02fSPetter Reinholdtsen 
1069c18ec02fSPetter Reinholdtsen 	/* The command proper */
1070c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1071c18ec02fSPetter Reinholdtsen 
1072c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
1073c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error setting SOL parameter '%s'", param);
1074c18ec02fSPetter Reinholdtsen 		return -1;
1075c18ec02fSPetter Reinholdtsen 	}
1076c18ec02fSPetter Reinholdtsen 
1077c18ec02fSPetter Reinholdtsen 	if (!(!strncmp(param, "set-in-progress", 15) && !strncmp(value, "commit-write", 12)) &&
1078c18ec02fSPetter Reinholdtsen 	    rsp->ccode > 0) {
1079c18ec02fSPetter Reinholdtsen 		switch (rsp->ccode) {
1080c18ec02fSPetter Reinholdtsen 		case 0x80:
1081c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
1082c18ec02fSPetter Reinholdtsen 				"Parameter not supported", param);
1083c18ec02fSPetter Reinholdtsen 			break;
1084c18ec02fSPetter Reinholdtsen 		case 0x81:
1085c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
1086c18ec02fSPetter Reinholdtsen 				"Attempt to set set-in-progress when not in set-complete state",
1087c18ec02fSPetter Reinholdtsen 				param);
1088c18ec02fSPetter Reinholdtsen 			break;
1089c18ec02fSPetter Reinholdtsen 		case 0x82:
1090c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
1091c18ec02fSPetter Reinholdtsen 				"Attempt to write read-only parameter", param);
1092c18ec02fSPetter Reinholdtsen 			break;
1093c18ec02fSPetter Reinholdtsen 		case 0x83:
1094c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
1095c18ec02fSPetter Reinholdtsen 				"Attempt to read write-only parameter", param);
1096c18ec02fSPetter Reinholdtsen 			break;
1097c18ec02fSPetter Reinholdtsen 		default:
1098c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error setting SOL parameter '%s' to '%s': %s",
1099c18ec02fSPetter Reinholdtsen 				param, value, val2str(rsp->ccode, completion_code_vals));
1100c18ec02fSPetter Reinholdtsen 			break;
1101c18ec02fSPetter Reinholdtsen 		}
1102c18ec02fSPetter Reinholdtsen 
1103c18ec02fSPetter Reinholdtsen 		if (bGuarded &&
1104c18ec02fSPetter Reinholdtsen 			(ipmi_sol_set_param(intf,
1105c18ec02fSPetter Reinholdtsen 					    channel,
1106c18ec02fSPetter Reinholdtsen 					    "set-in-progress",
1107c18ec02fSPetter Reinholdtsen 					    "set-complete",
1108c18ec02fSPetter Reinholdtsen 					    bGuarded)))
1109c18ec02fSPetter Reinholdtsen 		{
1110c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error could not set \"set-in-progress\" "
1111c18ec02fSPetter Reinholdtsen 				   "to \"set-complete\"");
1112c18ec02fSPetter Reinholdtsen 		}
1113c18ec02fSPetter Reinholdtsen 
1114c18ec02fSPetter Reinholdtsen 		return -1;
1115c18ec02fSPetter Reinholdtsen 	}
1116c18ec02fSPetter Reinholdtsen 
1117c18ec02fSPetter Reinholdtsen 
1118c18ec02fSPetter Reinholdtsen 	/*
1119c18ec02fSPetter Reinholdtsen 	 * The commit write could very well fail, but that's ok.
1120c18ec02fSPetter Reinholdtsen 	 * It may not be implemented.
1121c18ec02fSPetter Reinholdtsen 	 */
1122c18ec02fSPetter Reinholdtsen 	if (bGuarded)
1123c18ec02fSPetter Reinholdtsen 		ipmi_sol_set_param(intf,
1124c18ec02fSPetter Reinholdtsen 				   channel,
1125c18ec02fSPetter Reinholdtsen 				   "set-in-progress",
1126c18ec02fSPetter Reinholdtsen 				   "commit-write",
1127c18ec02fSPetter Reinholdtsen 				   bGuarded);
1128c18ec02fSPetter Reinholdtsen 
1129c18ec02fSPetter Reinholdtsen 
1130c18ec02fSPetter Reinholdtsen 	if (bGuarded &&
1131c18ec02fSPetter Reinholdtsen  		ipmi_sol_set_param(intf,
1132c18ec02fSPetter Reinholdtsen 				   channel,
1133c18ec02fSPetter Reinholdtsen 				   "set-in-progress",
1134c18ec02fSPetter Reinholdtsen 				   "set-complete",
1135c18ec02fSPetter Reinholdtsen 				   bGuarded))
1136c18ec02fSPetter Reinholdtsen 	{
1137c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error could not set \"set-in-progress\" "
1138c18ec02fSPetter Reinholdtsen 			   "to \"set-complete\"");
1139c18ec02fSPetter Reinholdtsen 		return -1;
1140c18ec02fSPetter Reinholdtsen 	}
1141c18ec02fSPetter Reinholdtsen 
1142c18ec02fSPetter Reinholdtsen 	return 0;
1143c18ec02fSPetter Reinholdtsen }
1144c18ec02fSPetter Reinholdtsen 
1145c18ec02fSPetter Reinholdtsen 
1146c18ec02fSPetter Reinholdtsen 
1147c18ec02fSPetter Reinholdtsen void
leave_raw_mode(void)1148c18ec02fSPetter Reinholdtsen leave_raw_mode(void)
1149c18ec02fSPetter Reinholdtsen {
1150c18ec02fSPetter Reinholdtsen 	if (!_in_raw_mode)
1151c18ec02fSPetter Reinholdtsen 		return;
1152c18ec02fSPetter Reinholdtsen 	if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1)
1153c18ec02fSPetter Reinholdtsen 		perror("tcsetattr");
1154c18ec02fSPetter Reinholdtsen 	else
1155c18ec02fSPetter Reinholdtsen 		_in_raw_mode = 0;
1156c18ec02fSPetter Reinholdtsen }
1157c18ec02fSPetter Reinholdtsen 
1158c18ec02fSPetter Reinholdtsen 
1159c18ec02fSPetter Reinholdtsen 
1160c18ec02fSPetter Reinholdtsen void
enter_raw_mode(void)1161c18ec02fSPetter Reinholdtsen enter_raw_mode(void)
1162c18ec02fSPetter Reinholdtsen {
1163c18ec02fSPetter Reinholdtsen 	struct termios tio;
1164c18ec02fSPetter Reinholdtsen 	if (tcgetattr(fileno(stdin), &tio) == -1) {
1165c18ec02fSPetter Reinholdtsen 		perror("tcgetattr");
1166c18ec02fSPetter Reinholdtsen 		return;
1167c18ec02fSPetter Reinholdtsen 	}
1168c18ec02fSPetter Reinholdtsen 	_saved_tio = tio;
1169c18ec02fSPetter Reinholdtsen 	tio.c_iflag |= IGNPAR;
1170c18ec02fSPetter Reinholdtsen 	tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
1171c18ec02fSPetter Reinholdtsen 	tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
1172c18ec02fSPetter Reinholdtsen 	//	#ifdef IEXTEN
1173c18ec02fSPetter Reinholdtsen 	tio.c_lflag &= ~IEXTEN;
1174c18ec02fSPetter Reinholdtsen 	//	#endif
1175c18ec02fSPetter Reinholdtsen 	tio.c_oflag &= ~OPOST;
1176c18ec02fSPetter Reinholdtsen 	tio.c_cc[VMIN] = 1;
1177c18ec02fSPetter Reinholdtsen 	tio.c_cc[VTIME] = 0;
1178c18ec02fSPetter Reinholdtsen 	if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1)
1179c18ec02fSPetter Reinholdtsen 		perror("tcsetattr");
1180c18ec02fSPetter Reinholdtsen 	else
1181c18ec02fSPetter Reinholdtsen 		_in_raw_mode = 1;
1182c18ec02fSPetter Reinholdtsen }
1183c18ec02fSPetter Reinholdtsen 
1184c18ec02fSPetter Reinholdtsen 
1185c18ec02fSPetter Reinholdtsen static void
sendBreak(struct ipmi_intf * intf)1186c18ec02fSPetter Reinholdtsen sendBreak(struct ipmi_intf * intf)
1187c18ec02fSPetter Reinholdtsen {
1188c18ec02fSPetter Reinholdtsen 	struct ipmi_v2_payload  v2_payload;
1189c18ec02fSPetter Reinholdtsen 
1190c18ec02fSPetter Reinholdtsen 	memset(&v2_payload, 0, sizeof(v2_payload));
1191c18ec02fSPetter Reinholdtsen 
1192c18ec02fSPetter Reinholdtsen 	v2_payload.payload.sol_packet.character_count = 0;
1193c18ec02fSPetter Reinholdtsen 	v2_payload.payload.sol_packet.generate_break  = 1;
1194c18ec02fSPetter Reinholdtsen 
1195c18ec02fSPetter Reinholdtsen 	intf->send_sol(intf, &v2_payload);
1196c18ec02fSPetter Reinholdtsen }
1197c18ec02fSPetter Reinholdtsen 
1198c18ec02fSPetter Reinholdtsen 
1199c18ec02fSPetter Reinholdtsen 
1200c18ec02fSPetter Reinholdtsen /*
1201c18ec02fSPetter Reinholdtsen  * suspendSelf
1202c18ec02fSPetter Reinholdtsen  *
1203c18ec02fSPetter Reinholdtsen  * Put ourself in the background
1204c18ec02fSPetter Reinholdtsen  *
1205c18ec02fSPetter Reinholdtsen  * param bRestoreTty specifies whether we will put our self back
1206c18ec02fSPetter Reinholdtsen  *       in raw mode when we resume
1207c18ec02fSPetter Reinholdtsen  */
1208c18ec02fSPetter Reinholdtsen static void
suspendSelf(int bRestoreTty)1209c18ec02fSPetter Reinholdtsen suspendSelf(int bRestoreTty)
1210c18ec02fSPetter Reinholdtsen {
1211c18ec02fSPetter Reinholdtsen 	leave_raw_mode();
1212c18ec02fSPetter Reinholdtsen 	kill(getpid(), SIGTSTP);
1213c18ec02fSPetter Reinholdtsen 
1214c18ec02fSPetter Reinholdtsen 	if (bRestoreTty)
1215c18ec02fSPetter Reinholdtsen 		enter_raw_mode();
1216c18ec02fSPetter Reinholdtsen }
1217c18ec02fSPetter Reinholdtsen 
1218c18ec02fSPetter Reinholdtsen 
1219c18ec02fSPetter Reinholdtsen 
1220c18ec02fSPetter Reinholdtsen /*
1221c18ec02fSPetter Reinholdtsen  * printSolEscapeSequences
1222c18ec02fSPetter Reinholdtsen  *
1223c18ec02fSPetter Reinholdtsen  * Send some useful documentation to the user
1224c18ec02fSPetter Reinholdtsen  */
1225c18ec02fSPetter Reinholdtsen static void
printSolEscapeSequences(struct ipmi_intf * intf)1226c18ec02fSPetter Reinholdtsen printSolEscapeSequences(struct ipmi_intf * intf)
1227c18ec02fSPetter Reinholdtsen {
1228c18ec02fSPetter Reinholdtsen 	printf(
1229c18ec02fSPetter Reinholdtsen 		   "%c?\n\
1230c18ec02fSPetter Reinholdtsen 	Supported escape sequences:\n\
1231c18ec02fSPetter Reinholdtsen 	%c.  - terminate connection\n\
1232c18ec02fSPetter Reinholdtsen 	%c^Z - suspend ipmitool\n\
1233c18ec02fSPetter Reinholdtsen 	%c^X - suspend ipmitool, but don't restore tty on restart\n\
1234c18ec02fSPetter Reinholdtsen 	%cB  - send break\n\
1235c18ec02fSPetter Reinholdtsen 	%c?  - this message\n\
1236c18ec02fSPetter Reinholdtsen 	%c%c  - send the escape character by typing it twice\n\
1237c18ec02fSPetter Reinholdtsen 	(Note that escapes are only recognized immediately after newline.)\n",
1238*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char,
1239*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char,
1240*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char,
1241*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char,
1242*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char,
1243*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char,
1244*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char,
1245*eb541367SZdenek Styblik 		   intf->ssn_params.sol_escape_char);
1246c18ec02fSPetter Reinholdtsen }
1247c18ec02fSPetter Reinholdtsen 
1248c18ec02fSPetter Reinholdtsen 
1249c18ec02fSPetter Reinholdtsen 
1250c18ec02fSPetter Reinholdtsen /*
1251c18ec02fSPetter Reinholdtsen  * output
1252c18ec02fSPetter Reinholdtsen  *
1253c18ec02fSPetter Reinholdtsen  * Send the specified data to stdout
1254c18ec02fSPetter Reinholdtsen  */
1255c18ec02fSPetter Reinholdtsen static void
output(struct ipmi_rs * rsp)1256c18ec02fSPetter Reinholdtsen output(struct ipmi_rs * rsp)
1257c18ec02fSPetter Reinholdtsen {
1258c18ec02fSPetter Reinholdtsen 	/* Add checks to make sure it is actually SOL data, in general I see
1259c18ec02fSPetter Reinholdtsen 	 * outside code mostly trying to guard against this happening, but
1260c18ec02fSPetter Reinholdtsen 	 * some places fail to do so, so I do so here to make sure nothing gets
1261c18ec02fSPetter Reinholdtsen 	 * through.  If non-sol data comes through here, there is probably
1262c18ec02fSPetter Reinholdtsen 	 * a packet that won't get processed somewhere else, but the alternative
1263c18ec02fSPetter Reinholdtsen 	 * of outputting corrupt data is worse.  Generally I see the get device
1264c18ec02fSPetter Reinholdtsen 	 * id response make it here somehow.  I assume it is a heartbeat and the
1265c18ec02fSPetter Reinholdtsen 	 * other code will retry if it cares about the response and misses it.
1266c18ec02fSPetter Reinholdtsen 	 */
1267c18ec02fSPetter Reinholdtsen 	if (rsp &&
1268c18ec02fSPetter Reinholdtsen 	    (rsp->session.authtype    == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
1269c18ec02fSPetter Reinholdtsen 	    (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
1270c18ec02fSPetter Reinholdtsen 	{
1271c18ec02fSPetter Reinholdtsen 		int i;
1272c18ec02fSPetter Reinholdtsen 
1273c18ec02fSPetter Reinholdtsen 		for (i = 0; i < rsp->data_len; ++i)
1274c18ec02fSPetter Reinholdtsen 			putc(rsp->data[i], stdout);
1275c18ec02fSPetter Reinholdtsen 
1276c18ec02fSPetter Reinholdtsen 		fflush(stdout);
1277c18ec02fSPetter Reinholdtsen 	}
1278c18ec02fSPetter Reinholdtsen }
1279c18ec02fSPetter Reinholdtsen 
1280c18ec02fSPetter Reinholdtsen 
1281c18ec02fSPetter Reinholdtsen 
1282c18ec02fSPetter Reinholdtsen /*
1283c18ec02fSPetter Reinholdtsen  * ipmi_sol_deactivate
1284c18ec02fSPetter Reinholdtsen  */
1285c18ec02fSPetter Reinholdtsen static int
ipmi_sol_deactivate(struct ipmi_intf * intf,int instance)1286c18ec02fSPetter Reinholdtsen ipmi_sol_deactivate(struct ipmi_intf * intf, int instance)
1287c18ec02fSPetter Reinholdtsen {
1288c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1289c18ec02fSPetter Reinholdtsen 	struct ipmi_rq   req;
1290c18ec02fSPetter Reinholdtsen 	uint8_t          data[6];
1291c18ec02fSPetter Reinholdtsen 
1292c18ec02fSPetter Reinholdtsen 	if ((instance <= 0) || (instance > 15)) {
1293c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: Instance must range from 1 to 15");
1294c18ec02fSPetter Reinholdtsen 		return -1;
1295c18ec02fSPetter Reinholdtsen 	}
1296c18ec02fSPetter Reinholdtsen 
1297c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1298c18ec02fSPetter Reinholdtsen 	req.msg.netfn    = IPMI_NETFN_APP;
1299c18ec02fSPetter Reinholdtsen 	req.msg.cmd      = IPMI_DEACTIVATE_PAYLOAD;
1300c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 6;
1301c18ec02fSPetter Reinholdtsen 	req.msg.data     = data;
1302c18ec02fSPetter Reinholdtsen 
13030a1f5c03SZdenek Styblik 	memset(data, 0, sizeof(data));
1304c18ec02fSPetter Reinholdtsen 	data[0] = IPMI_PAYLOAD_TYPE_SOL;  /* payload type      */
1305c18ec02fSPetter Reinholdtsen 	data[1] = instance;               /* payload instance. */
1306c18ec02fSPetter Reinholdtsen 
1307c18ec02fSPetter Reinholdtsen 	/* Lots of important data */
1308c18ec02fSPetter Reinholdtsen 	data[2] = 0;
1309c18ec02fSPetter Reinholdtsen 	data[3] = 0;
1310c18ec02fSPetter Reinholdtsen 	data[4] = 0;
1311c18ec02fSPetter Reinholdtsen 	data[5] = 0;
1312c18ec02fSPetter Reinholdtsen 
1313c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1314c18ec02fSPetter Reinholdtsen 
1315c18ec02fSPetter Reinholdtsen 	if (NULL != rsp) {
1316c18ec02fSPetter Reinholdtsen 		switch (rsp->ccode) {
1317c18ec02fSPetter Reinholdtsen 			case 0x00:
1318c18ec02fSPetter Reinholdtsen 				return 0;
1319c18ec02fSPetter Reinholdtsen 			case 0x80:
1320c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: SOL payload already de-activated");
1321c18ec02fSPetter Reinholdtsen 				break;
1322c18ec02fSPetter Reinholdtsen 			case 0x81:
1323c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: SOL payload type disabled");
1324c18ec02fSPetter Reinholdtsen 				break;
1325c18ec02fSPetter Reinholdtsen 			default:
1326c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error de-activating SOL payload: %s",
1327c18ec02fSPetter Reinholdtsen 					val2str(rsp->ccode, completion_code_vals));
1328c18ec02fSPetter Reinholdtsen 				break;
1329c18ec02fSPetter Reinholdtsen 		}
1330c18ec02fSPetter Reinholdtsen 	} else {
1331c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response de-activating SOL payload");
1332c18ec02fSPetter Reinholdtsen 	}
1333c18ec02fSPetter Reinholdtsen 
1334c18ec02fSPetter Reinholdtsen 	return -1;
1335c18ec02fSPetter Reinholdtsen }
1336c18ec02fSPetter Reinholdtsen 
1337c18ec02fSPetter Reinholdtsen 
1338c18ec02fSPetter Reinholdtsen 
1339c18ec02fSPetter Reinholdtsen /*
1340c18ec02fSPetter Reinholdtsen  * processSolUserInput
1341c18ec02fSPetter Reinholdtsen  *
1342c18ec02fSPetter Reinholdtsen  * Act on user input into the SOL session.  The only reason this
1343c18ec02fSPetter Reinholdtsen  * is complicated is that we have to process escape sequences.
1344c18ec02fSPetter Reinholdtsen  *
1345c18ec02fSPetter Reinholdtsen  * return   0 on success
1346c18ec02fSPetter Reinholdtsen  *          1 if we should exit
1347c18ec02fSPetter Reinholdtsen  *        < 0 on error (BMC probably closed the session)
1348c18ec02fSPetter Reinholdtsen  */
1349c18ec02fSPetter Reinholdtsen static int
processSolUserInput(struct ipmi_intf * intf,uint8_t * input,uint16_t buffer_length)1350c18ec02fSPetter Reinholdtsen processSolUserInput(
1351c18ec02fSPetter Reinholdtsen 					struct ipmi_intf * intf,
1352c18ec02fSPetter Reinholdtsen 					uint8_t    * input,
1353c18ec02fSPetter Reinholdtsen 					uint16_t   buffer_length)
1354c18ec02fSPetter Reinholdtsen {
1355c18ec02fSPetter Reinholdtsen 	static int escape_pending = 0;
1356c18ec02fSPetter Reinholdtsen 	static int last_was_cr    = 1;
1357c18ec02fSPetter Reinholdtsen 	struct ipmi_v2_payload v2_payload;
1358c18ec02fSPetter Reinholdtsen 	int  length               = 0;
1359c18ec02fSPetter Reinholdtsen 	int  retval               = 0;
1360c18ec02fSPetter Reinholdtsen 	char ch;
1361c18ec02fSPetter Reinholdtsen 	int  i;
1362c18ec02fSPetter Reinholdtsen 
1363c18ec02fSPetter Reinholdtsen 	memset(&v2_payload, 0, sizeof(v2_payload));
1364c18ec02fSPetter Reinholdtsen 
1365c18ec02fSPetter Reinholdtsen 	/*
1366c18ec02fSPetter Reinholdtsen 	 * Our first order of business is to check the input for escape
1367c18ec02fSPetter Reinholdtsen 	 * sequences to act on.
1368c18ec02fSPetter Reinholdtsen 	 */
1369c18ec02fSPetter Reinholdtsen 	for (i = 0; i < buffer_length; ++i)
1370c18ec02fSPetter Reinholdtsen 	{
1371c18ec02fSPetter Reinholdtsen 		ch = input[i];
1372c18ec02fSPetter Reinholdtsen 
1373c18ec02fSPetter Reinholdtsen 		if (escape_pending){
1374c18ec02fSPetter Reinholdtsen 			escape_pending = 0;
1375c18ec02fSPetter Reinholdtsen 
1376c18ec02fSPetter Reinholdtsen 			/*
1377c18ec02fSPetter Reinholdtsen 			 * Process a possible escape sequence.
1378c18ec02fSPetter Reinholdtsen 			 */
1379c18ec02fSPetter Reinholdtsen 			switch (ch) {
1380c18ec02fSPetter Reinholdtsen 			case '.':
1381c18ec02fSPetter Reinholdtsen 				printf("%c. [terminated ipmitool]\n",
1382*eb541367SZdenek Styblik 				       intf->ssn_params.sol_escape_char);
1383c18ec02fSPetter Reinholdtsen 				retval = 1;
1384c18ec02fSPetter Reinholdtsen 				break;
1385c18ec02fSPetter Reinholdtsen 
1386c18ec02fSPetter Reinholdtsen 			case 'Z' - 64:
1387c18ec02fSPetter Reinholdtsen 				printf("%c^Z [suspend ipmitool]\n",
1388*eb541367SZdenek Styblik 				       intf->ssn_params.sol_escape_char);
1389c18ec02fSPetter Reinholdtsen 				suspendSelf(1); /* Restore tty back to raw */
1390c18ec02fSPetter Reinholdtsen 				continue;
1391c18ec02fSPetter Reinholdtsen 
1392c18ec02fSPetter Reinholdtsen 			case 'X' - 64:
1393c18ec02fSPetter Reinholdtsen 				printf("%c^Z [suspend ipmitool]\n",
1394*eb541367SZdenek Styblik 				       intf->ssn_params.sol_escape_char);
1395c18ec02fSPetter Reinholdtsen 				suspendSelf(0); /* Don't restore to raw mode */
1396c18ec02fSPetter Reinholdtsen 				continue;
1397c18ec02fSPetter Reinholdtsen 
1398c18ec02fSPetter Reinholdtsen 			case 'B':
1399c18ec02fSPetter Reinholdtsen 				printf("%cB [send break]\n",
1400*eb541367SZdenek Styblik 				       intf->ssn_params.sol_escape_char);
1401c18ec02fSPetter Reinholdtsen 				sendBreak(intf);
1402c18ec02fSPetter Reinholdtsen 				continue;
1403c18ec02fSPetter Reinholdtsen 
1404c18ec02fSPetter Reinholdtsen 			case '?':
1405c18ec02fSPetter Reinholdtsen 				printSolEscapeSequences(intf);
1406c18ec02fSPetter Reinholdtsen 				continue;
1407c18ec02fSPetter Reinholdtsen 
1408c18ec02fSPetter Reinholdtsen 			default:
1409*eb541367SZdenek Styblik 				if (ch != intf->ssn_params.sol_escape_char)
1410c18ec02fSPetter Reinholdtsen 					v2_payload.payload.sol_packet.data[length++] =
1411*eb541367SZdenek Styblik 						intf->ssn_params.sol_escape_char;
1412c18ec02fSPetter Reinholdtsen 				v2_payload.payload.sol_packet.data[length++] = ch;
1413c18ec02fSPetter Reinholdtsen 			}
1414c18ec02fSPetter Reinholdtsen 		}
1415c18ec02fSPetter Reinholdtsen 
1416c18ec02fSPetter Reinholdtsen 		else
1417c18ec02fSPetter Reinholdtsen 		{
1418*eb541367SZdenek Styblik 			if (last_was_cr && (ch == intf->ssn_params.sol_escape_char)) {
1419c18ec02fSPetter Reinholdtsen 				escape_pending = 1;
1420c18ec02fSPetter Reinholdtsen 				continue;
1421c18ec02fSPetter Reinholdtsen 			}
1422c18ec02fSPetter Reinholdtsen 
1423c18ec02fSPetter Reinholdtsen 			v2_payload.payload.sol_packet.data[length++] =	ch;
1424c18ec02fSPetter Reinholdtsen 		}
1425c18ec02fSPetter Reinholdtsen 
1426c18ec02fSPetter Reinholdtsen 
1427c18ec02fSPetter Reinholdtsen 		/*
1428c18ec02fSPetter Reinholdtsen 		 * Normal character.  Record whether it was a newline.
1429c18ec02fSPetter Reinholdtsen 		 */
1430c18ec02fSPetter Reinholdtsen 		last_was_cr = (ch == '\r' || ch == '\n');
1431c18ec02fSPetter Reinholdtsen 	}
1432c18ec02fSPetter Reinholdtsen 
1433c18ec02fSPetter Reinholdtsen 
1434c18ec02fSPetter Reinholdtsen 	/*
1435c18ec02fSPetter Reinholdtsen 	 * If there is anything left to process we dispatch it to the BMC,
1436c18ec02fSPetter Reinholdtsen 	 * send intf->session->sol_data.max_outbound_payload_size bytes
1437c18ec02fSPetter Reinholdtsen 	 * at a time.
1438c18ec02fSPetter Reinholdtsen 	 */
1439c18ec02fSPetter Reinholdtsen 	if (length)
1440c18ec02fSPetter Reinholdtsen 	{
1441c18ec02fSPetter Reinholdtsen 		struct ipmi_rs * rsp = NULL;
1442c18ec02fSPetter Reinholdtsen 		int try = 0;
1443c18ec02fSPetter Reinholdtsen 
1444*eb541367SZdenek Styblik 		while (try < intf->ssn_params.retry) {
1445c18ec02fSPetter Reinholdtsen 
1446c18ec02fSPetter Reinholdtsen 			v2_payload.payload.sol_packet.character_count = length;
1447c18ec02fSPetter Reinholdtsen 
1448c18ec02fSPetter Reinholdtsen 			rsp = intf->send_sol(intf, &v2_payload);
1449c18ec02fSPetter Reinholdtsen 
1450c18ec02fSPetter Reinholdtsen 			if (rsp)
1451c18ec02fSPetter Reinholdtsen 			{
1452c18ec02fSPetter Reinholdtsen 				break;
1453c18ec02fSPetter Reinholdtsen 			}
1454c18ec02fSPetter Reinholdtsen 
1455c18ec02fSPetter Reinholdtsen 			usleep(5000);
1456c18ec02fSPetter Reinholdtsen 			try++;
1457c18ec02fSPetter Reinholdtsen 		}
1458c18ec02fSPetter Reinholdtsen 
1459c18ec02fSPetter Reinholdtsen 		if (! rsp)
1460c18ec02fSPetter Reinholdtsen 		{
1461c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error sending SOL data: FAIL");
1462c18ec02fSPetter Reinholdtsen 			retval = -1;
1463c18ec02fSPetter Reinholdtsen 		}
1464c18ec02fSPetter Reinholdtsen 
1465c18ec02fSPetter Reinholdtsen 		/* If the sequence number is set we know we have new data */
1466c18ec02fSPetter Reinholdtsen 		if (retval == 0)
1467c18ec02fSPetter Reinholdtsen 			if ((rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
1468c18ec02fSPetter Reinholdtsen 			    (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)        &&
1469c18ec02fSPetter Reinholdtsen 			    (rsp->payload.sol_packet.packet_sequence_number))
1470c18ec02fSPetter Reinholdtsen 				output(rsp);
1471c18ec02fSPetter Reinholdtsen 	}
1472c18ec02fSPetter Reinholdtsen 
1473c18ec02fSPetter Reinholdtsen 	return retval;
1474c18ec02fSPetter Reinholdtsen }
1475c18ec02fSPetter Reinholdtsen 
1476c18ec02fSPetter Reinholdtsen static int
ipmi_sol_keepalive_using_sol(struct ipmi_intf * intf)1477c18ec02fSPetter Reinholdtsen ipmi_sol_keepalive_using_sol(struct ipmi_intf * intf)
1478c18ec02fSPetter Reinholdtsen {
1479c18ec02fSPetter Reinholdtsen 	struct ipmi_v2_payload v2_payload;
1480c18ec02fSPetter Reinholdtsen 	struct timeval end;
1481c18ec02fSPetter Reinholdtsen 
1482c18ec02fSPetter Reinholdtsen 	if (_disable_keepalive)
1483c18ec02fSPetter Reinholdtsen 		return 0;
1484c18ec02fSPetter Reinholdtsen 
1485c18ec02fSPetter Reinholdtsen 	gettimeofday(&end, 0);
1486c18ec02fSPetter Reinholdtsen 
1487c18ec02fSPetter Reinholdtsen 	if (end.tv_sec - _start_keepalive.tv_sec > SOL_KEEPALIVE_TIMEOUT) {
1488c18ec02fSPetter Reinholdtsen 		memset(&v2_payload, 0, sizeof(v2_payload));
1489c18ec02fSPetter Reinholdtsen 		v2_payload.payload.sol_packet.character_count = 0;
149021fbd0e9SZdenek Styblik 		if (intf->send_sol(intf, &v2_payload) == NULL)
149121fbd0e9SZdenek Styblik 			return -1;
149221fbd0e9SZdenek Styblik 		/* good return, reset start time */
1493c18ec02fSPetter Reinholdtsen 		gettimeofday(&_start_keepalive, 0);
1494c18ec02fSPetter Reinholdtsen 	}
149521fbd0e9SZdenek Styblik 	return 0;
1496c18ec02fSPetter Reinholdtsen }
1497c18ec02fSPetter Reinholdtsen 
1498c18ec02fSPetter Reinholdtsen static int
ipmi_sol_keepalive_using_getdeviceid(struct ipmi_intf * intf)1499c18ec02fSPetter Reinholdtsen ipmi_sol_keepalive_using_getdeviceid(struct ipmi_intf * intf)
1500c18ec02fSPetter Reinholdtsen {
1501c18ec02fSPetter Reinholdtsen 	struct timeval  end;
1502c18ec02fSPetter Reinholdtsen 
1503c18ec02fSPetter Reinholdtsen 	if (_disable_keepalive)
1504c18ec02fSPetter Reinholdtsen 		return 0;
1505c18ec02fSPetter Reinholdtsen 
1506c18ec02fSPetter Reinholdtsen 	gettimeofday(&end, 0);
1507c18ec02fSPetter Reinholdtsen 
1508c18ec02fSPetter Reinholdtsen 	if (end.tv_sec - _start_keepalive.tv_sec > SOL_KEEPALIVE_TIMEOUT) {
150921fbd0e9SZdenek Styblik 		if (intf->keepalive(intf) != 0)
151021fbd0e9SZdenek Styblik          		return -1;
151121fbd0e9SZdenek Styblik 		/* good return, reset start time */
1512c18ec02fSPetter Reinholdtsen 		gettimeofday(&_start_keepalive, 0);
1513c18ec02fSPetter Reinholdtsen    	}
151421fbd0e9SZdenek Styblik 	return 0;
1515c18ec02fSPetter Reinholdtsen }
1516c18ec02fSPetter Reinholdtsen 
1517c18ec02fSPetter Reinholdtsen 
1518c18ec02fSPetter Reinholdtsen 
1519c18ec02fSPetter Reinholdtsen /*
1520c18ec02fSPetter Reinholdtsen  * ipmi_sol_red_pill
1521c18ec02fSPetter Reinholdtsen  */
1522c18ec02fSPetter Reinholdtsen static int
ipmi_sol_red_pill(struct ipmi_intf * intf,int instance)1523c18ec02fSPetter Reinholdtsen ipmi_sol_red_pill(struct ipmi_intf * intf, int instance)
1524c18ec02fSPetter Reinholdtsen {
1525c18ec02fSPetter Reinholdtsen 	char   * buffer;
1526c18ec02fSPetter Reinholdtsen 	int    numRead;
1527c18ec02fSPetter Reinholdtsen 	int    bShouldExit       = 0;
1528c18ec02fSPetter Reinholdtsen 	int    bBmcClosedSession = 0;
1529c18ec02fSPetter Reinholdtsen 	fd_set read_fds;
1530c18ec02fSPetter Reinholdtsen 	struct timeval tv;
1531c18ec02fSPetter Reinholdtsen 	int    retval;
1532c18ec02fSPetter Reinholdtsen 	int    buffer_size = intf->session->sol_data.max_inbound_payload_size;
1533c18ec02fSPetter Reinholdtsen 	int    keepAliveRet = 0;
1534c18ec02fSPetter Reinholdtsen 	int    retrySol = 0;
1535c18ec02fSPetter Reinholdtsen 
1536c18ec02fSPetter Reinholdtsen 	/* Subtract SOL header from max_inbound_payload_size */
1537c18ec02fSPetter Reinholdtsen 	if (buffer_size > 4)
1538c18ec02fSPetter Reinholdtsen 		buffer_size -= 4;
1539c18ec02fSPetter Reinholdtsen 
1540c18ec02fSPetter Reinholdtsen 	buffer = (char*)malloc(buffer_size);
1541c18ec02fSPetter Reinholdtsen 	if (buffer == NULL) {
1542c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "ipmitool: malloc failure");
1543c18ec02fSPetter Reinholdtsen 		return -1;
1544c18ec02fSPetter Reinholdtsen 	}
1545c18ec02fSPetter Reinholdtsen 
1546c18ec02fSPetter Reinholdtsen 	/* Initialize keepalive start time */
1547c18ec02fSPetter Reinholdtsen 	gettimeofday(&_start_keepalive, 0);
1548c18ec02fSPetter Reinholdtsen 
1549c18ec02fSPetter Reinholdtsen 	enter_raw_mode();
1550c18ec02fSPetter Reinholdtsen 
1551c18ec02fSPetter Reinholdtsen 	while (! bShouldExit)
1552c18ec02fSPetter Reinholdtsen 	{
1553c18ec02fSPetter Reinholdtsen 		FD_ZERO(&read_fds);
1554c18ec02fSPetter Reinholdtsen 		FD_SET(0, &read_fds);
1555c18ec02fSPetter Reinholdtsen 		FD_SET(intf->fd, &read_fds);
1556c18ec02fSPetter Reinholdtsen 
1557c18ec02fSPetter Reinholdtsen 		if (!ipmi_oem_active(intf,"i82571spt"))
1558c18ec02fSPetter Reinholdtsen 		{
1559c18ec02fSPetter Reinholdtsen 			/* Send periodic keepalive packet */
1560c18ec02fSPetter Reinholdtsen 			if(_use_sol_for_keepalive == 0)
1561c18ec02fSPetter Reinholdtsen 			{
1562c18ec02fSPetter Reinholdtsen 				keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
1563c18ec02fSPetter Reinholdtsen 			}
1564c18ec02fSPetter Reinholdtsen 			else
1565c18ec02fSPetter Reinholdtsen 			{
1566c18ec02fSPetter Reinholdtsen 				keepAliveRet = ipmi_sol_keepalive_using_sol(intf);
1567c18ec02fSPetter Reinholdtsen 			}
1568c18ec02fSPetter Reinholdtsen 
1569c18ec02fSPetter Reinholdtsen 			if (keepAliveRet != 0)
1570c18ec02fSPetter Reinholdtsen 			{
1571c18ec02fSPetter Reinholdtsen 				/*
1572c18ec02fSPetter Reinholdtsen 				 * Retrying the keep Alive before declaring a communication
1573c18ec02fSPetter Reinholdtsen 				 * lost state with the IPMC. Helpful when the payload is
1574c18ec02fSPetter Reinholdtsen 				 * reset and brings down the connection temporarily. Otherwise,
1575c18ec02fSPetter Reinholdtsen 				 * if we send getDevice Id to check the status of IPMC during
1576c18ec02fSPetter Reinholdtsen 				 * this down time when the connection is restarting, SOL will
1577c18ec02fSPetter Reinholdtsen 				 * exit even though the IPMC is available and the session is open.
1578c18ec02fSPetter Reinholdtsen 				 */
1579c18ec02fSPetter Reinholdtsen 				if (retrySol == MAX_SOL_RETRY)
1580c18ec02fSPetter Reinholdtsen 				{
1581c18ec02fSPetter Reinholdtsen 					/* no response to Get Device ID keepalive message */
1582c18ec02fSPetter Reinholdtsen 					bShouldExit = 1;
1583c18ec02fSPetter Reinholdtsen 					continue;
1584c18ec02fSPetter Reinholdtsen 				}
1585c18ec02fSPetter Reinholdtsen 				else
1586c18ec02fSPetter Reinholdtsen 				{
1587c18ec02fSPetter Reinholdtsen 					retrySol++;
1588c18ec02fSPetter Reinholdtsen 				}
1589c18ec02fSPetter Reinholdtsen 			}
1590c18ec02fSPetter Reinholdtsen 			else
1591c18ec02fSPetter Reinholdtsen 			{
1592c18ec02fSPetter Reinholdtsen 				/* if the keep Alive is successful reset retries to zero */
1593c18ec02fSPetter Reinholdtsen 				retrySol = 0;
1594c18ec02fSPetter Reinholdtsen 			}
1595c18ec02fSPetter Reinholdtsen 		} /* !oem="i82571spt" */
1596c18ec02fSPetter Reinholdtsen 		/* Wait up to half a second */
1597c18ec02fSPetter Reinholdtsen 		tv.tv_sec =  0;
1598c18ec02fSPetter Reinholdtsen 		tv.tv_usec = 500000;
1599c18ec02fSPetter Reinholdtsen 
1600c18ec02fSPetter Reinholdtsen 		retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv);
1601c18ec02fSPetter Reinholdtsen 
1602c18ec02fSPetter Reinholdtsen 		if (retval)
1603c18ec02fSPetter Reinholdtsen 		{
1604c18ec02fSPetter Reinholdtsen 			if (retval == -1)
1605c18ec02fSPetter Reinholdtsen 			{
1606c18ec02fSPetter Reinholdtsen 				/* ERROR */
1607c18ec02fSPetter Reinholdtsen 				perror("select");
1608c18ec02fSPetter Reinholdtsen 				return -1;
1609c18ec02fSPetter Reinholdtsen 			}
1610c18ec02fSPetter Reinholdtsen 
1611c18ec02fSPetter Reinholdtsen 
1612c18ec02fSPetter Reinholdtsen 			/*
1613c18ec02fSPetter Reinholdtsen 			 * Process input from the user
1614c18ec02fSPetter Reinholdtsen 			 */
1615c18ec02fSPetter Reinholdtsen 			if (FD_ISSET(0, &read_fds))
1616c18ec02fSPetter Reinholdtsen 	 		{
1617c18ec02fSPetter Reinholdtsen 				memset(buffer, 0, buffer_size);
1618c18ec02fSPetter Reinholdtsen 				numRead = read(fileno(stdin),
1619c18ec02fSPetter Reinholdtsen 							   buffer,
1620c18ec02fSPetter Reinholdtsen 							   buffer_size);
1621c18ec02fSPetter Reinholdtsen 
1622c18ec02fSPetter Reinholdtsen 				if (numRead > 0)
1623c18ec02fSPetter Reinholdtsen 				{
1624c18ec02fSPetter Reinholdtsen 					int rc = processSolUserInput(intf, (uint8_t *)buffer, numRead);
1625c18ec02fSPetter Reinholdtsen 
1626c18ec02fSPetter Reinholdtsen 					if (rc)
1627c18ec02fSPetter Reinholdtsen 					{
1628c18ec02fSPetter Reinholdtsen 						if (rc < 0)
1629c18ec02fSPetter Reinholdtsen 							bShouldExit = bBmcClosedSession = 1;
1630c18ec02fSPetter Reinholdtsen 						else
1631c18ec02fSPetter Reinholdtsen 							bShouldExit = 1;
1632c18ec02fSPetter Reinholdtsen 					}
1633c18ec02fSPetter Reinholdtsen 				}
1634c18ec02fSPetter Reinholdtsen 				else
1635c18ec02fSPetter Reinholdtsen 				{
1636c18ec02fSPetter Reinholdtsen 					bShouldExit = 1;
1637c18ec02fSPetter Reinholdtsen 				}
1638c18ec02fSPetter Reinholdtsen 			}
1639c18ec02fSPetter Reinholdtsen 
1640c18ec02fSPetter Reinholdtsen 
1641c18ec02fSPetter Reinholdtsen 			/*
1642c18ec02fSPetter Reinholdtsen 			 * Process input from the BMC
1643c18ec02fSPetter Reinholdtsen 			 */
1644c18ec02fSPetter Reinholdtsen 			else if (FD_ISSET(intf->fd, &read_fds))
1645c18ec02fSPetter Reinholdtsen 			{
1646c18ec02fSPetter Reinholdtsen 				struct ipmi_rs * rs =intf->recv_sol(intf);
164721fbd0e9SZdenek Styblik 				if ( rs)
1648c18ec02fSPetter Reinholdtsen 				{
1649c18ec02fSPetter Reinholdtsen 					output(rs);
1650c18ec02fSPetter Reinholdtsen 				}
165121fbd0e9SZdenek Styblik 				/*
165221fbd0e9SZdenek Styblik 				 * Should recv_sol come back null, the incoming packet was not ours.
165321fbd0e9SZdenek Styblik 				 * Just fall through, the keepalive logic will determine if
165421fbd0e9SZdenek Styblik 				 * the BMC has dropped the session.
165521fbd0e9SZdenek Styblik 				 */
1656c18ec02fSPetter Reinholdtsen  			}
1657c18ec02fSPetter Reinholdtsen 
1658c18ec02fSPetter Reinholdtsen 
1659c18ec02fSPetter Reinholdtsen 			/*
1660c18ec02fSPetter Reinholdtsen 			 * ERROR in select
1661c18ec02fSPetter Reinholdtsen 			 */
1662c18ec02fSPetter Reinholdtsen  			else
1663c18ec02fSPetter Reinholdtsen 			{
1664c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error: Select returned with nothing to read");
1665c18ec02fSPetter Reinholdtsen 				bShouldExit = 1;
1666c18ec02fSPetter Reinholdtsen 			}
1667c18ec02fSPetter Reinholdtsen 		}
1668c18ec02fSPetter Reinholdtsen 	}
1669c18ec02fSPetter Reinholdtsen 
1670c18ec02fSPetter Reinholdtsen 	leave_raw_mode();
1671c18ec02fSPetter Reinholdtsen 
1672c18ec02fSPetter Reinholdtsen 	if (keepAliveRet != 0)
1673c18ec02fSPetter Reinholdtsen 	{
1674c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response to keepalive - Terminating session");
1675c18ec02fSPetter Reinholdtsen 		/* attempt to clean up anyway */
1676c18ec02fSPetter Reinholdtsen 		ipmi_sol_deactivate(intf, instance);
1677c18ec02fSPetter Reinholdtsen 		exit(1);
1678c18ec02fSPetter Reinholdtsen 	}
1679c18ec02fSPetter Reinholdtsen 
1680c18ec02fSPetter Reinholdtsen 	if (bBmcClosedSession)
1681c18ec02fSPetter Reinholdtsen 	{
1682c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "SOL session closed by BMC");
1683c18ec02fSPetter Reinholdtsen 		exit(1);
1684c18ec02fSPetter Reinholdtsen 	}
1685c18ec02fSPetter Reinholdtsen 	else
1686c18ec02fSPetter Reinholdtsen 		ipmi_sol_deactivate(intf, instance);
1687c18ec02fSPetter Reinholdtsen 
1688c18ec02fSPetter Reinholdtsen 	return 0;
1689c18ec02fSPetter Reinholdtsen }
1690c18ec02fSPetter Reinholdtsen 
1691c18ec02fSPetter Reinholdtsen 
1692c18ec02fSPetter Reinholdtsen 
1693c18ec02fSPetter Reinholdtsen 
1694c18ec02fSPetter Reinholdtsen /*
1695c18ec02fSPetter Reinholdtsen  * ipmi_sol_activate
1696c18ec02fSPetter Reinholdtsen  */
1697c18ec02fSPetter Reinholdtsen static int
ipmi_sol_activate(struct ipmi_intf * intf,int looptest,int interval,int instance)1698c18ec02fSPetter Reinholdtsen ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
1699c18ec02fSPetter Reinholdtsen 		int instance)
1700c18ec02fSPetter Reinholdtsen {
1701c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
1702c18ec02fSPetter Reinholdtsen 	struct ipmi_rq   req;
1703c18ec02fSPetter Reinholdtsen 	struct activate_payload_rsp ap_rsp;
1704c18ec02fSPetter Reinholdtsen 	uint8_t    data[6];
1705c18ec02fSPetter Reinholdtsen 	uint8_t    bSolEncryption     = 1;
1706c18ec02fSPetter Reinholdtsen 	uint8_t    bSolAuthentication = 1;
1707c18ec02fSPetter Reinholdtsen 
1708c18ec02fSPetter Reinholdtsen 	/*
1709c18ec02fSPetter Reinholdtsen 	 * This command is only available over RMCP+ (the lanplus
1710c18ec02fSPetter Reinholdtsen 	 * interface).
1711c18ec02fSPetter Reinholdtsen 	 */
1712c18ec02fSPetter Reinholdtsen 	if (strncmp(intf->name, "lanplus", 7) != 0)
1713c18ec02fSPetter Reinholdtsen 	{
1714c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: This command is only available over the "
1715c18ec02fSPetter Reinholdtsen 			   "lanplus interface");
1716c18ec02fSPetter Reinholdtsen 		return -1;
1717c18ec02fSPetter Reinholdtsen 	}
1718c18ec02fSPetter Reinholdtsen 
1719c18ec02fSPetter Reinholdtsen 	if ((instance <= 0) || (instance > 15)) {
1720c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: Instance must range from 1 to 15");
1721c18ec02fSPetter Reinholdtsen 		return -1;
1722c18ec02fSPetter Reinholdtsen 	}
1723c18ec02fSPetter Reinholdtsen 
1724c18ec02fSPetter Reinholdtsen 
1725c18ec02fSPetter Reinholdtsen 	/*
1726c18ec02fSPetter Reinholdtsen 	 * Setup a callback so that the lanplus processing knows what
1727c18ec02fSPetter Reinholdtsen 	 * to do with packets that come unexpectedly (while waiting for
1728c18ec02fSPetter Reinholdtsen 	 * an ACK, perhaps.
1729c18ec02fSPetter Reinholdtsen 	 */
1730c18ec02fSPetter Reinholdtsen 	intf->session->sol_data.sol_input_handler = output;
1731c18ec02fSPetter Reinholdtsen 
1732c18ec02fSPetter Reinholdtsen 
1733c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
1734c18ec02fSPetter Reinholdtsen 	req.msg.netfn    = IPMI_NETFN_APP;
1735c18ec02fSPetter Reinholdtsen 	req.msg.cmd      = IPMI_ACTIVATE_PAYLOAD;
1736c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 6;
1737c18ec02fSPetter Reinholdtsen 	req.msg.data     = data;
1738c18ec02fSPetter Reinholdtsen 
1739c18ec02fSPetter Reinholdtsen 	data[0] = IPMI_PAYLOAD_TYPE_SOL;  /* payload type     */
1740c18ec02fSPetter Reinholdtsen 	data[1] = instance;               /* payload instance */
1741c18ec02fSPetter Reinholdtsen 
1742c18ec02fSPetter Reinholdtsen 	/* Lots of important data.  Most is default */
1743c18ec02fSPetter Reinholdtsen 	data[2]  = bSolEncryption?     0x80 : 0;
1744c18ec02fSPetter Reinholdtsen 	data[2] |= bSolAuthentication? 0x40 : 0;
1745c18ec02fSPetter Reinholdtsen 	data[2] |= IPMI_SOL_SERIAL_ALERT_MASK_DEFERRED;
1746c18ec02fSPetter Reinholdtsen 
1747c18ec02fSPetter Reinholdtsen 	if (ipmi_oem_active(intf, "intelplus")) {
1748c18ec02fSPetter Reinholdtsen 		data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_TRUE;
1749c18ec02fSPetter Reinholdtsen 	} else if (ipmi_oem_active(intf, "i82571spt")) {
1750c18ec02fSPetter Reinholdtsen 		/*
1751c18ec02fSPetter Reinholdtsen 		 * A quote from Intel: "Engineering believes the problem
1752c18ec02fSPetter Reinholdtsen 		 * lies within the Auxiliary data being sent with the
1753c18ec02fSPetter Reinholdtsen 		 * 'Activate Payload' command from IPMITool.  IPMITool
1754c18ec02fSPetter Reinholdtsen 		 * sends a C6h which sets some bits having to do with
1755c18ec02fSPetter Reinholdtsen 		 * encryption and some behavior dealing with CTS DCD/DSR.
1756c18ec02fSPetter Reinholdtsen 		 * I recommend that the customer modify this request
1757c18ec02fSPetter Reinholdtsen 		 * to send 08h instead. This is what our internal utility
1758c18ec02fSPetter Reinholdtsen 		 * sends and it works without issue. I will work with
1759c18ec02fSPetter Reinholdtsen 		 * engineering to ensure the settings that IPMITool uses
1760c18ec02fSPetter Reinholdtsen 		 * (C6h) are supported in the future.
1761c18ec02fSPetter Reinholdtsen 		 */
1762c18ec02fSPetter Reinholdtsen 		data[2] = 0x08;
1763c18ec02fSPetter Reinholdtsen 	} else {
1764c18ec02fSPetter Reinholdtsen 		data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_FALSE;
1765c18ec02fSPetter Reinholdtsen 	}
1766c18ec02fSPetter Reinholdtsen 
1767c18ec02fSPetter Reinholdtsen 	data[3] = 0x00; /* reserved */
1768c18ec02fSPetter Reinholdtsen 	data[4] = 0x00; /* reserved */
1769c18ec02fSPetter Reinholdtsen 	data[5] = 0x00; /* reserved */
1770c18ec02fSPetter Reinholdtsen 
1771c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1772c18ec02fSPetter Reinholdtsen 
1773c18ec02fSPetter Reinholdtsen 	if (NULL != rsp) {
1774c18ec02fSPetter Reinholdtsen 		switch (rsp->ccode) {
1775c18ec02fSPetter Reinholdtsen 			case 0x00:
1776c18ec02fSPetter Reinholdtsen 				if (rsp->data_len == 12) {
1777c18ec02fSPetter Reinholdtsen 					break;
1778c18ec02fSPetter Reinholdtsen 				} else {
1779c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
1780c18ec02fSPetter Reinholdtsen 						   "in payload activation response",
1781c18ec02fSPetter Reinholdtsen 						   rsp->data_len);
1782c18ec02fSPetter Reinholdtsen 					return -1;
1783c18ec02fSPetter Reinholdtsen 				}
1784c18ec02fSPetter Reinholdtsen 				break;
1785c18ec02fSPetter Reinholdtsen 			case 0x80:
1786c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: SOL payload already active on another session");
1787c18ec02fSPetter Reinholdtsen 				return -1;
1788c18ec02fSPetter Reinholdtsen 			case 0x81:
1789c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: SOL payload disabled");
1790c18ec02fSPetter Reinholdtsen 				return -1;
1791c18ec02fSPetter Reinholdtsen 			case 0x82:
1792c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: SOL payload activation limit reached");
1793c18ec02fSPetter Reinholdtsen 				return -1;
1794c18ec02fSPetter Reinholdtsen 			case 0x83:
1795c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: cannot activate SOL payload with encryption");
1796c18ec02fSPetter Reinholdtsen 				return -1;
1797c18ec02fSPetter Reinholdtsen 			case 0x84:
1798c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Info: cannot activate SOL payload without encryption");
1799c18ec02fSPetter Reinholdtsen 				return -1;
1800c18ec02fSPetter Reinholdtsen 			default:
1801c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Error activating SOL payload: %s",
1802c18ec02fSPetter Reinholdtsen 					val2str(rsp->ccode, completion_code_vals));
1803c18ec02fSPetter Reinholdtsen 				return -1;
1804c18ec02fSPetter Reinholdtsen 		}
1805c18ec02fSPetter Reinholdtsen 	} else {
1806c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error: No response activating SOL payload");
1807c18ec02fSPetter Reinholdtsen 		return -1;
1808c18ec02fSPetter Reinholdtsen 	}
1809c18ec02fSPetter Reinholdtsen 
1810c18ec02fSPetter Reinholdtsen 
1811c18ec02fSPetter Reinholdtsen 	memcpy(&ap_rsp, rsp->data, sizeof(struct activate_payload_rsp));
1812c18ec02fSPetter Reinholdtsen 
1813c18ec02fSPetter Reinholdtsen 	intf->session->sol_data.max_inbound_payload_size =
1814c18ec02fSPetter Reinholdtsen 		(ap_rsp.inbound_payload_size[1] << 8) |
1815c18ec02fSPetter Reinholdtsen 		ap_rsp.inbound_payload_size[0];
1816c18ec02fSPetter Reinholdtsen 
1817c18ec02fSPetter Reinholdtsen 	intf->session->sol_data.max_outbound_payload_size =
1818c18ec02fSPetter Reinholdtsen 		(ap_rsp.outbound_payload_size[1] << 8) |
1819c18ec02fSPetter Reinholdtsen 		ap_rsp.outbound_payload_size[0];
1820c18ec02fSPetter Reinholdtsen 
1821c18ec02fSPetter Reinholdtsen 	intf->session->sol_data.port =
1822c18ec02fSPetter Reinholdtsen 		(ap_rsp.payload_udp_port[1] << 8) |
1823c18ec02fSPetter Reinholdtsen 		ap_rsp.payload_udp_port[0];
1824c18ec02fSPetter Reinholdtsen 
1825c18ec02fSPetter Reinholdtsen 	intf->session->timeout = 1;
1826c18ec02fSPetter Reinholdtsen 
1827c18ec02fSPetter Reinholdtsen 
1828c18ec02fSPetter Reinholdtsen 	/* NOTE: the spec does allow for SOL traffic to be sent on
1829c18ec02fSPetter Reinholdtsen 	 * a different port.  we do not yet support that feature. */
1830*eb541367SZdenek Styblik 	if (intf->session->sol_data.port != intf->ssn_params.port)
1831c18ec02fSPetter Reinholdtsen 	{
1832c18ec02fSPetter Reinholdtsen 		/* try byteswapping port in case BMC sent it incorrectly */
1833c18ec02fSPetter Reinholdtsen 		uint16_t portswap = BSWAP_16(intf->session->sol_data.port);
1834c18ec02fSPetter Reinholdtsen 
1835*eb541367SZdenek Styblik 		if (portswap == intf->ssn_params.port) {
1836c18ec02fSPetter Reinholdtsen 			intf->session->sol_data.port = portswap;
1837c18ec02fSPetter Reinholdtsen 		}
1838c18ec02fSPetter Reinholdtsen 		else {
1839c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Error: BMC requests SOL session on different port");
1840c18ec02fSPetter Reinholdtsen 			return -1;
1841c18ec02fSPetter Reinholdtsen 		}
1842c18ec02fSPetter Reinholdtsen 	}
1843c18ec02fSPetter Reinholdtsen 
1844c18ec02fSPetter Reinholdtsen 	printf("[SOL Session operational.  Use %c? for help]\n",
1845*eb541367SZdenek Styblik 	       intf->ssn_params.sol_escape_char);
1846c18ec02fSPetter Reinholdtsen 
1847c18ec02fSPetter Reinholdtsen 	if(looptest == 1)
1848c18ec02fSPetter Reinholdtsen 	{
1849c18ec02fSPetter Reinholdtsen 		ipmi_sol_deactivate(intf, instance);
1850c18ec02fSPetter Reinholdtsen 		usleep(interval*1000);
1851c18ec02fSPetter Reinholdtsen 		return 0;
1852c18ec02fSPetter Reinholdtsen 	}
1853c18ec02fSPetter Reinholdtsen 
1854c18ec02fSPetter Reinholdtsen 	/*
1855c18ec02fSPetter Reinholdtsen 	 * At this point we are good to go with our SOL session.  We
1856c18ec02fSPetter Reinholdtsen 	 * need to listen to
1857c18ec02fSPetter Reinholdtsen 	 * 1) STDIN for user input
1858c18ec02fSPetter Reinholdtsen 	 * 2) The FD for incoming SOL packets
1859c18ec02fSPetter Reinholdtsen 	 */
1860c18ec02fSPetter Reinholdtsen 	if (ipmi_sol_red_pill(intf, instance))
1861c18ec02fSPetter Reinholdtsen 	{
1862c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Error in SOL session");
1863c18ec02fSPetter Reinholdtsen 		return -1;
1864c18ec02fSPetter Reinholdtsen 	}
1865c18ec02fSPetter Reinholdtsen 
1866c18ec02fSPetter Reinholdtsen 	return 0;
1867c18ec02fSPetter Reinholdtsen }
1868c18ec02fSPetter Reinholdtsen 
1869c18ec02fSPetter Reinholdtsen 
1870c18ec02fSPetter Reinholdtsen 
1871c18ec02fSPetter Reinholdtsen /*
1872c18ec02fSPetter Reinholdtsen  * print_sol_usage
1873c18ec02fSPetter Reinholdtsen  */
1874c18ec02fSPetter Reinholdtsen static void
print_sol_usage(void)1875c18ec02fSPetter Reinholdtsen print_sol_usage(void)
1876c18ec02fSPetter Reinholdtsen {
1877c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "SOL Commands: info [<channel number>]");
1878c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "              set <parameter> <value> [channel]");
1879c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "              payload <enable|disable|status> [channel] [userid]");
1880c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "              activate [<usesolkeepalive|nokeepalive>] [instance=<number>]");
1881c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "              deactivate [instance=<number>]");
1882c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "              looptest [<loop times> [<loop interval(in ms)> [<instance>]]]");
1883c18ec02fSPetter Reinholdtsen }
1884c18ec02fSPetter Reinholdtsen 
1885c18ec02fSPetter Reinholdtsen 
1886c18ec02fSPetter Reinholdtsen 
1887c18ec02fSPetter Reinholdtsen /*
1888c18ec02fSPetter Reinholdtsen  * print_sol_set_usage
1889c18ec02fSPetter Reinholdtsen  */
1890c18ec02fSPetter Reinholdtsen static void
print_sol_set_usage(void)1891c18ec02fSPetter Reinholdtsen print_sol_set_usage(void)
1892c18ec02fSPetter Reinholdtsen {
1893c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "\nSOL set parameters and values: \n");
1894c18ec02fSPetter Reinholdtsen   	lprintf(LOG_NOTICE, "  set-in-progress             set-complete | "
1895c18ec02fSPetter Reinholdtsen 		"set-in-progress | commit-write");
1896c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  enabled                     true | false");
1897c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  force-encryption            true | false");
1898c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  force-authentication        true | false");
1899c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  privilege-level             user | operator | admin | oem");
1900c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  character-accumulate-level  <in 5 ms increments>");
1901c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  character-send-threshold    N");
1902c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  retry-count                 N");
1903c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  retry-interval              <in 10 ms increments>");
1904c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  non-volatile-bit-rate       "
1905c18ec02fSPetter Reinholdtsen 		"serial | 9.6 | 19.2 | 38.4 | 57.6 | 115.2");
1906c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  volatile-bit-rate           "
1907c18ec02fSPetter Reinholdtsen 		"serial | 9.6 | 19.2 | 38.4 | 57.6 | 115.2");
1908c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
1909c18ec02fSPetter Reinholdtsen }
1910c18ec02fSPetter Reinholdtsen 
1911c18ec02fSPetter Reinholdtsen 
1912c18ec02fSPetter Reinholdtsen 
1913c18ec02fSPetter Reinholdtsen /* ipmi_sol_main */
1914c18ec02fSPetter Reinholdtsen int
ipmi_sol_main(struct ipmi_intf * intf,int argc,char ** argv)1915c18ec02fSPetter Reinholdtsen ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
1916c18ec02fSPetter Reinholdtsen {
1917c18ec02fSPetter Reinholdtsen 	int retval = 0;
1918c18ec02fSPetter Reinholdtsen 	if (!argc || !strncmp(argv[0], "help", 4)) {
1919c18ec02fSPetter Reinholdtsen 		/* Help */
1920c18ec02fSPetter Reinholdtsen 		print_sol_usage();
1921c18ec02fSPetter Reinholdtsen 	} else if (!strncmp(argv[0], "info", 4)) {
1922c18ec02fSPetter Reinholdtsen 		/* Info */
1923c18ec02fSPetter Reinholdtsen 		uint8_t channel;
1924c18ec02fSPetter Reinholdtsen 		if (argc == 1) {
1925c18ec02fSPetter Reinholdtsen 			/* Ask about the current channel */
1926c18ec02fSPetter Reinholdtsen 			channel = 0x0E;
1927c18ec02fSPetter Reinholdtsen 		} else if (argc == 2) {
1928c18ec02fSPetter Reinholdtsen 			if (is_ipmi_channel_num(argv[1], &channel) != 0) {
1929c18ec02fSPetter Reinholdtsen 				return (-1);
1930c18ec02fSPetter Reinholdtsen 			}
1931c18ec02fSPetter Reinholdtsen 		} else {
1932c18ec02fSPetter Reinholdtsen 			print_sol_usage();
1933c18ec02fSPetter Reinholdtsen 			return -1;
1934c18ec02fSPetter Reinholdtsen 		}
1935c18ec02fSPetter Reinholdtsen 		retval = ipmi_print_sol_info(intf, channel);
1936c18ec02fSPetter Reinholdtsen 	} else if (!strncmp(argv[0], "payload", 7)) {
1937c18ec02fSPetter Reinholdtsen 		/* Payload enable or disable */
1938c18ec02fSPetter Reinholdtsen 		uint8_t channel = 0xe;
1939c18ec02fSPetter Reinholdtsen 		uint8_t userid = 1;
1940c18ec02fSPetter Reinholdtsen 		int enable = -1;
1941c18ec02fSPetter Reinholdtsen 		if (argc == 1 || argc > 4) {
1942c18ec02fSPetter Reinholdtsen 			print_sol_usage();
1943c18ec02fSPetter Reinholdtsen 			return -1;
1944c18ec02fSPetter Reinholdtsen 		}
1945c18ec02fSPetter Reinholdtsen 		if (argc >= 3) {
1946c18ec02fSPetter Reinholdtsen 			if (is_ipmi_channel_num(argv[2], &channel) != 0) {
1947c18ec02fSPetter Reinholdtsen 				return (-1);
1948c18ec02fSPetter Reinholdtsen 			}
1949c18ec02fSPetter Reinholdtsen 		}
1950c18ec02fSPetter Reinholdtsen 		if (argc == 4) {
1951c18ec02fSPetter Reinholdtsen 			if (is_ipmi_user_id(argv[3], &userid) != 0) {
1952c18ec02fSPetter Reinholdtsen 				return (-1);
1953c18ec02fSPetter Reinholdtsen 			}
1954c18ec02fSPetter Reinholdtsen 		}
1955c18ec02fSPetter Reinholdtsen 		if (!strncmp(argv[1], "enable", 6)) {
1956c18ec02fSPetter Reinholdtsen 			enable = 1;
1957c18ec02fSPetter Reinholdtsen 		} else if (!strncmp(argv[1], "disable", 7)) {
1958c18ec02fSPetter Reinholdtsen 			enable = 0;
1959c18ec02fSPetter Reinholdtsen 		} else if (!strncmp(argv[1], "status", 6)) {
1960c18ec02fSPetter Reinholdtsen 			return ipmi_sol_payload_access_status(intf, channel, userid);
1961c18ec02fSPetter Reinholdtsen 		} else {
1962c18ec02fSPetter Reinholdtsen 			print_sol_usage();
1963c18ec02fSPetter Reinholdtsen 			return -1;
1964c18ec02fSPetter Reinholdtsen 		}
1965c18ec02fSPetter Reinholdtsen 		retval = ipmi_sol_payload_access(intf, channel, userid, enable);
1966c18ec02fSPetter Reinholdtsen 	} else if (!strncmp(argv[0], "set", 3)) {
1967c18ec02fSPetter Reinholdtsen 		/* Set a parameter value */
1968c18ec02fSPetter Reinholdtsen 		uint8_t channel = 0xe;
1969c18ec02fSPetter Reinholdtsen 		uint8_t guard = 1;
1970c18ec02fSPetter Reinholdtsen 		if (argc == 3) {
1971c18ec02fSPetter Reinholdtsen 			channel = 0xe;
1972c18ec02fSPetter Reinholdtsen 		} else if (argc == 4) {
1973c18ec02fSPetter Reinholdtsen 			if (!strncmp(argv[3], "noguard", 7)) {
1974c18ec02fSPetter Reinholdtsen 				guard = 0;
1975c18ec02fSPetter Reinholdtsen 			} else {
1976c18ec02fSPetter Reinholdtsen 				if (is_ipmi_channel_num(argv[3], &channel) != 0) {
1977c18ec02fSPetter Reinholdtsen 					return (-1);
1978c18ec02fSPetter Reinholdtsen 				}
1979c18ec02fSPetter Reinholdtsen 			}
1980c18ec02fSPetter Reinholdtsen 		} else if (argc == 5) {
1981c18ec02fSPetter Reinholdtsen 			if (is_ipmi_channel_num(argv[3], &channel) != 0) {
1982c18ec02fSPetter Reinholdtsen 				return (-1);
1983c18ec02fSPetter Reinholdtsen 			}
1984c18ec02fSPetter Reinholdtsen 			if (!strncmp(argv[4], "noguard", 7)) {
1985c18ec02fSPetter Reinholdtsen 				guard = 0;
1986c18ec02fSPetter Reinholdtsen 			}
1987c18ec02fSPetter Reinholdtsen 		} else {
1988c18ec02fSPetter Reinholdtsen 			print_sol_set_usage();
1989c18ec02fSPetter Reinholdtsen 			return -1;
1990c18ec02fSPetter Reinholdtsen 		}
1991c18ec02fSPetter Reinholdtsen 		retval = ipmi_sol_set_param(intf, channel, argv[1], argv[2], guard);
1992c18ec02fSPetter Reinholdtsen 	} else if (!strncmp(argv[0], "activate", 8)) {
1993c18ec02fSPetter Reinholdtsen 		/* Activate */
1994c18ec02fSPetter Reinholdtsen 		int i;
1995c18ec02fSPetter Reinholdtsen 		uint8_t instance = 1;
1996c18ec02fSPetter Reinholdtsen 		for (i = 1; i < argc; i++) {
1997c18ec02fSPetter Reinholdtsen 			if (!strncmp(argv[i], "usesolkeepalive", 15)) {
1998c18ec02fSPetter Reinholdtsen 				_use_sol_for_keepalive = 1;
1999c18ec02fSPetter Reinholdtsen 			} else if (!strncmp(argv[i], "nokeepalive", 11)) {
2000c18ec02fSPetter Reinholdtsen 				_disable_keepalive = 1;
2001c18ec02fSPetter Reinholdtsen 			} else if (!strncmp(argv[i], "instance=", 9)) {
2002c18ec02fSPetter Reinholdtsen 				if (str2uchar(argv[i] + 9, &instance) != 0) {
2003c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR, "Given instance '%s' is invalid.", argv[i] + 9);
2004c18ec02fSPetter Reinholdtsen 					print_sol_usage();
2005c18ec02fSPetter Reinholdtsen 					return -1;
2006c18ec02fSPetter Reinholdtsen 				}
2007c18ec02fSPetter Reinholdtsen 			} else {
2008c18ec02fSPetter Reinholdtsen 				print_sol_usage();
2009c18ec02fSPetter Reinholdtsen 				return -1;
2010c18ec02fSPetter Reinholdtsen 			}
2011c18ec02fSPetter Reinholdtsen 		}
2012c18ec02fSPetter Reinholdtsen 		retval = ipmi_sol_activate(intf, 0, 0, instance);
2013c18ec02fSPetter Reinholdtsen 	} else if (!strncmp(argv[0], "deactivate", 10)) {
2014c18ec02fSPetter Reinholdtsen 		/* Dectivate */
2015c18ec02fSPetter Reinholdtsen 		int i;
2016c18ec02fSPetter Reinholdtsen 		uint8_t instance = 1;
2017c18ec02fSPetter Reinholdtsen 		for (i = 1; i < argc; i++) {
2018c18ec02fSPetter Reinholdtsen 			if (!strncmp(argv[i], "instance=", 9)) {
2019c18ec02fSPetter Reinholdtsen 				if (str2uchar(argv[i] + 9, &instance) != 0) {
2020c18ec02fSPetter Reinholdtsen 					lprintf(LOG_ERR,
2021c18ec02fSPetter Reinholdtsen 							"Given instance '%s' is invalid.",
2022c18ec02fSPetter Reinholdtsen 							argv[i] + 9);
2023c18ec02fSPetter Reinholdtsen 					print_sol_usage();
2024c18ec02fSPetter Reinholdtsen 					return -1;
2025c18ec02fSPetter Reinholdtsen 				}
2026c18ec02fSPetter Reinholdtsen 			} else {
2027c18ec02fSPetter Reinholdtsen 				print_sol_usage();
2028c18ec02fSPetter Reinholdtsen 				return -1;
2029c18ec02fSPetter Reinholdtsen 			}
2030c18ec02fSPetter Reinholdtsen 		}
2031c18ec02fSPetter Reinholdtsen 		retval = ipmi_sol_deactivate(intf, instance);
2032c18ec02fSPetter Reinholdtsen 	} else if (!strncmp(argv[0], "looptest", 8)) {
2033c18ec02fSPetter Reinholdtsen 		/* SOL loop test: Activate and then Dectivate */
2034c18ec02fSPetter Reinholdtsen 		int cnt = 200;
2035c18ec02fSPetter Reinholdtsen 		int interval = 100; /* Unit is: ms */
2036c18ec02fSPetter Reinholdtsen 		uint8_t instance = 1;
2037c18ec02fSPetter Reinholdtsen 		if (argc > 4) {
2038c18ec02fSPetter Reinholdtsen 			print_sol_usage();
2039c18ec02fSPetter Reinholdtsen 			return -1;
2040c18ec02fSPetter Reinholdtsen 		}
2041c18ec02fSPetter Reinholdtsen 		if (argc != 1) {
2042c18ec02fSPetter Reinholdtsen 			/* at least 2 */
2043c18ec02fSPetter Reinholdtsen 			if (str2int(argv[1], &cnt) != 0) {
2044c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Given cnt '%s' is invalid.",
2045c18ec02fSPetter Reinholdtsen 						argv[1]);
2046c18ec02fSPetter Reinholdtsen 				return (-1);
2047c18ec02fSPetter Reinholdtsen 			}
2048c18ec02fSPetter Reinholdtsen 			if (cnt <= 0) {
2049c18ec02fSPetter Reinholdtsen 				cnt = 200;
2050c18ec02fSPetter Reinholdtsen 			}
2051c18ec02fSPetter Reinholdtsen 		}
2052c18ec02fSPetter Reinholdtsen 		if (argc >= 3) {
2053c18ec02fSPetter Reinholdtsen 			if (str2int(argv[2], &interval) != 0) {
2054c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Given interval '%s' is invalid.",
2055c18ec02fSPetter Reinholdtsen 						argv[2]);
2056c18ec02fSPetter Reinholdtsen 				return (-1);
2057c18ec02fSPetter Reinholdtsen 			}
2058c18ec02fSPetter Reinholdtsen 			if (interval < 0) {
2059c18ec02fSPetter Reinholdtsen 				interval = 0;
2060c18ec02fSPetter Reinholdtsen 			}
2061c18ec02fSPetter Reinholdtsen 		}
2062c18ec02fSPetter Reinholdtsen 		if (argc >= 4) {
2063c18ec02fSPetter Reinholdtsen 			if (str2uchar(argv[3], &instance) != 0) {
2064c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Given instance '%s' is invalid.",
2065c18ec02fSPetter Reinholdtsen 						argv[3]);
2066c18ec02fSPetter Reinholdtsen 				print_sol_usage();
2067c18ec02fSPetter Reinholdtsen 				return -1;
2068c18ec02fSPetter Reinholdtsen 			}
2069c18ec02fSPetter Reinholdtsen 		}
2070c18ec02fSPetter Reinholdtsen 
2071c18ec02fSPetter Reinholdtsen 		while (cnt > 0) {
2072c18ec02fSPetter Reinholdtsen 			printf("remain loop test counter: %d\n", cnt);
2073c18ec02fSPetter Reinholdtsen 			retval = ipmi_sol_activate(intf, 1, interval, instance);
2074c18ec02fSPetter Reinholdtsen 			if (retval) {
2075c18ec02fSPetter Reinholdtsen 				printf("SOL looptest failed: %d\n",
2076c18ec02fSPetter Reinholdtsen 						retval);
2077c18ec02fSPetter Reinholdtsen 				break;
2078c18ec02fSPetter Reinholdtsen 			}
2079c18ec02fSPetter Reinholdtsen 			cnt -= 1;
2080c18ec02fSPetter Reinholdtsen 		}
2081c18ec02fSPetter Reinholdtsen 	} else {
2082c18ec02fSPetter Reinholdtsen 		print_sol_usage();
2083c18ec02fSPetter Reinholdtsen 		retval = -1;
2084c18ec02fSPetter Reinholdtsen 	}
2085c18ec02fSPetter Reinholdtsen 	return retval;
2086c18ec02fSPetter Reinholdtsen }
2087