local: Parse real kernel size from NOLO!img header when dumping kernel image

Kernel image is prepended with 2kB header with NOLO!img magic and contains
size of the kernel image. 0xFFFF until now just skipped this header. With
this change is reads from it real kernel image size and correctly truncate
final dumped image for 0xFFFF -e/-E dump operation.
This commit is contained in:
Pali Rohár committed 2021-05-01 18:20:13 +02:00
1 parent 67427daf17
commit 342dc610b3
1 file changed
+47 -19
+47 -19
View File
@@ -244,36 +244,36 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
} }
struct nanddump_args { struct nanddump_args {
int valid;
int mtd; int mtd;
int offset; int offset;
int length; int length;
int header;
}; };
static struct nanddump_args nanddump_rx51[] = { static struct nanddump_args nanddump_rx51[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000000, 0x00004000 }, [IMAGE_XLOADER] = { 0, 0x00000000, 0x00004000, 0x00000000 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 }, [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
[IMAGE_KERNEL] = { 1, 3, 0x00000800, 0x001FF800 }, [IMAGE_KERNEL] = { 3, 0x00000000, 0x00200000, 0x00000800 },
[IMAGE_INITFS] = { 1, 4, 0x00000000, 0x00200000 }, [IMAGE_INITFS] = { 4, 0x00000000, 0x00200000, 0x00000000 },
[IMAGE_ROOTFS] = { 1, 5, 0x00000000, 0x0fb40000 }, [IMAGE_ROOTFS] = { 5, 0x00000000, 0x0fb40000, 0x00000000 },
}; };
/* FIXME: Is this table correct? */ /* FIXME: Is this table correct? */
static struct nanddump_args nanddump_rx4x[] = { static struct nanddump_args nanddump_rx4x[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 }, [IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 }, [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x0021F800 }, [IMAGE_KERNEL] = { 2, 0x00000000, 0x00220000, 0x00000800 },
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00400000 }, [IMAGE_INITFS] = { 3, 0x00000000, 0x00400000, 0x00000000 },
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0f960000 }, [IMAGE_ROOTFS] = { 4, 0x00000000, 0x0f960000, 0x00000000 },
}; };
/* FIXME: Is this table correct? */ /* FIXME: Is this table correct? */
static struct nanddump_args nanddump_old[] = { static struct nanddump_args nanddump_old[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 }, [IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 }, [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 }, [IMAGE_KERNEL] = { 2, 0x00000000, 0x00200000, 0x00000800 },
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00200000 }, [IMAGE_INITFS] = { 3, 0x00000000, 0x00200000, 0x00000000 },
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 }, [IMAGE_ROOTFS] = { 4, 0x00000000, 0x0fb80000, 0x00000000 },
}; };
struct nanddump_device { struct nanddump_device {
@@ -380,10 +380,13 @@ static void local_find_internal_mydocs(int * maj, int * min) {
int local_dump_image(enum image_type image, const char * file) { int local_dump_image(enum image_type image, const char * file) {
unsigned char buf[20];
int ret = -1; int ret = -1;
int fd = -1; int fd = -1;
int header = 0;
unsigned char * addr = NULL; unsigned char * addr = NULL;
off_t nlen, len; off_t nlen = (off_t)-1;
off_t len;
int align; int align;
int maj, min; int maj, min;
@@ -425,7 +428,28 @@ int local_dump_image(enum image_type image, const char * file) {
goto clean; goto clean;
} }
ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, nanddump[device].args[image].length); header = nanddump[device].args[image].header;
if ( header > 0 ) {
ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, header);
if ( ret != 0 ) {
unlink(file);
ret = -1;
goto clean;
}
fd = open(file, O_RDONLY);
if ( fd >= 0 ) {
if ( read(fd, buf, 20) == 20 && memcmp(buf, "NOLO!img\x02\x00\x00\x00\x00\x00\x00\x00", 16) == 0 )
nlen = (buf[16] << 0) | (buf[17] << 8) | (buf[18] << 16) | (buf[19] << 24);
close(fd);
}
unlink(file);
}
ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset + header, nanddump[device].args[image].length - header);
} }
@@ -442,6 +466,8 @@ int local_dump_image(enum image_type image, const char * file) {
if ( len == (off_t)-1 || len == 0 ) if ( len == (off_t)-1 || len == 0 )
goto clean; goto clean;
if ( header <= 0 || nlen == (off_t)-1 ) {
addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
if ( addr == MAP_FAILED ) if ( addr == MAP_FAILED )
@@ -466,7 +492,9 @@ int local_dump_image(enum image_type image, const char * file) {
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 ) if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
nlen = ((nlen >> align) + 1) << align; nlen = ((nlen >> align) + 1) << align;
if ( nlen == 0 ) { }
if ( header <= 0 && nlen == 0 ) {
printf("File %s is empty, removing it...\n", file); printf("File %s is empty, removing it...\n", file);
unlink(file); unlink(file);
} else if ( nlen != len ) { } else if ( nlen != len ) {