Linux on a Routerboard from Scratch
From ME2000
This is an attempt to build a linux distro from scratch for the Routerboard 532, without using any of the pre-formatted images from mikrotik. All we'll use is a bit of fdisk magic for the compact flash card, build the kernel, build the rootfs, embed the rootfs in the kernel, slap it onto the first partition on the CF and boot it.
After that, we'll look at how to create a second partition on the CF as an e2fs filesystem, so we can save changes in the config files to make things persist across reboots.
Contents |
Prepping the Compact Flash card
All we really need on the compact flash card initially is a type 27 partition (unknown to linux, but that's what routerboot wants) big enough to hold the kernel and it's embedded rootfs. I've picked 8 megs. depending on how much functionality you want in your distribution, you might want to size it accordingly.
What you need for this is a linux box with some way of talking to a CF card. I happen to have a PCMCIA to CF adapter, and my linux kernel on the laptop sees this as /dev/hdc. I think it's the PCMCIA-IDE driver that does this.
The following fdisk session shows the partition being created and the type 27 being assigned.
# fdisk /dev/hdc Command (m for help): p Disk /dev/hdc: 8 heads, 32 sectors, 991 cylinders Units = cylinders of 256 * 512 bytes Device Boot Start End Blocks Id System Command (m for help): n Command action e extended p primary partition (1-4) p Partition number (1-4): 1 First cylinder (1-991, default 1): Using default value 1 Last cylinder or +size or +sizeM or +sizeK (1-991, default 991): +8M Command (m for help): t Partition number (1-4): 1 Hex code (type L to list codes): 27 Changed system type of partition 1 to 27 (Unknown) Command (m for help): p Disk /dev/hdc: 8 heads, 32 sectors, 991 cylinders Units = cylinders of 256 * 512 bytes Device Boot Start End Blocks Id System /dev/hdc1 1 65 8304 27 Unknown Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks. #
That's it for the partitioning for now. Later we'll add the other partition for persistent storage.
The way routerboot loads is fairly straightforward. It loads up the first ELF image it finds in the first partition, so to write the kernel to the partition we just use
dd if=vmlinux of=/dev/hdc1
What's the vmlinux file? We'll do that over the next few sections.
Building the kernel
TBD
The Buildroot system
"Buildroot is a set of Makefiles and patches that makes it easy generate a cross-compilation toolchain and root filesystem for your target Linux system using the uClibc C library."
Firstly, you have to get the buildroot system. This can be done via subversion access to the source. In whatever directory you choose for your builds, run
svn co svn://uclibc.org/trunk/buildroot
This will check out the buildroot system into the 'buildroot' directory. If you dont have svn installed, or don't want to install it, you can get daily snapshots. Check the buildroot website. Once the checkout is complete, we can start building the system. cd into buildroot, and run 'make menuconfig'
Select 'mipsel' as the target architecture. WHen we're making, various questions will be asked about the architecture again, so just leave it at that for now. Select 2.4.31 for the kernel headers, because we'll be patching a 2.4.31 kernel for the routerboard. gcc 3.4.2 is fine. In the package selection, add in 'modutils' and 'wireless tools'. In the Target options, take out the ext2 root filesystem, we'll do that ourselves later. The ext2 build as part of build root didnt work at the time of writing. Once you save your configuration, then do 'make'.
make
Once the make is running, the uClibc config needs more info, so it asks us what Target we're building for. Select 'mips'. The processor architecture should be set to 'MIPS32'. Endianness should be set to 'Little Endian'. All the other questions, leave at the defaults, unless you know better. Once you've defaulted all the other questions, the real compilation starts. Depending on your build machine and your internet connection, this could take a while.
Once the compilation is complete, we end up with a buildroot/build_mipsel/root directory. This contains the root filesystem files. With a bit of massaging, we can create a rootfs.gz file from this, a gzipped filesystem, ready for use as the initial ram disk.
Create the following script in the build_mipsel directory.
#!/bin/bash dd if=/dev/zero of=rootfs bs=1k count=8192 /sbin/mke2fs -q -F -m 0 -i 1024 rootfs mkdir -p rootfsmnt sudo mount -t ext2 -o loop rootfs rootfsmnt cd root tar --exclude="*/lib*\.a" --exclude="*/man/*" --exclude="*/include/*" -cpf - * | sudo tar -C ../rootfsmnt -xf - cd .. du -sh rootfs sudo chown -h -R 0:0 rootfsmnt sudo umount rootfsmnt gzip -9 -c rootfs > rootfs.gz
What this does is create an 8meg file, and makes an ext2 filesystem. It then mounts it using the loop device so we can write into it. We tar the contents of the root directory into it, change the ownership of the files and unmout it. the final stage is to gzip it. Now we have our rootfs.gz file ready for embedding into the kernel.
Embedding rootfs in the kernel
echo root=/dev/ram0 rw gpio=16375 console=ttyS0,115200 >kernel.params mipsel-linux-uclibc-objcopy --add-section kernparm=kernel.params vmlinux mipsel-linux-uclibc-objcopy --add-section initrd=rootfs.gz vmlinux
then strip vmlinux.
mipsel-linux-strip vmlinux
Writing the kernel onto the CF
Copy the kernel (including the rootfs) onto the first partition on the CF.
dd if=vmlinux of=/dev/hdc1
And the fekking thing boots! the rootfs.gz was a gzipped image of the root filessystem I used previously on the /dev/cfa2 ext2 filesystem. Compressing it up and embedding it in the kernel, telling the kernel to use /dev/ram0 as a root, and it works. Sweet.
Adding madwifi to buildroot
One of the great things about the buildroot system is that you can add in packages into the build. For madwifi in particular, a patch needed to be developed so that it would use the right variables during complilation. Also, because it needs to check the kernel config, we need to add the following environemntal variable:
export KERNELPATH=/home/daveh/mips/kernel/linux
To make a new 'madwifi' option appear in the buildroot "make menuconfig" menu, add the following line to buildroot/package/Config.in, and keep it in in alphaberical order so it's easier to find when you 'make menuconfig'.
source "package/madwifi/Config.in"
Then, in the buildroot/package directory, make a 'madwifi' subdirectory. Copy in the contents of the following file - buildroot package files for madwifi. This contains the Config.in, madwifi.mk and madwifi.patch that will get the package, patch it to fix some 'strip' problems, and make the package.
The next time you make, you should end up with the madwifi modules and tools in the target root directory.
Persistent Storage
Now we'll add another partition on the CF for storing settings, etc.
fdisk /dev/hdc
and add a new partition of the default type (83). Then
mke2fs /dev/hdc2
This makes and ext2 partition that we can mount.
In the dev directory, we make a few more block devices.
sudo mknod cfa b 13 0 sudo mknod cfa1 b 13 1 sudo mknod cfa2 b 13 2 sudo mknod cfa3 b 13 3 sudo mknod cfa4 b 13 4
/dev/cfa2 will be our persistent storage partition, and we will mount it on /mnt. So add the following line to the etc/fstab file in the root filesystem.
/dev/cfa2 /mnt ext2 defaults 0 0
This will get picked up in the 'mount -a' at boot.
References
The above howto would not have been possible without the following invaluable resources.
Installation of Debian Sarge on Rouberboard 532
Secure Internet Appliance for Small Office / Home Office HOWTO

