eepromread: support for reading from /dev/eeprom
eepromread could only read EEPROMs through the /dev/i2c interface. Once the cat24c256 driver is started and claims/reserves the device, it can no longer be read through the /dev/i2c interface. This patch adds support for reading from EEPROMs through the /dev/eeprom interface. For example, to read the on-board eeprom on the BBB, one would do `eepromread -f /dev/eepromb1s50 -i`. Change-Id: If08ce37231e593982eeb109bdd6d5458ad271108
This commit is contained in:
parent
9a00643262
commit
13054fd168
4 changed files with 67 additions and 35 deletions
|
@ -16,9 +16,12 @@
|
|||
* Attempt to read the board info from an eeprom on this board.
|
||||
*/
|
||||
|
||||
static int board_info_beaglebone(int fd, i2c_addr_t address, int flags);
|
||||
static int board_info_cape_a0(int fd, i2c_addr_t address, int flags);
|
||||
static int board_info_cape_a1(int fd, i2c_addr_t address, int flags);
|
||||
static int board_info_beaglebone(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type);
|
||||
static int board_info_cape_a0(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type);
|
||||
static int board_info_cape_a1(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type);
|
||||
|
||||
/* Memory Layout of the BeagleBone and BeagleBone Black EEPROM */
|
||||
typedef struct beaglebone_info
|
||||
|
@ -68,7 +71,8 @@ typedef struct cape_info_a1
|
|||
} cape_info_a1_t;
|
||||
|
||||
static int
|
||||
board_info_beaglebone(int fd, i2c_addr_t address, int flags)
|
||||
board_info_beaglebone(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type)
|
||||
{
|
||||
int r;
|
||||
int i, j;
|
||||
|
@ -76,7 +80,7 @@ board_info_beaglebone(int fd, i2c_addr_t address, int flags)
|
|||
beaglebone_info_t boneinfo;
|
||||
|
||||
r = eeprom_read(fd, address, 0x0000, &boneinfo,
|
||||
sizeof(beaglebone_info_t), flags);
|
||||
sizeof(beaglebone_info_t), flags, device_type);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "Failed to read BeagleBone info r=%d\n", r);
|
||||
return -1;
|
||||
|
@ -102,7 +106,8 @@ board_info_beaglebone(int fd, i2c_addr_t address, int flags)
|
|||
}
|
||||
|
||||
static int
|
||||
board_info_cape_a0(int fd, i2c_addr_t address, int flags)
|
||||
board_info_cape_a0(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type)
|
||||
{
|
||||
int r;
|
||||
int i, j;
|
||||
|
@ -110,7 +115,7 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags)
|
|||
cape_info_a0_t capeinfo;
|
||||
|
||||
r = eeprom_read(fd, address, 0x0000, &capeinfo,
|
||||
sizeof(cape_info_a0_t), flags);
|
||||
sizeof(cape_info_a0_t), flags, device_type);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "failed to read cape A0 info r=%d\n", r);
|
||||
return -1;
|
||||
|
@ -148,7 +153,8 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags)
|
|||
}
|
||||
|
||||
static int
|
||||
board_info_cape_a1(int fd, i2c_addr_t address, int flags)
|
||||
board_info_cape_a1(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type)
|
||||
{
|
||||
int r;
|
||||
int i, j;
|
||||
|
@ -156,7 +162,7 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags)
|
|||
cape_info_a1_t capeinfo;
|
||||
|
||||
r = eeprom_read(fd, address, 0x0000, &capeinfo,
|
||||
sizeof(cape_info_a1_t), flags);
|
||||
sizeof(cape_info_a1_t), flags, device_type);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "failed to read cape A0 info r=%d\n", r);
|
||||
return -1;
|
||||
|
@ -194,12 +200,14 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags)
|
|||
}
|
||||
|
||||
int
|
||||
board_info(int fd, i2c_addr_t address, int flags)
|
||||
board_info(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type)
|
||||
{
|
||||
int r;
|
||||
uint8_t magic_number[6];
|
||||
|
||||
r = eeprom_read(fd, address, 0x0000, &magic_number, 6, flags);
|
||||
r = eeprom_read(fd, address, 0x0000, &magic_number, 6, flags,
|
||||
device_type);
|
||||
if (r == -1) {
|
||||
printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
|
||||
return 0;
|
||||
|
@ -211,11 +219,11 @@ board_info(int fd, i2c_addr_t address, int flags)
|
|||
|
||||
/* Check if Cape Rev A0, Cape Rev A1, or on-board EEPROM */
|
||||
if (magic_number[4] == 'A' && magic_number[5] == '0') {
|
||||
board_info_cape_a0(fd, address, flags);
|
||||
board_info_cape_a0(fd, address, flags, device_type);
|
||||
} else if (magic_number[4] == 'A' && magic_number[5] == '1') {
|
||||
board_info_cape_a1(fd, address, flags);
|
||||
board_info_cape_a1(fd, address, flags, device_type);
|
||||
} else {
|
||||
board_info_beaglebone(fd, address, flags);
|
||||
board_info_beaglebone(fd, address, flags, device_type);
|
||||
}
|
||||
} else {
|
||||
printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
|
||||
|
|
|
@ -43,6 +43,10 @@ number is sent with the memory address. Use this when reading EDID.
|
|||
.TP 20
|
||||
.B eepromread -f /dev/i2c-3 -n
|
||||
# read the EDID info from the display on I2C bus 3 on the BeagleBoard-xM.
|
||||
.TP 20
|
||||
.B eepromread -f /dev/eepromb1s50 -i
|
||||
# access the EEPROM through the /dev/eeprom interface once the
|
||||
cat24c256 driver has been started.
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fIeepromread\fR is a simple tool for viewing the contents of an EEPROM.
|
||||
|
@ -51,5 +55,5 @@ detect, \fIeepromread\fR can properly format each of the fields and display
|
|||
the information via the \fI-i\fR command line option.
|
||||
.SH NOTES
|
||||
If the \fIcat24c256\fR driver has claimed the EEPROM device that this
|
||||
program is attempting to read from, then this program will fail. Once
|
||||
a driver claims an I2C device, the driver has exclusive access.
|
||||
program is attempting to read from, then you must access it through
|
||||
the /dev/eeprom interface rather than the /dev/i2c interface.
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
#include "eepromread.h"
|
||||
|
||||
static int __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr,
|
||||
void *buf, size_t buflen, int flags);
|
||||
static int eeprom_dump(int fd, i2c_addr_t addr, int flags);
|
||||
void *buf, size_t buflen, int flags, enum device_types device_type);
|
||||
static int eeprom_dump(int fd, i2c_addr_t addr, int flags,
|
||||
enum device_types device_type);
|
||||
|
||||
#define DEFAULT_I2C_DEVICE "/dev/i2c-1"
|
||||
#define DEFAULT_I2C_ADDRESS 0x50
|
||||
|
@ -26,16 +27,11 @@ static int eeprom_dump(int fd, i2c_addr_t addr, int flags);
|
|||
* larger, so to read the whole EEPROM, the task is broken down into 128 byte
|
||||
* chunks in eeprom_read(). __eeprom_read128() does the actual ioctl() to do
|
||||
* the read.
|
||||
*
|
||||
* A future enhancement might be to add support for the /dev/eeprom interface
|
||||
* and if one way fails, fall back to the other. /dev/eeprom can fail if the
|
||||
* eeprom driver isn't running and /dev/i2c can fail if the eeprom driver
|
||||
* claimed the eeprom device.
|
||||
*/
|
||||
|
||||
static int
|
||||
__eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
||||
size_t buflen, int flags)
|
||||
size_t buflen, int flags, enum device_types device_type)
|
||||
{
|
||||
int r;
|
||||
minix_i2c_ioctl_exec_t ioctl_exec;
|
||||
|
@ -46,6 +42,20 @@ __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* if /dev/eeprom, then use read() */
|
||||
if (device_type == EEPROM_DEVICE) {
|
||||
|
||||
off_t offset;
|
||||
|
||||
offset = lseek(fd, memaddr, SEEK_SET);
|
||||
if (offset != memaddr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return read(fd, buf, buflen);
|
||||
|
||||
}
|
||||
/* else /dev/i2c, use i2c_ioctl_exec_t interface */
|
||||
memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t));
|
||||
|
||||
ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP;
|
||||
|
@ -77,7 +87,7 @@ __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
|||
|
||||
int
|
||||
eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
||||
size_t buflen, int flags)
|
||||
size_t buflen, int flags, enum device_types device_type)
|
||||
{
|
||||
int r;
|
||||
uint16_t i;
|
||||
|
@ -87,11 +97,11 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < buflen; i += 128) {
|
||||
|
||||
r = __eeprom_read128(fd, addr, memaddr + i, buf + i,
|
||||
((buflen - i) < 128) ? (buflen - i) : 128, flags);
|
||||
((buflen - i) < 128) ? (buflen - i) : 128, flags,
|
||||
device_type);
|
||||
if (r == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -104,14 +114,14 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
|||
* Read 256 bytes and print it to the screen in HEX and ASCII.
|
||||
*/
|
||||
static int
|
||||
eeprom_dump(int fd, i2c_addr_t addr, int flags)
|
||||
eeprom_dump(int fd, i2c_addr_t addr, int flags, enum device_types device_type)
|
||||
{
|
||||
int i, j, r;
|
||||
uint8_t buf[256];
|
||||
|
||||
memset(buf, '\0', 256);
|
||||
|
||||
r = eeprom_read(fd, addr, 0x0000, buf, 256, flags);
|
||||
r = eeprom_read(fd, addr, 0x0000, buf, 256, flags, device_type);
|
||||
if (r == -1) {
|
||||
return r;
|
||||
}
|
||||
|
@ -163,6 +173,7 @@ main(int argc, char *argv[])
|
|||
int ch, iflag = 0, read_flags = 0;
|
||||
char *device = DEFAULT_I2C_DEVICE;
|
||||
i2c_addr_t address = DEFAULT_I2C_ADDRESS;
|
||||
enum device_types device_type = DEFAULT_DEVICE;
|
||||
|
||||
setprogname(*argv);
|
||||
|
||||
|
@ -185,6 +196,10 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
/* determine whether to use /dev/i2c or /dev/eeprom interface */
|
||||
device_type =
|
||||
strstr(device, "i2c") == NULL ? EEPROM_DEVICE : I2C_DEVICE;
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "open(): %s\n", strerror(errno));
|
||||
|
@ -192,15 +207,16 @@ main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (iflag == 1) {
|
||||
r = board_info(fd, address, read_flags);
|
||||
r = board_info(fd, address, read_flags, device_type);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "board_info(): %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
r = eeprom_dump(fd, address, read_flags);
|
||||
r = eeprom_dump(fd, address, read_flags, device_type);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "eeprom_dump(): %s\n", strerror(errno));
|
||||
fprintf(stderr, "eeprom_dump(): %s\n",
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -213,4 +229,3 @@ main(int argc, char *argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#ifndef __EEPROMREAD_H
|
||||
#define __EEPROMREAD_H
|
||||
|
||||
enum device_types { I2C_DEVICE, EEPROM_DEVICE };
|
||||
#define DEFAULT_DEVICE I2C_DEVICE
|
||||
|
||||
int eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
||||
size_t buflen, int flags);
|
||||
int board_info(int fd, i2c_addr_t address, int flags);
|
||||
size_t buflen, int flags, enum device_types device_type);
|
||||
|
||||
int board_info(int fd, i2c_addr_t address, int flags,
|
||||
enum device_types device_type);
|
||||
|
||||
#endif /* __EEPROMREAD_H */
|
||||
|
|
Loading…
Reference in a new issue