25 Jan

Creating an image file from a local directory on Linux

Sometimes I wish to create disk image files using a directory on my local computer. It’s an easy task with Linux, which can be accomplished with only a couple of commands.

The main scenario for when I wish to create a disk image is when creating a .img file that can be written straight to a SD card (for example Arch Linux for the Raspberry Pi comes as a tar.gz of the root filesystem rather than an image file) or used with QEMU as the hard disk.

The following steps (that I use for creating an Arch Linux SD card image file) will take you through creating an image file and writing the files you wish to it.

Create an 8GB image file:

dd if=/dev/zero of=newfile.img bs=1M count=8192

Partition the image file:

fdisk ./newfile.img

I usually create 2 partitions, a FAT partition of about 100M for the boot files and the rest of the image a ext4 for the root filesystem.

Mount the image file using the loopback device. (I used the -f switch to find the next available loop device rather than explicitly specifying one)

sudo losetup -Pf ./newfile.img

The image file should now be visible as a block device on /dev/loopX where X is 0 if you don’t have any other loop devices

Running the following should give similiar output as below:

[[email protected] blog]$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0         7:0    0     1G  0 loop 
├─loop0p1   259:6    0   100M  0 loop 
└─loop0p2   259:7    0   933M  0 loop

Format the partitions

sudo mkfs.vfat /dev/loop0p1
sudo mkfs.ext4 /dev/loop0p2

Mount the partitions:

mkdir p1
mkdir p2
sudo mount /dev/loop0p1 p1
sudo mount /dev/loop0p2 p2

You can now copy anything across my moving your files into directories p1 or p2.

For example, as I usually create SD card images from the Arch Linux ARM root filesystem tar.gz. I do the following:

sudo bsdtar -xpf ArchLinuxARM-rpi-latest.tar.gz -C p2
sync
sudo mv p2/boot/* p1

Clean up:
At this point we just need to clean up and unmount the image file and detach the loop back device:

sudo umount p1 p2
sudo losetup -d /dev/loop0

You should now have a nicely prepared image file. You can also mount existing image files using losetup, as we did above.

20 Mar

Boot ArchLinux from USB on the Raspberry Pi

If you have ever wanted to store your root file system on a USB stick rather than an SD card then the following will describe how to do so.

You can’t get rid of the SD card completely as the Raspberry Pi is designed to boot from an SD card however you only need to store the “boot” files on the SD card as this is what the Raspberry Pi will attempt to load when powered on.

The usual instructions for installing Arch on the Raspberry Pi is to format the SD card with two partitions using a DOS (MBR) partitioning format. The first partition is recommended to be 100 MB in size and is formatted using the FAT file system. The second partition takes up the rest of the space on the SD card and is formatted using the standard Linux Ext4 file system.

Once the partitions are created and file systems formatted then we download the latest Arch Linux package for the Raspberry Pi (I’m using the Raspberry Pi 2 package here) (http://archlinuxarm.org/os/ArchLinuxARM-rpi-2-latest.tar.gz). Extract this archive to the main Ext4 partition on the SD card and then move the “boot” files from /mnt/p2/boot/ to /mnt/p1 assuming that the 100 MB FAT partition is mounted at /mnt/p1 and the Ext4 partition is mounted at /mnt/p2.

This works because the “boot” files on the first partition point to the second partition containing the root file system.

All we need to do is install the root file system on a USB drive and change the “boot” files on the SD card to point to our root file system partition on the USB drive.

The following assumes that on the Linux system used to prepare the USB and SD card that /dev/sdb is the USB drive and /dev/sdc is the SD card.

  1. Start fdisk to partition the SD card:
    fdisk /dev/sdc
  2. At the fdisk prompt, delete old partitions and create a new one:
    1. Type o. This will create a new MBR partition table at the beginning of the SD card.
    2. Type n to create a new partition.
    3. Make it a primary partition by typing p.
    4. Type 1 for the first partition on the SD card and press ENTER twice to accept the default first and last sector.
    5. Type t, then c to set the first partition to type W95 FAT32 (LBA).
    6. Save the changes and exit by typing w.
  3. Start fdisk to partition the USB drive:
    fdisk /dev/sdb
  4. At the fdisk prompt, delete old partitions and create a new one:
    1. Type o. This will create a new MBR partition table at the beginning of the USB drive.
    2. Type n to create a new partition.
    3. Make it a primary partition by typing p.
    4. Type 1 for the first partition on the USB drive and press ENTER twice to accept the default first and last sector.
    5. Save the changes and exit by typing w.
  5. Create and mount the FAT filesystem:
    mkfs.vfat /dev/sdc1
    mkdir boot
    mount /dev/sdc1 boot
  6. Create and mount the ext4 filesystem:
    mkfs.ext4 /dev/sdb1
    mkdir root
    mount /dev/sdb1 root
  7. Download and extract the root filesystem (as root, not via sudo):
    wget http://archlinuxarm.org/os/ArchLinuxARM-rpi-2-latest.tar.gz
    bsdtar -xpf ArchLinuxARM-rpi-2-latest.tar.gz -C root
    sync
  8. Move boot files to the first partition:
    mv root/boot/* boot
  9. Modify the file boot/cmdline.txt so that the root= kernel option specifies the first partition on the USB device. It should look similar to this:
    root=/dev/sda1 rw rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop

    If no other USB drives are to be plugged into the Raspberry Pi then the USB device is likely to get assigned /dev/sda.

  10. Unmount the two partitions:
    umount boot root
  11. Insert the SD card and USB drive into the Raspberry Pi and switch it on

The problem with the above is that you cannot guarantee that the USB drive will be assigned /dev/sda and this is especially the case when using more than one USB drive with the Pi.

To make this more reliable then when partitioning the USB drive in the above you should use gdisk to create a GPT based partition table. This way the partition can be referenced using a UUID and then modifying cmdline.txt so that the root kernel option is in the form root=PARTUUID=4673c3fe-9bab-476c-88c5-65e2c842f72a.