--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <limits.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <trbnet.h>
+
+static const uint32_t SetupReg = 0x1d001; /* RW */
+static const uint32_t CtrlReg = 0x1d000; /* RW, only if SetupRegister
+ Bits 7-0 == 0x00 */
+static const uint32_t BlockRam = 0x1d100; /* RW */
+
+static const uint16_t HardwareId = 0x0042;
+static const uint32_t MDCFlashRomSelect = 0x1d200;
+
+static uint8_t* pageBuffer = NULL;
+
+static uint8_t* imageBuffer = NULL;
+
+static char deviceName[256] = "/dev/pexor-0";
+
+/* 32-Bit Words: */
+#define BLOCKRAM_SIZE 64
+
+/* 8-Bit Words: */
+#define PAGE_SIZE 256
+static unsigned int NUM_PAGES = 0;
+
+#define BLOCK_SIZE (64 * 1024)
+static unsigned int NUM_BLOCKS = 0;
+
+static FILE *logFile = NULL;
+static const char logFileName[256] = "pexorflash.log";
+
+static const char busy[4][5] = {
+ "|\b",
+ "/\b",
+ "-\b",
+ "\\\b"
+};
+
+static const unsigned int timeout = 10000;
+
+typedef enum {
+ FLASH_INVALID = 0,
+ FLASH_PEXOR23 = 1
+} FlashType;
+
+static const char FlashTypeStr[2][32] =
+ {
+ "INVALID",
+ "PEXOR23"
+ };
+
+static FlashType flashType = FLASH_INVALID;
+static uint32_t manId = 0;
+static const char pexorflash_version[] = "$Revision: 1.1 $";
+
+static int yesToAll = 0;
+
+static int skipFirmwareIdCheck = 0;
+
+static int skipVerify = 0;
+
+/* ------ Local Functions ----------------------------------------------- */
+
+static void atexit0()
+{
+ /* Close files */
+ if ((logFile != NULL) && (logFile != stderr)) {
+ fclose(logFile);
+ }
+
+ /* Free memory */
+ free(pageBuffer);
+ free(imageBuffer);
+}
+
+static int register_read(uint32_t pexorRegister, uint32_t* value)
+{
+ uint32_t val;
+
+ if (fpga_register_read(pexorRegister, &val) == -1) return -1;
+ if (value != NULL) {
+ *value = val;
+ }
+
+ return 1;
+}
+
+static int register_write(uint32_t pexorRegister, uint32_t value)
+{
+ return fpga_register_write(pexorRegister, value);
+}
+
+static int readSetupRegister(uint32_t* value)
+{
+ return register_read(SetupReg, value);
+}
+
+static int writeSetupRegister(uint8_t value)
+{
+ if (register_write(SetupReg, (uint32_t)(value << 24)) == -1) {
+ fprintf(logFile, "Error > writeSetupRegister\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int writeCtrlRegister(uint32_t value)
+{
+ uint32_t val = 0;
+ int status = -1;
+
+ /* Wait until access is allowed */
+ do {
+ status = readSetupRegister(&val);
+ } while ((val & 0x00ff) != 0);
+
+ status = register_write(CtrlReg, value);
+ if (status == -1) {
+ fprintf(logFile, "Error > writeCtrlRegister\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int sendCommand(uint32_t cmd, uint8_t max)
+{
+ uint32_t val = 0;
+
+ if (writeSetupRegister(max) == -1) {
+ return -1;
+ }
+ if (writeCtrlRegister(cmd) == -1) {
+ return -1;
+ }
+ do {
+ readSetupRegister(&val);
+ } while ((val & 0x00ff) != 0);
+
+ return 0;
+}
+
+static int checkStatus()
+{
+ uint32_t cmd;
+ uint32_t val;
+ int status;
+ int ret;
+
+ /* Read Status Register */
+ cmd = 0x05 << 24;
+ if (sendCommand(cmd, 0) == -1) {
+ return -1;
+ }
+
+ if ((status = register_read(BlockRam, &val)) == -1) {
+ fprintf(logFile, "Error > checkStatus\n");
+ return -1;
+ }
+
+ ret = 0;
+ if ((manId == 0x01461f) ||
+ (manId == 0x00471f)) {
+ /* Check EPE Bit (ADCM and SHOWER) */
+ if (((val >> 5) & 0x01) == 1) {
+ fprintf(logFile, "Error > checkStatus: Erase or program error on "
+ "Board %s\n", deviceName);
+ return -1; /* Fatal Error */
+ }
+ }
+ if ((val & 0x01) == 1) {
+ ret = -2; /* One is busy */
+ }
+
+ return ret;
+}
+
+static int writeStatusRegister(uint8_t value)
+{
+ int status;
+
+ /* Enable writing */
+ if (sendCommand(0x06 << 24, 0) == -1) {
+ fprintf(logFile, "Error > writeStatusRegister: write enable\n");
+ return -1;
+ }
+
+ if (register_write(BlockRam, (uint32_t)value) == -1) {
+ fprintf(logFile, "Error > writeStatusRegister\n");
+ return -1;
+ }
+ if (sendCommand(0x01 << 24, 0) == -1) {
+ fprintf(logFile, "Error > writeStatusRegister: sendCommand\n");
+ return -1;
+ }
+
+ /* Wait for not busy and check status */
+ while ((status = checkStatus() == -2)) {}
+
+ if (status != 0) {
+ fprintf(logFile, "Error > writeStatusRegister: invalid status\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int initTransfer()
+{
+ /* Find Endpoint(s) ManId and allocate needed memory */
+ uint32_t cmd;
+ uint32_t val;
+ int status;
+
+ manId = 0;
+ flashType = FLASH_INVALID;
+
+ /* Read ManIds from all Boards and validate (all must be the same as well) */
+ cmd = 0x9f << 24;
+ if (sendCommand(cmd, 3) == -1) {
+ return -1;
+ }
+
+ if ((status = register_read(BlockRam, &val)) == -1) {
+ fprintf(logFile, "Error > initTransfer, read ManIds\n");
+ return -1;
+ }
+
+ manId = (val & 0x00ffffff);
+ if (!((manId == 0x01461f) ||
+ (manId == 0x00471f) ||
+ (manId == 0x1520c2))) {
+ fprintf(logFile, "Error > initTransfer: "
+ "Unsupported ManId 0x%08x on Board %s\n",
+ manId, deviceName);
+ return -1;
+ }
+
+ /* Set NUM_PAGES */
+ switch (manId) {
+ case 0x1520c2:
+ flashType = FLASH_PEXOR23;
+ NUM_PAGES = 8192;
+ break;
+
+ default:
+ abort();
+ }
+
+ NUM_BLOCKS = (NUM_PAGES * PAGE_SIZE) / BLOCK_SIZE;
+
+ /* Buffer holding the entire rom-image */
+ imageBuffer =
+ (uint8_t*)malloc(sizeof(uint8_t) * (PAGE_SIZE * (NUM_PAGES + 2)));
+ if (imageBuffer == NULL) {
+ abort();
+ }
+
+ fprintf(stderr, "Found Board of type %s\n", FlashTypeStr[flashType]);
+
+ return 0;
+}
+
+static int readPage(uint32_t pageNumber, unsigned int numBytes)
+{
+
+ uint16_t size = 0;
+ uint32_t cmd;
+ unsigned int bytes = 0;
+ unsigned int i;
+
+ if (pageNumber >= NUM_PAGES) return -1;
+ if ((numBytes > PAGE_SIZE) || (numBytes == 0)) return -1;
+
+ cmd = (0x03 << 24) | ((pageNumber * PAGE_SIZE) & 0xffffff);
+ if (sendCommand(cmd, numBytes - 1) == -1) {
+ return -1;
+ }
+
+ size = (numBytes / 4) + (numBytes % 4 != 0 ? 1 : 0);
+ if (size > BLOCKRAM_SIZE) return -1;
+
+ if (fpga_register_read_mem(BlockRam, (uint32_t*)pageBuffer, size) == -1) {
+ fprintf(logFile, "Error > readPage: BlockRam\n");
+ return -1;
+ }
+
+ for (i = 0; i < size; i++) {
+ unsigned int c;
+ uint32_t val = *(((uint32_t*)pageBuffer) + i);
+ for (c = 0; (c < 4) && (bytes < numBytes); c++, bytes++) {
+ pageBuffer[i * 4 + c] = (val >> (c * 8)) & 0xff;
+ }
+ }
+
+ return 1;
+}
+
+static int writePage(uint32_t pageNumber,
+ const uint8_t* buffer,
+ unsigned int numBytes)
+{
+ uint16_t size = 0;
+ uint32_t cmd;
+ int status = 0;
+
+ if (pageNumber >= NUM_PAGES) return -1;
+ if ((numBytes > PAGE_SIZE) || (numBytes == 0)) return -1;
+
+ size = (numBytes / 4) + (numBytes % 4 != 0 ? 1 : 0);
+ if (size > BLOCKRAM_SIZE) return -1;
+
+ /* Write Page to SPI Buffer */
+ if (fpga_register_write_mem(BlockRam, (uint32_t*)buffer, size) == -1) {
+ fprintf(logFile, "Error > writePage: BlockRam\n");
+ return -1;
+ }
+ /* Enable writing */
+ if (sendCommand(0x06 << 24, 0) == -1) {
+ fprintf(logFile, "Error > writePage: write enable\n");
+ return -1;
+ }
+
+ /* Write page */
+ cmd = (0x02 << 24) | ((pageNumber * PAGE_SIZE) & 0xffffff);
+ if (sendCommand(cmd, numBytes - 1) == -1) {
+ fprintf(logFile, "Error > pageWrite: invalid status\n");
+ return -1;
+ }
+
+ /* Wait for not busy and check status */
+ while ((status = checkStatus()) == -2) {
+ }
+ if (status != 0) {
+ fprintf(logFile, "Error > pageWrite: invalid status\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+typedef enum {
+ PMODE_PROGRAM,
+ PMODE_PROGRAM_FULL,
+ PMODE_VERIFY
+} PMode;
+
+static int programImageBuffer(unsigned int size,
+ PMode mode,
+ int infoPage)
+{
+ unsigned int block;
+ int status;
+ int errorCtr = 0;
+ unsigned int i;
+ unsigned int page;
+ int bytesWritten = size;
+ int tmp;
+
+ if ((mode != PMODE_VERIFY) && (yesToAll == 0)) {
+ /* Be nice and ask before start flashing the roms */
+ char c;
+ fprintf(stdout,
+ "You decided to reprogram the FlashRom of "
+ "%s, are you sure [N,y]: ", FlashTypeStr[flashType]);
+ fflush(stdout);
+ c = getc(stdin);
+ if (!((c == 'Y') || (c == 'y'))) {
+ fprintf(stdout, "\nAborting on user request\n");
+ return -1;
+ }
+ }
+
+ if (mode != PMODE_VERIFY) {
+ fprintf(stdout,
+ "Programming Board: %s\n", deviceName);
+ fprintf(stdout,
+ "Symbols:\n"
+ " E: Erasing\n"
+ " P: Programming\n"
+ " @: Success\n"
+ " .: Skipped\n\n");
+ } else {
+ fprintf(stdout,
+ "Verifying Board: %s\n", deviceName);
+ fprintf(stdout,
+ "Symbols:\n"
+ " V: Verifying\n"
+ " X: Failed (see logfile 'pexorflash.log' for details)\n"
+ " @: Success\n"
+ " .: Skipped\n\n");
+ }
+ fprintf(stdout, "Block: 0 1 2 3 4 5 6 7 8 9 A B C D E F");
+ fflush(stdout);
+
+ errorCtr = 0;
+
+ if ((mode != PMODE_VERIFY) && (manId == 0x1520c2)) {
+ /* Unprotect all Sectors */
+ if (writeStatusRegister(0) == -1) {
+ fprintf(stderr,
+ "\nError > program: unprotect all sectors, aborting\n");
+ return -1;
+ }
+ }
+
+ for (block = 0; (block < NUM_BLOCKS); block++) {
+ int error = 0;
+ int writeInfoPage =
+ (block == NUM_BLOCKS - 1) && (infoPage == 1) ? 1 : 0;
+ if (block % 16 == 0) {
+ fprintf(stdout, "\n%x ", block / 16);
+ }
+ fprintf(stdout, ".\b");
+ fflush(stdout);
+ if (!(bytesWritten > 0) && (writeInfoPage == 0)) {
+ fprintf(stdout, ". ");
+ fflush(stdout);
+ continue;
+ }
+
+ if ((mode != PMODE_VERIFY) &&
+ ((bytesWritten > 0) || (writeInfoPage == 1))) {
+ if ((manId == 0x01461f) ||
+ (manId == 0x00471f)) {
+ /* Enable writing */
+ if (sendCommand(0x06 << 24, 0) == -1) {
+ fprintf(stderr, "\nError > program: write enable, aborting\n");
+ return -1;
+ }
+
+ /* Unprotect sector */
+ if (sendCommand(0x39 << 24 | (BLOCK_SIZE * block), 3)
+ == -1) {
+ fprintf(stderr,
+ "\nError > program: unprotect sector #%d, aborting\n",
+ block);
+ return -1;
+ }
+ }
+
+ /* Enable writing */
+ if (sendCommand(0x06 << 24, 0) == -1) {
+ fprintf(stderr, "\nError > program: write enable, aborting\n");
+ return -1;
+ }
+
+ /* Erase block */
+ fprintf(stdout, "E\b");
+ fflush(stdout);
+ if (sendCommand(0xd8 << 24 | (BLOCK_SIZE * block), 3)
+ == -1) {
+ fprintf(stderr, "\nError > program: erase block #%d, aborting\n",
+ block);
+ return -1;
+ }
+
+ /* Wait for not busy and check status */
+ while ((status = checkStatus() == -2)) {}
+
+ if (status != 0) {
+ fprintf(stderr, "\nError > program: invalid status, aborting\n");
+ return -1;
+ }
+
+ /* Now write pages */
+ fprintf(stdout, "P\b");
+ fflush(stdout);
+ tmp = bytesWritten;
+ for (i = 0, page = (block * BLOCK_SIZE) / PAGE_SIZE;
+ (i < (BLOCK_SIZE / PAGE_SIZE)) && (tmp > 0);
+ i++, page++) {
+ int bytes = tmp < PAGE_SIZE ? tmp : PAGE_SIZE;
+ tmp -= bytes;
+ bytesWritten = tmp;
+
+ status = writePage(page, imageBuffer + page * PAGE_SIZE, bytes);
+ if (status == -1) {
+ fprintf(stderr,
+ "\nError > program: pageProgram page #%d, aborting\n",
+ page);
+ return -1;
+ }
+ }
+
+ if (writeInfoPage == 1) {
+ /* Write Info-Page */
+ status = writePage((NUM_PAGES - 1),
+ imageBuffer + (NUM_PAGES - 1) *
+ PAGE_SIZE, PAGE_SIZE);
+ if (status == -1) {
+ fprintf(stderr,
+ "\nError > program: pageProgram page #%d, aborting\n",
+ page);
+ return -1;
+ }
+ }
+
+ if ((manId == 0x01461f) ||
+ (manId == 0x00471f)) {
+ /* Enable writing */
+ if (sendCommand(0x06 << 24, 0x00) == -1) {
+ fprintf(stderr, "\nError > program: write enable, aborting\n");
+ return -1;
+ }
+
+ /* Protect sector */
+ if (sendCommand(0x36 << 24 | (BLOCK_SIZE * block), 3)
+ == -1) {
+ fprintf(stderr, "\nError > program: protect sector #%d, aborting\n",
+ block);
+ return -1;
+ }
+ }
+ } else {
+ /* Verify pages */
+ fprintf(stdout, "V\b");
+ fflush(stdout);
+ tmp = bytesWritten;
+ for (i = 0, page = (block * BLOCK_SIZE) / PAGE_SIZE;
+ (i < (BLOCK_SIZE / PAGE_SIZE)) && (tmp > 0);
+ i++, page++) {
+ unsigned int c;
+ int bytes = tmp < PAGE_SIZE ? tmp : PAGE_SIZE;
+ tmp -= bytes;
+ bytesWritten = tmp;
+
+ if ((status = readPage(page, bytes)) == -1) {
+ fprintf(stderr, "\nError > program: reading Page #%d, aborting\n",
+ page);
+ return -1;
+ }
+
+ for (c = 0; c < bytes; c++) {
+ if (pageBuffer[c] != imageBuffer[page * PAGE_SIZE + c]) {
+ error = -1;
+ errorCtr++;
+ fprintf(logFile,
+ "verify failed page #%d, byte #%d "
+ "(exp: 0x%02x rec: 0x%02x)\n",
+ page, c,
+ imageBuffer[page * PAGE_SIZE + c],
+ pageBuffer[c]);
+ }
+ }
+ }
+
+ /* Verify Info-Page */
+ if (writeInfoPage == 1) {
+ unsigned int c;
+ int bytes = tmp < PAGE_SIZE ? tmp : PAGE_SIZE;
+ tmp -= bytes;
+
+ if ((status = readPage(NUM_PAGES - 1, PAGE_SIZE)) == -1) {
+ fprintf(stderr, "\nError > program: reading InfoPage, aborting\n");
+ return -1;
+ }
+
+ for (c = 0; c < PAGE_SIZE; c++) {
+ if (pageBuffer[c] != imageBuffer[(NUM_PAGES - 1) * PAGE_SIZE + c]) {
+ error = -1;
+ errorCtr++;
+ fprintf(logFile,
+ "verify failed InfoPage, byte #%d "
+ "(exp: 0x%02x rec: 0x%02x)\n",
+ c,
+ imageBuffer[(NUM_PAGES - 1) * PAGE_SIZE + c],
+ pageBuffer[c]);
+ }
+ }
+ }
+ }
+
+ if (error == 0) {
+ fprintf(stdout, "@ ");
+ } else {
+ fprintf(stdout, "X ");
+ }
+ fflush(stdout);
+ }
+
+ if ((mode != PMODE_VERIFY) && (manId == 0x1520c2)) {
+ /* Protect all Sectors i.e. write 0x3c to statusRegister */
+ if (writeStatusRegister(0x00) == -1) {
+ fprintf(stderr, "\nError > program: protect all sectors, aborting\n");
+ return -1;
+ }
+ }
+
+ if (errorCtr == 0) {
+ fprintf(stdout, "\n\nSuccess\n\n");
+ } else {
+ fprintf(stdout,
+ "\n\n%d Errors have occured, see logFile %s for details\n\n",
+ errorCtr, logFileName);
+ }
+ fflush(stdout);
+
+ return errorCtr == 0 ? 0 : -1;
+}
+
+
+static int readImageFile(const char *imageFileName)
+{
+ FILE *imageFile = NULL;
+ int imageSize;
+ unsigned int i;
+
+ /* Cleanup Buffer */
+ for (i = 0; i < (PAGE_SIZE * (NUM_PAGES + 2)); i++) {
+ imageBuffer[i] = 0;
+ }
+
+ /* Read in image */
+ imageFile = fopen(imageFileName, "r");
+ if (imageFile == NULL) {
+ fprintf(logFile,
+ "Error > readImageFile: Could not open ImageFile %s: %s\n",
+ imageFileName, strerror(errno));
+ return -1;
+ }
+
+ imageSize = 0;
+ do {
+ imageSize += fread((void*)(imageBuffer + imageSize), sizeof(uint8_t),
+ PAGE_SIZE, imageFile);
+ } while ((feof(imageFile) == 0) && (imageSize <= PAGE_SIZE * NUM_PAGES));
+
+ fclose(imageFile);
+
+ if (imageSize > (PAGE_SIZE * NUM_PAGES)) {
+ fprintf(logFile,
+ "Error > readImageFile: Imagefile '%s' is too large (%d bytes)\n",
+ imageFileName, imageSize);
+ return -1;
+ }
+
+ return imageSize;
+}
+
+static int prepareImageBuffer()
+{
+ char* strId = "INVALID";
+ int found;
+ unsigned int end;
+ unsigned int i;
+
+ /* Verify imageFile Id */
+ switch (flashType) {
+
+ case FLASH_PEXOR23:
+ strId = "pexor";
+ break;
+
+ default:
+ abort();
+ break;
+ }
+
+ /* Verify imageFile Id */
+ found = 0;
+ for (i = 0; i < 2 * PAGE_SIZE; i++) {
+ if (memcmp(imageBuffer + i, strId, strlen(strId)) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ if ((skipFirmwareIdCheck == 0) && (found == 0)) {
+ fprintf(logFile, "Error > prepareImageBuffer: "
+ "invalid Firmware-Id of Image-File, should be: %s\n", strId);
+ return -1;
+ }
+
+ /* Overwrite Header with 0xff and move it to the left by 4 bytes */
+ end = 0;
+ for (i = 0; i < 2 * PAGE_SIZE; i++) {
+ if (memcmp(imageBuffer + i, "Bits: ", 6) == 0) {
+ end = i + 20;
+ break;
+ }
+ }
+ if (end == 0) {
+ fprintf(logFile, "Error > prepareImageBuffer: invalid Firmware, "
+ "'Bits: ' not found\n");
+ return -1;
+ }
+ for (i = 0; i < end; i++) {
+ imageBuffer[i] = 0xff;
+ }
+
+ return 0;
+}
+
+static int createInfoPage(const char* fileName, const char* userString)
+{
+ char* buffer = (char*)(imageBuffer + (NUM_PAGES - 1) * PAGE_SIZE);
+ struct stat statBuf;
+
+ unsigned int i;
+ for (i = 0; i < PAGE_SIZE; i++) {
+ buffer[i] = '\0';
+ }
+
+ if (stat(fileName, &statBuf) == -1) {
+ fprintf(logFile, "Error > prepareInfoPage: statCall failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ snprintf(buffer + 0, 63, "NAME: %s", basename((char*)fileName));
+ snprintf(buffer + 64, 31, "DATE: %s", ctime(&statBuf.st_mtime));
+ snprintf(buffer + 96, 159, "USER: %s", userString);
+
+ fprintf(stderr, "%s\n", buffer);
+ fprintf(stderr, "%s\n", buffer + 64);
+ fprintf(stderr, "%s\n", buffer + 96);
+
+ return 0;
+}
+
+static int openLog() {
+ time_t datet;
+ char date[128];
+
+ /* Open LogFile */
+ logFile = fopen(logFileName, "w+");
+ if (logFile == NULL) {
+ fprintf(stderr, "Could not open logFile %s: %s\n",
+ logFileName, strerror(errno));
+ return -1;
+ }
+
+ datet = time(NULL);
+ ctime_r(&datet, date);
+ date[strlen(date) - 1] = '\0';
+ fprintf(logFile,
+ "\n\n------------ %s ----------------------------------\n\n", date);
+
+ return 0;
+}
+
+/* ------ MAIN ---------------------------------------------------------- */
+
+void usage(const char *progName)
+{
+ printf("Usage: %s [-d deviceName] [-s str] [-y] [-f] [-v] "
+ "[-h] [-V] <COMMAND>\n",
+ progName);
+ printf("Options:\n");
+ printf(" -d device-name (default: %s)\n", pexor_deviceName);
+ printf(" -s set user-string of info page (default: empty string)\n");
+ printf(" -y assume yes to all questions which might will be asked\n");
+ printf(" -f do not validate FirmwareId of ImageFile (DON'T USE, for "
+ "EXPERTS ONLY)\n");
+ printf(" -v skip verify after programming\n");
+ printf(" -h give this help\n");
+ printf(" -V Version number\n");
+ printf("\nCommands:\n");
+ printf(" program <bit-file> -> "
+ "program bit-file to flash-memory\n");
+ printf(" verify <bit-file> -> "
+ "compare bit-file with flash-memory\n");
+ printf(" backup <raw-file> -> "
+ "write entire flash-memory to raw-file\n");
+ printf(" restore <raw-file> -> "
+ "write backuped raw-file to flash-memory\n");
+ printf(" info -> "
+ "dump content of info-page to stdout\n");
+ printf(" dumppage pagenumber -> "
+ "dump one flash-memory page to stdout\n");
+}
+
+int main(int argc, char ** argv)
+{
+ unsigned int i;
+ char userInfoStr[256] = "";
+
+ logFile = stderr;
+ yesToAll = 0;
+ skipFirmwareIdCheck = 0;
+ skipVerify = 0;
+
+ /* Parse Arguments */
+ while ((i = getopt(argc, argv, "+hd:s:yvVf")) != -1) {
+ switch (i) {
+ case '?':
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ case 'h':
+ usage(basename(argv[0]));
+ exit(EXIT_SUCCESS);
+ case 'd':
+ strncpy(pexor_deviceName, optarg, 256);
+ break;
+ case 's':
+ strncpy(userInfoStr, optarg, 256);
+ break;
+ case 'y':
+ yesToAll = 1;
+ break;
+ case 'f':
+ skipFirmwareIdCheck = 1;
+ break;
+ case 'v':
+ skipVerify = 1;
+ break;
+ case 'V':
+ printf("%s %s\n", basename(argv[0]), pexorflash_version);
+ exit(EXIT_SUCCESS);
+ break;
+ default:
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (argc - optind < 1) {
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+
+ if (init_ports() == -1) {
+ fprintf(stderr, "Init_Ports failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ atexit(atexit0);
+
+ /* Allocate memory for buffers */
+
+ /* Buffer holding the pages of the endpoints */
+ pageBuffer = (uint8_t*)malloc(sizeof(uint8_t) * PAGE_SIZE);
+ if (pageBuffer== NULL) abort();
+
+ /* Execute command */
+ if (strcmp(argv[optind], "program") == 0) {
+
+ /*********************************************************/
+ /* Program Image */
+ /*********************************************************/
+
+ char* imageFileName = NULL;
+ int size;
+
+ if (argc - optind != 2) {
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+
+ imageFileName = argv[optind + 1];
+
+ /* Check for correct ManId */
+ if (initTransfer() == -1) {
+ fprintf(stderr, "InitTransfer failed, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read imageFile to imageBuffer */
+ if ((size = readImageFile(imageFileName)) == -1) {
+ exit(EXIT_FAILURE);
+ }
+ if (size > (PAGE_SIZE * (NUM_PAGES - 1))) {
+ fprintf(stderr, "ImageFile to large (%d bytes, maximum is %d bytes)\n",
+ size, PAGE_SIZE * (NUM_PAGES - 1));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Validate Id and prepare imageBuffer */
+ if (prepareImageBuffer() == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ /* Create InfoPage */
+ createInfoPage(imageFileName, userInfoStr);
+
+ /* Open LogFile */
+ if (openLog() == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "Start programming ImageFile '%s'\n",
+ imageFileName);
+
+ if (programImageBuffer(size, PMODE_PROGRAM, 1) == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ if (skipVerify == 0) {
+ if (programImageBuffer(size, PMODE_VERIFY, 1) == -1) {
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ } else if (strcmp(argv[optind], "verify") == 0) {
+
+ /*********************************************************/
+ /* Verify Image */
+ /*********************************************************/
+
+ char* imageFileName = NULL;
+ int size;
+
+ if (argc - optind != 2) {
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+
+ imageFileName = argv[optind + 1];
+
+ /* Check for correct ManId */
+ if (initTransfer() == -1) {
+ fprintf(stderr, "InitTransfer failed, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read imageFile to imageBuffer */
+ if ((size = readImageFile(imageFileName)) == -1) {
+ exit(EXIT_FAILURE);
+ }
+ if (size > (PAGE_SIZE * (NUM_PAGES - 1))) {
+ fprintf(stderr, "ImageFile to large (%d bytes, maximum is %d bytes)\n",
+ size, PAGE_SIZE * (NUM_PAGES - 1));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Validate Id and prepare imageBuffer */
+ if (prepareImageBuffer() == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ /* Open LogFile */
+ if (openLog() == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "Start verifying ImageFile '%s'\n",
+ imageFileName);
+
+ if (programImageBuffer(size, PMODE_VERIFY, 0) == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ } else if (strcmp(argv[optind], "backup") == 0) {
+
+ /*********************************************************/
+ /* Backup Image */
+ /*********************************************************/
+
+ char* imageFileName;
+ FILE* imageFile = NULL;
+ unsigned int page;
+
+ if (argc - optind != 2) {
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+ imageFileName = argv[optind + 1];
+
+ if (initTransfer() == -1) {
+ fprintf(stderr, "InitTransfer failed, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (checkStatus() < 0) {
+ exit(EXIT_FAILURE);
+ }
+
+ /* Write Pages to file */
+ fprintf(stderr,
+ "Dumping entire flashrom of Board %s to file '%s' ",
+ deviceName, imageFileName);
+
+ imageFile = fopen(imageFileName, "w+");
+ if (imageFile == NULL) {
+ fprintf(stderr, "Could not open Imagefile %s: %s\n",
+ imageFileName, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ for (page = 0; page < NUM_PAGES; page++) {
+ if (readPage(page, PAGE_SIZE) == -1) {
+ fprintf(stderr, "\nError reading Page #%d, aborting..\n", page);
+ fclose(imageFile);
+ exit(EXIT_FAILURE);
+ }
+ if (fwrite((void*)pageBuffer, PAGE_SIZE, 1, imageFile) != 1) {
+ fprintf(stderr,
+ "\nError writing Page #%d to file, aborting..\n", page);
+ fclose(imageFile);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "%s", busy[page % 4]);
+ }
+ fprintf(stderr, " \nDone\n");
+
+ fclose(imageFile);
+
+ } else if (strcmp(argv[optind], "restore") == 0) {
+
+ /*********************************************************/
+ /* Restore Image */
+ /*********************************************************/
+
+ char* imageFileName;
+ int size;
+
+ if (argc - optind != 3) {
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+ imageFileName = argv[optind + 2];
+
+ /* Check for correct ManId */
+ if (initTransfer() == -1) {
+ fprintf(stderr, "InitTransfer failed, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read imageFile to imageBuffer */
+ if ((size = readImageFile(imageFileName)) == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ if (size != PAGE_SIZE * NUM_PAGES) {
+ fprintf(stderr, "Invalid ImageFile %s, aborting\n", imageFileName);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Check ImageBuffer ??? */
+
+ /* Open LogFile */
+ if (openLog() == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "Start restoring ImageFile '%s'\n",
+ imageFileName);
+
+ if (programImageBuffer(size, PMODE_PROGRAM_FULL, 0) == -1) {
+ exit(EXIT_FAILURE);
+ }
+
+ if (skipVerify == 0) {
+ if (programImageBuffer(size, PMODE_VERIFY, 0) == -1) {
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ } else if (strcmp(argv[optind], "info") == 0) {
+
+ /*********************************************************/
+ /* Dump Info-Page */
+ /*********************************************************/
+
+ unsigned int i;
+ int status;
+
+ if (argc - optind != 1) {
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Check for correct ManId */
+ if (initTransfer() == -1) {
+ fprintf(stderr, "InitTransfer failed, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if ((status = readPage(NUM_PAGES - 1, PAGE_SIZE)) == -1) {
+ fprintf(stderr, "Error reading InfoPage, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < status; i++) {
+ pageBuffer[63] = '\0';
+ pageBuffer[95] = '\0';
+ pageBuffer[255] = '\0';
+ fprintf(stdout, "\nEndPoint: %s InfoPage\n", deviceName);
+ if (
+ (strncmp((char*)(pageBuffer + 0), "NAME:", 5) != 0) ||
+ (strncmp((char*)(pageBuffer + 64), "DATE:", 5) != 0) ||
+ (strncmp((char*)(pageBuffer + 96), "USER:", 5) != 0)
+ ) {
+ fprintf(stdout, "INVALID CONTENT\n");
+ continue;
+ }
+
+ fprintf(stdout, "%s\n", pageBuffer);
+ fprintf(stdout, "%s\n", pageBuffer + 64);
+ fprintf(stdout, "%s\n", pageBuffer + 96);
+ }
+ fprintf(stdout, "\n");
+
+ } else if (strcmp(argv[optind], "dumppage") == 0) {
+
+ /*********************************************************/
+ /* Read and dump a page */
+ /*********************************************************/
+
+ uint32_t pageNumber;
+ int status;
+
+ if (argc - optind != 2) {
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+ pageNumber = strtoul(argv[optind + 1], NULL, 0);
+
+ /* Check for correct ManId */
+ if (initTransfer() == -1) {
+ fprintf(stderr, "InitTransfer failed, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if ((status = readPage(pageNumber, PAGE_SIZE)) == -1) {
+ fprintf(stderr, "Error reading Page, aborting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ char text[32] = "";
+ char cc[2] = " \0";
+ int c;
+ fprintf(stdout, "\nEndPoint: %s Page #%d\n", deviceName, pageNumber);
+ for (c = 0; c < PAGE_SIZE; c++) {
+ if ((c % 16) == 0) {
+ text[0] = '\0';
+ fprintf(stdout, "0x%02x ", c);
+ }
+ fprintf(stdout, "%02x ", pageBuffer[c]);
+ cc[0] = isprint((char)pageBuffer[c]) == 0
+ ? '.' : (char)pageBuffer[c];
+ strncat(text, cc, 32);
+ if ((c % 16) == 15) {
+ fprintf(stdout, " %s\n", text);
+ }
+ }
+ fprintf(stdout, "\n");
+
+ } else {
+
+ /* Invalid command */
+ usage(basename(argv[0]));
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}