Creating Windows installation media on Linux

Every so often I need to install Windows, most recently for my GNOME on WSL experiments, and to do this I need to write the Windows installer ISO to a USB stick. Unlike most Linux distro ISOs, these are true, pure ISO 9660 images—not hybrid images that can also be treated as a DOS/MBR disk image—so they can’t just be written directly to the disk. Microsoft’s own tool is only available for Windows, of course.

I’m sure there are other ways but this is what I do. Edit: check the comments for an approach which involves 2 partitions and a little more careful copying, but no special tools. I’m writing it down so I can easily find the instructions next time!

The basic process is quite simple:

  • Download an ISO 9660 disk image from Microsoft
  • Partition the USB drive with a single basic data partition, formatted as FAT32
  • Mount the ISO image – on GNOME, you should just be able to double-click it to mount it with Disk Image Mounter
  • Copy all the files from the mounted ISO image to the USB drive

But there is a big catch with that last step: at least one of the .wim files in the ISO is too large for a FAT32 partition.

The trick is to first copy all the files to a writeable directory on internal storage, then use a tool called wimlib-imagex split from wimlib to split the large .wim file into a number of smaller .swm files before copying them to the FAT32 partition. I think I compiled it from source, in a toolbox container, but you could also use this OCI container image whose README helpfully provides these instructions:

find . -size +4294967000c -iname '*.wim' -print | while read -r wimpath; do
  wimbase="$(basename "$wimpath" '.wim')"
  wimdir="$(dirname "$wimpath")"
  echo "splitting ${wimpath}"
  docker run \
    --rm \
    --interactive \
    --tty \
    --volume "$(pwd):/work" \
    "backplane/wimlib-imagex" \
      split "$wimpath" "${wimdir}/${wimbase}.swm" 4000

Now you can copy all those files, minus the too-large .wim, onto the FAT32 drive, and then boot from it.

This all assumes that you only care about a modern system with EFI firmware. I have no idea about creating a BIOS-bootable Windows installer on Linux, and fortunately I have never needed to do this: to test stuff on a BIOS Windows installation, I have used the time-limited virtual machines that Microsoft publishes for testing stuff in old versions of Internet Explorer.

I was inspired to resurrect this old draft post by a tweet by Ross Burton.

8 thoughts on “Creating Windows installation media on Linux”

  1. It is even easier: make two partitions, one FAT32, and another NTFS. Now, copy in the NTFS all the contents of the ISO image. Do the same in the FAT32 with the exception of the SOURCES folder (which is the one with the very-very-big file). Finally, in the FAT32 partition create an empty SOURCES folder and copy inside only the BOOT.WIM file from the SOURCES folder of the ISO image.

    Et voila! You have a bootable USB drive to install Windows.

  2. Funnily enough, I also recently had to install Windows. My solution was to format the USB as NTFS, which doesn’t have the 4GB limitation of FAT32.

  3. I think this is how I’ve done it before, but why not point boxes at the downloaded ISO?

  4. I think most recently I wanted bare metal because I wanted to limit the amount of VM nesting and to try WSLg’s support for using the host GPU in the WSL VM. And before that, I sacrificed my Hack laptop to use USB devices, test bootloader stuff on real firmware, and generally avoid the confusion of working in a VM

Comments are closed.