Signed-off-by: Mikko Hissa <mikko.hissa@werzek.com> SVN-Revision: 41224master
parent
28277caccb
commit
dc5fe5f73f
@ -0,0 +1,28 @@ |
|||||||
|
--- a/drivers/mtd/mtdpart.c 2014-04-27 10:09:21.566294160 +0300
|
||||||
|
+++ b/drivers/mtd/mtdpart.c 2014-06-09 11:27:48.952211672 +0300
|
||||||
|
@@ -793,8 +793,11 @@
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
__be32 magic;
|
||||||
|
- __be32 pad[2];
|
||||||
|
+ __be32 pad0[2];
|
||||||
|
__be32 size;
|
||||||
|
+ __be32 pad1[4];
|
||||||
|
+ __be32 name[7];
|
||||||
|
+ __be32 kern_size;
|
||||||
|
} hdr;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
@@ -804,7 +807,11 @@
|
||||||
|
if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
- len = be32_to_cpu(hdr.size) + 0x40;
|
||||||
|
+ if (hdr.kern_size != 0 && hdr.name[0] == 0)
|
||||||
|
+ len = be32_to_cpu(hdr.kern_size);
|
||||||
|
+ else
|
||||||
|
+ len = be32_to_cpu(hdr.size) + 0x40;
|
||||||
|
+
|
||||||
|
__mtd_add_partition(master, "rootfs", part->offset + len,
|
||||||
|
part->mtd.size - len, false);
|
||||||
|
}
|
@ -0,0 +1,294 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright (C) 2014 OpenWrt.org |
||||||
|
* Copyright (C) 2014 Mikko Hissa <mikko.hissa@werzek.com> |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify it |
||||||
|
* under the terms of the GNU General Public License version 2 as published |
||||||
|
* by the Free Software Foundation. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <errno.h> |
||||||
|
#include <fcntl.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <netinet/in.h> |
||||||
|
#include <sys/mman.h> |
||||||
|
#include <sys/stat.h> |
||||||
|
#include <time.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <zlib.h> |
||||||
|
|
||||||
|
#define IH_MAGIC 0x27051956 |
||||||
|
#define IH_NMLEN 32 |
||||||
|
#define IH_PRODLEN 23 |
||||||
|
|
||||||
|
#define IH_TYPE_INVALID 0 |
||||||
|
#define IH_TYPE_STANDALONE 1 |
||||||
|
#define IH_TYPE_KERNEL 2 |
||||||
|
#define IH_TYPE_RAMDISK 3 |
||||||
|
#define IH_TYPE_MULTI 4 |
||||||
|
#define IH_TYPE_FIRMWARE 5 |
||||||
|
#define IH_TYPE_SCRIPT 6 |
||||||
|
#define IH_TYPE_FILESYSTEM 7 |
||||||
|
|
||||||
|
/*
|
||||||
|
* Compression Types |
||||||
|
*/ |
||||||
|
#define IH_COMP_NONE 0 |
||||||
|
#define IH_COMP_GZIP 1 |
||||||
|
#define IH_COMP_BZIP2 2 |
||||||
|
#define IH_COMP_LZMA 3 |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
uint8_t major; |
||||||
|
uint8_t minor; |
||||||
|
} version_t; |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
version_t kernel; |
||||||
|
version_t fs; |
||||||
|
uint8_t productid[IH_PRODLEN]; |
||||||
|
uint8_t sub_fs; |
||||||
|
uint32_t ih_ksz; |
||||||
|
} asus_t; |
||||||
|
|
||||||
|
typedef struct image_header { |
||||||
|
uint32_t ih_magic; |
||||||
|
uint32_t ih_hcrc; |
||||||
|
uint32_t ih_time; |
||||||
|
uint32_t ih_size; |
||||||
|
uint32_t ih_load; |
||||||
|
uint32_t ih_ep; |
||||||
|
uint32_t ih_dcrc; |
||||||
|
uint8_t ih_os; |
||||||
|
uint8_t ih_arch; |
||||||
|
uint8_t ih_type; |
||||||
|
uint8_t ih_comp; |
||||||
|
union { |
||||||
|
uint8_t ih_name[IH_NMLEN]; |
||||||
|
asus_t asus; |
||||||
|
} tail; |
||||||
|
} image_header_t; |
||||||
|
|
||||||
|
typedef struct squashfs_sb { |
||||||
|
uint32_t s_magic; |
||||||
|
uint32_t pad0[9]; |
||||||
|
uint64_t bytes_used; |
||||||
|
} squashfs_sb_t; |
||||||
|
|
||||||
|
typedef enum { |
||||||
|
NONE, FACTORY, SYSUPGRADE, |
||||||
|
} op_mode_t; |
||||||
|
|
||||||
|
void |
||||||
|
calc_crc(image_header_t *hdr, void *data, uint32_t len) |
||||||
|
{ |
||||||
|
/*
|
||||||
|
* Calculate payload checksum |
||||||
|
*/ |
||||||
|
hdr->ih_dcrc = htonl(crc32(0, data, len)); |
||||||
|
hdr->ih_size = htonl(len); |
||||||
|
/*
|
||||||
|
* Calculate header checksum |
||||||
|
*/ |
||||||
|
hdr->ih_hcrc = 0; |
||||||
|
hdr->ih_hcrc = htonl(crc32(0, hdr, sizeof(image_header_t))); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static void |
||||||
|
usage(const char *progname, int status) |
||||||
|
{ |
||||||
|
FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; |
||||||
|
int i; |
||||||
|
|
||||||
|
fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); |
||||||
|
fprintf(stream, "\n" |
||||||
|
"Options:\n" |
||||||
|
" -f <file> generate a factory flash image <file>\n" |
||||||
|
" -s <file> generate a sysupgrade flash image <file>\n" |
||||||
|
" -h show this screen\n"); |
||||||
|
exit(status); |
||||||
|
} |
||||||
|
|
||||||
|
int |
||||||
|
process_image(char *progname, char *filename, op_mode_t opmode) |
||||||
|
{ |
||||||
|
int fd, len; |
||||||
|
void *data, *ptr; |
||||||
|
char namebuf[IH_NMLEN]; |
||||||
|
struct stat sbuf; |
||||||
|
uint32_t checksum, offset_kernel, offset_sqfs, offset_end, |
||||||
|
offset_sec_header, offset_eb, offset_image_end; |
||||||
|
squashfs_sb_t *sqs; |
||||||
|
image_header_t *hdr; |
||||||
|
|
||||||
|
if ((fd = open(filename, O_RDWR, 0666)) < 0) { |
||||||
|
fprintf (stderr, "%s: Can't open %s: %s\n", |
||||||
|
progname, filename, strerror(errno)); |
||||||
|
return (EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
if (fstat(fd, &sbuf) < 0) { |
||||||
|
fprintf (stderr, "%s: Can't stat %s: %s\n", |
||||||
|
progname, filename, strerror(errno)); |
||||||
|
return (EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
if ((unsigned)sbuf.st_size < sizeof(image_header_t)) { |
||||||
|
fprintf (stderr, |
||||||
|
"%s: Bad size: \"%s\" is no valid image\n", |
||||||
|
progname, filename); |
||||||
|
return (EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
ptr = (void *)mmap(0, sbuf.st_size, |
||||||
|
PROT_READ | PROT_WRITE, |
||||||
|
MAP_SHARED, |
||||||
|
fd, 0); |
||||||
|
|
||||||
|
if ((caddr_t)ptr == (caddr_t)-1) { |
||||||
|
fprintf (stderr, "%s: Can't read %s: %s\n", |
||||||
|
progname, filename, strerror(errno)); |
||||||
|
return (EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
hdr = ptr; |
||||||
|
|
||||||
|
if (ntohl(hdr->ih_magic) != IH_MAGIC) { |
||||||
|
fprintf (stderr, |
||||||
|
"%s: Bad Magic Number: \"%s\" is no valid image\n", |
||||||
|
progname, filename); |
||||||
|
return (EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
if (opmode == FACTORY) { |
||||||
|
strncpy(&namebuf, (char *)&hdr->tail.ih_name, IH_NMLEN); |
||||||
|
hdr->tail.asus.kernel.major = 0; |
||||||
|
hdr->tail.asus.kernel.minor = 0; |
||||||
|
hdr->tail.asus.fs.major = 0; |
||||||
|
hdr->tail.asus.fs.minor = 0; |
||||||
|
strncpy((char *)&hdr->tail.asus.productid, "RT-N56U", IH_PRODLEN); |
||||||
|
} |
||||||
|
|
||||||
|
if (hdr->tail.asus.ih_ksz == 0) |
||||||
|
hdr->tail.asus.ih_ksz = htonl(ntohl(hdr->ih_size) + sizeof(image_header_t)); |
||||||
|
|
||||||
|
offset_kernel = sizeof(image_header_t); |
||||||
|
offset_sqfs = ntohl(hdr->tail.asus.ih_ksz); |
||||||
|
sqs = ptr + offset_sqfs; |
||||||
|
offset_sec_header = offset_sqfs + sqs->bytes_used; |
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserve space for the second header. |
||||||
|
*/ |
||||||
|
offset_end = offset_sec_header + sizeof(image_header_t); |
||||||
|
offset_eb = ((offset_end>>16)+1)<<16; |
||||||
|
|
||||||
|
if (opmode == FACTORY) |
||||||
|
offset_image_end = offset_eb + 4; |
||||||
|
else |
||||||
|
offset_image_end = sbuf.st_size; |
||||||
|
/*
|
||||||
|
* Move the second header at the end of the image. |
||||||
|
*/ |
||||||
|
offset_end = offset_sec_header; |
||||||
|
offset_sec_header = offset_eb - sizeof(image_header_t); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove jffs2 markers between squashfs and eb boundary. |
||||||
|
*/ |
||||||
|
if (opmode == FACTORY) |
||||||
|
memset(ptr+offset_end, 0xff ,offset_eb - offset_end); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Grow the image if needed. |
||||||
|
*/ |
||||||
|
if (offset_image_end > sbuf.st_size) { |
||||||
|
(void) munmap((void *)ptr, sbuf.st_size); |
||||||
|
ftruncate(fd, offset_image_end); |
||||||
|
ptr = (void *)mmap(0, offset_image_end, |
||||||
|
PROT_READ | PROT_WRITE, |
||||||
|
MAP_SHARED, |
||||||
|
fd, 0); |
||||||
|
/*
|
||||||
|
* jffs2 marker |
||||||
|
*/ |
||||||
|
if (opmode == FACTORY) { |
||||||
|
*(uint8_t *)(ptr+offset_image_end-4) = 0xde; |
||||||
|
*(uint8_t *)(ptr+offset_image_end-3) = 0xad; |
||||||
|
*(uint8_t *)(ptr+offset_image_end-2) = 0xc0; |
||||||
|
*(uint8_t *)(ptr+offset_image_end-1) = 0xde; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate checksums for the second header to be used after flashing. |
||||||
|
*/ |
||||||
|
if (opmode == FACTORY) { |
||||||
|
hdr = ptr+offset_sec_header; |
||||||
|
memcpy(hdr, ptr, sizeof(image_header_t)); |
||||||
|
strncpy((char *)&hdr->tail.ih_name, &namebuf, IH_NMLEN); |
||||||
|
calc_crc(hdr, ptr+offset_kernel, offset_sqfs - offset_kernel); |
||||||
|
calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_image_end - offset_kernel); |
||||||
|
} else { |
||||||
|
calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_sqfs - offset_kernel); |
||||||
|
} |
||||||
|
|
||||||
|
if (sbuf.st_size > offset_image_end) |
||||||
|
(void) munmap((void *)ptr, sbuf.st_size); |
||||||
|
else |
||||||
|
(void) munmap((void *)ptr, offset_image_end); |
||||||
|
|
||||||
|
ftruncate(fd, offset_image_end); |
||||||
|
(void) close (fd); |
||||||
|
|
||||||
|
return EXIT_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
int |
||||||
|
main(int argc, char **argv) |
||||||
|
{ |
||||||
|
int opt; |
||||||
|
char *filename, *progname; |
||||||
|
op_mode_t opmode = NONE; |
||||||
|
|
||||||
|
progname = argv[0]; |
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv,":s:f:h?")) != -1) { |
||||||
|
switch (opt) { |
||||||
|
case 's': |
||||||
|
opmode = SYSUPGRADE; |
||||||
|
filename = optarg; |
||||||
|
break; |
||||||
|
case 'f': |
||||||
|
opmode = FACTORY; |
||||||
|
filename = optarg; |
||||||
|
break; |
||||||
|
case 'h': |
||||||
|
opmode = NONE; |
||||||
|
default: |
||||||
|
usage(progname, EXIT_FAILURE); |
||||||
|
opmode = NONE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(filename == NULL) |
||||||
|
opmode = NONE; |
||||||
|
|
||||||
|
switch (opmode) { |
||||||
|
case NONE: |
||||||
|
usage(progname, EXIT_FAILURE); |
||||||
|
break; |
||||||
|
case FACTORY: |
||||||
|
case SYSUPGRADE: |
||||||
|
return process_image(progname, filename, opmode); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return EXIT_SUCCESS; |
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue