An Introduction to Embedded Linux Development, Part 3
At the end of the second article in this series, which outlines a step-by-step process for embedded Linux development, we had the LBox up and running, ready to use for application development. On some occasions, however, the developer needs to modify the underlying system. Any Linux system can be considered to consist of three parts: the root filesystem, the kernel image and the bootloader (the BIOS plays this role in the desktop system). Typically, we leave the bootloader alone--at least we hope to--and modify the root filesystem, the kernel image or both.
With this need for modification in mind, Part 3 of this article series consists of four sections:
Memory organization and filesystem layout
Replacing the kernel and root filesystem
Replacing the JFFS2 filesystem
Replacing the bootloader
Some of these activities can be dangerous and may result in a non-functional system. Recovery from that state will be discussed in the fourth and final installment of this introductory sequence.
We continue to work with the SBC (single-board computer) we used in Parts 1 and 2 of this series, the LBox from Engineering Technologies Canada Ltd. Nevertheless, much of the material has broader applications and should be useful for a variety of target platforms.
To replace the root filesystem and/or kernel image intelligently, it is useful both to understand the boot-up process in a general way and to have a grasp of memory organization. Useful details can be obtained from the SBC vendor; if Linux is resident, the operating system itself can be a source of information. In particular, when connected to the LBox we found these Linux commands to be informative: dmesg, df, cat /proc/mtd, cat /proc/meminfo and cat /proc/mounts.
The memory and filesystem layout differ in their details, depending on the SBC. Using the aforementioned commands and information from the vendor, the following information emerges. Our LBox memory consists of 4MB of Flash memory and 8MB of SDRAM. At the start of the boot process, the RAM is not yet deployed and the Flash organization is as follows:
device is /dev/mtd0
space provided = 0x0000E000
location: 0x00000000 -> 0x0000E000
device is /dev/mtd1
space provided = 0x00002000
location: 0x0000E000 -> 0x00010000
Image (root filesystem and kernel image, both compressed)
device is /dev/mtd2
space provided = 0x00100000
location: 0x00010000 -> 0x00110000
JFSS2 (Journaling filesystem to be mounted during boot)
device is /dev/mtd3
space provided = 0x002F0000
location: 0x00110000 -> 0x00400000
At boot, the typical SBC with Linux resident has a bootloader that finds the compressed kernel image and root filesystem in Flash, decompresses them into RAM and transfers control to the decompressed kernel in RAM. The kernel then completes the initialization of the system.
The LBox provides a specific example of the foregoing. When it powers up, the bootloader, in Flash, begins executing. It decompresses the root filesystem and the kernel image and moves them into the 8MB of SDRAM. In addition, part of the SDRAM is used for the root filesystem, which is set up as a ROM filesystem. Then, a ramdisk, /dev/ram1, is mounted on /var. Finally, the JFFS2 filesystem, /dev/mtdblock3, is mounted on /etc/config. As a result, the root filesystem, originally a totally ROM filesystem, has been modified by the mount events to include read/write areas--a ramdisk and a JFFS2 area. Things to notice:
The ROM filesystem intrinsically is read-only and its contents will be reconstituted at the next boot sequence.
The ramdisk is volatile and its contents will be lost at power down.
The JFFS2 filesystem is on Flash and its contents will persist through power-down events, so that it emulates a hard drive.
The filesystem organization of a pristine system, after boot, looks like this:
root file system (romfs) in RAM, read-only
/dev/root mounted on /
size = 1113 kbytes
ramdisk (ext2 file system) in RAM, read/write
/dev/ram1 mounted on /var
size = 115 kbytes
emulated hard drive (JFFS2 filesystem) in Flash, read/write
/dev/mtdblock3 mounted on /etc/config
size = 3008 kbytes