From 463b91b491eda75df3eaca04625695e3a2030e26 Mon Sep 17 00:00:00 2001 From: hadaq Date: Mon, 10 Oct 2011 21:49:25 +0000 Subject: [PATCH] initial release of pexorflash --- pexor/Makefile | 92 ++++ pexor/pexorflash.c | 1162 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1254 insertions(+) create mode 100644 pexor/Makefile create mode 100644 pexor/pexorflash.c diff --git a/pexor/Makefile b/pexor/Makefile new file mode 100644 index 0000000..9f0ad3f --- /dev/null +++ b/pexor/Makefile @@ -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 index 0000000..8cd9092 --- /dev/null +++ b/pexor/pexorflash.c @@ -0,0 +1,1162 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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] \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 -> " + "program bit-file to flash-memory\n"); + printf(" verify -> " + "compare bit-file with flash-memory\n"); + printf(" backup -> " + "write entire flash-memory to raw-file\n"); + printf(" restore -> " + "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); +} -- 2.43.0