ramips: RT-N56U support fixes and factory image creation
Signed-off-by: Mikko Hissa <mikko.hissa@werzek.com> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@41224 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
8167453148
commit
bbb8942009
|
@ -5,7 +5,7 @@
|
||||||
# this, so we make sure to zero checksum and size to be checksummed before
|
# this, so we make sure to zero checksum and size to be checksummed before
|
||||||
# that happens, so this needs to run very early during boot.
|
# that happens, so this needs to run very early during boot.
|
||||||
|
|
||||||
do_wnce2001_checksumming_disable() {
|
do_checksumming_disable() {
|
||||||
. /lib/ramips.sh
|
. /lib/ramips.sh
|
||||||
|
|
||||||
local board=$(ramips_board_name)
|
local board=$(ramips_board_name)
|
||||||
|
@ -35,9 +35,22 @@ do_wnce2001_checksumming_disable() {
|
||||||
echo "Checksum is already zero, nothing to do."
|
echo "Checksum is already zero, nothing to do."
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
rt-n56u)
|
||||||
|
echo "Board is ASUS RT-N56U, replacing uImage header..."
|
||||||
|
local firmware_mtd=$(find_mtd_part firmware)
|
||||||
|
local rootfs_mtd=$(find_mtd_part rootfs)
|
||||||
|
local rootfs_data_mtd=$(find_mtd_part rootfs_data)
|
||||||
|
local rootfs_len=$(grep \"rootfs\" /proc/mtd | awk -F' ' '{print "0x"$2}')
|
||||||
|
local rootfs_data_len=$(grep \"rootfs_data\" /proc/mtd | awk -F' ' '{print "0x"$2}')
|
||||||
|
local offset=$(echo "$rootfs_len $rootfs_data_len 0x40" | awk -F' ' '{printf "%i",$1-$2-$3}')
|
||||||
|
local signature=$(dd if=$rootfs_mtd skip=$offset bs=1 count=4 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"')
|
||||||
|
if [ "$signature" == "27051956" ]; then
|
||||||
|
dd conv=notrunc if=$rootfs_mtd skip=$offset of=$firmware_mtd bs=1 count=64 2>/dev/null
|
||||||
|
fi
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
boot_hook_add preinit_main do_wnce2001_checksumming_disable
|
boot_hook_add preinit_main do_checksumming_disable
|
|
@ -43,12 +43,20 @@
|
||||||
host-bridge {
|
host-bridge {
|
||||||
pci-bridge@1 {
|
pci-bridge@1 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
wmac@0,0 {
|
||||||
|
compatible = "ralink,rt2880-pci", "pciclass060400", "pciclass0604";
|
||||||
|
reg = < 0x10000 0 0 0 0 >;
|
||||||
|
ralink,eeprom = "rt2x00pci_1_0.eeprom";
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
wmac@10180000 {
|
wmac@10180000 {
|
||||||
|
status = "okay";
|
||||||
ralink,2ghz = <0>;
|
ralink,2ghz = <0>;
|
||||||
|
ralink,eeprom = "soc_wmac.eeprom";
|
||||||
};
|
};
|
||||||
|
|
||||||
ehci@101c0000 {
|
ehci@101c0000 {
|
||||||
|
|
|
@ -665,7 +665,13 @@ Image/Build/Profile/DIR645=$(call BuildFirmware/Seama/$(1),$(1),dir-645,DIR-645,
|
||||||
omniembhpm_mtd_size=16449536
|
omniembhpm_mtd_size=16449536
|
||||||
Image/Build/Profile/OMNIEMBHPM=$(call BuildFirmware/CustomFlash/$(1),$(1),omni-emb-hpm,OMNI-EMB-HPM,$(omniembhpm_mtd_size))
|
Image/Build/Profile/OMNIEMBHPM=$(call BuildFirmware/CustomFlash/$(1),$(1),omni-emb-hpm,OMNI-EMB-HPM,$(omniembhpm_mtd_size))
|
||||||
|
|
||||||
Image/Build/Profile/RTN56U=$(call BuildFirmware/Default8M/$(1),$(1),rt-n56u,RTN56U)
|
define BuildFirmware/RTN56U/squashfs
|
||||||
|
$(call BuildFirmware/Default8M/$(1),$(1),rt-n56u,RTN56U)
|
||||||
|
-mkrtn56uimg -s $(call sysupname,$(1),rt-n56u)
|
||||||
|
-cp $(call sysupname,$(1),rt-n56u) $(call imgname,$(1),rt-n56u)-factory.bin
|
||||||
|
-mkrtn56uimg -f $(call imgname,$(1),rt-n56u)-factory.bin
|
||||||
|
endef
|
||||||
|
Image/Build/Profile/RTN56U=$(call BuildFirmware/RTN56U/$(1),$(1),rt-n56u,RTN56U)
|
||||||
|
|
||||||
Image/Build/Profile/TEW691GR=$(call BuildFirmware/UMedia/$(1),$(1),tew-691gr,TEW-691GR,0x026910)
|
Image/Build/Profile/TEW691GR=$(call BuildFirmware/UMedia/$(1),$(1),tew-691gr,TEW-691GR,0x026910)
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -67,6 +67,7 @@ define Host/Compile
|
||||||
#$(call cc,mkhilinkfw, -lcrypto)
|
#$(call cc,mkhilinkfw, -lcrypto)
|
||||||
$(call cc,mkdcs932, -Wall)
|
$(call cc,mkdcs932, -Wall)
|
||||||
$(call cc,mkheader_gemtek,-lz)
|
$(call cc,mkheader_gemtek,-lz)
|
||||||
|
$(call cc,mkrtn56uimg, -lz)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Host/Install
|
define Host/Install
|
||||||
|
|
|
@ -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