summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--config.mk2
-rw-r--r--doc/dumping5
-rw-r--r--doc/fiasco70
-rw-r--r--src/device.c14
-rw-r--r--src/disk.c124
-rw-r--r--src/disk.h2
-rw-r--r--src/fiasco.c298
-rw-r--r--src/image.c48
-rw-r--r--src/image.h19
-rw-r--r--src/local.c340
-rw-r--r--src/main.c70
-rw-r--r--src/mkii.c16
-rw-r--r--src/nolo.c16
14 files changed, 792 insertions, 234 deletions
diff --git a/TODO b/TODO
index 292b372..fbf0f2d 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/config.mk b/config.mk
index 85c7684..ec685de 100644
--- a/config.mk
+++ b/config.mk
@@ -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"
diff --git a/doc/fiasco b/doc/fiasco
index 941a2da..674c693 100644
--- a/doc/fiasco
+++ b/doc/fiasco
@@ -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;
diff --git a/src/disk.c b/src/disk.c
index 38fbb09..41d1823 100644
--- a/src/disk.c
+++ b/src/disk.c
@@ -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;
}
diff --git a/src/disk.h b/src/disk.h
index 15eb127..f6e3930 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -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");
diff --git a/src/main.c b/src/main.c
index 6c64e6e..5a1cc35 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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");
+
+ }
+
}
}
diff --git a/src/mkii.c b/src/mkii.c
index e50637e..51045f6 100644
--- a/src/mkii.c
+++ b/src/mkii.c
@@ -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;
diff --git a/src/nolo.c b/src/nolo.c
index c30eb77..0684145 100644
--- a/src/nolo.c
+++ b/src/nolo.c
@@ -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;