2012-07-14 10:33:15 +02:00
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
#include "image.h"
|
|
|
|
|
|
2012-07-14 10:33:15 +02:00
|
|
|
#define IMAGE_CHECK(image) do { if ( ! image || image->fd < 0 ) return; } while (0)
|
|
|
|
|
#define IMAGE_STORE_CUR(image) do { if ( shared_fd ) image->cur = lseek(image->fd, 0, SEEK_CUR) - image->offset; } while (0)
|
|
|
|
|
#define IMAGE_RESTORE_CUR(image) do { if ( shared_fd ) lseek(image->fd, image->offset + image->cur, SEEK_SET); } while (0)
|
|
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
static void image_append(struct image * image, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
|
|
|
|
|
|
|
|
|
|
IMAGE_CHECK(image);
|
2012-07-14 10:33:15 +02:00
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
image->hash = image_hash_from_data(image);
|
|
|
|
|
image->device = device_from_string(device);
|
2012-07-14 10:33:15 +02:00
|
|
|
|
|
|
|
|
if ( type )
|
2012-08-07 14:00:50 +02:00
|
|
|
image->type = image_type_from_string(type);
|
2012-07-14 10:33:15 +02:00
|
|
|
else
|
2012-08-07 14:00:50 +02:00
|
|
|
image->type = image_type_from_data(image);
|
2012-07-14 10:33:15 +02:00
|
|
|
|
|
|
|
|
if ( hwrevs )
|
|
|
|
|
image->hwrevs = strdup(hwrevs);
|
|
|
|
|
|
|
|
|
|
if ( version )
|
|
|
|
|
image->version = strdup(version);
|
|
|
|
|
|
|
|
|
|
if ( layout )
|
|
|
|
|
image->layout = strdup(layout);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct image * image_alloc(void) {
|
|
|
|
|
|
|
|
|
|
struct image * image = calloc(1, sizeof(struct image));
|
|
|
|
|
if ( ! image ) {
|
|
|
|
|
perror("Cannot allocate memory");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return image;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 = image_alloc();
|
|
|
|
|
if ( ! image )
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
image->shared_fd = 0;
|
|
|
|
|
image->fd = open(file, O_RDONLY);
|
|
|
|
|
if ( image->fd < 0 ) {
|
|
|
|
|
perror("Cannot open file");
|
|
|
|
|
free(image);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image->size = lseek(image->fd, 0, SEEK_END);
|
|
|
|
|
image->offset = 0;
|
|
|
|
|
image->cur = 0;
|
|
|
|
|
|
|
|
|
|
image_append(image, type, device, hwrevs, version, layout);
|
|
|
|
|
return image;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
struct image * image_alloc_from_fiasco(struct fiasco * fiasco, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
|
2012-07-14 10:33:15 +02:00
|
|
|
|
|
|
|
|
struct image * image = image_alloc();
|
|
|
|
|
if ( ! image )
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
image->shared_fd = 1;
|
2012-08-07 14:00:50 +02:00
|
|
|
image->fd = fiasco->fd;
|
2012-07-14 10:33:15 +02:00
|
|
|
image->size = size;
|
|
|
|
|
image->offset = offset;
|
|
|
|
|
image->cur = 0;
|
|
|
|
|
|
|
|
|
|
image_append(image, type, device, hwrevs, version, layout);
|
2012-08-07 14:00:50 +02:00
|
|
|
|
|
|
|
|
if ( image->hash != hash ) {
|
|
|
|
|
fprintf(stderr, "Image hash mishmash");
|
|
|
|
|
image_free(image);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-14 10:33:15 +02:00
|
|
|
return image;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void image_free(struct image * image) {
|
|
|
|
|
|
|
|
|
|
IMAGE_CHECK(image);
|
|
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
if ( ! image->shared_fd ) {
|
2012-07-14 10:33:15 +02:00
|
|
|
close(image->fd);
|
|
|
|
|
image->fd = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(image->hwrevs);
|
|
|
|
|
free(image->version);
|
|
|
|
|
free(image->layout);
|
|
|
|
|
|
|
|
|
|
free(image);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void image_seek(struct image * image, whence) {
|
|
|
|
|
|
|
|
|
|
IMAGE_CHECK(image);
|
|
|
|
|
lseek(image->fd, image->offset + whence, SEEK_SET);
|
|
|
|
|
IMAGE_STORE_CUR(image)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t image_read(struct image * image, void * buf, size_t count) {
|
|
|
|
|
|
|
|
|
|
IMAGE_CHECK(image);
|
|
|
|
|
IMAGE_RESTORE_CUR(image);
|
|
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
if ( image->cur + count > image->size ) {
|
|
|
|
|
if ( image->size < image->cur )
|
|
|
|
|
return 0;
|
2012-07-14 10:33:15 +02:00
|
|
|
count = image->size - image->cur;
|
2012-08-07 14:00:50 +02:00
|
|
|
}
|
2012-07-14 10:33:15 +02:00
|
|
|
|
|
|
|
|
count = read(image->fd, buf, count);
|
|
|
|
|
|
|
|
|
|
IMAGE_STORE_CUR(image);
|
|
|
|
|
return count;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
/*size_t image_write(struct image * image, void * buf, size_t count) {
|
2012-07-14 10:33:15 +02:00
|
|
|
|
|
|
|
|
IMAGE_CHECK(image);
|
|
|
|
|
IMAGE_RESTORE_CUR(image);
|
|
|
|
|
count = write(image->fd, buf, count);
|
|
|
|
|
IMAGE_STORE_CUR(image);
|
|
|
|
|
return count;
|
|
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
}*/
|
2012-07-14 10:33:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void image_list_add(struct image_list ** list, struct image * image) {
|
|
|
|
|
|
2012-08-07 14:00:50 +02:00
|
|
|
IMAGE_CHECK(image);
|
2012-07-14 10:33:15 +02:00
|
|
|
struct image_list * first = calloc(1, sizeof(struct image_list));
|
|
|
|
|
if ( ! next )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
first->image = image;
|
|
|
|
|
first->next = *list;
|
|
|
|
|
|
|
|
|
|
if ( *list ) {
|
|
|
|
|
first->prev = *list->prev;
|
|
|
|
|
if ( *list->prev )
|
|
|
|
|
*list->prev->next = first;
|
|
|
|
|
*list->prev = first;
|
|
|
|
|
} else {
|
|
|
|
|
*list = first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void image_list_del(struct image_list * list) {
|
|
|
|
|
|
|
|
|
|
if ( ! list )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if ( list->prev )
|
|
|
|
|
list->prev->next = list->next;
|
|
|
|
|
|
|
|
|
|
if ( list->next )
|
|
|
|
|
list->next->prev = list->prev;
|
|
|
|
|
|
|
|
|
|
image_free(list->image);
|
|
|
|
|
free(list);
|
|
|
|
|
|
|
|
|
|
}
|
2012-08-07 14:00:50 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t image_hash_from_data(struct image * image) {
|
|
|
|
|
|
|
|
|
|
/* TODO */
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char * image_types[] = {
|
|
|
|
|
[IMAGE_XLOADER] = "xloader",
|
|
|
|
|
[IMAGE_2ND] = "2nd",
|
|
|
|
|
[IMAGE_SECONDARY] = "secondary",
|
|
|
|
|
[IMAGE_KERNEL] = "kernel",
|
|
|
|
|
[IMAGE_INITFS] = "initfs",
|
|
|
|
|
[IMAGE_ROOTFS] = "rootfs",
|
|
|
|
|
[IMAGE_OMAP_NAND] = "omap-nand",
|
|
|
|
|
[IMAGE_MMC] = "mmc",
|
|
|
|
|
[IMAGE_CMT_2ND] = "cmt-2nd",
|
|
|
|
|
[IMAGE_CMT_ALGO] = "cmt-algo",
|
|
|
|
|
[IMAGE_CMT_MCUSW] = "cmt-mcusw",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum image_type image_type_from_data(struct image * image) {
|
|
|
|
|
|
|
|
|
|
IMAGE_CHECK(image);
|
|
|
|
|
unsigned char buf[512];
|
|
|
|
|
|
|
|
|
|
image_seek(image, 0);
|
|
|
|
|
image_read(image, buf, sizeof(buf));
|
|
|
|
|
|
|
|
|
|
// 2nd : +0x34 = 2NDAPE
|
|
|
|
|
// secondary: +0x04 = NOLOScnd
|
|
|
|
|
// x-loader : +0x14 = X-LOADER
|
|
|
|
|
// xloader8 : +0x0c = NOLOXldr
|
|
|
|
|
// kernel : +0x00 = 0000 a0e1 0000 a0e1
|
|
|
|
|
// initfs : <2M...be sure with 3M 0x300000
|
|
|
|
|
|
|
|
|
|
if ( memcmp(buf+0x34, "2NDAPE", 6) == 0 )
|
|
|
|
|
return IMAGE_2ND;
|
|
|
|
|
else if ( memcmp(buf+0x04, "NOLOScnd", 8) == 0 )
|
|
|
|
|
return IMAGE_SECONDARY;
|
|
|
|
|
else if ( memcmp(buf+0x14, "X-LOADER", 8) == 0 )
|
|
|
|
|
return IMAGE_XLOADER;
|
|
|
|
|
else if ( memcmp(buf+0x0c, "NOLOXldr", 8) == 0 )
|
|
|
|
|
return IMAGE_XLOADER;
|
|
|
|
|
else if ( memcmp(buf+4, "NOLOXldr", 8) == 0 )
|
|
|
|
|
// TODO: this is xloader800, not valid on 770?
|
|
|
|
|
return IMAGE_2ND;
|
|
|
|
|
else if ( memcmp(buf, "\x00\x00\xa0\xe1\x00\x00\xa0\xe1", 8) == 0 )
|
|
|
|
|
return IMAGE_KERNEL;
|
|
|
|
|
else if ( memcmp(buf, "\x21\x01\x01", 3) == 0 )
|
|
|
|
|
return IMAGE_KERNEL;
|
|
|
|
|
else if ( memcmp(b+0x00, "\x85\x19", 2) == 0 ) {
|
|
|
|
|
// JFFS2 MAGIC
|
|
|
|
|
if ( image->size < 0x300000 )
|
|
|
|
|
return IMAGE_INITFS;
|
|
|
|
|
else
|
|
|
|
|
return IMAGE_ROOTFS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO: Add support for UBIFS rootfs and other types */
|
|
|
|
|
|
|
|
|
|
return IMAGE_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum image_type image_type_from_string(const char * type) {
|
|
|
|
|
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
if ( ! type )
|
|
|
|
|
return IMAGE_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
for ( i = 0; i < sizeof(image_types)/sizeof(image_types[0]); ++i )
|
|
|
|
|
if ( image_types[i] && strcmp(image_types[i], type) == 0 )
|
|
|
|
|
return i;
|
|
|
|
|
|
|
|
|
|
return IMAGE_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char * image_type_to_string(enum image_type type) {
|
|
|
|
|
|
|
|
|
|
if ( type > sizeof(image_types) )
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return image_types[type];
|
|
|
|
|
|
|
|
|
|
}
|