8.3 CRAMFS

CRAMFS was written by Linus Torvalds as a filesystem with a bare minimum feature set. It is a very simple, and sometimes simplistic, compressed and read-only filesystem aimed at embedded systems. Apart from the characteristics summarized in Table 8-1, CRAMFS has the following limitations:

  • The maximum size a file can have is 16 MB.

  • There are no current (.) or parent (..) directory entries.

  • The UID field for files is 16 bits wide and the GID field is 8 bits wide. Normal filesystems usually support either 16- or 32-bit UIDs and GIDs. On CRAMFS, GIDs are truncated to the lower 8 bits. In other words, the maximum GID usable in a root filesystem built on CRAMFS is 255.[4]

    [4] See Chapter 5 in Running Linux for a discussion about UIDs and GIDs.

  • All file timestamps are set to epoch (00:00:00 GMT, January 1, 1970). The timestamps may be updated at runtime, but the updated values will last only as long as the inode is cached in memory. Once the file is reloaded, its timestamp will revert to epoch.

  • CRAMFS images can be read only by kernels using 4096-byte page sizes (The value of PAGE_CACHE_SIZE must be 4096).

  • All files, whether they are linked or not, have a link count[5] of 1. Even when multiple filesystem entries point to the same file, that file has a link count of only 1. This is fine for most operations, however, since no files can actually be deleted from CRAMFS.

    [5] As in other Unix systems, named links can be created toward files with most Linux filesystems. Typically, filesystems maintain a count of the number of links toward a file, and when this count reaches 0 the file is deleted.

The truncated GIDs are not problematic if your target's root filesystem does not contain a group with a GID above 255. If your target is a single-user system, you don't need to worry about this limitation. If your system must support a multiuser environment, make sure the GIDs of all files and directories are below 255. Otherwise, any GID above 255 will wrap around to a number below 255 and, possibly, create a security risk. If you absolutely need a filesystem that can support at least 16-bit GIDs, you may want to consider using a disk filesystem over a RAM disk. It provides compression on the storage media, like CRAMFS, and also allows read and write access, instead of read-only access in the case of CRAMFS.

In addition to CRAMFS's limitations, the tools provided for creating CRAMFS filesystem images used to be subject to the host's byte ordering. Hence, you needed to use a host that had the same byte ordering as your target to create a CRAMFS image. The only way to bypass this limitation was to follow the technique I describe in Section 8.2. In essence, you had to mount the target's root filesystem on NFS, create the CRAMFS image for the target on the NFS-mounted filesystem, and write the created CRAMFS image to flash. Though, at the time of this writing, this limitation still applies to the CRAMFS creation tools found in the kernel sources, there is a patch that can be applied to the latest version of the CRAMFS tools to obtain filesystem creation tools that are independent of the host's byte ordering. The latest CRAMFS tools package is found at http://sourceforge.net/projects/cramfs/, and the byte swapping patch is in the "Patches" section of the site.

If your system can function with CRAMFS's limitations, it is probably a serious candidate for your project. If you are interested in CRAMFS but chaff at its limitations, you may want to ask around for modified versions of CRAMFS. As the host byte ordering problem mentioned above shows, there are people who have modified CRAMFS to bypass some of its limitations. Some reports on the linuxppc-embedded mailing list mentioned in Chapter 3, for example, suggest that some people have modified CRAMFS to avoid the page size issues. Although such modifications are not part of the CRAMFS code found from the mainstream kernel sources, you may find them useful. Have a look at the "Patches" section of the site provided above for a list of commonly available CRAMFS patches.

To create a CRAMFS image of your root filesystem, you first need to create and install the CRAMFS tools, cramfsck and mkcramfs. Both of these utilities are part of the package distributed by the project site and are found in the kernel's sources in the scripts/cramfs directory. To build the utilities from the kernel's sources, move to the scripts/cramfs directory and issue the make command:

$ cd ${PRJROOT}/kernel/linux-2.4.18/scripts/cramfs
$ make

Now, copy the tools to an appropriate directory:

$ cp cramfsck mkcramfs ${PREFIX}/bin/

You can now create a CRAMFS image of your target's root filesystem:

$ cd ${PRJROOT}
$ mkcramfs rootfs/ images/cramfs.img      
  bin
  boot
  dev
  etc
  lib
  linuxrc
  proc
  sbin
  tmp
  usr
'bin':
  addgroup
...
'boot':
  boot.b
...
'sbin':
  chroot
Directory data: 6484 bytes
166.67% (+15 bytes)     addgroup
-31.46% (-2196 bytes)   allinone
-40.27% (-240 bytes)    arch
185.71% (+13 bytes)     ash
...
-49.60% (-3700 bytes)   wall
-49.54% (-695 bytes)    include
Everything: 3560 kilobytes
Super block: 76 bytes
CRC: f18594b6
warning: gids truncated to 8 bits.  (This may be a security concern.)

In this case, rootfs/ contains 7840 KB while the CRAMFS image's size is 3560 KB, a compression ratio of approximately 50%. This ratio is consistent with CRAMFS's typical yields.

With the filesystem image ready, we can now write it to our storage device:

$ su -m
Password:
# cat rootfs/cramfs.img > /dev/mtd4
# exit

Of course the commands above assume that the storage device is accessible on the host. If that is not the case, use an NFS-mounted root filesystem first, as I describe in Section 8.2. To verify the content of a CRAMFS filesystem, use the cramfsck utility built earlier.