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 <string.h>
34c18ec02fSPetter Reinholdtsen #include <stdlib.h>
35c18ec02fSPetter Reinholdtsen #include <stdio.h>
36c18ec02fSPetter Reinholdtsen
37c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
38c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
39c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
40c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
41c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_raw.h>
42c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
43c18ec02fSPetter Reinholdtsen
44c18ec02fSPetter Reinholdtsen #define IPMI_I2C_MASTER_MAX_SIZE 0x40 /* 64 bytes */
45c18ec02fSPetter Reinholdtsen
46c18ec02fSPetter Reinholdtsen static int is_valid_param(const char *input_param, uint8_t *uchr_ptr,
47c18ec02fSPetter Reinholdtsen const char *label);
48*70099a3cSPat Donlin int ipmi_spd_print(uint8_t *, int);
49c18ec02fSPetter Reinholdtsen
50c18ec02fSPetter Reinholdtsen /* ipmi_master_write_read - Perform I2C write/read transactions
51c18ec02fSPetter Reinholdtsen *
52c18ec02fSPetter Reinholdtsen * This function performs an I2C master write-read function through
53c18ec02fSPetter Reinholdtsen * IPMI interface. It has a maximum transfer size of 32 bytes.
54c18ec02fSPetter Reinholdtsen *
55c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
56c18ec02fSPetter Reinholdtsen * @bus: channel number, i2c bus id and type
57c18ec02fSPetter Reinholdtsen * @addr: i2c slave address
58c18ec02fSPetter Reinholdtsen * @wdata: data to write
59c18ec02fSPetter Reinholdtsen * @wsize: length of data to write (max 64 bytes)
60c18ec02fSPetter Reinholdtsen * @rsize: length of data to read (max 64 bytes)
61c18ec02fSPetter Reinholdtsen *
62c18ec02fSPetter Reinholdtsen * Returns pointer to IPMI Response
63c18ec02fSPetter Reinholdtsen */
64c18ec02fSPetter Reinholdtsen struct ipmi_rs *
ipmi_master_write_read(struct ipmi_intf * intf,uint8_t bus,uint8_t addr,uint8_t * wdata,uint8_t wsize,uint8_t rsize)65c18ec02fSPetter Reinholdtsen ipmi_master_write_read(struct ipmi_intf * intf, uint8_t bus, uint8_t addr,
66c18ec02fSPetter Reinholdtsen uint8_t * wdata, uint8_t wsize, uint8_t rsize)
67c18ec02fSPetter Reinholdtsen {
68c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
69c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
70c18ec02fSPetter Reinholdtsen uint8_t rqdata[IPMI_I2C_MASTER_MAX_SIZE + 3];
71c18ec02fSPetter Reinholdtsen
72c18ec02fSPetter Reinholdtsen if (rsize > IPMI_I2C_MASTER_MAX_SIZE) {
73c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Master Write-Read: Too many bytes (%d) to read", rsize);
74c18ec02fSPetter Reinholdtsen return NULL;
75c18ec02fSPetter Reinholdtsen }
76c18ec02fSPetter Reinholdtsen if (wsize > IPMI_I2C_MASTER_MAX_SIZE) {
77c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Master Write-Read: Too many bytes (%d) to write", wsize);
78c18ec02fSPetter Reinholdtsen return NULL;
79c18ec02fSPetter Reinholdtsen }
80c18ec02fSPetter Reinholdtsen
81c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(struct ipmi_rq));
82c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_APP;
83c18ec02fSPetter Reinholdtsen req.msg.cmd = 0x52; /* master write-read */
84c18ec02fSPetter Reinholdtsen req.msg.data = rqdata;
85c18ec02fSPetter Reinholdtsen req.msg.data_len = 3;
86c18ec02fSPetter Reinholdtsen
87c18ec02fSPetter Reinholdtsen memset(rqdata, 0, IPMI_I2C_MASTER_MAX_SIZE + 3);
88c18ec02fSPetter Reinholdtsen rqdata[0] = bus; /* channel number, bus id, bus type */
89c18ec02fSPetter Reinholdtsen rqdata[1] = addr; /* slave address */
90c18ec02fSPetter Reinholdtsen rqdata[2] = rsize; /* number of bytes to read */
91c18ec02fSPetter Reinholdtsen
92c18ec02fSPetter Reinholdtsen if (wsize > 0) {
93c18ec02fSPetter Reinholdtsen /* copy in data to write */
94c18ec02fSPetter Reinholdtsen memcpy(rqdata+3, wdata, wsize);
95c18ec02fSPetter Reinholdtsen req.msg.data_len += wsize;
96c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Writing %d bytes to i2cdev %02Xh", wsize, addr);
97c18ec02fSPetter Reinholdtsen }
98c18ec02fSPetter Reinholdtsen
99c18ec02fSPetter Reinholdtsen if (rsize > 0) {
100c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Reading %d bytes from i2cdev %02Xh", rsize, addr);
101c18ec02fSPetter Reinholdtsen }
102c18ec02fSPetter Reinholdtsen
103c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
104c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
105c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Master Write-Read command failed");
106c18ec02fSPetter Reinholdtsen return NULL;
107c18ec02fSPetter Reinholdtsen }
108c18ec02fSPetter Reinholdtsen else if (rsp->ccode > 0) {
109c18ec02fSPetter Reinholdtsen switch (rsp->ccode) {
110c18ec02fSPetter Reinholdtsen case 0x81:
111c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Master Write-Read command failed: Lost Arbitration");
112c18ec02fSPetter Reinholdtsen break;
113c18ec02fSPetter Reinholdtsen case 0x82:
114c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Master Write-Read command failed: Bus Error");
115c18ec02fSPetter Reinholdtsen break;
116c18ec02fSPetter Reinholdtsen case 0x83:
117c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Master Write-Read command failed: NAK on Write");
118c18ec02fSPetter Reinholdtsen break;
119c18ec02fSPetter Reinholdtsen case 0x84:
120c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Master Write-Read command failed: Truncated Read");
121c18ec02fSPetter Reinholdtsen break;
122c18ec02fSPetter Reinholdtsen default:
123c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Master Write-Read command failed: %s",
124c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
125c18ec02fSPetter Reinholdtsen break;
126c18ec02fSPetter Reinholdtsen }
127c18ec02fSPetter Reinholdtsen return NULL;
128c18ec02fSPetter Reinholdtsen }
129c18ec02fSPetter Reinholdtsen
130c18ec02fSPetter Reinholdtsen return rsp;
131c18ec02fSPetter Reinholdtsen }
132c18ec02fSPetter Reinholdtsen
1330ff2d6e4SZdenek Styblik #define RAW_SPD_SIZE 512
134c18ec02fSPetter Reinholdtsen
135c18ec02fSPetter Reinholdtsen int
ipmi_rawspd_main(struct ipmi_intf * intf,int argc,char ** argv)136c18ec02fSPetter Reinholdtsen ipmi_rawspd_main(struct ipmi_intf * intf, int argc, char ** argv)
137c18ec02fSPetter Reinholdtsen {
138c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
139c18ec02fSPetter Reinholdtsen uint8_t msize = IPMI_I2C_MASTER_MAX_SIZE; /* allow to override default */
140c18ec02fSPetter Reinholdtsen uint8_t channel = 0;
141c18ec02fSPetter Reinholdtsen uint8_t i2cbus = 0;
142c18ec02fSPetter Reinholdtsen uint8_t i2caddr = 0;
143c18ec02fSPetter Reinholdtsen uint8_t spd_data[RAW_SPD_SIZE];
144c18ec02fSPetter Reinholdtsen int i;
145c18ec02fSPetter Reinholdtsen
146c18ec02fSPetter Reinholdtsen memset(spd_data, 0, RAW_SPD_SIZE);
147c18ec02fSPetter Reinholdtsen
148c18ec02fSPetter Reinholdtsen if (argc < 2 || strncmp(argv[0], "help", 4) == 0) {
149c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "usage: spd <i2cbus> <i2caddr> [channel] [maxread]");
150c18ec02fSPetter Reinholdtsen return 0;
151c18ec02fSPetter Reinholdtsen }
152c18ec02fSPetter Reinholdtsen
153c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[0], &i2cbus, "i2cbus") != 0)
154c18ec02fSPetter Reinholdtsen return (-1);
155c18ec02fSPetter Reinholdtsen
156c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[1], &i2caddr, "i2caddr") != 0)
157c18ec02fSPetter Reinholdtsen return (-1);
158c18ec02fSPetter Reinholdtsen
159c18ec02fSPetter Reinholdtsen if (argc >= 3) {
160c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[2], &channel, "channel") != 0)
161c18ec02fSPetter Reinholdtsen return (-1);
162c18ec02fSPetter Reinholdtsen }
163c18ec02fSPetter Reinholdtsen
164c18ec02fSPetter Reinholdtsen if (argc >= 4) {
165c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[3], &msize, "maxread") != 0)
166c18ec02fSPetter Reinholdtsen return (-1);
167c18ec02fSPetter Reinholdtsen }
168c18ec02fSPetter Reinholdtsen
169c18ec02fSPetter Reinholdtsen i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | 1;
170c18ec02fSPetter Reinholdtsen
171c18ec02fSPetter Reinholdtsen for (i = 0; i < RAW_SPD_SIZE; i+= msize) {
172c18ec02fSPetter Reinholdtsen rsp = ipmi_master_write_read(intf, i2cbus, i2caddr,
173c18ec02fSPetter Reinholdtsen (uint8_t *)&i, 1, msize );
174c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
175c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
176c18ec02fSPetter Reinholdtsen return -1;
177c18ec02fSPetter Reinholdtsen }
178c18ec02fSPetter Reinholdtsen
179c18ec02fSPetter Reinholdtsen memcpy(spd_data+i, rsp->data, msize);
180c18ec02fSPetter Reinholdtsen }
181c18ec02fSPetter Reinholdtsen
182c18ec02fSPetter Reinholdtsen ipmi_spd_print(spd_data, i);
183c18ec02fSPetter Reinholdtsen return 0;
184c18ec02fSPetter Reinholdtsen }
185c18ec02fSPetter Reinholdtsen
rawi2c_usage(void)186c18ec02fSPetter Reinholdtsen static void rawi2c_usage(void)
187c18ec02fSPetter Reinholdtsen {
188c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "usage: i2c [bus=public|# [chan=#] <i2caddr> <read bytes> [write data]");
189c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, " bus=public is default");
190c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, " chan=0 is default, bus= must be specified to use chan=");
191c18ec02fSPetter Reinholdtsen }
192c18ec02fSPetter Reinholdtsen
193c18ec02fSPetter Reinholdtsen int
ipmi_rawi2c_main(struct ipmi_intf * intf,int argc,char ** argv)194c18ec02fSPetter Reinholdtsen ipmi_rawi2c_main(struct ipmi_intf * intf, int argc, char ** argv)
195c18ec02fSPetter Reinholdtsen {
196c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
197c18ec02fSPetter Reinholdtsen uint8_t wdata[IPMI_I2C_MASTER_MAX_SIZE];
198c18ec02fSPetter Reinholdtsen uint8_t i2caddr = 0;
199c18ec02fSPetter Reinholdtsen uint8_t rsize = 0;
200c18ec02fSPetter Reinholdtsen uint8_t wsize = 0;
201c18ec02fSPetter Reinholdtsen unsigned int rbus = 0;
202c18ec02fSPetter Reinholdtsen uint8_t bus = 0;
203c18ec02fSPetter Reinholdtsen int i = 0;
204c18ec02fSPetter Reinholdtsen
205c18ec02fSPetter Reinholdtsen /* handle bus= argument */
206c18ec02fSPetter Reinholdtsen if (argc > 2 && strncmp(argv[0], "bus=", 4) == 0) {
207c18ec02fSPetter Reinholdtsen i = 1;
208c18ec02fSPetter Reinholdtsen if (strncmp(argv[0], "bus=public", 10) == 0)
209c18ec02fSPetter Reinholdtsen bus = 0;
210c18ec02fSPetter Reinholdtsen else if (sscanf(argv[0], "bus=%u", &rbus) == 1)
211c18ec02fSPetter Reinholdtsen bus = ((rbus & 7) << 1) | 1;
212c18ec02fSPetter Reinholdtsen else
213c18ec02fSPetter Reinholdtsen bus = 0;
214c18ec02fSPetter Reinholdtsen
215c18ec02fSPetter Reinholdtsen /* handle channel= argument
216c18ec02fSPetter Reinholdtsen * the bus= argument must be supplied first on command line */
217c18ec02fSPetter Reinholdtsen if (argc > 3 && strncmp(argv[1], "chan=", 5) == 0) {
218c18ec02fSPetter Reinholdtsen i = 2;
219c18ec02fSPetter Reinholdtsen if (sscanf(argv[1], "chan=%u", &rbus) == 1)
220c18ec02fSPetter Reinholdtsen bus |= rbus << 4;
221c18ec02fSPetter Reinholdtsen }
222c18ec02fSPetter Reinholdtsen }
223c18ec02fSPetter Reinholdtsen
224c18ec02fSPetter Reinholdtsen if ((argc-i) < 2 || strncmp(argv[0], "help", 4) == 0) {
225c18ec02fSPetter Reinholdtsen rawi2c_usage();
226c18ec02fSPetter Reinholdtsen return 0;
227c18ec02fSPetter Reinholdtsen }
228c18ec02fSPetter Reinholdtsen else if (argc-i-2 > IPMI_I2C_MASTER_MAX_SIZE) {
229c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Raw command input limit (%d bytes) exceeded",
230c18ec02fSPetter Reinholdtsen IPMI_I2C_MASTER_MAX_SIZE);
231c18ec02fSPetter Reinholdtsen return -1;
232c18ec02fSPetter Reinholdtsen }
233c18ec02fSPetter Reinholdtsen
234c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[i++], &i2caddr, "i2caddr") != 0)
235c18ec02fSPetter Reinholdtsen return (-1);
236c18ec02fSPetter Reinholdtsen
237c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[i++], &rsize, "read size") != 0)
238c18ec02fSPetter Reinholdtsen return (-1);
239c18ec02fSPetter Reinholdtsen
240c18ec02fSPetter Reinholdtsen if (i2caddr == 0) {
241c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid I2C address 0");
242c18ec02fSPetter Reinholdtsen rawi2c_usage();
243c18ec02fSPetter Reinholdtsen return -1;
244c18ec02fSPetter Reinholdtsen }
245c18ec02fSPetter Reinholdtsen
246c18ec02fSPetter Reinholdtsen memset(wdata, 0, IPMI_I2C_MASTER_MAX_SIZE);
247c18ec02fSPetter Reinholdtsen for (; i < argc; i++) {
248c18ec02fSPetter Reinholdtsen uint8_t val = 0;
249c18ec02fSPetter Reinholdtsen
250c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[i], &val, "parameter") != 0)
251c18ec02fSPetter Reinholdtsen return (-1);
252c18ec02fSPetter Reinholdtsen
253c18ec02fSPetter Reinholdtsen wdata[wsize] = val;
254c18ec02fSPetter Reinholdtsen wsize++;
255c18ec02fSPetter Reinholdtsen }
256c18ec02fSPetter Reinholdtsen
257c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "RAW I2C REQ (i2caddr=%x readbytes=%d writebytes=%d)",
258c18ec02fSPetter Reinholdtsen i2caddr, rsize, wsize);
259c18ec02fSPetter Reinholdtsen printbuf(wdata, wsize, "WRITE DATA");
260c18ec02fSPetter Reinholdtsen
261c18ec02fSPetter Reinholdtsen rsp = ipmi_master_write_read(intf, bus, i2caddr, wdata, wsize, rsize);
262c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
263c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
264c18ec02fSPetter Reinholdtsen return -1;
265c18ec02fSPetter Reinholdtsen }
266c18ec02fSPetter Reinholdtsen
267c18ec02fSPetter Reinholdtsen if (wsize > 0) {
268c18ec02fSPetter Reinholdtsen if (verbose || rsize == 0)
269c18ec02fSPetter Reinholdtsen printf("Wrote %d bytes to I2C device %02Xh\n", wsize, i2caddr);
270c18ec02fSPetter Reinholdtsen }
271c18ec02fSPetter Reinholdtsen
272c18ec02fSPetter Reinholdtsen if (rsize > 0) {
273c18ec02fSPetter Reinholdtsen if (verbose || wsize == 0)
274c18ec02fSPetter Reinholdtsen printf("Read %d bytes from I2C device %02Xh\n", rsp->data_len, i2caddr);
275c18ec02fSPetter Reinholdtsen
276c18ec02fSPetter Reinholdtsen if (rsp->data_len < rsize)
277c18ec02fSPetter Reinholdtsen return -1;
278c18ec02fSPetter Reinholdtsen
279c18ec02fSPetter Reinholdtsen /* print the raw response buffer */
280c18ec02fSPetter Reinholdtsen for (i=0; i<rsp->data_len; i++) {
281c18ec02fSPetter Reinholdtsen if (((i%16) == 0) && (i != 0))
282c18ec02fSPetter Reinholdtsen printf("\n");
283c18ec02fSPetter Reinholdtsen printf(" %2.2x", rsp->data[i]);
284c18ec02fSPetter Reinholdtsen }
285c18ec02fSPetter Reinholdtsen printf("\n");
286c18ec02fSPetter Reinholdtsen
287c18ec02fSPetter Reinholdtsen if (rsp->data_len <= 4) {
288c18ec02fSPetter Reinholdtsen uint32_t bit;
289c18ec02fSPetter Reinholdtsen int j;
290c18ec02fSPetter Reinholdtsen for (i = 0; i < rsp->data_len; i++) {
291c18ec02fSPetter Reinholdtsen for (j = 1, bit = 0x80; bit > 0; bit /= 2, j++) {
292c18ec02fSPetter Reinholdtsen printf("%s", (rsp->data[i] & bit) ? "1" : "0");
293c18ec02fSPetter Reinholdtsen }
294c18ec02fSPetter Reinholdtsen printf(" ");
295c18ec02fSPetter Reinholdtsen }
296c18ec02fSPetter Reinholdtsen printf("\n");
297c18ec02fSPetter Reinholdtsen }
298c18ec02fSPetter Reinholdtsen }
299c18ec02fSPetter Reinholdtsen
300c18ec02fSPetter Reinholdtsen return 0;
301c18ec02fSPetter Reinholdtsen }
302c18ec02fSPetter Reinholdtsen
303c18ec02fSPetter Reinholdtsen /* ipmi_raw_help() - print 'raw' help text
304c18ec02fSPetter Reinholdtsen *
305c18ec02fSPetter Reinholdtsen * returns void
306c18ec02fSPetter Reinholdtsen */
307c18ec02fSPetter Reinholdtsen void
ipmi_raw_help()308c18ec02fSPetter Reinholdtsen ipmi_raw_help()
309c18ec02fSPetter Reinholdtsen {
310c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "RAW Commands: raw <netfn> <cmd> [data]");
311c18ec02fSPetter Reinholdtsen print_valstr(ipmi_netfn_vals, "Network Function Codes", LOG_NOTICE);
312c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "(can also use raw hex values)");
313c18ec02fSPetter Reinholdtsen } /* ipmi_raw_help() */
314c18ec02fSPetter Reinholdtsen
315c18ec02fSPetter Reinholdtsen int
ipmi_raw_main(struct ipmi_intf * intf,int argc,char ** argv)316c18ec02fSPetter Reinholdtsen ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv)
317c18ec02fSPetter Reinholdtsen {
318c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
319c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
320c18ec02fSPetter Reinholdtsen uint8_t netfn, cmd, lun;
321c18ec02fSPetter Reinholdtsen uint16_t netfn_tmp = 0;
322c18ec02fSPetter Reinholdtsen int i;
323c18ec02fSPetter Reinholdtsen uint8_t data[256];
324c18ec02fSPetter Reinholdtsen
325c18ec02fSPetter Reinholdtsen if (argc == 1 && strncmp(argv[0], "help", 4) == 0) {
326c18ec02fSPetter Reinholdtsen ipmi_raw_help();
327c18ec02fSPetter Reinholdtsen return 0;
328c18ec02fSPetter Reinholdtsen }
329c18ec02fSPetter Reinholdtsen else if (argc < 2) {
330c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
331c18ec02fSPetter Reinholdtsen ipmi_raw_help();
332c18ec02fSPetter Reinholdtsen return (-1);
333c18ec02fSPetter Reinholdtsen }
334c18ec02fSPetter Reinholdtsen else if (argc > sizeof(data))
335c18ec02fSPetter Reinholdtsen {
336c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Raw command input limit (256 bytes) exceeded");
337c18ec02fSPetter Reinholdtsen return -1;
338c18ec02fSPetter Reinholdtsen }
339c18ec02fSPetter Reinholdtsen
340c18ec02fSPetter Reinholdtsen lun = intf->target_lun;
341c18ec02fSPetter Reinholdtsen netfn_tmp = str2val(argv[0], ipmi_netfn_vals);
342c18ec02fSPetter Reinholdtsen if (netfn_tmp == 0xff) {
343c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[0], &netfn, "netfn") != 0)
344c18ec02fSPetter Reinholdtsen return (-1);
345c18ec02fSPetter Reinholdtsen } else {
346c18ec02fSPetter Reinholdtsen if (netfn_tmp >= UINT8_MAX) {
347c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Given netfn \"%s\" is out of range.", argv[0]);
348c18ec02fSPetter Reinholdtsen return (-1);
349c18ec02fSPetter Reinholdtsen }
350c18ec02fSPetter Reinholdtsen netfn = netfn_tmp;
351c18ec02fSPetter Reinholdtsen }
352c18ec02fSPetter Reinholdtsen
353c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[1], &cmd, "command") != 0)
354c18ec02fSPetter Reinholdtsen return (-1);
355c18ec02fSPetter Reinholdtsen
356c18ec02fSPetter Reinholdtsen memset(data, 0, sizeof(data));
357c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
358c18ec02fSPetter Reinholdtsen req.msg.netfn = netfn;
359c18ec02fSPetter Reinholdtsen req.msg.lun = lun;
360c18ec02fSPetter Reinholdtsen req.msg.cmd = cmd;
361c18ec02fSPetter Reinholdtsen req.msg.data = data;
362c18ec02fSPetter Reinholdtsen
363c18ec02fSPetter Reinholdtsen for (i=2; i<argc; i++) {
364c18ec02fSPetter Reinholdtsen uint8_t val = 0;
365c18ec02fSPetter Reinholdtsen
366c18ec02fSPetter Reinholdtsen if (is_valid_param(argv[i], &val, "data") != 0)
367c18ec02fSPetter Reinholdtsen return (-1);
368c18ec02fSPetter Reinholdtsen
369c18ec02fSPetter Reinholdtsen req.msg.data[i-2] = val;
370c18ec02fSPetter Reinholdtsen req.msg.data_len++;
371c18ec02fSPetter Reinholdtsen }
372c18ec02fSPetter Reinholdtsen
373c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,
374c18ec02fSPetter Reinholdtsen "RAW REQ (channel=0x%x netfn=0x%x lun=0x%x cmd=0x%x data_len=%d)",
375c18ec02fSPetter Reinholdtsen intf->target_channel & 0x0f, req.msg.netfn,req.msg.lun ,
376c18ec02fSPetter Reinholdtsen req.msg.cmd, req.msg.data_len);
377c18ec02fSPetter Reinholdtsen
378c18ec02fSPetter Reinholdtsen printbuf(req.msg.data, req.msg.data_len, "RAW REQUEST");
379c18ec02fSPetter Reinholdtsen
380c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
381c18ec02fSPetter Reinholdtsen
382c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
383c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to send RAW command "
384c18ec02fSPetter Reinholdtsen "(channel=0x%x netfn=0x%x lun=0x%x cmd=0x%x)",
385c18ec02fSPetter Reinholdtsen intf->target_channel & 0x0f, req.msg.netfn, req.msg.lun, req.msg.cmd);
386c18ec02fSPetter Reinholdtsen return -1;
387c18ec02fSPetter Reinholdtsen }
388c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
389c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to send RAW command "
390c18ec02fSPetter Reinholdtsen "(channel=0x%x netfn=0x%x lun=0x%x cmd=0x%x rsp=0x%x): %s",
391c18ec02fSPetter Reinholdtsen intf->target_channel & 0x0f, req.msg.netfn, req.msg.lun, req.msg.cmd, rsp->ccode,
392c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
393c18ec02fSPetter Reinholdtsen return -1;
394c18ec02fSPetter Reinholdtsen }
395c18ec02fSPetter Reinholdtsen
396c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "RAW RSP (%d bytes)", rsp->data_len);
397c18ec02fSPetter Reinholdtsen
398c18ec02fSPetter Reinholdtsen /* print the raw response buffer */
399c18ec02fSPetter Reinholdtsen for (i=0; i<rsp->data_len; i++) {
400c18ec02fSPetter Reinholdtsen if (((i%16) == 0) && (i != 0))
401c18ec02fSPetter Reinholdtsen printf("\n");
402c18ec02fSPetter Reinholdtsen printf(" %2.2x", rsp->data[i]);
403c18ec02fSPetter Reinholdtsen }
404c18ec02fSPetter Reinholdtsen printf("\n");
405c18ec02fSPetter Reinholdtsen
406c18ec02fSPetter Reinholdtsen return 0;
407c18ec02fSPetter Reinholdtsen }
408c18ec02fSPetter Reinholdtsen
409c18ec02fSPetter Reinholdtsen /* is_valid_param -
410c18ec02fSPetter Reinholdtsen *
411c18ec02fSPetter Reinholdtsen * @input_param: string to convert from
412c18ec02fSPetter Reinholdtsen * @uchr_ptr: pointer where to store converted value
413c18ec02fSPetter Reinholdtsen * @label: string used in error message
414c18ec02fSPetter Reinholdtsen *
415c18ec02fSPetter Reinholdtsen * returns 0 if parameter is valid
416c18ec02fSPetter Reinholdtsen * returns (-1) if parameter is invalid/on error
417c18ec02fSPetter Reinholdtsen */
418c18ec02fSPetter Reinholdtsen int
is_valid_param(const char * input_param,uint8_t * uchr_ptr,const char * label)419c18ec02fSPetter Reinholdtsen is_valid_param(const char *input_param, uint8_t *uchr_ptr, const char *label) {
420c18ec02fSPetter Reinholdtsen if (input_param == NULL || label == NULL) {
421c18ec02fSPetter Reinholdtsen lprintf(LOG_ERROR, "ERROR: NULL pointer passed.");
422c18ec02fSPetter Reinholdtsen return (-1);
423c18ec02fSPetter Reinholdtsen }
424c18ec02fSPetter Reinholdtsen if (str2uchar(input_param, uchr_ptr) == 0)
425c18ec02fSPetter Reinholdtsen return 0;
426c18ec02fSPetter Reinholdtsen
427c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Given %s \"%s\" is invalid.", label, input_param);
428c18ec02fSPetter Reinholdtsen return (-1);
429c18ec02fSPetter Reinholdtsen }
430