eepromread: simple program to view eeprom contents
This program uses the i2c /dev interface to read the contents of EEPROMs and display it to the user in HEX and ASCII. It also has a mode that can display data in label:value pairs. That mode is used for board detection in the rc script to start the right i2c drivers for the board. Change-Id: I0bf5b13ffab5a89533c762d6881a145cf7f14914
This commit is contained in:
parent
526eb34144
commit
fdbede5dcf
8 changed files with 382 additions and 0 deletions
|
@ -38,4 +38,9 @@ SUBDIR+= atnormalize dosread fdisk loadfont \
|
|||
autopart part partition playwave \
|
||||
recwave repartition screendump
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_ARCH} == "earm"
|
||||
SUBDIR+= eepromread
|
||||
.endif
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
5
commands/eepromread/Makefile
Normal file
5
commands/eepromread/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
PROG= eepromread
|
||||
SRCS= eepromread.c eepromread.h board_info.c
|
||||
MAN= eepromread.1
|
||||
|
||||
.include <bsd.prog.mk>
|
87
commands/eepromread/board_info.c
Normal file
87
commands/eepromread/board_info.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
#include <minix/i2c.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "eepromread.h"
|
||||
|
||||
/*
|
||||
* Attempt to read the board info from an eeprom on this board.
|
||||
* Currently only supports the BeagleBone and BeagleBone Black.
|
||||
* In the future, this could be expanded to support cape EEPROMs.
|
||||
*/
|
||||
|
||||
static int board_info_beaglebone(int fd, i2c_addr_t address);
|
||||
|
||||
/* Memory Layout of the BeagleBone and BeagleBone Black EEPROM */
|
||||
typedef struct beaglebone_info
|
||||
{
|
||||
uint8_t magic_number[4]; /* Should be 0xaa 0x55 0x33 0xee */
|
||||
char board_name[8]; /* Warning: strings not NULL terminated */
|
||||
char version[4];
|
||||
char serial_number[12];
|
||||
char config[32]; /* All 0x00 on BeagleBone White */
|
||||
char mac_addrs[3][6]; /* Not set on BeagleBone White */
|
||||
} beaglebone_info_t;
|
||||
|
||||
static int
|
||||
board_info_beaglebone(int fd, i2c_addr_t address)
|
||||
{
|
||||
int r;
|
||||
int i, j;
|
||||
char s[33];
|
||||
beaglebone_info_t boneinfo;
|
||||
|
||||
r = eeprom_read(fd, address, 0x0000, &boneinfo,
|
||||
sizeof(beaglebone_info_t));
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "Failed to read BeagleBone info r=%d\n", r);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%-16s: 0x%x%x%x%x\n", "MAGIC_NUMBER",
|
||||
boneinfo.magic_number[0], boneinfo.magic_number[1],
|
||||
boneinfo.magic_number[2], boneinfo.magic_number[3]);
|
||||
|
||||
memset(s, '\0', 33);
|
||||
memcpy(s, boneinfo.board_name, 8);
|
||||
fprintf(stdout, "%-16s: %s\n", "BOARD_NAME", s);
|
||||
|
||||
memset(s, '\0', 33);
|
||||
memcpy(s, boneinfo.version, 4);
|
||||
fprintf(stdout, "%-16s: %s\n", "VERSION", s);
|
||||
|
||||
memcpy(s, boneinfo.serial_number, 12);
|
||||
fprintf(stdout, "%-16s: %s\n", "SERIAL_NUMBER", s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
board_info(int fd, i2c_addr_t address)
|
||||
{
|
||||
int r;
|
||||
uint8_t magic_number[4];
|
||||
|
||||
r = eeprom_read(fd, address, 0x0000, &magic_number, 4);
|
||||
if (r == -1) {
|
||||
printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (magic_number[0] == 0xaa && magic_number[1] == 0x55 &&
|
||||
magic_number[2] == 0x33 && magic_number[3] == 0xee) {
|
||||
board_info_beaglebone(fd, address);
|
||||
} else {
|
||||
printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
46
commands/eepromread/eepromread.1
Normal file
46
commands/eepromread/eepromread.1
Normal file
|
@ -0,0 +1,46 @@
|
|||
.TH EEPROMREAD 1
|
||||
.SH NAME
|
||||
eepromread \- read data from an EEPROM
|
||||
.SH SYNOPSIS
|
||||
\fBeepromread\fR [\fB\-i\fR] [\fB\-f\fR \fIdev\fR] [\fB\-a\fR \fIslave_addr\fR]
|
||||
.br
|
||||
.de FL
|
||||
.TP
|
||||
\\fB\\$1\\fR
|
||||
\\$2
|
||||
..
|
||||
.de EX
|
||||
.TP 20
|
||||
\\fB\\$1\\fR
|
||||
# \\$2
|
||||
..
|
||||
.SH OPTIONS
|
||||
.TP 5
|
||||
.B \-i
|
||||
# interpret the data on the EEPROM and display it as a set of fields.
|
||||
.TP 5
|
||||
.B \-f
|
||||
# Use \fIdevice\fR instead of \fI/dev/i2c-1\fR.
|
||||
.TP 5
|
||||
.B \-a
|
||||
# Use \fIslave_address\fR instead of \fI0x50\fR.
|
||||
.SH EXAMPLES
|
||||
.TP 20
|
||||
.B eepromread -i
|
||||
# display the contents of the EEPROM as a list of label:value pairs.
|
||||
.TP 20
|
||||
.B eepromread
|
||||
# display the first 256 bytes of the EEPROM in HEX and ASCII.
|
||||
.TP 20
|
||||
.B eepromread -f /dev/i2c-3 -a 0x54
|
||||
# display the first 256 bytes of the EEPROM on I2C bus 3, slave address 0x54.
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fIeepromread\fR is a simple tool for viewing the contents of an EEPROM.
|
||||
For EEPROM data that is in a specific format that this program knows how to
|
||||
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.
|
205
commands/eepromread/eepromread.c
Normal file
205
commands/eepromread/eepromread.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
#include <minix/i2c.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "eepromread.h"
|
||||
|
||||
static int __eeprom_read32(int fd, i2c_addr_t addr, uint16_t memaddr,
|
||||
void *buf, size_t buflen);
|
||||
static int eeprom_dump(int fd, i2c_addr_t addr);
|
||||
|
||||
#define DEFAULT_I2C_DEVICE "/dev/i2c-1"
|
||||
#define DEFAULT_I2C_ADDRESS 0x50
|
||||
|
||||
/*
|
||||
* The /dev interface only supports 32 byte reads/writes and the EEPROM is
|
||||
* larger, so to read the whole EEPROM, the task is broken down into 32 byte
|
||||
* chunks in eeprom_read(). __eeprom_read32() 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_read32(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
int r;
|
||||
minix_i2c_ioctl_exec_t ioctl_exec;
|
||||
|
||||
if (buflen > I2C_EXEC_MAX_BUFLEN || buf == NULL
|
||||
|| ((memaddr + buflen) < memaddr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t));
|
||||
|
||||
ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP;
|
||||
ioctl_exec.iie_addr = addr;
|
||||
|
||||
/* set the address to read from */
|
||||
ioctl_exec.iie_cmd[0] = ((memaddr >> 8) & 0xff);
|
||||
ioctl_exec.iie_cmd[1] = (memaddr & 0xff);
|
||||
ioctl_exec.iie_cmdlen = 2;
|
||||
|
||||
ioctl_exec.iie_buflen = buflen;
|
||||
|
||||
r = ioctl(fd, MINIX_I2C_IOCTL_EXEC, &ioctl_exec);
|
||||
if (r == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* call was good, copy results to caller's buffer */
|
||||
memcpy(buf, ioctl_exec.iie_buf, buflen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
int r;
|
||||
uint16_t i;
|
||||
|
||||
if (buf == NULL || ((memaddr + buflen) < memaddr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < buflen; i += 32) {
|
||||
|
||||
r = __eeprom_read32(fd, addr, memaddr + i, buf + i,
|
||||
((buflen - i) < 32) ? (buflen - i) : 32);
|
||||
if (r == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read 256 bytes and print it to the screen in HEX and ASCII.
|
||||
*/
|
||||
static int
|
||||
eeprom_dump(int fd, i2c_addr_t addr)
|
||||
{
|
||||
int i, j, r;
|
||||
uint8_t buf[256];
|
||||
|
||||
memset(buf, '\0', 256);
|
||||
|
||||
r = eeprom_read(fd, addr, 0x0000, buf, 256);
|
||||
if (r == -1) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* print table header */
|
||||
for (i = 0; i < 2; i++) {
|
||||
printf(" ");
|
||||
for (j = 0x0; j <= 0xf; j++) {
|
||||
if (i == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("%x", j);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* print table data */
|
||||
for (i = 0x00; i < 0xff; i += 0x10) {
|
||||
|
||||
/* row label */
|
||||
printf("%02x:", i);
|
||||
|
||||
/* row data (in hex) */
|
||||
for (j = 0x0; j <= 0xf; j++) {
|
||||
printf(" %02x", buf[i + j]);
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
|
||||
/* row data (in ASCII) */
|
||||
for (j = 0x0; j <= 0xf; j++) {
|
||||
if (isprint(buf[i + j])) {
|
||||
printf("%c", buf[i + j]);
|
||||
} else {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int r, fd;
|
||||
int ch, iflag = 0;
|
||||
char *device = DEFAULT_I2C_DEVICE;
|
||||
i2c_addr_t address = DEFAULT_I2C_ADDRESS;
|
||||
|
||||
setprogname(*argv);
|
||||
|
||||
while ((ch = getopt(argc, argv, "a:f:i")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
address = strtol(optarg, NULL, 0x10);
|
||||
break;
|
||||
case 'f':
|
||||
device = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
iflag = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "open(): %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (iflag == 1) {
|
||||
r = board_info(fd, address);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "board_info(): %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
r = eeprom_dump(fd, address);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "eeprom_dump(): %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
r = close(fd);
|
||||
if (r == -1) {
|
||||
fprintf(stderr, "close(): %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
8
commands/eepromread/eepromread.h
Normal file
8
commands/eepromread/eepromread.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __EEPROMREAD_H
|
||||
#define __EEPROMREAD_H
|
||||
|
||||
int eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
|
||||
size_t buflen);
|
||||
int board_info(int fd, i2c_addr_t address);
|
||||
|
||||
#endif /* __EEPROMREAD_H */
|
|
@ -10,6 +10,7 @@
|
|||
./multiboot/mod10_vm minix-sys
|
||||
./multiboot/mod11_pfs minix-sys
|
||||
./multiboot/mod12_init minix-sys
|
||||
./usr/bin/eepromread minix-sys
|
||||
./usr/include/arm minix-sys
|
||||
./usr/include/arm/aeabi.h minix-sys
|
||||
./usr/include/arm/ansi.h minix-sys
|
||||
|
@ -101,6 +102,7 @@
|
|||
./usr/lib/libi2cdriver_pic.a minix-sys
|
||||
./usr/lib/libpadconf.a minix-sys
|
||||
./usr/lib/libpadconf_pic.a minix-sys
|
||||
./usr/man/man1/eepromread.1 minix-sys
|
||||
./usr/mdec minix-sys
|
||||
./usr/sbin/cat24c256 minix-sys
|
||||
./usr/sbin/fb minix-sys
|
||||
|
|
24
etc/usr/rc
24
etc/usr/rc
|
@ -194,6 +194,30 @@ start)
|
|||
-args instance=${bus}
|
||||
done
|
||||
echo .
|
||||
|
||||
BOARD_NAME=`eepromread -i | sed -n 's/^BOARD_NAME : \(.*\)$/\1/p'`
|
||||
case "${BOARD_NAME}" in
|
||||
A335BONE)
|
||||
echo "Detected BeagleBone"
|
||||
echo -n "Starting i2c device drivers: "
|
||||
test -e /dev/eepromb1s50 || (cd /dev && MAKEDEV eepromb1s50)
|
||||
up cat24c256 -dev /dev/eepromb1s50 \
|
||||
-label cat24c256.1.50 -args 'bus=1 address=0x50'
|
||||
;;
|
||||
A335BNLT)
|
||||
echo "Detected BeagleBone Black"
|
||||
echo -n "Starting i2c device drivers: "
|
||||
test -e /dev/eepromb1s50 || (cd /dev && MAKEDEV eepromb1s50)
|
||||
up cat24c256 -dev /dev/eepromb1s50 \
|
||||
-label cat24c256.1.50 -args 'bus=1 address=0x50'
|
||||
;;
|
||||
UNKNOWN)
|
||||
echo "Unable to detect board -- assuming BeagleBoard-xM"
|
||||
echo -n "Starting i2c device drivers: "
|
||||
;;
|
||||
esac
|
||||
|
||||
echo .
|
||||
fi
|
||||
|
||||
if [ "$net" ]
|
||||
|
|
Loading…
Reference in a new issue