First, when we talk about a ramdisk, we're usually talking about an image of an ext2 filesystem and not necessarily the ramdisk device driver. We often use the ramdisk device driver, copying in the ramdisk image, mounting the filesystem, etc., but we could also use the flash block device driver or the loopback driver. These instructions tell how to use the loopback device to access an ext2 image, in which case ramdisk is not really involved at all.
Given an uncompressed filesystem image, you can mount it either through a ramdisk device or through the loopback filesystem type. Via ramdisk:
bash# mkdir mnt bash# cat init-ramdisk-2-35 > /dev/ram1 bash# mount /dev/ram1 mnt |
Or via loopback:
bash# mount -o loop init-ramdisk-2-35 mnt |
In both of these cases, we omitted the '-t fstype' option from mount because it will read the superblock to determine the filesystem type. I've found that I often need to supply the type when mounting fat filesystems, but maybe that's just me.
Finally, we almost always compress the image before making copies of it, and we install the compressed filesystem image for the initial ramdisk, because the initrd driver knows how to recognize and unzip compressed filesystem images. We use the highest level of compression to minimize xmodem download times.
A small note: if you did some work (copied, moved, deleted files), the ramdisk will have some dirty blocks. Those blocks are not in use by the ext2 filesystem, but they still have the original file contents, and hence aren't that easy compressable as empty blocks (i.e. blocks only containing zeros). To get a smaller compressed image, you can copy the contents of the ramdisk to a clean ramdisk. Create a second ramdisk (or loopback device) and mount it. Suppose we have the original ramdisk mounted on /tmp/orig and the new one on /tmp/new, we just copy the contents:
cd /tmp/orig tar cf - . | ( cd /tmp/new ; tar xpf - ) |
Unmount the ramdisks, extract the new ramdisk, compress it, and you'll have a smaller compressed image with exactly the same contents.
Example 1. Modifying an existing ext2 filesystem image
bash# gunzip ramdisk-file.gz bash# mkdir temp bash# mount -o loop ramdisk-file temp bash# cd temp (Do what you need to do.) bash# cd .. bash# umount temp bash# gzip -9 ramdisk-file |
Example 2. Creating a new ext2 filesystem image
bash# dd if=/dev/zero of=init-ramdisk.img bs=1k count=8k bash# mke2fs -i 1024 -b 1024 -m 3 -F -v init-ramdisk.img bash# mkdir temp bash# mount -o loop init-ramdisk.img temp bash# cd temp (Do what you need to do.) bash# cd .. bash# umount temp bash# gzip -9 init-ramdisk.img |
Example 3. Creating an ext2 filesystem on a device
bash# mkfs -t ext2 /specialfile |
Example 4. Going from a device to a file
bash# dd if=specialfile of=imagefile |
will read the entire special file into a plain file, e.g.:
bash# dd if=/dev/ram1 of=init-ramdisk-2-35 |
But remember to unmount it before you extract it, or it can be out-of-sync (i.e.: the kernel hasn't flushed all data to disk yet). And of course the "mounted" bit is set if it is still mounted, so the next time you mount it you'll get a warning about dirty filesystems.
Accessing cramfs is similar to ext2 ramdisk, except that cramfs is a readonly filesystem. It's new to 2.4.x so most 2.2.x-based development machines do not support it. Since cramfs is readonly, you cannot 'mkfs -t cramfs' and then populate. The mkcramfs utility creates an image of a cramfs filesystem from a directory tree.
bash# mkdir mntpoint bash# mkdir temp bash# mount -t cramfs init-2-40.cramfs mntpoint -o loop bash# cp -a mntpoint temp (do what you need to do) bash# cd .. bash# mkcramfs temp init-2-41.cramfs |
Now get to the boot loader and load the file where it belongs.
Since 2.2 does not support cramfs filesystems, you cannot mount the cramfs filesystem. You will need the 'src' tar ball, e.g. root-src-2-40.tar.gz
bash# tar xfz root-src-2-40.tar.gz bash# cd root bash# (do what you need to do) bash# cd .. bash# mkcramfs root root-src-2-41.cramfs |
Now get to the boot loader and load the file where it belongs.
Ramfs is new to 2.4.x. It is a filesystem which keeps all files in RAM. It allows read and write access. Ramfs grows and shrinks to accomodate the files it contains, in contrast to a 'ext2 ramdisk', which gets allocated a fixed amount of RAM. To use ramfs, type:
bash# mkdir /mnt/mntpoint bash# mount -t ramfs ramfs /mnt/mntpoint |
Many people have asked me how to clone an iPAQ. Here is one way to clone an iPAQ that is a little scary because it involves reading and writing the raw device under a mounted JFFS2 filesystem. Several of us have used this mechanism with good results.
Example 5. Cloning a filesystem with dd
On the ipaq to be cloned, mount a filesystem on a card or network (via NFS). For the sake of argument, let us assume an IDE card mounted that filesystem on /mnt/hda.
Assuming the standard Familiar root filesytem mounted on /dev/mtdblock/1, execute the following command:
sh-2.03# mount /dev/hda1 /mnt/hda hda: 700560 sectors (359 MB) w/96KiB Cache, CHS=695/16/63 Partition check: /dev/ide/host0/bus0/target0/lun0: p1 sh-2.03# dd if=/dev/mtdblock/1 of=/mnt/hda/snapshot.jffs2 mtdblock_open 65024+0 records in 65024+0 records out mtdblock_release ok sh-2.03# umount /mnt/hda sh-2.03# |
Example 6. Cloning a filesystem using the bootldr
The bootldr can write to CF/IDE partitions or to VFAT filesytems. Using this mechanism, one can make a copy of the root filesystem image.
boot> copy input=flash:root output=cfa0:/backup.jffs2 |
boot> vfat write 0x50040000 /backup.jffs2 |
Example 7. Option A: Restoring a filesystem with dd
On the clonee ipaq, with at least task-bootstrap installed, insert the IDE card and mount the filesystem. Again, let us assume it is installed on /mnt/hda.
sh-2.03# mount /dev/hda1 /mnt/hda hda: 700560 sectors (359 MB) w/96KiB Cache, CHS=695/16/63 Partition check: /dev/ide/host0/bus0/target0/lun0: p1 sh-2.03# dd if=/mnt/hda/snapshot.jffs2 of=/dev/mtdblock/1 mtdblock_open 65024+0 records in 65024+0 records out mtdblock_release ok sh-2.03# |
Now push the reset button. Trying to execute commands afterwards
Example 8. Option B: Restoring a filesystem via the bootldr
This method currently only works with H3600 or H3700 and VFAT filesystems. On the clonee ipaq, install bootldr 2.18.16 or newer.
boot> ver Compaq OHH BootLoader, Rev 2-18-21 [BIG_KERNEL] [MD5] [MONO] Last link date: Mon Mar 11 12:53:44 EST 2002 Contact: bootldr@handhelds.org |
First, detect and attach the sleeve driver with the sleeve insert. In this example, it is a Compaq dual pcmcia sleeve.
boot> sleeve insert h3600_sleeve_insert: no spi read, defaulting sleeve vendor h3600_sleeve_insert: no spi read, defaulting sleeve deviceid sleeve vendorid=00001125 sleeve deviceid=0000D7C3 pcmcia_probe_sleeve probing for dual pcmcia sleeve dual_pcmcia_linkup[0]->prc=000019F0 dual_pcmcia_probe_sleeve pcmcia_register_ops: ops=0002D6F8 h3600_sleeve_insert: matched driver Compaq PC Card Sleeve |
Next, detect and attach the driver for the PCMCIA card. In this example, it is a 340MB IBM Microdrive CF card.
boot> pcmcia insert cis mapping=28000000 cis[0] =00000301 01 03 00 00 FF 17 04 67 5A 08 FF 1D 05 01 67 5A 08 FF 15 50 05 00 4C 75 63 65 6E 74 20 54 65 63 68 6E 6F 6C 6F 67 69 65 73 00 57 61 76 65 4C 41 4E 2F 49 45 45 45 00 56 65 72 73 69 6F 6E 20 30 31 2E 30 31 00 00 00 00 00 00 00 00 00 00 00 0 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 20 04 56 01 02 00 21 02 06 00 22 02 01 07 22 05 02 40 42 0F 00 22 05 02 80 84 1E 00 22 05 02 60 EC 53 00 22 05 02 C0 D8 A7 00 22 02 03 07 22 08 04 06 00 02 2D 0A EA 8B 22 02 05 0 1 1A 07 03 01 E0 03 00 00 01 1B 0F C1 01 19 76 C5 4B D5 19 36 36 05 46 7F FF FF FF 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF F F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF cis mapping=38000000 cis[0] =00000001 01 03 D9 01 FF 1C 04 03 D9 01 FF 18 02 DF 01 20 04 A4 00 00 00 manfid[0]=000000A4 manfid[1]=00000000 15 12 04 01 49 42 4D 00 6D 69 63 72 6F 64 72 69 76 65 00 FF 21 02 04 01 funcid=00000004 fixed disk 22 02 01 01 22 03 02 08 2F 1A 05 01 07 00 02 0F 1B 0B C0 C0 A1 27 55 4D 5D 4E 08 00 20 1B 06 00 01 21 B5 1E 3E 1B 0D C1 41 99 27 55 4D 5D 4E 64 F0 FF FF 20 1B 06 01 01 21 B5 1E 3E 1B 12 C2 41 99 27 55 4D 5D 4E EA 61 F0 01 07 F6 03 01 EE 20 1B 06 02 01 21 B5 1E 3E 1B 12 C3 41 99 27 55 4D 5D 4E EA 61 70 01 07 76 03 01 EE 20 1B 06 03 01 21 B5 1E 3E end ide status=000000D0 ide status=000000D0 ide status=000000D0 ide status=000000D0 C1A00594: 8A 84 B7 02 00 00 10 00-00 7E 00 02 3F 00 0A 00 | .........~..?... C1A005A4: 90 B0 00 00 20 20 20 20-20 20 20 20 20 20 20 20 | .... C1A005B4: 48 58 54 41 34 36 39 32-03 00 C0 00 04 00 44 4D | HXTA4692......DM C1A005C4: 49 32 36 43 31 30 42 49-2D 4D 4D 44 4D 44 31 2D | I26C10BI-MMDMD1- C1A005D4: 33 30 30 34 20 20 20 20-20 20 20 20 20 20 20 20 | 3004 C1A005E4: 20 20 20 20 20 20 20 20-20 20 20 20 20 20 10 80 | .. C1A005F4: 00 00 00 0E 00 40 00 01-00 00 01 00 B7 02 10 00 | .....@.......... C1A00604: 3F 00 90 B0 0A 00 00 01-90 B0 0A 00 00 00 00 00 | ?............... serial_number: HXTA4692 firmware_revision: DMI26C10 model_number: BI-MMDMD1-3004 bytes_per_sector=00000200 bytes_per_track=00007E00 n_sectors_per_track=0000003F n_cylinders=000002B7 n_heads=00000010 n_sectors_user_addressable=00000000 |
Now mount the partition:
boot> vfat mount 0 cmd vfat mount: partid=00000000 ptable signature=0000AA55 vfat mount: reading bpb_info C1A00628: EB 3C 90 6D 6B 64 6F 73-66 73 00 00 02 10 01 00 | .<.mkdosfs...... C1A00638: 02 00 02 00 00 F8 AB 00-3F 00 10 00 00 00 00 00 | ........?....... C1A00648: 50 B0 0A 00 00 00 29 2B-04 01 00 20 20 20 20 20 | P.....)+... C1A00658: 20 20 20 20 20 20 46 41-54 31 36 20 20 20 0E 1F | FAT16 .. C1A00668: BE 5B 7C AC 22 C0 74 0B-56 B4 0E BB 07 00 CD 10 | .[|.".t.V....... C1A00678: 5E EB F0 32 E4 CD 16 CD-19 EB FE 54 | ^..2.......T oemname=mkdosfs sectors_per_cluster=00000010 n_reserved_sectors=00000001 n_root_entries=00000200 root_dir_sectors=00000020 first_root_dir_sector=00000157 fat_size=000000AB fat_size_bytes=00015600 n_fats=00000002 total_sectors=000AB050 n_data_sectors=000AAED9 first_data_sector=00000177 n_clusters=0000AAED fat_type=00000002 root_dir_entries: C1A02FA0: 41 62 00 6F 00 6F 00 74-00 00 00 0F 00 DD FF FF | Ab.o.o.t........ C1A02FB0: FF FF FF FF FF FF FF FF-FF FF 00 00 FF FF FF FF | ................ C1A02FC0: 42 4F 4F 54 20 20 20 20-20 20 20 10 00 00 00 00 | BOOT ..... C1A02FD0: 21 00 21 00 00 00 00 00-21 00 02 00 00 00 00 00 | !.!.....!....... C1A02FE0: 42 7A 00 00 00 FF FF FF-FF FF FF 0F 00 D8 FF FF | Bz.............. C1A02FF0: FF FF FF FF FF FF FF FF-FF FF 00 00 FF FF FF FF | ................ C1A03000: 01 68 00 33 00 36 00 30-00 30 00 0F 00 D8 5F 00 | .h.3.6.0.0...._. C1A03010: 69 00 6D 00 61 00 67 00-65 00 00 00 2E 00 67 00 | i.m.a.g.e.....g. C1A03020: 48 33 36 30 30 5F 7E 31-47 5A 20 20 00 00 00 00 | H3600_~1GZ .... C1A03030: 21 00 21 00 00 00 | !.!... fat: C1A0B9B0: F8 FF FF FF F8 FF 04 00-05 00 06 00 07 00 08 00 | ................ C1A0B9C0: 09 00 0A 00 0B 00 0C 00-0D 00 0E 00 0F 00 10 00 | ................ C1A0B9D0: 11 00 12 00 13 00 14 00-15 00 16 00 17 00 18 00 | ................ C1A0B9E0: 19 00 1A 00 1B 00 1C 00-1D 00 1E 00 1F 00 20 00 | .............. . first data: C1A006A0: 41 62 00 6F 00 6F 00 74-00 00 00 0F 00 DD FF FF | Ab.o.o.t........ C1A006B0: FF FF FF FF FF FF FF FF-FF FF 00 00 FF FF FF FF | ................ C1A006C0: 42 4F 4F 54 20 20 20 20-20 20 20 10 00 00 00 00 | BOOT ..... C1A006D0: 21 00 21 00 00 00 00 00-21 00 02 00 00 00 00 00 | !.!.....!....... cmd vfat mount: listing the root directory vfat_list_dir_entries: attr=0000000F skipping long entries boot attr=00000010 first_cluster=00000002 n_bytes=00000000 h3600_~1.gz attr=00000020 first_cluster=00000197 n_bytes=008C3EF8 h3800-~1.jff attr=00000020 first_cluster=000001E7 n_bytes=01F80000 task-b~1.jff attr=00000020 first_cluster=00001607 n_bytes=00580000 h3800_~1 attr=00000020 first_cluster=00001C7E n_bytes=01F80000 snapsh~1.jff attr=00000020 first_cluster=000018C7 n_bytes=01FC0000 |
Now read the file, named in the lowercase 8.3 format, into DRAM. The following command will read the roughly 32MB snapshot into DRAM at address 32MB (requiring 64MB in the iPAQ):
boot> vfat read 0xc2000000 snapsh~1.jff vfat_find_file_entry: fname='snapsh~1.jff' dirname='' basename='snapsh~1.jff' looking for file entry in root_dir_entries: vfat_find_file_entry: C1A03180: 53 4E 41 50 53 48 7E 31-4A 46 46 20 00 00 7C 36 | SNAPSH~1JFF ..|6 C1A03190: 21 2A 21 2A 00 00 7C 36-21 2A C7 18 00 00 FC 01 | !*!*..|6!*...... got file entry rc=00000000 entry.n_bytes=01FC0000 rc=01FC0000 |
Now program the root partition with the data that was read into DRAM:
boot> program root 0xc2000000 0x01fc0000 programming flash partition root ram src =C2000000 len =01FC0000 programming flash...erasing ... Erasing sector 00040000 Erasing sector 00080000 Erasing sector 000C0000 Erasing sector 00100000 |
...
Erasing sector 01F00000 Erasing sector 01F40000 Erasing sector 01F80000 Erasing sector 01FC0000 writing flash.. addr: 00040000 data: E0021985 addr: 00050000 data: FFFFFFFF addr: 00060000 data: FFFFFFFF addr: 00070000 data: FFFFFFFF |
...
addr: 01FC0000 data: 00031985 addr: 01FD0000 data: 5FF71D11 addr: 01FE0000 data: F73FF3FF addr: 01FF0000 data: 368CE5C0 verifying ... formatting ... done. boot> |
JFFS2 is designed for linear flash, not for Compact Flash cards, which already have a wear-leveling mechanism internally, nor for hard drives, which do not require a wear-leveling mechanism.
Ext2 is not so great, because it is hard to remember to unmount the filesytem before pulling the card out, which leads to running fsck and loss of data.
Ext3 is good because it enables you to journal directory and file data.
Reiserfs is also good for removable block devices because it is a journaling filesystem.