first commit

This commit is contained in:
pandacraft 2025-03-21 16:04:17 +01:00
commit a5a0434432
1126 changed files with 439481 additions and 0 deletions

View file

@ -0,0 +1,182 @@
/***************************************************************************
copyright : (C) by 2002-2003 Stefano Barbato
email : stefano@codesink.org
$Id: 24cXX.c 4230 2006-11-10 09:22:12Z khali $
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include "24cXX.h"
static int i2c_write_1b(struct eeprom *e, __u8 buf)
{
int r;
// we must simulate a plain I2C byte write with SMBus functions
r = i2c_smbus_write_byte(e->fd, buf);
if(r < 0)
fprintf(stderr, "Error i2c_write_1b: %s\n", strerror(errno));
usleep(10);
return r;
}
static int i2c_write_2b(struct eeprom *e, __u8 buf[2])
{
int r;
// we must simulate a plain I2C byte write with SMBus functions
r = i2c_smbus_write_byte_data(e->fd, buf[0], buf[1]);
if(r < 0)
fprintf(stderr, "Error i2c_write_2b: %s\n", strerror(errno));
usleep(10);
return r;
}
static int i2c_write_3b(struct eeprom *e, __u8 buf[3])
{
int r;
// we must simulate a plain I2C byte write with SMBus functions
// the __u16 data field will be byte swapped by the SMBus protocol
r = i2c_smbus_write_word_data(e->fd, buf[0], buf[2] << 8 | buf[1]);
if(r < 0)
fprintf(stderr, "Error i2c_write_3b: %s\n", strerror(errno));
usleep(10);
return r;
}
#define CHECK_I2C_FUNC( var, label ) \
do { if(0 == (var & label)) { \
fprintf(stderr, "\nError: " \
#label " function is required. Program halted.\n\n"); \
exit(1); } \
} while(0);
int eeprom_open(char *dev_fqn, int addr, int type, struct eeprom* e)
{
int fd, r;
unsigned long funcs;
e->fd = e->addr = 0;
e->dev = 0;
fd = open(dev_fqn, O_RDWR);
if(fd <= 0)
return -1;
// get funcs list
if((r = ioctl(fd, I2C_FUNCS, &funcs) < 0))
return r;
// check for req funcs
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE );
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE );
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE_DATA );
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE_DATA );
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_WORD_DATA );
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_WORD_DATA );
// set working device
if( ( r = ioctl(fd, I2C_SLAVE, addr)) < 0)
return r;
e->fd = fd;
e->addr = addr;
e->dev = dev_fqn;
e->type = type;
return 0;
}
int eeprom_close(struct eeprom *e)
{
close(e->fd);
e->fd = -1;
e->dev = 0;
e->type = EEPROM_TYPE_UNKNOWN;
return 0;
}
#if 0
int eeprom_24c32_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data)
{
__u8 buf[3] = { (mem_addr >> 8) & 0x00ff, mem_addr & 0x00ff, data };
return i2c_write_3b(e, buf);
}
int eeprom_24c32_read_current_byte(struct eeprom* e)
{
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
return i2c_smbus_read_byte(e->fd);
}
int eeprom_24c32_read_byte(struct eeprom* e, __u16 mem_addr)
{
int r;
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
__u8 buf[2] = { (mem_addr >> 8) & 0x0ff, mem_addr & 0x0ff };
r = i2c_write_2b(e, buf);
if (r < 0)
return r;
r = i2c_smbus_read_byte(e->fd);
return r;
}
#endif
int eeprom_read_current_byte(struct eeprom* e)
{
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
return i2c_smbus_read_byte(e->fd);
}
int eeprom_read_byte(struct eeprom* e, __u16 mem_addr)
{
int r;
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
if(e->type == EEPROM_TYPE_8BIT_ADDR)
{
__u8 buf = mem_addr & 0x0ff;
r = i2c_write_1b(e, buf);
} else if(e->type == EEPROM_TYPE_16BIT_ADDR) {
__u8 buf[2] = { (mem_addr >> 8) & 0x0ff, mem_addr & 0x0ff };
r = i2c_write_2b(e, buf);
} else {
fprintf(stderr, "ERR: unknown eeprom type\n");
return -1;
}
if (r < 0)
return r;
r = i2c_smbus_read_byte(e->fd);
return r;
}
int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data)
{
if(e->type == EEPROM_TYPE_8BIT_ADDR) {
__u8 buf[2] = { mem_addr & 0x00ff, data };
return i2c_write_2b(e, buf);
} else if(e->type == EEPROM_TYPE_16BIT_ADDR) {
__u8 buf[3] =
{ (mem_addr >> 8) & 0x00ff, mem_addr & 0x00ff, data };
return i2c_write_3b(e, buf);
} else {
fprintf(stderr, "ERR: unknown eeprom type\n");
return -1;
}
}

View file

@ -0,0 +1,58 @@
/***************************************************************************
copyright : (C) by 2002-2003 Stefano Barbato
email : stefano@codesink.org
$Id: 24cXX.h 4495 2007-06-27 12:57:50Z khali $
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef _24CXX_H_
#define _24CXX_H_
#include <linux/i2c-dev.h>
#define EEPROM_TYPE_UNKNOWN 0
#define EEPROM_TYPE_8BIT_ADDR 1
#define EEPROM_TYPE_16BIT_ADDR 2
struct eeprom
{
char *dev; // device file i.e. /dev/i2c-N
int addr; // i2c address
int fd; // file descriptor
int type; // eeprom type
};
/*
* opens the eeprom device at [dev_fqn] (i.e. /dev/i2c-N) whose address is
* [addr] and set the eeprom_24c32 [e]
*/
int eeprom_open(char *dev_fqn, int addr, int type, struct eeprom*);
/*
* closees the eeprom device [e]
*/
int eeprom_close(struct eeprom *e);
/*
* read and returns the eeprom byte at memory address [mem_addr]
* Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address)
*/
int eeprom_read_byte(struct eeprom* e, __u16 mem_addr);
/*
* read the current byte
* Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address)
*/
int eeprom_read_current_byte(struct eeprom *e);
/*
* writes [data] at memory address [mem_addr]
* Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address)
*/
int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data);
#endif

