Mounting JFFS2 Images on a Linux PC
It is possible to mount a binary JFFS2 image on a Linux PC without a flash device. This can be useful for examining the contents of the image, making required changes, and creating a new image in any format. When a JFFS2 image is copied directly from a JFFS2 flash partition, the resulting image is the size of the source partition, regardless of how much space is actually used for storage. Mounting the filesystem and using the mkfs.jffs2
utility to create a new image will result in a JFFS2 image without blank nodes. This can also be used to create multiple images for flashes with different characteristics, such as erase block sizes. This page describes two different methods of mounting JFFS2 images on a Linux PC.
This procedure requires that the following kernel modules are available or built-in to the kernel on the development machine: mtdram, mtdblock, jffs2, block2mtd, and loop.
One method of mounting JFFS2 images uses the mtdram module to emulate an MTD device using system RAM. This works well for JFFS2 images that are less than approximately 32 MB but will not work for larger images since it requires allocating a large amount of system RAM. The basic steps of this process are as follows:
- Load mtdram and mtdblock modules.
- Use the dd command to copy the JFFS2 image to
/dev/mtdblock0
. - Mount
/dev/mtdblock0
as aJFFS2 filesytem
.
In order to simplify this process, EMAC has created a script which takes the JFFS2 image, mount point, and the erase block size of the image as parameters. The default erase block size for this script is 128 KiB, which is the correct value for most NOR flashes used on EMAC products and some NAND flashes. The eraseblock size can be determined from the contents of /proc/mtd
from the system that the image was copied from or created for. For example, if the value of the "erasesize" parameter is 00040000
, the erase block size for the device is 256 KiB (0x40000 = 262144 bytes, 262144 / 1024 = 256 KiB). The jffs2_mount_mtdram.sh
script is shown below.
#!/bin/bash
## Script to mount jffs2 filesystem using mtd kernel modules.
## EMAC, Inc. 2009
if [[ $# -lt 2 ]]
then
echo "Usage: $0 FSNAME.JFFS2 MOUNTPOINT [ERASEBLOCK_SIZE]"
exit 1
fi
if [ "$(whoami)" != "root" ]
then
echo "$0 must be run as root!"
exit 1
fi
if [[ ! -e $1 ]]
then
echo "$1 does not exist"
exit 1
fi
if [[ ! -d $2 ]]
then
echo "$2 is not a valid mount point"
exit 1
fi
if [[ "$3" == "" ]]
then
esize="128"
else
esize="$3"
fi
# cleanup if necessary
umount /dev/mtdblock0 &>/dev/null
modprobe -r mtdram &>/dev/null
modprobe -r mtdblock &>/dev/null
modprobe mtdram total_size=32768 erase_size=$esize || exit 1
modprobe mtdblock || exit 1
dd if="$1" of=/dev/mtdblock0 || exit 1
mount -t jffs2 /dev/mtdblock0 $2 || exit 1
echo "Successfully mounted $1 on $2"
exit 0
To mount an image with 256 KiB erase block size named rootfs.jffs2
on /mnt/jffs2
using jffs2_mount_mtdram.sh
, run the script as shown below:
developer@ldc:~$ sudo ./jffs2_mount_mtdram.sh rootfs.jffs2 /mnt/jffs2 256
Once this has been done, the contents of the image should be accessible at /mnt/jffs2
.
Changes made to the mounted filesystem will not affect the original JFFS2 image.
A second method for mounting JFFS2 images utilizes a loop device. This method is appropriate for larger images that cannot be mounted successfully with the mtdram approach. The process requires the following steps:
- Load loop, block2mtd, and jffs2 modules
- Create a loop device
- Set the block2mtd parameters for the loop device
- Mount the JFFS2 image
EMAC has created a script to simplify this process that takes the JFFS2 image, mount point, and image erase block size as parameters. The default erase block size for this script is 128 KiB, which is the correct value for most NOR flashes used on EMAC products and some NAND flashes. See the description of determining the correct erase block size to use in the previous section. The jffs2_mount_loop.sh
script is shown below.
#!/bin/bash
## Script to mount jffs2 filesystem using mtd kernel modules.
## EMAC, Inc. 2011
if [[ $# -lt 2 ]]
then
echo "Usage: $0 FSNAME.JFFS2 MOUNTPOINT [ERASEBLOCK_SIZE]"
exit 1
fi
if [ "$(whoami)" != "root" ]
then
echo "$0 must be run as root!"
exit 1
fi
if [[ ! -e $1 ]]
then
echo "$1 does not exist"
exit 1
fi
if [[ ! -d $2 ]]
then
echo "$2 is not a valid mount point"
exit 1
fi
if [[ "$3" == "" ]]
then
esize="128"
else
esize="$3"
fi
# cleanup if necessary
umount /tmp/mtdblock0 &>/dev/null
umount $2 &>/dev/null
modprobe -r jffs2 &>/dev/null
modprobe -r block2mtd &>/dev/null
modprobe -r mtdblock &>/dev/null
sleep 0.25
losetup -d /dev/loop1 &>/dev/null
sleep 0.25
modprobe loop || exit 1
losetup /dev/loop1 "$1" || exit 1
modprobe block2mtd || exit 1
modprobe jffs2 || exit 1
if [[ ! -e /tmp/mtdblock0 ]]
then
mknod /tmp/mtdblock0 b 31 0 || exit 1
fi
echo "/dev/loop1,${esize}KiB" > /sys/module/block2mtd/parameters/block2mtd
mount -t jffs2 /tmp/mtdblock0 "$2" || exit 1
echo "Successfully mounted $1 on $2"
exit 0
Usage for this script is identical to the jffs2_mount_mtdram.sh
script discussed in the previous section.