JFFS2 (Journalling Flash File System version 2)
was specifically designed for use on flash memory devices
in embedded systems.
It is a log-structured file system which means that it is robust
against loss of power, crashes or other unorderly shutdowns of the system
("robust" means that data that is just being written when the
system goes down may be lost,
but the file system itself does not get corrupted
and the system can be rebootet without need for any kind
of file system check).
Some of the advantages of using JFFS2 as root file system in embedded systems
are:
- file system uses compression, thus making efficient use of flash memory
- log-structured file system, thus robust against unorderly shutdown
- flash sector wear-leveling
- writable flash file system
Disadvantages are:
- long mount times (especially older versions)
- slow when reading: files to be read get uncompressed on the fly
which eats CPU cycles and takes time
- slow when writing: files to be written get compressed,
which eats CPU cycles and takes time, but it may even take much
longer until data gets actually stored in flash if the file system
becomes full and blocks must be erased first or - even worse - if
garbage collection becomes necessary
- The garbage collector thread may run at any time,
consuming CPU cycles and blocking accesses to the file system.
Despite the aforementioned disadvantages,
systems using a JFFS2 based root file system are easy to build,
make efficient use of the available resources
and can run pretty reliably.
To create a JFFS2 based root file system please proceed as follows:
- Create a directory tree with the content of the target root filesystem.
We do this by unpacking our master tarball:
$ mkdir rootfs
$ cd rootfs
$ tar zxf /tmp/rootfs.tar.gz
- We can now create a
JFFS2
file system image using the
mkfs.jffs2
tool:
$ ROOTFS_DIR=rootfs # directory with root file system content
$ ROOTFS_EBSIZE=0x20000 # erase block size of flash memory
$ ROOTFS_ENDIAN=b # target system is big endian
$ ROOTFS_DEVICES=rootfs_devices.tab # device description file
$ ROOTFS_IMAGE=jffs2.img # generated file system image
$ mkfs.jffs2 -U \
-d ${ROOTFS_DIR} \
-D ${ROOTFS_DEVICES} \
-${ROOTFS_ENDIAN} \
-e ${ROOTFS_EBSIZE} \
-o ${ROOTFS_IMAGE}
mkfs.jffs2: skipping device_table entry '/dev': no parent directory!
Note: When you intend to write the
JFFS2
file system image to a NAND flash
device, you should also add the
"-n"
(or
"--no-cleanmarkers"
) option,
as cleanmarkers are not needed then.
When booting the Linux kernel prints the following
messages showing the default partition map
which is used for the flash memory
on the TQM8xxL boards:
TQM flash bank 0: Using static image partition definition
Creating 7 MTD partitions on "TQM8xxL0":
0x00000000-0x00040000 : "u-boot"
0x00040000-0x00100000 : "kernel"
0x00100000-0x00200000 : "user"
0x00200000-0x00400000 : "initrd"
0x00400000-0x00600000 : "cramfs"
0x00600000-0x00800000 : "jffs"
0x00400000-0x00800000 : "big_fs"
We use U-Boot to load and store the JFFS2 image into the last
partition and set up the Linux boot arguments to use this as
root device:
- Erase flash:
=> era 40400000 407FFFFF
................. done
Erased 35 sectors
- Download JFFS2 image:
=> tftp 100000 /tftpboot/TQM860L/jffs2.img
Using FEC ETHERNET device
TFTP from server 192.168.3.1; our IP address is 192.168.3.80
Filename '/tftpboot/TQM860L/jffs2.img'.
Load address: 0x100000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
########
done
Bytes transferred = 2033888 (1f08e0 hex)
- Copy image to flash:
=> cp.b 100000 40400000 ${filesize}
Copy to Flash... done
- set up boot arguments to use flash partition 6 as root device:
=> setenv mtd_args setenv bootargs root=/dev/mtdblock6 rw rootfstype=jffs2
=> printenv addip
addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1
=> setenv flash_mtd 'run mtd_args addip;bootm ${kernel_addr}'
=> run flash_mtd
Using FEC ETHERNET device
TFTP from server 192.168.3.1; our IP address is 192.168.3.80
Filename '/tftpboot/TQM860L/uImage'.
Load address: 0x200000
Loading: #################################################################
#################################################################
###########
done
Bytes transferred = 719233 (af981 hex)
## Booting image at 40040000 ...
Image Name: Linux-2.4.25
Created: 2005-06-12 16:32:24 UTC
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 782219 Bytes = 763.9 kB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
Linux version 2.4.25 (wd@xpert) (gcc version 3.3.3 (DENX ELDK 3.1.1 3.3.3-9)) #1 Sun Jun 12 18:32:18 MEST 2005
On node 0 totalpages: 4096
zone(0): 4096 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: root=/dev/mtdblock6 rw rootfstype=jffs2 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.
VFS: Mounted root (jffs2 filesystem).
Freeing unused kernel memory: 56k 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 ...
# mount
rootfs on / type rootfs (rw)
/dev/mtdblock6 on / type jffs2 (rw)
/proc on /proc type proc (rw)
# df /
Filesystem 1k-blocks Used Available Use% Mounted on
rootfs 4096 2372 1724 58% /