Kirkwood devices are limited by EA3500/EA4500 kernel size. How to increase it?

The external storage/USB booting is no longer supported for all the Kirkwood devices, as external storage code was moved from kernel to modules on the master branch in June, 2020, because their kernel size hit the limit:

  • EA3500: 2624k
  • EA4500: 2688k

They are the smallest 2 devices in the Kirkwood system, but eliminate the big possibility to GBs and TBs for all. It's not fair. :sob:

Ironically, they have quite bit of space, 64/128 MB in total:

root@EA3500:~# cat /proc/mtd
dev:    size     in KB  name
mtd0: 00080000    512   "u-boot"
mtd1: 00004000     16   "u_env"
mtd2: 00004000     16   "s_env"
mtd3: 00290000   2624   "kernel1"
mtd4: 01170000  17856   "rootfs1"
mtd5: 00290000   2624   "kernel2"
mtd6: 01170000  17856   "ubi"
mtd7: 01600000  22528   "syscfg"
mtd8: 00178000   1504   "unused"
root@EA4500:~# cat /proc/mtd
dev:    size     in KB  name
mtd0: 00080000    512   "u-boot"
mtd1: 00020000    128   "u_env"
mtd2: 00020000    128   "s_env"
mtd3: 002a0000   2688   "kernel1"
mtd4: 01760000  23936   "rootfs1"
mtd5: 002a0000   2688   "kernel2"
mtd6: 01760000  23936   "rootfs2"
mtd7: 04a00000  75776   "syscfg"
mtd8: 00140000   1280   "unused"

How to increase the kernel size for EA3500/EA4500? A couple options:

  1. Repartition and install OpenWrt over mtd3 to mtd8
  2. Over mtd5 to mtd8, leaving stock firmware alone

editing partitions is pretty simple

edit the DTS file
make your own build
and if you think it needs to be like this for everyone you can make a pull request

the "reg" property is what you change
syntax is <start length>
whenever you change one value you have to do some math for the others
making sure the partitions are not overlapping
(when you make kernel larger, obviously make rootfs smaller)

partitions here should only be changed by multiples of 64k
(don't touch the last 4 zeros of each value)

here is DTS of EA3500 for example
partitions at line 145

Thank you, Michael @mpratt14 , for the helpful pointer.

It seems that your idea (the 3rd option) is much simpler and less risky to implement. There are a lot of unknown implications for options 1 and 2.

  1. Repartition and install OpenWrt over mtd3 to mtd8
  2. Over mtd5 to mtd8, leaving stock firmware alone
  3. Make kernel (mtd3/5) larger and make rootfs (mtd4/6) smaller

If increasing the kernel size to 3072 KB, is it right that no u-boot variable changes will be needed? The mtdparts variable is ignored for EA3500/EA4500, too?

root@EA3500:~# fw_printenv 
bootdelay=0
baudrate=115200
loads_echo=0
ipaddr=192.168.1.10
serverip=192.168.1.254
rootpath=/mnt/ARM_FS
netmask=255.255.255.0
run_diag=yes
stdin=serial
stdout=serial
stderr=serial
console=console=ttyS0,115200
badcount=0
bootbadcount=0
uenvbadcount=0
senvbadcount=0
buffbadcount=0
fs_bootargs=unused
mtdparts=mtdparts=nand_mtd:512k(uboot)ro,16k@512k(u_env),16k@528k(s_env),20m@2m(kernel),20m@2m(rootfs)fs,20m@22m(alt_kernel),20m@22m(alt_rootfs)fs,22m@42m(syscfg)
mfg_mtdparts=mtdparts=nand_mtd:512k(uboot)ro,16k@512k(u_env),16k@528k(s_env),20m@2m(kernel),20m@2m(rootfs)fs,20m@22m(alt_kernel),20m@22m(alt_rootfs)fs,20m@42m(mfg_kernel),20m@42m(mfg_rootfs)fs,2m@62m(syscfg)
mainlineLinux=no
enaMonExt=no
enaCpuStream=no
enaWrAllo=no
pexMode=RC
disL2Cache=no
setL2CacheWT=yes
disL2Prefetch=yes
enaICPref=yes
enaDCPref=yes
sata_dma_mode=yes
ethprime=egiga0
netbsd_en=no
vxworks_en=no
bootargs_root=root=/dev/nfs rw
fs_bootargs_root=root=/dev/mtdblock4 ro rootfstype=jffs2
alt_fs_bootargs_root=root=/dev/mtdblock6 ro rootfstype=jffs2
mfg_fs_bootargs_root=root=/dev/mtdblock8 ro rootfstype=jffs2
usb_fs_bootargs_root=root=/dev/sda1 rw rootfstype=ext2
bootargs_end=:::DB88FXX81:eth0:none
image_name=uImage
nfsboot=tftp 0x2000000 uImage; setenv bootargs $(console) $(mfg_mtdparts) $(bootargs_root) nfsroot=$(serverip):$(rootpath) ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x2000000;
mfgboot=nand read.e 0x2000000 0x2a00000 0x300000; setenv bootargs $(console) $(mfg_mtdparts) $(mfg_fs_bootargs_root) serial_number=$(sn) uuid=$(uuid) hw_version=$(hw) device_mac=$(mac) factory_date=$(date) wps_pin=$(wps); bootm 0x2000000;
usbboot=usb start;ext2load usb 0:1 2000000 /uImage; setenv bootargs $(console) $(mtdparts) $(usb_fs_bootargs_root) rootdelay=10; bootm 0x2000000;
standalone=fsload 0x2000000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvPhoneConfig); bootm 0x2000000;
lcd0_enable=0
lcd0_params=640x480-16@60
disaMvPnp=no
ethmtu=1500
eth1mtu=1500
mvPhoneConfig=mv_phone_config=dev[0]:fxs,dev[1]:fxo
mvNetConfig=mv_net_config=(00:11:11:11:11:11,0:1:2:3),mtu=1500
usb0Mode=host
yuk_ethaddr=00:00:00:11:11:11
nandEcc=1bit
netretry=no
rcvrip=169.254.100.100
loadaddr=0x02000000
autoload=no
image_multi=yes
enaAutoRecovery=yes
mtdparts_version=2
envsaved=yes
pcieTune=no
pcieTune1=no
ethact=egiga0
layout=ver.0.0.7
model=EA3500
hw=RGWM-C5_0GA
date=2014/10/29
auto_recovery=yes
nandboot=run openwrt_usb_boot; nand read.e 0x2000000 0x200000 0x300000; setenv bootargs $(console) $(mtdparts) $(fs_bootargs_root) serial_number=$(sn) uuid=$(uuid) hw_version=$(hw) device_mac=$(mac) factory_date=$(date) wps_pin=$(wps); bootm 0x2000000;
altnandboot=run openwrt_usb_boot; nand read.e 0x2000000 0x1600000 0x300000; setenv bootargs $(console) $(mtdparts) $(alt_fs_bootargs_root) serial_number=$(sn) uuid=$(uuid) hw_version=$(hw) device_mac=$(mac) factory_date=$(date) wps_pin=$(wps); bootm 0x2000000;
openwrt_usb_boot=usb start; mw ${loadaddr} 0 8; ext2load usb 0:1 ${loadaddr} /boot/kernel; setenv bootargs ${console} ${mtdparts} ${usb_fs_bootargs_root} rootdelay=10; bootm ${loadaddr}; usb stop
boot_part_ready=3
boot_part=1
bootcmd=run nandboot

