xref: /openbmc/ipmitool/lib/ipmi_kontronoem.c (revision 58837647)
1c18ec02fSPetter Reinholdtsen /*
2c18ec02fSPetter Reinholdtsen  * Copyright (c) 2004 Kontron Canada, Inc.  All Rights Reserved.
3c18ec02fSPetter Reinholdtsen  *
4c18ec02fSPetter Reinholdtsen  * Base on code from
5c18ec02fSPetter Reinholdtsen  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
6c18ec02fSPetter Reinholdtsen  *
7c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
8c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
9c18ec02fSPetter Reinholdtsen  * are met:
10c18ec02fSPetter Reinholdtsen  *
11c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
12c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
13c18ec02fSPetter Reinholdtsen  *
14c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
15c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
16c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
17c18ec02fSPetter Reinholdtsen  *
18c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
19c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
20c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
21c18ec02fSPetter Reinholdtsen  *
22c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
23c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
24c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
25c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
26c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
27c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
28c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
29c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
30c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
31c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
32c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
33c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34c18ec02fSPetter Reinholdtsen  */
35c18ec02fSPetter Reinholdtsen 
36c18ec02fSPetter Reinholdtsen /*
37c18ec02fSPetter Reinholdtsen  * Tue Mar 7 14:36:12 2006
38c18ec02fSPetter Reinholdtsen  * <stephane.filion@ca.kontron.com>
39c18ec02fSPetter Reinholdtsen  *
40c18ec02fSPetter Reinholdtsen  * This code implements an Kontron OEM proprietary commands.
41c18ec02fSPetter Reinholdtsen  */
42c18ec02fSPetter Reinholdtsen #include <string.h>
43c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
44*58837647SZdenek Styblik #include <ipmitool/log.h>
45c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
46c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
47c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_fru.h>
48c18ec02fSPetter Reinholdtsen 
49c18ec02fSPetter Reinholdtsen extern int verbose;
50c18ec02fSPetter Reinholdtsen extern int read_fru_area(struct ipmi_intf *intf, struct fru_info *fru,
51c18ec02fSPetter Reinholdtsen 		uint8_t id, uint32_t offset, uint32_t length,
52c18ec02fSPetter Reinholdtsen 		uint8_t *frubuf);
53c18ec02fSPetter Reinholdtsen extern int write_fru_area(struct ipmi_intf * intf, struct fru_info *fru,
547560d4f2SZdenek Styblik 		uint8_t id, uint16_t soffset,
557560d4f2SZdenek Styblik 		uint16_t doffset,  uint16_t length,
567560d4f2SZdenek Styblik 		uint8_t *pFrubuf);
57c18ec02fSPetter Reinholdtsen extern char *get_fru_area_str(uint8_t *data, uint32_t *offset);
58c18ec02fSPetter Reinholdtsen 
59c18ec02fSPetter Reinholdtsen static void ipmi_kontron_help(void);
60c18ec02fSPetter Reinholdtsen static int ipmi_kontron_set_serial_number(struct ipmi_intf *intf);
61c18ec02fSPetter Reinholdtsen static int ipmi_kontron_set_mfg_date (struct ipmi_intf *intf);
62c18ec02fSPetter Reinholdtsen static void ipmi_kontron_nextboot_help(void);
63*58837647SZdenek Styblik static int ipmi_kontron_nextboot_set(struct ipmi_intf *intf, int argc,
64*58837647SZdenek Styblik 		char **argv);
65c18ec02fSPetter Reinholdtsen static int ipmi_kontronoem_send_set_large_buffer(struct ipmi_intf *intf,
66*58837647SZdenek Styblik 		unsigned char channel, unsigned char size);
67*58837647SZdenek Styblik 
68*58837647SZdenek Styblik static char *bootdev[] = {"BIOS", "FDD", "HDD", "CDROM", "network", 0};
69c18ec02fSPetter Reinholdtsen 
70c18ec02fSPetter Reinholdtsen int
71c18ec02fSPetter Reinholdtsen ipmi_kontronoem_main(struct ipmi_intf *intf, int argc, char **argv)
72c18ec02fSPetter Reinholdtsen {
73c18ec02fSPetter Reinholdtsen 	int rc = 0;
74*58837647SZdenek Styblik 	if (argc == 0) {
75*58837647SZdenek Styblik 		lprintf(LOG_ERR, "Not enough parameters given.");
76c18ec02fSPetter Reinholdtsen 		ipmi_kontron_help();
77*58837647SZdenek Styblik 		return (-1);
78*58837647SZdenek Styblik 	}
79*58837647SZdenek Styblik 	if (strncmp(argv[0], "help", 4) == 0) {
80c18ec02fSPetter Reinholdtsen 		ipmi_kontron_help();
81*58837647SZdenek Styblik 		rc = 0;
82*58837647SZdenek Styblik 	} else if (!strncmp(argv[0], "setsn", 5)) {
83*58837647SZdenek Styblik 		if (argc < 1) {
84c18ec02fSPetter Reinholdtsen 			printf("fru setsn\n");
85*58837647SZdenek Styblik 			return (-1);
86c18ec02fSPetter Reinholdtsen 		}
87*58837647SZdenek Styblik 		if (ipmi_kontron_set_serial_number(intf) > 0) {
88*58837647SZdenek Styblik 			printf("FRU serial number setted successfully\n");
89*58837647SZdenek Styblik 		} else {
90*58837647SZdenek Styblik 			printf("FRU serial number set failed\n");
91*58837647SZdenek Styblik 			rc = (-1);
92c18ec02fSPetter Reinholdtsen 		}
93*58837647SZdenek Styblik 	} else if (!strncmp(argv[0], "setmfgdate", 10)) {
94*58837647SZdenek Styblik 		if (argc < 1) {
95c18ec02fSPetter Reinholdtsen 			printf("fru setmfgdate\n");
96*58837647SZdenek Styblik 			return (-1);
97c18ec02fSPetter Reinholdtsen 		}
98*58837647SZdenek Styblik 		if (ipmi_kontron_set_mfg_date(intf) > 0) {
99*58837647SZdenek Styblik 			printf("FRU manufacturing date setted successfully\n");
100*58837647SZdenek Styblik 		} else {
101*58837647SZdenek Styblik 			printf("FRU manufacturing date set failed\n");
102*58837647SZdenek Styblik 			rc = (-1);
103c18ec02fSPetter Reinholdtsen 		}
104*58837647SZdenek Styblik 	} else if (!strncmp(argv[0], "nextboot", 8)) {
105*58837647SZdenek Styblik 		if (argc < 2) {
106*58837647SZdenek Styblik 			lprintf(LOG_ERR, "Not enough parameters given.");
107c18ec02fSPetter Reinholdtsen 			ipmi_kontron_nextboot_help();
108*58837647SZdenek Styblik 			rc = (-1);
109c18ec02fSPetter Reinholdtsen 		}
110*58837647SZdenek Styblik 		rc = ipmi_kontron_nextboot_set(intf, (argc - 1), (argv + 1));
111*58837647SZdenek Styblik 		if (rc == 0) {
112*58837647SZdenek Styblik 			printf("Nextboot set successfully\n");
113*58837647SZdenek Styblik 		} else {
114*58837647SZdenek Styblik 			printf("Nextboot set failed\n");
115*58837647SZdenek Styblik 			rc = (-1);
116c18ec02fSPetter Reinholdtsen 		}
117*58837647SZdenek Styblik 	} else  {
118*58837647SZdenek Styblik 		lprintf(LOG_ERR, "Invalid Kontron command: %s", argv[0]);
119c18ec02fSPetter Reinholdtsen 		ipmi_kontron_help();
120*58837647SZdenek Styblik 		rc = (-1);
121c18ec02fSPetter Reinholdtsen 	}
122c18ec02fSPetter Reinholdtsen 	return rc;
123c18ec02fSPetter Reinholdtsen }
124c18ec02fSPetter Reinholdtsen 
125*58837647SZdenek Styblik static void
126*58837647SZdenek Styblik ipmi_kontron_help(void)
127c18ec02fSPetter Reinholdtsen {
128c18ec02fSPetter Reinholdtsen 	printf("Kontron Commands:  setsn setmfgdate nextboot\n");
129c18ec02fSPetter Reinholdtsen }
130c18ec02fSPetter Reinholdtsen 
131*58837647SZdenek Styblik int
132*58837647SZdenek Styblik ipmi_kontronoem_set_large_buffer(struct ipmi_intf *intf, unsigned char size)
133c18ec02fSPetter Reinholdtsen {
134c18ec02fSPetter Reinholdtsen 	uint8_t error_occurs = 0;
135c18ec02fSPetter Reinholdtsen 	uint32_t prev_target_addr = intf->target_addr ;
136*58837647SZdenek Styblik 	if (intf->target_addr > 0 && (intf->target_addr != intf->my_addr)) {
137c18ec02fSPetter Reinholdtsen 		intf->target_addr = intf->my_addr;
138c18ec02fSPetter Reinholdtsen 		printf("Set local big buffer\n");
139*58837647SZdenek Styblik 		if (ipmi_kontronoem_send_set_large_buffer(intf, 0x0e, size) == 0) {
140c18ec02fSPetter Reinholdtsen 			printf("Set local big buffer:success\n");
141*58837647SZdenek Styblik 		} else {
142c18ec02fSPetter Reinholdtsen 			error_occurs = 1;
143c18ec02fSPetter Reinholdtsen 		}
144*58837647SZdenek Styblik 		if (error_occurs == 0) {
145*58837647SZdenek Styblik 			if (ipmi_kontronoem_send_set_large_buffer(intf, 0x00, size) == 0) {
146c18ec02fSPetter Reinholdtsen 				printf("IPMB was set\n");
147*58837647SZdenek Styblik 			} else {
148c18ec02fSPetter Reinholdtsen 				/* Revert back the previous set large buffer */
149c18ec02fSPetter Reinholdtsen 				error_occurs = 1;
150c18ec02fSPetter Reinholdtsen 				ipmi_kontronoem_send_set_large_buffer( intf, 0x0e, 0 );
151c18ec02fSPetter Reinholdtsen 			}
152c18ec02fSPetter Reinholdtsen 		}
153c18ec02fSPetter Reinholdtsen 		/* Restore target address */
154c18ec02fSPetter Reinholdtsen 		intf->target_addr = prev_target_addr;
155c18ec02fSPetter Reinholdtsen 	}
156*58837647SZdenek Styblik 	if (error_occurs == 0) {
157*58837647SZdenek Styblik 		if(ipmi_kontronoem_send_set_large_buffer(intf, 0x0e, size) == 0) {
158*58837647SZdenek Styblik 			/* printf("Set remote big buffer\n"); */
159*58837647SZdenek Styblik 		} else {
160*58837647SZdenek Styblik 			if (intf->target_addr > 0  && (intf->target_addr != intf->my_addr)) {
161c18ec02fSPetter Reinholdtsen 				/* Error occurs revert back the previous set large buffer */
162c18ec02fSPetter Reinholdtsen 				intf->target_addr = intf->my_addr;
163*58837647SZdenek Styblik 				/* ipmi_kontronoem_send_set_large_buffer(intf, 0x00, 0); */
164c18ec02fSPetter Reinholdtsen 				ipmi_kontronoem_send_set_large_buffer(intf, 0x0e, 0);
165c18ec02fSPetter Reinholdtsen 				intf->target_addr = prev_target_addr;
166c18ec02fSPetter Reinholdtsen 			}
167c18ec02fSPetter Reinholdtsen 		}
168c18ec02fSPetter Reinholdtsen 	}
169c18ec02fSPetter Reinholdtsen 	return error_occurs;
170c18ec02fSPetter Reinholdtsen }
171c18ec02fSPetter Reinholdtsen 
172*58837647SZdenek Styblik int
173*58837647SZdenek Styblik ipmi_kontronoem_send_set_large_buffer(struct ipmi_intf *intf,
174*58837647SZdenek Styblik 		unsigned char channel, unsigned char size)
175c18ec02fSPetter Reinholdtsen {
176c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
177c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
178c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[2];
179c18ec02fSPetter Reinholdtsen 	int i;
180c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, sizeof(msg_data));
181*58837647SZdenek Styblik 	/* channel =~ 0x0e => Currently running interface */
182*58837647SZdenek Styblik 	msg_data[0] = channel;
183c18ec02fSPetter Reinholdtsen 	msg_data[1] = size;
184c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
185*58837647SZdenek Styblik 	req.msg.netfn = 0x3E;
186*58837647SZdenek Styblik 	/* Set Channel Buffer Length - OEM */
187*58837647SZdenek Styblik 	req.msg.cmd = 0x82;
188c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
189c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 2;
190c18ec02fSPetter Reinholdtsen 	req.msg.lun = 0x00;
191c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
192*58837647SZdenek Styblik 	if (rsp == NULL)  {
193c18ec02fSPetter Reinholdtsen 		printf("Cannot send large buffer command\n");
194c18ec02fSPetter Reinholdtsen 		return(-1);
195*58837647SZdenek Styblik 	} else if (rsp->ccode > 0)  {
196c18ec02fSPetter Reinholdtsen 		printf("Invalid length for the selected interface (%s) %d\n",
197c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals), rsp->ccode);
198c18ec02fSPetter Reinholdtsen 		return(-1);
199c18ec02fSPetter Reinholdtsen 	}
200c18ec02fSPetter Reinholdtsen 	return 0;
201c18ec02fSPetter Reinholdtsen }
202c18ec02fSPetter Reinholdtsen 
203c18ec02fSPetter Reinholdtsen /* ipmi_fru_set_serial_number -  Set the Serial Number in FRU
204c18ec02fSPetter Reinholdtsen  *
205c18ec02fSPetter Reinholdtsen  * @intf: ipmi interface
206c18ec02fSPetter Reinholdtsen  * @id: fru id
207c18ec02fSPetter Reinholdtsen  *
208c18ec02fSPetter Reinholdtsen  * returns -1 on error
209c18ec02fSPetter Reinholdtsen  * returns 1 if successful
210c18ec02fSPetter Reinholdtsen  */
211c18ec02fSPetter Reinholdtsen static int
212c18ec02fSPetter Reinholdtsen ipmi_kontron_set_serial_number(struct ipmi_intf *intf)
213c18ec02fSPetter Reinholdtsen {
214*58837647SZdenek Styblik 	struct fru_header header;
215*58837647SZdenek Styblik 	struct fru_info fru;
216c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
217c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
218c18ec02fSPetter Reinholdtsen 	char *sn;
219c18ec02fSPetter Reinholdtsen 	char *fru_area;
220*58837647SZdenek Styblik 	uint8_t checksum;
221*58837647SZdenek Styblik 	uint8_t *fru_data;
222*58837647SZdenek Styblik 	uint8_t msg_data[4];
223*58837647SZdenek Styblik 	uint8_t sn_size;
224*58837647SZdenek Styblik 	uint32_t board_sec_len;
225*58837647SZdenek Styblik 	uint32_t fru_data_offset;
226*58837647SZdenek Styblik 	uint32_t fru_data_offset_tmp;
227*58837647SZdenek Styblik 	uint32_t i;
228*58837647SZdenek Styblik 	uint32_t prod_sec_len;
229c18ec02fSPetter Reinholdtsen 
230c18ec02fSPetter Reinholdtsen 	sn = NULL;
231c18ec02fSPetter Reinholdtsen 	fru_data = NULL;
232c18ec02fSPetter Reinholdtsen 
233c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, 4);
234c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0xb4;
235c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x90;
236c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x91;
237c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x8b;
238c18ec02fSPetter Reinholdtsen 
239c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
240c18ec02fSPetter Reinholdtsen 	req.msg.netfn = 0x3E;
241c18ec02fSPetter Reinholdtsen 	req.msg.cmd = 0x0C;
242c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
243c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4;
244c18ec02fSPetter Reinholdtsen 	/* Set Lun, necessary for this oem command */
245c18ec02fSPetter Reinholdtsen 	req.msg.lun = 0x03;
246c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
247*58837647SZdenek Styblik 	if (rsp == NULL) {
248c18ec02fSPetter Reinholdtsen 		printf(" Device not present (No Response)\n");
249*58837647SZdenek Styblik 		return (-1);
250*58837647SZdenek Styblik 	} else if (rsp->ccode > 0) {
251c18ec02fSPetter Reinholdtsen 		printf(" This option is not implemented for this board\n");
252*58837647SZdenek Styblik 		return (-1);
253c18ec02fSPetter Reinholdtsen 	}
254c18ec02fSPetter Reinholdtsen 	sn_size = rsp->data_len;
255c18ec02fSPetter Reinholdtsen 	sn = malloc(sn_size + 1);
256*58837647SZdenek Styblik 	if (sn == NULL) {
257*58837647SZdenek Styblik 		lprintf(LOG_ERR, "ipmitool: malloc failure");
258*58837647SZdenek Styblik 		return (-1);
259c18ec02fSPetter Reinholdtsen 	}
260c18ec02fSPetter Reinholdtsen 	memset(sn, 0, sn_size + 1);
261c18ec02fSPetter Reinholdtsen 	memcpy(sn, rsp->data, sn_size);
262*58837647SZdenek Styblik 	if (verbose >= 1) {
263c18ec02fSPetter Reinholdtsen 		printf("Original serial number is : [%s]\n", sn);
264c18ec02fSPetter Reinholdtsen 	}
265c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, 4);
266c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0;
267c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
268c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
269c18ec02fSPetter Reinholdtsen 	req.msg.cmd = GET_FRU_INFO;
270c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
271c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 1;
272c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
273c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
274c18ec02fSPetter Reinholdtsen 		printf(" Device not present (No Response)\n");
275c18ec02fSPetter Reinholdtsen 		free(sn);
276c18ec02fSPetter Reinholdtsen 		sn = NULL;
277*58837647SZdenek Styblik 		return (-1);
278*58837647SZdenek Styblik 	} else if (rsp->ccode > 0) {
279c18ec02fSPetter Reinholdtsen 		printf(" Device not present (%s)\n",
280c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
281c18ec02fSPetter Reinholdtsen 		free(sn);
282c18ec02fSPetter Reinholdtsen 		sn = NULL;
283c18ec02fSPetter Reinholdtsen 		return (-1);
284c18ec02fSPetter Reinholdtsen 	}
285c18ec02fSPetter Reinholdtsen 	memset(&fru, 0, sizeof(fru));
286c18ec02fSPetter Reinholdtsen 	fru.size = (rsp->data[1] << 8) | rsp->data[0];
287c18ec02fSPetter Reinholdtsen 	fru.access = rsp->data[2] & 0x1;
288c18ec02fSPetter Reinholdtsen 	if (fru.size < 1) {
289c18ec02fSPetter Reinholdtsen 		printf(" Invalid FRU size %d", fru.size);
290c18ec02fSPetter Reinholdtsen 		free(sn);
291c18ec02fSPetter Reinholdtsen 		sn = NULL;
292*58837647SZdenek Styblik 		return (-1);
293c18ec02fSPetter Reinholdtsen 	}
294*58837647SZdenek Styblik 	/* retrieve the FRU header */
295c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0;
296c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0;
297c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0;
298c18ec02fSPetter Reinholdtsen 	msg_data[3] = 8;
299c18ec02fSPetter Reinholdtsen 
300c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
301c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
302c18ec02fSPetter Reinholdtsen 	req.msg.cmd = GET_FRU_DATA;
303c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
304c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4;
305c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
306*58837647SZdenek Styblik 	if (rsp == NULL) {
307c18ec02fSPetter Reinholdtsen 		printf(" Device not present (No Response)\n");
308c18ec02fSPetter Reinholdtsen 		free(sn);
309c18ec02fSPetter Reinholdtsen 		sn = NULL;
310c18ec02fSPetter Reinholdtsen 		return (-1);
311*58837647SZdenek Styblik 	} else if (rsp->ccode > 0) {
312c18ec02fSPetter Reinholdtsen 		printf(" Device not present (%s)\n",
313c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
314c18ec02fSPetter Reinholdtsen 		free(sn);
315c18ec02fSPetter Reinholdtsen 		sn = NULL;
316c18ec02fSPetter Reinholdtsen 		return (-1);
317c18ec02fSPetter Reinholdtsen 	}
318*58837647SZdenek Styblik 	if (verbose > 1) {
319c18ec02fSPetter Reinholdtsen 		printbuf(rsp->data, rsp->data_len, "FRU DATA");
320*58837647SZdenek Styblik 	}
321c18ec02fSPetter Reinholdtsen 	memcpy(&header, rsp->data + 1, 8);
322*58837647SZdenek Styblik 	if (header.version != 1) {
323c18ec02fSPetter Reinholdtsen 		printf(" Unknown FRU header version 0x%02x",
324c18ec02fSPetter Reinholdtsen 				header.version);
325c18ec02fSPetter Reinholdtsen 		free(sn);
326c18ec02fSPetter Reinholdtsen 		sn = NULL;
327c18ec02fSPetter Reinholdtsen 		return(-1);
328c18ec02fSPetter Reinholdtsen 	}
329c18ec02fSPetter Reinholdtsen 	/* Set the Board Section */
330c18ec02fSPetter Reinholdtsen 	board_sec_len = (header.offset.product * 8) - (header.offset.board * 8);
331c18ec02fSPetter Reinholdtsen 	fru_data = malloc(fru.size);
332*58837647SZdenek Styblik 	if (fru_data == NULL) {
333*58837647SZdenek Styblik 		lprintf(LOG_ERR, "ipmitool: malloc failure");
334c18ec02fSPetter Reinholdtsen 		free(sn);
335c18ec02fSPetter Reinholdtsen 		sn = NULL;
336c18ec02fSPetter Reinholdtsen 		return (-1);
337c18ec02fSPetter Reinholdtsen 	}
338c18ec02fSPetter Reinholdtsen 	memset(fru_data, 0, fru.size);
339*58837647SZdenek Styblik 	if (read_fru_area(intf, &fru, 0, (header.offset.board * 8),
340*58837647SZdenek Styblik 				board_sec_len, fru_data) < 0) {
341c18ec02fSPetter Reinholdtsen 		free(sn);
342c18ec02fSPetter Reinholdtsen 		sn = NULL;
343c18ec02fSPetter Reinholdtsen 		free(fru_data);
344c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
345c18ec02fSPetter Reinholdtsen 		return (-1);
346c18ec02fSPetter Reinholdtsen 	}
347c18ec02fSPetter Reinholdtsen 	/* Position at Board Manufacturer */
348c18ec02fSPetter Reinholdtsen 	fru_data_offset = (header.offset.board * 8) + 6;
349c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset);
350c18ec02fSPetter Reinholdtsen 	/* Position at Board Product Name */
351c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset);
352c18ec02fSPetter Reinholdtsen 	fru_data_offset_tmp = fru_data_offset;
353c18ec02fSPetter Reinholdtsen 	/* Position at Serial Number */
354c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp);
355c18ec02fSPetter Reinholdtsen 	fru_data_offset++;
356*58837647SZdenek Styblik 	if (strlen(fru_area) != sn_size) {
357c18ec02fSPetter Reinholdtsen 		printf("The length of the serial number in the FRU Board Area is wrong.\n");
358c18ec02fSPetter Reinholdtsen 		free(sn);
359c18ec02fSPetter Reinholdtsen 		sn = NULL;
360c18ec02fSPetter Reinholdtsen 		free(fru_data);
361c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
362c18ec02fSPetter Reinholdtsen 		return(-1);
363c18ec02fSPetter Reinholdtsen 	}
364c18ec02fSPetter Reinholdtsen 	/* Copy the new serial number in the board section saved in memory*/
365c18ec02fSPetter Reinholdtsen 	memcpy(fru_data + fru_data_offset, sn, sn_size);
366c18ec02fSPetter Reinholdtsen 	checksum = 0;
367c18ec02fSPetter Reinholdtsen 	/* Calculate Header Checksum */
368*58837647SZdenek Styblik 	for(i = (header.offset.board * 8);
369*58837647SZdenek Styblik 			i < (((header.offset.board * 8) + board_sec_len) - 2);
370*58837647SZdenek Styblik 			i++) {
371c18ec02fSPetter Reinholdtsen 		checksum += fru_data[i];
372c18ec02fSPetter Reinholdtsen 	}
373c18ec02fSPetter Reinholdtsen 	checksum = (~checksum) + 1;
374c18ec02fSPetter Reinholdtsen 	fru_data[(header.offset.board * 8) + board_sec_len - 1] = checksum;
375c18ec02fSPetter Reinholdtsen 	/* Write the new FRU Board section */
376*58837647SZdenek Styblik 	if (write_fru_area(intf, &fru, 0, (header.offset.board * 8),
377*58837647SZdenek Styblik 				(header.offset.board * 8),
378*58837647SZdenek Styblik 				board_sec_len, fru_data) < 0) {
379c18ec02fSPetter Reinholdtsen 		free(sn);
380c18ec02fSPetter Reinholdtsen 		sn = NULL;
381c18ec02fSPetter Reinholdtsen 		free(fru_data);
382c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
383c18ec02fSPetter Reinholdtsen 		return(-1);
384c18ec02fSPetter Reinholdtsen 	}
385c18ec02fSPetter Reinholdtsen 	/* Set the Product Section */
386c18ec02fSPetter Reinholdtsen 	prod_sec_len = (header.offset.multi * 8) - (header.offset.product * 8);
387*58837647SZdenek Styblik 	if (read_fru_area(intf, &fru, 0, (header.offset.product * 8),
388*58837647SZdenek Styblik 				prod_sec_len, fru_data) < 0) {
389c18ec02fSPetter Reinholdtsen 		free(sn);
390c18ec02fSPetter Reinholdtsen 		sn = NULL;
391c18ec02fSPetter Reinholdtsen 		free(fru_data);
392c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
393c18ec02fSPetter Reinholdtsen 		return(-1);
394c18ec02fSPetter Reinholdtsen 	}
395c18ec02fSPetter Reinholdtsen 	/* Position at Product Manufacturer */
396c18ec02fSPetter Reinholdtsen 	fru_data_offset = (header.offset.product * 8) + 3;
397c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset);
398c18ec02fSPetter Reinholdtsen 	/* Position at Product Name */
399c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset);
400c18ec02fSPetter Reinholdtsen 	/* Position at Product Part */
401c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset);
402c18ec02fSPetter Reinholdtsen 	/* Position at Product Version */
403c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset);
404c18ec02fSPetter Reinholdtsen 	fru_data_offset_tmp = fru_data_offset;
405c18ec02fSPetter Reinholdtsen 	/* Position at Serial Number */
406c18ec02fSPetter Reinholdtsen 	fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp);
407c18ec02fSPetter Reinholdtsen 	fru_data_offset ++;
408*58837647SZdenek Styblik 	if (strlen(fru_area) != sn_size) {
409c18ec02fSPetter Reinholdtsen 		free(sn);
410c18ec02fSPetter Reinholdtsen 		sn = NULL;
411c18ec02fSPetter Reinholdtsen 		free(fru_data);
412c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
413c18ec02fSPetter Reinholdtsen 		printf("The length of the serial number in the FRU Product Area is wrong.\n");
414c18ec02fSPetter Reinholdtsen 		return(-1);
415c18ec02fSPetter Reinholdtsen 	}
416c18ec02fSPetter Reinholdtsen 	/* Copy the new serial number in the product section saved in memory*/
417c18ec02fSPetter Reinholdtsen 	memcpy(fru_data + fru_data_offset, sn, sn_size);
418c18ec02fSPetter Reinholdtsen 	checksum = 0;
419c18ec02fSPetter Reinholdtsen 	/* Calculate Header Checksum */
420*58837647SZdenek Styblik 	for (i = (header.offset.product * 8);
421*58837647SZdenek Styblik 			i < (((header.offset.product * 8) + prod_sec_len) - 2);
422*58837647SZdenek Styblik 			i ++) {
423c18ec02fSPetter Reinholdtsen 		checksum += fru_data[i];
424c18ec02fSPetter Reinholdtsen 	}
425c18ec02fSPetter Reinholdtsen 	checksum = (~checksum) + 1;
426c18ec02fSPetter Reinholdtsen 	fru_data[(header.offset.product * 8)+prod_sec_len - 1] = checksum;
427c18ec02fSPetter Reinholdtsen 	/* Write the new FRU Board section */
428*58837647SZdenek Styblik 	if (write_fru_area(intf, &fru, 0, (header.offset.product * 8),
429*58837647SZdenek Styblik 				(header.offset.product * 8),
430*58837647SZdenek Styblik 				prod_sec_len, fru_data) < 0) {
431c18ec02fSPetter Reinholdtsen 		free(sn);
432c18ec02fSPetter Reinholdtsen 		sn = NULL;
433c18ec02fSPetter Reinholdtsen 		free(fru_data);
434c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
435c18ec02fSPetter Reinholdtsen 		return -1;
436c18ec02fSPetter Reinholdtsen 	}
437c18ec02fSPetter Reinholdtsen 	free(sn);
438c18ec02fSPetter Reinholdtsen 	sn = NULL;
439c18ec02fSPetter Reinholdtsen 	free(fru_data);
440c18ec02fSPetter Reinholdtsen 	fru_data = NULL;
441c18ec02fSPetter Reinholdtsen 	return(1);
442c18ec02fSPetter Reinholdtsen }
443c18ec02fSPetter Reinholdtsen 
444c18ec02fSPetter Reinholdtsen /* ipmi_fru_set_mfg_date -  Set the Manufacturing Date in FRU
445c18ec02fSPetter Reinholdtsen  *
446c18ec02fSPetter Reinholdtsen  * @intf: ipmi interface
447c18ec02fSPetter Reinholdtsen  * @id: fru id
448c18ec02fSPetter Reinholdtsen  *
449c18ec02fSPetter Reinholdtsen  * returns -1 on error
450c18ec02fSPetter Reinholdtsen  * returns 1 if successful
451c18ec02fSPetter Reinholdtsen  */
452c18ec02fSPetter Reinholdtsen static int
453c18ec02fSPetter Reinholdtsen ipmi_kontron_set_mfg_date (struct ipmi_intf *intf)
454c18ec02fSPetter Reinholdtsen {
455*58837647SZdenek Styblik 	struct fru_header header;
456*58837647SZdenek Styblik 	struct fru_info fru;
457c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
458c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
459*58837647SZdenek Styblik 	uint8_t *fru_data;
460*58837647SZdenek Styblik 	uint8_t checksum;
461c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[4];
462c18ec02fSPetter Reinholdtsen 	uint8_t mfg_date[3];
463*58837647SZdenek Styblik 	uint32_t board_sec_len;
464*58837647SZdenek Styblik 	uint32_t i;
465c18ec02fSPetter Reinholdtsen 
466c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, 4);
467c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0xb4;
468c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x90;
469c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x91;
470c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x8b;
471c18ec02fSPetter Reinholdtsen 
472c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
473c18ec02fSPetter Reinholdtsen 	req.msg.netfn = 0x3E;
474c18ec02fSPetter Reinholdtsen 	req.msg.cmd = 0x0E;
475c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
476c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4;
477c18ec02fSPetter Reinholdtsen 	/* Set Lun temporary, necessary for this oem command */
478c18ec02fSPetter Reinholdtsen 	req.msg.lun = 0x03;
479c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
480*58837647SZdenek Styblik 	if (rsp == NULL)  {
481c18ec02fSPetter Reinholdtsen 		printf("Device not present (No Response)\n");
482c18ec02fSPetter Reinholdtsen 		return(-1);
483*58837647SZdenek Styblik 	} else if (rsp->ccode > 0) {
484c18ec02fSPetter Reinholdtsen 		printf("This option is not implemented for this board\n");
485c18ec02fSPetter Reinholdtsen 		return(-1);
486c18ec02fSPetter Reinholdtsen 	}
487*58837647SZdenek Styblik 	if (rsp->data_len != 3) {
488c18ec02fSPetter Reinholdtsen 		printf("Invalid response for the Manufacturing date\n");
489c18ec02fSPetter Reinholdtsen 		return(-1);
490c18ec02fSPetter Reinholdtsen 	}
491c18ec02fSPetter Reinholdtsen 	memset(mfg_date, 0, 3);
492c18ec02fSPetter Reinholdtsen 	memcpy(mfg_date, rsp->data, 3);
493c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, 4);
494c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0;
495c18ec02fSPetter Reinholdtsen 
496c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
497c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
498c18ec02fSPetter Reinholdtsen 	req.msg.cmd = GET_FRU_INFO;
499c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
500c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 1;
501c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
502c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
503c18ec02fSPetter Reinholdtsen 		printf(" Device not present (No Response)\n");
504c18ec02fSPetter Reinholdtsen 		return(-1);
505*58837647SZdenek Styblik 	} else if (rsp->ccode > 0) {
506c18ec02fSPetter Reinholdtsen 		printf(" Device not present (%s)\n",
507c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
508c18ec02fSPetter Reinholdtsen 		return(-1);
509c18ec02fSPetter Reinholdtsen 	}
510c18ec02fSPetter Reinholdtsen 
511c18ec02fSPetter Reinholdtsen 	memset(&fru, 0, sizeof(fru));
512c18ec02fSPetter Reinholdtsen 	fru.size = (rsp->data[1] << 8) | rsp->data[0];
513c18ec02fSPetter Reinholdtsen 	fru.access = rsp->data[2] & 0x1;
514c18ec02fSPetter Reinholdtsen 	if (fru.size < 1) {
515c18ec02fSPetter Reinholdtsen 		printf(" Invalid FRU size %d", fru.size);
516c18ec02fSPetter Reinholdtsen 		return(-1);
517c18ec02fSPetter Reinholdtsen 	}
518*58837647SZdenek Styblik 	/* retrieve the FRU header */
519c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0;
520c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0;
521c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0;
522c18ec02fSPetter Reinholdtsen 	msg_data[3] = 8;
523c18ec02fSPetter Reinholdtsen 
524c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
525c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_STORAGE;
526c18ec02fSPetter Reinholdtsen 	req.msg.cmd = GET_FRU_DATA;
527c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
528c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 4;
529c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
530*58837647SZdenek Styblik 	if (rsp == NULL) {
531c18ec02fSPetter Reinholdtsen 		printf(" Device not present (No Response)\n");
532c18ec02fSPetter Reinholdtsen 		return (-1);
533*58837647SZdenek Styblik 	} else if (rsp->ccode > 0) {
534c18ec02fSPetter Reinholdtsen 		printf(" Device not present (%s)\n",
535c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
536c18ec02fSPetter Reinholdtsen 		return (-1);
537c18ec02fSPetter Reinholdtsen 	}
538*58837647SZdenek Styblik 	if (verbose > 1) {
539c18ec02fSPetter Reinholdtsen 		printbuf(rsp->data, rsp->data_len, "FRU DATA");
540*58837647SZdenek Styblik 	}
541c18ec02fSPetter Reinholdtsen 	memcpy(&header, rsp->data + 1, 8);
542*58837647SZdenek Styblik 	if (header.version != 1) {
543c18ec02fSPetter Reinholdtsen 		printf(" Unknown FRU header version 0x%02x",
544c18ec02fSPetter Reinholdtsen 				header.version);
545c18ec02fSPetter Reinholdtsen 		return(-1);
546c18ec02fSPetter Reinholdtsen 	}
547c18ec02fSPetter Reinholdtsen 	board_sec_len = (header.offset.product * 8) - (header.offset.board * 8);
548c18ec02fSPetter Reinholdtsen 	fru_data = malloc(fru.size);
549*58837647SZdenek Styblik 	if(fru_data == NULL) {
550*58837647SZdenek Styblik 		lprintf(LOG_ERR, "ipmitool: malloc failure");
551c18ec02fSPetter Reinholdtsen 		return(-1);
552c18ec02fSPetter Reinholdtsen 	}
553c18ec02fSPetter Reinholdtsen 	memset(fru_data, 0, fru.size);
554*58837647SZdenek Styblik 	if (read_fru_area(intf ,&fru ,0 ,(header.offset.board * 8),
555*58837647SZdenek Styblik 				board_sec_len ,fru_data) < 0) {
556c18ec02fSPetter Reinholdtsen 		free(fru_data);
557c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
558c18ec02fSPetter Reinholdtsen 		return(-1);
559c18ec02fSPetter Reinholdtsen 	}
560c18ec02fSPetter Reinholdtsen 	/* Copy the new manufacturing date in the board section saved in memory*/
561c18ec02fSPetter Reinholdtsen 	memcpy(fru_data + (header.offset.board * 8) + 3, mfg_date, 3);
562c18ec02fSPetter Reinholdtsen 	checksum = 0;
563c18ec02fSPetter Reinholdtsen 	/* Calculate Header Checksum */
564*58837647SZdenek Styblik 	for (i = (header.offset.board * 8);
565*58837647SZdenek Styblik 			i < (((header.offset.board * 8) + board_sec_len) - 2);
566*58837647SZdenek Styblik 			i ++ ) {
567c18ec02fSPetter Reinholdtsen 		checksum += fru_data[i];
568c18ec02fSPetter Reinholdtsen 	}
569c18ec02fSPetter Reinholdtsen 	checksum = (~checksum) + 1;
570c18ec02fSPetter Reinholdtsen 	fru_data[(header.offset.board * 8)+board_sec_len - 1] = checksum;
571c18ec02fSPetter Reinholdtsen 	/* Write the new FRU Board section */
572*58837647SZdenek Styblik 	if (write_fru_area(intf, &fru, 0, (header.offset.board * 8),
573*58837647SZdenek Styblik 				(header.offset.board * 8),
574*58837647SZdenek Styblik 				board_sec_len, fru_data) < 0) {
575c18ec02fSPetter Reinholdtsen 		free(fru_data);
576c18ec02fSPetter Reinholdtsen 		fru_data = NULL;
577c18ec02fSPetter Reinholdtsen 		return (-1);
578c18ec02fSPetter Reinholdtsen 	}
579c18ec02fSPetter Reinholdtsen 	free(fru_data);
580c18ec02fSPetter Reinholdtsen 	fru_data = NULL;
581c18ec02fSPetter Reinholdtsen 	return (1);
582c18ec02fSPetter Reinholdtsen }
583c18ec02fSPetter Reinholdtsen 
584c18ec02fSPetter Reinholdtsen static void
585c18ec02fSPetter Reinholdtsen ipmi_kontron_nextboot_help(void)
586c18ec02fSPetter Reinholdtsen {
587c18ec02fSPetter Reinholdtsen 	int i;
588c18ec02fSPetter Reinholdtsen 	printf("nextboot <device>\n"
589c18ec02fSPetter Reinholdtsen 			"Supported devices:\n");
590c18ec02fSPetter Reinholdtsen 	for (i = 0; bootdev[i] != 0; i++) {
591c18ec02fSPetter Reinholdtsen 		printf("- %s\n", bootdev[i]);
592c18ec02fSPetter Reinholdtsen 	}
593c18ec02fSPetter Reinholdtsen }
594c18ec02fSPetter Reinholdtsen 
595c18ec02fSPetter Reinholdtsen /* ipmi_kontron_next_boot_set - Select the next boot order on CP6012
596c18ec02fSPetter Reinholdtsen  *
597c18ec02fSPetter Reinholdtsen  * @intf: ipmi interface
598c18ec02fSPetter Reinholdtsen  * @id: fru id
599c18ec02fSPetter Reinholdtsen  *
600c18ec02fSPetter Reinholdtsen  * returns -1 on error
601c18ec02fSPetter Reinholdtsen  * returns 1 if successful
602c18ec02fSPetter Reinholdtsen  */
603c18ec02fSPetter Reinholdtsen static int
604c18ec02fSPetter Reinholdtsen ipmi_kontron_nextboot_set(struct ipmi_intf *intf, int argc, char **argv)
605c18ec02fSPetter Reinholdtsen {
606c18ec02fSPetter Reinholdtsen 	struct ipmi_rs *rsp;
607c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
608c18ec02fSPetter Reinholdtsen 	uint8_t msg_data[8];
609c18ec02fSPetter Reinholdtsen 	int i;
610c18ec02fSPetter Reinholdtsen 
611c18ec02fSPetter Reinholdtsen 	memset(msg_data, 0, sizeof(msg_data));
612c18ec02fSPetter Reinholdtsen 	msg_data[0] = 0xb4;
613c18ec02fSPetter Reinholdtsen 	msg_data[1] = 0x90;
614c18ec02fSPetter Reinholdtsen 	msg_data[2] = 0x91;
615c18ec02fSPetter Reinholdtsen 	msg_data[3] = 0x8b;
616c18ec02fSPetter Reinholdtsen 	msg_data[4] = 0x9d;
617c18ec02fSPetter Reinholdtsen 	msg_data[5] = 0xFF;
618c18ec02fSPetter Reinholdtsen 	msg_data[6] = 0xFF; /* any */
619c18ec02fSPetter Reinholdtsen 	for (i = 0; bootdev[i] != 0; i++) {
620c18ec02fSPetter Reinholdtsen 		if (strcmp(argv[0], bootdev[i]) == 0) {
621c18ec02fSPetter Reinholdtsen 			msg_data[5] = i;
622c18ec02fSPetter Reinholdtsen 			break;
623c18ec02fSPetter Reinholdtsen 		}
624c18ec02fSPetter Reinholdtsen 	}
625c18ec02fSPetter Reinholdtsen 	/* Invalid device selected? */
626c18ec02fSPetter Reinholdtsen 	if (msg_data[5] == 0xFF) {
627c18ec02fSPetter Reinholdtsen 		printf("Unknown boot device: %s\n", argv[0]);
628*58837647SZdenek Styblik 		return (-1);
629c18ec02fSPetter Reinholdtsen 	}
630c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(req));
631c18ec02fSPetter Reinholdtsen 	req.msg.netfn = 0x3E;
632c18ec02fSPetter Reinholdtsen 	req.msg.cmd = 0x02;
633c18ec02fSPetter Reinholdtsen 	req.msg.data = msg_data;
634c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 7;
635c18ec02fSPetter Reinholdtsen 	/* Set Lun temporary, necessary for this oem command */
636c18ec02fSPetter Reinholdtsen 	req.msg.lun = 0x03;
637c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
638*58837647SZdenek Styblik 	if (rsp == NULL) {
639c18ec02fSPetter Reinholdtsen 		printf("Device not present (No Response)\n");
640c18ec02fSPetter Reinholdtsen 		return(-1);
641*58837647SZdenek Styblik 	} else if (rsp->ccode > 0) {
642c18ec02fSPetter Reinholdtsen 		printf("Device not present (%s)\n",
643c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
644c18ec02fSPetter Reinholdtsen 		return (-1);
645c18ec02fSPetter Reinholdtsen 	}
646c18ec02fSPetter Reinholdtsen 	return 0;
647c18ec02fSPetter Reinholdtsen }
648