Skip to main content.
Navigation:
DENX
>
DULG
>
RootFileSystemInAReadOnlyFile
Translations:
Edit
|
Attach
|
Raw
|
Ref-By
|
Printable
|
More
DULG
Sections of this site:
DENX Home
|
DULG
|
ELDK-5
|
Know
|
Training
|
U-Boot
|
U-Bootdoc
Topics
DULG Home
BoardSelect
Manual
FAQ
Application Notes
Changes
Index
List of pages in DULG
Search
%SECTION0{name=RootFileSystemInAReadOnlyFile}% Root File System in a Read-Only File in a FAT File System This is a more complicated example that shows that - depending on project requirements - many other alternatives for chosing a root file system for your embedded system exist. The scenario is as follows: on your embedded device you use a cheap and popular storage medium like <nop>CompactFlash, MMC or SD cards or USB memory sticks to store both the Linux kernel and your root file system. You want to distribute software updates over the internet: your customers can download the file from your web site, or you sent the images by email. Your customers may use any flash card or memory stick they happen to find, so you have no information about brand or size of the storage device. Unfortunately most of your customers use Windows systems. And they don't want to be bothered with long instructions how to create special partitions on the storage device or how to write binary images or things like that. A simple "copy file" operation is nearly exhausting their capabilities. What to do? Well, if copying a file is all your customers can do we should not ask for more. Storage devices like <nop>CompactFlash cards etc. typically come with a single partition on it, which holds a =FAT= or =VFAT= file system. This cannot be used as a Linux root file system directly, so we have to use some trickery. Here is one possible solution: Your software distribution consistes of two files: The first file is the Linux kernel with a minimal ramdisk image attached (using the multi-file image format for U-Boot); U-Boot can load and boot such files from a FAT or VFAT file system. The second file is your root file system. For convenience and speed we use again an image of an =ext2= file system. When Linux boots, it will initially use the attached ramdisk as root file system. The programs in this ramdisk will mount the FAT or VFAT file system - read-only. Then we can use a loop device (see _losetup(8)_) to associate the root file system image with a block device which can be used as a mount point. And finally we use _pivot_root(8)_ to change the root file system to our image on the CF card. This sounds not so complicated, and actually it is quite simple once you understand what needs to be done. Here is a more detailed description: 1 The root file system image is easy: as mantioned before, we will use an =ext2= file system image, and to avoid wearing the flash storage device we will use it in read-only mode - we did a read-only =ext2= root file system image before, and here we can just re-use the existing image file. 1 The initial ramdisk image that performs the _pivot_root_ step must be created from scratch, but we already know how to create ramdisk images, so we just have to figure out what to put in it. %BR% %BR% The most important tool here is =nash=, a script interpreter that was specifically designed for such purposes (see _nash(8)_). We don't need any additional tools, and if we use static linking, then the =nash= binary plus a small script to control it is all we need for our initial ramdisk. %BR% %BR% To be precise, we need a couple of (empty) directories (=bin=, =dev=, =etc=, =lib=, =loopfs=, =mnt=, =proc=, and =sysroot=), the =bin/nash= binary, the =linuxrc= script and a symbolic link =sbin= pointing to =bin=: <verbatim> drwxr-xr-x 2 wd users 4096 Apr 13 01:11 bin -rwxr-xr-x 1 wd users 469512 Apr 11 22:47 bin/nash drwxr-xr-x 2 wd users 4096 Apr 12 00:04 dev drwxr-xr-x 2 wd users 4096 Apr 12 00:04 etc drwxr-xr-x 2 wd users 4096 Apr 12 00:04 lib -rwxr-xr-x 1 wd users 511 Apr 13 01:28 linuxrc drwxr-xr-x 2 wd users 4096 Apr 12 00:04 loopfs drwxr-xr-x 2 wd users 4096 Apr 12 00:09 mnt drwxr-xr-x 2 wd users 4096 Apr 12 00:04 proc lrwxrwxrwx 1 wd users 3 Jun 12 18:54 sbin -> bin drwxr-xr-x 2 wd users 4096 Apr 12 00:04 sysroot </verbatim> 1 We also need only a minimal device table for creating the initial ramdisk: <verbatim> #<name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count> /dev d 755 0 0 - - - - - /dev/console c 640 0 0 5 1 - - - /dev/hda b 640 0 0 3 0 - - - /dev/hda b 640 0 0 3 1 1 1 8 /dev/loop b 640 0 0 7 0 0 1 4 /dev/null c 640 0 0 1 3 - - - /dev/ram b 640 0 0 1 0 0 1 2 /dev/ram b 640 0 0 1 1 - - - /dev/tty c 640 0 0 4 0 0 1 4 /dev/tty c 640 0 0 5 0 - - - /dev/ttyS c 640 0 0 4 64 0 1 4 /dev/zero c 640 0 0 1 5 - - - </verbatim> 1 To create the initial ramdisk we perform the usual steps: <verbatim> $ INITRD_DIR=initrd $ INITRD_SIZE=490 $ INITRD_FREE=0 $ INITRD_INODES=54 $ INITRD_DEVICES=initrd_devices.tab $ INITRD_IMAGE=initrd.img $ genext2fs -U \ -d ${INITRD_DIR} \ -D ${INITRD_DEVICES} \ -b ${INITRD_SIZE} \ -r ${INITRD_FREE} \ -i ${INITRD_INODES} \ ${INITRD_IMAGE} $ gzip -v9 ${INITRD_IMAGE} </verbatim> The result is a really small (233 kB) compressed ramdisk image. 1 Assuming you already have your Linux kernel image, you can now use =mkimage= to build an U-Boot multi-file image that combines the Linux kernel and the initial ramdisk: <verbatim> $ LINUX_KERNEL=linuxppc_2_4_devel/arch/ppc/boot/images/vmlinux.gz $ mkimage -A ppc -O Linux -T multi -C gzip \ > -n 'Linux with Pivot Root Helper' \ > -d ${LINUX_KERNEL}:${INITRD_IMAGE}.gz linux.img Image Name: Linux with Pivot Root Helper Created: Mon Jun 13 01:48:11 2005 Image Type: PowerPC Linux Multi-File Image (gzip compressed) Data Size: 1020665 Bytes = 996.74 kB = 0.97 MB Load Address: 0x00000000 Entry Point: 0x00000000 Contents: Image 0: 782219 Bytes = 763 kB = 0 MB Image 1: 238433 Bytes = 232 kB = 0 MB </verbatim> The newly created file =linux.img= is the second image we have to copy to the CF card. %BR% %BR% We are done. But wait - one essential part was not mentioned yet: the =linuxrc= script in our initial ramdisk image which contains all the magic. This script is quite simple: <verbatim> #!/bin/nash echo Mounting /proc filesystem mount -t proc /proc /proc echo Creating block devices mkdevices /dev echo Creating root device mkrootdev /dev/root echo 0x0100 > /proc/sys/kernel/real-root-dev echo Mounting flash card mount -o noatime -t vfat /dev/hda1 /mnt echo losetup for filesystem image losetup /dev/loop0 /mnt/rootfs.img echo Mounting root filesystem image mount -o defaults --ro -t ext2 /dev/loop0 /sysroot echo Running pivot_root pivot_root /sysroot /sysroot/initrd umount /initrd/proc </verbatim> Let's go though it step by step: * The first line says that it's a script file for the =/bin/nash= interpreter. %BR% %X% Note: even if this file looks like a shell script it is NOT interpreted by a shell, but by the =nash= interpreter. For a complete list of available =nash= commands and their syntax please refer to the manual page, _nash(8)_. * The first action is to mount the =/proc= pseudo file system which is needed to find out some required information. * Then we create block device entries for all partitions listed in =/proc/partitions= (=mkdevices= command). * In the next step a block device for our new root file system is created (=mkrootdev= command). * Then we mount the CF card. We assume that there is only a single partition on it (=/dev/hda1=) which is of type =VFAT= (which also will work with =FAT= file systems). These assumptions work fine with basicly all memory devices used under Windows. * We further assume that the file name of the root file system image on the CF card is ="rootfs.img"= - this file now gets mounted using a loop device (=losetup= and =mount= commands). * Our file system image, is now mounted on the =/sysroot= directory. In the last step we use =pivot_root= to make this the new root file system. * As a final cleanup we unmount the =/proc= file system which is not needed any more. There is one tiny flaw in this method: since we mount the CF card on a directory in the ramdisk to be able to access to root file system image. This means that we cannot unmount the CF card, which in turn prevents us from freeing the space for the inital ramdisk. The consequence is that you permanently lose approx. 450 kB of RAM for the ramdisk. [We could of course re-use this ramdisk space for temporary data, but such optimization is beyond the scope of this document.] And how does this work on our target? 1 First we copy the two images to the CF card; we do this on the target under Linux: <verbatim> bash-2.05b# fdisk -l /dev/hda Disk /dev/hda: 256 MB, 256376832 bytes 16 heads, 32 sectors/track, 978 cylinders Units = cylinders of 512 * 512 = 262144 bytes Device Boot Start End Blocks Id System /dev/hda1 * 1 978 250352 6 FAT16 bash-2.05b# mkfs.vfat /dev/hda1 mkfs.vfat 2.8 (28 Feb 2001) bash-2.05b# mount -t vfat /dev/hda1 /mnt bash-2.05b# cp -v linux.img rootfs.img /mnt/ `linux.img' -> `/mnt/linux.img' `rootfs.img' -> `/mnt/rootfs.img' bash-2.05b# ls -l /mnt total 4700 -rwxr--r-- 1 root root 1020729 Jun 14 05:36 linux.img -rwxr--r-- 1 root root 3788800 Jun 14 05:36 rootfs.img bash-2.05b# umount /mnt </verbatim> 1 We now prepare U-Boot to load the ="uMulti"= file (combined Linux kernel and initial ramdisk) from the CF card and boot it: <verbatim> => setenv fat_args setenv bootargs rw => setenv fat_boot 'run fat_args addip;fatload ide 0:1 200000 linux.img;bootm' => setenv bootcmd run fat_boot </verbatim> 1 And finally we try it out: <verbatim> U-Boot 1.1.3 (Jun 13 2005 - 02:24:00) CPU: XPC86xxxZPnnD4 at 50 MHz: 4 kB I-Cache 4 kB D-Cache FEC present Board: TQM860LDB0A3-T50.202 DRAM: 16 MB FLASH: 8 MB In: serial Out: serial Err: serial Net: SCC ETHERNET, FEC ETHERNET [PRIME] PCMCIA: 3.3V card found: Transcend 256M Fixed Disk Card IDE interface [silicon] [unique] [single] [sleep] [standby] [idle] [low power] Bus 0: OK Device 0: Model: Transcend 256M Firm: 1.1 Ser#: SSSC256M04Z27A25906T Type: Removable Hard Disk Capacity: 244.5 MB = 0.2 GB (500736 x 512) Type "run flash_nfs" to mount root filesystem over NFS Hit any key to stop autoboot: 0 reading linux.img 1025657 bytes read ## Booting image at 00200000 ... Image Name: Linux with Pivot Root Helper Created: 2005-06-13 0:32:41 UTC Image Type: PowerPC Linux Multi-File Image (gzip compressed) Data Size: 1025593 Bytes = 1001.6 kB Load Address: 00000000 Entry Point: 00000000 Contents: Image 0: 787146 Bytes = 768.7 kB Image 1: 238433 Bytes = 232.8 kB Verifying Checksum ... OK Uncompressing Multi-File Image ... OK Loading Ramdisk to 00f3d000, end 00f77361 ... OK Linux version 2.4.25 (wd@xpert) (gcc version 3.3.3 (DENX ELDK 3.1.1 3.3.3-9)) #1 Mon Jun 13 02:32:10 MEST 2005 On node 0 totalpages: 4096 zone(0): 4096 pages. zone(1): 0 pages. zone(2): 0 pages. Kernel command line: rw ip=192.168.3.80:192.168.3.1::255.255.255.0:tqm860l:eth1:off panic=1 Decrementer Frequency = 187500000/60 Calibrating delay loop... 49.86 BogoMIPS ... NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. RAMDISK: Compressed image found at block 0 Freeing initrd memory: 232k freed VFS: Mounted root (ext2 filesystem). Red Hat nash version 4.1.18 starting Mounting /proc filesystem Creating block devices Creating root device Mounting flash card hda: hda1 hda: hda1 losetup for filesystem image Mounting root filesystem image Running pivot_root Freeing unused kernel memory: 60k init BusyBox v0.60.5 (2005.03.07-06:54+0000) Built-in shell (msh) Enter 'help' for a list of built-in commands. # ### Application running ... </verbatim> %IF{ "%ARCH%" eq "powerpc"}% ---++ Kernel with a Flattened Device Tree Blob When booting an =arch/powerpc= kernel that requires a flattened device tree blob, the above procedure must be slightly modified. Namely, the multi-image file has to include the blob as the thrid image. Here's an example of the =mkimage= command to create it: <pre> mkimage -A ppc -O Linux -T multi -C gzip \ -n 'Kernel + Pivot Root Helper initrd + FDT blob' \ -d vmlinux.bin.gz:ramdisk_image.gz:%BOARD%.dtb kernel+initrd+blob.img Image Name: Kernel + Pivot Root Helper initrd + FDT blob Created: Fri Sep 14 18:24:29 2007 Image Type: PowerPC Linux Multi-File Image (gzip compressed) Data Size: 2894576 Bytes = 2826.73 kB = 2.76 MB Load Address: 0x00000000 Entry Point: 0x00000000 Contents: Image 0: 1351205 Bytes = 1319 kB = 1 MB Image 1: 1531063 Bytes = 1495 kB = 1 MB Image 2: 12288 Bytes = 12 kB = 0 MB </pre> The newly created file =kernel+initrd+blob.img= needs to be copied to the CF card. %ENDIF%
9.5.5. Root File System on a Flash Card
1. Abstract
9.6. Root File System Selection
Prev
Home
Next