Create Windows 10 UEFI install USB from ISO
Steps to create Win10 installer using Linux tools
Every now and then I have $reasons
to install Windows 10 to one or more
workstations, quite often reason is that many games just aren’t available for
Linux. This was one of such days. As I only have Linux workstations (without
DVD drives) I had to create installer USB from ISO image provided by
Microsoft.
I tried couple methods:
- a)
dd if=windows.iso of=/dev/myusbstick
and - b) creating FAT32 partition & copying disk contents there. (FAT32 because it’s the requirement for UEFI booting.)
Both of these failed to produce working USB installer, and after some debugging
I found out, that sources/install.wim
is more than 4 gigabytes in size, and
maximum filesize limitation on FAT32 filesystems happens to be 4 gigabytes.
So I had to do some research (read: googling), and then I was able to find blog post by Microsoft describing various methods for creating UEFI USB installer using Windows. But, as mentioned before, I didn’t have working Windows installation available … thus methods described in the blog post weren’t helping me. But this seemed to be something that could work, only if I was able to reproduce the results on Linux.
Some more research (googling), and I found some Linux tools for handling .wim
files. And those were just apt-get install
away, pure win:
apt-get install wimtools
Especially interesting was tool called wimlib-imagex
, which is able to do
same tricks as dism
in Windows. And I already had that Microsoft’s blog post
describing how to split files larger than 4GB. I decided to proceed my test,
and split sources/install.wim
to parts with maximum size of 250 megabytes.
(This was just arbitrary size I picked, eg. 1024 (ie. 1GB) would have worked as
well.)
wimlib-imagex split install.wim install.swm 250
And to make life easier for everyone, including future me, here’s full script to unpack ISO image, split that one huge file, and then format USB device and finally copy files to get working Windows 10 installer.
Script to create Windows 10 installer on Linux
And, to make it easier to repeat, here’s everything in single script. Remember
to configure correct path for ISOFILE
and USBDEVICE
. As you’re writing new
partitions etc, most commands require root privileges, ie. maybe copy this as
script, set correct values for ISOFILE
and USBDEVICE
variables, and then
run with sudo
.
# Path to source ISO image.
# <https://www.microsoft.com/software-download/windows10ISO>
export ISOFILE="Win10_1809Oct_EnglishInternational_x64.iso"
# Path to the device that points to your USB stick
# Your modified installer will be written here, "target".
export USBDEVICE="/dev/sdX"
# Temporary directory we create for manipulating the image contents
export TEMPDIR="$(mktemp -d winimage-XXXXXX)"
# Our mountpoint for the ISO image
export SOURCE="source"
# Our mountpoint for the target device
export TARGET="target"
# Install necessary tools
# - parted: for creating disk partitions
# - rsync: for copying files around efficiently
# - wimtools: for manipulating Windows installer contents
apt-get install parted rsync wimtools
# Directory for mounting the ISO image
mkdir "${SOURCE}"
# Directory for mounting the USB stick
mkdir "${TARGET}"
# Create GPT partition table, one FAT32 partition that uses 100% of available space
# first create msdos table to ensure that existing table is purged
parted --script "${USBDEVICE}" mklabel msdos
parted --script "${USBDEVICE}" mklabel gpt
parted --script "${USBDEVICE}" mkpart primary fat32 1 100%
parted --script "${USBDEVICE}" set 1 msftdata on
# Just to make sure that partition is correctly formatted as FAT32
mkfs.vfat "${USBDEVICE}1"
# Mount Windows ISO image for file copying
mount -oloop "${ISOFILE}" "${SOURCE}"
# Mount USB stick, partition 1
mount "${USBDEVICE}1" "${TARGET}"
# Copy all files from ISO image to temporary directory
rsync -avh --no-o --no-g "${SOURCE}/" "${TEMPDIR}/"
# Split the install.wim file to smaller parts (max 250MB), to temporary directory
wimlib-imagex split \
"${TEMPDIR}/sources/install.wim" \
"${TEMPDIR}/sources/install.swm" \
250
# Finally, copy resulting data structure, without large file (install.wim) to
# the USB stick
rsync -avh --no-o --no-g --exclude="install.wim" "${TEMPDIR}/" "${TARGET}/"
# Ensure that everything has been written to disk
sync
# Unmount, your stick is ready now
umount "${SOURCE}"
umount "${TARGET}"
rm -rf "${TEMPDIR}"
Revision history
- 2020-11-06 post was completely rewritten to use better language
Feedback / comments?
Either, send e-mail of ping at Mastodon (mastodontti.fi/@ypcs.