Linux on a Routerboard from Scratch

From ME2000

Jump to: navigation, search

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

RB500 Linux SDK

Buildroot Homepage

Personal tools