View file

@ -0,0 +1,14 @@
#eepromer Makefile
CFLAGS = -O2 -I../include -Wall
all: eepromer eeprom eeprog
eepromer: eepromer.o
eeprom: eeprom.o
eeprog: eeprog.o 24cXX.o
clean:
rm -rf *~ *.o eepromer eeprom eeprog

View file

@ -0,0 +1,31 @@
These programs are used to read and write eeproms.
Use eeprom for small eeproms with one-byte addresses:
24C01, 24C01A, 24C02, 24C04, 24C08, and 24C16
It works only on true i2c bus adapters.
See README.eeprom for details.
Use eepromer for large eeproms with two-byte addresses:
24C32, 24C64, 24C128, 24C256, and 24C512
It works only on true i2c bus adapters.
See README.eepromer for details.
Use eeprog for either small or large eeproms.
Use the -16 switch for large eeproms.
It works on both i2c and smbus bus adapters.
See README.eeprog for details.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!! !
!!! These programs should only be used on external busses such as i2c-pport !
!!! unless you REALLY know what you are doing. !
!!! !
!!! Your computer probably contains eeproms for saving data vital to its !
!!! operation. If you are not careful you might overwrite this data with !
!!! this program and your computer may no longer boot! !
!!! !
!!! An example are the EEPROMS on your SDRAM DIMMs, your computer may no !
!!! longer detect the RAM module rendering it essentially USELESS! !
!!! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

View file

@ -0,0 +1,12 @@
Important! See the README file for important warnings.
eeprog reads and writes 24Cxx EEPROMs connected to I2C serial bus.
It uses the SMBus protocol used by most of the recent chipsets. Don't forget to load
your i2c chipset and the i2c-dev drivers.
Use -16 switch for EEPROM larger then 24C16 (16 bit addressing mode).
Again, it's really important that you read the README file.
Type "make" to compile.

View file

@ -0,0 +1,85 @@
You can use this program to read/write to i2c-eeproms
like the popular 24C16, 24C08, 24C04,.. In contrast to eeprommer
which supports 24C256-type eeproms 24C16ss use 1-byte addresses!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!! !
!!! This program should only be used on external busses such as i2c-pport. !
!!! !
!!! Your computer may contain i2c-eeproms for saving data vital to its !
!!! operation. If you are not careful you might overwrite this data with !
!!! this program and your computer may no longer boot! !
!!! !
!!! An example are the EEPROMS on your SDRAM DIMMs, your computer may no !
!!! longer detect the RAM module rendering it essentially USELESS! !
!!! !
!!! IBM Thinkpads are said to store their configuration data in a eeprom, !
!!! if you manage to overwrite this eeprom you will have to send your !
!!! computer to the manufacturer for a costly repair! !
!!! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
It has several options:
-d devicenode
set this to the device-node of the i2c-bus
you want to use like /dev/i2c-0.
Use /dev/i2c-1 for the second bus, i2c-2 for the third...
The default /dev/i2c-0 should work most of the time.
-a address
set this to the device-address of your
eeprom. For a 24C16 the address is hardcoded to
0x50, which is -you guessed it- the default.
For a 24C08 and smaller types you can choose which
addresses they occupy by forcing the address-pins
of the chip to High or Low so here the address may differ.
-p number_of_pages
set this to the number of pages you want to read
from or write to the eeprom. The 24C16 maps it's
pages to consecutive addresses on the i2c-bus so
we will try to read 256 bytes from every i2c
address between 'address' (inclusive) and
'address + number_of_pages' (exclusive)...
A 24C16 has 8 pages so that's the default for this
parameter.
-f filename
read data from this file (when writing to eeprom) or
write data to this file (when reading from eeprom).
When reading a file that's smaller than the
eeprom's storage size we will pad the eeprom
with zeroes.
If no file is given we will just read the
eeprom (while in read-mode) and test it's presence
this way. In write-mode we will just write zeroes
to the eeprom.
-w When '-w' is present we will *write* to the eeprom.
If you do not specify '-w' we will read the contents
of the eeprom.
-y This flag will suppress the warning when you write to the
eeprom. You will not be required to enter 'yes' so be careful
when using this switch!
I wrote that program to clear a 24C16 eeprom that sit's in my crappy
satellite receiver because sometimes its Z80 processor likes to
write garbage to it and then crash....
No further testing besides writing a long series of "The quick brown
fox jumps over the lazy dog!" and reading it back has been done so
of course this comes without any warranty.
Chris <chris@hedonism.cx>

View file

