]> jspc29.x-matter.uni-frankfurt.de Git - trbnettools.git/commitdiff
initial release of pexorflash
authorhadaq <hadaq>
Mon, 10 Oct 2011 21:49:25 +0000 (21:49 +0000)
committerhadaq <hadaq>
Mon, 10 Oct 2011 21:49:25 +0000 (21:49 +0000)
pexor/Makefile [new file with mode: 0644]
pexor/pexorflash.c [new file with mode: 0644]

diff --git a/pexor/Makefile b/pexor/Makefile
new file mode 100644 (file)
index 0000000..9f0ad3f
--- /dev/null
@@ -0,0 +1,92 @@
+# ------------ Compiler / Linker Options -------------------------------
+
+ARCH=$(shell uname -m)
+ifeq ($(shell uname -m), x86_64)
+       CPPFLAGS = -DPEXOR -DX86_64
+else
+       CPPFLAGS = -DPEXOR
+endif
+
+INCDIR = -I. -I../libtrbnet
+
+CC = gcc
+CFLAGS = -pipe -g  -Wall -O3 
+
+CXX = g++
+CXXFLAGS = -pipe -g -Wall
+
+LD = $(CC)
+
+LDFLAGS = 
+LIBDIR = -L../libtrbnet
+LOADLIBES = -ltrbnet
+
+# ------------ TARGETS -------------------------------------------------
+
+TARGETS = pexorflash
+
+LIB_TARGETS =
+
+# ------------ Libaries ------------------------------------------------
+
+AR = ar
+ARFLAGS = -srv
+
+# ------------ Pattern Rules -------------------------------------------
+
+# C Code:
+%.o: %.c
+       $(CC) $< -c $(CFLAGS) $(CPPFLAGS) $(INCDIR) -o $@ 
+
+# C++ Code:
+%.o: %.cpp
+       $(CXX) $< -c $(CXXFLAGS) $(CPPFLAGS) $(INCDIR) -o $@ 
+
+%.o: %.cc
+       $(CXX) $< -c $(CXXFLAGS) $(CPPFLAGS) $(INCDIR) -o $@ 
+
+%.o: %.C
+       $(CXX) $< -c $(CXXFLAGS) $(CPPFLAGS) $(INCDIR) -o $@ 
+
+# C/C++ Objects (set LD accordingly)
+%: %.o
+       @echo LINKING $@
+       $(LD) $^ $(LDFLAGS) $(LIBDIR) $(LOADLIBES) -o $@ 
+       @echo DONE!
+
+# Libaries
+%.a: $%
+       @echo CREATING library $@
+       $(AR) $(ARFLAGS) $@ $^
+       @echo DONE!
+
+%.so: $%
+       @echo CREATING shared library $@
+       $(LD) -shared -O $^ -o $@
+       @echo DONE!
+
+
+# ------------ Targets -------------------------------------------------
+
+.PHONY: all
+all: $(LIB_TARGETS) $(TARGETS)
+
+.PHONY: clean 
+clean:
+       rm -f *.o core core.*
+       rcsclean
+
+.PHONY: distclean
+distclean: clean
+       rm -f $(TARGETS) $(LIB_TARGETS)
+       find . -type l -exec rm {} \;
+       rcsclean -u
+
+.PHONY: depend
+depend:
+       $(CC) -MM $(CFLAGS) $(CPPFLAGS) $(INCDIR) *.c
+
+# ------------ Dependencies --------------------------------------------
+
+pexorflash: pexorflash.o
+pexorflash.o: pexorflash.c 
diff --git a/pexor/pexorflash.c b/pexor/pexorflash.c
new file mode 100644 (file)
index 0000000..8cd9092
--- /dev/null
@@ -0,0 +1,1162 @@
+#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);
+}