summaryrefslogtreecommitdiffstats
path: root/src/local.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/local.c')
-rw-r--r--src/local.c340
1 files changed, 275 insertions, 65 deletions
diff --git a/src/local.c b/src/local.c
index 3813910..eed2c2a 100644
--- a/src/local.c
+++ b/src/local.c
@@ -19,6 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
#include <sys/statvfs.h>
#include <sys/types.h>
@@ -198,14 +199,6 @@ enum device local_get_device(void) {
}
-int local_flash_image(struct image * image) {
-
- ERROR("Not implemented yet");
- (void)image;
- return -1;
-
-}
-
static int local_nanddump(const char * file, int mtd, int offset, int length) {
struct statvfs buf;
@@ -227,15 +220,18 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
return 1;
}
- size = snprintf(NULL, 0, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
+ size = snprintf(NULL, 0, "nanddump --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd);
command = malloc(size+1);
if ( ! command )
return 1;
- snprintf(command, size+1, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
+ snprintf(command, size+1, "nanddump --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd);
- ret = system(command);
+ if ( ! simulate )
+ ret = system(command);
+ else
+ ret = 0;
free(command);
@@ -243,52 +239,77 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
}
-struct nanddump_args {
- int valid;
- int mtd;
- int offset;
- int length;
+static FILE * local_nandwrite(int mtd, int offset) {
+
+ char * command;
+ FILE * stream;
+ size_t size;
+
+ size = snprintf(NULL, 0, "nandwrite -a -s %d -p /dev/mtd%d -", offset, mtd);
+
+ command = malloc(size+1);
+ if ( ! command )
+ return NULL;
+
+ snprintf(command, size+1, "nandwrite -a -s %d -p /dev/mtd%d -", offset, mtd);
+
+ if ( ! simulate )
+ stream = popen(command, "w");
+ else
+ stream = NULL;
+
+ free(command);
+
+ return stream;
+
+}
+
+struct nandpart_args {
+ unsigned int mtd;
+ unsigned int offset;
+ unsigned int length;
+ unsigned int header;
};
-static struct nanddump_args nanddump_rx51[] = {
- [IMAGE_XLOADER] = { 1, 0, 0x00000000, 0x00004000 },
- [IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
- [IMAGE_KERNEL] = { 1, 3, 0x00000800, 0x001FF800 },
- [IMAGE_INITFS] = { 1, 4, 0x00000000, 0x00200000 },
- [IMAGE_ROOTFS] = { 1, 5, 0x00000000, 0x0fb40000 },
+static struct nandpart_args nandpart_rx51[] = {
+ [IMAGE_XLOADER] = { 0, 0x00000000, 0x00004000, 0x00000000 },
+ [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
+ [IMAGE_KERNEL] = { 3, 0x00000000, 0x00200000, 0x00000800 },
+ [IMAGE_INITFS] = { 4, 0x00000000, 0x00200000, 0x00000000 },
+ [IMAGE_ROOTFS] = { 5, 0x00000000, 0x0fb40000, 0x00000000 },
};
/* FIXME: Is this table correct? */
-static struct nanddump_args nanddump_rx4x[] = {
- [IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
- [IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
- [IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x0021F800 },
- [IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00400000 },
- [IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0f960000 },
+static struct nandpart_args nandpart_rx4x[] = {
+ [IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
+ [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
+ [IMAGE_KERNEL] = { 2, 0x00000000, 0x00220000, 0x00000800 },
+ [IMAGE_INITFS] = { 3, 0x00000000, 0x00400000, 0x00000000 },
+ [IMAGE_ROOTFS] = { 4, 0x00000000, 0x0f960000, 0x00000000 },
};
/* FIXME: Is this table correct? */
-static struct nanddump_args nanddump_old[] = {
- [IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
- [IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
- [IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 },
- [IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00200000 },
- [IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 },
+static struct nandpart_args nandpart_old[] = {
+ [IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
+ [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
+ [IMAGE_KERNEL] = { 2, 0x00000000, 0x00200000, 0x00000800 },
+ [IMAGE_INITFS] = { 3, 0x00000000, 0x00200000, 0x00000000 },
+ [IMAGE_ROOTFS] = { 4, 0x00000000, 0x0fb80000, 0x00000000 },
};
-struct nanddump_device {
+struct nand_device {
size_t count;
- struct nanddump_args * args;
+ struct nandpart_args * args;
};
-#define NANDDUMP(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
+#define NAND_DEVICE(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
-static struct nanddump_device nanddump[] = {
- NANDDUMP(DEVICE_SU_18, nanddump_old),
- NANDDUMP(DEVICE_RX_34, nanddump_old),
- NANDDUMP(DEVICE_RX_44, nanddump_rx4x),
- NANDDUMP(DEVICE_RX_48, nanddump_rx4x),
- NANDDUMP(DEVICE_RX_51, nanddump_rx51),
+static struct nand_device nand_device[] = {
+ NAND_DEVICE(DEVICE_SU_18, nandpart_old),
+ NAND_DEVICE(DEVICE_RX_34, nandpart_old),
+ NAND_DEVICE(DEVICE_RX_44, nandpart_rx4x),
+ NAND_DEVICE(DEVICE_RX_48, nandpart_rx4x),
+ NAND_DEVICE(DEVICE_RX_51, nandpart_rx51),
};
#undef NANDDUMP
@@ -380,10 +401,13 @@ static void local_find_internal_mydocs(int * maj, int * min) {
int local_dump_image(enum image_type image, const char * file) {
+ unsigned char buf[20];
int ret = -1;
int fd = -1;
+ int header = 0;
unsigned char * addr = NULL;
- off_t nlen, len;
+ off_t nlen = (off_t)-1;
+ off_t len;
int align;
int maj, min;
@@ -415,17 +439,49 @@ int local_dump_image(enum image_type image, const char * file) {
} else {
- if ( device >= sizeof(nanddump)/sizeof(nanddump[0]) ) {
+ if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) ) {
ERROR("Unsupported device");
goto clean;
}
- if ( image >= nanddump[device].count ) {
+ if ( image >= nand_device[device].count ) {
ERROR("Unsupported image type: %s", image_type_to_string(image));
goto clean;
}
- ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, nanddump[device].args[image].length);
+ header = nand_device[device].args[image].header;
+
+ if ( header > 0 ) {
+
+ ret = local_nanddump(file, nand_device[device].args[image].mtd, nand_device[device].args[image].offset, header);
+ if ( ret != 0 ) {
+ if ( ! simulate )
+ unlink(file);
+ ret = -1;
+ goto clean;
+ }
+
+ if ( ! simulate ) {
+
+ fd = open(file, O_RDONLY);
+ if ( fd >= 0 ) {
+ if ( read(fd, buf, 20) == 20 ) {
+ if ( memcmp(buf, "NOLO!img\x02\x00\x00\x00\x00\x00\x00\x00", 16) == 0 )
+ nlen = ((unsigned int)buf[16] << 0) | ((unsigned int)buf[17] << 8) | ((unsigned int)buf[18] << 16) | ((unsigned int)buf[19] << 24);
+ else if ( memcmp(buf, "NOLO img", 8) == 0 )
+ nlen = ((unsigned int)buf[8] << 0) | ((unsigned int)buf[9] << 8) | ((unsigned int)buf[10] << 16) | ((unsigned int)buf[11] << 24);
+ }
+ close(fd);
+ fd = -1;
+ }
+
+ unlink(file);
+
+ }
+
+ }
+
+ ret = local_nanddump(file, nand_device[device].args[image].mtd, nand_device[device].args[image].offset + header, nand_device[device].args[image].length - header);
}
@@ -434,6 +490,9 @@ int local_dump_image(enum image_type image, const char * file) {
goto clean;
}
+ if ( simulate )
+ goto clean;
+
fd = open(file, O_RDWR);
if ( fd < 0 )
goto clean;
@@ -442,31 +501,35 @@ int local_dump_image(enum image_type image, const char * file) {
if ( len == (off_t)-1 || len == 0 )
goto clean;
- addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if ( header <= 0 || nlen == (off_t)-1 ) {
- if ( addr == MAP_FAILED )
- addr = NULL;
+ addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
- if ( ! addr )
- goto clean;
+ if ( addr == MAP_FAILED )
+ addr = NULL;
- for ( nlen = len; nlen > 0; --nlen )
- if ( addr[nlen-1] != 0xFF )
- break;
+ if ( ! addr )
+ goto clean;
- for ( ; nlen > 0; --nlen )
- if ( addr[nlen-1] != 0x00 )
- break;
+ for ( nlen = len; nlen > 0; --nlen )
+ if ( addr[nlen-1] != 0xFF )
+ break;
- if ( image == IMAGE_MMC )
- align = 8;
- else
- align = 7;
+ for ( ; nlen > 0; --nlen )
+ if ( addr[nlen-1] != 0x00 )
+ break;
- if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
- nlen = ((nlen >> align) + 1) << align;
+ if ( image == IMAGE_MMC )
+ align = 8;
+ else
+ align = 7;
- if ( nlen == 0 ) {
+ if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
+ nlen = ((nlen >> align) + 1) << align;
+
+ }
+
+ if ( header <= 0 && nlen == 0 ) {
printf("File %s is empty, removing it...\n", file);
unlink(file);
} else if ( nlen != len ) {
@@ -487,6 +550,153 @@ clean:
}
+int local_flash_image(struct image * image) {
+
+ unsigned char buf[0x20000];
+ unsigned int remaining, size;
+ void (*sighandler)(int);
+ int min, maj, fd;
+ FILE * stream;
+ int ret;
+
+ printf("Flash image:\n");
+ image_print_info(image);
+
+ if ( image->type == IMAGE_MMC ) {
+
+ maj = -1;
+ min = -1;
+
+ local_find_internal_mydocs(&maj, &min);
+ if ( maj == -1 || min == -1 )
+ ERROR_RETURN("Cannot find MyDocs mmc device: Slot 'internal' was not found", -1);
+
+ VERBOSE("Detected internal MyDocs mmc device: major=%d minor=%d\n", maj, min);
+
+ fd = disk_open_dev(maj, min, 1, simulate ? 1 : 0);
+ if ( fd < 0 )
+ ERROR_RETURN("Cannot open MyDocs mmc device in /dev/", -1);
+
+ ret = disk_flash_dev(fd, image);
+
+ close(fd);
+
+ } else {
+
+ if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) )
+ ERROR_RETURN("Unsupported device", -1);
+
+ if ( image->type >= nand_device[device].count ) {
+ ERROR("Unsupported image type: %s", image_type_to_string(image->type));
+ return -1;
+ }
+
+ if ( image->size > nand_device[device].args[image->type].length - nand_device[device].args[image->type].header )
+ ERROR_RETURN("Image is too big", -1);
+
+ printf("Using nandwrite for flashing %s image...\n", image_type_to_string(image->type));
+
+ stream = local_nandwrite(nand_device[device].args[image->type].mtd, nand_device[device].args[image->type].offset);
+ if ( ! simulate && ! stream )
+ ERROR_RETURN("Cannot start nandwrite process", -1);
+
+ ret = 0;
+ sighandler = signal(SIGPIPE, SIG_IGN);
+
+ /* Write NOLO!img or NOLO img header with size */
+ if ( nand_device[device].args[image->type].header > 0 ) {
+ if ( device == DEVICE_RX_51 ) {
+ memcpy(buf, "NOLO!img\x02\x00\x00\x00\x00\x00\x00\x00", 16);
+ buf[16] = (image->size >> 0) & 0xFF;
+ buf[17] = (image->size >> 8) & 0xFF;
+ buf[18] = (image->size >> 16) & 0xFF;
+ buf[19] = (image->size >> 24) & 0xFF;
+ size = 20;
+ } else {
+ memcpy(buf, "NOLO img", 8);
+ buf[ 8] = (image->size >> 0) & 0xFF;
+ buf[ 9] = (image->size >> 8) & 0xFF;
+ buf[10] = (image->size >> 16) & 0xFF;
+ buf[11] = (image->size >> 24) & 0xFF;
+ size = 12;
+ }
+
+ if ( ! simulate ) {
+ if ( fwrite(buf, size, 1, stream) != 1 ) {
+ ret = -1;
+ goto clean;
+ }
+ }
+
+ memset(buf, 0, sizeof(buf));
+ remaining = nand_device[device].args[image->type].header - size;
+ while ( remaining > 0 ) {
+ size = remaining < sizeof(buf) ? remaining : sizeof(buf);
+ if ( ! simulate ) {
+ if ( fwrite(buf, size, 1, stream) != 1 ) {
+ ret = -1;
+ goto clean;
+ }
+ }
+ remaining -= size;
+ }
+ }
+
+ /* Write image data */
+ image_seek(image, 0);
+ remaining = image->size;
+ while ( remaining > 0 ) {
+ size = remaining < sizeof(buf) ? remaining : sizeof(buf);
+ size = image_read(image, buf, size);
+ if ( size == 0 ) {
+ ERROR("Failed to read image");
+ ret = -1;
+ goto clean;
+ }
+ if ( ! simulate ) {
+ if ( fwrite(buf, size, 1, stream) != 1 ) {
+ ret = -1;
+ goto clean;
+ }
+ }
+ remaining -= size;
+ }
+
+ /* Write filler zeros to clear previous data */
+ memset(buf, 0, sizeof(buf));
+ remaining = nand_device[device].args[image->type].length - (image->size + nand_device[device].args[image->type].header);
+ while ( remaining > 0 ) {
+ size = remaining < sizeof(buf) ? remaining : sizeof(buf);
+ if ( ! simulate ) {
+ if ( fwrite(buf, size, 1, stream) != 1 ) {
+ ret = -1;
+ goto clean;
+ }
+ }
+ remaining -= size;
+ }
+
+clean:
+ if ( ! simulate ) {
+ if ( ret == 0 )
+ ret = pclose(stream);
+ else
+ pclose(stream);
+ }
+
+ signal(SIGPIPE, sighandler);
+
+ if ( ret != 0 )
+ ERROR("Flashing failed");
+ }
+
+ if ( ret == 0 )
+ printf("Done\n");
+
+ return ret;
+
+}
+
int local_check_badblocks(const char * device) {
ERROR("Not implemented yet");