The process of creating FlickOS

Posted on Wed 22 March 2023 in operating system

Hey everyone. First off, I want to say thank you to all who downloaded Flick. According to sourceforge log, we have 500+ downloads in the span of just two weeks. That means we saved and made 500+ computers usable again and that makes me very proud. Anyway, today's blog is about the processes and steps that I did to create Flick. This content will serve as my personal record but could also be used by anyone who wants to create their own. I will list down below the general steps and then explain it even further.

Steps:

  1. install necessary tools
  2. extract the squash file and unsquash it
  3. mount to chroot
  4. apply modifications and changes
  5. squash it again and create the ISO file

Install tools

To begin our journey in creating Flick, we have to first install tools and packages needed for the tasks ahead.

    sudo apt-get install \
    binutils \
    debootstrap \
    squashfs-tools \
    xorriso \
    grub-pc-bin \
    grub-efi-amd64-bin \
    mtools \
    isomaster

Now that we have all the tools needed, let us proceed to extracting the neccessary files from our chosen ISO distribution.

Extract and unsquash

For this step, we will first extract filesystem.squashfs from an existing ISO image, and in my case the LXLE ISO image. Second, we are going to unsquash the filesystem.squashfs, this action will create a folder named squashfs-root that contains all the files of the operating system.

  • Using isomaster extract the filesystem.squashfs
  • Unsquash the file sudo unsquashfs filesystem.squashfs
  • Confirm that the previous command created the folder squashfs-root

Mount everything

And now the fun begins. For us to be productive in this step, we have to understand first what is chroot. Chroot in Linux is like a virtual machine but not quite. It's a kernel-level virtualization so its very light in resource usage. By chrooting you create an isolated environment within your Linux system, where you can install and run applications with their own file system hierarchy. This can be useful for testing and debugging applications, isolating processes from the rest of the system, and for security purposes. So, that's what we are going to do with our freshly unsquashed squashfs-root folder. To chroot inside we execute:

sudo mount --bind /dev squashfs-root/dev
sudo mount --bind /run squashfs-root/run
sudo chroot squashfs-root

And other mounts needed when we are making modifications inside the root system:

mount none -t proc /proc
mount none -t sysfs /sys
mount none -t devpts /dev/pts
export HOME=/root
export LC_ALL=C

If we encounter no errors, our terminal prompt will change to this: root@host-os:/#. Always remember that whatever command that we execute inside this prompt, we are doing it inside the squashfs-root directory operating system, not the host operating system. If we need to execute commands for our host operating system, we have to open another terminal that belongs to the host OS.

Go loco

Okay, this is where the most fun of them all. This the time where we customize the operating system that we want. Some of the things that we can do are: remove applications that we don't like and install the ones that we like, set per applications configuration, create the user template under /etc/skel, configure the ubiquity installer, create your own tools and utilities, and many more. Below is the list of folders I found important for modifications.

- /usr/share /applications /icons /backgrounds
- /usr/bin
- /etc/init.d /grub.d /skel
- /usr/local/bin
- /home/username/.local/bin /applications
- /home/username/.config

Squash and create

Congratulations if you're reading this last step. This step is where the excitement happens. Here we will have mixed emotions like excitement and anxiousness at the same time. We are excited to see the fruit of our labor but worried that we might missed something. The code to create our final product is:

#!/bin/bash

cd $HOME/lxle

echo "Clean up..."
sudo rm -r image *.iso

echo "Create directories.."
mkdir -p image/{casper,isolinux,install}

echo "Copy vmlinuz and initrd..."
sudo cp squashfs-root/boot/vmlinuz-5.4.0-113-generic image/casper/vmlinuz
sudo cp squashfs-root/boot/initrd.img-5.4.0-113-generic image/casper/initrd

echo "Copy memtest86+..."
sudo cp squashfs-root/boot/memtest86+.bin image/install/memtest86+

touch image/ubuntu

echo "Create grub menu..."
cat <<EOF > image/isolinux/grub.cfg

search --set=root --file /ubuntu

insmod all_video

set default="0"
set timeout=30

menuentry "Try Flick OS without installing" {
   linux /casper/vmlinuz boot=casper nopersistent toram fsck.mode=skip quiet splash ---
   initrd /casper/initrd
}

menuentry "Install Flick OS" {
   linux /casper/vmlinuz boot=casper only-ubiquity fsck.mode=skip quiet splash ---
   initrd /casper/initrd
}

menuentry "Check disc for defects" {
   linux /casper/vmlinuz boot=casper integrity-check quiet splash ---
   initrd /casper/initrd
}