@ -0,0 +1,27 @@
Simple program for storing data to I2C EEPROM.
!!!!!!!!!!!!!!!!!!!!!!!!Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
The EEPROM must be a large EEPROM which uses a 2-byte address
field (24C32 or larger). It will NOT WORK on small EEPROMs
(24C01 - 24C16) such as those used on SDRAM DIMMs.
Tested only on 24C256.
!!!!!!!!!!!!!!!!!!!!!!!!Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
This program is intended for use on eeproms using external busses such as
i2c-pport.
Do not use this on your SDRAM DIMM EEPROMS, it won't work!!!!!!!!!
Doing so will render your SDRAM USELESS and leave your system UNBOOTABLE!!!
!!!!!!!!!!!!!!!!!!!!!!!!Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Options:
-r read
-w write
-e erase
-p print "super block of EEPROM" (date and size stored data)
Daniel Smolik
marvin@sitour.cz

View file

@ -0,0 +1,283 @@
/***************************************************************************
copyright : (C) by 2002-2003 Stefano Barbato
email : stefano@codesink.org
$Id: eeprog.c 5122 2008-02-18 09:22:21Z khali $
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "24cXX.h"
#define VERSION "0.7.5"
#define ENV_DEV "EEPROG_DEV"
#define ENV_I2C_ADDR "EEPROG_I2C_ADDR"
int g_quiet;
#define usage_if(a) do { do_usage_if( a , __LINE__); } while(0);
void do_usage_if(int b, int line)
{
static const char *eeprog_usage =
"eeprog " VERSION ", a 24Cxx EEPROM reader/writer\n"
"Copyright (c) 2003 by Stefano Barbato - All rights reserved.\n"
"Usage: eeprog [-fqxdh] [-16|-8] [ -r addr[:count] | -w addr ] /dev/i2c-N i2c-address\n"
"\n"
" Address modes:\n"
" -8 Use 8bit address mode for 24c0x...24C16 [default]\n"
" -16 Use 16bit address mode for 24c32...24C256\n"
" Actions:\n"
" -r addr[:count] Read [count] (1 if omitted) bytes from [addr]\n"
" and print them to the standard output\n"
" -w addr Write input (stdin) at address [addr] of the EEPROM\n"
" -h Print this help\n"
" Options:\n"
" -x Set hex output mode\n"
" -d Dummy mode, display what *would* have been done\n"
" -f Disable warnings and don't ask confirmation\n"
" -q Quiet mode\n"
"\n"
"The following environment variables could be set instead of the command\n"
"line arguments:\n"
" EEPROG_DEV device name(/dev/i2c-N)\n"
" EEPROG_I2C_ADDR i2c-address\n"
"\n"
" Examples\n"
" 1- read 64 bytes from the EEPROM at address 0x54 on bus 0 starting\n"
" at address 123 (decimal)\n"
" eeprog /dev/i2c-0 0x54 -r 123:64\n"
" 2- prints the hex codes of the first 32 bytes read from bus 1\n"
" at address 0x22\n"
" eeprog /dev/i2c-1 0x51 -x -r 0x22:0x20\n"
" 3- write the current timestamp at address 0x200 of the EEPROM on\n"
" bus 0 at address 0x33\n"
" date | eeprog /dev/i2c-0 0x33 -w 0x200\n";
if(!b)
return;
fprintf(stderr, "%s\n[line %d]\n", eeprog_usage, line);
exit(1);
}
#define die_if(a, msg) do { do_die_if( a , msg, __LINE__); } while(0);
void do_die_if(int b, char* msg, int line)
{
if(!b)
return;
fprintf(stderr, "Error at line %d: %s\n", line, msg);
//fprintf(stderr, " sysmsg: %s\n", strerror(errno));
exit(1);
}
#define print_info(args...) do { if(!g_quiet) fprintf(stderr, args); } while(0);
void parse_arg(char *arg, int* paddr, int *psize)
{
char *end;
*paddr = strtoul(arg, &end, 0);
if(*end == ':')
*psize = strtoul(++end, 0, 0);
}
int confirm_action()
{
fprintf(stderr,
"\n"
"____________________________WARNING____________________________\n"
"Erroneously writing to a system EEPROM (like DIMM SPD modules)\n"
"can break your system. It will NOT boot anymore so you'll not\n"
"be able to fix it.\n"
"\n"
"Reading from 8bit EEPROMs (like that in your DIMM) without using\n"
"the -8 switch can also UNEXPECTEDLY write to them, so be sure to\n"
"use the -8 command param when required.\n"
"\n"
"Use -f to disable this warning message\n"
"\n"
"Press ENTER to continue or hit CTRL-C to exit\n"
"\n"
);
getchar();
return 1;
}
int read_from_eeprom(struct eeprom *e, int addr, int size, int hex)
{
int ch, i;
// hex print out
die_if((ch = eeprom_read_byte(e, addr)) < 0, "read error");
i = 1;
if(hex)
printf("\n %.4x| %.2x ", addr, ch);
else
putchar(ch);
while(--size)
{
die_if((ch = eeprom_read_current_byte(e)) < 0, "read error");
if(hex)
{
addr++;
if( (i % 16) == 0 )
printf("\n %.4x| ", addr);
else if( (i % 8) == 0 )
printf(" ");
i++;
printf("%.2x ", ch);
} else {
putchar(ch);
}
}
if(hex)
printf("\n\n");
fflush(stdout);
return 0;
}
int write_to_eeprom(struct eeprom *e, int addr)
{
int c;
while((c = getchar()) != EOF)
{
print_info(".");
fflush(stdout);
die_if(eeprom_write_byte(e, addr++, c), "write error");
}
print_info("\n\n");
return 0;
}
int main(int argc, char** argv)
{
struct eeprom e;
int ret, op, i2c_addr, memaddr, size, want_hex, dummy, force, sixteen;
char *device, *arg = 0, *i2c_addr_s;
struct stat st;
int eeprom_type = 0;
op = want_hex = dummy = force = sixteen = 0;
g_quiet = 0;
while((ret = getopt(argc, argv, "1:8fr:qhw:xd")) != -1)
{
switch(ret)
{
case '1':
usage_if(*optarg != '6' || strlen(optarg) != 1);
die_if(eeprom_type, "EEPROM type switch (-8 or -16) used twice");
eeprom_type = EEPROM_TYPE_16BIT_ADDR;
break;
case 'x':
want_hex++;
break;
case 'd':
dummy++;
break;
case '8':
die_if(eeprom_type, "EEPROM type switch (-8 or -16) used twice");
eeprom_type = EEPROM_TYPE_8BIT_ADDR;
break;
case 'f':
force++;
break;
case 'q':
g_quiet++;
break;
case 'h':
usage_if(1);
break;
default:
die_if(op != 0, "Both read and write requested");
arg = optarg;
op = ret;
}
}
if(!eeprom_type)
eeprom_type = EEPROM_TYPE_8BIT_ADDR; // default
usage_if(op == 0); // no switches
// set device and i2c_addr reading from cmdline or env
device = i2c_addr_s = 0;
switch(argc - optind)
{
case 0:
device = getenv(ENV_DEV);
i2c_addr_s = getenv(ENV_I2C_ADDR);
break;
case 1:
if(stat(argv[optind], &st) != -1)
{
device = argv[optind];
i2c_addr_s = getenv(ENV_I2C_ADDR);
} else {
device = getenv(ENV_DEV);
i2c_addr_s = argv[optind];
}
break;
case 2:
device = argv[optind++];
i2c_addr_s = argv[optind];
break;
default:
usage_if(1);
}
usage_if(!device || !i2c_addr_s);
i2c_addr = strtoul(i2c_addr_s, 0, 0);
print_info("eeprog %s, a 24Cxx EEPROM reader/writer\n", VERSION);
print_info("Copyright (c) 2003 by Stefano Barbato - All rights reserved.\n");
print_info(" Bus: %s, Address: 0x%x, Mode: %dbit\n",
device, i2c_addr,
(eeprom_type == EEPROM_TYPE_8BIT_ADDR ? 8 : 16) );
if(dummy)
{
fprintf(stderr, "Dummy mode selected, nothing done.\n");
return 0;
}
die_if(eeprom_open(device, i2c_addr, eeprom_type, &e) < 0,
"unable to open eeprom device file (check that the file exists and that it's readable)");
switch(op)
{
case 'r':
if(force == 0)
confirm_action();
size = 1; // default
parse_arg(arg, &memaddr, &size);
print_info(" Reading %d bytes from 0x%x\n", size, memaddr);
read_from_eeprom(&e, memaddr, size, want_hex);
break;
case 'w':
if(force == 0)
confirm_action();
parse_arg(arg, &memaddr, &size);
print_info(" Writing stdin starting at address 0x%x\n",
memaddr);
write_to_eeprom(&e, memaddr);
break;
default:
usage_if(1);
exit(1);
}
eeprom_close(&e);
return 0;
}

View file

@ -0,0 +1,297 @@
/*
This program is hereby placed into the public domain.
Of course the program is provided without warranty of any kind.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <linux/i2c-dev.h>
/*
this program can read 24C16 (and probably smaller ones, too)
I wrote it as a quick and dirty hack because my satellite receiver
hung again... so I had to reprogram the eeprom where is stores it's
settings.
*/
#define DEFAULT_I2C_BUS "/dev/i2c-0"
#define DEFAULT_EEPROM_ADDR 0x50 /* the 24C16 sits on i2c address 0x50 */
#define DEFAULT_NUM_PAGES 8 /* we default to a 24C16 eeprom which has 8 pages */
#define BYTES_PER_PAGE 256 /* one eeprom page is 256 byte */
#define MAX_BYTES 8 /* max number of bytes to write in one chunk */
/* ... note: 24C02 and 24C01 only allow 8 bytes to be written in one chunk. *
* if you are going to write 24C04,8,16 you can change this to 16 */
/* write len bytes (stored in buf) to eeprom at address addr, page-offset offset */
/* if len=0 (buf may be NULL in this case) you can reposition the eeprom's read-pointer */
/* return 0 on success, -1 on failure */
int eeprom_write(int fd,
unsigned int addr,
unsigned int offset,
unsigned char *buf,
unsigned char len
){
struct i2c_rdwr_ioctl_data msg_rdwr;
struct i2c_msg i2cmsg;
int i;
char _buf[MAX_BYTES + 1];
if(len>MAX_BYTES){
fprintf(stderr,"I can only write MAX_BYTES bytes at a time!\n");
return -1;
}
if(len+offset >256){
fprintf(stderr,"Sorry, len(%d)+offset(%d) > 256 (page boundary)\n",
len,offset);
return -1;
}
_buf[0]=offset; /* _buf[0] is the offset into the eeprom page! */
for(i=0;i<len;i++) /* copy buf[0..n] -> _buf[1..n+1] */
_buf[1+i]=buf[i];
msg_rdwr.msgs = &i2cmsg;
msg_rdwr.nmsgs = 1;
i2cmsg.addr = addr;
i2cmsg.flags = 0;
i2cmsg.len = 1+len;
i2cmsg.buf = _buf;
if((i=ioctl(fd,I2C_RDWR,&msg_rdwr))<0){
perror("ioctl()");
fprintf(stderr,"ioctl returned %d\n",i);
return -1;
}
if(len>0)
fprintf(stderr,"Wrote %d bytes to eeprom at 0x%02x, offset %08x\n",
len,addr,offset);
else
fprintf(stderr,"Positioned pointer in eeprom at 0x%02x to offset %08x\n",
addr,offset);
return 0;
}
/* read len bytes stored in eeprom at address addr, offset offset in array buf */
/* return -1 on error, 0 on success */
int eeprom_read(int fd,
unsigned int addr,
unsigned int offset,
unsigned char *buf,
unsigned char len
){
struct i2c_rdwr_ioctl_data msg_rdwr;
struct i2c_msg i2cmsg;
int i;
if(len>MAX_BYTES){
fprintf(stderr,"I can only write MAX_BYTES bytes at a time!\n");
return -1;
}
if(eeprom_write(fd,addr,offset,NULL,0)<0)
return -1;
msg_rdwr.msgs = &i2cmsg;
msg_rdwr.nmsgs = 1;
i2cmsg.addr = addr;
i2cmsg.flags = I2C_M_RD;
i2cmsg.len = len;
i2cmsg.buf = buf;
if((i=ioctl(fd,I2C_RDWR,&msg_rdwr))<0){
perror("ioctl()");
fprintf(stderr,"ioctl returned %d\n",i);
return -1;
}
fprintf(stderr,"Read %d bytes from eeprom at 0x%02x, offset %08x\n",
len,addr,offset);
return 0;
}
int main(int argc, char **argv){
int i,j;
/* filedescriptor and name of device */
int d;
char *dn=DEFAULT_I2C_BUS;
/* filedescriptor and name of data file */
int f=-1;
char *fn=NULL;
unsigned int addr=DEFAULT_EEPROM_ADDR;
int rwmode=0;
int pages=DEFAULT_NUM_PAGES;
int force=0; /* suppress warning on write! */
while((i=getopt(argc,argv,"d:a:p:wyf:h"))>=0){
switch(i){
case 'h':
fprintf(stderr,"%s [-d dev] [-a adr] [-p pgs] [-w] [-y] [-f file]\n",argv[0]);
fprintf(stderr,"\tdev: device, e.g. /dev/i2c-0 (def)\n");
fprintf(stderr,"\tadr: base address of eeprom, eg 0xA0 (def)\n");
fprintf(stderr,"\tpgs: number of pages to read, eg 8 (def)\n");
fprintf(stderr,"\t-w : write to eeprom (default is reading!)\n");
fprintf(stderr,"\t-y : suppress warning when writing (default is to warn!)\n");
fprintf(stderr,"\t-f file: copy eeprom contents to/from file\n");
fprintf(stderr,"\t (default for read is test only; for write is all zeros)\n");
fprintf(stderr,"Note on pages/addresses:\n");
fprintf(stderr,"\teeproms with more than 256 byte appear as if they\n");
fprintf(stderr,"\twere several eeproms with consecutive addresses on the bus\n");
fprintf(stderr,"\tso we might as well address several separate eeproms with\n");
fprintf(stderr,"\tincreasing addresses....\n\n");
exit(1);
break;
case 'd':
dn=optarg;
break;
case 'a':
if(sscanf(optarg,"0x%x",&addr)!=1){
fprintf(stderr,"Cannot parse '%s' as addrs., example: 0xa0\n",
optarg);
exit(1);
}
break;
case 'p':
if(sscanf(optarg,"%d",&pages)!=1){
fprintf(stderr,"Cannot parse '%s' as number of pages, example: 8\n",
optarg);
exit(1);
}
break;
case 'w':
rwmode++;
break;
case 'f':
fn=optarg;
break;
case 'y':
force++;
break;
}
}
fprintf(stderr,"base-address of eeproms : 0x%02x\n",addr);
fprintf(stderr,"number of pages to read : %d (0x%02x .. 0x%02x)\n",
pages,addr,addr+pages-1);
if(fn){
if(!rwmode) /* if we are reading, *WRITE* to file */
f=open(fn,O_WRONLY|O_CREAT,0666);
else /* if we are writing to eeprom, *READ* from file */
f=open(fn,O_RDONLY);
if(f<0){
fprintf(stderr,"Could not open data-file %s for reading or writing\n",fn);
perror(fn);
exit(1);
}
fprintf(stderr,"file opened for %7s : %s\n",rwmode?"reading":"writing",fn);
fprintf(stderr," on filedescriptor : %d\n",f);
}
if((d=open(dn,O_RDWR))<0){
fprintf(stderr,"Could not open i2c at %s\n",dn);
perror(dn);
exit(1);
}
fprintf(stderr,"i2c-devicenode is : %s\n",dn);
fprintf(stderr," on filedescriptor : %d\n\n",d);
/***
*** I'm not the one to blame of you screw your computer!
***/
if(rwmode && ! force){
unsigned char warnbuf[4];
fprintf(stderr,"**WARNING**\n");
fprintf(stderr," - \tYou have chosen to WRITE to this eeprom.\n");
fprintf(stderr,"\tMake sure that this tiny chip is *NOT* vital to the\n");
fprintf(stderr,"\toperation of your computer as you can easily corrupt\n");
fprintf(stderr,"\tthe configuration memory of your SDRAM-memory-module,\n");
fprintf(stderr,"\tyour IBM ThinkPad or whatnot...! Fixing these errors can be\n");
fprintf(stderr,"\ta time-consuming and very costly process!\n\n");
fprintf(stderr,"Things to consider:\n");
fprintf(stderr," - \tYou can have more than one i2c-bus, check in /proc/bus/i2c\n");
fprintf(stderr,"\tand specify the correct one with -d\n");
fprintf(stderr,"\tright now you have chosen to use '%s'\n",dn);
fprintf(stderr," - \tA eeprom can occupy several i2c-addresses (one per page)\n");
fprintf(stderr,"\tso please make sure that there is no vital eeprom in your computer\n");
fprintf(stderr,"\tsitting at addresses between 0x%02x and 0x%02x\n",addr,addr+pages-1);
fprintf(stderr,"Enter 'yes' to continue:");
fflush(stderr);
if(!fgets(warnbuf,sizeof(warnbuf),stdin)){
fprintf(stderr,"\nCould not read confirmation from stdin!\n");
exit(1);
}
if(strncmp(warnbuf,"yes",3)){
fprintf(stderr,"\n** ABORTING WRITE! **, you did not answer 'yes'\n");
exit(1);
}
}
for(i=0;i<pages;i++){
unsigned char buf[BYTES_PER_PAGE];
if(rwmode){
if(f>=0){
j=read(f,buf,sizeof(buf));
if(j<0){
fprintf(stderr,"Cannot read from file '%s'\n",fn);
perror(fn);
exit(1);
}
if(j!=sizeof(buf)){
fprintf(stderr,"File '%s' is too small, padding eeprom with zeroes\n",fn);
while(j<sizeof(buf))
buf[j++]=0;
}
} else {
for(j=0;j<sizeof(buf);j++)
buf[j]=0;
}
for(j=0;j<(BYTES_PER_PAGE/MAX_BYTES);j++)
if(eeprom_write(d,addr+i,j*MAX_BYTES,buf+(j*MAX_BYTES),MAX_BYTES)<0)
exit(1);
} else {
for(j=0;j<(BYTES_PER_PAGE/MAX_BYTES);j++)
if(eeprom_read(d,addr+i,j*MAX_BYTES,buf+(j*MAX_BYTES),MAX_BYTES)<0)
exit(1);
}
if(!rwmode && f>=0){
j=write(f,buf,sizeof(buf));
if(j!=sizeof(buf)){
fprintf(stderr,"Cannot write to file '%s'\n",fn);
perror(fn);
exit(1);
}
}
}
if(f>=0)
close(f);
close(d);
exit(0);
}

