From 25abfc4a9fb71440833d085ae44ed20618a3b155 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Mon, 16 Aug 2021 00:46:55 +0300 Subject: [PATCH] Major changes: mbr/fat32, gpt/fat32, gpt/ntfs, gpt+uefintfs * Use FAT32 partition in MBR mode and also install EFI bootloader * Use wimsplit to split 4+ GiB install.wim file to fit FAT32 partition * Rework partitioning modes --- windows2usb | 159 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 110 insertions(+), 49 deletions(-) diff --git a/windows2usb b/windows2usb index a959a2e..0aa6d23 100755 --- a/windows2usb +++ b/windows2usb @@ -13,7 +13,7 @@ dirpath="$(dirname "$scriptpath")" function check_requirements() { - local reqs=(awk lsblk 7z mkfs.vfat mkfs.ntfs sfdisk ms-sys mktemp) + local reqs=(awk lsblk 7z mkfs.vfat mkfs.ntfs sfdisk ms-sys mktemp wimsplit) for req in ${reqs[*]}; do if ! command -v "$req" > /dev/null; @@ -69,9 +69,10 @@ function check_installwim_gt4gib() { function create_partitions() { local mbrscript="- - 7 *" local gptscript="- - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 *" - local gptntfsscript="- 1MiB U *\n- - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 *" + local gptuefintfsscript="- 1MiB U *\n- - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 *" - if [[ "$1" == "dos" ]] || [[ "$1" == "gpt" ]] || [[ "$1" == "gptntfs" ]]; + if [[ "$1" == "dos" ]] || [[ "$1" == "gpt" ]] || [[ "$1" == "gptntfs" ]] \ + || [[ "$1" == "gpt+uefintfs" ]]; then if [[ "$1" == "dos" ]]; then @@ -83,7 +84,11 @@ function create_partitions() { elif [[ "$1" == "gptntfs" ]]; then - echo -e "$gptntfsscript" | sfdisk "$2" + echo -e "$gptscript" | sfdisk "$2" + + elif [[ "$1" == "gpt+uefintfs" ]]; + then + echo -e "$gptuefintfsscript" | sfdisk "$2" fi else echo "${bold} == create_partitions: INTERNAL ERROR ==${normal}" @@ -122,8 +127,23 @@ function write_uefintfs() { function extract_iso() { # $1 - isopath # $2 - destdir + # $3 - exclude install.wim extraction flag - 7z x "$1" -o"$2" + if [[ "$3" == "skipinstallwim" ]]; then + 7z x "$1" -o"$2" '-x!sources/install.wim' + else + 7z x "$1" -o"$2" + fi +} + +function split_wim() { + # $1 - isopath + # $2 - isomountpath + # $3 - destdir + + mount -o ro "$1" "$2" + wimsplit "$2/sources/install.wim" "$3/sources/install.swm" 3800 + umount "$2" } function extract_bootmgfw_from_installwim() { @@ -134,28 +154,47 @@ function extract_bootmgfw_from_installwim() { } function umount_rm_path() { - if [ -d "$1" ]; - then + if [ -d "$1" ]; then umount "$1" || true rm -r "$1" fi + + if [ -d "$2" ]; then + umount "$2" 2>/dev/null || true + rm -r "$2" + fi } function sigint_handler() { - umount_rm_path "$partpath" + umount_rm_path "$partpath" "$isomountpath" } if [[ ! "$3" ]]; then - echo "Windows 7/8/8.1/10 ISO to Flash Drive burning utility" - echo "WARNING: this program will delete all existing data on your drive!" + echo "${bold}Windows 7/8/8.1/10/11 ISO to Flash Drive burning utility" + echo "WARNING: this program will delete all existing data on your drive!${normal}" echo - echo "$(basename "$0")" " " + echo "$(basename "$0")" " " echo - echo "Use MBR mode for old computers with BIOS (without UEFI), or for UEFI legacy mode (CSM)." - echo "Use GPT mode for new UEFI computers." - echo "Use 'gptntfs' mode for custom ISO images with install.wim file greater than 4 GiB." - echo "NOTE: gptntfs does not support Secure Boot!" + echo "mbr mode: the most universal, RECOMMENDED method." + echo " This mode creates MBR partition table with FAT32 partition," + echo " installs BIOS and UEFI bootloaders, supports Secure Boot." + echo " install.wim file larger than 4 GiB will be split." + echo " Suitable for all computers (UEFI/CSM/BIOS)." + echo + echo "gpt mode: less universal mode, for modern (UEFI) computers." + echo " GPT+FAT32, UEFI only, supports Secure Boot." + echo + echo "gptntfs mode: all the same as 'gpt' but NTFS is used." + echo " GPT+NTFS, UEFI only, supports Secure Boot." + echo " Large install.wim file will not be split." + echo " NOTE: not all UEFI are compatible with this mode," + echo " NTFS driver should be present on the motherboard." + echo + echo "gpt+uefintfs mode: alternative hacky installation method, not recommended." + echo " This mode uses NTFS partition and third-party 'uefintfs' bootloader." + echo " GPT+NTFS(data)+FAT32(efi), UEFI only, NO Secure Boot support." + echo " Large install.wim file will not be split." echo echo "${bold} == Removable storage list ==${normal}" @@ -169,9 +208,6 @@ then isopath="$2" isolabel="" labeltype="$3" - uefimode= - [[ "$labeltype" == "gpt" ]] && uefimode=1 - [[ "$labeltype" == "gptntfs" ]] && uefimode=1 mountntfs_cmd="mount.ntfs-3g" if ! command -v "$mountntfs_cmd" > /dev/null; then @@ -188,10 +224,13 @@ then fi echo "${bold} == Working with ISO $isolabel ==${normal}" + skipinstallwim="" + splitinstallwim=1 partpath="$(mktemp -d /run/windows2usb.XXXXXXXXXX)" + isomountpath="$(mktemp -d /run/windows2usb-mount.XXXXXXXXXX)" trap sigint_handler INT EXIT - # MBR + # MBR FAT32 if [[ "$labeltype" == "mbr" ]]; then echo "${bold} == Creating new MBR-formatted partition table ==${normal}" @@ -200,44 +239,56 @@ then echo "${bold} == Waiting 3 seconds to settle new partition layout ==${normal}" sleep 3 - echo "${bold} == Creating NTFS partition ==${normal}" + echo "${bold} == Creating FAT partition ==${normal}" create_partitions "dos" "$dev" - mkfs.ntfs -L "$isolabel" -f "$(get_dev_partition_num "${dev}" "1")" + mkfs.vfat -n "${isolabel:0:11}" "$(get_dev_partition_num "${dev}" "1")" echo "${bold} == Writing bootloader ==${normal}" ms-sys -7 "${dev}" - ms-sys -n "$(get_dev_partition_num "${dev}" "1")" + ms-sys -e "$(get_dev_partition_num "${dev}" "1")" echo "${bold} == Mounting data partition ==${normal}" - "$mountntfs_cmd" "$(get_dev_partition_num "${dev}" "1")" "$partpath" + mount "$(get_dev_partition_num "${dev}" "1")" "$partpath" - # GPT + # GPT FAT32 elif [[ "$labeltype" == "gpt" ]]; then - if check_installwim_gt4gib "$isopath"; - then - echo "${bold} == ERROR: install.wim is greater than 4 GiB ==${normal}" - echo "${bold} == ERROR: Please use gptntfs mode ==${normal}" - echo "NOTE: gptntfs does not support Secure Boot!" - umount_rm_path "$partpath" - exit 103 - fi echo "${bold} == Creating new GPT-formatted partition table ==${normal}" format_drive "gpt" "$dev" echo "${bold} == Waiting 3 seconds to settle new partition layout ==${normal}" sleep 3 - echo "${bold} == Creating UEFI FAT partition ==${normal}" + echo "${bold} == Creating FAT partition ==${normal}" create_partitions "gpt" "$dev" mkfs.vfat -n "${isolabel:0:11}" "$(get_dev_partition_num "${dev}" "1")" echo "${bold} == Mounting data partition ==${normal}" mount "$(get_dev_partition_num "${dev}" "1")" "$partpath" - # GPT FAT32 + NTFS + # GPT NTFS elif [[ "$labeltype" == "gptntfs" ]]; then + splitinstallwim="" # do NOT split install.wim in this mode + + echo "${bold} == Creating new GPT-formatted partition table ==${normal}" + format_drive "gpt" "$dev" + + echo "${bold} == Waiting 3 seconds to settle new partition layout ==${normal}" + sleep 3 + + echo "${bold} == Creating Microsoft NTFS partition ==${normal}" + create_partitions "gptntfs" "$dev" + mkfs.ntfs -L "$isolabel" -f "$(get_dev_partition_num "${dev}" "1")" + + echo "${bold} == Mounting data partition ==${normal}" + "$mountntfs_cmd" "$(get_dev_partition_num "${dev}" "1")" "$partpath" + + # GPT FAT32 (UEFINTFS) + NTFS + elif [[ "$labeltype" == "gpt+uefintfs" ]]; + then + splitinstallwim="" # do NOT split install.wim in this mode + echo "${bold} == Creating new GPT-formatted partition table ==${normal}" format_drive "gpt" "$dev" @@ -245,7 +296,7 @@ then sleep 3 echo "${bold} == Creating UEFI FAT and Microsoft NTFS partitions ==${normal}" - create_partitions "gptntfs" "$dev" + create_partitions "gpt+uefintfs" "$dev" write_uefintfs "$(get_dev_partition_num "${dev}" "1")" mkfs.ntfs -L "$isolabel" -f "$(get_dev_partition_num "${dev}" "2")" @@ -253,24 +304,34 @@ then "$mountntfs_cmd" "$(get_dev_partition_num "${dev}" "2")" "$partpath" fi - echo "${bold} == Extracting files from ISO to the partition ==${normal}" - extract_iso "$isopath" "$partpath" - - if [[ "$uefimode" ]]; + if [[ "$splitinstallwim" ]] && check_installwim_gt4gib "$isopath"; then - if [ ! -f "$partpath/efi/boot/bootx64.efi" ] && \ - [ ! -f "$partpath/efi/boot/bootia32.efi" ]; - then - echo "${bold} == Extracting UEFI bootloader from install.wim ==${normal}" - mkdir -p "$partpath/efi/boot/" || true - extract_bootmgfw_from_installwim "$partpath/sources/install.wim" "$partpath/efi/boot/" - mv "$partpath/efi/boot/bootmgfw.efi" "$partpath/efi/boot/bootx64.efi" - cp "$partpath/efi/boot/bootx64.efi" "$partpath/efi/boot/bootia32.efi" - fi + echo "${bold} == NOTE: install.wim is greater than 4 GiB and will be split to fit FAT32 limit ==${normal}" + skipinstallwim="skipinstallwim" + fi + + echo "${bold} == Extracting files from ISO to the partition ==${normal}" + extract_iso "$isopath" "$partpath" "$skipinstallwim" + + if [[ "$skipinstallwim" ]]; then + split_wim "$isopath" "$isomountpath" "$partpath" + fi + + # If there's no .efi bootloader files inside the iso, + # extract them from install.wim + # This is true for older Windows 7 ISO files. + if [ ! -f "$partpath/efi/boot/bootx64.efi" ] && \ + [ ! -f "$partpath/efi/boot/bootia32.efi" ]; + then + echo "${bold} == Extracting UEFI bootloader from install.wim ==${normal}" + mkdir -p "$partpath/efi/boot/" || true + extract_bootmgfw_from_installwim "$partpath/sources/install.wim" "$partpath/efi/boot/" + mv "$partpath/efi/boot/bootmgfw.efi" "$partpath/efi/boot/bootx64.efi" + cp "$partpath/efi/boot/bootx64.efi" "$partpath/efi/boot/bootia32.efi" fi echo "${bold} == Unmounting partition ==${normal}" - umount_rm_path "$partpath" + umount_rm_path "$partpath" "$isomountpath" echo "${bold} == All done! ==${normal}" else