I've patched official OpenWrt release 19.07.0 kernel for TP-Link WR703N with resized DTS partition structure to have ability to use release packages without any SNAPSHOT compilation.
With patched kernel you can build any packages configuration with Image Builder. It will be helpfull for owners of hardware moded routers with similar hardware.
You can use precompilled image by link below or build your own package configuration.
Images and kernels for 16Mb flash moded TP-Link WR703N device:
patched_kernel_19.07.0
tp-link_wr703n_19.07.0_images
patched_kernel_19.07.1
tp-link_wr703n_19.07.1_images
If you want to use precompilled image just download and flash it. It includes Luci and USB ASIX network adapter support.
If you want to modify kernel patcher for example 8Mb flash and compile your own build please follow next steps, if no just put patched kernel file into Image Builder and pass stage with python script execution:
Download and unpack image builder
wget https://downloads.openwrt.org/releases/19.07.0/targets/ath79/tiny/openwrt-imagebuilder-19.07.0-ath79-tiny.Linux-x86_64.tar.xz
tar xvf openwrt-imagebuilder-19.07.0-ath79-tiny.Linux-x86_64.tar.xz
cd openwrt-imagebuilder-19.07.0-ath79-tiny.Linux-x86_64
Increase image size
vim ~/openwrt-imagebuilder-19.07.0-ath79-tiny.Linux-x86_64/target/linux/ath79/image/tiny-tp-link.mk
define Device/tplink_tl-wr703n
- $(Device/tplink-4mlzma)
+ $(Device/tplink-16mlzma)
ATH_SOC := ar9331
DEVICE_TITLE := TP-Link TL-WR703N
DEVICE_PACKAGES := kmod-usb-chipidea2
TPLINK_HWID := 0x07030101
SUPPORTED_DEVICES += tl-wr703n
endef
TARGET_DEVICES += tplink_tl-wr703n
Put script file 'kernel_patcher.py' into Image Builder folder
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "Taras Gavrylenko"
__copyright__ = "Copyright 2020, The OpenWrt Project"
__version__ = "0.9"
__email__ = "gavrylenko.taras@gmail.com"
__status__ = "Beta"
"""
OpenWrt TP-Link WR703N kernel DTS patcher allows to use release 19.07 kernel
and packages on hardware modded devices with increased flash chip size.
Set environment variable $LZMA_UTIL_PATH with path to LZMA utility
Recommended LZMA 4.65 : Igor Pavlov : Public domain : 2009-02-03
from Openwrt originals
Be sure you have Python interpreter 3.8 or higher
Run: python3.8 kernel_patcher.py <path_to_kernel_file>
Script stages:
1. Rename original kernel to *.bak
2. Unpack original kernel
3. Patch DTS partition table
4. Pack new kernel
"""
import argparse
import logging
import os
import subprocess
from pathlib import Path
logging.basicConfig(
format='%(asctime)s %(levelname)s %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
def run_command(cmd: str):
return subprocess.call(cmd, shell=True)
def compress_lzma(lzma_util: str, raw_path: Path, lzma_path: Path) -> int:
cmd = f'{lzma_util} e {raw_path} {lzma_path} -lc1 -lp2'
status = run_command(cmd)
if status != 0:
raise RuntimeError(f'Failed to compress {raw_path}')
return lzma_path.stat().st_size
def decompress_lzma(lzma_util: str, lzma_path: Path, raw_path: Path) -> int:
cmd = f'{lzma_util} d {lzma_path} {raw_path}'
status = run_command(cmd)
if status != 0:
raise RuntimeError(f'Failed to decompress {lzma_path}')
return raw_path.stat().st_size
def resize_kernel_dts(krnl_path: Path):
chunk_num = 0
chunk_size = 64 * 1024
with krnl_path.open(mode='rb+') as f_out:
while data := f_out.read(chunk_size):
if (offset := data.find(b'partition@20000')) > 0:
ofs_part = chunk_num * chunk_size + offset
logger.info('Found DTS partition table at: '
f'0x{ofs_part:08x}')
break
chunk_num += 1
else:
raise RuntimeError('Could not find DTS partition table')
f_out.seek(ofs_part)
data = bytearray(f_out.read(0x100))
if (offset := data.find(b'\xaa\0\x02\0\0\0\x3d\0\0')) > 0:
data[offset+6] |= 0xc0
else:
raise RuntimeError('Partition pattern not found')
if (offset := data.find(b'partition@3f0000')) > 0:
data[offset+10] = ord('f')
else:
raise RuntimeError('Partition pattern not found')
if (offset := data.find(b'\xaa\0\x3f\0\0\0\x01\0\0')) > 0:
data[offset+2] |= 0xc0
else:
raise RuntimeError('Partition pattern not found')
f_out.seek(ofs_part)
f_out.write(data)
def main():
logger.info('OpenWrt TP-Link WR703N kernel DTS patcher v0.9')
lzma_util_path = os.getenv('LZMA_UTIL_PATH')
if lzma_util_path is None:
logger.error('Compressor utility path is not set: LZMA_UTIL_PATH')
exit(1)
parser = argparse.ArgumentParser()
parser.add_argument('image', help='OpenWrt kernel image file')
args = parser.parse_args()
krnl_path = Path(args.image)
if krnl_path.is_file() is False:
logger.error(f'Kernel image file does not exist: {krnl_path}')
exit(1)
krnl_size = krnl_path.stat().st_size
logger.info(f'Processing kernel image file: {krnl_path}')
logger.info(f'Origin kernel size: 0x{krnl_size:08x}')
kernel_raw_path = Path(krnl_path.with_suffix('.raw'))
logger.info('Decompressing kernel...')
krnl_raw_size = decompress_lzma(
lzma_util_path, krnl_path, kernel_raw_path)
logger.info(f'Decompressed kernel size: 0x{krnl_raw_size:08x}')
logger.info('Resizing kernel DTS...')
resize_kernel_dts(kernel_raw_path)
krnl_path.rename(krnl_path.with_suffix('.bak'))
logger.info('Compressing kernel...')
krnl_lzma_size = compress_lzma(
lzma_util_path, kernel_raw_path, krnl_path)
logger.info(f'Compressed kernel size: 0x{krnl_lzma_size:08x}')
if krnl_lzma_size > krnl_size:
logger.warning('Re-compressed kernel is bigger than original.')
logger.info('Done')
if __name__ == '__main__':
main()
Set environment variable $LZMA_UTIL_PATH with path to LZMA utility
Recommended LZMA 4.65 : Igor Pavlov : Public domain : 2009-02-03 from Openwrt originals
Run script. Be sure you have Python interpreter version >= 3.8
python3.8 kernel_patcher.py ~/openwrt-imagebuilder-19.07.0-ath79-tiny.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ath79_tiny/tplink_tl-wr703n-kernel.bin
If there is no error on previous step, build new image
make image PROFILE=tplink_tl-wr703n PACKAGES="uhttpd luci luci-ssl kmod-usb-net-asix kmod-usb-storage"
...
[mktplinkfw] rootfs offset aligned to 0x1424964
[mktplinkfw] firmware file "~/openwrt-imagebuilder-19.07.0-ath79-tiny.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ath79_tiny/tmp/openwrt-19.07.0-ath79-tiny-tplink_tl-wr703n-squashfs-sysupgrade.bin.new" completed
5067+1 records in
5067+1 records out
2594796 bytes (2.6 MB, 2.5 MiB) copied, 0.0184814 s, 140 MB/s
[mktplinkfw] rootfs offset aligned to 0x1424964
[mktplinkfw] firmware file "~/openwrt-imagebuilder-19.07.0-ath79-tiny.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ath79_tiny/tmp/openwrt-19.07.0-ath79-tiny-tplink_tl-wr703n-squashfs-factory.bin.new" completed
Flash appropriate image into your router and have fun. Forget to save SNAPSHOT compiled packages
***************************************
* U-Boot 1.1.4-7a540a78-clean *
* Build: 2018-02-23 *
***************************************
** Warning: bad env CRC, using default,
use 'saveenv' to save it in FLASH
BOARD: TP-Link TL-WR703N v1
SOC: AR9330 rev. 1
CPU: MIPS 24Kc
RAM: 64 MB DDR1 16-bit CL3-3-3-8
FLASH: 16 MB Winbond W25Q128
MAC: 14:CF:92:BA:A2:7F
CLOCKS: CPU/RAM/AHB/SPI/REF
400/400/200/ 25/ 25 MHz
Hit any key to stop booting: 0
Booting image from 0x9F020000...
Vendor/image name: OpenWrt r10860-a3ffeb413b
Hardware ID: 0x7030101
Whole image size: 7.8 MB (8126464 bytes)
Kernel size: 1.4 MB (1424449 bytes)
Rootfs size: 2.5 MB (2594808 bytes)
Kernel load address: 0x80060000
Kernel entry point: 0x80060000
Header CRC... skipped
Data CRC... skipped
Stopping network... OK!
Uncompressing Kernel... OK!
Starting kernel...
[ 0.000000] Linux version 4.14.162 (builder@buildhost) (gcc version 7.5.0 (OpenWrt GCC 7.5.0 r10860-a3ffeb413b)) #0 Mon Jan 6 16:47:09 2020
[ 0.000000] bootconsole [early0] enabled
[ 0.000000] CPU0 revision is: 00019374 (MIPS 24Kc)
[ 0.000000] MIPS: machine is TP-Link TL-WR703N
[ 0.000000] SoC: Atheros AR9330 rev 1
[ 0.000000] Determined physical RAM map:
[ 0.000000] memory: 04000000 @ 00000000 (usable)
[ 0.000000] Initrd not found or empty - disabling initrd
[ 0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[ 0.000000] Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000000000000-0x0000000003ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000000000-0x0000000003ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000003ffffff]
[ 0.000000] random: get_random_bytes called from 0x804776ec with crng_init=0
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 16256
[ 0.000000] Kernel command line: console=ttyATH0,115200 rootfstype=squashfs,jffs2
[ 0.000000] PID hash table entries: 256 (order: -2, 1024 bytes)
[ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.000000] Writing ErrCtl register=00000000
[ 0.000000] Readback ErrCtl register=00000000
[ 0.000000] Memory: 58924K/65536K available (3544K kernel code, 144K rwdata, 492K rodata, 1188K init, 203K bss, 6612K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS: 51
[ 0.000000] CPU clock: 400.000 MHz
[ 0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302233 ns
[ 0.000014] sched_clock: 32 bits at 200MHz, resolution 5ns, wraps every 10737418237ns
[ 0.007914] Calibrating delay loop... 265.42 BogoMIPS (lpj=1327104)
[ 0.092720] pid_max: default: 32768 minimum: 301
[ 0.097654] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.103979] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.116931] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.125382] futex hash table entries: 256 (order: -1, 3072 bytes)
[ 0.131538] pinctrl core: initialized pinctrl subsystem
[ 0.140169] NET: Registered protocol family 16
[ 0.175968] clocksource: Switched to clocksource MIPS
[ 0.181211] NET: Registered protocol family 2
[ 0.185470] TCP established hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.191170] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.197492] TCP: Hash tables configured (established 1024 bind 1024)
[ 0.204010] UDP hash table entries: 256 (order: 0, 4096 bytes)
[ 0.209694] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.216250] NET: Registered protocol family 1
[ 0.225949] Crashlog allocated RAM at address 0x3f00000
[ 0.231733] workingset: timestamp_bits=30 max_order=14 bucket_order=0
[ 0.245164] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 0.249618] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[ 0.273681] io scheduler noop registered
[ 0.276226] io scheduler deadline registered (default)
[ 0.281811] ar7200-usb-phy usb-phy: phy reset is missing
[ 0.287326] pinctrl-single 18040028.pinmux: 64 pins at pa b8040028 size 8
[ 0.294823] Serial: 8250/16550 driver, 16 ports, IRQ sharing enabled
[ 0.303691] 18020000.uart: ttyATH0 at MMIO 0x18020000 (irq = 9, base_baud = 1562500) is a AR933X UART
[ 0.311956] console [ttyATH0] enabled
[ 0.311956] console [ttyATH0] enabled
[ 0.318778] bootconsole [early0] disabled
[ 0.318778] bootconsole [early0] disabled
[ 0.349961] m25p80 spi0.0: w25q128 (16384 Kbytes)
[ 0.353275] 3 fixed-partitions partitions found on MTD device spi0.0
[ 0.359589] Creating 3 MTD partitions on "spi0.0":
[ 0.364345] 0x000000000000-0x000000020000 : "u-boot"
[ 0.370581] 0x000000020000-0x000000ff0000 : "firmware"
[ 0.375771] 2 tplink-fw partitions found on MTD device firmware
[ 0.380386] Creating 2 MTD partitions on "firmware":
[ 0.385265] 0x000000000000-0x00000015be41 : "kernel"
[ 0.391346] 0x00000015be44-0x000000fd0000 : "rootfs"
[ 0.396279] mtd: device 3 (rootfs) set to be root filesystem
[ 0.400828] 1 squashfs-split partitions found on MTD device rootfs
[ 0.407023] 0x0000003e0000-0x000000fd0000 : "rootfs_data"
[ 0.413520] 0x000000ff0000-0x000001000000 : "art"
[ 0.419280] libphy: Fixed MDIO Bus: probed
[ 0.756451] libphy: ag71xx_mdio: probed
[ 0.759838] libphy: ar8xxx-mdio: probed
[ 0.765326] switch0: Atheros AR724X/AR933X built-in rev. 2 switch registered on mdio-bus.0
[ 1.147720] ag71xx 19000000.eth: connected to PHY at mdio-bus.0:1f:04 [uid=004dd041, driver=Generic PHY]
[ 1.156791] eth0: Atheros AG71xx at 0xb9000000, irq 4, mode: mii
[ 1.164743] NET: Registered protocol family 10
[ 1.174090] Segment Routing with IPv6
[ 1.176551] NET: Registered protocol family 17
[ 1.180811] bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need this.
[ 1.194583] 8021q: 802.1Q VLAN Support v1.8
[ 1.201548] usb_vbus: disabling
[ 1.212067] VFS: Mounted root (squashfs filesystem) readonly on device 31:3.
[ 1.226915] Freeing unused kernel memory: 1188K
[ 1.229983] This architecture does not have kernel memory protection.
[ 2.555986] random: fast init done
[ 3.931778] init: Console is alive
[ 3.934064] init: - watchdog -
[ 5.792046] kmodloader: loading kernel modules from /etc/modules-boot.d/*
[ 6.136381] usbcore: registered new interface driver usbfs
[ 6.140546] usbcore: registered new interface driver hub
[ 6.145835] usbcore: registered new device driver usb
[ 6.161636] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[ 6.174905] ci_hdrc ci_hdrc.0: EHCI Host Controller
[ 6.178455] ci_hdrc ci_hdrc.0: new USB bus registered, assigned bus number 1
[ 6.205990] ci_hdrc ci_hdrc.0: USB 2.0 started, EHCI 1.00
[ 6.211197] hub 1-0:1.0: USB hub found
[ 6.214183] hub 1-0:1.0: 1 port detected
[ 6.230302] SCSI subsystem initialized
[ 6.243616] usbcore: registered new interface driver usb-storage
[ 6.249542] kmodloader: done loading kernel modules from /etc/modules-boot.d/*
[ 6.258913] init: - preinit -
[ 7.584085] random: jshn: uninitialized urandom read (4 bytes read)
[ 8.044837] random: jshn: uninitialized urandom read (4 bytes read)
[ 8.101201] random: jshn: uninitialized urandom read (4 bytes read)
[ 8.397010] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
[ 10.497896] eth0: link up (100Mbps/Full duplex)
[ 10.501016] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[ 12.056534] mount_root: jffs2 not ready yet, using temporary tmpfs overlay
[ 12.104682] urandom-seed: Seed file not found (/etc/urandom.seed)
[ 12.546448] eth0: link down
[ 12.566726] procd: - early -
[ 12.568297] procd: - watchdog -
[ 13.494501] procd: - watchdog -
[ 13.496780] procd: - ubus -
[ 13.928219] urandom_read: 5 callbacks suppressed
[ 13.928232] random: ubusd: uninitialized urandom read (4 bytes read)
[ 13.942235] random: ubusd: uninitialized urandom read (4 bytes read)
[ 13.949430] procd: - init -
Please press Enter to activate this console.
[ 15.406367] kmodloader: loading kernel modules from /etc/modules.d/*
[ 15.433106] ip6_tables: (C) 2000-2006 Netfilter Core Team
[ 15.468704] Loading modules backported from Linux version v4.19.85-0-gc63ee2939dc1
[ 15.474826] Backport generated by backports.git v4.19.85-1-0-g8a8be258
[ 15.499676] ip_tables: (C) 2000-2006 Netfilter Core Team
[ 15.526972] nf_conntrack version 0.5.0 (1024 buckets, 4096 max)
[ 15.719100] xt_time: kernel timezone is -0000
[ 15.729456] usbcore: registered new interface driver asix
[ 15.894010] PPP generic driver version 2.4.2
[ 15.907545] NET: Registered protocol family 24
[ 16.042810] ieee80211 phy0: Atheros AR9330 Rev:1 mem=0xb8100000, irq=2
[ 16.146582] kmodloader: done loading kernel modules from /etc/modules.d/*
[ 16.357454] urngd: v1.0.2 started.
[ 17.450356] random: crng init done
[ 66.170530] br-lan: port 1(eth0) entered blocking state
[ 66.174316] br-lan: port 1(eth0) entered disabled state
[ 66.180094] device eth0 entered promiscuous mode
[ 66.226238] IPv6: ADDRCONF(NETDEV_UP): br-lan: link is not ready
[ 68.258012] eth0: link up (10Mbps/Full duplex)
[ 68.261066] br-lan: port 1(eth0) entered blocking state
[ 68.266286] br-lan: port 1(eth0) entered forwarding state
[ 68.316112] IPv6: ADDRCONF(NETDEV_CHANGE): br-lan: link becomes ready
[ 71.536683] eth0: link down
[ 71.538971] br-lan: port 1(eth0) entered disabled state
[ 73.617998] eth0: link up (100Mbps/Full duplex)
[ 73.621143] br-lan: port 1(eth0) entered blocking state
[ 73.626359] br-lan: port 1(eth0) entered forwarding state
[ 81.547922] jffs2_scan_eraseblock(): End of filesystem marker found at 0x0
[ 81.553402] jffs2_build_filesystem(): unlocking the mtd device...
[ 81.556566] done.
[ 81.563210] jffs2_build_filesystem(): erasing all blocks after the end marker...
[ 120.756026] done.
[ 120.764023] jffs2: notice: (1429) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.
[ 121.080236] overlayfs: upper fs does not support tmpfile.
BusyBox v1.30.1 () built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 19.07.0, r10860-a3ffeb413b
-----------------------------------------------------
=== WARNING! =====================================
There is no root password defined on this device!
Use the "passwd" command to set up a new password
in order to prevent unauthorized SSH logins.
--------------------------------------------------
root@OpenWrt:/# cat /proc/mtd
dev: size erasesize name
mtd0: 00020000 00010000 "u-boot"
mtd1: 00fd0000 00010000 "firmware"
mtd2: 0015be41 00010000 "kernel"
mtd3: 00e741bc 00010000 "rootfs"
mtd4: 00bf0000 00010000 "rootfs_data"
mtd5: 00010000 00010000 "art"
root@OpenWrt:/# df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 3.0M 3.0M 0 100% /rom
tmpfs 29.4M 56.0K 29.3M 0% /tmp
tmpfs 29.4M 64.0K 29.3M 0% /tmp/root
tmpfs 512.0K 0 512.0K 0% /dev
/dev/mtdblock4 11.9M 488.0K 11.5M 4% /overlay
overlayfs:/overlay 11.9M 488.0K 11.5M 4% /
root@OpenWrt:/#