While on vacations, my wife’s Samsung phone suddenly refused to turn on. I thought I might be able to fix it by re-flashing the firmware (looking forward, I was wrong: the phone had a hardware failure). For this, I needed a Windows machine to run the flashing tool. I have no Windows on my laptop and I had no USB stick to install it either. So I had to figure out a “vegetarian” way of installing an operating system without using any installation media. Turns out, this is pretty straightforward if you are using modern Linux.

Challenges

The installation media (USB stick) is generally needed for two purposes when installing a new OS. First, you need to re-partition your hard drive to free up the necessary space (at least 50 Gb for Windows 10). For this, you boot from a live USB with self-contained re-partitioning tools. Second, you boot with another live USB containing OS installation files. Sometimes, you can combine these two steps into one if the OS live media supports re-partitioning (all Linuxes for example). All in all, having an emergency USB stick is very helpful. Not having it means that you need to find a different way of booting live images.

The power of GRUB

GRUB is Linux bootloader: a program that prepares environment for booting Linux kernels. You may see GRUB menu soon after you turn your Linux machine on. Despite serving a rather simple purpose, GRUB is an ecosystem on its own: it has a command line, supports scripting, plugins. I had GRUB installed on my machine as a part of Fedora 36 installation. Thus, the idea I decided to challenge is to make GRUB to boot a live image placed on my hard drive.

Realization

Making GRUB boot something is as easy as preparing a menu entry for it. GRUB understands many filesystems (through plugins). You may even put an iso file with the installation/live OS and point GRUB to it! If configured properly, you will be able to reboot into the needed live iso image. This made up the following plan:

  1. Download Fedora live image
  2. Configure GRUB

    First, you need to add a new entry into /etc/grub.d/40_custom (copy-pasted).

    menuentry "Fedora-Workstation-Live-x86_64-33-1.2.iso" {
      insmod ext2
      set isofile="/home/linuxbabe/Downloads/Fedora-Workstation-Live-x86_64-33-1.2.iso"
      loopback loop (hd0,5)$isofile
      linux (loop)/isolinux/vmlinuz root=live:CDLABEL=Fedora-WS-Live-33-1-2 rd.live.image verbose iso-scan/filename=$isofile
      initrd (loop)/isolinux/initrd.img
    }
    

    Note that this example is given for Fedora 33 so you have to adjust it accordingly. Breakdown of what happens here:

    1. insmod ext2: loads a plugin for reading ext2-ext4 filesystems where the downloaded image is saved (use insmod btrfs for btrfs filesystem, etc).
    2. set isofile="..." sets the variable isofile to contain your downloaded image path.
    3. loopback loop (hd0,5)$isofile defines a loopback device loop with iso contents. Note that (hd0,5) has to be changed to a proper identifier of the partition where the image is saved. Use fdisk -l to figure it out.
    4. linux and initrd point to the linux kernel and the filesystem for booting.

    After the new menu entry is set up, you need to push the changes by running grub-mkconfig -o /boot/grub2/grub.cfg.

  3. Reboot

    After rebooting, you should be able to see the GRUB menu with the new entry. Note that, you may need to hit Esc after turning on the machine to see the menu. Afterwards, select the new entry and hit Enter. If there is an error read it carefully and act accordingly. Sometimes (hd0,5) is a wrong identifier: you should try neighboring ones such as (hd0,6) or (hd0,4). For example, I had to change it to (hd1,5), for whatever reason, to make it boot. To make on-the-fly changes in GRUB, hit key e when the menu entry is selected and edit the script. All such changes are temporary: fortunately, you need to boot live image only once.

  4. Repartition

    Do the necessary repartitioning using live image tools. In practice, I just needed to shrink my primary home partition to free up some space on the hard drive. If you use btrfs (like I did) you may avoid all above steps and shrink the “hot” filesystem directly from the OS. gparted is the simplest way to do it but there are command-line tools as well.

  5. Repeat p. 1-3 for the Windows live image

    This time, I launched the downloaded Windows 10 live media using a similar procedure. Instead of directly pointing to iso, however, I had to prepare a separate 7GB ntfs partition where I copied all installation files from the iso. Once you freed up the space you can do it from your main Linux installation (or from Linux live image as well). The GRUB menu entry becomes somewhat simpler:

    menuentry "Windows-10-Installer.iso" {
      set root=(hd0,5)
      insmod part_gpt
      insmod ntfs
      insmod chain
      chainloader /efi/boot/bootx64.efi
    }
    

    Important note: ntfs is GRUB module and some distributions do not include it by default. In this case, you will see a message saying that it can’t find the module. For Fedora, you have to install the module bundle:

    dnf install grub2-efi-x64-modules
    

    and then copy the module to where GRUB can find it (create the target folder first):

    sudo cp /usr/lib/grub/x86_64-efi/ntfs.mod /boot/efi/EFI/fedora/x86_64-efi/
    

    Same instructions apply to (hd0,5): adjust it to your partition number and if fails during the boot, try changing it to neighboring ones using e key from the GRUB menu. Remember to push the changes by running grub-mkconfig. Afterwards you should be able to boot into Windows live image and install Windows into the unoccupied disk space. Surprisingly, this did not overwrite GRUB bootloader. If it would, the plan would be to boot Linux from Windows bootloader which lately recognizes Linux partitions and fix GRUB.

  6. Finally, re-run grub-mkconfig after installing Windows

    Windows installer reboots your machine a couple of times during the installation. Since GRUB does not know about freshly installed OS, you will fail completing install without GRUB discovering the new partition and the new OS. Thus, after the first reboot make sure to run grub-mkconfig which will probe other operating systems on the hard drive. Moreover, after each reboot you will have to select the new Windows entry manually. Make sure you do not confuse it with Windows live partition (which you may get rid of now).

  7. Cleanup Windows installation partition and additional GRUB entries

Surprisingly, it all went very well: my Linux setup left intact and I was able to install and boot a new Windows partition. A lot of drivers were missing but once you go online you should be able to fix that, too.