I will assume that we are starting from a Linux-only setup with free space available on the disk, e.g. by following everything at https://gist.github.com/apsun/1f7b1da40b028a9ed1e0409ca8c3b3cc.
Starting out, the disk should look like:
/dev/sda
sda1 <-- ESP
sda2 <-- Linux
(free space)
Follow the steps from this blog: https://techbit.ca/2019/02/creating-a-bootable-windows-10-uefi-usb-drive-using-linux/
The tl;dr is to format the disk with GPT and create two partitions: a bootable FAT32 ESP partition containing all of the files except sources/
but including sources/boot.wim
, and a NTFS partition with the rest of sources/
. This is necessary because install.wim
is larger than 4GiB nowadays, which exceeds the FAT32 file size limit.
In the end, your USB drive should look like:
/dev/sdb1/ <-- FAT32
boot/
efi/
sources/
boot.wim
(other files)
/dev/sdb2/ <-- NTFS
sources/
install.wim
(other files)
Reboot into the USB drive. Unfortunately, the Windows graphical installer is unable to understand existing UEFI-based Linux installations. If you try to install it normally, you'll get the error:
Windows could not prepare the computer to boot into the next phase of installation. To install Windows, restart the installation.
To work around this, we need to install Windows manually using the DISM tool. Most of the instructions here are adapted from: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/capture-and-apply-windows-system-and-recovery-partitions
First, hit SHIFT+F10
to open a command prompt. We're going to create the NTFS partition that Windows will be installed on, and mount the ESP and partition containing install.wim
while we're at it:
> diskpart
# Create the Windows partition and assign it to W:
list disk
select disk 0 <-- replace with the disk you're installing to
list partition
create partition primary
format quick fs=ntfs
assign letter=W
# Assign the EFI system partition (ESP) to S:
list disk
select disk 0 <-- replace with the disk you're installing to
list partition
select partition 1 <-- replace with the EFI system partition (ESP)
assign letter=S
# Assign the partition containing install.wim to Z:
list disk
select disk 1 <-- replace with the USB drive
list partition
select partition 2 <-- replace with the partition containing install.wim
assign letter=Z
exit
Note that by default, create partition primary
fills the remainder of the disk. You can play around with the settings if you want a different setup. From a Linux standpoint, your disk should now look like:
/dev/sda
sda1 <-- ESP, mounted at S:
sda2 <-- Linux
sda3 <-- Windows, mounted at W:
/dev/sdb
sdb1
sdb2 <-- mounted at Z:
A install.wim
file may contain more than one Windows edition (e.g. Pro, Education, etc.). Figure out the index number of the edition you want to install by running:
dism /Get-WimInfo /WimFile:Z:\sources\install.wim
It should show a few entries like:
Index : 4
Name : Windows 10 Education
Description : Windows 10 Education
Size : 15,074,233,945 bytes
Take note of the index 4
. Next, we're basically going to extract the contents of install.wim
onto the W:
partition. Run:
dism /Apply-Image /ImageFile:Z:\sources\install.wim /Index:4 /ApplyDir:W:\
Replace 4
with the index of the edition you want. This will take a while. Once it's done, you will then need to copy the Windows bootloader into the ESP:
W:\Windows\System32\bcdboot W:\Windows /s S:
Finally, exit out of the command prompt, reboot into Windows (it may or may not do that automatically; if not, configure your UEFI boot manager), and the installation should continue normally.
I'm not entirely certain whether this is necessary, but I configured BitLocker with a password instead of TPM + PIN. To do this, follow the steps here: https://www.howtogeek.com/howto/6229/how-to-use-bitlocker-on-drives-without-tpm/
Then, when enabling BitLocker, uncheck the option to "Run BitLocker system check", or else you'll get an error like:
The data drive specified is not set to automatically unlock on the current computer and cannot be unlocked automatically.
Other than that, everything should work normally.