diff --git a/PortValhalla.code-workspace b/PortValhalla.code-workspace index e94c96fdb..d137a55d2 100644 --- a/PortValhalla.code-workspace +++ b/PortValhalla.code-workspace @@ -10,6 +10,10 @@ { "name": "archiso-valhalla", "path": "./archiso" + }, + { + "name": "winiso-valhalla", + "path": "./winiso" } ] } diff --git a/winiso/.env.template b/winiso/.env.template new file mode 100644 index 000000000..4a41de2c1 --- /dev/null +++ b/winiso/.env.template @@ -0,0 +1,2 @@ +# The path to the Windows 11 ISO image +WIN11_IMAGE_PATH= diff --git a/winiso/.gitignore b/winiso/.gitignore new file mode 100644 index 000000000..e8644cccd --- /dev/null +++ b/winiso/.gitignore @@ -0,0 +1,2 @@ +.env +build/ diff --git a/winiso/README.md b/winiso/README.md new file mode 100644 index 000000000..ad3f7c4b6 --- /dev/null +++ b/winiso/README.md @@ -0,0 +1,3 @@ +# winiso-valhalla + +A project for generating a Windows installation medium. \ No newline at end of file diff --git a/winiso/deploy.fish b/winiso/deploy.fish new file mode 100644 index 000000000..e6a628c93 --- /dev/null +++ b/winiso/deploy.fish @@ -0,0 +1,229 @@ +#!/bin/env fish +begin + set -l dir (status dirname) + source "$dir/lib/choose-disk.fish" + + set -q WIN11_IMAGE_PATH + or begin + echo "Please specify the Windows 11 ISO in the `WIN11_IMAGE_PATH` variable." + exit 1 + end + + set -l setupLabel "winiso-valhalla" + set -l buildDir "$(status dirname)/build" + set -l cacheDir ~/.cache/winiso-valhalla + set -l isoFile "$buildDir/winiso-valhalla.iso" + set -l winpe "$cacheDir/winpe.iso" + set -l winPath "/media/win" + set -l winpePath "/media/winpe" + set -l valhallaPath "/media/winiso-valhalla" + set -l bootPath "/media/boot" + set -l dataPath "/media/data" + set -l winpeOverlay (mktemp -d) + set -l winOverlay (mktemp -d) + set -l upperDir (mktemp -d) + set -l workDir (mktemp -d) + set -l editionField "Edition ID" + set -l wimFile "sources/install.wim" + + set -l files + + set -l fileDefinitions \ + drivers/network/intel \ + "https://dlcdnets.asus.com/pub/ASUS/mb/04LAN/DRV_LAN_Intel_I211_UWD_TP_W10_64_VER12151841_20190306R.zip?model=ROG%20ZENITH%20EXTREME%20ALPHA" \ + zip \ + . \ + \ + drivers/network/marvell \ + "https://dlcdnets.asus.com/pub/ASUS/mb/04LAN/DRV_LAN_Marvell_TP_TSD_W11_64_V3130_20211118R.zip?model=ROG%20ZENITH%20EXTREME%20ALPHA" \ + zip \ + ./x64 \ + \ + software/git \ + "https://github.com/git-for-windows/git/releases/download/v2.41.0.windows.1/PortableGit-2.41.0-64-bit.7z.exe" \ + exe \ + . \ + \ + software/pwsh \ + "https://github.com/PowerShell/PowerShell/releases/download/v7.3.7/PowerShell-7.3.7-win-x64.zip" \ + zip \ + . + + for i in (seq 1 4 (count $fileDefinitions)) + set -l entry $fileDefinitions[$i.."$(math "$i" + 3)"] + set -l name "$entry[1]" + set -l url "$entry[2]" + set -l type "$entry[3]" + set -l dir "$entry[4]" + set -l winPath "X:\\$(echo "$name" | sed "s/\//\\\\/g")" + set -l file "$cacheDir/$name.$type" + set -l target "$winpeOverlay/$name" + + set -a files \ + "$file" \ + "$dir" \ + "$name" \ + "$winPath" + + mkdir -p (dirname "$file") + + if [ ! -f "$file" ] + curl -L "$url" -o "$file" + end + + begin + set -l tempDir (mktemp -d) + + switch $type + case zip + unzip "$file" -d "$tempDir" + case exe + pushd "$tempDir" > /dev/null + 7z x "$file" + popd > /dev/null + end + + mkdir -p (dirname "$target") + cp -r "$tempDir/$dir" "$target" + rm -rf "$tempDir" + end + end + + set -l intel $files[1..4] + set -l marvell $files[5..8] + set -l git $files[9..12] + set -l pwsh $files[13..16] + + cp -r "$dir/winfs"/* "$winpeOverlay" + + begin + set -l startupFile "$winpeOverlay/Windows/System32/startnet.cmd" + mkdir -p (dirname "$startupFile") + + begin + set -l path + + for sw in git pwsh + set -a path $$sw[1][4] + end + + printf %s\n \ + "@echo off" \ + "echo Loading Drivers..." ( + string join ";" \ + "set PATH=%PATH%" \ + $path \ + "$git[4]\\bin" + ) \ + 'pwsh -file "X:\Scripts\Drivers.ps1"' \ + "echo Configuring Network..." \ + "wpeinit" \ + "echo Configuring keyboard layout..." \ + "wpeutil SetKeyboardLayout 0807:00000807" \ + "echo Disabling Energy Saving Mode..." \ + "powercfg /s 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c" \ + 'start pwsh -NoExit -ExecutionPolicy bypass -file "X:\Scripts\Startup.ps1"' + end | sudo tee "$startupFile" > /dev/null + end + + mkdir -p "$(dirname "$winpe")" + sudo mount --mkdir "$WIN11_IMAGE_PATH" "$winPath" + mkwinpeimg --iso --arch amd64 --overlay "$winpeOverlay" --windows-dir "$winPath" "$winpe" + rm -rf "$winpeOverlay" + sudo mount --mkdir "$winpe" "$winpePath" + + begin + echo "$wimFile" + end | rsync --files-from=/dev/stdin "$winPath" "$winOverlay" + + begin + set -l wimFile "$winOverlay/$wimFile" + + while [ ! (wiminfo "$wimFile" 1 | grep "^$editionField" | cut -d ":" -f2 | string trim) = "Professional" ] + sudo wimdelete --soft "$wimFile" 1 + end + + while wiminfo "$wimFile" 2 &> /dev/null + sudo wimdelete --soft "$wimFile" 2 + end + end + + sudo mount --mkdir -t overlay overlay -o lowerdir="$winOverlay":"$winpePath":"$winPath",upperdir="$upperDir",workdir="$workDir" "$valhallaPath" + + if [ -z "$_flag_usb" ] + mkisofs \ + -V "$setupLabel" \ + -no-emul-boot \ + -b "efi/microsoft/boot/efisys.bin" \ + -iso-level 4 \ + -udf \ + -joliet \ + -disable-deep-relocation \ + -omit-version-number \ + -relaxed-filenames \ + -output "$isoFile" \ + "$valhallaPath" + else + if [ ! -b "$WIN_DISK" ] + chooseDisk WIN_DISK + end + + sudo shred -vfzn 0 -s 512 "$WIN_DISK" + + begin + printf %s\n \ + o \ + n \ + "" \ + "" \ + "" \ + +2G \ + y \ + t \ + c \ + a \ + "" \ + \ + n \ + "" \ + "" \ + "" \ + "" \ + y \ + t \ + "" \ + 7 \ + \ + w + end | sudo fdisk "$WIN_DISK" + + begin + set -l disks + + while true + set disks (string split -n " " (bash -c "echo $WIN_DISK*")) + [ (count $disks) -ge 3 ] && break + end + + set -l bootDisk "$disks[2]" + set -l dataDisk "$disks[3]" + sudo mkfs.fat -F 32 -n "BOOT" "$bootDisk" + sudo mkfs.ntfs -fFL "$setupLabel" "$dataDisk" + sudo mount --mkdir "$bootDisk" "$bootPath" + sudo mount --mkdir "$dataDisk" "$dataPath" + sudo cp -r "$winpePath"/* "$bootPath" + + sudo cp -r "$valhallaPath"/* "$dataPath" + sudo cp -r "$valhallaPath/efi" "$bootPath" + + for path in "$valhallaPath" \ + "$winPath" \ + "$winpePath" \ + "$bootPath" \ + "$dataPath" + sudo umount -vf "$path" + sudo rm -rf "$path" + end + end + end +end diff --git a/winiso/deploy.sh b/winiso/deploy.sh new file mode 100755 index 000000000..8841a54ac --- /dev/null +++ b/winiso/deploy.sh @@ -0,0 +1,25 @@ +#!/bin/bash +WIN_DISK="${WIN_DISK}"; +workingDir="$(pwd)"; +pushd "${BASH_SOURCE%/*}" > /dev/null; +. "./.env" > /dev/null 2>&1; + +if [ ! -z "$WIN11_IMAGE_PATH" ] +then + WIN11_IMAGE_PATH="$(bash -c "realpath $WIN11_IMAGE_PATH")"; +fi; + +if [ ! -f "$WIN11_IMAGE_PATH" ] +then + if [ ! -f "./.env" ] + then + cp .env.template .env; + fi; + + echo "Please specify the path to the Windows 11 ISO image in your .env file located at:"; + realpath --relative-to "$workingDir" "$(realpath .env)"; +else + WIN11_IMAGE_PATH="$WIN11_IMAGE_PATH" fish ./deploy.fish; +fi; + +popd > /dev/null; diff --git a/winiso/lib/choose-disk.fish b/winiso/lib/choose-disk.fish new file mode 100644 index 000000000..5082db043 --- /dev/null +++ b/winiso/lib/choose-disk.fish @@ -0,0 +1,44 @@ +#!/bin/env fish +function chooseDisk -a result message + set -l disks + + lsblk -do NAME,SIZE,TYPE | while read disk + set -l diskInfo (string split -n " " $disk) + + if contains "$diskInfo[3]" "TYPE" "disk" + set -a disks "$diskInfo" + end + end + + set -l diskCount (count $disks) + set -l padding (math (string length "$diskCount") + 1) + + if [ "$diskCount" -gt 0 ] + while true + echo "$message" + set -l prefix + + for i in (seq "$diskCount") + if [ "$i" -eq 1 ] + set prefix "" + else + set prefix "$(math "$i" - 1):" + end + + printf "%"$padding"s %s\n" "$prefix" "$disks[$i]" + end + + read -lP "Your choice: " choice + + if [ "$choice" -ge 1 ] && [ "$choice" -le "$diskCount" ] + set -l disk (string split -n " " "$disks[$(math "$choice" + 1)]") + set -g "$result" "/dev/$disk[1]" + return + else + echo "The specified choice \"$choice\" is invalid!" >&2 + end + end + else + echo "No valid disk found!" >&2 + end +end diff --git a/winiso/winfs/Scripts/Drivers.ps1 b/winiso/winfs/Scripts/Drivers.ps1 new file mode 100644 index 000000000..2875e2440 --- /dev/null +++ b/winiso/winfs/Scripts/Drivers.ps1 @@ -0,0 +1,3 @@ +Get-ChildItem -Recurse X:\drivers "*.inf" | ForEach-Object { + drvload $_; +}; diff --git a/winiso/winfs/Scripts/Setup.ps1 b/winiso/winfs/Scripts/Setup.ps1 new file mode 100644 index 000000000..5f5416c46 --- /dev/null +++ b/winiso/winfs/Scripts/Setup.ps1 @@ -0,0 +1,6 @@ +$drives = & wmic volume get "DriveLetter,Label"; +$drive = $($($drives | Select-String -Pattern "winiso-valhalla") -split "\s+")[0]; + +Write-Warning "Attention: This program will completely wipe your current disk #1 and install Windows on it. Are you sure you want to do this?" +Read-Host -Prompt "Hit enter to continue or CTRL+C to abort" +& "$drive\setup.exe"; diff --git a/winiso/winfs/Scripts/Startup.ps1 b/winiso/winfs/Scripts/Startup.ps1 new file mode 100644 index 000000000..3a2cd8067 --- /dev/null +++ b/winiso/winfs/Scripts/Startup.ps1 @@ -0,0 +1,5 @@ +$null = $env:WIN_COMPUTER_NAME; +$null = $env:SETUP_SCRIPT_NAME; + +git clone https://git.nuth.ch/manuth/PortValhalla.git; +Set-Location PortValhalla;