summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fiasco.c152
-rw-r--r--src/image.c45
-rw-r--r--src/image.h16
-rw-r--r--src/main.c24
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);
diff --git a/src/main.c b/src/main.c
index 9b9e4a5..55467ca 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,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;