Creating Windows USB install media in Linux

I spent entirely too long today trying to discern why my efforts to dd a Windows USB install ISO onto a USB stick were failing. Everything worked, the USB stick would mount fine in Windows, but I couldn’t boot from it despite setting it bootable in cfdisk.

The trick is to write a Windows (or presumably DOS?) compatible boot sector to the volume. I will no doubt forget this by the time I next need to create one of these installers, so I’m putting these notes here while I remember.

The commonly recommended way of achieving this is with LILO, of all things. I’ve not had LILO installed for years and didn’t fancy installing it just for this. Thankfully I found ms-sys, a small C program which does exactly one thing: create Microsoft compatible boot records. The missing step turned out to be a single command: ms-sys --mbr7 /dev/sdX.

Assuming you have either installed ms-sys with your package manager, or simply compiled it locally, here is the full process:

  1. Run cfdisk /dev/sdX, delete any existing partitions and create a new whole-disk partition. Set it to type NTFS (code 7), and set it bootable.
  2. Create the NTFS filesystem with mkfs.ntfs -f /dev/sdX1
  3. Mount the install ISO and the new USB NTFS volume, and copy the contents of the install ISO across: cp -vr /media/ISO/* /media/USB-STICK
  4. Copy any additional drivers/installers you need onto the USB stick
  5. Run ms-sys --mbr7 /dev/sdX (for Windows 7, there are other options for Vista etc. check the manual)

Alternatively, you could dd the ISO image onto the USB stick and then run ms-sys --mbr7. I needed to add a bunch of drivers and a Ninite installer to the base image, so I opted for the manual approach.