CrystalFetch/Extras/esd2iso.sh
2023-09-04 13:04:49 -07:00

302 lines
7.2 KiB
Bash
Executable file

#!/bin/sh
#
# w11arm_esd2iso - download and convert Microsoft ESD files for Windows 11 ARM to ISO
#
# Copyright (C) 2023 Paul Rockwell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA#
#
# Credit: Location and methods of obtaining Microsoft ESD distributions and
# Microsoft Product catalog from b0gdanw "ESD to ISO on macOS.txt" https://gist.github.com/b0gdanw/e36ea84828dbd19e03eff6158f1fc77c
#
versionID="4.0.2 (13-July-2023)"
version="w11arm_esd2iso ${versionID}\n"
verbosityLevel=0
awk="/usr/bin/awk"
genisoimage="$(command -v mkisofs)"
declare -a lTags
declare -a lDesc
usage() {
echo "Usage:\n"
echo "$0 [-v]"
echo "$0 [-Vh]"
echo "\nOptions:"
echo "\t-h\tPrint usage and exit"
echo "\t-v\tEnable verbose output"
echo "\t-V\tPrint program version and exit"
}
printVersion() {
echo $version
}
verboseOn() {
if (( verbosityLevel == 0 )); then
return 1
else
return 0
fi
}
extractEsd(){
local eFile
local eDir
local retVal
local esdImageCount
local bootWimFile
local installWimFile
local images
local imageIndex
local imageEdition
local beQuiet
eFile=$1
eDir=$2
beQuiet="--quiet"
bootWimFile=$eDir/sources/boot.wim
installWimFile=$eDir/sources/install.wim
images=("4" "5")
verboseOn && beQuiet=""
esdImageCount=$(wimlib-imagex info $eFile | $awk '/Image Count:/ {print $3}')
verboseOn && echo "[DEBUG] image count in ESD: $esdImageCount"
for (( i = 6; i <= esdImageCount; i++ )); do
images+=("$i")
done
#---------------
# Extract image 1 in the ESD to create the boot environment
#---------------
echo "\nApplying boot files to the image"
wimlib-imagex apply $eFile 1 $eDir $beQuiet 2>/dev/null
retVal=$?
if (( retVal != 0 )); then
echo "[ERROR] Extract of boot files failed"
return $retVal
fi
echo "Boot files successfully applied to image"
#---------------
# Create the boot.wim file that contains WinPE and Windows Setup
# Images 2 and 3 in the ESD contain these components
#
# Important: image 3 in the ESD must be marked as bootable when
# transferred to boot.wim or else the installer will fail
#---------------
echo "\nAdding WinPE and Windows Setup to the image"
wimlib-imagex export $eFile 2 $bootWimFile --compress=LZX --chunk-size 32K $beQuiet
retVal=$?
if (( retVal != 0 )); then
echo "[ERROR] Add of WinPE failed"
return $retVal
fi
wimlib-imagex export $eFile 3 $bootWimFile --compress=LZX --chunk-size 32K --boot $beQuiet
retVal=$?
if (( retVal != 0 )); then
echo "[ERROR] Add of Windows Setup failed"
return $retVal
fi
echo "WinPE and Windows Setup added successfully to image\n"
verboseOn && {
echo "[DEBUG] contents of $bootWimFile"
wimlib-imagex info $bootWimFile
}
#---------------
# Create the install.wim file that contains the files that Setup will install
# Images 4, 5, (and 6 if it exists) in the ESD contain these components
#---------------
for imageIndex in ${images[*]}; do
imageEdition="$(wimlib-imagex info $eFile $imageIndex | grep '^Description:' | sed 's/Description:[ \t]*//')"
echo "\nAdding $imageEdition to the image"
wimlib-imagex export $eFile $imageIndex $installWimFile --compress=LZMS --chunk-size 128K $beQuiet
retVal=$?
if (( retVal != 0 )); then
echo "[ERROR] Addition of $imageIndex to the image failed"
return $retVal
fi
echo "$imageEdition added successfully to the image"
done
echo "\nAll Windows editions added to image"
verboseOn && {
echo "[DEBUG] contents of $installWimFile"
wimlib-imagex info $installWimFile
}
return 0
}
buildIso(){
local iDir=$1
local iFile=$2
local iLabel=$3
local elToritoBootFile
iDir=$1
iFile=$2
if [ -e $iFile ]; then
echo "\t[INFO] File $iFile exists, removing it"
rm -rf $iFile
fi
elToritoBootFile=$iDir/efi/microsoft/boot/efisys.bin
#
# Create the ISO file
#
#$hdiutil makehybrid -o $iFile -iso -udf -hard-disk-boot -eltorito-boot $elToritoBootFile $iDir
"$genisoimage" -b "efi/microsoft/boot/efisys.bin" --no-emul-boot \
--udf -iso-level 3 --hide "*" -V "$iLabel" -o "$iFile" $iDir
return $?
}
#-------------------
#
# Start of program
#
#-------------------
#-------------------
#
# Process arguments
#
#-------------------
while getopts ":hr:vV" opt; do
case $opt in
h)
usage
exit 1
;;
v)
let verbosityLevel+=1
;;
V)
printVersion
exit 1
;;
:)
echo "[ERROR] Option -$OPTARG requires an argument"
usage
exit 1
;;
\?)
echo "[ERROR] Invalid option: -$OPTARG\n"
usage
exit 1
;;
esac
done
shift "$((OPTIND-1))"
printVersion
esdFile="$1"
isoFile="$2"
isoLabel="$3"
#-------------------
# Check number of arguments
# One argument is allowed when using the -r option for restart
# No arguments are allowed otherwise
#-------------------
if (( $# > 3 )); then
echo "[ERROR] Too many arguments"
usage
exit 1
fi
workingDir="$(mktemp -q -d ./esd2iso_temp.XXXXXX)"
if (( $? != 0 )); then
echo "[ERROR] Unable to create work directory, exiting"
exit 1
fi
#---------------
#
# extDir is the "extract directory" where we're going to extract the ESD
# and evenutally build the ISO from. It's a subdirectory of the working/temp directory
#
##---------------
extDir=$workingDir/ESD_ISO
mkdir $extDir
echo "\nStep 3: Building installation image from ESD distribution"
extractEsd $esdFile $extDir
retVal=$?
if (( retVal != 0 )); then
echo "[ERROR] Installation image build failed with error code $retVal"
echo "Work directory $workingDir was not deleted, use for debugging"
exit 1
fi
#---------------
# At this point we no longer need the ESD file as it's already extracted
# In order to reduce disk space reauirements, delete the ESD file unless we
# have set the environment variable keepDownloads
#---------------
if [[ "x${keepDownloads}" == "x" ]]; then
echo \n"ESD added successfully to installation image and is no longer needed.\nDeleting it to save disk space."
verboseOn && echo "Deleting ESD file ${esdFile}"
rm -rf ${esdFile}
retVal=$?
if (( retVal != 0 )); then
echo "[WARNING] Deletion of ESD file encountered a problem."
echo " The ISO build can continue, but will consume an addtional 5 GB of disk space."
else
echo "ESD file deleted successfully\n"
fi
else
verboseOn && echo "[DEBUG] keepDownloads is set - keeping ESD download"
fi
echo "\nStep 3 complete - installation image built"
echo "\nStep 4: Creating ISO $isoFile from the installation image\n"
buildIso $extDir $isoFile $isoLabel
retVal=$?
if (( retVal != 0 )); then
echo "[ERROR] ISO was NOT created"
echo "Working directory $workingDir was not deleted, use for debugging"
exit 1
fi
echo "Step 4 complete - ISO created"
echo "\nCleaning up work directory"
rm -rf $workingDir
echo "Done!"
exit 0