Hi,
Since the last few days I tried to get block-extroot and MMC/SD storage working together on my WRT54GL1.1.
Yesterday I managed to get it working and I thought "Man, it was really a big PITA".
So I'm posting this to help other people stucked into this nightmare of bugs and mystical howtos... (hey that's all the fun about openwrt )
By assembling bits from posts in the forum , howtos from the wiki and experimenting I finally got it to work.
Prereq. :
- A Linksys WRT54GL (mine was 1.1 but I am sure that others do fine) with the MMC/SD mod.
- A configured openwrt brcm-2.4 buildroot
- A SD card with one partition formatted with ext2 (you can do this directly on the router if you installed the necessary tools like fdisk and e2fsprogs. I did this on my desktop)
- A brain and at least one hand to type
I won't go explaining how to solder your storage to the motherboard as there are lots of (crystal clear) documentation on the web.
I won't explain the configuration of the buildroot , the provided doc is good and clear enough and if you have no experience in [s]compiling[/s] configuring something like a kernel you shouldn't be reading this.
One more thing, I tried to get this with the 2.6 build but mmc_over_gpio just crashed and reboot my router each time I wrote more than 16k on my sd card so it is 2.4 only. (sorry bleeding edge guys).
=========================================
[size=15]1 - Buildroot stuff[/size]
Okay so you have your brcm-2.4 tree ready and up-to-date with your usual working config, after a nice "make menuconfig" check these as compiled in (not modules) :
- Base system > block-extroot (block-mount should add itself auto) > Set settle time to 60s
- Base system > block-hotplug ( hotplug2 should add itself auto )
- Filesystems > kmod-fs-ext2 & kmod-nls-base
- Kernel modules > Other modules > kmod-broadcom-sdhc
I choosed ext2 (hence no journalling) to protect my sdcard from constant writings but you can choose any filesystem you want if you include the related modules in your config. Wear levelling is prone to lots of discussion and you should make your own idea on the question. By the way if you want journalling, you could save your card a bit by setting more time between journal updates on the sdcard with the commit=100 option... the system will write the journal every 100 seconds instead of every 5 seconds.
Next make a "files" directory at the root of your tree and put these files inside :
files/etc/config/fstab
config global automount
option from_fstab 1
option anon_mount 1
config mount
option target /overlay
option device /dev/sdcard/part1
option fstype ext2
option options rw,noatime
option enabled 1
option enabled_fsck 0
option is_rootfs 1
Here we're declaring the sdcard partition to be mounted on /overlay at boot, fs is ext2 the noatime is for avoiding frequent writes on the sdcard, we're enabling the mount, disabling fs checking, and finally declaring it as an available root fs.
I didn't add the sync option because it's slowing things down writing everything on the sdcard immediately but be careful : if you power off the router without syncing your data first it will be lost in damnation forever.
files/etc/sdcard.conf
partition=1
#mountpoint=/sdcard
cs=7
clk=3
din=2
dout=4
major=0
maxsec=32
rahead=2
dbg=0
Be careful to put your correct gpio pins number here. Notice the commented line, it's to avoid automounting on the sdcard dir at boot time.
files/etc/modules.d/33-sdhc
# May be required for rootfs
sdhc din=2 dout=4 clk=3 cs=7 mode=0
Be careful to put your correct gpio pins number here. Keep the comment line, init script will check this.
files/etc/init.d/fstab
#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org
# Copyright (C) 2010 Vertical Communications
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
START=20
do_mount() {
local cfg="$1"
config_mount_by_section "$cfg"
}
do_swapon() {
local cfg="$1"
config_swapon_by_section "$cfg"
}
do_unmount() {
local cfg="$1"
config_get target "$cfg" target
config_get_bool enabled "$cfg" "enabled" '1'
[ -n "$target" -a "$enabled" -gt 0 ] || return 0
umount $target
}
do_swapoff() {
local cfg="$1"
config_get device "$cfg" device
config_get_bool enabled "$cfg" "enabled" '1'
[ -n "$device" -a "$enabled" -gt 0 ] && type swapoff >/dev/null || return 0
swapoff $device
}
start() {
. /lib/functions/mount.sh
config_load fstab
mkdir -p /var/lock
lock /var/lock/fstab.lck
# echo '# WARNING: this is an auto generated file, please use uci to set defined filesystems' > /etc/fstab
lock -u /var/lock/fstab.lck
config_foreach do_mount mount
config_foreach do_swapon swap
}
stop() {
. /lib/functions/mount.sh
config_load fstab
config_foreach do_unmount mount
config_foreach do_swapoff swap
swapoff -a
}
Here I just commented the line beginning with "echo '# WARNING: this is a..." to prevent a bug from happening when creating the symlink to /tmp/fstab.( Well I guess as I didn't check this with the line, blindly following one of the howto ).
files/lib/functions/extmount.sh
#!/bin/sh
# Copyright 2010 Vertical Communications
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
determine_root_device() {
root_device="$(mount | grep ' / ' | cut -f1 -d\ | grep -v rootfs )"
}
set_jffs_mp() {
jffs="$(awk '/jffs2/ {print $2}' /proc/mounts)"
}
er_load_modules() {
mkdir -p /tmp/extroot_modules/modules.d
mkdir -p /tmp/extroot_modules/modules
ln -sf /etc/modules.d/* /tmp/overlay/etc/modules.d/* /tmp/extroot_modules/modules.d
ln -sf /lib/modules/*/* /tmp/overlay/lib/modules/*/* /tmp/extroot_modules/modules
local modules="$(grep -l '# May be required for rootfs' /tmp/extroot_modules/modules.d/*)"
cd /tmp/extroot_modules/modules && {
cat $modules | sed -e 's/^\([^#].*\)/insmod \.\/\1.o/'| sh 2>&- || :
}
rm -rf /tmp/extroot_modules
}
I modified one character in this script because it was only checking for 2.6 modules (*.ko) so I've made it checking for 2.4 modules (*.o) . It's at the third line beginning from the end ( cat $modules | ... ). Maybe this is a bug ...
files/lib/preinit/00_extroot.conf
extroot_settle_time="60"
Same as in .config, not sure if it's useful (or too much) but things are working for me like this.
This is telling the kernel to wait for a fs eligible for rootfs to mount.
files/lib/preinit/39_init_sd_card
#!/bin/sh
#
# Preinit script for sdhc card mod. Based on
# Init script for sdhc card mod - mmc, sd, sdhc support
# Script Version: 1.0
# OpenWRT Version: BACKFIRE 2.4 kernel
# Save state of led's in /proc/diag/led/ as shell variables.
save_led_state() {
for file in /proc/diag/led/*; do
local var=`basename ${file}`
local val=`cat ${file}`
eval "${var}=${val}"
done
}
# Restore saved led state. Default unknown led's to state "0".
restore_led_state() {
for file in /proc/diag/led/*; do
local var=`basename ${file}`
eval "echo \"\${$var:-0}\" > ${file}"
done
}
# Initialize the SD Card
init_sd_card()
{
SD_MODNAME="sdhc"
SD_MODARG=""
SD_CONFIG="/etc/sdcard.conf"
# If no config file is found then no need to go any further
if [ ! -r ${SD_CONFIG} ]; then
echo "sdcard - config not found: skipping"
return
fi
echo "sdcard - found config at ${SD_CONFIG}"
. ${SD_CONFIG}
# We can compute the GPIO pin values supplied in the config file
let mask="(1<<$cs)|(1<<$clk)|(1<<$din)|(1<<$dout)"
# Error if gpio values not set.
if [ "$mask" -eq "1" ]; then
echo "sdcard - Gpio pins not set: skipping"
return
fi
echo "sdcard - using cs=$cs clk=$clk din=$din dout=$dout"
echo "sdcard - computed mask $mask"
# If the dbg value is > 0, arrange to load the debug enabled module instead.
[ ${dbg:-0} -eq 0 ] || SD_MODNAME="${SD_MODNAME}d"
# Do nothing if the module is already loaded!
if [ -d "/proc/sdcard" ]; then
echo "sdcard - Already started..."
return
fi
echo "sdcard - setting gpiomask"
# Set the diag module gpio mask to disable it from using our GPIO pins
# It buggers up the led state, so we save, then restore it afterwards
save_led_state
echo "$mask" > /proc/diag/gpiomask
restore_led_state
# Build module arguments from values in config file.
# Don't provide the dbg module argument if set to 0
for arg in clk din dout cs major maxsec rahead dbg gpio_input gpio_output gpio_enable gpio_control; do
[ ${arg} == "dbg" ] && [ ${dbg:-0} -eq 0 ] && continue
eval "z=\${${arg}:-z}"
if [ "$z" != "z" ]; then
SD_MODARG="${SD_MODARG} ${arg}=${z}"
fi
done
echo "sdcard - inserting module $SD_MODNAME $SD_MODARG"
# Insert the kernel module passing appropriate arguments
insmod $SD_MODNAME $SD_MODARG
if [ "$?" -gt "0" ] ; then
echo "sdcard - Card not present or failed to initialize"
echo "0x0000" > /proc/diag/gpiomask
restore_led_state
return;
fi
echo "sdcard - Card detected and initialized"
}
boot_hook_add preinit_mount_root init_sd_card
Props to Mr_Smoke for the script from this post : http://forum.openwrt.org/viewtopic.php? … 65#p108765
It enables the sdcard and diag leds in a correct state to get it recognized before pivot_root does its magic.
[size=15]2 - Get it all together[/size]
Now you're ready to compile assuming you got your stuff configured too into .config.
Type
make -j<your number of cpu +1> V=99
and go make some coffee.
Returning with your cup, things should be done and you'll find a nice "openwrt-brcm-2.4-squashfs.trx" in the bin/brcm-2.4 directory. Flash it to the router, I prefer this method :
user@host # scp openwrt-brcm-2.4-squashfs.trx root@xxx.xxx.xxx.xxx:/tmp
user@host # slogin root@xxx.xxx.xxx.xxx
root@Openwrt # mtd -r /tmp/openwrt-brcm-2.4-squashfs.trx linux
The box should reboot itself, wait for it, telnet it to assign a passwd, disconnect and reconnect with ssh.
On the first boot you will see a /dev/mtdblock/# mounted on /rom/overlay and the sdcard on /overlay.
Reboot the router.
Slogin it and check your mounts , if everything worked all right you should see :
root@OpenWrt # mount
rootfs on / type rootfs (rw)
/dev/root on /rom type squashfs (ro)
none on /dev type devfs (rw)
none on /proc type proc (rw)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw)
/dev/sdcard/part1 on /overlay type ext2 (rw,noatime)
mini_fo:/overlay on / type mini_fo (rw)
root@OpenWrt # df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 1.3M 1.3M 0 100% /rom
tmpfs 7.0M 1016.0K 6.0M 14% /tmp
/dev/sdcard/part1 3.6G 8.4M 3.4G 0% /overlay
mini_fo:/overlay 1.3M 1.3M 0 100% /
et voilà , sdcard is mounted as an overlay on the root filesystem. No double mounts sh*t, persistent and working with SDHC.
This was done with Backfire (10.03, r23346) buildroot.
You will maybe find some things too much redundant or useless, I have not experimented every possible combination so there may be some things you can remove/enhance. I'm open to any suggestions. And if you find my english bad I'm sorry but it's not my primary language.
Thanks to all the people I read to make this working
[size=15]Sources :[/size]
http://wiki.openwrt.org/doc/howto/extroot
http://forum.openwrt.org/viewtopic.php?pid=107264
http://dev.openwrt.org/ticket/7768
http://wiki.openwrt.org/inbox/howto/con … ge-overlay
http://wiki.openwrt.org/doc/howto/buildroot
(Last edited by ektat on 15 Oct 2010, 00:08)