diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | config.mk | 2 | ||||
-rw-r--r-- | doc/dumping | 5 | ||||
-rw-r--r-- | doc/fiasco | 70 | ||||
-rw-r--r-- | src/device.c | 14 | ||||
-rw-r--r-- | src/disk.c | 124 | ||||
-rw-r--r-- | src/disk.h | 2 | ||||
-rw-r--r-- | src/fiasco.c | 298 | ||||
-rw-r--r-- | src/image.c | 48 | ||||
-rw-r--r-- | src/image.h | 19 | ||||
-rw-r--r-- | src/local.c | 340 | ||||
-rw-r--r-- | src/main.c | 70 | ||||
-rw-r--r-- | src/mkii.c | 16 | ||||
-rw-r--r-- | src/nolo.c | 16 |
14 files changed, 792 insertions, 234 deletions
@@ -5,7 +5,6 @@ cold-flash: * Detect device from asic id disk: - * Support for flashing mmc images * Badblock checking fiasco: @@ -15,7 +14,6 @@ image: * Support for Harmattan images local: - * Support for flashing (on device) * Write versions * Badblock checking @@ -1,4 +1,4 @@ -VERSION = 0.8 +VERSION = 0.10 PREFIX = /usr/local # NetBSD stuff diff --git a/doc/dumping b/doc/dumping index 4a629cd..b7e9cdf 100644 --- a/doc/dumping +++ b/doc/dumping @@ -30,11 +30,10 @@ Technical details: For dumping mtd partition is used tool nanddump. Here is example how to dump kernel image without padding to file zImage: - $ nanddump -o -b -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2 + $ nanddump --omitoob -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2 Params means: --o - "Omit oob data" --b - "Omit bad blocks" +--omitoob - "Omit oob data" -s - "Start address" -l - "Length" -f - "Output file" @@ -38,24 +38,64 @@ IMAGE 1 byte = 0x54 -- signature 1 byte -- number of subsection blocks - (start of data block) - 1 byte -- type of subsection block (data - always 0x2e) - 1 byte -- length of subsection block (data - always 25) - 3 bytes -- unknown (always 0x01 0x01 0x00) - 2 bytes -- checksum for the image contents (xorpair) (big endian) - 12 bytes -- image name type (first byte is FF if is the last image) - 4 bytes -- length of image data (big endian) - 4 bytes -- unknown (always 0x00 0x00 0x00 0x00) - (end of data block) block { 1 byte -- type of subsection block - '1' - version - '2' - device & hw revisions (size of device is 16, hw revision 8) - '3' - layout - '4' - unknown - '/' - unknown + 0x2E - file data + 0x2F - partition info + 0x31 - version + 0x32 - device & hw revisions (size of device is 16, hw revision 8) + 0x33 - layout + 0x34 - image data part block (one block for one data part) 1 byte -- length of subsection block N bytes -- subsection block data } - 1 byte -- unknown (0x00 is accepted, maybe end of subsections?) + 1 byte -- checksum of subsection data without signature (0xFF - xorpair) N bytes -- image data + + +FILE DATA BLOCK + + 1 byte -- asic index (always APE - 0x01) + 1 byte -- device type (always NAND - 0x01) + 1 byte -- device index (always 0x00) + 2 bytes -- checksum for the image contents (xorpair) (big endian) + 12 bytes -- image name type (first byte is FF if is the last image) + 4 bytes -- length of image data (big endian) + 4 bytes -- load address of image data (big endian, unused always zero) + + +PARTITION INFO BLOCK + + N bytes -- unknown + + +IMAGE DATA PART BLOCK + + 4 bytes -- unknown (always 0x00 0x00 0x00 0x00) + 4 bytes -- offset (big endian) + 4 bytes -- unknown (always 0x00 0x00 0x00 0x00) + 4 bytes -- size (big endian) + N bytes -- partition name (prefix) in layout (may be omitted) + + +LAYOUT DATA BLOCK + + N bytes of text data, e.g.: + +mmc { + name = "internal"; + partition { + fs_type = "vfat"; + prefix = "mydocs"; + no_create = true; + } + partition { + size = 2048; + fs_type = "ext3"; + prefix = "home"; + } + partition { + size = 768; + fs_type = "swap"; + } +} diff --git a/src/device.c b/src/device.c index db2c6a7..0a7820a 100644 --- a/src/device.c +++ b/src/device.c @@ -184,9 +184,11 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) { continue; } - for ( i = 0; device_first->hwrevs[i] != -1; ++i ) - if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 ) - ++local; + if ( device_first->hwrevs ) { + for ( i = 0; device_first->hwrevs[i] != -1; ++i ) + if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 ) + ++local; + } size += (1+16+(MAX_HWREVS+1)*8)*(local/MAX_HWREVS+1); count += local/MAX_HWREVS; @@ -215,7 +217,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) { continue; } - while ( device_first->hwrevs[i+1] != -1 ) { + do { uint8_t len = 0; ret[j] = ++last_ptr; @@ -228,7 +230,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) { for ( k = 0; k < MAX_HWREVS; ++k ) { - if ( device_first->hwrevs[i+1] == -1 ) + if ( ! device_first->hwrevs || device_first->hwrevs[i+1] == -1 ) break; ++i; @@ -246,7 +248,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) { ++j; - } + } while ( device_first->hwrevs && device_first->hwrevs[i+1] != -1 ); device_first = device_first->next; @@ -118,7 +118,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) { blkdev[len] = 0; - fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK); + fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK); if ( fd < 0 ) { ERROR_INFO("Cannot open block device %s", blkdev); return -1; @@ -144,13 +144,13 @@ int disk_open_dev(int maj, int min, int partition, int readonly) { ERROR("Block device name is too long"); return -1; } - fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL); + fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL); if ( fd < 0 && errno == ENOENT ) { if ( snprintf(blkdev+len, sizeof(blkdev)-len, "%d", partition) >= (int)(sizeof(blkdev)-len) ) { ERROR("Block device name is too long"); return -1; } - fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL); + fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL); } if ( fd < 0 && errno == ENOENT ) { blkdev[len] = 0; @@ -201,7 +201,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) { int disk_dump_dev(int fd, const char * file) { - int fd2; + int fd2 = -1; int ret; char * path; uint64_t blksize; @@ -253,11 +253,15 @@ int disk_dump_dev(int fd, const char * file) { return -1; } - fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if ( ! simulate ) { + + fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + if ( fd2 < 0 ) { + ERROR_INFO("Cannot create file %s", file); + return -1; + } - if ( fd2 < 0 ) { - ERROR_INFO("Cannot create file %s", file); - return -1; } sent = 0; @@ -272,29 +276,89 @@ int disk_dump_dev(int fd, const char * file) { break; if ( size < 0 ) { PRINTF_ERROR("Reading from block device failed"); - close(fd2); + if ( ! simulate ) + close(fd2); return -1; } - if ( write(fd2, global_buf, size) != size ) { - PRINTF_ERROR("Dumping image failed"); - close(fd2); - return -1; + if ( ! simulate ) { + if ( write(fd2, global_buf, size) != size ) { + PRINTF_ERROR("Dumping image failed"); + close(fd2); + return -1; + } } sent += size; printf_progressbar(sent, blksize); } - close(fd2); + if ( ! simulate ) + close(fd2); return 0; } -int disk_flash_dev(int fd, const char * file) { +int disk_flash_dev(int fd, struct image * image) { - ERROR("Not implemented yet"); - (void)fd; - (void)file; - return -1; + uint64_t blksize; + size_t need, sent; + ssize_t size; + + if ( image->type != IMAGE_MMC ) + ERROR_RETURN("Only mmc images are supported", -1); + + printf("Writing image to block device...\n"); + +#ifdef __linux__ + + if ( ioctl(fd, BLKGETSIZE64, &blksize) != 0 ) { + ERROR_INFO("Cannot get size of block device"); + return -1; + } + +#else + + blksize = lseek(fd, 0, SEEK_END); + if ( (off_t)blksize == (off_t)-1 ) { + ERROR_INFO("Cannot get size of block device"); + return -1; + } + + if ( lseek(fd, 0, SEEK_SET) == (off_t)-1 ) { + ERROR_INFO("Cannot seek to begin of block device"); + return -1; + } + +#endif + + if ( blksize == 0 ) + ERROR_RETURN("Block device has zero size", -1); + + if ( image->size > blksize ) + ERROR_RETURN("Image is too big", -1); + + sent = 0; + printf_progressbar(0, image->size); + + while ( sent < image->size ) { + need = image->size - sent; + if ( need > sizeof(global_buf) ) + need = sizeof(global_buf); + size = image_read(image, global_buf, need); + if ( size == 0 ) { + PRINTF_ERROR("Failed to read image"); + return -1; + } + if ( ! simulate ) { + if ( write(fd, global_buf, size) != size ) { + PRINTF_ERROR("Writing image failed"); + return -1; + } + } + sent += size; + printf_progressbar(sent, image->size); + } + + return 0; } @@ -412,16 +476,14 @@ int disk_init(struct usb_device_info * dev) { maj2 = tmp; } - /* TODO: change 1 to 0 when disk_flash_dev will be implemented */ - /* RX-51, RM-680 and RM-696 export MyDocs in first usb device and just first partion, so host system see whole device without MBR table */ if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 || dev->device == DEVICE_RM_696 ) - fd = disk_open_dev(maj1, min1, -1, 1); + fd = disk_open_dev(maj1, min1, -1, simulate ? 1 : 0); /* Other devices can export SD card as first partition and export whole mmc device, so host system will see MBR table */ else if ( maj2 != -1 && min2 != -1 ) - fd = disk_open_dev(maj2, min2, 1, 1); + fd = disk_open_dev(maj2, min2, 1, simulate ? 1 : 0); else - fd = disk_open_dev(maj1, min1, 1, 1); + fd = disk_open_dev(maj1, min1, 1, simulate ? 1 : 0); if ( fd < 0 ) return -1; @@ -454,10 +516,16 @@ enum device disk_get_device(struct usb_device_info * dev) { int disk_flash_image(struct usb_device_info * dev, struct image * image) { - ERROR("Not implemented yet"); - (void)dev; - (void)image; - return -1; + int ret; + + printf("Flash image:\n"); + image_print_info(image); + + ret = disk_flash_dev(dev->data, image); + if ( ret == 0 ) + printf("Done\n"); + + return ret; } @@ -30,7 +30,7 @@ enum device disk_get_device(struct usb_device_info * dev); int disk_open_dev(int maj, int min, int partition, int readonly); int disk_dump_dev(int fd, const char * file); -int disk_flash_dev(int fd, const char * file); +int disk_flash_dev(int fd, struct image * image); int disk_flash_image(struct usb_device_info * dev, struct image * image); int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file); diff --git a/src/fiasco.c b/src/fiasco.c index caa0a9f..c8b8af5 100644 --- a/src/fiasco.c +++ b/src/fiasco.c @@ -34,10 +34,11 @@ #include "image.h" #include "fiasco.h" +#define CHECKSUM(checksum, buf, size) do { size_t _i; for ( _i = 0; _i < size; _i++ ) checksum += ((unsigned char *)buf)[_i]; } while (0) #define FIASCO_READ_ERROR(fiasco, ...) do { ERROR_INFO(__VA_ARGS__); fiasco_free(fiasco); return NULL; } while (0) #define FIASCO_WRITE_ERROR(file, fd, ...) do { ERROR_INFO_STR(file, __VA_ARGS__); if ( fd >= 0 ) close(fd); return -1; } while (0) #define READ_OR_FAIL(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) { FIASCO_READ_ERROR(fiasco, "Cannot read %d bytes", size); } } while (0) -#define READ_OR_RETURN(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; } while (0) +#define READ_OR_RETURN(fiasco, checksum, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; CHECKSUM(checksum, buf, size); } while (0) #define WRITE_OR_FAIL_FREE(file, fd, buf, size, var) do { if ( ! simulate ) { if ( write(fd, buf, size) != (ssize_t)size ) { free(var); FIASCO_WRITE_ERROR(file, fd, "Cannot write %d bytes", size); } } } while (0) #define WRITE_OR_FAIL(file, fd, buf, size) WRITE_OR_FAIL_FREE(file, fd, buf, size, NULL) @@ -65,9 +66,16 @@ struct fiasco * fiasco_alloc_from_file(const char * file) { char hwrevs[1024]; char version[257]; char layout[257]; + uint8_t asicidx; + uint8_t devicetype; + uint8_t deviceidx; + uint8_t checksum; + uint32_t address; uint16_t hash; off_t offset; struct image * image; + struct image_part * image_part; + struct image_part * image_parts; char hwrev[9]; unsigned char buf[512]; @@ -120,23 +128,41 @@ struct fiasco * fiasco_alloc_from_file(const char * file) { while ( 1 ) { /* If end of file, return fiasco image */ - READ_OR_RETURN(fiasco, buf, 7); + checksum = 0x00; + READ_OR_RETURN(fiasco, checksum, buf, 1); - /* Header of next image */ - if ( ! ( buf[0] == 0x54 && buf[2] == 0x2E && buf[3] == 0x19 && buf[4] == 0x01 && buf[5] == 0x01 && buf[6] == 0x00 ) ) { + /* Header of next image (0x54) */ + if ( buf[0] != 0x54 ) { ERROR("Invalid next image header"); return fiasco; } - count8 = buf[1]; - if ( count8 > 0 ) - --count8; + checksum = 0x00; + + READ_OR_RETURN(fiasco, checksum, &count8, 1); + + if ( count8 == 0 ) { + ERROR("No section in image header"); + return fiasco; + } + + READ_OR_RETURN(fiasco, checksum, buf, 2); - READ_OR_RETURN(fiasco, &hash, 2); + /* File data section (0x2E) with length of 25 bytes */ + if ( buf[0] != 0x2E || buf[1] != 25 ) { + ERROR("First section in image header is not file data with length of 25 bytes"); + return fiasco; + } + + READ_OR_RETURN(fiasco, checksum, &asicidx, 1); + READ_OR_RETURN(fiasco, checksum, &devicetype, 1); + READ_OR_RETURN(fiasco, checksum, &deviceidx, 1); + + READ_OR_RETURN(fiasco, checksum, &hash, 2); hash = ntohs(hash); memset(type, 0, sizeof(type)); - READ_OR_RETURN(fiasco, type, 12); + READ_OR_RETURN(fiasco, checksum, type, 12); byte = type[0]; if ( byte == 0xFF ) @@ -144,26 +170,35 @@ struct fiasco * fiasco_alloc_from_file(const char * file) { VERBOSE(" %s\n", type); - READ_OR_RETURN(fiasco, &length, 4); + READ_OR_RETURN(fiasco, checksum, &length, 4); length = ntohl(length); - /* unknown */ - READ_OR_RETURN(fiasco, buf, 4); + /* load address (unused) */ + READ_OR_RETURN(fiasco, checksum, &address, 4); + + /* end of file data section */ + --count8; VERBOSE(" size: %d bytes\n", length); - VERBOSE(" hash: %#04x\n", hash); + VERBOSE(" address: 0x%04x\n", address); + VERBOSE(" hash: 0x%04x\n", hash); + VERBOSE(" asic idx: %d\n", asicidx); + VERBOSE(" device type: %d\n", devicetype); + VERBOSE(" device idx: %d\n", deviceidx); VERBOSE(" subsections: %d\n", count8); memset(device, 0, sizeof(device)); memset(hwrevs, 0, sizeof(hwrevs)); memset(version, 0, sizeof(version)); memset(layout, 0, sizeof(layout)); + image_part = NULL; + image_parts = NULL; while ( count8 > 0 ) { - READ_OR_RETURN(fiasco, &byte, 1); - READ_OR_RETURN(fiasco, &length8, 1); - READ_OR_RETURN(fiasco, buf, length8); + READ_OR_RETURN(fiasco, checksum, &byte, 1); + READ_OR_RETURN(fiasco, checksum, &length8, 1); + READ_OR_RETURN(fiasco, checksum, buf, length8); VERBOSE(" subinfo\n"); VERBOSE(" length: %d\n", length8); @@ -207,15 +242,55 @@ struct fiasco * fiasco_alloc_from_file(const char * file) { memset(layout, 0, sizeof(layout)); strncpy(layout, (char *)buf, length8); VERBOSE("layout\n"); + } else if ( byte == '4' ) { + VERBOSE("data part\n"); + if ( length8 < 16 ) { + VERBOSE(" (damaged)\n"); + } else { + if ( image_parts ) { + image_part->next = calloc(1, sizeof(struct image_part)); + if ( ! image_part->next ) + FIASCO_READ_ERROR(fiasco, "Cannot allocate image"); + image_part = image_part->next; + } else { + image_parts = calloc(1, sizeof(struct image_part)); + if ( ! image_parts ) + FIASCO_READ_ERROR(fiasco, "Cannot allocate image"); + image_part = image_parts; + } + image_part->offset = ntohl(*(uint32_t *)&buf[4]); + image_part->size = ntohl(*(uint32_t *)&buf[12]); + if ( length8 > 16 ) { + image_part->name = calloc(1, length8-16+1); + if ( image_part->name ) + memcpy(image_part->name, &buf[16], length8-16); + } + VERBOSE(" unknown: 0x%02x 0x%02x 0x%02x 0x%02x\n", buf[0], buf[1], buf[2], buf[3]); + VERBOSE(" offset: %u bytes\n", image_part->offset); + VERBOSE(" unknown: 0x%02x 0x%02x 0x%02x 0x%02x\n", buf[8], buf[9], buf[10], buf[11]); + VERBOSE(" size: %u bytes\n", image_part->size); + if ( image_part->name ) + VERBOSE(" partition name: %s\n", image_part->name); + } } else { - VERBOSE("unknown ('%c':%#x)\n", byte, byte); + int i; + VERBOSE("unknown (%#x)\n", byte); + VERBOSE(" hexdump:"); + for ( i = 0; i < length8; i++ ) VERBOSE(" 0x%02x", buf[i]); + VERBOSE("\n"); } --count8; } - /* unknown */ - READ_OR_RETURN(fiasco, buf, 1); + /* checksum */ + READ_OR_RETURN(fiasco, checksum, buf, 1); + VERBOSE(" subinfo checksum: 0x%02x\n", buf[0]); + + if ( ! noverify && buf[0] != 0x00 && checksum != 0xFF ) { + ERROR("Image header subinfo checksum mishmash (counted 0x%02x, got 0x%02x)", (0xFF - checksum + buf[0]) & 0xFF, buf[0]); + return fiasco; + } offset = lseek(fiasco->fd, 0, SEEK_CUR); if ( offset == (off_t)-1 ) @@ -226,7 +301,7 @@ struct fiasco * fiasco_alloc_from_file(const char * file) { VERBOSE(" hwrevs: %s\n", hwrevs); VERBOSE(" data at: %#08x\n", (unsigned int)offset); - image = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout); + image = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout, image_parts); if ( ! image ) FIASCO_READ_ERROR(fiasco, "Cannot allocate image"); @@ -274,10 +349,12 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) { uint32_t length; uint16_t hash; uint8_t length8; + uint8_t checksum; char ** device_hwrevs_bufs; const char * str; const char * type; struct image_list * image_list; + struct image_part * image_part; struct image * image; unsigned char buf[4096]; @@ -375,32 +452,40 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) { /* signature */ WRITE_OR_FAIL_FREE(file, fd, "T", 1, device_hwrevs_bufs); + checksum = 0x00; + /* number of subsections */ - length8 = device_count+1; + length8 = device_count+2; if ( image->version ) ++length8; if ( image->layout ) ++length8; WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs); + CHECKSUM(checksum, &length8, 1); - /* unknown */ + /* file data: asic index: APE (0x01), device type: NAND (0x01), device index: 0 */ WRITE_OR_FAIL_FREE(file, fd, "\x2e\x19\x01\x01\x00", 5, device_hwrevs_bufs); + CHECKSUM(checksum, "\x2e\x19\x01\x01\x00", 5); /* checksum */ hash = htons(image->hash); WRITE_OR_FAIL_FREE(file, fd, &hash, 2, device_hwrevs_bufs); + CHECKSUM(checksum, &hash, 2); /* image type name */ memset(buf, 0, 12); strncpy((char *)buf, type, 12); WRITE_OR_FAIL_FREE(file, fd, buf, 12, device_hwrevs_bufs); + CHECKSUM(checksum, buf, 12); /* image size */ size = htonl(image->size); WRITE_OR_FAIL_FREE(file, fd, &size, 4, device_hwrevs_bufs); + CHECKSUM(checksum, &size, 4); - /* unknown */ + /* image load address (unused always zero) */ WRITE_OR_FAIL_FREE(file, fd, "\x00\x00\x00\x00", 4, device_hwrevs_bufs); + CHECKSUM(checksum, "\x00\x00\x00\x00", 4); /* append version subsection */ if ( image->version ) { @@ -408,6 +493,9 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) { length8 = strlen(image->version)+1; /* +1 for NULL term */ WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs); WRITE_OR_FAIL_FREE(file, fd, image->version, length8, device_hwrevs_bufs); + CHECKSUM(checksum, "1", 1); + CHECKSUM(checksum, &length8, 1); + CHECKSUM(checksum, image->version, length8); } /* append device & hwrevs subsection */ @@ -416,6 +504,9 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) { length8 = ((uint8_t *)(device_hwrevs_bufs[i]))[0]; WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs); WRITE_OR_FAIL_FREE(file, fd, device_hwrevs_bufs[i]+1, length8, device_hwrevs_bufs); + CHECKSUM(checksum, "2", 1); + CHECKSUM(checksum, &length8, 1); + CHECKSUM(checksum, device_hwrevs_bufs[i]+1, length8); } free(device_hwrevs_bufs); @@ -425,10 +516,47 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) { length8 = strlen(image->layout); WRITE_OR_FAIL(file, fd, &length8, 1); WRITE_OR_FAIL(file, fd, image->layout, length8); + CHECKSUM(checksum, "3", 1); + CHECKSUM(checksum, &length8, 1); + CHECKSUM(checksum, image->layout, length8); } - /* dummy byte - end of all subsections */ - WRITE_OR_FAIL(file, fd, "\x00", 1); + if ( image->parts ) { + /* for each image part append subsection */ + for ( image_part = image->parts; image_part; image_part = image_part->next ) { + WRITE_OR_FAIL(file, fd, "4", 1); /* 4 - image data part */ + CHECKSUM(checksum, "4", 1); + length = 16 + (image_part->name ? strlen(image_part->name) : 0); + length8 = length <= UINT8_MAX ? length : UINT8_MAX; + WRITE_OR_FAIL(file, fd, &length8, 1); + CHECKSUM(checksum, &length8, 1); + WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4); /* unknown */ + CHECKSUM(checksum, "\x00\x00\x00\x00", 4); + size = htonl(image_part->offset); + WRITE_OR_FAIL(file, fd, &size, 4); + CHECKSUM(checksum, &size, 4); + WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4); /* unknown */ + CHECKSUM(checksum, "\x00\x00\x00\x00", 4); + size = htonl(image_part->size); + WRITE_OR_FAIL(file, fd, &size, 4); + CHECKSUM(checksum, &size, 4); + if ( image_part->name ) { + WRITE_OR_FAIL(file, fd, image_part->name, length-16); + CHECKSUM(checksum, image_part->name, length-16); + } + } + } else { + /* append one image data part subsection */; + WRITE_OR_FAIL(file, fd, "4\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14); + CHECKSUM(checksum, "4\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14); + size = htonl(image->size); + WRITE_OR_FAIL(file, fd, &size, 4); + CHECKSUM(checksum, &size, 4); + } + + /* checksum of header */ + checksum = 0xFF - checksum; + WRITE_OR_FAIL(file, fd, &checksum, 1); printf("Writing image data...\n"); @@ -461,8 +589,10 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) { char * name; char * layout_name; struct image * image; + struct image_part * image_part; struct image_list * image_list; - uint32_t size; + uint32_t offset, size, need, total_size, written; + int part_num; char cwd[256]; unsigned char buf[4096]; @@ -489,68 +619,30 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) { while ( image_list ) { fd = -1; - name = NULL; - layout_name = NULL; image = image_list->image; - name = image_name_alloc_from_values(image); - if ( ! name ) - return -1; - printf("\n"); printf("Unpacking image...\n"); image_print_info(image); if ( image->layout ) { - layout_name = calloc(1, strlen(name) + sizeof(".layout")-1 + 1); + name = image_name_alloc_from_values(image, -1); + if ( ! name ) + ALLOC_ERROR_RETURN(-1); + + layout_name = calloc(1, strlen(name) + sizeof("_layout")-1 + 1); if ( ! layout_name ) { free(name); ALLOC_ERROR_RETURN(-1); } - sprintf(layout_name, "%s.layout", name); + sprintf(layout_name, "%s_layout", name); + free(name); printf(" Layout file: %s\n", layout_name); - } - - printf(" Output file: %s\n", name); - - if ( ! simulate ) { - fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644); - if ( fd < 0 ) { - ERROR_INFO("Cannot create output file %s", name); - free(name); - free(layout_name); - return -1; - } - } - - image_seek(image, 0); - while ( 1 ) { - size = image_read(image, buf, sizeof(buf)); - if ( size == 0 ) - break; - if ( ! simulate ) { - if ( write(fd, buf, size) != (ssize_t)size ) { - ERROR_INFO_STR(name, "Cannot write %d bytes", size); - close(fd); - free(name); - free(layout_name); - return -1; - } - } - } - - free(name); - - if ( ! simulate ) - close(fd); - - if ( image->layout ) { - if ( ! simulate ) { fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644); if ( fd < 0 ) { @@ -571,11 +663,73 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) { free(layout_name); - if ( ! simulate ) + if ( ! simulate ) { close(fd); + fd = -1; + } } + part_num = 0; + image_part = image->parts; + + do { + + offset = image_part ? image_part->offset : 0; + total_size = image_part ? image_part->size : image->size; + + name = image_name_alloc_from_values(image, image_part ? part_num : -1); + if ( ! name ) + ALLOC_ERROR_RETURN(-1); + + if ( image_part && ( part_num > 0 || image_part->next ) ) + printf(" Output file part %d: %s\n", part_num+1, name); + else + printf(" Output file: %s\n", name); + + if ( ! simulate ) { + fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644); + if ( fd < 0 ) { + ERROR_INFO("Cannot create output file %s", name); + free(name); + return -1; + } + } + + written = 0; + image_seek(image, offset); + while ( written < total_size ) { + need = total_size - written; + if ( need > sizeof(buf) ) + need = sizeof(buf); + size = image_read(image, buf, need); + if ( size == 0 ) + break; + if ( ! simulate ) { + if ( write(fd, buf, size) != (ssize_t)size ) { + ERROR_INFO_STR(name, "Cannot write %d bytes", size); + close(fd); + free(name); + return -1; + } + } + written += size; + } + + free(name); + + if ( ! simulate ) { + close(fd); + fd = -1; + } + + if ( image_part ) { + image_part = image_part->next; + part_num++; + } + + } while ( image_part ); + image_list = image_list->next; } diff --git a/src/image.c b/src/image.c index b78633b..fef124e 100644 --- a/src/image.c +++ b/src/image.c @@ -100,7 +100,7 @@ static void image_missing_values_from_name(struct image * image, const char * na } /* format: type-device:hwrevs_version */ -char * image_name_alloc_from_values(struct image * image) { +char * image_name_alloc_from_values(struct image * image, int part_num) { char * name; char * ptr; @@ -108,6 +108,8 @@ char * image_name_alloc_from_values(struct image * image) { size_t length; const char * type; const char * device; + struct image_part * part; + int i; type = image_type_to_string(image->type); @@ -124,6 +126,14 @@ char * image_name_alloc_from_values(struct image * image) { else hwrevs = NULL; + part = image->parts; + + if ( part && ( !part->next || part_num < 0 ) ) + part = NULL; + + for ( i = 0; i < part_num && part; i++ ) + part = part->next; + length = 1 + strlen(type); if ( device ) @@ -132,6 +142,10 @@ char * image_name_alloc_from_values(struct image * image) { length += 1 + strlen(hwrevs); if ( image->version ) length += 1 + strlen(image->version); + if ( part ) + length += 4 + 3; /* 3 <= strlen(part_num) */ + if ( part && part->name ) + length += 1 + strlen(part->name); name = calloc(1, length); if ( ! name ) { @@ -149,13 +163,19 @@ char * image_name_alloc_from_values(struct image * image) { if ( image->version ) ptr += sprintf(ptr, "_%s", image->version); + if ( part ) { + ptr += sprintf(ptr, "_part%d", part_num+1); + if ( part->name ) + ptr += sprintf(ptr, "_%s", part->name); + } + free(hwrevs); return name; } -static int image_append(struct image * image, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { +static int image_append(struct image * image, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { enum image_type detected_type; @@ -210,6 +230,8 @@ static int image_append(struct image * image, const char * type, const char * de else image->layout = NULL; + image->parts = parts; + return 0; } @@ -244,7 +266,7 @@ static struct image * image_alloc(void) { } -struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { +struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { int fd; @@ -254,11 +276,11 @@ struct image * image_alloc_from_file(const char * file, const char * type, const return NULL; } - return image_alloc_from_fd(fd, file, type, device, hwrevs, version, layout); + return image_alloc_from_fd(fd, file, type, device, hwrevs, version, layout, parts); } -struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { +struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { off_t offset; struct image * image = image_alloc(); @@ -291,7 +313,7 @@ struct image * image_alloc_from_fd(int fd, const char * orig_filename, const cha return NULL; } - if ( image_append(image, type, device, hwrevs, version, layout) < 0 ) + if ( image_append(image, type, device, hwrevs, version, layout, parts) < 0 ) return NULL; if ( ( ! type || ! type[0] ) && ( ! device || ! device[0] ) && ( ! hwrevs || ! hwrevs[0] ) && ( ! version || ! version[0] ) ) @@ -303,7 +325,7 @@ struct image * image_alloc_from_fd(int fd, const char * orig_filename, const cha } -struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { +struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { struct image * image = image_alloc(); if ( ! image ) @@ -315,7 +337,7 @@ struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, ui image->offset = offset; image->cur = 0; - if ( image_append(image, type, device, hwrevs, version, layout) < 0 ) + if ( image_append(image, type, device, hwrevs, version, layout, parts) < 0 ) return NULL; if ( ! noverify && image->hash != hash ) { @@ -347,6 +369,13 @@ void image_free(struct image * image) { image->devices = next; } + while ( image->parts ) { + struct image_part * next = image->parts->next; + free(image->parts->name); + free(image->parts); + image->parts = next; + } + free(image->version); free(image->layout); free(image->orig_filename); @@ -516,6 +545,9 @@ static const char * image_types[] = { [IMAGE_CMT_2ND] = "cmt-2nd", [IMAGE_CMT_ALGO] = "cmt-algo", [IMAGE_CMT_MCUSW] = "cmt-mcusw", + [IMAGE_1ST] = "1st", + [IMAGE_CERT_SW] = "cert-sw", + [IMAGE_APE_ALGO] = "ape-algo", }; enum image_type image_type_from_data(struct image * image) { diff --git a/src/image.h b/src/image.h index 42111bf..824c8ad 100644 --- a/src/image.h +++ b/src/image.h @@ -37,9 +37,19 @@ enum image_type { IMAGE_CMT_2ND, IMAGE_CMT_ALGO, IMAGE_CMT_MCUSW, + IMAGE_1ST, + IMAGE_CERT_SW, + IMAGE_APE_ALGO, IMAGE_COUNT, }; +struct image_part { + struct image_part * next; + uint32_t offset; + uint32_t size; + char * name; +}; + struct image { enum image_type type; struct device_list * devices; @@ -47,6 +57,7 @@ struct image { char * layout; uint16_t hash; uint32_t size; + struct image_part * parts; int fd; int is_shared_fd; @@ -63,9 +74,9 @@ struct image_list { struct image_list * next; }; -struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout); -struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout); -struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout); +struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts); +struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts); +struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts); void image_free(struct image * image); void image_seek(struct image * image, size_t whence); size_t image_read(struct image * image, void * buf, size_t count); @@ -76,7 +87,7 @@ void image_list_unlink(struct image_list * list); uint16_t image_hash_from_data(struct image * image); enum image_type image_type_from_data(struct image * image); -char * image_name_alloc_from_values(struct image * image); +char * image_name_alloc_from_values(struct image * image, int part_num); enum image_type image_type_from_string(const char * type); const char * image_type_to_string(enum image_type type); int image_hwrev_is_valid(struct image * image, int16_t hwrev); 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"); @@ -143,7 +143,7 @@ int simulate; int noverify; int verbose; -/* arg = [[[dev:[hw:]]ver:]type:]file[%%lay] */ +/* arg = [[[dev:[hw:]]ver:]type:]file[%file2%file3...%lay] */ static void parse_image_arg(char * arg, struct image_list ** image_first) { struct stat st; @@ -154,14 +154,16 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) { char * hwrevs; char * version; char * layout; + char * parts; char * layout_file; + char * ptr; int fd; /* First check if arg is file, then try to parse arg format */ fd = open(arg, O_RDONLY); if ( fd >= 0 ) { if ( fstat(fd, &st) == 0 && !S_ISDIR(st.st_mode) ) { - image = image_alloc_from_fd(fd, arg, NULL, NULL, NULL, NULL, NULL); + image = image_alloc_from_fd(fd, arg, NULL, NULL, NULL, NULL, NULL, NULL); if ( ! image ) { ERROR("Cannot load image file %s", arg); exit(1); @@ -175,9 +177,15 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) { exit(1); } - layout_file = strchr(arg, '%'); - if ( layout_file ) - *(layout_file++) = 0; + parts = strchr(arg, '%'); + if ( parts ) + *(parts++) = 0; + + layout_file = parts; + if ( layout_file ) { + while ( ( ptr = strchr(layout_file, '%') ) ) + layout_file = ptr+1; + } type = NULL; device = NULL; @@ -237,7 +245,9 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) { close(fd); } - image = image_alloc_from_file(file, type, device, hwrevs, version, layout); + /* TODO: alloc parts */ + + image = image_alloc_from_file(file, type, device, hwrevs, version, layout, NULL); if ( layout ) free(layout); @@ -426,6 +436,8 @@ int main(int argc, char **argv) { int i; char buf[512]; char * ptr = NULL; + char * ptr1 = NULL; + char * ptr2 = NULL; char * tmp = NULL; char nolo_ver[512]; @@ -1036,9 +1048,9 @@ int main(int argc, char **argv) { /* filter images by device & hwrev */ if ( detected_device ) filter_images_by_device(dev->detected_device, &image_first); - if ( detected_hwrev ) + if ( detected_hwrev > 0 ) filter_images_by_hwrev(dev->detected_hwrev, &image_first); - if ( fiasco_in && ( detected_device || detected_hwrev ) ) + if ( fiasco_in && ( detected_device || detected_hwrev > 0 ) ) fiasco_in->first = image_first; /* set kernel and initfs images for loading */ @@ -1096,7 +1108,7 @@ int main(int argc, char **argv) { if ( dev_load ) { if ( image_kernel ) { ret = dev_load_image(dev, image_kernel->image); - if ( ret < 0 ) + if ( ret == -EAGAIN ) goto again; if ( image_kernel == image_first ) @@ -1110,7 +1122,7 @@ int main(int argc, char **argv) { if ( image_initfs ) { ret = dev_load_image(dev, image_initfs->image); - if ( ret < 0 ) + if ( ret == -EAGAIN ) goto again; if ( image_initfs == image_first ) @@ -1129,7 +1141,7 @@ int main(int argc, char **argv) { while ( image_ptr ) { struct image_list * next = image_ptr->next; ret = dev_flash_image(dev, image_ptr->image); - if ( ret < 0 ) + if ( ret == -EAGAIN ) goto again; if ( image_ptr == image_first ) @@ -1265,7 +1277,8 @@ int main(int argc, char **argv) { continue; buf[0] = 0; - snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev); + if ( dev->detected_hwrev > 0 ) + snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev); switch ( i ) { case IMAGE_2ND: @@ -1295,7 +1308,9 @@ int main(int argc, char **argv) { break; } - image_dump = image_alloc_from_file(image_tmp_name(i), image_type_to_string(i), device_to_string(dev->detected_device), buf, ptr, NULL); + /* TODO: add support for dumping mmc layout and also other mmc partitions as image data parts */ + + image_dump = image_alloc_from_file(image_tmp_name(i), image_type_to_string(i), device_to_string(dev->detected_device), buf, ptr, NULL, NULL); if ( ! image_dump ) continue; @@ -1366,7 +1381,20 @@ int main(int argc, char **argv) { } buf[0] = 0; - snprintf(buf, sizeof(buf), "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr); + snprintf(buf, sizeof(buf), "%s", image_type_to_string(i)); + ptr1 = buf + strlen(buf); + + if ( dev->detected_device ) { + snprintf(ptr1, sizeof(buf)-(ptr1-buf), "-%s", device_to_string(dev->detected_device)); + ptr1 += strlen(ptr1); + } + + if ( dev->detected_hwrev > 0 ) + snprintf(ptr1, sizeof(buf)-(ptr1-buf), ":%hd", dev->detected_hwrev); + ptr2 = ptr1 + strlen(ptr1); + + if ( ptr && ptr[0] ) + snprintf(ptr2, sizeof(buf)-(ptr2-buf), "_%s", ptr); rename_ret = rename(image_tmp_name(i), buf); rename_errno = errno; @@ -1381,13 +1409,21 @@ int main(int argc, char **argv) { errno = rename_errno; ERROR_INFO("Renaming failed"); - buf[0] = 0; - snprintf(buf, sizeof(buf), "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr); + *ptr2 = 0; printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf); - if ( rename(image_tmp_name(i), buf) < 0 ) + if ( rename(image_tmp_name(i), buf) < 0 ) { + ERROR_INFO("Renaming failed"); + *ptr1 = 0; + printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf); + + if ( rename(image_tmp_name(i), buf) < 0 ) + ERROR_INFO("Renaming failed"); + + } + } } @@ -213,14 +213,18 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) { msg1 = (struct mkii_message *)buf1; ptr = msg->data; - /* Signature */ - memcpy(ptr, "\x2E\x19\x01\x01", 4); - ptr += 4; + /* File data header */ + memcpy(ptr, "\x2E", 1); + ptr += 1; - /* Space */ - memcpy(ptr, "\x00", 1); + /* Length of file data */ + memcpy(ptr, "\x19", 1); ptr += 1; + /* File data (ignored): asic index: APE (0x01), device type: NAND (0x01), device index: 0 */ + memcpy(ptr, "\x01\x01\x00", 3); + ptr += 3; + /* Hash */ hash = htons(image->hash); memcpy(ptr, &hash, 2); @@ -239,7 +243,7 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) { memcpy(ptr, &size, 4); ptr += 4; - /* Space */ + /* Load address (ignored) */ memcpy(ptr, "\x00\x00\x00\x00", 4); ptr += 4; @@ -269,14 +269,18 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i ptr = buf; - /* Signature */ - memcpy(ptr, "\x2E\x19\x01\x01", 4); - ptr += 4; + /* File data header */ + memcpy(ptr, "\x2E", 1); + ptr += 1; - /* Space */ - memcpy(ptr, "\x00", 1); + /* Length of file data */ + memcpy(ptr, "\x19", 1); ptr += 1; + /* File data (ignored by NOLO): asic index: APE (0x01), device type: NAND (0x01), device index: 0 */ + memcpy(ptr, "\x01\x01\x00", 3); + ptr += 3; + /* Hash */ hash = htons(image->hash); memcpy(ptr, &hash, 2); @@ -295,7 +299,7 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i memcpy(ptr, &size, 4); ptr += 4; - /* Space */ + /* Load address (ignored by NOLO) */ memcpy(ptr, "\x00\x00\x00\x00", 4); ptr += 4; |