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