diff options
Diffstat (limited to 'src/local.c')
-rw-r--r-- | src/local.c | 340 |
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"); |