15 Commits
2 changed files with 120 additions and 18 deletions
+3
View File
@@ -21,6 +21,8 @@ Download latest [portable AppImage version](https://github.com/ValdikSS/windows2
The program prints removable storage list if no arguments supplied. The program prints removable storage list if no arguments supplied.
If you don't want to use AppImage, you'll need to install all dependencies and download [uefi-ntfs.img](https://github.com/pbatard/rufus/tree/master/res/uefi) from Rufus project.
### BIOS Boot ### BIOS Boot
BIOS Boot (Legacy Boot/UEFI-CSM) uses stock Windows 7 MBR and NTFS bootloader, courtesy of [ms-sys](http://ms-sys.sourceforge.net/) project. BIOS Boot (Legacy Boot/UEFI-CSM) uses stock Windows 7 MBR and NTFS bootloader, courtesy of [ms-sys](http://ms-sys.sourceforge.net/) project.
@@ -68,3 +70,4 @@ This script uses:
* **lsblk** and **sfdisk** from [util-linux](https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/) * **lsblk** and **sfdisk** from [util-linux](https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/)
* [**ms-sys**](http://ms-sys.sourceforge.net/) for native Windows 7 MBR and NTFS bootloaders * [**ms-sys**](http://ms-sys.sourceforge.net/) for native Windows 7 MBR and NTFS bootloaders
* [**p7zip**](https://www.7-zip.org/) for ISO extraction * [**p7zip**](https://www.7-zip.org/) for ISO extraction
* [**autofsync**](https://github.com/i-rinat/autofsync/) to prevent filesystem bufferbloat and properly show copying progress (AppImage only)
+117 -18
View File
@@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
set -e # errexit set -e # errexit
set -f # noglob set -f # noglob
set +o braceexpand # disable braceexpand set +o braceexpand # disable braceexpand
@@ -24,6 +24,20 @@ function check_requirements() {
done done
} }
function check_iso_and_device() {
if [ ! -f "$1" ]
then
echo "${bold} == ERROR: ISO file not found! ==${normal}"
exit 106
fi
if [ ! -b "$2" ]
then
echo "${bold} == ERROR: Device file not found! ==${normal}"
exit 107
fi
}
function list_removable_drives() { function list_removable_drives() {
lsblk -d -I 8 -o RM,NAME,SIZE,MODEL | \ lsblk -d -I 8 -o RM,NAME,SIZE,MODEL | \
awk '($1 == 1) {print "/dev/" substr($0, index($0, $2))}' awk '($1 == 1) {print "/dev/" substr($0, index($0, $2))}'
@@ -39,13 +53,17 @@ function format_drive() {
fi fi
} }
function get_iso_name() {
7z l "$1" | awk '/Comment = / {print $3; exit 0}'
}
function check_installwim_gt4gib() { function check_installwim_gt4gib() {
7z l "$1" | awk '($6 ~ /install.wim/) {if ($4 > 429496296) {exit 1}; exit}' 7z l "$1" | awk '($6 ~ /install.wim/) {if ($4 > 4294967296) {exit 0}; exit 1}'
} }
function create_partitions() { function create_partitions() {
local mbrscript="- - 7 *" local mbrscript="- - 7 *"
local gptscript="- - U *" local gptscript="- - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 *"
local gptntfsscript="- 1MiB U *\n- - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 *" local gptntfsscript="- 1MiB U *\n- - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 *"
if [[ "$1" == "dos" ]] || [[ "$1" == "gpt" ]] || [[ "$1" == "gptntfs" ]]; if [[ "$1" == "dos" ]] || [[ "$1" == "gpt" ]] || [[ "$1" == "gptntfs" ]];
@@ -68,8 +86,32 @@ function create_partitions() {
fi fi
} }
function get_dev_partition_num() {
# $1 - device
# $2 - partition number
if [ -b "${1}${2}" ];
then
echo "${1}${2}"
return
fi
if [ -b "${1}p${2}" ];
then
echo "${1}p${2}"
return
fi
echo "${bold} == get_dev_partition_num: INTERNAL ERROR ==${normal}"
exit 105
}
function write_uefintfs() { function write_uefintfs() {
cat "$dirpath/uefi-ntfs.img" > "$1" if [ -a "$dirpath/uefi-ntfs.img" ]; then
cat "$dirpath/uefi-ntfs.img" > "$1"
elif [ -a "/usr/share/windows2usb/uefi-ntfs.img" ]; then
cat "/usr/share/windows2usb/uefi-ntfs.img" > "$1"
fi
} }
function extract_iso() { function extract_iso() {
@@ -79,9 +121,19 @@ function extract_iso() {
7z x "$1" -o"$2" 7z x "$1" -o"$2"
} }
function extract_bootmgfw_from_installwim() {
# $1 - install.wim path
# $2 - destdir
7z e "$1" -o"$2" 1/Windows/Boot/EFI/bootmgfw.efi
}
function umount_rm_path() { function umount_rm_path() {
umount "$1" || true if [ -d "$1" ];
rm -r "$1" then
umount "$1" || true
rm -r "$1"
fi
} }
function sigint_handler() { function sigint_handler() {
@@ -91,6 +143,8 @@ function sigint_handler() {
if [[ ! "$3" ]]; if [[ ! "$3" ]];
then then
echo "Windows 7/8/8.1/10 ISO to Flash Drive burning utility" 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
echo "$(basename "$0")" "<device> <windows iso> <mbr/gpt/gptntfs>" echo "$(basename "$0")" "<device> <windows iso> <mbr/gpt/gptntfs>"
echo echo
echo "Use MBR mode for old computers with BIOS (without UEFI), or for UEFI legacy mode (CSM)." echo "Use MBR mode for old computers with BIOS (without UEFI), or for UEFI legacy mode (CSM)."
@@ -108,11 +162,29 @@ if [[ "$EUID" == "0" ]];
then then
dev="$1" dev="$1"
isopath="$2" isopath="$2"
isolabel=""
labeltype="$3" labeltype="$3"
partpath="$(mktemp -d /run/winiso-write.XXXXXXXXXX)" uefimode=
[[ "$labeltype" == "gpt" ]] && uefimode=1
[[ "$labeltype" == "gptntfs" ]] && uefimode=1
mountntfs_cmd="mount.ntfs-3g"
if ! command -v "$mountntfs_cmd" > /dev/null;
then
mountntfs_cmd="mount"
fi
check_requirements check_requirements
trap sigint_handler INT check_iso_and_device "$isopath" "$dev"
isolabel="$(get_iso_name "$isopath")"
if [ $? -ne 0 ]
then
isolabel=""
fi
echo "${bold} == Working with ISO $isolabel ==${normal}"
partpath="$(mktemp -d /run/windows2usb.XXXXXXXXXX)"
trap sigint_handler INT EXIT
# MBR # MBR
if [[ "$labeltype" == "mbr" ]]; if [[ "$labeltype" == "mbr" ]];
@@ -120,16 +192,19 @@ then
echo "${bold} == Creating new MBR-formatted partition table ==${normal}" echo "${bold} == Creating new MBR-formatted partition table ==${normal}"
format_drive "dos" "$dev" format_drive "dos" "$dev"
echo "${bold} == Waiting 3 seconds to settle new partition layout ==${normal}"
sleep 3
echo "${bold} == Creating NTFS partition ==${normal}" echo "${bold} == Creating NTFS partition ==${normal}"
create_partitions "dos" "$dev" create_partitions "dos" "$dev"
mkfs.ntfs -f "${dev}1" mkfs.ntfs -L "$isolabel" -f "$(get_dev_partition_num "${dev}" "1")"
echo "${bold} == Writing bootloader ==${normal}" echo "${bold} == Writing bootloader ==${normal}"
ms-sys -7 "${dev}" ms-sys -7 "${dev}"
ms-sys -n "${dev}1" ms-sys -n "$(get_dev_partition_num "${dev}" "1")"
echo "${bold} == Mounting data partition ==${normal}" echo "${bold} == Mounting data partition ==${normal}"
mount "${dev}1" "$partpath" "$mountntfs_cmd" "$(get_dev_partition_num "${dev}" "1")" "$partpath"
# GPT # GPT
elif [[ "$labeltype" == "gpt" ]]; elif [[ "$labeltype" == "gpt" ]];
@@ -138,18 +213,22 @@ then
then then
echo "${bold} == ERROR: install.wim is greater than 4 GiB ==${normal}" echo "${bold} == ERROR: install.wim is greater than 4 GiB ==${normal}"
echo "${bold} == ERROR: Please use gptntfs mode ==${normal}" echo "${bold} == ERROR: Please use gptntfs mode ==${normal}"
echo "NOTE: gptntfs does not support Secure Boot!"
umount_rm_path "$partpath" umount_rm_path "$partpath"
exit 103 exit 103
fi fi
echo "${bold} == Creating new GPT-formatted partition table ==${normal}" echo "${bold} == Creating new GPT-formatted partition table ==${normal}"
format_drive "gpt" "$dev" 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 UEFI FAT partition ==${normal}"
create_partitions "gpt" "$dev" create_partitions "gpt" "$dev"
mkfs.vfat "${dev}1" mkfs.vfat -n "${isolabel:0:11}" "$(get_dev_partition_num "${dev}" "1")"
echo "${bold} == Mounting data partition ==${normal}" echo "${bold} == Mounting data partition ==${normal}"
mount "${dev}1" "$partpath" mount "$(get_dev_partition_num "${dev}" "1")" "$partpath"
# GPT FAT32 + NTFS # GPT FAT32 + NTFS
elif [[ "$labeltype" == "gptntfs" ]]; elif [[ "$labeltype" == "gptntfs" ]];
@@ -157,18 +236,34 @@ then
echo "${bold} == Creating new GPT-formatted partition table ==${normal}" echo "${bold} == Creating new GPT-formatted partition table ==${normal}"
format_drive "gpt" "$dev" format_drive "gpt" "$dev"
echo "${bold} == Waiting 3 seconds to settle new partition layout ==${normal}"
sleep 3
echo "${bold} == Creating UEFI FAT and Microsoft NTFS partitions ==${normal}" echo "${bold} == Creating UEFI FAT and Microsoft NTFS partitions ==${normal}"
create_partitions "gptntfs" "$dev" create_partitions "gptntfs" "$dev"
write_uefintfs "${dev}1" write_uefintfs "$(get_dev_partition_num "${dev}" "1")"
mkfs.ntfs -f "${dev}2" mkfs.ntfs -L "$isolabel" -f "$(get_dev_partition_num "${dev}" "2")"
echo "${bold} == Mounting data partition ==${normal}" echo "${bold} == Mounting data partition ==${normal}"
mount "${dev}2" "$partpath" "$mountntfs_cmd" "$(get_dev_partition_num "${dev}" "2")" "$partpath"
fi fi
echo "${bold} == Extracting files from ISO to the partition ==${normal}" echo "${bold} == Extracting files from ISO to the partition ==${normal}"
extract_iso "$isopath" "$partpath" extract_iso "$isopath" "$partpath"
if [[ "$uefimode" ]];
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
fi
echo "${bold} == Unmounting partition ==${normal}" echo "${bold} == Unmounting partition ==${normal}"
umount_rm_path "$partpath" umount_rm_path "$partpath"
@@ -177,12 +272,16 @@ else
if [[ "$APPIMAGE" ]]; if [[ "$APPIMAGE" ]];
then then
scriptpath="$APPIMAGE" scriptpath="$APPIMAGE"
fi; fi
[ -f "$1" ] && PARAM1="$(readlink -f -- "$1")" || PARAM1="$1"
[ -f "$2" ] && PARAM2="$(readlink -f -- "$2")" || PARAM2="$2"
shift; shift;
privescs=(pkexec sudo) privescs=(pkexec sudo)
for privesc in ${privescs[*]}; do for privesc in ${privescs[*]}; do
if command -v "$privesc" > /dev/null; then if command -v "$privesc" > /dev/null; then
"$privesc" "$scriptpath" "$@" "$privesc" "$scriptpath" "$PARAM1" "$PARAM2" "$@"
exit exit
fi fi
done done