diff options
-rw-r--r-- | src/fiasco.c | 152 | ||||
-rw-r--r-- | src/image.c | 45 | ||||
-rw-r--r-- | src/image.h | 16 | ||||
-rw-r--r-- | src/main.c | 24 |
4 files changed, 169 insertions, 68 deletions
diff --git a/src/fiasco.c b/src/fiasco.c index 890e1c0..a0caf1a 100644 --- a/src/fiasco.c +++ b/src/fiasco.c @@ -74,6 +74,8 @@ struct fiasco * fiasco_alloc_from_file(const char * file) { 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]; @@ -188,6 +190,8 @@ struct fiasco * fiasco_alloc_from_file(const char * file) { memset(hwrevs, 0, sizeof(hwrevs)); memset(version, 0, sizeof(version)); memset(layout, 0, sizeof(layout)); + image_part = NULL; + image_parts = NULL; while ( count8 > 0 ) { @@ -237,6 +241,36 @@ 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); } @@ -262,7 +296,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"); @@ -516,8 +550,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]; @@ -543,69 +579,29 @@ 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 ) { @@ -631,6 +627,64 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) { } + 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); + + 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..f9d8059 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); diff --git a/src/image.h b/src/image.h index 42111bf..2535a14 100644 --- a/src/image.h +++ b/src/image.h @@ -40,6 +40,13 @@ enum image_type { 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 +54,7 @@ struct image { char * layout; uint16_t hash; uint32_t size; + struct image_part * parts; int fd; int is_shared_fd; @@ -63,9 +71,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 +84,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); @@ -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,13 @@ 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; + while ( ( ptr = strchr(layout_file, '%') ) ) + layout_file = ptr+1; type = NULL; device = NULL; @@ -237,7 +243,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); @@ -1298,7 +1306,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; |