]> Zhao Yanbai Git Server - minix.git/commitdiff
eepromread: simple program to view eeprom contents 80/680/2
authorThomas Cort <tcort@minix3.org>
Mon, 15 Jul 2013 14:29:37 +0000 (10:29 -0400)
committerThomas Cort <tcort@minix3.org>
Mon, 15 Jul 2013 21:03:18 +0000 (17:03 -0400)
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

commands/Makefile
commands/eepromread/Makefile [new file with mode: 0644]
commands/eepromread/board_info.c [new file with mode: 0644]
commands/eepromread/eepromread.1 [new file with mode: 0644]
commands/eepromread/eepromread.c [new file with mode: 0644]
commands/eepromread/eepromread.h [new file with mode: 0644]
distrib/sets/lists/minix/md.evbarm
etc/usr/rc

index aa9c0d42ae657e7f83aa23e03f9272642b5a7db1..3cae84cb1740c49c6fa683df13ff4faa78f7e240 100644 (file)
@@ -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>
diff --git a/commands/eepromread/Makefile b/commands/eepromread/Makefile
new file mode 100644 (file)
index 0000000..66c0b43
--- /dev/null
@@ -0,0 +1,5 @@
+PROG=  eepromread
+SRCS=  eepromread.c eepromread.h board_info.c
+MAN=   eepromread.1
+
+.include <bsd.prog.mk>
diff --git a/commands/eepromread/board_info.c b/commands/eepromread/board_info.c
new file mode 100644 (file)
index 0000000..0000868
--- /dev/null
@@ -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;
+}
diff --git a/commands/eepromread/eepromread.1 b/commands/eepromread/eepromread.1
new file mode 100644 (file)
index 0000000..a3bbfc9
--- /dev/null
@@ -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.
diff --git a/commands/eepromread/eepromread.c b/commands/eepromread/eepromread.c
new file mode 100644 (file)
index 0000000..1d9e84f
--- /dev/null
@@ -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;
+}
+
diff --git a/commands/eepromread/eepromread.h b/commands/eepromread/eepromread.h
new file mode 100644 (file)
index 0000000..ee04677
--- /dev/null
@@ -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 */
index 5d9778808bb6aece4f40b609b67c7a3dd7c6d7c2..e671d2f73112f263dbd7ca103ba1265cc9de13a6 100644 (file)
@@ -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
 ./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
index 21c2cd99c0108cb12e762fde9c24a23674b56a25..ab8595c8f6447c10f63459cbfb1747e194eb1437 100644 (file)
@@ -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" ]