View file

@ -0,0 +1,721 @@
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <linux/i2c-dev.h>
#define MAX_BLK_SIZE 64
#define EEPROM_SIZE 32768
#define READ 1
#define WRITE 0
#define ERASE 2
#define PHEADER 3
#define VER "eepromer v 0.4 (c) Daniel Smolik 2001\n"
#define HEAD_SIZE sizeof(struct mini_inode)
#define START_ADDR 0
#define FORCE 1
/*
To disable startup warning #undef WARNINC
*/
#define WARNINC
int block_write(int file,int dev_addr,int eeprom_addr,unsigned char *buf,int lenght);int block_write(int file,int dev_addr,int eeprom_addr,unsigned char *buf,int lenght);
int block_read(int file,int dev_addr,int eeprom_addr,unsigned char *buf);
/* block_read read block 64 bytes length and returns actual length of data*/
void help(void);
int init(char *device,int addr);
int content_write(int file, int addr);
int content_read(int file, int addr);
int inode_write(int file, int dev_addr, int lenght);
int inode_read(int file, int dev_addr, void *p_inode);
void pheader(int file, int addr);
void erase(int file,int addr,int eeprom_size);
void made_address(int addr,unsigned char *buf);
void warn(void);
void bar(void);
static int stav=0;
static struct mini_inode {
time_t timestamp;
int data_len;
char data[56];
} m_ind,*p_ind;
void help(void)
{
FILE *fptr;
char s[100];
fprintf(stderr,"Syntax: eepromer [-r|-w|-e|-p] -f /dev/i2c-X ADDRESS \n\n");
fprintf(stderr," ADDRESS is address of i2c device eg. 0x51\n");
if((fptr = fopen("/proc/bus/i2c", "r"))) {
fprintf(stderr," Installed I2C busses:\n");
while(fgets(s, 100, fptr))
fprintf(stderr, " %s", s);
fclose(fptr);
}
}
int main(int argc, char *argv[]){
int i, file, addr;
int action; //in this variable will be (-r,-w,-e)
char device[45];
int force;
p_ind=&m_ind;
force=0;
for(i=1; i < argc;i++){
if(!strcmp("-r",argv[i])) {
action=READ;
break;
}
if(!strcmp("-e",argv[i])) {
action=ERASE;
break;
}
if(!strcmp("-w",argv[i])) {
action=WRITE;
break;
}
if(!strcmp("-p",argv[i])) {
action=PHEADER;
break;
}
if(!strcmp("-force",argv[i])) {
force=FORCE;
break;
}
if(!strcmp("-v",argv[i])) {
fprintf(stderr,VER);
exit(0);
break;
}
else {
fprintf(stderr,"Error: No action specified !\n");
help();
exit(1);
}
}
#ifdef WARNINC
if(force!=FORCE) warn();
#endif
if(argc < 5) {
fprintf(stderr,"Error: No i2c address specified !\n");
help();
exit(1);
}
for(i=1; i < argc;i++){
if(!strcmp("-f",argv[i])) {
strcpy(device,argv[i+1]);
break;
}
}
if(!strlen(device)) {
fprintf(stderr,"Error: No device specified !\n");
help();
exit(1);
}
if(! (addr=strtol(argv[4],NULL,16))) {
fprintf(stderr,"Error: Bad device address !\n");
help();
exit(1);
}
if(! (file=init(device,addr))){
fprintf(stderr,"Error: Init failed !\n");
exit(1);
}
switch(action){
case READ:
content_read(file,addr);
break;
case WRITE:
content_write(file,addr);
break;
case ERASE: erase(file,addr,EEPROM_SIZE);
break;
case PHEADER: pheader(file,addr);
break;
default:
fprintf(stderr,"Internal error!\n");
exit(1); break;
}
close(file);
exit(0);
}
/****************************************************************************/
/* Low level function */
/* */
/****************************************************************************/
int block_write(int file,int dev_addr,int eeprom_addr,unsigned char *buf,int lenght){
unsigned char buff[2];
struct i2c_msg msg[2];
struct i2c_ioctl_rdwr_data {
struct i2c_msg *msgs; /* ptr to array of simple messages */
int nmsgs; /* number of messages to exchange */
} msgst;
if ( lenght > (MAX_BLK_SIZE) ) {
fprintf(stderr,
"Error: Block too large:\n");
}
//bar();
made_address(eeprom_addr,buff);
msg[0].addr = dev_addr;
msg[0].flags = 0;
msg[0].len = 2;
msg[0].buf = buff;
msg[1].addr = dev_addr;
msg[1].flags = I2C_M_NOSTART;
msg[1].len = lenght;
msg[1].buf = buf;
msgst.msgs = msg;
msgst.nmsgs = 2;
if (ioctl(file,I2C_RDWR,&msgst) < 0){
fprintf(stderr,
"Error: Transaction failed: %s\n",
strerror(errno));
return 1;
}
return 0;
}
int block_read(int file,int dev_addr,int eeprom_addr,unsigned char *buf){
int ln;
char buff[2]; //={0x0,0x0};
struct i2c_msg msg[2];
struct i2c_ioctl_rdwr_data {
struct i2c_msg *msgs; /* ptr to array of simple messages */
int nmsgs; /* number of messages to exchange */
} msgst;
made_address(eeprom_addr,buff);
ln=0;
//bar();
msg[0].addr = dev_addr;
msg[0].flags = 0;
msg[0].len = 2;
msg[0].buf = buff;
msg[1].addr = dev_addr;
msg[1].flags = I2C_M_RD;
msg[1].len = MAX_BLK_SIZE;
msg[1].buf = buf;
msgst.msgs = msg;
msgst.nmsgs = 2;
if ((ln = ioctl(file, I2C_RDWR, &msgst)) < 0) {
fprintf(stderr,
"Error: Read error:%d\n",ln);
return ln;
}
return ln;
}
void made_address(int addr,unsigned char *buf){
int k;
//addr = addr & 0xFFFF; /*odstranim nepoterbne bity*/
k=addr;
buf[1]=(unsigned char) (k & 0xFF); //vyrobim druhy byte adresy
k=addr & 0xFF00 ;
buf[0]= ((unsigned char) (k >> 8)) & 0x7F;
return;
}
int init(char *device,int addr) {
int file;
unsigned long funcs;
if ((file = open(device,O_RDWR)) < 0) {
fprintf(stderr,"Error: Could not open file %s\n",
device);
return 0;
}
/* check adapter functionality */
if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
fprintf(stderr,
"Error: Could not get the adapter functionality matrix: %s\n",
strerror(errno));
close(file);
return 0;
}
/* The I2C address */
if (ioctl(file,I2C_SLAVE,addr) < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong */
fprintf(stderr,
"Error: Cannot communicate with slave: %s\n",
strerror(errno));
close(file);
return 0;
}
return file;
}
int content_write(int file, int addr){
unsigned char buf[MAX_BLK_SIZE];
unsigned char pom;
int i, j, k, delka, addr_cnt;
delka=0;
addr_cnt=HEAD_SIZE;
k=0;
for(j=0;j<MAX_BLK_SIZE;j++)
buf[j]=0;
i=0;
for(;;) {
delka=fread(&pom,1,1,stdin);
if( delka > 0 ){
buf[i]=pom;
}
if(i==(MAX_BLK_SIZE-1) || (delka < 1)) {
if(block_write(file,addr,addr_cnt,buf,delka<1?i:(i+1)) !=0) {
fprintf(stderr,"Block write failed\n");
return 1;
}
//printf("i:%d\n",i);
addr_cnt=addr_cnt + i + (delka==1?1:0); //+i
for(j=0;j<MAX_BLK_SIZE;j++)
buf[j]=0;
i=0;
if(delka<1) {
//pisu EOF
if(inode_write(file,addr,(addr_cnt-HEAD_SIZE)) !=0) {
fprintf(stderr,"Inode write failed\n");
return 1;
}
break;
}
} else i++;
}
return 0;
}
int content_read(int file, int addr){
unsigned char buf[MAX_BLK_SIZE];
int i, j, k, delka;
delka=0;
k=0;
inode_read(file,addr,p_ind );
for(i=HEAD_SIZE;i<= (HEAD_SIZE + p_ind->data_len);i=i+MAX_BLK_SIZE ) {
if(block_read(file,addr,i,buf) !=0) {
fprintf(stderr,"Block read failed\n");
return 1;
}
if( (HEAD_SIZE + p_ind->data_len - i) < MAX_BLK_SIZE ) {
k= HEAD_SIZE + p_ind->data_len - i;
}else {
k=MAX_BLK_SIZE;
}
for(j=0;j<k ;j++){
putc(buf[j],stdout);
}
}
return 0;
}
void erase(int file, int addr,int eeprom_size){
unsigned char buf[MAX_BLK_SIZE];
int i, j, k, delka;
delka=0;
k=0;
for(j=0;j<MAX_BLK_SIZE;j++)
buf[j]=0;
for(i=0;i<eeprom_size;i=i+MAX_BLK_SIZE) {
if(block_write(file,addr,i,buf,MAX_BLK_SIZE) !=0) {
fprintf(stderr,"Block write failed\n");
return;
}
}
return;
}
void bar(void){
if( stav > 70 ) stav=0;
switch(stav) {
case 10: fwrite("\\",1,1,stderr);
fflush(stderr);
rewind(stderr);
break;
case 20: fwrite("|",1,1,stderr);
fflush(stderr);
rewind(stderr);
break;
case 30: fwrite("/",1,1,stderr);
fflush(stderr);
rewind(stderr);
break;
case 40: fwrite("-",1,1,stderr);
fflush(stderr);
rewind(stderr);
break;
case 50: fwrite("\\",1,1,stderr);
fflush(stderr);
rewind(stderr);
break;
case 60: fwrite("|",1,1,stderr);
fflush(stderr);
rewind(stderr);
break;
case 70: fwrite("/",1,1,stderr);
fflush(stderr);
rewind(stderr);
break;
}
stav++;
}
int inode_write(int file,int dev_addr,int lenght){
unsigned char buff[2];
struct i2c_msg msg[2];
struct i2c_ioctl_rdwr_data {
struct i2c_msg *msgs; /* ptr to array of simple messages */
int nmsgs; /* number of messages to exchange */
} msgst;
m_ind.timestamp=time(NULL);
m_ind.data_len=lenght;
//bar();
made_address(START_ADDR,buff);
msg[0].addr = dev_addr;
msg[0].flags = 0;
msg[0].len = 2;
msg[0].buf = buff;
msg[1].addr = dev_addr;
msg[1].flags = I2C_M_NOSTART;
msg[1].len = sizeof(struct mini_inode);
msg[1].buf = (char *) &m_ind;
msgst.msgs = msg;
msgst.nmsgs = 2;
if (ioctl(file,I2C_RDWR,&msgst) < 0){
fprintf(stderr,
"Error: Transaction failed: %s\n",
strerror(errno));
return 1;
}
return 0;
}
int inode_read(int file,int dev_addr,void *p_inode ){
#define POK 32
int ln;
char buff[2]; //={0x0,0x0};
struct i2c_msg msg[2];
struct i2c_ioctl_rdwr_data {
struct i2c_msg *msgs; /* ptr to array of simple messages */
int nmsgs; /* number of messages to exchange */
} msgst;
made_address(START_ADDR,buff);
ln=0;
//bar();
msg[0].addr = dev_addr;
msg[0].flags = 0;
msg[0].len = 2;
msg[0].buf = buff;
msg[1].addr = dev_addr;
msg[1].flags = I2C_M_RD;
msg[1].len = sizeof(struct mini_inode);
msg[1].buf = p_inode;
msgst.msgs = msg;
msgst.nmsgs = 2;
if ((ln = ioctl(file, I2C_RDWR, &msgst)) < 0) {
fprintf(stderr,
"Error: Read error:%d\n",ln);
return ln;
}
return ln;
}
void pheader(int file,int dev_addr){
struct tm *p_tm;
char time_buf[15],*p_buf;
p_buf=time_buf;
inode_read(file,dev_addr,p_ind );
p_tm=localtime(&p_ind->timestamp);
strftime(p_buf,sizeof(time_buf),"%Y%m%d%H%M%S",p_tm);
printf("LEN=%d,TIME=%s\n",p_ind->data_len,p_buf);
return;
}
#ifdef WARNINC
void warn(void)
{
fprintf(stderr,"\n\n!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!\n");
fprintf(stderr,"This program is intended for use on eeproms\nusing external busses such as i2c-pport.\n");
fprintf(stderr,"Do not use this on your SDRAM DIMM EEPROMS\nunless you REALLY REALLY know what you are\ndoing!!! Doing so will render your SDRAM\nUSELESS and leave your system UNBOOTABLE!!!\n");
fprintf(stderr,"To disable this warning use -force\n");
fprintf(stderr,"\n\nPress ENTER to continue or hit Control-C NOW !!!!\n\n\n");
getchar();
}
#endif