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