xref: /openbmc/ipmitool/lib/ipmi_mc.c (revision c18ec02f)
1*c18ec02fSPetter Reinholdtsen /*
2*c18ec02fSPetter Reinholdtsen  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3*c18ec02fSPetter Reinholdtsen  *
4*c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
5*c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
6*c18ec02fSPetter Reinholdtsen  * are met:
7*c18ec02fSPetter Reinholdtsen  *
8*c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
9*c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
10*c18ec02fSPetter Reinholdtsen  *
11*c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
12*c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
13*c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
14*c18ec02fSPetter Reinholdtsen  *
15*c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
16*c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
17*c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
18*c18ec02fSPetter Reinholdtsen  *
19*c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
20*c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21*c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22*c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23*c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24*c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25*c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26*c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27*c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28*c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29*c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30*c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31*c18ec02fSPetter Reinholdtsen  */
32*c18ec02fSPetter Reinholdtsen 
33*c18ec02fSPetter Reinholdtsen #include <stdlib.h>
34*c18ec02fSPetter Reinholdtsen #include <string.h>
35*c18ec02fSPetter Reinholdtsen #include <stdio.h>
36*c18ec02fSPetter Reinholdtsen #include <time.h>
37*c18ec02fSPetter Reinholdtsen 
38*c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
39*c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
40*c18ec02fSPetter Reinholdtsen #include <ipmitool/bswap.h>
41*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
42*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
43*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_mc.h>
44*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
45*c18ec02fSPetter Reinholdtsen 
46*c18ec02fSPetter Reinholdtsen extern int verbose;
47*c18ec02fSPetter Reinholdtsen 
48*c18ec02fSPetter Reinholdtsen static int ipmi_sysinfo_main(struct ipmi_intf *intf, int argc, char ** argv,
49*c18ec02fSPetter Reinholdtsen 		int is_set);
50*c18ec02fSPetter Reinholdtsen static void printf_sysinfo_usage(int full_help);
51*c18ec02fSPetter Reinholdtsen 
52*c18ec02fSPetter Reinholdtsen /* ipmi_mc_reset  -  attempt to reset an MC
53*c18ec02fSPetter Reinholdtsen  *
54*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
55*c18ec02fSPetter Reinholdtsen  * @cmd:	reset command to send
56*c18ec02fSPetter Reinholdtsen  *              BMC_WARM_RESET or
57*c18ec02fSPetter Reinholdtsen  *              BMC_COLD_RESET
58*c18ec02fSPetter Reinholdtsen  *
59*c18ec02fSPetter Reinholdtsen  * returns 0 on success
60*c18ec02fSPetter Reinholdtsen  * returns -1 on error
61*c18ec02fSPetter Reinholdtsen  */
62*c18ec02fSPetter Reinholdtsen static int
63*c18ec02fSPetter Reinholdtsen ipmi_mc_reset(struct ipmi_intf * intf, int cmd)
64*c18ec02fSPetter Reinholdtsen {
65*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
66*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
67*c18ec02fSPetter Reinholdtsen 
68*c18ec02fSPetter Reinholdtsen 	if( !intf->opened )
69*c18ec02fSPetter Reinholdtsen 	intf->open(intf);
70*c18ec02fSPetter Reinholdtsen 
71*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
72*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
73*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = cmd;
74*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 0;
75*c18ec02fSPetter Reinholdtsen 
76*c18ec02fSPetter Reinholdtsen 	if (cmd == BMC_COLD_RESET)
77*c18ec02fSPetter Reinholdtsen 		intf->noanswer = 1;
78*c18ec02fSPetter Reinholdtsen 
79*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
80*c18ec02fSPetter Reinholdtsen 
81*c18ec02fSPetter Reinholdtsen 	if (cmd == BMC_COLD_RESET)
82*c18ec02fSPetter Reinholdtsen 		intf->abort = 1;
83*c18ec02fSPetter Reinholdtsen 
84*c18ec02fSPetter Reinholdtsen 	if (cmd == BMC_COLD_RESET && rsp == NULL) {
85*c18ec02fSPetter Reinholdtsen 		/* This is expected. See 20.2 Cold Reset Command, p.243, IPMIv2.0 rev1.0 */
86*c18ec02fSPetter Reinholdtsen 	} else if (rsp == NULL) {
87*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "MC reset command failed.");
88*c18ec02fSPetter Reinholdtsen 		return (-1);
89*c18ec02fSPetter Reinholdtsen 	} else if (rsp->ccode > 0) {
90*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "MC reset command failed: %s",
91*c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
92*c18ec02fSPetter Reinholdtsen 		return (-1);
93*c18ec02fSPetter Reinholdtsen 	}
94*c18ec02fSPetter Reinholdtsen 
95*c18ec02fSPetter Reinholdtsen 	printf("Sent %s reset command to MC\n",
96*c18ec02fSPetter Reinholdtsen 	       (cmd == BMC_WARM_RESET) ? "warm" : "cold");
97*c18ec02fSPetter Reinholdtsen 
98*c18ec02fSPetter Reinholdtsen 	return 0;
99*c18ec02fSPetter Reinholdtsen }
100*c18ec02fSPetter Reinholdtsen 
101*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
102*c18ec02fSPetter Reinholdtsen #pragma pack(1)
103*c18ec02fSPetter Reinholdtsen #endif
104*c18ec02fSPetter Reinholdtsen struct bmc_enables_data {
105*c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN
106*c18ec02fSPetter Reinholdtsen 	uint8_t oem2		: 1;
107*c18ec02fSPetter Reinholdtsen 	uint8_t oem1		: 1;
108*c18ec02fSPetter Reinholdtsen 	uint8_t oem0		: 1;
109*c18ec02fSPetter Reinholdtsen 	uint8_t __reserved	: 1;
110*c18ec02fSPetter Reinholdtsen 	uint8_t system_event_log	: 1;
111*c18ec02fSPetter Reinholdtsen 	uint8_t event_msgbuf	: 1;
112*c18ec02fSPetter Reinholdtsen 	uint8_t event_msgbuf_intr	: 1;
113*c18ec02fSPetter Reinholdtsen 	uint8_t receive_msg_intr	: 1;
114*c18ec02fSPetter Reinholdtsen #else
115*c18ec02fSPetter Reinholdtsen 	uint8_t receive_msg_intr	: 1;
116*c18ec02fSPetter Reinholdtsen 	uint8_t event_msgbuf_intr	: 1;
117*c18ec02fSPetter Reinholdtsen 	uint8_t event_msgbuf	: 1;
118*c18ec02fSPetter Reinholdtsen 	uint8_t system_event_log	: 1;
119*c18ec02fSPetter Reinholdtsen 	uint8_t __reserved	: 1;
120*c18ec02fSPetter Reinholdtsen 	uint8_t oem0		: 1;
121*c18ec02fSPetter Reinholdtsen 	uint8_t oem1		: 1;
122*c18ec02fSPetter Reinholdtsen 	uint8_t oem2		: 1;
123*c18ec02fSPetter Reinholdtsen #endif
124*c18ec02fSPetter Reinholdtsen } ATTRIBUTE_PACKING;
125*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
126*c18ec02fSPetter Reinholdtsen #pragma pack(0)
127*c18ec02fSPetter Reinholdtsen #endif
128*c18ec02fSPetter Reinholdtsen 
129*c18ec02fSPetter Reinholdtsen struct bitfield_data {
130*c18ec02fSPetter Reinholdtsen 	const char * name;
131*c18ec02fSPetter Reinholdtsen 	const char * desc;
132*c18ec02fSPetter Reinholdtsen 	uint32_t mask;
133*c18ec02fSPetter Reinholdtsen };
134*c18ec02fSPetter Reinholdtsen 
135*c18ec02fSPetter Reinholdtsen struct bitfield_data mc_enables_bf[] = {
136*c18ec02fSPetter Reinholdtsen 	{
137*c18ec02fSPetter Reinholdtsen 		name:	"recv_msg_intr",
138*c18ec02fSPetter Reinholdtsen 		desc:	"Receive Message Queue Interrupt",
139*c18ec02fSPetter Reinholdtsen 		mask:	1<<0,
140*c18ec02fSPetter Reinholdtsen 	},
141*c18ec02fSPetter Reinholdtsen 	{
142*c18ec02fSPetter Reinholdtsen 		name:	"event_msg_intr",
143*c18ec02fSPetter Reinholdtsen 		desc:	"Event Message Buffer Full Interrupt",
144*c18ec02fSPetter Reinholdtsen 		mask:	1<<1,
145*c18ec02fSPetter Reinholdtsen 	},
146*c18ec02fSPetter Reinholdtsen 	{
147*c18ec02fSPetter Reinholdtsen 		name:	"event_msg",
148*c18ec02fSPetter Reinholdtsen 		desc:	"Event Message Buffer",
149*c18ec02fSPetter Reinholdtsen 		mask:	1<<2,
150*c18ec02fSPetter Reinholdtsen 	},
151*c18ec02fSPetter Reinholdtsen 	{
152*c18ec02fSPetter Reinholdtsen 		name:	"system_event_log",
153*c18ec02fSPetter Reinholdtsen 		desc:	"System Event Logging",
154*c18ec02fSPetter Reinholdtsen 		mask:	1<<3,
155*c18ec02fSPetter Reinholdtsen 	},
156*c18ec02fSPetter Reinholdtsen 	{
157*c18ec02fSPetter Reinholdtsen 		name:	"oem0",
158*c18ec02fSPetter Reinholdtsen 		desc:	"OEM 0",
159*c18ec02fSPetter Reinholdtsen 		mask:	1<<5,
160*c18ec02fSPetter Reinholdtsen 	},
161*c18ec02fSPetter Reinholdtsen 	{
162*c18ec02fSPetter Reinholdtsen 		name:	"oem1",
163*c18ec02fSPetter Reinholdtsen 		desc:	"OEM 1",
164*c18ec02fSPetter Reinholdtsen 		mask:	1<<6,
165*c18ec02fSPetter Reinholdtsen 	},
166*c18ec02fSPetter Reinholdtsen 	{
167*c18ec02fSPetter Reinholdtsen 		name:	"oem2",
168*c18ec02fSPetter Reinholdtsen 		desc:	"OEM 2",
169*c18ec02fSPetter Reinholdtsen 		mask:	1<<7,
170*c18ec02fSPetter Reinholdtsen 	},
171*c18ec02fSPetter Reinholdtsen 	{ NULL },
172*c18ec02fSPetter Reinholdtsen };
173*c18ec02fSPetter Reinholdtsen 
174*c18ec02fSPetter Reinholdtsen static void
175*c18ec02fSPetter Reinholdtsen printf_mc_reset_usage(void)
176*c18ec02fSPetter Reinholdtsen {
177*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "usage: mc reset <warm|cold>");
178*c18ec02fSPetter Reinholdtsen } /* printf_mc_reset_usage(void) */
179*c18ec02fSPetter Reinholdtsen 
180*c18ec02fSPetter Reinholdtsen static void
181*c18ec02fSPetter Reinholdtsen printf_mc_usage(void)
182*c18ec02fSPetter Reinholdtsen {
183*c18ec02fSPetter Reinholdtsen 	struct bitfield_data * bf;
184*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "MC Commands:");
185*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  reset <warm|cold>");
186*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  guid");
187*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  info");
188*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  watchdog <get|reset|off>");
189*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  selftest");
190*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  getenables");
191*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  setenables <option=on|off> ...");
192*c18ec02fSPetter Reinholdtsen 	for (bf = mc_enables_bf; bf->name != NULL; bf++) {
193*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "    %-20s  %s", bf->name, bf->desc);
194*c18ec02fSPetter Reinholdtsen 	}
195*c18ec02fSPetter Reinholdtsen 	printf_sysinfo_usage(0);
196*c18ec02fSPetter Reinholdtsen }
197*c18ec02fSPetter Reinholdtsen 
198*c18ec02fSPetter Reinholdtsen static void
199*c18ec02fSPetter Reinholdtsen printf_sysinfo_usage(int full_help)
200*c18ec02fSPetter Reinholdtsen {
201*c18ec02fSPetter Reinholdtsen 	if (full_help != 0)
202*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "usage:");
203*c18ec02fSPetter Reinholdtsen 
204*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  getsysinfo <argument>");
205*c18ec02fSPetter Reinholdtsen 
206*c18ec02fSPetter Reinholdtsen 	if (full_help != 0) {
207*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
208*c18ec02fSPetter Reinholdtsen 				"    Retrieves system info from BMC for given argument");
209*c18ec02fSPetter Reinholdtsen 	}
210*c18ec02fSPetter Reinholdtsen 
211*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "  setsysinfo <argument> <string>");
212*c18ec02fSPetter Reinholdtsen 
213*c18ec02fSPetter Reinholdtsen 	if (full_help != 0) {
214*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE,
215*c18ec02fSPetter Reinholdtsen 				"    Stores system info string for given argument to BMC");
216*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "");
217*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_NOTICE, "  Valid arguments are:");
218*c18ec02fSPetter Reinholdtsen 	}
219*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE,
220*c18ec02fSPetter Reinholdtsen 			"    primary_os_name     Primary operating system name");
221*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "    os_name             Operating system name");
222*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE,
223*c18ec02fSPetter Reinholdtsen 			"    system_name         System Name of server(vendor dependent)");
224*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE,
225*c18ec02fSPetter Reinholdtsen 			"    delloem_os_version  Running version of operating system");
226*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "    delloem_url         URL of BMC webserver");
227*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
228*c18ec02fSPetter Reinholdtsen }
229*c18ec02fSPetter Reinholdtsen 
230*c18ec02fSPetter Reinholdtsen static void
231*c18ec02fSPetter Reinholdtsen print_watchdog_usage(void)
232*c18ec02fSPetter Reinholdtsen {
233*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "usage: watchdog <command>:");
234*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "   get    :  Get Current Watchdog settings");
235*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "   reset  :  Restart Watchdog timer based on most recent settings");
236*c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "   off    :  Shut off a running Watchdog timer");
237*c18ec02fSPetter Reinholdtsen }
238*c18ec02fSPetter Reinholdtsen 
239*c18ec02fSPetter Reinholdtsen /* ipmi_mc_get_enables  -  print out MC enables
240*c18ec02fSPetter Reinholdtsen  *
241*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi inteface
242*c18ec02fSPetter Reinholdtsen  *
243*c18ec02fSPetter Reinholdtsen  * returns 0 on success
244*c18ec02fSPetter Reinholdtsen  * returns -1 on error
245*c18ec02fSPetter Reinholdtsen  */
246*c18ec02fSPetter Reinholdtsen static int
247*c18ec02fSPetter Reinholdtsen ipmi_mc_get_enables(struct ipmi_intf * intf)
248*c18ec02fSPetter Reinholdtsen {
249*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
250*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
251*c18ec02fSPetter Reinholdtsen 	struct bitfield_data * bf;
252*c18ec02fSPetter Reinholdtsen 
253*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
254*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
255*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = BMC_GET_GLOBAL_ENABLES;
256*c18ec02fSPetter Reinholdtsen 
257*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
258*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
259*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Global Enables command failed");
260*c18ec02fSPetter Reinholdtsen 		return -1;
261*c18ec02fSPetter Reinholdtsen 	}
262*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
263*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Global Enables command failed: %s",
264*c18ec02fSPetter Reinholdtsen 		       val2str(rsp->ccode, completion_code_vals));
265*c18ec02fSPetter Reinholdtsen 		return -1;
266*c18ec02fSPetter Reinholdtsen 	}
267*c18ec02fSPetter Reinholdtsen 
268*c18ec02fSPetter Reinholdtsen 	for (bf = mc_enables_bf; bf->name != NULL; bf++) {
269*c18ec02fSPetter Reinholdtsen 		printf("%-40s : %sabled\n", bf->desc,
270*c18ec02fSPetter Reinholdtsen 		       rsp->data[0] & bf->mask ? "en" : "dis");
271*c18ec02fSPetter Reinholdtsen 	}
272*c18ec02fSPetter Reinholdtsen 
273*c18ec02fSPetter Reinholdtsen 	return 0;
274*c18ec02fSPetter Reinholdtsen }
275*c18ec02fSPetter Reinholdtsen 
276*c18ec02fSPetter Reinholdtsen /* ipmi_mc_set_enables  -  set MC enable flags
277*c18ec02fSPetter Reinholdtsen  *
278*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi inteface
279*c18ec02fSPetter Reinholdtsen  * @argc:	argument count
280*c18ec02fSPetter Reinholdtsen  * @argv:	argument list
281*c18ec02fSPetter Reinholdtsen  *
282*c18ec02fSPetter Reinholdtsen  * returns 0 on success
283*c18ec02fSPetter Reinholdtsen  * returns -1 on error
284*c18ec02fSPetter Reinholdtsen  */
285*c18ec02fSPetter Reinholdtsen static int
286*c18ec02fSPetter Reinholdtsen ipmi_mc_set_enables(struct ipmi_intf * intf, int argc, char ** argv)
287*c18ec02fSPetter Reinholdtsen {
288*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
289*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
290*c18ec02fSPetter Reinholdtsen 	struct bitfield_data * bf;
291*c18ec02fSPetter Reinholdtsen 	uint8_t en;
292*c18ec02fSPetter Reinholdtsen 	int i;
293*c18ec02fSPetter Reinholdtsen 
294*c18ec02fSPetter Reinholdtsen 	if (argc < 1) {
295*c18ec02fSPetter Reinholdtsen 		printf_mc_usage();
296*c18ec02fSPetter Reinholdtsen 		return (-1);
297*c18ec02fSPetter Reinholdtsen 	}
298*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "help", 4) == 0) {
299*c18ec02fSPetter Reinholdtsen 		printf_mc_usage();
300*c18ec02fSPetter Reinholdtsen 		return 0;
301*c18ec02fSPetter Reinholdtsen 	}
302*c18ec02fSPetter Reinholdtsen 
303*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
304*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
305*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = BMC_GET_GLOBAL_ENABLES;
306*c18ec02fSPetter Reinholdtsen 
307*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
308*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
309*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Global Enables command failed");
310*c18ec02fSPetter Reinholdtsen 		return -1;
311*c18ec02fSPetter Reinholdtsen 	}
312*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
313*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Global Enables command failed: %s",
314*c18ec02fSPetter Reinholdtsen 		       val2str(rsp->ccode, completion_code_vals));
315*c18ec02fSPetter Reinholdtsen 		return -1;
316*c18ec02fSPetter Reinholdtsen 	}
317*c18ec02fSPetter Reinholdtsen 
318*c18ec02fSPetter Reinholdtsen 	en = rsp->data[0];
319*c18ec02fSPetter Reinholdtsen 
320*c18ec02fSPetter Reinholdtsen 	for (i = 0; i < argc; i++) {
321*c18ec02fSPetter Reinholdtsen 		for (bf = mc_enables_bf; bf->name != NULL; bf++) {
322*c18ec02fSPetter Reinholdtsen 			int nl = strlen(bf->name);
323*c18ec02fSPetter Reinholdtsen 			if (strncmp(argv[i], bf->name, nl) != 0)
324*c18ec02fSPetter Reinholdtsen 				continue;
325*c18ec02fSPetter Reinholdtsen 			if (strncmp(argv[i]+nl+1, "off", 3) == 0) {
326*c18ec02fSPetter Reinholdtsen 					printf("Disabling %s\n", bf->desc);
327*c18ec02fSPetter Reinholdtsen 					en &= ~bf->mask;
328*c18ec02fSPetter Reinholdtsen 			}
329*c18ec02fSPetter Reinholdtsen 			else if (strncmp(argv[i]+nl+1, "on", 2) == 0) {
330*c18ec02fSPetter Reinholdtsen 					printf("Enabling %s\n", bf->desc);
331*c18ec02fSPetter Reinholdtsen 					en |= bf->mask;
332*c18ec02fSPetter Reinholdtsen 			}
333*c18ec02fSPetter Reinholdtsen 			else {
334*c18ec02fSPetter Reinholdtsen 				lprintf(LOG_ERR, "Unrecognized option: %s", argv[i]);
335*c18ec02fSPetter Reinholdtsen 			}
336*c18ec02fSPetter Reinholdtsen 		}
337*c18ec02fSPetter Reinholdtsen 	}
338*c18ec02fSPetter Reinholdtsen 
339*c18ec02fSPetter Reinholdtsen 	if (en == rsp->data[0]) {
340*c18ec02fSPetter Reinholdtsen 		printf("\nNothing to change...\n");
341*c18ec02fSPetter Reinholdtsen 		ipmi_mc_get_enables(intf);
342*c18ec02fSPetter Reinholdtsen 		return 0;
343*c18ec02fSPetter Reinholdtsen 	}
344*c18ec02fSPetter Reinholdtsen 
345*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = BMC_SET_GLOBAL_ENABLES;
346*c18ec02fSPetter Reinholdtsen 	req.msg.data = &en;
347*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 1;
348*c18ec02fSPetter Reinholdtsen 
349*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
350*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
351*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Set Global Enables command failed");
352*c18ec02fSPetter Reinholdtsen 		return -1;
353*c18ec02fSPetter Reinholdtsen 	}
354*c18ec02fSPetter Reinholdtsen 	else if (rsp->ccode > 0) {
355*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Set Global Enables command failed: %s",
356*c18ec02fSPetter Reinholdtsen 		       val2str(rsp->ccode, completion_code_vals));
357*c18ec02fSPetter Reinholdtsen 		return -1;
358*c18ec02fSPetter Reinholdtsen 	}
359*c18ec02fSPetter Reinholdtsen 
360*c18ec02fSPetter Reinholdtsen 	printf("\nVerifying...\n");
361*c18ec02fSPetter Reinholdtsen 	ipmi_mc_get_enables(intf);
362*c18ec02fSPetter Reinholdtsen 
363*c18ec02fSPetter Reinholdtsen 	return 0;
364*c18ec02fSPetter Reinholdtsen }
365*c18ec02fSPetter Reinholdtsen 
366*c18ec02fSPetter Reinholdtsen /* IPM Device, Get Device ID Command - Additional Device Support */
367*c18ec02fSPetter Reinholdtsen const char *ipm_dev_adtl_dev_support[8] = {
368*c18ec02fSPetter Reinholdtsen 	"Sensor Device",         /* bit 0 */
369*c18ec02fSPetter Reinholdtsen 	"SDR Repository Device", /* bit 1 */
370*c18ec02fSPetter Reinholdtsen 	"SEL Device",            /* bit 2 */
371*c18ec02fSPetter Reinholdtsen 	"FRU Inventory Device",  /*  ...  */
372*c18ec02fSPetter Reinholdtsen 	"IPMB Event Receiver",
373*c18ec02fSPetter Reinholdtsen 	"IPMB Event Generator",
374*c18ec02fSPetter Reinholdtsen 	"Bridge",
375*c18ec02fSPetter Reinholdtsen 	"Chassis Device"         /* bit 7 */
376*c18ec02fSPetter Reinholdtsen };
377*c18ec02fSPetter Reinholdtsen 
378*c18ec02fSPetter Reinholdtsen /* ipmi_mc_get_deviceid  -  print information about this MC
379*c18ec02fSPetter Reinholdtsen  *
380*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
381*c18ec02fSPetter Reinholdtsen  *
382*c18ec02fSPetter Reinholdtsen  * returns 0 on success
383*c18ec02fSPetter Reinholdtsen  * returns -1 on error
384*c18ec02fSPetter Reinholdtsen  */
385*c18ec02fSPetter Reinholdtsen static int
386*c18ec02fSPetter Reinholdtsen ipmi_mc_get_deviceid(struct ipmi_intf * intf)
387*c18ec02fSPetter Reinholdtsen {
388*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
389*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
390*c18ec02fSPetter Reinholdtsen 	struct ipm_devid_rsp *devid;
391*c18ec02fSPetter Reinholdtsen 	int i;
392*c18ec02fSPetter Reinholdtsen 	const char *product=NULL;
393*c18ec02fSPetter Reinholdtsen 
394*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
395*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
396*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = BMC_GET_DEVICE_ID;
397*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 0;
398*c18ec02fSPetter Reinholdtsen 
399*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
400*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
401*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Device ID command failed");
402*c18ec02fSPetter Reinholdtsen 		return -1;
403*c18ec02fSPetter Reinholdtsen 	}
404*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
405*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Device ID command failed: %s",
406*c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
407*c18ec02fSPetter Reinholdtsen 		return -1;
408*c18ec02fSPetter Reinholdtsen 	}
409*c18ec02fSPetter Reinholdtsen 
410*c18ec02fSPetter Reinholdtsen 	devid = (struct ipm_devid_rsp *) rsp->data;
411*c18ec02fSPetter Reinholdtsen 	printf("Device ID                 : %i\n",
412*c18ec02fSPetter Reinholdtsen 		devid->device_id);
413*c18ec02fSPetter Reinholdtsen 	printf("Device Revision           : %i\n",
414*c18ec02fSPetter Reinholdtsen 		devid->device_revision & IPM_DEV_DEVICE_ID_REV_MASK);
415*c18ec02fSPetter Reinholdtsen 	printf("Firmware Revision         : %u.%02x\n",
416*c18ec02fSPetter Reinholdtsen 		devid->fw_rev1 & IPM_DEV_FWREV1_MAJOR_MASK,
417*c18ec02fSPetter Reinholdtsen 		devid->fw_rev2);
418*c18ec02fSPetter Reinholdtsen 	printf("IPMI Version              : %x.%x\n",
419*c18ec02fSPetter Reinholdtsen 		IPM_DEV_IPMI_VERSION_MAJOR(devid->ipmi_version),
420*c18ec02fSPetter Reinholdtsen 		IPM_DEV_IPMI_VERSION_MINOR(devid->ipmi_version));
421*c18ec02fSPetter Reinholdtsen 	printf("Manufacturer ID           : %lu\n",
422*c18ec02fSPetter Reinholdtsen 		(long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id));
423*c18ec02fSPetter Reinholdtsen 	printf("Manufacturer Name         : %s\n",
424*c18ec02fSPetter Reinholdtsen 			val2str( (long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id),
425*c18ec02fSPetter Reinholdtsen 				ipmi_oem_info) );
426*c18ec02fSPetter Reinholdtsen 
427*c18ec02fSPetter Reinholdtsen 	printf("Product ID                : %u (0x%02x%02x)\n",
428*c18ec02fSPetter Reinholdtsen 		buf2short((uint8_t *)(devid->product_id)),
429*c18ec02fSPetter Reinholdtsen 		devid->product_id[1], devid->product_id[0]);
430*c18ec02fSPetter Reinholdtsen 
431*c18ec02fSPetter Reinholdtsen 	product=oemval2str(IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id),
432*c18ec02fSPetter Reinholdtsen 							 (devid->product_id[1]<<8)+devid->product_id[0],
433*c18ec02fSPetter Reinholdtsen 							 ipmi_oem_product_info);
434*c18ec02fSPetter Reinholdtsen 
435*c18ec02fSPetter Reinholdtsen 	if (product!=NULL) {
436*c18ec02fSPetter Reinholdtsen 		printf("Product Name              : %s\n", product);
437*c18ec02fSPetter Reinholdtsen 	}
438*c18ec02fSPetter Reinholdtsen 
439*c18ec02fSPetter Reinholdtsen 	printf("Device Available          : %s\n",
440*c18ec02fSPetter Reinholdtsen 		(devid->fw_rev1 & IPM_DEV_FWREV1_AVAIL_MASK) ?
441*c18ec02fSPetter Reinholdtsen 		"no" : "yes");
442*c18ec02fSPetter Reinholdtsen 	printf("Provides Device SDRs      : %s\n",
443*c18ec02fSPetter Reinholdtsen 		(devid->device_revision & IPM_DEV_DEVICE_ID_SDR_MASK) ?
444*c18ec02fSPetter Reinholdtsen 		"yes" : "no");
445*c18ec02fSPetter Reinholdtsen 	printf("Additional Device Support :\n");
446*c18ec02fSPetter Reinholdtsen 	for (i = 0; i < IPM_DEV_ADTL_SUPPORT_BITS; i++) {
447*c18ec02fSPetter Reinholdtsen 		if (devid->adtl_device_support & (1 << i)) {
448*c18ec02fSPetter Reinholdtsen 			printf("    %s\n", ipm_dev_adtl_dev_support[i]);
449*c18ec02fSPetter Reinholdtsen 		}
450*c18ec02fSPetter Reinholdtsen 	}
451*c18ec02fSPetter Reinholdtsen 	if (rsp->data_len == sizeof(*devid)) {
452*c18ec02fSPetter Reinholdtsen 		printf("Aux Firmware Rev Info     : \n");
453*c18ec02fSPetter Reinholdtsen 		/* These values could be looked-up by vendor if documented,
454*c18ec02fSPetter Reinholdtsen 		 * so we put them on individual lines for better treatment later
455*c18ec02fSPetter Reinholdtsen 		 */
456*c18ec02fSPetter Reinholdtsen 		printf("    0x%02x\n    0x%02x\n    0x%02x\n    0x%02x\n",
457*c18ec02fSPetter Reinholdtsen 			devid->aux_fw_rev[0],
458*c18ec02fSPetter Reinholdtsen 			devid->aux_fw_rev[1],
459*c18ec02fSPetter Reinholdtsen 			devid->aux_fw_rev[2],
460*c18ec02fSPetter Reinholdtsen 			devid->aux_fw_rev[3]);
461*c18ec02fSPetter Reinholdtsen 	}
462*c18ec02fSPetter Reinholdtsen 	return 0;
463*c18ec02fSPetter Reinholdtsen }
464*c18ec02fSPetter Reinholdtsen 
465*c18ec02fSPetter Reinholdtsen /* Structure follow the IPMI V.2 Rev 1.0
466*c18ec02fSPetter Reinholdtsen  * See Table 20-10 */
467*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
468*c18ec02fSPetter Reinholdtsen #pragma pack(1)
469*c18ec02fSPetter Reinholdtsen #endif
470*c18ec02fSPetter Reinholdtsen 
471*c18ec02fSPetter Reinholdtsen struct ipmi_guid {
472*c18ec02fSPetter Reinholdtsen 	uint32_t  time_low;	/* timestamp low field */
473*c18ec02fSPetter Reinholdtsen 	uint16_t  time_mid;	/* timestamp middle field */
474*c18ec02fSPetter Reinholdtsen 	uint16_t  time_hi_and_version; /* timestamp high field and version number */
475*c18ec02fSPetter Reinholdtsen 	uint8_t   clock_seq_hi_variant;/* clock sequence high field and variant */
476*c18ec02fSPetter Reinholdtsen 	uint8_t   clock_seq_low; /* clock sequence low field */
477*c18ec02fSPetter Reinholdtsen 	uint8_t   node[6];	/* node */
478*c18ec02fSPetter Reinholdtsen } ATTRIBUTE_PACKING;
479*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
480*c18ec02fSPetter Reinholdtsen #pragma pack(0)
481*c18ec02fSPetter Reinholdtsen #endif
482*c18ec02fSPetter Reinholdtsen 
483*c18ec02fSPetter Reinholdtsen /* ipmi_mc_get_guid  -  print this MC GUID
484*c18ec02fSPetter Reinholdtsen  *
485*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
486*c18ec02fSPetter Reinholdtsen  *
487*c18ec02fSPetter Reinholdtsen  * returns 0 on success
488*c18ec02fSPetter Reinholdtsen  * returns -1 on error
489*c18ec02fSPetter Reinholdtsen  */
490*c18ec02fSPetter Reinholdtsen static int
491*c18ec02fSPetter Reinholdtsen ipmi_mc_get_guid(struct ipmi_intf * intf)
492*c18ec02fSPetter Reinholdtsen {
493*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
494*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
495*c18ec02fSPetter Reinholdtsen 	struct ipmi_guid guid;
496*c18ec02fSPetter Reinholdtsen 
497*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
498*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
499*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = BMC_GET_GUID;
500*c18ec02fSPetter Reinholdtsen 
501*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
502*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
503*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get GUID command failed");
504*c18ec02fSPetter Reinholdtsen 		return -1;
505*c18ec02fSPetter Reinholdtsen 	}
506*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode > 0) {
507*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get GUID command failed: %s",
508*c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
509*c18ec02fSPetter Reinholdtsen 		return -1;
510*c18ec02fSPetter Reinholdtsen 	}
511*c18ec02fSPetter Reinholdtsen 
512*c18ec02fSPetter Reinholdtsen 	if (rsp->data_len == sizeof(struct ipmi_guid)) {
513*c18ec02fSPetter Reinholdtsen 		char tbuf[40];
514*c18ec02fSPetter Reinholdtsen 		time_t s;
515*c18ec02fSPetter Reinholdtsen 		memset(tbuf, 0, 40);
516*c18ec02fSPetter Reinholdtsen 		memset(&guid, 0, sizeof(struct ipmi_guid));
517*c18ec02fSPetter Reinholdtsen 		memcpy(&guid, rsp->data, rsp->data_len);
518*c18ec02fSPetter Reinholdtsen 
519*c18ec02fSPetter Reinholdtsen 		/* Kipp - changed order of last field (node) to follow specification */
520*c18ec02fSPetter Reinholdtsen 		printf("System GUID  : %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n",
521*c18ec02fSPetter Reinholdtsen 		       guid.time_low, guid.time_mid, guid.time_hi_and_version,
522*c18ec02fSPetter Reinholdtsen 		       guid.clock_seq_hi_variant << 8 | guid.clock_seq_low,
523*c18ec02fSPetter Reinholdtsen 		       guid.node[0], guid.node[1], guid.node[2],
524*c18ec02fSPetter Reinholdtsen 		       guid.node[3], guid.node[4], guid.node[5]);
525*c18ec02fSPetter Reinholdtsen 
526*c18ec02fSPetter Reinholdtsen 		s = (time_t)guid.time_low; /* Kipp - removed the BSWAP_32, it was not needed here */
527*c18ec02fSPetter Reinholdtsen 		strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s));
528*c18ec02fSPetter Reinholdtsen 		printf("Timestamp    : %s\n", tbuf);
529*c18ec02fSPetter Reinholdtsen 	}
530*c18ec02fSPetter Reinholdtsen 	else {
531*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid GUID length %d", rsp->data_len);
532*c18ec02fSPetter Reinholdtsen 	}
533*c18ec02fSPetter Reinholdtsen 
534*c18ec02fSPetter Reinholdtsen 	return 0;
535*c18ec02fSPetter Reinholdtsen }
536*c18ec02fSPetter Reinholdtsen 
537*c18ec02fSPetter Reinholdtsen /* ipmi_mc_get_selftest -  returns and print selftest results
538*c18ec02fSPetter Reinholdtsen  *
539*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
540*c18ec02fSPetter Reinholdtsen  */
541*c18ec02fSPetter Reinholdtsen static int ipmi_mc_get_selftest(struct ipmi_intf * intf)
542*c18ec02fSPetter Reinholdtsen {
543*c18ec02fSPetter Reinholdtsen    int rv = 0;
544*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
545*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
546*c18ec02fSPetter Reinholdtsen 	struct ipm_selftest_rsp *sft_res;
547*c18ec02fSPetter Reinholdtsen 
548*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
549*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
550*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = BMC_GET_SELF_TEST;
551*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 0;
552*c18ec02fSPetter Reinholdtsen 
553*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
554*c18ec02fSPetter Reinholdtsen 	if (!rsp) {
555*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "No response from devices\n");
556*c18ec02fSPetter Reinholdtsen 		return -1;
557*c18ec02fSPetter Reinholdtsen 	}
558*c18ec02fSPetter Reinholdtsen 
559*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode) {
560*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Bad response: (%s)",
561*c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
562*c18ec02fSPetter Reinholdtsen 		return -1;
563*c18ec02fSPetter Reinholdtsen 	}
564*c18ec02fSPetter Reinholdtsen 
565*c18ec02fSPetter Reinholdtsen 	sft_res = (struct ipm_selftest_rsp *) rsp->data;
566*c18ec02fSPetter Reinholdtsen 
567*c18ec02fSPetter Reinholdtsen 	if (sft_res->code == IPM_SFT_CODE_OK) {
568*c18ec02fSPetter Reinholdtsen 		printf("Selftest: passed\n");
569*c18ec02fSPetter Reinholdtsen 		rv = 0;
570*c18ec02fSPetter Reinholdtsen 	}
571*c18ec02fSPetter Reinholdtsen 
572*c18ec02fSPetter Reinholdtsen 	else if (sft_res->code == IPM_SFT_CODE_NOT_IMPLEMENTED) {
573*c18ec02fSPetter Reinholdtsen 		printf("Selftest: not implemented\n");
574*c18ec02fSPetter Reinholdtsen 		rv = -1;
575*c18ec02fSPetter Reinholdtsen 	}
576*c18ec02fSPetter Reinholdtsen 
577*c18ec02fSPetter Reinholdtsen 	else if (sft_res->code == IPM_SFT_CODE_DEV_CORRUPTED) {
578*c18ec02fSPetter Reinholdtsen 		printf("Selftest: device corrupted\n");
579*c18ec02fSPetter Reinholdtsen 		rv = -1;
580*c18ec02fSPetter Reinholdtsen 
581*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_SEL_ERROR) {
582*c18ec02fSPetter Reinholdtsen 			printf(" -> SEL device not accessible\n");
583*c18ec02fSPetter Reinholdtsen 		}
584*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_SDR_ERROR) {
585*c18ec02fSPetter Reinholdtsen 			printf(" -> SDR repository not accesible\n");
586*c18ec02fSPetter Reinholdtsen 		}
587*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_FRU_ERROR) {
588*c18ec02fSPetter Reinholdtsen 			printf("FRU device not accessible\n");
589*c18ec02fSPetter Reinholdtsen 		}
590*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_IPMB_ERROR) {
591*c18ec02fSPetter Reinholdtsen 			printf("IPMB signal lines do not respond\n");
592*c18ec02fSPetter Reinholdtsen 		}
593*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_SDRR_EMPTY) {
594*c18ec02fSPetter Reinholdtsen 			printf("SDR repository empty\n");
595*c18ec02fSPetter Reinholdtsen 		}
596*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_INTERNAL_USE) {
597*c18ec02fSPetter Reinholdtsen 			printf("Internal Use Area corrupted\n");
598*c18ec02fSPetter Reinholdtsen 		}
599*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_FW_BOOTBLOCK) {
600*c18ec02fSPetter Reinholdtsen 			printf("Controller update boot block corrupted\n");
601*c18ec02fSPetter Reinholdtsen 		}
602*c18ec02fSPetter Reinholdtsen 		if (sft_res->test & IPM_SELFTEST_FW_CORRUPTED) {
603*c18ec02fSPetter Reinholdtsen 			printf("controller operational firmware corrupted\n");
604*c18ec02fSPetter Reinholdtsen 		}
605*c18ec02fSPetter Reinholdtsen 	}
606*c18ec02fSPetter Reinholdtsen 
607*c18ec02fSPetter Reinholdtsen 	else if (sft_res->code == IPM_SFT_CODE_FATAL_ERROR) {
608*c18ec02fSPetter Reinholdtsen 		printf("Selftest     : fatal error\n");
609*c18ec02fSPetter Reinholdtsen 		printf("Failure code : %02x\n", sft_res->test);
610*c18ec02fSPetter Reinholdtsen 		rv = -1;
611*c18ec02fSPetter Reinholdtsen 	}
612*c18ec02fSPetter Reinholdtsen 
613*c18ec02fSPetter Reinholdtsen 	else if (sft_res->code == IPM_SFT_CODE_RESERVED) {
614*c18ec02fSPetter Reinholdtsen 		printf("Selftest: N/A");
615*c18ec02fSPetter Reinholdtsen 		rv = -1;
616*c18ec02fSPetter Reinholdtsen 	}
617*c18ec02fSPetter Reinholdtsen 
618*c18ec02fSPetter Reinholdtsen 	else {
619*c18ec02fSPetter Reinholdtsen 		printf("Selftest     : device specific (%02Xh)\n", sft_res->code);
620*c18ec02fSPetter Reinholdtsen 		printf("Failure code : %02Xh\n", sft_res->test);
621*c18ec02fSPetter Reinholdtsen 		rv = 0;
622*c18ec02fSPetter Reinholdtsen 	}
623*c18ec02fSPetter Reinholdtsen 
624*c18ec02fSPetter Reinholdtsen 	return rv;
625*c18ec02fSPetter Reinholdtsen }
626*c18ec02fSPetter Reinholdtsen 
627*c18ec02fSPetter Reinholdtsen /* ipmi_mc_get_watchdog
628*c18ec02fSPetter Reinholdtsen  *
629*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
630*c18ec02fSPetter Reinholdtsen  *
631*c18ec02fSPetter Reinholdtsen  * returns 0 on success
632*c18ec02fSPetter Reinholdtsen  * returns -1 on error
633*c18ec02fSPetter Reinholdtsen  */
634*c18ec02fSPetter Reinholdtsen 
635*c18ec02fSPetter Reinholdtsen const char *wdt_use_string[8] = {
636*c18ec02fSPetter Reinholdtsen 	"Reserved",
637*c18ec02fSPetter Reinholdtsen 	"BIOS FRB2",
638*c18ec02fSPetter Reinholdtsen 	"BIOS/POST",
639*c18ec02fSPetter Reinholdtsen 	"OS Load",
640*c18ec02fSPetter Reinholdtsen 	"SMS/OS",
641*c18ec02fSPetter Reinholdtsen 	"OEM",
642*c18ec02fSPetter Reinholdtsen 	"Reserved",
643*c18ec02fSPetter Reinholdtsen 	"Reserved"
644*c18ec02fSPetter Reinholdtsen };
645*c18ec02fSPetter Reinholdtsen 
646*c18ec02fSPetter Reinholdtsen const char *wdt_action_string[8] = {
647*c18ec02fSPetter Reinholdtsen 	"No action",
648*c18ec02fSPetter Reinholdtsen 	"Hard Reset",
649*c18ec02fSPetter Reinholdtsen 	"Power Down",
650*c18ec02fSPetter Reinholdtsen 	"Power Cycle",
651*c18ec02fSPetter Reinholdtsen 	"Reserved",
652*c18ec02fSPetter Reinholdtsen 	"Reserved",
653*c18ec02fSPetter Reinholdtsen 	"Reserved",
654*c18ec02fSPetter Reinholdtsen 	"Reserved"
655*c18ec02fSPetter Reinholdtsen };
656*c18ec02fSPetter Reinholdtsen 
657*c18ec02fSPetter Reinholdtsen static int
658*c18ec02fSPetter Reinholdtsen ipmi_mc_get_watchdog(struct ipmi_intf * intf)
659*c18ec02fSPetter Reinholdtsen {
660*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
661*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
662*c18ec02fSPetter Reinholdtsen 	struct ipm_get_watchdog_rsp * wdt_res;
663*c18ec02fSPetter Reinholdtsen 
664*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
665*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
666*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = BMC_GET_WATCHDOG_TIMER;
667*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 0;
668*c18ec02fSPetter Reinholdtsen 
669*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
670*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
671*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Watchdog Timer command failed");
672*c18ec02fSPetter Reinholdtsen 		return -1;
673*c18ec02fSPetter Reinholdtsen 	}
674*c18ec02fSPetter Reinholdtsen 
675*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode) {
676*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Get Watchdog Timer command failed: %s",
677*c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
678*c18ec02fSPetter Reinholdtsen 		return -1;
679*c18ec02fSPetter Reinholdtsen 	}
680*c18ec02fSPetter Reinholdtsen 
681*c18ec02fSPetter Reinholdtsen 	wdt_res = (struct ipm_get_watchdog_rsp *) rsp->data;
682*c18ec02fSPetter Reinholdtsen 
683*c18ec02fSPetter Reinholdtsen 	printf("Watchdog Timer Use:     %s (0x%02x)\n",
684*c18ec02fSPetter Reinholdtsen 			wdt_use_string[(wdt_res->timer_use & 0x07 )], wdt_res->timer_use);
685*c18ec02fSPetter Reinholdtsen 	printf("Watchdog Timer Is:      %s\n",
686*c18ec02fSPetter Reinholdtsen 		wdt_res->timer_use & 0x40 ? "Started/Running" : "Stopped");
687*c18ec02fSPetter Reinholdtsen 	printf("Watchdog Timer Actions: %s (0x%02x)\n",
688*c18ec02fSPetter Reinholdtsen 		 wdt_action_string[(wdt_res->timer_actions&0x07)], wdt_res->timer_actions);
689*c18ec02fSPetter Reinholdtsen 	printf("Pre-timeout interval:   %d seconds\n", wdt_res->pre_timeout);
690*c18ec02fSPetter Reinholdtsen 	printf("Timer Expiration Flags: 0x%02x\n", wdt_res->timer_use_exp);
691*c18ec02fSPetter Reinholdtsen 	printf("Initial Countdown:      %i sec\n",
692*c18ec02fSPetter Reinholdtsen 			((wdt_res->initial_countdown_msb << 8) | wdt_res->initial_countdown_lsb)/10);
693*c18ec02fSPetter Reinholdtsen 	printf("Present Countdown:      %i sec\n",
694*c18ec02fSPetter Reinholdtsen 			(((wdt_res->present_countdown_msb << 8) | wdt_res->present_countdown_lsb)) / 10);
695*c18ec02fSPetter Reinholdtsen 
696*c18ec02fSPetter Reinholdtsen 	return 0;
697*c18ec02fSPetter Reinholdtsen }
698*c18ec02fSPetter Reinholdtsen 
699*c18ec02fSPetter Reinholdtsen /* ipmi_mc_shutoff_watchdog
700*c18ec02fSPetter Reinholdtsen  *
701*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
702*c18ec02fSPetter Reinholdtsen  *
703*c18ec02fSPetter Reinholdtsen  * returns 0 on success
704*c18ec02fSPetter Reinholdtsen  * returns -1 on error
705*c18ec02fSPetter Reinholdtsen  */
706*c18ec02fSPetter Reinholdtsen static int
707*c18ec02fSPetter Reinholdtsen ipmi_mc_shutoff_watchdog(struct ipmi_intf * intf)
708*c18ec02fSPetter Reinholdtsen {
709*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
710*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
711*c18ec02fSPetter Reinholdtsen 	unsigned char msg_data[6];
712*c18ec02fSPetter Reinholdtsen 
713*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
714*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
715*c18ec02fSPetter Reinholdtsen 	req.msg.cmd   = BMC_SET_WATCHDOG_TIMER;
716*c18ec02fSPetter Reinholdtsen 	req.msg.data  = msg_data;
717*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 6;
718*c18ec02fSPetter Reinholdtsen 
719*c18ec02fSPetter Reinholdtsen 	/*
720*c18ec02fSPetter Reinholdtsen 	 * The only set cmd we're allowing is to shut off the timer.
721*c18ec02fSPetter Reinholdtsen 	 * Turning on the timer should be the job of the ipmi watchdog driver.
722*c18ec02fSPetter Reinholdtsen 	 * See 'modinfo ipmi_watchdog' for more info. (NOTE: the reset
723*c18ec02fSPetter Reinholdtsen 	 * command will restart the timer if it's already been initialized.)
724*c18ec02fSPetter Reinholdtsen 	 *
725*c18ec02fSPetter Reinholdtsen 	 * Out-of-band watchdog set commands can still be sent via the raw
726*c18ec02fSPetter Reinholdtsen 	 * command interface but this is a very dangerous thing to do since
727*c18ec02fSPetter Reinholdtsen 	 * a periodic "poke"/reset over a network is unreliable.  This is
728*c18ec02fSPetter Reinholdtsen 	 * not a recommended way to use the IPMI watchdog commands.
729*c18ec02fSPetter Reinholdtsen 	 */
730*c18ec02fSPetter Reinholdtsen 
731*c18ec02fSPetter Reinholdtsen 	msg_data[0] = IPM_WATCHDOG_SMS_OS;
732*c18ec02fSPetter Reinholdtsen 	msg_data[1] = IPM_WATCHDOG_NO_ACTION;
733*c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x00;  /* pretimeout interval */
734*c18ec02fSPetter Reinholdtsen 	msg_data[3] = IPM_WATCHDOG_CLEAR_SMS_OS;
735*c18ec02fSPetter Reinholdtsen 	msg_data[4] = 0xb8;  /* countdown lsb (100 ms/count) */
736*c18ec02fSPetter Reinholdtsen 	msg_data[5] = 0x0b;  /* countdown msb - 5 mins */
737*c18ec02fSPetter Reinholdtsen 
738*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
739*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
740*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Watchdog Timer Shutoff command failed!");
741*c18ec02fSPetter Reinholdtsen 		return -1;
742*c18ec02fSPetter Reinholdtsen 	}
743*c18ec02fSPetter Reinholdtsen 
744*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode) {
745*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Watchdog Timer Shutoff command failed! %s",
746*c18ec02fSPetter Reinholdtsen 			val2str(rsp->ccode, completion_code_vals));
747*c18ec02fSPetter Reinholdtsen 		return -1;
748*c18ec02fSPetter Reinholdtsen 	}
749*c18ec02fSPetter Reinholdtsen 
750*c18ec02fSPetter Reinholdtsen 	printf("Watchdog Timer Shutoff successful -- timer stopped\n");
751*c18ec02fSPetter Reinholdtsen 	return 0;
752*c18ec02fSPetter Reinholdtsen }
753*c18ec02fSPetter Reinholdtsen 
754*c18ec02fSPetter Reinholdtsen 
755*c18ec02fSPetter Reinholdtsen /* ipmi_mc_rst_watchdog
756*c18ec02fSPetter Reinholdtsen  *
757*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
758*c18ec02fSPetter Reinholdtsen  *
759*c18ec02fSPetter Reinholdtsen  * returns 0 on success
760*c18ec02fSPetter Reinholdtsen  * returns -1 on error
761*c18ec02fSPetter Reinholdtsen  */
762*c18ec02fSPetter Reinholdtsen static int
763*c18ec02fSPetter Reinholdtsen ipmi_mc_rst_watchdog(struct ipmi_intf * intf)
764*c18ec02fSPetter Reinholdtsen {
765*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
766*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
767*c18ec02fSPetter Reinholdtsen 
768*c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
769*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
770*c18ec02fSPetter Reinholdtsen 	req.msg.cmd   = BMC_RESET_WATCHDOG_TIMER;
771*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 0;
772*c18ec02fSPetter Reinholdtsen 
773*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
774*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
775*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Reset Watchdog Timer command failed!");
776*c18ec02fSPetter Reinholdtsen 		return -1;
777*c18ec02fSPetter Reinholdtsen 	}
778*c18ec02fSPetter Reinholdtsen 
779*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode) {
780*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Reset Watchdog Timer command failed: %s",
781*c18ec02fSPetter Reinholdtsen 			(rsp->ccode == IPM_WATCHDOG_RESET_ERROR) ?
782*c18ec02fSPetter Reinholdtsen 				"Attempt to reset unitialized watchdog" :
783*c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
784*c18ec02fSPetter Reinholdtsen 		return -1;
785*c18ec02fSPetter Reinholdtsen 	}
786*c18ec02fSPetter Reinholdtsen 
787*c18ec02fSPetter Reinholdtsen 	printf("IPMI Watchdog Timer Reset -  countdown restarted!\n");
788*c18ec02fSPetter Reinholdtsen 	return 0;
789*c18ec02fSPetter Reinholdtsen }
790*c18ec02fSPetter Reinholdtsen 
791*c18ec02fSPetter Reinholdtsen /* ipmi_mc_main  -  top-level handler for MC functions
792*c18ec02fSPetter Reinholdtsen  *
793*c18ec02fSPetter Reinholdtsen  * @intf:	ipmi interface
794*c18ec02fSPetter Reinholdtsen  * @argc:	number of arguments
795*c18ec02fSPetter Reinholdtsen  * @argv:	argument list
796*c18ec02fSPetter Reinholdtsen  *
797*c18ec02fSPetter Reinholdtsen  * returns 0 on success
798*c18ec02fSPetter Reinholdtsen  * returns -1 on error
799*c18ec02fSPetter Reinholdtsen  */
800*c18ec02fSPetter Reinholdtsen int
801*c18ec02fSPetter Reinholdtsen ipmi_mc_main(struct ipmi_intf * intf, int argc, char ** argv)
802*c18ec02fSPetter Reinholdtsen {
803*c18ec02fSPetter Reinholdtsen 	int rc = 0;
804*c18ec02fSPetter Reinholdtsen 
805*c18ec02fSPetter Reinholdtsen 	if (argc < 1) {
806*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Not enough parameters given.");
807*c18ec02fSPetter Reinholdtsen 		printf_mc_usage();
808*c18ec02fSPetter Reinholdtsen 		rc = (-1);
809*c18ec02fSPetter Reinholdtsen 	}
810*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "help", 4) == 0) {
811*c18ec02fSPetter Reinholdtsen 		printf_mc_usage();
812*c18ec02fSPetter Reinholdtsen 		rc = 0;
813*c18ec02fSPetter Reinholdtsen 	}
814*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "reset", 5) == 0) {
815*c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
816*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Not enough parameters given.");
817*c18ec02fSPetter Reinholdtsen 			printf_mc_reset_usage();
818*c18ec02fSPetter Reinholdtsen 			rc = (-1);
819*c18ec02fSPetter Reinholdtsen 		}
820*c18ec02fSPetter Reinholdtsen 		else if (strncmp(argv[1], "help", 4) == 0) {
821*c18ec02fSPetter Reinholdtsen 			printf_mc_reset_usage();
822*c18ec02fSPetter Reinholdtsen 			rc = 0;
823*c18ec02fSPetter Reinholdtsen 		}
824*c18ec02fSPetter Reinholdtsen 		else if (strncmp(argv[1], "cold", 4) == 0) {
825*c18ec02fSPetter Reinholdtsen 			rc = ipmi_mc_reset(intf, BMC_COLD_RESET);
826*c18ec02fSPetter Reinholdtsen 		}
827*c18ec02fSPetter Reinholdtsen 		else if (strncmp(argv[1], "warm", 4) == 0) {
828*c18ec02fSPetter Reinholdtsen 			rc = ipmi_mc_reset(intf, BMC_WARM_RESET);
829*c18ec02fSPetter Reinholdtsen 		}
830*c18ec02fSPetter Reinholdtsen 		else {
831*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid mc/bmc %s command: %s", argv[0], argv[1]);
832*c18ec02fSPetter Reinholdtsen 			printf_mc_reset_usage();
833*c18ec02fSPetter Reinholdtsen 			rc = (-1);
834*c18ec02fSPetter Reinholdtsen 		}
835*c18ec02fSPetter Reinholdtsen 	}
836*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "info", 4) == 0) {
837*c18ec02fSPetter Reinholdtsen 		rc = ipmi_mc_get_deviceid(intf);
838*c18ec02fSPetter Reinholdtsen 	}
839*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "guid", 4) == 0) {
840*c18ec02fSPetter Reinholdtsen 		rc = ipmi_mc_get_guid(intf);
841*c18ec02fSPetter Reinholdtsen 	}
842*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "getenables", 10) == 0) {
843*c18ec02fSPetter Reinholdtsen 		rc = ipmi_mc_get_enables(intf);
844*c18ec02fSPetter Reinholdtsen 	}
845*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "setenables", 10) == 0) {
846*c18ec02fSPetter Reinholdtsen 		rc = ipmi_mc_set_enables(intf, argc-1, &(argv[1]));
847*c18ec02fSPetter Reinholdtsen 	}
848*c18ec02fSPetter Reinholdtsen 	else if (!strncmp(argv[0], "selftest", 8)) {
849*c18ec02fSPetter Reinholdtsen 		rc = ipmi_mc_get_selftest(intf);
850*c18ec02fSPetter Reinholdtsen 	}
851*c18ec02fSPetter Reinholdtsen 	else if (!strncmp(argv[0], "watchdog", 8)) {
852*c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
853*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Not enough parameters given.");
854*c18ec02fSPetter Reinholdtsen 			print_watchdog_usage();
855*c18ec02fSPetter Reinholdtsen 			rc = (-1);
856*c18ec02fSPetter Reinholdtsen 		}
857*c18ec02fSPetter Reinholdtsen 		else if (strncmp(argv[1], "help", 4) == 0) {
858*c18ec02fSPetter Reinholdtsen 			print_watchdog_usage();
859*c18ec02fSPetter Reinholdtsen 			rc = 0;
860*c18ec02fSPetter Reinholdtsen 		}
861*c18ec02fSPetter Reinholdtsen 		else if (strncmp(argv[1], "get", 3) == 0) {
862*c18ec02fSPetter Reinholdtsen 			rc = ipmi_mc_get_watchdog(intf);
863*c18ec02fSPetter Reinholdtsen 		}
864*c18ec02fSPetter Reinholdtsen 		else if(strncmp(argv[1], "off", 3) == 0) {
865*c18ec02fSPetter Reinholdtsen 			rc = ipmi_mc_shutoff_watchdog(intf);
866*c18ec02fSPetter Reinholdtsen 		}
867*c18ec02fSPetter Reinholdtsen 		else if(strncmp(argv[1], "reset", 5) == 0) {
868*c18ec02fSPetter Reinholdtsen 			rc = ipmi_mc_rst_watchdog(intf);
869*c18ec02fSPetter Reinholdtsen 		}
870*c18ec02fSPetter Reinholdtsen 		else {
871*c18ec02fSPetter Reinholdtsen 			lprintf(LOG_ERR, "Invalid mc/bmc %s command: %s", argv[0], argv[1]);
872*c18ec02fSPetter Reinholdtsen 			print_watchdog_usage();
873*c18ec02fSPetter Reinholdtsen 			rc = (-1);
874*c18ec02fSPetter Reinholdtsen 		}
875*c18ec02fSPetter Reinholdtsen 	}
876*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "getsysinfo", 10) == 0) {
877*c18ec02fSPetter Reinholdtsen 		rc = ipmi_sysinfo_main(intf, argc, argv, 0);
878*c18ec02fSPetter Reinholdtsen 	}
879*c18ec02fSPetter Reinholdtsen 	else if (strncmp(argv[0], "setsysinfo", 10) == 0) {
880*c18ec02fSPetter Reinholdtsen 		rc = ipmi_sysinfo_main(intf, argc, argv, 1);
881*c18ec02fSPetter Reinholdtsen 	}
882*c18ec02fSPetter Reinholdtsen 	else {
883*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid mc/bmc command: %s", argv[0]);
884*c18ec02fSPetter Reinholdtsen 		printf_mc_usage();
885*c18ec02fSPetter Reinholdtsen 		rc = (-1);
886*c18ec02fSPetter Reinholdtsen 	}
887*c18ec02fSPetter Reinholdtsen 	return rc;
888*c18ec02fSPetter Reinholdtsen }
889*c18ec02fSPetter Reinholdtsen 
890*c18ec02fSPetter Reinholdtsen /*
891*c18ec02fSPetter Reinholdtsen  * sysinfo_param() - function converts sysinfo param to int
892*c18ec02fSPetter Reinholdtsen  *
893*c18ec02fSPetter Reinholdtsen  * @str - user input string
894*c18ec02fSPetter Reinholdtsen  * @maxset - ?
895*c18ec02fSPetter Reinholdtsen  *
896*c18ec02fSPetter Reinholdtsen  * returns (-1) on error
897*c18ec02fSPetter Reinholdtsen  * returns > 0  on success
898*c18ec02fSPetter Reinholdtsen  */
899*c18ec02fSPetter Reinholdtsen static int
900*c18ec02fSPetter Reinholdtsen sysinfo_param(const char *str, int *maxset)
901*c18ec02fSPetter Reinholdtsen {
902*c18ec02fSPetter Reinholdtsen 	if (!str || !maxset)
903*c18ec02fSPetter Reinholdtsen 		return (-1);
904*c18ec02fSPetter Reinholdtsen 
905*c18ec02fSPetter Reinholdtsen 	*maxset = 4;
906*c18ec02fSPetter Reinholdtsen 	if (!strcmp(str, "system_name"))
907*c18ec02fSPetter Reinholdtsen 		return IPMI_SYSINFO_HOSTNAME;
908*c18ec02fSPetter Reinholdtsen 	else if (!strcmp(str, "primary_os_name"))
909*c18ec02fSPetter Reinholdtsen 		return IPMI_SYSINFO_PRIMARY_OS_NAME;
910*c18ec02fSPetter Reinholdtsen 	else if (!strcmp(str, "os_name"))
911*c18ec02fSPetter Reinholdtsen 		return IPMI_SYSINFO_OS_NAME;
912*c18ec02fSPetter Reinholdtsen 	else if (!strcmp(str, "delloem_os_version"))
913*c18ec02fSPetter Reinholdtsen 		return IPMI_SYSINFO_DELL_OS_VERSION;
914*c18ec02fSPetter Reinholdtsen 	else if (!strcmp(str, "delloem_url")) {
915*c18ec02fSPetter Reinholdtsen 		*maxset = 2;
916*c18ec02fSPetter Reinholdtsen 		return IPMI_SYSINFO_DELL_URL;
917*c18ec02fSPetter Reinholdtsen 	}
918*c18ec02fSPetter Reinholdtsen 
919*c18ec02fSPetter Reinholdtsen 	return (-1);
920*c18ec02fSPetter Reinholdtsen }
921*c18ec02fSPetter Reinholdtsen 
922*c18ec02fSPetter Reinholdtsen /*
923*c18ec02fSPetter Reinholdtsen  * ipmi_mc_getsysinfo() - function processes the IPMI Get System Info command
924*c18ec02fSPetter Reinholdtsen  *
925*c18ec02fSPetter Reinholdtsen  * @intf - ipmi interface
926*c18ec02fSPetter Reinholdtsen  * @param - parameter eg. 0xC0..0xFF = OEM
927*c18ec02fSPetter Reinholdtsen  * @block - number of block parameters
928*c18ec02fSPetter Reinholdtsen  * @set - number of set parameters
929*c18ec02fSPetter Reinholdtsen  * @len - length of buffer
930*c18ec02fSPetter Reinholdtsen  * @buffer - pointer to buffer
931*c18ec02fSPetter Reinholdtsen  *
932*c18ec02fSPetter Reinholdtsen  * returns (-1) on failure
933*c18ec02fSPetter Reinholdtsen  * returns   0  on success
934*c18ec02fSPetter Reinholdtsen  * returns > 0  IPMI code
935*c18ec02fSPetter Reinholdtsen  */
936*c18ec02fSPetter Reinholdtsen int
937*c18ec02fSPetter Reinholdtsen ipmi_mc_getsysinfo(struct ipmi_intf * intf, int param, int block, int set,
938*c18ec02fSPetter Reinholdtsen 		int len, void *buffer)
939*c18ec02fSPetter Reinholdtsen {
940*c18ec02fSPetter Reinholdtsen 	uint8_t data[4];
941*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp = NULL;
942*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req = {0};
943*c18ec02fSPetter Reinholdtsen 
944*c18ec02fSPetter Reinholdtsen 	memset(buffer, 0, len);
945*c18ec02fSPetter Reinholdtsen 	memset(data, 0, 4);
946*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
947*c18ec02fSPetter Reinholdtsen 	req.msg.lun = 0;
948*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_GET_SYS_INFO;
949*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4;
950*c18ec02fSPetter Reinholdtsen 	req.msg.data = data;
951*c18ec02fSPetter Reinholdtsen 
952*c18ec02fSPetter Reinholdtsen 	if (verbose > 1)
953*c18ec02fSPetter Reinholdtsen 		printf("getsysinfo: %.2x/%.2x/%.2x\n", param, block, set);
954*c18ec02fSPetter Reinholdtsen 
955*c18ec02fSPetter Reinholdtsen 	data[0] = 0; /* get/set */
956*c18ec02fSPetter Reinholdtsen 	data[1] = param;
957*c18ec02fSPetter Reinholdtsen 	data[2] = block;
958*c18ec02fSPetter Reinholdtsen 	data[3] = set;
959*c18ec02fSPetter Reinholdtsen 
960*c18ec02fSPetter Reinholdtsen 	/*
961*c18ec02fSPetter Reinholdtsen 	 * Format of get output is:
962*c18ec02fSPetter Reinholdtsen 	 *   u8 param_rev
963*c18ec02fSPetter Reinholdtsen 	 *   u8 selector
964*c18ec02fSPetter Reinholdtsen 	 *   u8 encoding  bit[0-3];
965*c18ec02fSPetter Reinholdtsen 	 *   u8 length
966*c18ec02fSPetter Reinholdtsen 	 *   u8 data0[14]
967*c18ec02fSPetter Reinholdtsen 	 */
968*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
969*c18ec02fSPetter Reinholdtsen 	if (rsp == NULL)
970*c18ec02fSPetter Reinholdtsen 		return (-1);
971*c18ec02fSPetter Reinholdtsen 
972*c18ec02fSPetter Reinholdtsen 	if (rsp->ccode == 0) {
973*c18ec02fSPetter Reinholdtsen 		if (len > rsp->data_len)
974*c18ec02fSPetter Reinholdtsen 			len = rsp->data_len;
975*c18ec02fSPetter Reinholdtsen 		if (len && buffer)
976*c18ec02fSPetter Reinholdtsen 			memcpy(buffer, rsp->data, len);
977*c18ec02fSPetter Reinholdtsen 	}
978*c18ec02fSPetter Reinholdtsen 	return rsp->ccode;
979*c18ec02fSPetter Reinholdtsen }
980*c18ec02fSPetter Reinholdtsen 
981*c18ec02fSPetter Reinholdtsen /*
982*c18ec02fSPetter Reinholdtsen  * ipmi_mc_setsysinfo() - function processes the IPMI Set System Info command
983*c18ec02fSPetter Reinholdtsen  *
984*c18ec02fSPetter Reinholdtsen  * @intf - ipmi interface
985*c18ec02fSPetter Reinholdtsen  * @len - length of buffer
986*c18ec02fSPetter Reinholdtsen  * @buffer - pointer to buffer
987*c18ec02fSPetter Reinholdtsen  *
988*c18ec02fSPetter Reinholdtsen  * returns (-1) on failure
989*c18ec02fSPetter Reinholdtsen  * returns   0  on success
990*c18ec02fSPetter Reinholdtsen  * returns > 0  IPMI code
991*c18ec02fSPetter Reinholdtsen  */
992*c18ec02fSPetter Reinholdtsen int
993*c18ec02fSPetter Reinholdtsen ipmi_mc_setsysinfo(struct ipmi_intf * intf, int len, void *buffer)
994*c18ec02fSPetter Reinholdtsen {
995*c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp = NULL;
996*c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req = {0};
997*c18ec02fSPetter Reinholdtsen 
998*c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_APP;
999*c18ec02fSPetter Reinholdtsen 	req.msg.lun = 0;
1000*c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_SET_SYS_INFO;
1001*c18ec02fSPetter Reinholdtsen 	req.msg.data_len = len;
1002*c18ec02fSPetter Reinholdtsen 	req.msg.data = buffer;
1003*c18ec02fSPetter Reinholdtsen 
1004*c18ec02fSPetter Reinholdtsen 	/*
1005*c18ec02fSPetter Reinholdtsen 	 * Format of set input:
1006*c18ec02fSPetter Reinholdtsen 	 *   u8 param rev
1007*c18ec02fSPetter Reinholdtsen 	 *   u8 selector
1008*c18ec02fSPetter Reinholdtsen 	 *   u8 data1[16]
1009*c18ec02fSPetter Reinholdtsen 	 */
1010*c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
1011*c18ec02fSPetter Reinholdtsen 	if (rsp != NULL) {
1012*c18ec02fSPetter Reinholdtsen 		return rsp->ccode;
1013*c18ec02fSPetter Reinholdtsen 	}
1014*c18ec02fSPetter Reinholdtsen 	return -1;
1015*c18ec02fSPetter Reinholdtsen }
1016*c18ec02fSPetter Reinholdtsen 
1017*c18ec02fSPetter Reinholdtsen static int
1018*c18ec02fSPetter Reinholdtsen ipmi_sysinfo_main(struct ipmi_intf *intf, int argc, char ** argv, int is_set)
1019*c18ec02fSPetter Reinholdtsen {
1020*c18ec02fSPetter Reinholdtsen 	char *str;
1021*c18ec02fSPetter Reinholdtsen 	unsigned char  infostr[256];
1022*c18ec02fSPetter Reinholdtsen 	unsigned char  paramdata[18];
1023*c18ec02fSPetter Reinholdtsen 	int len, maxset, param, pos, rc, set;
1024*c18ec02fSPetter Reinholdtsen 
1025*c18ec02fSPetter Reinholdtsen 	if (argc == 2 && strcmp(argv[1], "help") == 0) {
1026*c18ec02fSPetter Reinholdtsen 		printf_sysinfo_usage(1);
1027*c18ec02fSPetter Reinholdtsen 		return 0;
1028*c18ec02fSPetter Reinholdtsen 	}
1029*c18ec02fSPetter Reinholdtsen 	else if (argc < 2 || (is_set == 1 && argc < 3)) {
1030*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Not enough parameters given.");
1031*c18ec02fSPetter Reinholdtsen 		printf_sysinfo_usage(1);
1032*c18ec02fSPetter Reinholdtsen 		return (-1);
1033*c18ec02fSPetter Reinholdtsen 	}
1034*c18ec02fSPetter Reinholdtsen 
1035*c18ec02fSPetter Reinholdtsen 	/* Get Parameters */
1036*c18ec02fSPetter Reinholdtsen 	if ((param = sysinfo_param(argv[1], &maxset)) < 0) {
1037*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid mc/bmc %s command: %s", argv[0], argv[1]);
1038*c18ec02fSPetter Reinholdtsen 		printf_sysinfo_usage(1);
1039*c18ec02fSPetter Reinholdtsen 		return (-1);
1040*c18ec02fSPetter Reinholdtsen 	}
1041*c18ec02fSPetter Reinholdtsen 
1042*c18ec02fSPetter Reinholdtsen 	rc = 0;
1043*c18ec02fSPetter Reinholdtsen 	if (is_set != 0) {
1044*c18ec02fSPetter Reinholdtsen 		str = argv[2];
1045*c18ec02fSPetter Reinholdtsen 		set = pos = 0;
1046*c18ec02fSPetter Reinholdtsen 		len = strlen(str);
1047*c18ec02fSPetter Reinholdtsen 
1048*c18ec02fSPetter Reinholdtsen 		/* first block holds 14 bytes, all others hold 16 */
1049*c18ec02fSPetter Reinholdtsen 		if ((len + 2 + 15) / 16 >= maxset)
1050*c18ec02fSPetter Reinholdtsen 			len = (maxset * 16) - 2;
1051*c18ec02fSPetter Reinholdtsen 
1052*c18ec02fSPetter Reinholdtsen 		do {
1053*c18ec02fSPetter Reinholdtsen 			memset(paramdata, 0, sizeof(paramdata));
1054*c18ec02fSPetter Reinholdtsen 			paramdata[0] = param;
1055*c18ec02fSPetter Reinholdtsen 			paramdata[1] = set;
1056*c18ec02fSPetter Reinholdtsen 			if (set == 0) {
1057*c18ec02fSPetter Reinholdtsen 				/* First block is special case */
1058*c18ec02fSPetter Reinholdtsen 				paramdata[2] = 0;   /* ascii encoding */
1059*c18ec02fSPetter Reinholdtsen 				paramdata[3] = len; /* length */
1060*c18ec02fSPetter Reinholdtsen 				strncpy(paramdata + 4, str + pos, IPMI_SYSINFO_SET0_SIZE);
1061*c18ec02fSPetter Reinholdtsen 				pos += IPMI_SYSINFO_SET0_SIZE;
1062*c18ec02fSPetter Reinholdtsen 			}
1063*c18ec02fSPetter Reinholdtsen 			else {
1064*c18ec02fSPetter Reinholdtsen 				strncpy(paramdata + 2, str + pos, IPMI_SYSINFO_SETN_SIZE);
1065*c18ec02fSPetter Reinholdtsen 				pos += IPMI_SYSINFO_SETN_SIZE;
1066*c18ec02fSPetter Reinholdtsen 			}
1067*c18ec02fSPetter Reinholdtsen 			rc = ipmi_mc_setsysinfo(intf, 18, paramdata);
1068*c18ec02fSPetter Reinholdtsen 
1069*c18ec02fSPetter Reinholdtsen 			if (rc)
1070*c18ec02fSPetter Reinholdtsen 				break;
1071*c18ec02fSPetter Reinholdtsen 
1072*c18ec02fSPetter Reinholdtsen 			set++;
1073*c18ec02fSPetter Reinholdtsen 		} while (pos < len);
1074*c18ec02fSPetter Reinholdtsen 	}
1075*c18ec02fSPetter Reinholdtsen 	else {
1076*c18ec02fSPetter Reinholdtsen 		memset(infostr, 0, sizeof(infostr));
1077*c18ec02fSPetter Reinholdtsen 		/* Read blocks of data */
1078*c18ec02fSPetter Reinholdtsen 		pos = 0;
1079*c18ec02fSPetter Reinholdtsen 		for (set = 0; set < maxset; set++) {
1080*c18ec02fSPetter Reinholdtsen 			rc = ipmi_mc_getsysinfo(intf, param, set, 0, 18, paramdata);
1081*c18ec02fSPetter Reinholdtsen 
1082*c18ec02fSPetter Reinholdtsen 			if (rc)
1083*c18ec02fSPetter Reinholdtsen 				break;
1084*c18ec02fSPetter Reinholdtsen 
1085*c18ec02fSPetter Reinholdtsen 			if (set == 0) {
1086*c18ec02fSPetter Reinholdtsen 				/* First block is special case */
1087*c18ec02fSPetter Reinholdtsen 				if ((paramdata[2] & 0xF) == 0) {
1088*c18ec02fSPetter Reinholdtsen 					/* Determine max number of blocks to read */
1089*c18ec02fSPetter Reinholdtsen 					maxset = ((paramdata[3] + 2) + 15) / 16;
1090*c18ec02fSPetter Reinholdtsen 				}
1091*c18ec02fSPetter Reinholdtsen 				memcpy(infostr + pos, paramdata + 4, IPMI_SYSINFO_SET0_SIZE);
1092*c18ec02fSPetter Reinholdtsen 				pos += IPMI_SYSINFO_SET0_SIZE;
1093*c18ec02fSPetter Reinholdtsen 			}
1094*c18ec02fSPetter Reinholdtsen 			else {
1095*c18ec02fSPetter Reinholdtsen 				memcpy(infostr + pos, paramdata + 2, IPMI_SYSINFO_SETN_SIZE);
1096*c18ec02fSPetter Reinholdtsen 				pos += IPMI_SYSINFO_SETN_SIZE;
1097*c18ec02fSPetter Reinholdtsen 			}
1098*c18ec02fSPetter Reinholdtsen 		}
1099*c18ec02fSPetter Reinholdtsen 		printf("%s\n", infostr);
1100*c18ec02fSPetter Reinholdtsen 	}
1101*c18ec02fSPetter Reinholdtsen 	if (rc < 0) {
1102*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "%s %s set %d command failed", argv[0], argv[1], set);
1103*c18ec02fSPetter Reinholdtsen 	}
1104*c18ec02fSPetter Reinholdtsen 	else if (rc == 0x80) {
1105*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "%s %s parameter not supported", argv[0], argv[1]);
1106*c18ec02fSPetter Reinholdtsen 	}
1107*c18ec02fSPetter Reinholdtsen 	else if (rc > 0) {
1108*c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "%s command failed: %s", argv[0],
1109*c18ec02fSPetter Reinholdtsen 				val2str(rc, completion_code_vals));
1110*c18ec02fSPetter Reinholdtsen 	}
1111*c18ec02fSPetter Reinholdtsen 	return rc;
1112*c18ec02fSPetter Reinholdtsen }
1113