Although the reward (utilization of space on the 2 devices) is smaller, it will restore the booting capability form external storage. That can gain huge space.

By the way, what's in the partition mtd7 syscfg and what is it used for? I don't know how to open it for an inspection.

this is what repartitioning is...I'm not sure what you mean with "option 1"

keep in mind that if you do a sysupgrade, then it will install to the other set of kernel + rootfs
probably you have to follow factory install directions again to install to the same set

1 Like

Just a note that with 5.10.x a couple of mvebu targets are > 3M.

Option 3 doesn't quite work, as the new layout (bigger kernel smaller rootfs) trashes the stock firmware's rootfs. Not sure how to mandate on which set of kernel+rootfs OpenWrt resides in the stock flashing process and how to make the partition table dynamic in OpenWrt.

@mpratt14 , I'm trying Option 1, which combines partitions mtd3 thru mtd7 and allocates 3 MB to kernel and the rest to rootfs. I keep unused, a padding after s_env before kernel. Of course, there is lot of space to increase the kernel size to 4~8 MB.

[    1.225154] 0x000000000000-0x000000080000 : "u-boot"
[    1.230985] 0x000000080000-0x000000084000 : "u_env"
[    1.236670] 0x000000084000-0x000000088000 : "s_env"
[    1.242286] 0x000000200000-0x000000500000 : "kernel"
[    1.248146] 0x000000500000-0x000004000000 : "ubi"
[    1.255746] 0x000000088000-0x000000200000 : "unused"

root@EA3500:/# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00080000 00004000 "u-boot"
mtd1: 00004000 00004000 "u_env"
mtd2: 00004000 00004000 "s_env"
mtd3: 00300000 00004000 "kernel"
mtd4: 03b00000 00004000 "ubi"
mtd5: 00178000 00004000 "unused"
root@EA3500:/# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 2816      2816         0 100% /rom
tmpfs                    28092        60     28032   0% /tmp
/dev/ubi0_1              40092        40     37488   0% /overlay
overlayfs:/overlay       40092        40     37488   0% /
tmpfs                      512         0       512   0% /dev

Flashing OpenWrt will be a two-step process:

  1. Flash OpenWrt 19.07.x version of factory.bin in the stock Web interface. Set U-boot variables so that the new version of OpenWrt can be booted up from a USB drive. Alternatively, boot the new uImage in the console, with a serial cable.
  2. sysupgrade sysupgrade.bin to the single set of kernel+rootfs.

Any other implications? I wonder why partition overlay (39 MB) is much smaller than rootfs (59 MB), given /rom is only 2.75 MB?

only way to trash the other kernel / rootfs set is bad math or you flashed over it

I probably did both over the course of trial by error and testing :blush:.

Since other users also prefer bigger space (better nand utilization) on EA3500/EA4500, I will put together a PR for the 21.02 release.

By the way, I figure out how to open the stock syscfig partition:

root@EA3500:~# mount -t jffs2 /dev/mtdblock7 /mnt
root@EA3500:~# ls /mnt
detected_hosts_history  ewps                    license
esm                     files-to-keep.conf      syscfg
events                  ipa                     syspwl.lst

It's mounted/used by the stock firmware.

I've submitted a PR. Appreciate you all's review and comments.