diff --git a/fomu-flash.c b/fomu-flash.c index c1dc418..4599606 100755 --- a/fomu-flash.c +++ b/fomu-flash.c @@ -132,12 +132,13 @@ static int print_help(FILE *stream, const char *progname) { fprintf(stream, "Fomu Raspberry Pi Flash Utilities\n"); fprintf(stream, "Usage:\n"); fprintf(stream, "%15s (-[hri] | [-p offset] | [-f bin] | [-w bin] | [-v bin] | [-s out] | [-k n[:f]])\n", progname); - fprintf(stream, " [-g pinspec] [-t spitype] [-r]\n"); + fprintf(stream, " [-g pinspec] [-t spitype] [-b bytes]\n"); fprintf(stream, "Program mode (pick one):\n"); print_program_modes(stream); fprintf(stream, "Configuration options:\n"); fprintf(stream, " -g ps Set the pin assignment with the given pinspec\n"); fprintf(stream, " -t type Set the number of bits to use for SPI (1, 2, 4, or Q)\n"); + fprintf(stream, " -b bytes Override the size of the SPI flash, in bytes\n"); fprintf(stream, "You can remap various pins with -g. The format is [name]:[number].\n"); fprintf(stream, "\n"); fprintf(stream, "The width of SPI can be set with 't [width]'. Valid widths are:\n"); @@ -163,6 +164,7 @@ int main(int argc, char **argv) { struct ff_spi *spi; struct ff_fpga *fpga; int peek_offset = 0; + int spi_flash_bytes = -1; uint8_t security_reg; uint8_t security_val[256]; enum op op = OP_UNKNOWN; @@ -191,7 +193,7 @@ int main(int argc, char **argv) { return 1; } - while ((opt = getopt(argc, argv, "hip:rf:w:s:2:3:v:g:t:k:")) != -1) { + while ((opt = getopt(argc, argv, "hip:rf:b:w:s:2:3:v:g:t:k:")) != -1) { switch (opt) { case 'r': @@ -200,6 +202,10 @@ int main(int argc, char **argv) { op = OP_FPGA_RESET; break; + case 'b': + spi_flash_bytes = strtoul(optarg, NULL, 0); + break; + case 'k': { if (op != OP_UNKNOWN) return print_usage_error(stdout); @@ -332,6 +338,9 @@ int main(int argc, char **argv) { spiSetType(spi, spi_type); fpgaReset(fpga); + if (spi_flash_bytes != -1) + spiOverrideSize(spi, spi_flash_bytes); + switch (op) { case OP_SPI_ID: { struct spi_id id = spiId(spi); @@ -366,15 +375,25 @@ int main(int argc, char **argv) { } case OP_SPI_READ: { + struct spi_id id = spiId(spi); + if (id.bytes == -1) { + fprintf(stderr, "unknown spi flash size -- specify with -b\n"); + return 1; + } + fd = open(op_filename, O_WRONLY | O_CREAT | O_TRUNC, 0777); if (fd == -1) { perror("unable to open output file"); break; } - uint8_t *bfr = malloc(16777216); - spiRead(spi, 0, bfr, 16777216); - if (write(fd, bfr, 16777216) != 16777216) { - perror("unable to write SPI flash image"); + uint8_t *bfr = malloc(id.bytes); + if (!bfr) { + perror("unable to allocate memory for spi"); + return 1; + } + spiRead(spi, 0, bfr, id.bytes); + if (write(fd, bfr, id.bytes) != id.bytes) { + perror("unable to write SPI flash image to disk"); break; } close(fd); diff --git a/spi.c b/spi.c index 7dcd86d..b800aaf 100644 --- a/spi.c +++ b/spi.c @@ -29,6 +29,7 @@ struct ff_spi { enum spi_type desired_type; struct spi_id id; enum ff_spi_quirks quirks; + int size_override; struct { int clk; @@ -457,6 +458,7 @@ static void spi_decode_id(struct ff_spi *spi) { spi->id.manufacturer = "unknown"; spi->id.model = "unknown"; spi->id.capacity = "unknown"; + spi->id.bytes = -1; // unknown if (spi->id.manufacturer_id == 0xef) { spi->id.manufacturer = "Winbond"; @@ -464,6 +466,7 @@ static void spi_decode_id(struct ff_spi *spi) { && (spi->id.memory_size == 0x18)) { spi->id.model = "W25Q128JV"; spi->id.capacity = "128 Mbit"; + spi->id.bytes = 16 * 1024 * 1024; } } @@ -473,6 +476,7 @@ static void spi_decode_id(struct ff_spi *spi) { && (spi->id.memory_size == 0x01)) { spi->id.model = "AT25SF161"; spi->id.capacity = "16 Mbit"; + spi->id.bytes = 1 * 1024 * 1024; } } @@ -522,6 +526,16 @@ static void spi_get_id(struct ff_spi *spi) { return; } +void spiOverrideSize(struct ff_spi *spi, uint32_t size) { + spi->size_override = size; + + // If size is 0, re-read the capacity + if (!size) + spi_decode_id(spi); + else + spi->id.bytes = size; +} + int spiSetType(struct ff_spi *spi, enum spi_type type) { if (spi->type == type) @@ -606,8 +620,14 @@ int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count spiCommand(spi, addr >> 8); spiCommand(spi, addr >> 0); spiCommand(spi, 0x00); - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { + if ((i & 0x3fff) == 0) { + printf("\rReading @ %06x / %06x", i, count); + fflush(stdout); + } data[i] = spiRx(spi); + } + printf("\rReading @ %06x / %06x Done\n", i, count); spiEnd(spi); return 0; @@ -644,8 +664,9 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in // Erase all applicable blocks uint32_t erase_addr; for (erase_addr = 0; erase_addr < count; erase_addr += 32768) { - printf("\rErasing @ %06x", erase_addr); + printf("\rErasing @ %06x / %06x", erase_addr, count); fflush(stdout); + spiBegin(spi); spiCommand(spi, 0x06); spiEnd(spi); @@ -659,6 +680,7 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in spi_wait_for_not_busy(spi); } + printf(" Done\n"); uint8_t write_cmd; switch (spi->type) { @@ -677,9 +699,9 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in return 1; } - printf("\n"); + int total = count; while (count) { - printf("\rProgramming @ %06x", addr); + printf("\rProgramming @ %06x / %06x", addr, total); fflush(stdout); spiBegin(spi); spiCommand(spi, 0x06); @@ -701,7 +723,8 @@ int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned in addr += i; spi_wait_for_not_busy(spi); } - printf("\n"); + printf("\rProgramming @ %06x / %06x", addr, total); + printf(" Done\n"); return 0; } diff --git a/spi.h b/spi.h index 30c3428..fe93706 100644 --- a/spi.h +++ b/spi.h @@ -42,6 +42,7 @@ struct spi_id { uint8_t memory_size; // Result from 0x9f uint8_t signature; // Result from 0xab uint8_t serial[4]; // Result from 0x4b + int bytes; // -1 if unknown const char *manufacturer; const char *model; const char *capacity; @@ -70,6 +71,7 @@ int spiSetType(struct ff_spi *spi, enum spi_type type); int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count); struct spi_id spiId(struct ff_spi *spi); +void spiOverrideSize(struct ff_spi *spi, uint32_t new_size); //int spi_wait_for_not_busy(struct ff_spi *spi); int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count);