1*c18ec02fSPetter Reinholdtsen /*
2*c18ec02fSPetter Reinholdtsen * Copyright (c) 2003 Kontron Canada, Inc. All Rights Reserved.
3*c18ec02fSPetter Reinholdtsen *
4*c18ec02fSPetter Reinholdtsen * Redistribution and use in source and binary forms, with or without
5*c18ec02fSPetter Reinholdtsen * modification, are permitted provided that the following conditions
6*c18ec02fSPetter Reinholdtsen * are met:
7*c18ec02fSPetter Reinholdtsen *
8*c18ec02fSPetter Reinholdtsen * Redistribution of source code must retain the above copyright
9*c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer.
10*c18ec02fSPetter Reinholdtsen *
11*c18ec02fSPetter Reinholdtsen * Redistribution in binary form must reproduce the above copyright
12*c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer in the
13*c18ec02fSPetter Reinholdtsen * documentation and/or other materials provided with the distribution.
14*c18ec02fSPetter Reinholdtsen *
15*c18ec02fSPetter Reinholdtsen * Neither the name of Sun Microsystems, Inc. or the names of
16*c18ec02fSPetter Reinholdtsen * contributors may be used to endorse or promote products derived
17*c18ec02fSPetter Reinholdtsen * from this software without specific prior written permission.
18*c18ec02fSPetter Reinholdtsen *
19*c18ec02fSPetter Reinholdtsen * This software is provided "AS IS," without a warranty of any kind.
20*c18ec02fSPetter Reinholdtsen * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21*c18ec02fSPetter Reinholdtsen * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22*c18ec02fSPetter Reinholdtsen * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23*c18ec02fSPetter Reinholdtsen * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24*c18ec02fSPetter Reinholdtsen * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25*c18ec02fSPetter Reinholdtsen * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26*c18ec02fSPetter Reinholdtsen * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27*c18ec02fSPetter Reinholdtsen * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28*c18ec02fSPetter Reinholdtsen * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29*c18ec02fSPetter Reinholdtsen * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30*c18ec02fSPetter Reinholdtsen * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31*c18ec02fSPetter Reinholdtsen */
32*c18ec02fSPetter Reinholdtsen
33*c18ec02fSPetter Reinholdtsen #include <string.h>
34*c18ec02fSPetter Reinholdtsen
35*c18ec02fSPetter Reinholdtsen #include <math.h>
36*c18ec02fSPetter Reinholdtsen #include <stdio.h>
37*c18ec02fSPetter Reinholdtsen #include <unistd.h>
38*c18ec02fSPetter Reinholdtsen #include <sys/types.h>
39*c18ec02fSPetter Reinholdtsen #include <time.h>
40*c18ec02fSPetter Reinholdtsen
41*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
42*c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
43*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_mc.h>
44*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sdr.h>
45*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_gendev.h>
46*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
47*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sel.h>
48*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_entity.h>
49*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_constants.h>
50*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
51*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_raw.h>
52*c18ec02fSPetter Reinholdtsen
53*c18ec02fSPetter Reinholdtsen #if HAVE_CONFIG_H
54*c18ec02fSPetter Reinholdtsen # include <config.h>
55*c18ec02fSPetter Reinholdtsen #endif
56*c18ec02fSPetter Reinholdtsen
57*c18ec02fSPetter Reinholdtsen extern int verbose;
58*c18ec02fSPetter Reinholdtsen
59*c18ec02fSPetter Reinholdtsen
60*c18ec02fSPetter Reinholdtsen #define GENDEV_RETRY_COUNT 5
61*c18ec02fSPetter Reinholdtsen #define GENDEV_MAX_SIZE 16
62*c18ec02fSPetter Reinholdtsen
63*c18ec02fSPetter Reinholdtsen typedef struct gendev_eeprom_info
64*c18ec02fSPetter Reinholdtsen {
65*c18ec02fSPetter Reinholdtsen uint32_t size;
66*c18ec02fSPetter Reinholdtsen uint16_t page_size;
67*c18ec02fSPetter Reinholdtsen uint8_t address_span;
68*c18ec02fSPetter Reinholdtsen uint8_t address_length;
69*c18ec02fSPetter Reinholdtsen }t_gendev_eeprom_info;
70*c18ec02fSPetter Reinholdtsen
71*c18ec02fSPetter Reinholdtsen
72*c18ec02fSPetter Reinholdtsen static int
ipmi_gendev_get_eeprom_size(struct ipmi_intf * intf,struct sdr_record_generic_locator * dev,t_gendev_eeprom_info * info)73*c18ec02fSPetter Reinholdtsen ipmi_gendev_get_eeprom_size(
74*c18ec02fSPetter Reinholdtsen struct ipmi_intf *intf,
75*c18ec02fSPetter Reinholdtsen struct sdr_record_generic_locator *dev,
76*c18ec02fSPetter Reinholdtsen t_gendev_eeprom_info *info
77*c18ec02fSPetter Reinholdtsen )
78*c18ec02fSPetter Reinholdtsen {
79*c18ec02fSPetter Reinholdtsen int eeprom_size = 0;
80*c18ec02fSPetter Reinholdtsen /*
81*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Gen Device : %s", dev->id_string);
82*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Access Addr: %x", dev->dev_access_addr);
83*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Slave Addr : %x", dev->dev_slave_addr);
84*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Channel Num: %x", dev->channel_num);
85*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Lun : %x", dev->lun);
86*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Bus : %x", dev->bus);
87*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Addr Span : %x", dev->addr_span);
88*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "DevType : %x", dev->dev_type);
89*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "DevType Mod: %x", dev->dev_type_modifier);
90*c18ec02fSPetter Reinholdtsen */
91*c18ec02fSPetter Reinholdtsen if( info != NULL)
92*c18ec02fSPetter Reinholdtsen {
93*c18ec02fSPetter Reinholdtsen switch(dev->dev_type)
94*c18ec02fSPetter Reinholdtsen {
95*c18ec02fSPetter Reinholdtsen case 0x08: // 24C01
96*c18ec02fSPetter Reinholdtsen info->size = 128;
97*c18ec02fSPetter Reinholdtsen info->page_size = 8;
98*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
99*c18ec02fSPetter Reinholdtsen info->address_length = 1;
100*c18ec02fSPetter Reinholdtsen break;
101*c18ec02fSPetter Reinholdtsen case 0x09: // 24C02
102*c18ec02fSPetter Reinholdtsen info->size = 256;
103*c18ec02fSPetter Reinholdtsen info->page_size = 8;
104*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
105*c18ec02fSPetter Reinholdtsen info->address_length = 1;
106*c18ec02fSPetter Reinholdtsen break;
107*c18ec02fSPetter Reinholdtsen case 0x0A: // 24C04
108*c18ec02fSPetter Reinholdtsen info->size = 512;
109*c18ec02fSPetter Reinholdtsen info->page_size = 8;
110*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
111*c18ec02fSPetter Reinholdtsen info->address_length = 2;
112*c18ec02fSPetter Reinholdtsen break;
113*c18ec02fSPetter Reinholdtsen case 0x0B: // 24C08
114*c18ec02fSPetter Reinholdtsen info->size = 1024;
115*c18ec02fSPetter Reinholdtsen info->page_size = 8;
116*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
117*c18ec02fSPetter Reinholdtsen info->address_length = 2;
118*c18ec02fSPetter Reinholdtsen break;
119*c18ec02fSPetter Reinholdtsen case 0x0C: // 24C16
120*c18ec02fSPetter Reinholdtsen info->size = 2048;
121*c18ec02fSPetter Reinholdtsen info->page_size = 256;
122*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
123*c18ec02fSPetter Reinholdtsen info->address_length = 2;
124*c18ec02fSPetter Reinholdtsen break;
125*c18ec02fSPetter Reinholdtsen case 0x0D: // 24C17
126*c18ec02fSPetter Reinholdtsen info->size = 2048;
127*c18ec02fSPetter Reinholdtsen info->page_size = 256;
128*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
129*c18ec02fSPetter Reinholdtsen info->address_length = 2;
130*c18ec02fSPetter Reinholdtsen break;
131*c18ec02fSPetter Reinholdtsen case 0x0E: // 24C32
132*c18ec02fSPetter Reinholdtsen info->size = 4096;
133*c18ec02fSPetter Reinholdtsen info->page_size = 8;
134*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
135*c18ec02fSPetter Reinholdtsen info->address_length = 2;
136*c18ec02fSPetter Reinholdtsen break;
137*c18ec02fSPetter Reinholdtsen case 0x0F: // 24C64
138*c18ec02fSPetter Reinholdtsen info->size = 8192;
139*c18ec02fSPetter Reinholdtsen info->page_size = 32;
140*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
141*c18ec02fSPetter Reinholdtsen info->address_length = 2;
142*c18ec02fSPetter Reinholdtsen break;
143*c18ec02fSPetter Reinholdtsen case 0xC0: // Proposed OEM Code for 24C128
144*c18ec02fSPetter Reinholdtsen info->size = 16384;
145*c18ec02fSPetter Reinholdtsen info->page_size = 64;
146*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
147*c18ec02fSPetter Reinholdtsen info->address_length = 2;
148*c18ec02fSPetter Reinholdtsen break;
149*c18ec02fSPetter Reinholdtsen case 0xC1: // Proposed OEM Code for 24C256
150*c18ec02fSPetter Reinholdtsen info->size = 32748;
151*c18ec02fSPetter Reinholdtsen info->page_size = 64;
152*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
153*c18ec02fSPetter Reinholdtsen info->address_length = 2;
154*c18ec02fSPetter Reinholdtsen break;
155*c18ec02fSPetter Reinholdtsen case 0xC2: // Proposed OEM Code for 24C512
156*c18ec02fSPetter Reinholdtsen info->size = 65536;
157*c18ec02fSPetter Reinholdtsen info->page_size = 128;
158*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
159*c18ec02fSPetter Reinholdtsen info->address_length = 2;
160*c18ec02fSPetter Reinholdtsen break;
161*c18ec02fSPetter Reinholdtsen case 0xC3: // Proposed OEM Code for 24C1024
162*c18ec02fSPetter Reinholdtsen info->size = 131072;
163*c18ec02fSPetter Reinholdtsen info->page_size = 128;
164*c18ec02fSPetter Reinholdtsen info->address_span = dev->addr_span;
165*c18ec02fSPetter Reinholdtsen info->address_length = 2;
166*c18ec02fSPetter Reinholdtsen break;
167*c18ec02fSPetter Reinholdtsen /* Please reserved up to CFh for future update */
168*c18ec02fSPetter Reinholdtsen default: // Not a eeprom, return size = 0;
169*c18ec02fSPetter Reinholdtsen info->size = 0;
170*c18ec02fSPetter Reinholdtsen info->page_size = 0;
171*c18ec02fSPetter Reinholdtsen info->address_span = 0;
172*c18ec02fSPetter Reinholdtsen info->address_length = 0;
173*c18ec02fSPetter Reinholdtsen break;
174*c18ec02fSPetter Reinholdtsen }
175*c18ec02fSPetter Reinholdtsen
176*c18ec02fSPetter Reinholdtsen eeprom_size = info->size;
177*c18ec02fSPetter Reinholdtsen }
178*c18ec02fSPetter Reinholdtsen
179*c18ec02fSPetter Reinholdtsen return eeprom_size;
180*c18ec02fSPetter Reinholdtsen }
181*c18ec02fSPetter Reinholdtsen
182*c18ec02fSPetter Reinholdtsen
183*c18ec02fSPetter Reinholdtsen
184*c18ec02fSPetter Reinholdtsen static int
ipmi_gendev_read_file(struct ipmi_intf * intf,struct sdr_record_generic_locator * dev,const char * ofile)185*c18ec02fSPetter Reinholdtsen ipmi_gendev_read_file(
186*c18ec02fSPetter Reinholdtsen struct ipmi_intf *intf,
187*c18ec02fSPetter Reinholdtsen struct sdr_record_generic_locator *dev,
188*c18ec02fSPetter Reinholdtsen const char *ofile
189*c18ec02fSPetter Reinholdtsen )
190*c18ec02fSPetter Reinholdtsen {
191*c18ec02fSPetter Reinholdtsen int rc = 0;
192*c18ec02fSPetter Reinholdtsen int eeprom_size;
193*c18ec02fSPetter Reinholdtsen t_gendev_eeprom_info eeprom_info;
194*c18ec02fSPetter Reinholdtsen
195*c18ec02fSPetter Reinholdtsen eeprom_size = ipmi_gendev_get_eeprom_size(intf, dev, &eeprom_info);
196*c18ec02fSPetter Reinholdtsen
197*c18ec02fSPetter Reinholdtsen if(eeprom_size > 0)
198*c18ec02fSPetter Reinholdtsen {
199*c18ec02fSPetter Reinholdtsen FILE *fp;
200*c18ec02fSPetter Reinholdtsen
201*c18ec02fSPetter Reinholdtsen /* now write to file */
202*c18ec02fSPetter Reinholdtsen fp = ipmi_open_file_write(ofile);
203*c18ec02fSPetter Reinholdtsen
204*c18ec02fSPetter Reinholdtsen if(fp)
205*c18ec02fSPetter Reinholdtsen {
206*c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
207*c18ec02fSPetter Reinholdtsen int numWrite;
208*c18ec02fSPetter Reinholdtsen uint32_t counter;
209*c18ec02fSPetter Reinholdtsen uint8_t msize;
210*c18ec02fSPetter Reinholdtsen uint8_t channel = dev->channel_num;
211*c18ec02fSPetter Reinholdtsen uint8_t i2cbus = dev->bus;
212*c18ec02fSPetter Reinholdtsen uint8_t i2caddr = dev->dev_slave_addr;
213*c18ec02fSPetter Reinholdtsen uint8_t privatebus = 1;
214*c18ec02fSPetter Reinholdtsen uint32_t address_span_size;
215*c18ec02fSPetter Reinholdtsen uint8_t percentCompleted = 0;
216*c18ec02fSPetter Reinholdtsen
217*c18ec02fSPetter Reinholdtsen
218*c18ec02fSPetter Reinholdtsen /* Handle Address Span */
219*c18ec02fSPetter Reinholdtsen if( eeprom_info.address_span != 0)
220*c18ec02fSPetter Reinholdtsen {
221*c18ec02fSPetter Reinholdtsen address_span_size =
222*c18ec02fSPetter Reinholdtsen (eeprom_info.size / (eeprom_info.address_span+1));
223*c18ec02fSPetter Reinholdtsen }
224*c18ec02fSPetter Reinholdtsen else
225*c18ec02fSPetter Reinholdtsen {
226*c18ec02fSPetter Reinholdtsen address_span_size = eeprom_info.size;
227*c18ec02fSPetter Reinholdtsen }
228*c18ec02fSPetter Reinholdtsen
229*c18ec02fSPetter Reinholdtsen /* Setup read/write size */
230*c18ec02fSPetter Reinholdtsen if( eeprom_info.page_size < GENDEV_MAX_SIZE)
231*c18ec02fSPetter Reinholdtsen {
232*c18ec02fSPetter Reinholdtsen msize = eeprom_info.page_size;
233*c18ec02fSPetter Reinholdtsen }
234*c18ec02fSPetter Reinholdtsen else
235*c18ec02fSPetter Reinholdtsen {
236*c18ec02fSPetter Reinholdtsen msize = GENDEV_MAX_SIZE;
237*c18ec02fSPetter Reinholdtsen // All eeprom with page higher than 32 is on the
238*c18ec02fSPetter Reinholdtsen // 16 bytes boundary
239*c18ec02fSPetter Reinholdtsen }
240*c18ec02fSPetter Reinholdtsen
241*c18ec02fSPetter Reinholdtsen /* Setup i2c bus byte */
242*c18ec02fSPetter Reinholdtsen i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | privatebus;
243*c18ec02fSPetter Reinholdtsen
244*c18ec02fSPetter Reinholdtsen /*
245*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Generic device: %s", dev->id_string);
246*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Chnl: %x", channel);
247*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Bus : %x", i2cbus);
248*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Addr: %x", i2caddr); */
249*c18ec02fSPetter Reinholdtsen
250*c18ec02fSPetter Reinholdtsen for (
251*c18ec02fSPetter Reinholdtsen counter = 0;
252*c18ec02fSPetter Reinholdtsen (counter < (eeprom_info.size)) && (rc == 0);
253*c18ec02fSPetter Reinholdtsen counter+= msize
254*c18ec02fSPetter Reinholdtsen )
255*c18ec02fSPetter Reinholdtsen {
256*c18ec02fSPetter Reinholdtsen uint8_t retryCounter;
257*c18ec02fSPetter Reinholdtsen
258*c18ec02fSPetter Reinholdtsen for(
259*c18ec02fSPetter Reinholdtsen retryCounter = 0;
260*c18ec02fSPetter Reinholdtsen retryCounter<GENDEV_RETRY_COUNT;
261*c18ec02fSPetter Reinholdtsen retryCounter ++
262*c18ec02fSPetter Reinholdtsen )
263*c18ec02fSPetter Reinholdtsen {
264*c18ec02fSPetter Reinholdtsen uint8_t wrByte[GENDEV_MAX_SIZE+2];
265*c18ec02fSPetter Reinholdtsen
266*c18ec02fSPetter Reinholdtsen wrByte[0] = (uint8_t) (counter>>0);
267*c18ec02fSPetter Reinholdtsen if(eeprom_info.address_length > 1)
268*c18ec02fSPetter Reinholdtsen {
269*c18ec02fSPetter Reinholdtsen wrByte[1] = (uint8_t) (counter>>8);
270*c18ec02fSPetter Reinholdtsen }
271*c18ec02fSPetter Reinholdtsen
272*c18ec02fSPetter Reinholdtsen i2caddr+= (((eeprom_info.size) % address_span_size) * 2);
273*c18ec02fSPetter Reinholdtsen
274*c18ec02fSPetter Reinholdtsen rsp = ipmi_master_write_read(
275*c18ec02fSPetter Reinholdtsen intf,
276*c18ec02fSPetter Reinholdtsen i2cbus,
277*c18ec02fSPetter Reinholdtsen i2caddr,
278*c18ec02fSPetter Reinholdtsen (uint8_t *) wrByte,
279*c18ec02fSPetter Reinholdtsen eeprom_info.address_length,
280*c18ec02fSPetter Reinholdtsen msize
281*c18ec02fSPetter Reinholdtsen );
282*c18ec02fSPetter Reinholdtsen
283*c18ec02fSPetter Reinholdtsen if (rsp != NULL)
284*c18ec02fSPetter Reinholdtsen {
285*c18ec02fSPetter Reinholdtsen retryCounter = GENDEV_RETRY_COUNT;
286*c18ec02fSPetter Reinholdtsen rc = 0;
287*c18ec02fSPetter Reinholdtsen }
288*c18ec02fSPetter Reinholdtsen else if(retryCounter < GENDEV_RETRY_COUNT)
289*c18ec02fSPetter Reinholdtsen {
290*c18ec02fSPetter Reinholdtsen retryCounter ++;
291*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Retry");
292*c18ec02fSPetter Reinholdtsen sleep(1);
293*c18ec02fSPetter Reinholdtsen rc = -1;
294*c18ec02fSPetter Reinholdtsen }
295*c18ec02fSPetter Reinholdtsen else
296*c18ec02fSPetter Reinholdtsen {
297*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
298*c18ec02fSPetter Reinholdtsen rc = -1;
299*c18ec02fSPetter Reinholdtsen }
300*c18ec02fSPetter Reinholdtsen }
301*c18ec02fSPetter Reinholdtsen
302*c18ec02fSPetter Reinholdtsen if( rc == 0 )
303*c18ec02fSPetter Reinholdtsen {
304*c18ec02fSPetter Reinholdtsen static uint8_t previousCompleted = 101;
305*c18ec02fSPetter Reinholdtsen numWrite = fwrite(rsp->data, 1, msize, fp);
306*c18ec02fSPetter Reinholdtsen if (numWrite != msize)
307*c18ec02fSPetter Reinholdtsen {
308*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error writing file %s", ofile);
309*c18ec02fSPetter Reinholdtsen rc = -1;
310*c18ec02fSPetter Reinholdtsen break;
311*c18ec02fSPetter Reinholdtsen }
312*c18ec02fSPetter Reinholdtsen
313*c18ec02fSPetter Reinholdtsen percentCompleted = ((counter * 100) / eeprom_info.size );
314*c18ec02fSPetter Reinholdtsen
315*c18ec02fSPetter Reinholdtsen if(percentCompleted != previousCompleted)
316*c18ec02fSPetter Reinholdtsen {
317*c18ec02fSPetter Reinholdtsen printf("\r%i percent completed", percentCompleted);
318*c18ec02fSPetter Reinholdtsen previousCompleted = percentCompleted;
319*c18ec02fSPetter Reinholdtsen }
320*c18ec02fSPetter Reinholdtsen
321*c18ec02fSPetter Reinholdtsen
322*c18ec02fSPetter Reinholdtsen }
323*c18ec02fSPetter Reinholdtsen }
324*c18ec02fSPetter Reinholdtsen if(counter == (eeprom_info.size))
325*c18ec02fSPetter Reinholdtsen {
326*c18ec02fSPetter Reinholdtsen printf("\r%%100 percent completed\n");
327*c18ec02fSPetter Reinholdtsen }
328*c18ec02fSPetter Reinholdtsen else
329*c18ec02fSPetter Reinholdtsen {
330*c18ec02fSPetter Reinholdtsen printf("\rError: %i percent completed, read not completed \n", percentCompleted);
331*c18ec02fSPetter Reinholdtsen }
332*c18ec02fSPetter Reinholdtsen
333*c18ec02fSPetter Reinholdtsen fclose(fp);
334*c18ec02fSPetter Reinholdtsen }
335*c18ec02fSPetter Reinholdtsen }
336*c18ec02fSPetter Reinholdtsen else
337*c18ec02fSPetter Reinholdtsen {
338*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "The selected generic device is not an eeprom");
339*c18ec02fSPetter Reinholdtsen }
340*c18ec02fSPetter Reinholdtsen
341*c18ec02fSPetter Reinholdtsen return rc;
342*c18ec02fSPetter Reinholdtsen }
343*c18ec02fSPetter Reinholdtsen
344*c18ec02fSPetter Reinholdtsen
345*c18ec02fSPetter Reinholdtsen /* ipmi_gendev_write_file - Read raw SDR from binary file
346*c18ec02fSPetter Reinholdtsen *
347*c18ec02fSPetter Reinholdtsen * used for writing generic locator device Eeprom type
348*c18ec02fSPetter Reinholdtsen *
349*c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
350*c18ec02fSPetter Reinholdtsen * @dev: generic device to read
351*c18ec02fSPetter Reinholdtsen * @ofile: output filename
352*c18ec02fSPetter Reinholdtsen *
353*c18ec02fSPetter Reinholdtsen * returns 0 on success
354*c18ec02fSPetter Reinholdtsen * returns -1 on error
355*c18ec02fSPetter Reinholdtsen */
356*c18ec02fSPetter Reinholdtsen static int
ipmi_gendev_write_file(struct ipmi_intf * intf,struct sdr_record_generic_locator * dev,const char * ofile)357*c18ec02fSPetter Reinholdtsen ipmi_gendev_write_file(
358*c18ec02fSPetter Reinholdtsen struct ipmi_intf *intf,
359*c18ec02fSPetter Reinholdtsen struct sdr_record_generic_locator *dev,
360*c18ec02fSPetter Reinholdtsen const char *ofile
361*c18ec02fSPetter Reinholdtsen )
362*c18ec02fSPetter Reinholdtsen {
363*c18ec02fSPetter Reinholdtsen int rc = 0;
364*c18ec02fSPetter Reinholdtsen int eeprom_size;
365*c18ec02fSPetter Reinholdtsen t_gendev_eeprom_info eeprom_info;
366*c18ec02fSPetter Reinholdtsen
367*c18ec02fSPetter Reinholdtsen eeprom_size = ipmi_gendev_get_eeprom_size(intf, dev, &eeprom_info);
368*c18ec02fSPetter Reinholdtsen
369*c18ec02fSPetter Reinholdtsen if(eeprom_size > 0)
370*c18ec02fSPetter Reinholdtsen {
371*c18ec02fSPetter Reinholdtsen FILE *fp;
372*c18ec02fSPetter Reinholdtsen uint32_t fileLength = 0;
373*c18ec02fSPetter Reinholdtsen
374*c18ec02fSPetter Reinholdtsen /* now write to file */
375*c18ec02fSPetter Reinholdtsen fp = ipmi_open_file_read(ofile);
376*c18ec02fSPetter Reinholdtsen
377*c18ec02fSPetter Reinholdtsen if(fp)
378*c18ec02fSPetter Reinholdtsen {
379*c18ec02fSPetter Reinholdtsen /* Retreive file length, check if it's fits the Eeprom Size */
380*c18ec02fSPetter Reinholdtsen fseek(fp, 0 ,SEEK_END);
381*c18ec02fSPetter Reinholdtsen fileLength = ftell(fp);
382*c18ec02fSPetter Reinholdtsen
383*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "File Size: %i", fileLength);
384*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Eeprom Size: %i", eeprom_size);
385*c18ec02fSPetter Reinholdtsen if(fileLength != eeprom_size)
386*c18ec02fSPetter Reinholdtsen {
387*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "File size does not fit Eeprom Size");
388*c18ec02fSPetter Reinholdtsen fclose(fp);
389*c18ec02fSPetter Reinholdtsen fp = NULL;
390*c18ec02fSPetter Reinholdtsen }
391*c18ec02fSPetter Reinholdtsen else
392*c18ec02fSPetter Reinholdtsen {
393*c18ec02fSPetter Reinholdtsen fseek(fp, 0 ,SEEK_SET);
394*c18ec02fSPetter Reinholdtsen }
395*c18ec02fSPetter Reinholdtsen }
396*c18ec02fSPetter Reinholdtsen
397*c18ec02fSPetter Reinholdtsen if(fp)
398*c18ec02fSPetter Reinholdtsen {
399*c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
400*c18ec02fSPetter Reinholdtsen int numRead;
401*c18ec02fSPetter Reinholdtsen uint32_t counter;
402*c18ec02fSPetter Reinholdtsen uint8_t msize;
403*c18ec02fSPetter Reinholdtsen uint8_t channel = dev->channel_num;
404*c18ec02fSPetter Reinholdtsen uint8_t i2cbus = dev->bus;
405*c18ec02fSPetter Reinholdtsen uint8_t i2caddr = dev->dev_slave_addr;
406*c18ec02fSPetter Reinholdtsen uint8_t privatebus = 1;
407*c18ec02fSPetter Reinholdtsen uint32_t address_span_size;
408*c18ec02fSPetter Reinholdtsen uint8_t percentCompleted = 0;
409*c18ec02fSPetter Reinholdtsen
410*c18ec02fSPetter Reinholdtsen
411*c18ec02fSPetter Reinholdtsen /* Handle Address Span */
412*c18ec02fSPetter Reinholdtsen if( eeprom_info.address_span != 0)
413*c18ec02fSPetter Reinholdtsen {
414*c18ec02fSPetter Reinholdtsen address_span_size =
415*c18ec02fSPetter Reinholdtsen (eeprom_info.size / (eeprom_info.address_span+1));
416*c18ec02fSPetter Reinholdtsen }
417*c18ec02fSPetter Reinholdtsen else
418*c18ec02fSPetter Reinholdtsen {
419*c18ec02fSPetter Reinholdtsen address_span_size = eeprom_info.size;
420*c18ec02fSPetter Reinholdtsen }
421*c18ec02fSPetter Reinholdtsen
422*c18ec02fSPetter Reinholdtsen /* Setup read/write size */
423*c18ec02fSPetter Reinholdtsen if( eeprom_info.page_size < GENDEV_MAX_SIZE)
424*c18ec02fSPetter Reinholdtsen {
425*c18ec02fSPetter Reinholdtsen msize = eeprom_info.page_size;
426*c18ec02fSPetter Reinholdtsen }
427*c18ec02fSPetter Reinholdtsen else
428*c18ec02fSPetter Reinholdtsen {
429*c18ec02fSPetter Reinholdtsen msize = GENDEV_MAX_SIZE;
430*c18ec02fSPetter Reinholdtsen // All eeprom with page higher than 32 is on the
431*c18ec02fSPetter Reinholdtsen // 16 bytes boundary
432*c18ec02fSPetter Reinholdtsen }
433*c18ec02fSPetter Reinholdtsen
434*c18ec02fSPetter Reinholdtsen /* Setup i2c bus byte */
435*c18ec02fSPetter Reinholdtsen i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | privatebus;
436*c18ec02fSPetter Reinholdtsen
437*c18ec02fSPetter Reinholdtsen /*
438*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Generic device: %s", dev->id_string);
439*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Chnl: %x", channel);
440*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Bus : %x", i2cbus);
441*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "I2C Addr: %x", i2caddr); */
442*c18ec02fSPetter Reinholdtsen
443*c18ec02fSPetter Reinholdtsen for (
444*c18ec02fSPetter Reinholdtsen counter = 0;
445*c18ec02fSPetter Reinholdtsen (counter < (eeprom_info.size)) && (rc == 0);
446*c18ec02fSPetter Reinholdtsen counter+= msize
447*c18ec02fSPetter Reinholdtsen )
448*c18ec02fSPetter Reinholdtsen {
449*c18ec02fSPetter Reinholdtsen uint8_t retryCounter;
450*c18ec02fSPetter Reinholdtsen uint8_t readByte[GENDEV_MAX_SIZE];
451*c18ec02fSPetter Reinholdtsen
452*c18ec02fSPetter Reinholdtsen numRead = fread(readByte, 1, msize, fp);
453*c18ec02fSPetter Reinholdtsen if (numRead != msize)
454*c18ec02fSPetter Reinholdtsen {
455*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error reading file %s", ofile);
456*c18ec02fSPetter Reinholdtsen rc = -1;
457*c18ec02fSPetter Reinholdtsen break;
458*c18ec02fSPetter Reinholdtsen }
459*c18ec02fSPetter Reinholdtsen
460*c18ec02fSPetter Reinholdtsen
461*c18ec02fSPetter Reinholdtsen
462*c18ec02fSPetter Reinholdtsen for(
463*c18ec02fSPetter Reinholdtsen retryCounter = 0;
464*c18ec02fSPetter Reinholdtsen retryCounter<GENDEV_RETRY_COUNT;
465*c18ec02fSPetter Reinholdtsen retryCounter ++
466*c18ec02fSPetter Reinholdtsen )
467*c18ec02fSPetter Reinholdtsen {
468*c18ec02fSPetter Reinholdtsen uint8_t wrByte[GENDEV_MAX_SIZE+2];
469*c18ec02fSPetter Reinholdtsen wrByte[0] = (uint8_t) (counter>>0);
470*c18ec02fSPetter Reinholdtsen if(eeprom_info.address_length > 1)
471*c18ec02fSPetter Reinholdtsen {
472*c18ec02fSPetter Reinholdtsen wrByte[1] = (uint8_t) (counter>>8);
473*c18ec02fSPetter Reinholdtsen }
474*c18ec02fSPetter Reinholdtsen memcpy(&wrByte[eeprom_info.address_length], readByte, msize);
475*c18ec02fSPetter Reinholdtsen
476*c18ec02fSPetter Reinholdtsen i2caddr+= (((eeprom_info.size) % address_span_size) * 2);
477*c18ec02fSPetter Reinholdtsen
478*c18ec02fSPetter Reinholdtsen rsp = ipmi_master_write_read(intf, i2cbus, i2caddr, (uint8_t *) wrByte, eeprom_info.address_length+msize, 0);
479*c18ec02fSPetter Reinholdtsen if (rsp != NULL)
480*c18ec02fSPetter Reinholdtsen {
481*c18ec02fSPetter Reinholdtsen retryCounter = GENDEV_RETRY_COUNT;
482*c18ec02fSPetter Reinholdtsen rc = 0;
483*c18ec02fSPetter Reinholdtsen }
484*c18ec02fSPetter Reinholdtsen else if(retryCounter < GENDEV_RETRY_COUNT)
485*c18ec02fSPetter Reinholdtsen {
486*c18ec02fSPetter Reinholdtsen retryCounter ++;
487*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Retry");
488*c18ec02fSPetter Reinholdtsen sleep(1);
489*c18ec02fSPetter Reinholdtsen rc = -1;
490*c18ec02fSPetter Reinholdtsen }
491*c18ec02fSPetter Reinholdtsen else
492*c18ec02fSPetter Reinholdtsen {
493*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
494*c18ec02fSPetter Reinholdtsen rc = -1;
495*c18ec02fSPetter Reinholdtsen }
496*c18ec02fSPetter Reinholdtsen }
497*c18ec02fSPetter Reinholdtsen
498*c18ec02fSPetter Reinholdtsen if( rc == 0 )
499*c18ec02fSPetter Reinholdtsen {
500*c18ec02fSPetter Reinholdtsen static uint8_t previousCompleted = 101;
501*c18ec02fSPetter Reinholdtsen percentCompleted = ((counter * 100) / eeprom_info.size );
502*c18ec02fSPetter Reinholdtsen
503*c18ec02fSPetter Reinholdtsen if(percentCompleted != previousCompleted)
504*c18ec02fSPetter Reinholdtsen {
505*c18ec02fSPetter Reinholdtsen printf("\r%i percent completed", percentCompleted);
506*c18ec02fSPetter Reinholdtsen previousCompleted = percentCompleted;
507*c18ec02fSPetter Reinholdtsen }
508*c18ec02fSPetter Reinholdtsen
509*c18ec02fSPetter Reinholdtsen }
510*c18ec02fSPetter Reinholdtsen }
511*c18ec02fSPetter Reinholdtsen if(counter == (eeprom_info.size))
512*c18ec02fSPetter Reinholdtsen {
513*c18ec02fSPetter Reinholdtsen printf("\r%%100 percent completed\n");
514*c18ec02fSPetter Reinholdtsen }
515*c18ec02fSPetter Reinholdtsen else
516*c18ec02fSPetter Reinholdtsen {
517*c18ec02fSPetter Reinholdtsen printf("\rError: %i percent completed, read not completed \n", percentCompleted);
518*c18ec02fSPetter Reinholdtsen }
519*c18ec02fSPetter Reinholdtsen
520*c18ec02fSPetter Reinholdtsen fclose(fp);
521*c18ec02fSPetter Reinholdtsen }
522*c18ec02fSPetter Reinholdtsen }
523*c18ec02fSPetter Reinholdtsen else
524*c18ec02fSPetter Reinholdtsen {
525*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "The selected generic device is not an eeprom");
526*c18ec02fSPetter Reinholdtsen }
527*c18ec02fSPetter Reinholdtsen
528*c18ec02fSPetter Reinholdtsen return rc;
529*c18ec02fSPetter Reinholdtsen }
530*c18ec02fSPetter Reinholdtsen
531*c18ec02fSPetter Reinholdtsen
532*c18ec02fSPetter Reinholdtsen /* ipmi_gendev_main - top-level handler for generic device
533*c18ec02fSPetter Reinholdtsen *
534*c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
535*c18ec02fSPetter Reinholdtsen * @argc: number of arguments
536*c18ec02fSPetter Reinholdtsen * @argv: argument list
537*c18ec02fSPetter Reinholdtsen *
538*c18ec02fSPetter Reinholdtsen * returns 0 on success
539*c18ec02fSPetter Reinholdtsen * returns -1 on error
540*c18ec02fSPetter Reinholdtsen */
541*c18ec02fSPetter Reinholdtsen int
ipmi_gendev_main(struct ipmi_intf * intf,int argc,char ** argv)542*c18ec02fSPetter Reinholdtsen ipmi_gendev_main(struct ipmi_intf *intf, int argc, char **argv)
543*c18ec02fSPetter Reinholdtsen {
544*c18ec02fSPetter Reinholdtsen int rc = 0;
545*c18ec02fSPetter Reinholdtsen
546*c18ec02fSPetter Reinholdtsen /* initialize random numbers used later */
547*c18ec02fSPetter Reinholdtsen srand(time(NULL));
548*c18ec02fSPetter Reinholdtsen
549*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Rx gendev command: %s", argv[0]);
550*c18ec02fSPetter Reinholdtsen
551*c18ec02fSPetter Reinholdtsen if (
552*c18ec02fSPetter Reinholdtsen (argc == 0)
553*c18ec02fSPetter Reinholdtsen ||
554*c18ec02fSPetter Reinholdtsen (strncmp(argv[0], "help", 4) == 0)
555*c18ec02fSPetter Reinholdtsen )
556*c18ec02fSPetter Reinholdtsen {
557*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
558*c18ec02fSPetter Reinholdtsen "SDR Commands: list read write");
559*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
560*c18ec02fSPetter Reinholdtsen " list List All Generic Device Locators");
561*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
562*c18ec02fSPetter Reinholdtsen " read <sdr name> <file> Read to file eeprom specify by Generic Device Locators");
563*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
564*c18ec02fSPetter Reinholdtsen " write <sdr name> <file> Write from file eeprom specify by Generic Device Locators");
565*c18ec02fSPetter Reinholdtsen }
566*c18ec02fSPetter Reinholdtsen else if ( strncmp(argv[0], "list", 4) == 0)
567*c18ec02fSPetter Reinholdtsen {
568*c18ec02fSPetter Reinholdtsen rc = ipmi_sdr_print_sdr(intf,
569*c18ec02fSPetter Reinholdtsen SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
570*c18ec02fSPetter Reinholdtsen }
571*c18ec02fSPetter Reinholdtsen else if (strncmp(argv[0], "read", 4) == 0)
572*c18ec02fSPetter Reinholdtsen {
573*c18ec02fSPetter Reinholdtsen if (argc < 3)
574*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "usage: gendev read <gendev> <filename>");
575*c18ec02fSPetter Reinholdtsen else
576*c18ec02fSPetter Reinholdtsen {
577*c18ec02fSPetter Reinholdtsen struct sdr_record_list *sdr;
578*c18ec02fSPetter Reinholdtsen
579*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Gendev read sdr name : %s", argv[1]);
580*c18ec02fSPetter Reinholdtsen
581*c18ec02fSPetter Reinholdtsen printf("Locating sensor record '%s'...\n", argv[1]);
582*c18ec02fSPetter Reinholdtsen
583*c18ec02fSPetter Reinholdtsen /* lookup by sensor name */
584*c18ec02fSPetter Reinholdtsen sdr = ipmi_sdr_find_sdr_byid(intf, argv[1]);
585*c18ec02fSPetter Reinholdtsen if (sdr == NULL)
586*c18ec02fSPetter Reinholdtsen {
587*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Sensor data record not found!");
588*c18ec02fSPetter Reinholdtsen return -1;
589*c18ec02fSPetter Reinholdtsen }
590*c18ec02fSPetter Reinholdtsen
591*c18ec02fSPetter Reinholdtsen if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
592*c18ec02fSPetter Reinholdtsen {
593*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Target SDR is not a generic device locator");
594*c18ec02fSPetter Reinholdtsen return -1;
595*c18ec02fSPetter Reinholdtsen }
596*c18ec02fSPetter Reinholdtsen
597*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Gendev read file name: %s", argv[2]);
598*c18ec02fSPetter Reinholdtsen ipmi_gendev_read_file(intf, sdr->record.genloc, argv[2]);
599*c18ec02fSPetter Reinholdtsen
600*c18ec02fSPetter Reinholdtsen }
601*c18ec02fSPetter Reinholdtsen }
602*c18ec02fSPetter Reinholdtsen else if (strncmp(argv[0], "write", 5) == 0)
603*c18ec02fSPetter Reinholdtsen {
604*c18ec02fSPetter Reinholdtsen if (argc < 3)
605*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "usage: gendev write <gendev> <filename>");
606*c18ec02fSPetter Reinholdtsen else
607*c18ec02fSPetter Reinholdtsen {
608*c18ec02fSPetter Reinholdtsen struct sdr_record_list *sdr;
609*c18ec02fSPetter Reinholdtsen
610*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Gendev write sdr name : %s", argv[1]);
611*c18ec02fSPetter Reinholdtsen
612*c18ec02fSPetter Reinholdtsen printf("Locating sensor record '%s'...\n", argv[1]);
613*c18ec02fSPetter Reinholdtsen
614*c18ec02fSPetter Reinholdtsen /* lookup by sensor name */
615*c18ec02fSPetter Reinholdtsen sdr = ipmi_sdr_find_sdr_byid(intf, argv[1]);
616*c18ec02fSPetter Reinholdtsen if (sdr == NULL)
617*c18ec02fSPetter Reinholdtsen {
618*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Sensor data record not found!");
619*c18ec02fSPetter Reinholdtsen return -1;
620*c18ec02fSPetter Reinholdtsen }
621*c18ec02fSPetter Reinholdtsen
622*c18ec02fSPetter Reinholdtsen if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
623*c18ec02fSPetter Reinholdtsen {
624*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Target SDR is not a generic device locator");
625*c18ec02fSPetter Reinholdtsen return -1;
626*c18ec02fSPetter Reinholdtsen }
627*c18ec02fSPetter Reinholdtsen
628*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Gendev write file name: %s", argv[2]);
629*c18ec02fSPetter Reinholdtsen ipmi_gendev_write_file(intf, sdr->record.genloc, argv[2]);
630*c18ec02fSPetter Reinholdtsen
631*c18ec02fSPetter Reinholdtsen }
632*c18ec02fSPetter Reinholdtsen }
633*c18ec02fSPetter Reinholdtsen else
634*c18ec02fSPetter Reinholdtsen {
635*c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid gendev command: %s", argv[0]);
636*c18ec02fSPetter Reinholdtsen rc = -1;
637*c18ec02fSPetter Reinholdtsen }
638*c18ec02fSPetter Reinholdtsen
639*c18ec02fSPetter Reinholdtsen return rc;
640*c18ec02fSPetter Reinholdtsen }
641