Create LiveUSB in a general way

We can produce our own LiveUSB manually. The following are the steps that based on Arch Linux distro.

  1. Build a kernel that supports AUFS, SquashFS, and optionally vfat support. So that we can mount these filesystems. In Arch Linux, we can build linux-pf for these supports. This package can be found from AUR.
  2.  Then we can generate the initramfs. In Arch Linux, we can use mkinitcpio to create an initramfs image. For instance,
    mkinitcpio -k /boot/vmlinuz-linux-pf -c mkinitcpio-custom.conf -g initramfs.img

    (In Arch Linux, it is recommended to add in some modules in the mkinitcpio configuration file: zram, squashfs, loop, fuse, aufs, vfat)

  3. Besides that, we also need to prepare a squashfs so that it will act as a read only filesystem with workable programs. In order to create the squashfs, we can prepare it by using the existing filesystem.
    The important folders are: bin, etc, home, lib, mnt, opt, root, sbin, srv, usr, var.
    The important folders but let them empty are: dev, media, proc, run, sys, tmp.
    And also need to comment the lines in the /etc/fstab, so that after boot, there is no automount.
  4. Then we can prepare a USB pendrive so that it can boot by using syslinux. syslinux will run the syslinux.cfg, which can be located at /syslinux or /boot/syslinux. The simplest way to make the syslinux.cfg to boot is something like
    DEFAULT myliveusb
    LABEL myliveusb
    KERNEL vmlinuz-linux-pf
    APPEND initrd=initramfs.img

    By this, it will use the kernel vmlinuz-linux-pf which is built at the beginning (in step 1), and initrd with the initramfs.img that is generated (in step 2). These files need to be put at the same path with syslinux.cfg.

  5. In order to boot properly, we need to modify the “init” file in the initramfs.img. This image is actually compressed cpio. We can extract the data by
    zcat ../initramfs.img | cpio -i

    The extracted data contains some scripts, kernel modules, and libraries that are required to boot up. So, we just modify the init script.
    In the init script, we may need to disable the fsck_root (in Arch Linux) so that it will not fsck the root file.
    Then, we need to add in the statements to mount the USB pendrive and created squashfs.
    Therefore, we add in the following statements to somewhere before the initramfs switch the root.

    #The statements are based on
    mkdir -p /mnt/usb /squashfs /tmpfs
    mount -t vfat -o ro /dev/disk/by-label/MYPENDRIVE /mnt/usb
    mount -t squashfs -o ro,loop /mnt/usb/path-to/root.sfs /squashfs
    mount -t tmpfs none /tmpfs
    #cd /tmpfs ; mkdir -p tmp var/log ; chmod 1777 tmp ; cd / #This step is optional
    mount -t aufs -o br=/tmpfs:/squashfs none /new_root #where the new_root is the root which will be switched according to Arch Linux

    Finally we need to re-compress by

    find . | cpio -o -H newc | gzip > ../initramfs.img

    If we read through the init script, at the end there is a statement that calls “switch_root” which will switch to the /new_root. Then, the system will boot successfully.

The AUFS is required because SquashFS is read-only. The following is the explanation of the statements above,

mount -t vfat -o ro /dev/disk/by-label/MYPENDRIVE /mnt/usb

is to mount the current USB pendrive to the /mnt/usb. We use the /dev/disk/by-label because it is the easiest way by referring the pendrive based on the label. /dev/sd{a,b,c} and so on are not applicable because different computer may have different number of storages. After this,

mount -t squashfs -o ro,loop /mnt/usb/path-to/root.sfs /squashfs

we mount the root.sfs which is created by mksquashfs. Then,

mount -t tmpfs none /tmpfs

we mount the tmpfs to a new folder /tmpfs. So that we use the memory for read-write operation. We do not use the default /tmp because it is used by initramfs.

cd /tmpfs ; mkdir -p tmp var/log ; chmod 1777 tmp

This is to create a tmp folder with the 1777 ownership as /tmp in the root. Finally,

mount -t aufs -o br=/tmpfs:/squashfs none /new_root

we mount the tmpfs and squashfs unionly to the /new_root

Because tmpfs is writable, squashfs is read-only, but they are mounted unionly in the new_root, as a result after switch_root, then it can boot and write to the new_root file system, as all the data are actually stored in the memory (as tmpfs occupies the memory).

By this, we can also create our own filesystem as a file (formated with ext4), and mount it unionly to the /new_root. So, that we can “save” the data and restore it during the next boot. (I have not yet tested this step by editing the init script.)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s