aboutsummaryrefslogtreecommitdiffstats
path: root/meta-baldeagle/recipes-applications/spi-test/files/spirom-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'meta-baldeagle/recipes-applications/spi-test/files/spirom-test.c')
-rw-r--r--meta-baldeagle/recipes-applications/spi-test/files/spirom-test.c765
1 files changed, 434 insertions, 331 deletions
diff --git a/meta-baldeagle/recipes-applications/spi-test/files/spirom-test.c b/meta-baldeagle/recipes-applications/spi-test/files/spirom-test.c
index e7dfe6f1..9006c130 100644
--- a/meta-baldeagle/recipes-applications/spi-test/files/spirom-test.c
+++ b/meta-baldeagle/recipes-applications/spi-test/files/spirom-test.c
@@ -31,39 +31,34 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
-#include <getopt.h>
#include <fcntl.h>
#include <string.h>
-#include <errno.h>
+#include <dirent.h>
+#include <signal.h>
+
+#include <sys/types.h>
#include <sys/ioctl.h>
-#include <linux/types.h>
+#include <sys/stat.h>
+
+#include <readline/readline.h>
#include "spirom.h"
-#define SPI_APP_VERSION "0.1"
+#define SPI_APP_VERSION "1.0"
-#define WREN 0x06
-#define WRDI 0x04
-#define RDSR 0x05
-#define RDID 0x9F
-#define CHIP_ERASE 0x60
-#define SECTOR_ERASE 0x20
-#define BLOCK_ERASE 0xD8
-#define READ 0x03
-#define WRITE 0x02
+static int device_opened = 0;
+static char filename[20];
+static int fd = -1;
-static void pabort(const char *s)
+char *show_prompt(void)
{
- perror(s);
- abort();
+ return "$ ";
}
-static const char *device = "/dev/spirom0.0";
-static char command[20];
-static int inputfile_fd;
-static int outfile_fd;;
-static unsigned long address;
-static unsigned int num_bytes;
+void sighandler(int sig)
+{
+ /* Do nothing. That is the idea. */
+}
void show_license(void)
{
@@ -72,7 +67,7 @@ void show_license(void)
"* Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
"* All rights reserved.\n"
"*\n"
- "* Redistribution and use in source and binary forms, with or without\n"
+ "* Redistribution and use in source and binary forms, with or without\n"
"* modification, are permitted provided that the following conditions are met:\n"
"* * Redistributions of source code must retain the above copyright\n"
"* notice, this list of conditions and the following disclaimer.\n"
@@ -98,188 +93,302 @@ void show_license(void)
"***************************************************************************/\n");
}
-void parse_command(int fd)
+void print_usage(void)
+{
+ printf("\nCommands Supported ->\n");
+ printf(" enumerate : List all SPI device nodes available\n");
+ printf(" setdevice <dev_id> : Set the SPI device number to access\n");
+ printf(" wren : Enable Write operation on SPI device\n");
+ printf(" wrdi : Disable Write operation on SPI device\n");
+ printf(" chiperase : Erase entire ROM chip\n");
+ printf(" rdsr : Read status register of ROM device\n");
+ printf(" rdid : Read device identification string\n");
+ printf(" sectorerase <addr> <num_sectors> : Erase a fixed number of sectors starting at the address\n"
+ " specified\n");
+ printf(" blockerase <addr> <num_blocks> : Erase a fixed number of blocks starting at the address\n"
+ " specified\n");
+ printf(" read <addr> <num_bytes> <filename> : Read a fixed number of bytes starting at address\n"
+ " specified, and output the contents into file\n");
+ printf(" write <addr> <num_bytes> <filename> : Read a fixed number of bytes from file and output\n"
+ " the contents to the device starting at the address\n"
+ " specified\n");
+ printf(" license : Displays the terms of LICENSE for this application\n");
+ printf(" help : Displays help text\n");
+ printf(" exit : Exits the application\n\n");
+}
+
+void parse_cmd(const char *cmdline)
{
- uint8_t cmd_byte;
struct spi_ioc_transfer tr;
unsigned int bytes_chunks;
unsigned int remaining_bytes;
+ int addr;
int ret;
- /* Zero initialize spi_ioc_transfer */
- memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- if ((strncmp(command, "WREN", 4) == 0) ||
- (strncmp(command, "wren", 4) == 0)) {
- /* Command without data */
- tr.buf[0] = WREN;
+ if (strncmp(cmdline, "enumerate", 9) == 0) {
+ DIR *dir;
+ struct dirent *dir_entry;
+ int device_found = 0;
+
+ /* Get the directory handle */
+ if ((dir = opendir("/dev")) == NULL) {
+ printf("\n\nFailed to open directory /dev. Probably you "
+ "do not have right privilege!\n\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Iterate over all the directory entries */
+ while ((dir_entry = readdir(dir)) != NULL) {
+ /*
+ * If the file is a character device, and its signature
+ * matches spirom, then we print the corresponding file.
+ */
+ if ((dir_entry->d_type == DT_CHR) &&
+ (strncmp(dir_entry->d_name, "spirom", 6) == 0)) {
+ printf("/dev/%s\n", dir_entry->d_name);
+ device_found = 1;
+ }
+ }
+
+ printf("\n");
+
+ /*
+ * In case we did not find even a single entry, we print a
+ * message and exit.
+ */
+ if (!device_found) {
+ printf("\n\nNo spirom device nodes found, load spirom "
+ "kernel module and try again\n\n");
+ exit(EXIT_FAILURE);
+ }
+ } else if (strncmp(cmdline, "setdevice", 9) == 0) {
+ char input[2 + 1];
+ int file_desc;
+
+ cmdline += 10;
+ memset(input, 0, 3);
+ if (sscanf(cmdline, "%s", input) < 1) {
+ printf("\nInvalid inputs, please try again\n\n");
+ return;
+ }
+
+ memset(filename, 0, 20);
+ snprintf(filename, 19, "/dev/spirom%s", input);
+ file_desc = open(filename, O_RDWR);
+ if (file_desc < 0) {
+ printf("\nError opening file %s\n\n", filename);
+ return;
+ }
+
+ /* Once we have validated inputs, we store them into the global
+ * variables used at other places in the program.
+ */
+ fd = file_desc;
+ device_opened = 1;
+ printf("\nSPI device set to /dev/spirom%s\n\n", input);
+ } else if (strncmp(cmdline, "wren", 4) == 0) {
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
+ /* command without data */
+ tr.buf[0] = ROM_WREN;
tr.direction = 0;
tr.len = 0;
tr.addr_present = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
- pabort("can't send spi message");
- } else if ((strncmp(command, "WRDI", 4) == 0) ||
- (strncmp(command, "wrdi", 4) == 0)) {
- /* Command without data */
- tr.buf[0] = WRDI;
+ printf("\nError executing WREN command\n\n");
+ else
+ printf("\n...WREN completed successfully\n\n");
+ } else if (strncmp(cmdline, "wrdi", 4) == 0) {
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
+ /* command without data */
+ tr.buf[0] = ROM_WRDI;
tr.direction = 0;
tr.len = 0;
tr.addr_present = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
- pabort("can't send spi message");
- } else if ((strncmp(command, "CHIPERASE", 4) == 0) ||
- (strncmp(command, "chiperase", 4) == 0)) {
+ printf("\nError executing WRDI command\n\n");
+ else
+ printf("\n...WRDI completed successfully\n\n");
+ } else if (strncmp(cmdline, "chiperase", 9) == 0) {
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
- else if ((tr.buf[1] & 0x02) == 0x00) {
- printf("cannot execute command, write is disabled\n");
- exit(1);
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");;
+ return;
+ } else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("\nCannot execute RDSR command, write is disabled\n\n");
+ return;
}
/* Command without data */
- tr.buf[0] = CHIP_ERASE;
+ tr.buf[0] = ROM_CHIP_ERASE;
tr.direction = 0;
tr.len = 0;
tr.addr_present = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) {
- if (errno == EPERM)
- printf("\n\nIMC is enabled in your platform. "
- "Trying to perform CHIPERASE is not "
- "safe. If you really want to perform "
- "this operation, either disable IMC in "
- "BIOS, or set jumper JU105 to 2-3 "
- "position to disable IMC and then "
- "try again. Do not forget to remove "
- "power to the platform before changing "
- "jumper settings\n\n");
-
- pabort("can't send spi message");
+ printf("\nError executing CHIPERASE command\n\n");
+ return;
}
+ printf("\n\nCHIPERASE operation in progress, please do not "
+ " stop in between.\n\n");
+
/* Make sure WIP has been reset */
while (1) {
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ }
if ((tr.buf[1] & 0x01) == 0x00)
break;
}
- } else if ((strncmp(command, "RDSR", 4) == 0) ||
- (strncmp(command, "rdsr", 4) == 0)) {
+
+ printf("\n\n...CHIPERASE completed successfully\n\n");
+ /* Restore signal handler to default */
+ } else if (strncmp(cmdline, "rdsr", 4) == 0) {
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
/* Command with response */
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ }
/*
* The 1-byte response will be stored in tr.buf,
* so print it out
*/
- printf("command: 0x%.2x response: 0x%.2x\n", tr.buf[0],
- tr.buf[1]);
- } else if ((strncmp(command, "RDID", 4) == 0) ||
- (strncmp(command, "rdid", 4) == 0)) {
+ printf("\nRDSR command returned: 0x%.2x\n\n", tr.buf[1]);
+ } else if (strncmp(cmdline, "rdid", 4) == 0) {
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
/* Command with response */
- tr.buf[0] = RDID;
+ tr.buf[0] = ROM_RDID;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 3;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing RDID command\n\n");
+ return;
+ }
/*
* The 3-bytes response will be stored in tr.buf,
* so print it out
*/
- printf("command: 0x%.2x response: 0x%.2x%.2x%.2x\n", tr.buf[0],
- tr.buf[1], tr.buf[2], tr.buf[3]);
- } else if ((strncmp(command, "SECTORERASE", 6) ==0) ||
- (strncmp(command, "sectorerase", 6) ==0)) {
+ printf("\nRDID command returned: 0x%.2x%.2x%.2x\n", tr.buf[1],
+ tr.buf[2], tr.buf[3]);
+ } else if (strncmp(cmdline, "sectorerase", 11) == 0) {
+ int nsectors;
int i;
- tr.buf[0] = RDSR;
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
+ cmdline += 12;
+ if (sscanf(cmdline, "0x%x 0x%x", &addr, &nsectors) < 2) {
+ printf("\nInvalid inputs, please try again\n\n");
+ return;
+ }
+
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
- else if ((tr.buf[1] & 0x02) == 0x00) {
- printf("cannot execute command, write is disabled\n");
- exit(1);
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ } else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("\nCannot execute SECTORERASE command, write is disabled\n\n");
+ return;
}
- /*
- * num_bytes here is a little bit of misnomer, it indicates the
- * number of sectors to be erased, rather than the number of
- * bytes to be erased.
- */
- for (i = 0; i < num_bytes; i++) {
+ printf("\n\nSECTORERASE operation in progress, please do not "
+ " stop in between.\n\n");
+
+ for (i = 0; i < nsectors; i++) {
/* Write Enable before Sector Erase */
- tr.buf[0] = WREN;
+ tr.buf[0] = ROM_WREN;
tr.direction = 0;
tr.len = 0;
tr.addr_present = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing WREN command\n\n");
+ return;
+ }
/* Command with address but no data */
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = SECTOR_ERASE;
- tr.buf[3] = address & 0xff;
- tr.buf[2] = (address >> 8) & 0xff;
- tr.buf[1] = (address >> 16) & 0xff;
+ tr.buf[0] = ROM_SECTOR_ERASE;
+ tr.buf[3] = addr & 0xff;
+ tr.buf[2] = (addr >> 8) & 0xff;
+ tr.buf[1] = (addr >> 16) & 0xff;
tr.addr_present = 1;
tr.direction = 0;
tr.len = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) {
- if (errno == EPERM)
- printf("\n\nIMC is enabled in your "
- "platform. Trying to perform "
- "SECTORERASE is not safe. If you "
- "really want to perform this "
- "operation, either disable IMC "
- "in BIOS, or set jumper JU105 "
- "to 2-3 position to disable IMC "
- "and then try again. Do not "
- "forget to remove power to the "
- "platform before changing jumper "
- "settings.\n\n");
-
- pabort("can't send spi message");
+ printf("\nError executing SECTORERASE command\n\n");
+ return;
}
- /* point to the next 4k block */
- address += 4 * 1024;
+ /* point to the next 4k sector */
+ addr += 4 * 1024;
/*
* Before the next loop, we need to make sure that WIP
@@ -287,80 +396,86 @@ void parse_command(int fd)
*/
while (1) {
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ }
if ((tr.buf[1] & 0x01) == 0x00)
break;
}
}
- } else if ((strncmp(command, "BLOCKERASE", 5) == 0) ||
- (strncmp(command, "blockerase", 5) == 0)) {
+
+ printf("\n\n...SECTORERASE completed successfully\n\n");
+ } else if (strncmp(cmdline, "blockerase", 10) == 0) {
+ int nblocks;
int i;
- tr.buf[0] = RDSR;
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
+ cmdline += 11;
+ if (sscanf(cmdline, "0x%x 0x%x", &addr, &nblocks) < 2) {
+ printf("\nInvalid inputs, please try again\n\n");
+ return;
+ }
+
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
- else if ((tr.buf[1] & 0x02) == 0x00) {
- printf("cannot execute command, write is disabled\n");
- exit(1);
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ } else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("\nError executing BLOCKERASE command, write is disabled\n\n");
+ return;
}
- /*
- * num_bytes indicates the number of blocks to be erased,
- * rather than the number of bytes to be erased.
- */
- for (i = 0; i < num_bytes; i++) {
+ printf("\n\nBLOCKERASE operation in progress, please do not "
+ " stop in between.\n\n");
+
+ for (i = 0; i < nblocks; i++) {
/* Write Enable before Block Erase */
- tr.buf[0] = WREN;
+ tr.buf[0] = ROM_WREN;
tr.direction = 0;
tr.len = 0;
tr.addr_present = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing WREN command\n\n");
+ return;
+ }
/* Command with address but no data */
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = BLOCK_ERASE;
- tr.buf[3] = address & 0xff;
- tr.buf[2] = (address >> 8) & 0xff;
- tr.buf[1] = (address >> 16) & 0xff;
+ tr.buf[0] = ROM_BLOCK_ERASE;
+ tr.buf[3] = addr & 0xff;
+ tr.buf[2] = (addr >> 8) & 0xff;
+ tr.buf[1] = (addr >> 16) & 0xff;
tr.addr_present = 1;
tr.direction = 0;
tr.len = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) {
- if (errno == EPERM)
- printf("\n\nIMC is enabled in your "
- "platform. Trying to perform "
- "BLOCKERASE is not safe. If "
- "you really want to perform "
- "this operation, either disable "
- "IMC in BIOS, or set jumper "
- "JU105 to 2-3 position to "
- "disable IMC and then try "
- "again. Do not forget to remove "
- "power to the platform before "
- "changing jumper settings.\n\n");
-
- pabort("can't send spi message");
+ printf("\nError executing BLOCKERASE command\n\n");
+ return;
}
/* point to the next 64k block */
- address += 64 * 1024;
+ addr += 64 * 1024;
/*
* Before the next loop, we need to make sure that WIP
@@ -368,151 +483,205 @@ void parse_command(int fd)
*/
while (1) {
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ }
if ((tr.buf[1] & 0x01) == 0x00)
break;
}
}
- } else if ((strncmp(command, "READ", 4) == 0) ||
- (strncmp(command, "read", 4) ==0)) {
+
+ printf("\n\n...BLOCKERASE completed successfully\n\n");
+ } else if (strncmp(cmdline, "read", 4) == 0) {
+ int nbytes;
+ int outfile_fd;
int i;
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
+ cmdline += 5;
+ memset(filename, 0, 20);
+ if (sscanf(cmdline, "0x%x 0x%x %s", &addr, &nbytes, filename) < 3) {
+ printf("\nInvalid inputs, please try again\n\n");
+ return;
+ }
+
+ /*
+ * Open the output file for writing. Create a new file if not
+ * there, and empty the file before writing if file already
+ * exists.
+ */
+ outfile_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (outfile_fd < 0) {
+ printf("\nError opening file %s for writing\n\n", filename);
+ return;
+ }
+
/*
* We will break down the bytes to be received in chunks of
* of 4-bytes. Data might not be a even multiple of 4. So
* in that case, we will have some remaining bytes <4. We
* handle that separately.
*/
- bytes_chunks = num_bytes / 4;
- remaining_bytes = num_bytes % 4;
+ bytes_chunks = nbytes / 4;
+ remaining_bytes = nbytes % 4;
+
+ printf("\n\nREAD operation in progress.\n\n");
for (i = 0; i < bytes_chunks; i++) {
/* Command with address and data */
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = READ;
+ tr.buf[0] = ROM_READ;
tr.direction = RECEIVE;
/*
* We will store the address into the buffer in little
* endian order.
*/
- tr.buf[3] = address & 0xff;
- tr.buf[2] = (address >> 8) & 0xff;
- tr.buf[1] = (address >> 16) & 0xff;
+ tr.buf[3] = addr & 0xff;
+ tr.buf[2] = (addr >> 8) & 0xff;
+ tr.buf[1] = (addr >> 16) & 0xff;
tr.len = 4;
tr.addr_present = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing READ command\n\n");
+ return;
+ }
/* Write the data read to output file */
if (write(outfile_fd, &tr.buf[4], tr.len) < 0) {
- perror("write error");
- exit(1);
+ printf("\nError writing to file %s\n\n", filename);
+ return;
}
- address += 4;
+ addr += 4;
}
if (remaining_bytes) {
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = READ;
+ tr.buf[0] = ROM_READ;
tr.direction = RECEIVE;
- tr.buf[3] = address & 0xff;
- tr.buf[2] = (address >> 8) & 0xff;
- tr.buf[1] = (address >> 16) & 0xff;
+ tr.buf[3] = addr & 0xff;
+ tr.buf[2] = (addr >> 8) & 0xff;
+ tr.buf[1] = (addr >> 16) & 0xff;
tr.len = remaining_bytes;
tr.addr_present = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing READ command\n\n");
+ return;
+ }
if (write(outfile_fd, &tr.buf[4], tr.len) < 0) {
- perror("write error");
- exit(1);
+ printf("\nError writing to file %s\n\n", filename);
+ return;
}
}
- } else if ((strncmp(command, "WRITE", 5) == 0) ||
- (strncmp(command, "write", 5) ==0)) {
+
+ printf("\n\n...READ completed successfully\n\n");
+ close(outfile_fd);
+ } else if (strncmp(cmdline, "write", 5) == 0) {
+ int nbytes;
+ int infile_fd;
int i;
+ if (!device_opened) {
+ printf("\nSPI device needs to be set before you can "
+ "perform this operation\n\n");
+ return;
+ }
+
+ cmdline += 6;
+ memset(filename, 0, 20);
+ if (sscanf(cmdline, "0x%x 0x%x %s", &addr, &nbytes, filename) < 3) {
+ printf("\nInvalid inputs, please try again\n\n");
+ return;
+ }
+
+ /* Open the input file for reading*/
+ infile_fd = open(filename, O_RDONLY);
+ if (infile_fd < 0) {
+ printf("\nError opening file %s for reading\n\n", filename);
+ return;
+ }
+
/*
* We will break down the bytes to be transmitted in chunks of
* of 4-bytes. Like for read, we might not have data in an
* even multiple of 4 bytes. So we will handle the remaining
* bytes in the end.
*/
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
- else if ((tr.buf[1] & 0x02) == 0x00) {
- printf("cannot execute command, write is disabled\n");
- exit(1);
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ } else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("\nCannot execute WRITE command, write is disabled\n\n");
+ return;
}
- bytes_chunks = num_bytes / 4;
- remaining_bytes = num_bytes % 4;
+ bytes_chunks = nbytes / 4;
+ remaining_bytes = nbytes % 4;
+
+ printf("\n\nWRITE operation in progress, please do not "
+ " stop in between.\n\n");
for (i = 0; i < bytes_chunks; i++) {
- tr.buf[0] = WREN;
+ tr.buf[0] = ROM_WREN;
tr.direction = 0;
tr.len = 0;
tr.addr_present = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing WREN command\n\n");
+ return;
+ }
/* Command with data and address */
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = WRITE;
+ tr.buf[0] = ROM_WRITE;
tr.direction = TRANSMIT;
/*
* We will store the address into the buffer in little
* endian order.
*/
- tr.buf[3] = address & 0xff;
- tr.buf[2] = (address >> 8) & 0xff;
- tr.buf[1] = (address >> 16) & 0xff;
+ tr.buf[3] = addr & 0xff;
+ tr.buf[2] = (addr >> 8) & 0xff;
+ tr.buf[1] = (addr >> 16) & 0xff;
tr.len = 4;
tr.addr_present = 1;
- /* Read 4 bytes from inputfile to buffer */
- if (read(inputfile_fd, &tr.buf[4], tr.len) < 0) {
- perror("read error");
- exit(1);
+ /* Read 4 bytes from input file to buffer */
+ if (read(infile_fd, &tr.buf[4], tr.len) < 0) {
+ printf("\nError reading from file %s\n\n", filename);
+ return;
}
+
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) {
- if (errno == EPERM)
- printf("\n\nIMC is enabled in your "
- "platform. Trying to perform "
- "WRITE is not safe. If you "
- "really want to perform this "
- "operation, either disable IMC "
- "in BIOS, or set jumper JU105 "
- "to 2-3 position to disable IMC "
- "and then try again. Do not "
- "forget to remove power to the "
- "platform before changing jumper "
- "settings.\n\n");
-
- pabort("can't send spi message");
+ printf("\nError executing WRITE command\n\n");
+ return;
}
- address += 4;
+ addr += 4;
/*
* Before the next loop, we need to make sure that WIP
@@ -520,14 +689,16 @@ void parse_command(int fd)
*/
while (1) {
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ }
if ((tr.buf[1] & 0x01) == 0x00)
break;
@@ -535,161 +706,93 @@ void parse_command(int fd)
}
if (remaining_bytes) {
- tr.buf[0] = WREN;
+ tr.buf[0] = ROM_WREN;
tr.direction = 0;
tr.len = 0;
tr.addr_present = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing WREN command\n\n");
+ return;
+ }
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = WRITE;
+ tr.buf[0] = ROM_WRITE;
tr.direction = TRANSMIT;
- tr.buf[3] = address & 0xff;
- tr.buf[2] = (address >> 8) & 0xff;
- tr.buf[1] = (address >> 16) & 0xff;
+ tr.buf[3] = addr & 0xff;
+ tr.buf[2] = (addr >> 8) & 0xff;
+ tr.buf[1] = (addr >> 16) & 0xff;
tr.len = remaining_bytes;
tr.addr_present = 1;
- if (read(inputfile_fd, &tr.buf[4], tr.len) < 0) {
- perror("read error");
- exit(1);
+ if (read(infile_fd, &tr.buf[4], tr.len) < 0) {
+ printf("\nError reading from file %s\n\n", filename);
+ return;
}
+
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing WRITE command\n\n");
+ return;
+ }
while (1) {
memset(&tr, 0, sizeof(struct spi_ioc_transfer));
- tr.buf[0] = RDSR;
+ tr.buf[0] = ROM_RDSR;
tr.direction = RECEIVE;
tr.addr_present = 0;
tr.len = 1;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- if (ret < 1)
- pabort("can't send spi message");
+ if (ret < 1) {
+ printf("\nError executing RDSR command\n\n");
+ return;
+ }
if ((tr.buf[1] & 0x01) == 0x00)
break;
}
}
- } else
- pabort("Unrecognized command, please try again.\n");
-}
-
-static void print_usage(const char *prog)
-{
- printf("\nUsage: sudo %s [-DCAnio] [arguments]\n\n", prog);
- puts(" -D --device SPI ROM device to use\n"
- " (default /dev/spirom0.0)\n\n"
- " -C --command command to send to the device\n"
- " (WREN/WRDI/RDSR/RDID/CHIPERASE/SECTORERASE/\n"
- " BLOCKERASE/READ/WRITE)\n\n"
- " -A --address offset in decimal, into the device to read\n"
- " from or write to. For a ROM size of 8MB,\n"
- " address can go from 0 to 8388608. Negative\n"
- " offsets are not valid, but the program\n"
- " won't complain and convert it to its\n"
- " unsigned equivalent.\n\n"
- " -n --num-bytes number of bytes to be read from or written\n"
- " to. Depending on the address, this can\n"
- " take values from 0 to 8388608 for a ROM\n"
- " size of 8MB.\n\n"
- " In case of SECTORERASE and BLOCKERASE\n"
- " commands, num-bytes actually takes the\n"
- " number of sectors and blocks to be erased\n"
- " respectively, rather than the number of\n"
- " bytes.\n\n"
- " -i --input-file file to be used as input.\n\n"
- " -o --output-file file to be used for output. Remember that if\n"
- " an existing filename is given, its contents\n"
- " will be overwritten.\n"
- " -l --license displays the terms of LICENSE for this application\n\n");
- exit(1);
-}
-
-static void parse_opts(int argc, char *argv[])
-{
- if (argc == 1)
- print_usage(argv[0]);
- while (1) {
- static const struct option lopts[] = {
- { "device", 1, 0, 'D' },
- { "command", 1, 0, 'C' },
- { "address", 1, 0, 'A' },
- { "num-bytes", 1, 0, 'n' },
- { "input-file", 1, 0, 'i' },
- { "output-file", 1, 0, 'o' },
- { "license", 0, 0, 'l' },
- { NULL, 0, 0, 0 },
- };
- int c;
-
- c = getopt_long(argc, argv, "D:C:A:n:i:o:l", lopts, NULL);
-
- if (c == -1)
- break;
-
- switch (c) {
- case 'D':
- device = optarg;
- break;
- case 'C':
- memset(command, sizeof(command), 0);
- strncpy(command, optarg, sizeof(command));
- break;
- case 'A':
- address = atol(optarg);
- break;
- case 'n':
- num_bytes = atoi(optarg);
- break;
- case 'i':
- inputfile_fd = open(optarg, O_RDONLY);
- if (inputfile_fd < 0) {
- printf("Error opening %s\n", optarg);
- exit(1);
- }
- break;
- case 'o':
- outfile_fd = open(optarg, O_WRONLY | O_CREAT |
- O_TRUNC, 0644);
- if(outfile_fd < 0) {
- printf("Error opening %s\n", optarg);
- exit(1);
- }
- break;
- case 'l':
- show_license();
- exit(0);;
- default:
- print_usage(argv[0]);
- break;
- }
+ printf("\n\n...WRITE completed successfully\n\n");
+ close(infile_fd);
+ } else if (strncmp(cmdline, "license", 7) == 0) {
+ show_license();
+ } else if (strncmp(cmdline, "exit", 4) == 0) {
+ printf("\nExiting...\n");
+ close(fd);
+ exit(EXIT_SUCCESS);
+ } else if (strncmp(cmdline, "help", 4) == 0) {
+ print_usage();
+ } else {
+ printf("\nUnknown command\n");
+ print_usage();
}
}
-int main(int argc, char *argv[])
+int main(void)
{
- int ret = 0;
- int fd;
+ char *cmdline= NULL;
printf("SPI sample application version: %s\n", SPI_APP_VERSION);
printf("Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
"This sample application comes with ABSOLUTELY NO WARRANTY;\n"
"This is free software, and you are welcome to redistribute it\n"
- "under certain conditions; type `license' for details.\n\n");
+ "under certain conditions; type `license` for details.\n\n");
- parse_opts(argc, argv);
+ /* Set the signal handler */
+ signal(SIGINT, sighandler);
- fd = open(device, O_RDWR);
- if (fd < 0)
- pabort("can't open device");
+ while (1) {
+ cmdline = readline(show_prompt());
+ parse_cmd(cmdline);
+ /* Free the memory malloc'ed by readline */
+ free(cmdline);
+ }
- parse_command(fd);
+ /* Restore the default signal handler */
+ signal(SIGINT, SIG_DFL);
- return ret;
+ /* Should never reach here */
+ return 0;
}