menuentry "Test memory Memtest86+ (BIOS)" {
   linux16 /install/memtest86+
}

menuentry "Test memory Memtest86 (UEFI, long load time)" {
   insmod part_gpt
   insmod search_fs_uuid
   insmod chain
   loopback loop /install/memtest86
   chainloader (loop,gpt1)/efi/boot/BOOTX64.efi
}
EOF

echo "Generate manifest..."
sudo chroot squashfs-root dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee image/casper/filesystem.manifest
sudo cp -v image/casper/filesystem.manifest image/casper/filesystem.manifest-desktop
sudo sed -i '/ubiquity/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/casper/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/discover/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/laptop-detect/d' image/casper/filesystem.manifest-desktop
sudo sed -i '/os-prober/d' image/casper/filesystem.manifest-desktop

echo "Create squashfs..."
sudo mksquashfs squashfs-root image/casper/filesystem.squashfs

echo "Write filesystem.size..."
printf $(sudo du -sx --block-size=1 squashfs-root | cut -f1) > image/casper/filesystem.size

echo "Create README.diskdefines..."
cat <<EOF > image/README.diskdefines
#define DISKNAME  Flick
#define TYPE  binary
#define TYPEbinary  1
#define ARCH  amd64
#define ARCHamd64  1
#define DISKNUM  1
#define DISKNUM1  1
#define TOTALNUM  0
#define TOTALNUM0  1
EOF

cd $HOME/lxle/image

echo "Create a grub UEFI image..."
grub-mkstandalone \
   --format=x86_64-efi \
   --output=isolinux/bootx64.efi \
   --locales="" \
   --fonts="" \
   "boot/grub/grub.cfg=isolinux/grub.cfg"

echo "Create a FAT16 UEFI boot disk image containing the EFI bootloader..."
(
   cd isolinux && \
   dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
   sudo mkfs.vfat efiboot.img && \
   LC_CTYPE=C mmd -i efiboot.img efi efi/boot && \
   LC_CTYPE=C mcopy -i efiboot.img ./bootx64.efi ::efi/boot/
)

echo "Create a grub BIOS image..."
grub-mkstandalone \
   --format=i386-pc \
   --output=isolinux/core.img \
   --install-modules="linux16 linux normal iso9660 biosdisk memdisk search tar ls" \
   --modules="linux16 linux normal iso9660 biosdisk search" \
   --locales="" \
   --fonts="" \
   "boot/grub/grub.cfg=isolinux/grub.cfg"

echo "Combine a bootable Grub cdboot.img..."
cat /usr/lib/grub/i386-pc/cdboot.img isolinux/core.img > isolinux/bios.img

echo "Generate md5sum.txt..."
sudo /bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v -e 'md5sum.txt' -e 'bios.img' -e 'efiboot.img' > md5sum.txt)"

echo "Create ISO image..."

sudo xorriso \
   -as mkisofs \
   -iso-level 3 \
   -full-iso9660-filenames \
   -volid "FlickOS" \
   -output "../flickos.iso" \
   -eltorito-boot boot/grub/bios.img \
      -no-emul-boot \
      -boot-load-size 4 \
      -boot-info-table \
      --eltorito-catalog boot/grub/boot.cat \
      --grub2-boot-info \
      --grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \
   -eltorito-alt-boot \
      -e EFI/efiboot.img \
      -no-emul-boot \
   -append_partition 2 0xef isolinux/efiboot.img \
   -m "isolinux/efiboot.img" \
   -m "isolinux/bios.img" \
   -graft-points \
      "/EFI/efiboot.img=isolinux/efiboot.img" \
      "/boot/grub/bios.img=isolinux/bios.img" \
      "."

I know it's quite long, but you can save this as a bash file, make necessary adjustment and execute the file.

Conclusion

Linux is a file based operating system, this means everything is written somewhere like configurations and logs. We just need to be creative and learn how to ask the right questions. Everything is in google, I never asked a person about anything during the development of Flick so don't worry much where to get help. Best advise that I could give is that document everything. Every actions, commands and changes that you do should be recorded or noted. This way you can replicate the changes in the future or you could undo something that you do not like. On the plus side, when everything is documented, you could create a bash program to automate everything, and run the automation the next time you want to generate a fresh OS. Making a Linux operating system is fun and exciting. We have all the tools, documentations and forums that we can go to if needed. All that we need is unleash our creativity, programming skills if you want to create your own utilities and most importantly a lot of patience. The overall process is quite time consuming and it will definitely test your patience. Now that you have the idea, why not make your own Linux. Goodluck!

References

https://github.com/mvallim/live-custom-ubuntu-from-scratch