implemented VISO for Catalina

VISO file format support requires VirtualBox version 6 or higher
This commit is contained in:
img2tab
2019-06-28 18:11:04 +03:00
committed by GitHub
parent e1041fd6b0
commit dfc0fd22ce
+253 -207
View File
@@ -2,17 +2,17 @@
# One-key semi-automatic installer of macOS on VirtualBox # One-key semi-automatic installer of macOS on VirtualBox
# (c) img2tab, licensed under GPL2.0 or higher # (c) img2tab, licensed under GPL2.0 or higher
# url: https://github.com/img2tab/macos-guest-virtualbox # url: https://github.com/img2tab/macos-guest-virtualbox
# version 0.63.0 # version 0.65.0
# Requirements: 37.5GB available storage on host # Requirements: 37.5GB available storage on host
# Dependencies: bash>=4.0, unzip, wget, dmg2img, # Dependencies: bash >= 4.0, unzip, wget, dmg2img,
# VirtualBox with Extension Pack >=5.2 # VirtualBox with Extension Pack >= 6.0
# Customize the installation by setting these variables: # Customize the installation by setting these variables:
vmname="macOS Mojave" # name of the VirtualBox virtual machine vmname="macOS" # name of the VirtualBox virtual machine
storagesize=22000 # VM disk image size in MB. minimum 22000 storagesize=22000 # VM disk image size in MB. minimum 22000
cpucount=2 # VM CPU cores, minimum 2 cpucount=2 # VM CPU cores, minimum 2
memorysize=4096 # VM RAM in MB, minimum 2048 memorysize=4096 # VM RAM in MB, minimum 2048
gpuvram=128 # VM video RAM in MB, minimum 34, maximum 128 gpuvram=128 # VM video RAM in MB, minimum 34, maximum 128
resolution="1280x800" # VM display resolution resolution="1280x800" # VM display resolution
serialnumber="NOTAVALIDSN0" # valid serial required for iCloud, iMessage. serialnumber="NOTAVALIDSN0" # valid serial required for iCloud, iMessage.
@@ -28,7 +28,7 @@ defaultcolor="\033[0m"
function welcome() { function welcome() {
printf ' printf '
One-key semi-automatic installation of macOS On VirtualBox - Mojave 10.14 Semi-automatic installer of macOS on VirtualBox
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
This script installs only open-source software and unmodified Apple binaries. This script installs only open-source software and unmodified Apple binaries.
@@ -40,18 +40,19 @@ Some stages may fail due to errant keyboard presses; run the script with
For iCloud and iMessage connectivity, you will need to provide a valid For iCloud and iMessage connectivity, you will need to provide a valid
Apple serial number. macOS will work without it, but not Apple-connected apps. Apple serial number. macOS will work without it, but not Apple-connected apps.
The installation requires '${whiteonred}'37.5GB'${defaultcolor}' of available storage, The installation requires '${whiteonred}'38GB'${defaultcolor}' of available storage,
22GB for the virtual machine and 15.5GB for temporary installation files. 24GB for temporary installation files and 14GB for the virtual machine. Deleting
the temporary files when prompted reduces the storage requirement by about 10GB.
'${whiteonblack}'Press enter to review the script settings.'${defaultcolor} '${whiteonblack}'Press enter to review the script settings.'${defaultcolor}
read read
# custom settings prompt # custom settings prompt
printf ' printf '
vmname="'"${vmname}"'" # name of the VirtualBox virtual machine vmname="'"${vmname}"'" # name of the VirtualBox virtual machine
storagesize='"${storagesize}"' # VM disk image size in MB. minimum 22000 storagesize='"${storagesize}"' # VM disk image size in MB. minimum 22000
cpucount='"${cpucount}"' # VM CPU cores, minimum 2 cpucount='"${cpucount}"' # VM CPU cores, minimum 2
memorysize='"${memorysize}"' # VM RAM in MB, minimum 2048 memorysize='"${memorysize}"' # VM RAM in MB, minimum 2048
gpuvram='"${gpuvram}"' # VM video RAM in MB, minimum 34, maximum 128 gpuvram='"${gpuvram}"' # VM video RAM in MB, minimum 34, maximum 128
resolution="'"${resolution}"'" # VM display resolution resolution="'"${resolution}"'" # VM display resolution
serialnumber="'"${serialnumber}"'" # valid serial required for iCloud, iMessage. serialnumber="'"${serialnumber}"'" # valid serial required for iCloud, iMessage.
@@ -70,7 +71,7 @@ read
function check_dependencies() { function check_dependencies() {
# check if running on macOS # check if running on macOS
if [ -n "$(sw_vers 2>/dev/null)" ]; then if [ -n "$(sw_vers 2>/dev/null)" ]; then
printf '\nThis script is not tested on macOS. Exiting.\n' printf '\nThis script is not tested on macOS hosts. Exiting.\n'
exit exit
fi fi
@@ -146,8 +147,18 @@ elif [[ "$(cat /proc/sys/kernel/osrelease 2>/dev/null)" =~ Microsoft ]]; then
fi fi
# everything else (not cygwin and not wsl) # everything else (not cygwin and not wsl)
elif [ -z "$(VBoxManage -v 2>/dev/null)" ]; then elif [ -z "$(VBoxManage -v 2>/dev/null)" ]; then
echo "Please make sure VirtualBox is installed, and that the path to the" echo "Please make sure VirtualBox version 6.0 or higher is installed,"
echo "VBoxManage executable is in the PATH variable." echo "and that the path to the VBoxManage executable is in the PATH variable."
exit
fi
# VirtualBox version
vbox_version="$(VBoxManage -v 2>/dev/null)"
if [ -z "${vbox_version}" ]; then
echo "Can't determine VirtualBox version. Exiting."
exit
elif [ "${vbox_version:0:1}" -lt 6 ]; then
echo "Please make sure VirtualBox version 6.0 or higher is installed."
exit exit
fi fi
@@ -180,29 +191,52 @@ if [ -z "$(dmg2img -d 2>/dev/null)" ]; then
fi fi
fi fi
# prompt for macOS version
HighSierra_sucatalog='https://swscan.apple.com/content/catalogs/others/index-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog'
Mojave_sucatalog='https://swscan.apple.com/content/catalogs/others/index-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog'
Catalina_beta_sucatalog='https://swscan.apple.com/content/catalogs/others/index-10.15beta-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog'
# Catalina public release not yet available
# Catalina_sucatalog='https://swscan.apple.com/content/catalogs/others/index-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog'
printf "${whiteonblack}"'
Press a key to select the macOS version to install on the virtual machine:'"${defaultcolor}"'
[H]igh Sierra (10.13)
[M]ojave (10.14)
[C]atalina (10.15 beta)
'
read -n 1 -p " [H/M/C] " macOS_release_name 2>/dev/tty
echo ""
if [ "${macOS_release_name^^}" == "H" ]; then
macOS_release_name="HighSierra"
sucatalog="${HighSierra_sucatalog}"
elif [ "${macOS_release_name^^}" == "M" ]; then
macOS_release_name="Mojave"
sucatalog="${Mojave_sucatalog}"
else
macOS_release_name="Catalina"
sucatalog="${Catalina_beta_sucatalog}"
fi
# Find the correct download URL in the Apple catalog # Find the correct download URL in the Apple catalog
echo "Searching Apple macOS Mojave software update catalog" echo "Downloading Apple macOS ${macOS_release_name} software update catalog"
wget 'http://swscan.apple.com/content/catalogs/others/index-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog' \ wget "${sucatalog}" \
${wgetargs} \ ${wgetargs} \
--output-document='apple.sucatalog.tmp' --output-document="${macOS_release_name}.sucatalog.tmp"
echo "Trying to find latest macOS InstallAssistant entry" echo "Trying to find latest macOS InstallAssistant download URL"
tac "apple.sucatalog.tmp" | csplit - '/InstallAssistantAuto.smd/+1' -f "applecatalog.tmp." -s tac "${macOS_release_name}.sucatalog.tmp" | csplit - '/InstallAssistantAuto.smd/+1' -f "${macOS_release_name}.sucatalog.tmp." -s
urlbase="$(tail -n 1 "applecatalog.tmp.00")" urlbase="$(tail -n 1 "${macOS_release_name}.sucatalog.tmp.00")"
urlbase="$(expr match "${urlbase}" '.*\(http://[^<]*/\)')" urlbase="$(expr match "${urlbase}" '.*\(http://[^<]*/\)')"
if [ -z "${urlbase}" ]; then if [ -z "${urlbase}" ]; then
printf "Couldn't find the download URL in the Apple catalog. Please report this issue printf "Couldn't find the download URL in the Apple catalog. Please report this issue
on https://github.com/img2tab/macos-guest-virtualbox/issues on https://github.com/img2tab/macos-guest-virtualbox/issues
or update the URL yourself from the catalog found or update the URL yourself from the catalog found
on https://gist.github.com/nuomi1/16133b89c2b38b7eb197 on https://gist.github.com/nuomi1/16133b89c2b38b7eb197\n"
or http://swscan.apple.com/content/catalogs/others/
index-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog\n"
exit exit
fi fi
echo "Found BaseSystem.dmg URL: ${urlbase}BaseSystem.dmg" echo "Found download URL: ${urlbase}"
} }
# Done with dependencies # Done with dependencies
# Prompt to delete existing virtual machine config:
function prompt_delete_existing_vm() { function prompt_delete_existing_vm() {
if [ -n "$(VBoxManage showvminfo "${vmname}" 2>/dev/null)" ]; then if [ -n "$(VBoxManage showvminfo "${vmname}" 2>/dev/null)" ]; then
printf '\n"'"${vmname}"'" virtual machine already exists. printf '\n"'"${vmname}"'" virtual machine already exists.
@@ -233,28 +267,87 @@ Error message:
fi fi
} }
function prepare_macos_installation_files() {
echo ""
echo "Downloading macOS installation files from swcdn.apple.com"
for filename in "BaseSystem.chunklist" \
"InstallInfo.plist" \
"AppleDiagnostics.dmg" \
"AppleDiagnostics.chunklist" \
"BaseSystem.dmg" \
"InstallESDDmg.pkg"; \
do wget "${urlbase}${filename}" \
${wgetargs} --limit-rate=2000k \
--output-document "${macOS_release_name}_${filename}"
done
echo ""
echo "Downloading open-source APFS EFI drivers"
wget 'https://github.com/acidanthera/AppleSupportPkg/releases/download/2.0.4/AppleSupport-v2.0.4-RELEASE.zip' \
${wgetargs} \
--output-document 'AppleSupport-v2.0.4-RELEASE.zip'
unzip -oj 'AppleSupport-v2.0.4-RELEASE.zip'
echo ""
echo "Creating EFI startup script"
echo 'echo -off
load fs0:\EFI\driver\AppleImageLoader.efi
load fs0:\EFI\driver\AppleUiSupport.efi
load fs0:\EFI\driver\ApfsDriverLoader.efi
map -r
for %a run (1 5)
fs%a:
cd "macOS Install Data\Locked Files\Boot Files"
boot.efi
cd "System\Library\CoreServices"
boot.efi
endfor' > "startup.nsh"
}
function create_macos_installation_files_viso() {
macOS_installation_files_volume_id="swcdn-files"
echo "Crating VirtualBox 6 virtual ISO file with installation files from swcdn.apple.com"
echo ""
echo "Splitting InstallESDDmg.pkg into 1GB parts because VirtualBox hasn't"
echo "implemented UDF/HFS VISO support yet and macOS doesn't support ISO 9660 Level 3"
split -a 2 -d -b 1000000000 "${macOS_release_name}_InstallESDDmg.pkg" "${macOS_release_name}_InstallESD.part"
echo "--iprt-iso-maker-file-marker-bourne-sh 57c0ec7d-2112-4c24-a93f-32e6f08702b9
--volume-id=${macOS_installation_files_volume_id}
/AppleDiagnostics.chunklist=${macOS_release_name}_AppleDiagnostics.chunklist
/AppleDiagnostics.dmg=${macOS_release_name}_AppleDiagnostics.dmg
/BaseSystem.chunklist=${macOS_release_name}_BaseSystem.chunklist
/BaseSystem.dmg=${macOS_release_name}_BaseSystem.dmg
/InstallInfo.plist=${macOS_release_name}_InstallInfo.plist
/ApfsDriverLoader.efi=ApfsDriverLoader.efi
/AppleImageLoader.efi=AppleImageLoader.efi
/AppleUiSupport.efi=AppleUiSupport.efi
/startup.nsh=startup.nsh" > "${macOS_release_name}_installation_files.viso"
for part in "${macOS_release_name}_InstallESD.part"*; do
echo "/InstallESD${part##*InstallESD}=${part}" >> "${macOS_release_name}_installation_files.viso"
done
}
# Create the macOS base system virtual disk image: # Create the macOS base system virtual disk image:
function create_basesystem_vdi() { function create_basesystem_vdi() {
if [ -r "BaseSystem.vdi" ]; then if [ -r "${macOS_release_name}_BaseSystem.vdi" ]; then
echo "BaseSystem.vdi bootstrap virtual disk image ready." echo "${macOS_release_name}_BaseSystem.vdi bootstrap virtual disk image ready."
else else
echo "Downloading BaseSystem.dmg from swcdn.apple.com" echo "Downloading BaseSystem.dmg from swcdn.apple.com"
wget "${urlbase}BaseSystem.dmg" \ wget "${urlbase}BaseSystem.dmg" \
${wgetargs} \ ${wgetargs} \
--output-document="BaseSystem.dmg" --output-document="${macOS_release_name}_BaseSystem.dmg"
if [ ! -s BaseSystem.dmg ]; then if [ ! -s BaseSystem.dmg ]; then
printf ${whiteonred}'Could not download BaseSystem.dmg'${defaultcolor}'.' printf ${whiteonred}'Could not download BaseSystem.dmg'${defaultcolor}'.'
exit exit
fi fi
echo "Downloaded BaseSystem.dmg. Converting to BaseSystem.img" echo "Downloaded BaseSystem.dmg. Converting to BaseSystem.img"
if [ -n "$("${PWD}/dmg2img.exe" -d 2>/dev/null)" ]; then if [ -n "$("${PWD}/dmg2img.exe" -d 2>/dev/null)" ]; then
"${PWD}/dmg2img.exe" "BaseSystem.dmg" "BaseSystem.img" "${PWD}/dmg2img.exe" "${macOS_release_name}_BaseSystem.dmg" "BaseSystem.img"
else else
dmg2img "BaseSystem.dmg" "BaseSystem.img" dmg2img "${macOS_release_name}_BaseSystem.dmg" "BaseSystem.img"
fi fi
VBoxManage convertfromraw --format VDI "BaseSystem.img" "BaseSystem.vdi" VBoxManage convertfromraw --format VDI "${macOS_release_name}_BaseSystem.img" "BaseSystem.vdi"
if [ -s BaseSystem.vdi ]; then if [ -s "${macOS_release_name}_BaseSystem.vdi" ]; then
rm "BaseSystem.dmg" "BaseSystem.img" 2>/dev/null rm "${macOS_release_name}_BaseSystem.img" 2>/dev/null
fi fi
fi fi
} }
@@ -264,7 +357,7 @@ function create_target_vdi() {
if [ -w "${vmname}.vdi" ]; then if [ -w "${vmname}.vdi" ]; then
echo "${vmname}.vdi target system virtual disk image ready." echo "${vmname}.vdi target system virtual disk image ready."
elif [ "${storagesize}" -lt 22000 ]; then elif [ "${storagesize}" -lt 22000 ]; then
echo "Attempting to install macOS Mojave on a disk smaller than 22000MB will fail." echo "Attempting to install macOS on a disk smaller than 22000MB will fail."
echo "Please assign a larger virtual disk image size." echo "Please assign a larger virtual disk image size."
exit exit
else else
@@ -277,13 +370,13 @@ fi
# Create the installation media virtual disk image: # Create the installation media virtual disk image:
function create_install_vdi() { function create_install_vdi() {
if [ -w "Install ${vmname}.vdi" ]; then if [ -w "Install ${macOS_release_name}.vdi" ]; then
echo "Installation media virtual disk image ready." echo "Installation media virtual disk image ready."
else else
echo "Creating ${vmname} installation media virtual disk image." echo "Creating ${macOS_release_name} installation media virtual disk image."
VBoxManage createmedium --size=12000 \ VBoxManage createmedium --size=12000 \
--filename "Install ${vmname}.vdi" \ --filename "Install ${macOS_release_name}.vdi" \
--variant fixed 2>/dev/tty --variant standard 2>/dev/tty
fi fi
} }
@@ -294,12 +387,13 @@ VBoxManage storagectl "${vmname}" --add sata --name SATA --hostiocache on
VBoxManage storageattach "${vmname}" --storagectl SATA --port 0 \ VBoxManage storageattach "${vmname}" --storagectl SATA --port 0 \
--type hdd --nonrotational on --medium "${vmname}.vdi" --type hdd --nonrotational on --medium "${vmname}.vdi"
VBoxManage storageattach "${vmname}" --storagectl SATA --port 1 \ VBoxManage storageattach "${vmname}" --storagectl SATA --port 1 \
--type hdd --nonrotational on --medium "Install ${vmname}.vdi" --type hdd --nonrotational on --medium "Install ${macOS_release_name}.vdi"
VBoxManage storageattach "${vmname}" --storagectl SATA --port 2 \ VBoxManage storageattach "${vmname}" --storagectl SATA --port 2 \
--type hdd --nonrotational on --medium "BaseSystem.vdi" --type hdd --nonrotational on --medium "${macOS_release_name}_BaseSystem.vdi"
VBoxManage storageattach "${vmname}" --storagectl SATA --port 3 \
--type dvddrive --medium "${macOS_release_name}_installation_files.viso"
} }
# Configure the VM
function configure_vm() { function configure_vm() {
VBoxManage modifyvm "${vmname}" --cpus "${cpucount}" --memory "${memorysize}" \ VBoxManage modifyvm "${vmname}" --cpus "${cpucount}" --memory "${memorysize}" \
--vram "${gpuvram}" --pae on --boot1 dvd --boot2 disk --boot3 none \ --vram "${gpuvram}" --pae on --boot1 dvd --boot2 disk --boot3 none \
@@ -328,60 +422,60 @@ VBoxManage setextradata "${vmname}" \
# First half of hex code - press, second half - release, unless otherwise specified # First half of hex code - press, second half - release, unless otherwise specified
declare -A ksc=( declare -A ksc=(
["ESC"]="01 81" ["ESC"]="01 81"
["1"]="02 82" ["1"]="02 82"
["2"]="03 83" ["2"]="03 83"
["3"]="04 84" ["3"]="04 84"
["4"]="05 85" ["4"]="05 85"
["5"]="06 86" ["5"]="06 86"
["6"]="07 87" ["6"]="07 87"
["7"]="08 88" ["7"]="08 88"
["8"]="09 89" ["8"]="09 89"
["9"]="0A 8A" ["9"]="0A 8A"
["0"]="0B 8B" ["0"]="0B 8B"
["-"]="0C 8C" ["-"]="0C 8C"
["="]="0D 8D" ["="]="0D 8D"
["BKSP"]="0E 8E" ["BKSP"]="0E 8E"
["TAB"]="0F 8F" ["TAB"]="0F 8F"
["q"]="10 90" ["q"]="10 90"
["w"]="11 91" ["w"]="11 91"
["e"]="12 92" ["e"]="12 92"
["r"]="13 93" ["r"]="13 93"
["t"]="14 94" ["t"]="14 94"
["y"]="15 95" ["y"]="15 95"
["u"]="16 96" ["u"]="16 96"
["i"]="17 97" ["i"]="17 97"
["o"]="18 98" ["o"]="18 98"
["p"]="19 99" ["p"]="19 99"
["["]="1A 9A" ["["]="1A 9A"
["]"]="1B 9B" ["]"]="1B 9B"
["ENTER"]="1C 9C" ["ENTER"]="1C 9C"
["CTRLprs"]="1D" ["CTRLprs"]="1D"
["CTRLrls"]="9D" ["CTRLrls"]="9D"
["a"]="1E 9E" ["a"]="1E 9E"
["s"]="1F 9F" ["s"]="1F 9F"
["d"]="20 A0" ["d"]="20 A0"
["f"]="21 A1" ["f"]="21 A1"
["g"]="22 A2" ["g"]="22 A2"
["h"]="23 A3" ["h"]="23 A3"
["j"]="24 A4" ["j"]="24 A4"
["k"]="25 A5" ["k"]="25 A5"
["l"]="26 A6" ["l"]="26 A6"
[";"]="27 A7" [";"]="27 A7"
["'"]="28 A8" ["'"]="28 A8"
['`']="29 A9" ['`']="29 A9"
["LSHIFTprs"]="2A" ["LSHIFTprs"]="2A"
["LSHIFTrls"]="AA" ["LSHIFTrls"]="AA"
['\']="2B AB" ['\']="2B AB"
["z"]="2C AC" ["z"]="2C AC"
["x"]="2D AD" ["x"]="2D AD"
["c"]="2E AE" ["c"]="2E AE"
["v"]="2F AF" ["v"]="2F AF"
["b"]="30 B0" ["b"]="30 B0"
["n"]="31 B1" ["n"]="31 B1"
["m"]="32 B2" ["m"]="32 B2"
[","]="33 B3" [","]="33 B3"
["."]="34 B4" ["."]="34 B4"
["/"]="35 B5" ["/"]="35 B5"
["RSHIFTprs"]="36" ["RSHIFTprs"]="36"
["RSHIFTrls"]="B6" ["RSHIFTrls"]="B6"
["ALTprs"]="38" ["ALTprs"]="38"
@@ -462,50 +556,50 @@ declare -A ksc=(
) )
# hacky way to clear input buffer before sending scancodes # hacky way to clear input buffer before sending scancodes
function clearinputbuffer() { function clear_input_buffer() {
while read -d '' -r -t 0; do read -d '' -t 0.1 -n 10000; break; done while read -d '' -r -t 0; do read -d '' -t 0.1 -n 10000; break; done
} }
# read variable kbstring and convert string to scancodes and send to guest vm # read variable kbstring and convert string to scancodes and send to guest vm
function sendkeys() { function send_keys() {
scancode=$(for (( i=0; i < ${#kbstring}; i++ )); scancode=$(for (( i=0; i < ${#kbstring}; i++ ));
do c[i]=${kbstring:i:1}; echo -n ${ksc[${c[i]}]}" "; done) do c[i]=${kbstring:i:1}; echo -n ${ksc[${c[i]}]}" "; done)
scancode="${scancode} ${ksc['ENTER']}" scancode="${scancode} ${ksc['ENTER']}"
clearinputbuffer clear_input_buffer
VBoxManage controlvm "${vmname}" keyboardputscancode ${scancode} VBoxManage controlvm "${vmname}" keyboardputscancode ${scancode}
} }
# read variable kbspecial and send keystrokes by name, # read variable kbspecial and send keystrokes by name,
# for example "CTRLprs c CTRLrls", and send to guest vm # for example "CTRLprs c CTRLrls", and send to guest vm
function sendspecial() { function send_special() {
scancode="" scancode=""
for keypress in ${kbspecial}; do for keypress in ${kbspecial}; do
scancode="${scancode}${ksc[${keypress}]}"" " scancode="${scancode}${ksc[${keypress}]}"" "
done done
clearinputbuffer clear_input_buffer
VBoxManage controlvm "${vmname}" keyboardputscancode ${scancode} VBoxManage controlvm "${vmname}" keyboardputscancode ${scancode}
} }
function sendenter() { function send_enter() {
kbspecial="ENTER" kbspecial="ENTER"
sendspecial send_special
} }
function promptlangutils() { function prompt_lang_utils() {
printf ${whiteonblack}' printf ${whiteonblack}'
Press enter when the Language window is ready.'${defaultcolor} Press enter when the Language window is ready.'${defaultcolor}
read -p "" read -p ""
sendenter send_enter
printf ${whiteonblack}' printf ${whiteonblack}'
Press enter when the macOS Utilities window is ready.'${defaultcolor} Press enter when the macOS Utilities window is ready.'${defaultcolor}
read -p "" read -p ""
kbspecial='CTRLprs F2 CTRLrls u ENTER t ENTER' kbspecial='CTRLprs F2 CTRLrls u ENTER t ENTER'
sendspecial send_special
} }
function promptterminalready() { function prompt_terminal_ready() {
printf ${whiteonblack}' printf ${whiteonblack}'
Press enter when the Terminal command prompt is ready.'${defaultcolor} Press enter when the Terminal command prompt is ready.'${defaultcolor}
read -p "" read -p ""
@@ -516,48 +610,42 @@ function populate_virtual_disks() {
echo "Starting virtual machine ${vmname}. This should take a couple of minutes." echo "Starting virtual machine ${vmname}. This should take a couple of minutes."
VBoxManage startvm "${vmname}" 2>/dev/null VBoxManage startvm "${vmname}" 2>/dev/null
promptlangutils prompt_lang_utils
promptterminalready prompt_terminal_ready
echo "" echo ""
echo "Partitioning target virtual disk." echo "Partitioning target virtual disk."
# get "physical" disks from largest to smallest # get "physical" disks from largest to smallest
kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[012]$" | sort -gr | grep -o disk[012])"; disks=(${disks[@]})' kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[012]$" | sort -gr | grep -o disk[012])"; disks=(${disks[@]})'
sendkeys send_keys
# partition largest disk as APFS # partition largest disk as APFS
kbstring='diskutil partitionDisk "/dev/${disks[0]}" 1 GPT APFS "'"${vmname}"'" R' kbstring='diskutil partitionDisk "/dev/${disks[0]}" 1 GPT APFS "'"${vmname}"'" R'
sendkeys send_keys
promptterminalready prompt_terminal_ready
echo "" echo ""
echo "Partitioning installer virtual disk." echo "Partitioning installer virtual disk."
# partition second-largest disk as JHFS+ # partition second-largest disk as JHFS+
kbstring='diskutil partitionDisk "/dev/${disks[1]}" 1 GPT JHFS+ "Install" R' kbstring='diskutil partitionDisk "/dev/${disks[1]}" 1 GPT JHFS+ "Install" R'
sendkeys send_keys
promptterminalready prompt_terminal_ready
echo ""
echo "Downloading macOS Mojave 10.14 installer."
# downloading macOS
kbstring='urlbase="'"${urlbase}"'"; for filename in BaseSystem.chunklist InstallInfo.plist AppleDiagnostics.dmg AppleDiagnostics.chunklist BaseSystem.dmg InstallESDDmg.pkg; do curl -C - "${urlbase}${filename}" -o "/Volumes/'"${vmname}"'/${filename}"; done'
sendkeys
promptterminalready
echo "" echo ""
echo "Loading base system onto installer virtual disk" echo "Loading base system onto installer virtual disk"
# Create secondary base system and shut down the virtual machine # Create secondary base system and shut down the virtual machine
kbstring='asr restore --source "/Volumes/'"${vmname}"'/BaseSystem.dmg" --target /Volumes/Install --erase --noprompt' kbstring='asr restore --source "/Volumes/'"${macOS_installation_files_volume_id}"'/BaseSystem.dmg" --target /Volumes/Install --erase --noprompt'
sendkeys send_keys
promptterminalready prompt_terminal_ready
kbstring='shutdown -h now' kbstring='shutdown -h now'
sendkeys send_keys
printf ${whiteonblack}' printf ${whiteonblack}'
Shutting down virtual machine. Shutting down the virtual machine.
Press enter when the virtual machine shutdown is complete.'${defaultcolor} Press enter when the virtual machine shutdown is complete.'${defaultcolor}
read -p "" read -p ""
echo "" echo ""
@@ -571,23 +659,23 @@ function prepare_the_installer_app() {
echo "The VM will boot from the new base system on the installer virtual disk." echo "The VM will boot from the new base system on the installer virtual disk."
VBoxManage startvm "${vmname}" 2>/dev/null VBoxManage startvm "${vmname}" 2>/dev/null
promptlangutils prompt_lang_utils
promptterminalready prompt_terminal_ready
echo "" echo ""
echo "Moving installation files to installer virtual disk." echo "Moving installation files to installer virtual disk."
echo "The virtual machine may report that disk space is critically low; this is fine." echo "The virtual machine may report that disk space is critically low; this is fine."
kbstring='mount -rw / && installpath="/Install macOS Mojave.app/Contents/SharedSupport/" && mkdir -p "${installpath}" && cd "/Volumes/'"${vmname}/"'" && mv *.chunklist *.plist *.dmg *.pkg "${installpath}"' kbstring='app_path="$(ls -d /Install*.app)" && mount -rw / && install_path="${app_path}/Contents/SharedSupport/" && mkdir -p "${install_path}" && cd "/Volumes/'"${macOS_installation_files_volume_id}/"'" && cp *.chunklist *.plist *.dmg "${install_path}" && cat InstallESD.part* > "${install_path}/InstallESD.dmg"'
sendkeys send_keys
# Rename InstallESDDmg.pkg to InstallESD.dmg and update InstallInfo.plist # update InstallInfo.plist
promptterminalready prompt_terminal_ready
kbstring='mv "${installpath}InstallESDDmg.pkg" "${installpath}InstallESD.dmg" && sed -i.bak -e "s/InstallESDDmg\.pkg/InstallESD.dmg/" -e "s/pkg\.InstallESDDmg/dmg.InstallESD/" "${installpath}InstallInfo.plist" && sed -i.bak2 -e "/InstallESD\.dmg/{n;N;N;N;d;}" "${installpath}InstallInfo.plist"' kbstring='sed -i.bak -e "s/InstallESDDmg\.pkg/InstallESD.dmg/" -e "s/pkg\.InstallESDDmg/dmg.InstallESD/" "${install_path}InstallInfo.plist" && sed -i.bak2 -e "/InstallESD\.dmg/{n;N;N;N;d;}" "${install_path}InstallInfo.plist"'
sendkeys send_keys
# reboot, because the installer does not work when the partition is remounted # reboot, because the installer does not work when the partition is remounted
promptterminalready prompt_terminal_ready
kbstring='shutdown -h now' kbstring='shutdown -h now'
sendkeys send_keys
printf ${whiteonblack}' printf ${whiteonblack}'
Shutting down virtual machine. Shutting down virtual machine.
Press enter when the virtual machine shutdown is complete.'${defaultcolor} Press enter when the virtual machine shutdown is complete.'${defaultcolor}
@@ -596,116 +684,66 @@ read -p ""
function start_the_installer_app() { function start_the_installer_app() {
VBoxManage startvm "${vmname}" 2>/dev/null VBoxManage startvm "${vmname}" 2>/dev/null
promptlangutils prompt_lang_utils
promptterminalready prompt_terminal_ready
# Start the installer. # Start the installer.
kbstring='cd "/Install macOS Mojave.app/Contents/Resources/"; ./startosinstall --volume "/Volumes/'"${vmname}"'"' kbstring='app_path="$(ls -d /Install*.app)" && cd "/${app_path}/Contents/Resources/"; ./startosinstall --volume "/Volumes/'"${vmname}"'"'
sendkeys send_keys
printf ${whiteonblack}' printf ${whiteonblack}'
Installer started. Please wait for the license prompt to appear at Installer started. Please wait for the license prompt to appear at
the bottom of the virtual machine terminal, then press enter here. the bottom of the virtual machine terminal, then press enter here.
This will accept the license on the virtual machine.'${defaultcolor} This will accept the license on the virtual machine.'${defaultcolor}
read -p "" read -p ""
kbspecial="A ENTER" kbspecial="A ENTER"
sendspecial send_special
echo "" echo ""
echo "When the installer finishes preparing, the virtual machine will reboot" echo "When the installer finishes preparing, the virtual machine will reboot"
echo "into the base system, not the installer." echo "into the base system, not the installer."
} }
function manually_install_efi_apfs_drivers { function place_efi_apfs_drivers {
printf ${whiteonblack}' printf ${whiteonblack}'
After the VM boots, press enter when either the Language window'${defaultcolor}' After the VM boots, press enter when either the Language window'${defaultcolor}'
'${whiteonblack}'or Utilities window is ready.'${defaultcolor} '${whiteonblack}'or Utilities window is ready.'${defaultcolor}
read -p "" read -p ""
sendenter send_enter
printf ${whiteonblack}' printf ${whiteonblack}'
Press enter when the macOS Utilities window is ready.'${defaultcolor} Press enter when the macOS Utilities window is ready.'${defaultcolor}
read -p "" read -p ""
# Start Safari (Get Help Online)
kbspecial="UP UP UP UP DOWN DOWN TAB SPACE"
sendspecial
printf ${whiteonblack}'
Press enter when Safari is ready.'${defaultcolor}
read -p ""
# Browse the web!
kbspecial="CMDprs l CMDrls"
sendspecial
kbstring="https://github.com/acidanthera/AppleSupportPkg/releases/tag/2.0.4"
sendkeys
echo ""
printf 'Safari should be browsing the following URL:
https://github.com/acidanthera/AppleSupportPkg/releases/tag/2.0.4
In the VM, '${whiteonred}'manually'${defaultcolor}' right-click on AppleSupport-v2.0.4-RELEASE.zip
and click '${whiteonblack}'"Download Linked File As..."'${defaultcolor}', then from the dropdown menu
select "'"${vmname}"'" for "Where:", then unbind the mouse cursor from
the virtual machine with the '${whiteonblack}'right control key'${defaultcolor}' or "host key".'
echo ""
read -p "Click here and press enter when the download is complete."
kbspecial="CMDprs q CMDrls"
sendspecial
printf ${whiteonblack}'
Press enter when the macOS Utilities window is ready.'${defaultcolor}
read -p ""
kbspecial="CTRLprs F2 CTRLrls u ENTER t ENTER"
sendspecial
promptterminalready
# find largest drive # find largest drive
kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[012]$" | sort -gr | grep -o disk[012])"; disks=(${disks[@]})' kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[012]$" | sort -gr | grep -o disk[012])"; disks=(${disks[@]})'
sendkeys send_keys
promptterminalready prompt_terminal_ready
echo "" echo ""
echo "Copying open-source APFS drivers to EFI partition" echo "Copying open-source APFS drivers to EFI partition"
# move drivers into path on EFI partition # move drivers into path on EFI partition
kbstring='mkdir -p "/Volumes/'"${vmname}"'/mount_efi" && mount_msdos /dev/${disks[0]}s1 "/Volumes/'"${vmname}"'/mount_efi" && mkdir -p "/Volumes/'"${vmname}"'/mount_efi/EFI/driver/" && cd "/Volumes/'"${vmname}"'/mount_efi/EFI/driver/" && tar -xf "/Volumes/'"${vmname}"'/AppleSupport-v2.0.4-RELEASE.zip" && cd "Drivers/" && mv *.efi "/Volumes/'"${vmname}"'/mount_efi/EFI/driver/"' kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[012]$" | sort -gr | grep -o disk[012])"; disks=(${disks[@]})'
sendkeys send_keys
promptterminalready kbstring='mkdir -p "/Volumes/'"${vmname}"'/mount_efi" && mount_msdos /dev/${disks[0]}s1 "/Volumes/'"${vmname}"'/mount_efi" && mkdir -p "/Volumes/'"${vmname}"'/mount_efi/EFI/driver/" && cp "/Volumes/'"${macOS_installation_files_volume_id}"'/"*.efi "/Volumes/'"${vmname}"'/mount_efi/EFI/driver/"'
send_keys
prompt_terminal_ready
# create startup.nsh EFI script # place startup.nsh EFI script
echo "" echo ""
echo "Creating EFI startup script that searches for boot.efi" echo "Placing EFI startup script that searches for boot.efi on the EFI partition"
kbstring='cd "/Volumes/'"${vmname}"'/mount_efi/" && vim startup.nsh' kbstring='cp "/Volumes/'"${macOS_installation_files_volume_id}"'/startup.nsh" "/Volumes/'"${vmname}"'/mount_efi/startup.nsh"'
sendkeys send_keys
printf ${whiteonblack}'
Press enter when '${defaultcolor}'"startup.nsh" [New File]'${whiteonblack}' appears
at the bottom of the terminal.'${defaultcolor}
read -p ""
kbstring='Iecho -off'; sendkeys
kbstring='load fs0:\EFI\driver\AppleImageLoader.efi'; sendkeys
kbstring='load fs0:\EFI\driver\AppleUiSupport.efi'; sendkeys
kbstring='load fs0:\EFI\driver\ApfsDriverLoader.efi'; sendkeys
kbstring='map -r'; sendkeys
kbstring='for %a run (1 5)'; sendkeys
kbstring=' fs%a:'; sendkeys
kbstring=' cd "macOS Install Data\Locked Files\Boot Files"'; sendkeys
kbstring=' boot.efi'; sendkeys
kbstring=' cd "System\Library\CoreServices"'; sendkeys
kbstring=' boot.efi'; sendkeys
kbstring='endfor'; sendkeys
kbspecial="ESC : w q ENTER"; sendspecial
} }
function detach_installer_vdi() { function detach_installer_vdi_and_viso() {
# Shut down the virtual machine # Shut down the virtual machine
printf ${whiteonblack}' printf ${whiteonblack}'
Press enter when the terminal is ready.'${defaultcolor} Press enter when the terminal is ready.'${defaultcolor}
read -p "" read -p ""
kbstring='shutdown -h now' kbstring='shutdown -h now'
sendkeys send_keys
echo "" echo ""
echo "Shutting down virtual machine." echo "Shutting down virtual machine."
@@ -715,28 +753,32 @@ read -p ""
# detach installer from virtual machine # detach installer from virtual machine
VBoxManage storageattach "${vmname}" --storagectl SATA --port 1 --medium none VBoxManage storageattach "${vmname}" --storagectl SATA --port 1 --medium none
VBoxManage storageattach "${vmname}" --storagectl SATA --port 3 --medium none
} }
function boot_macos_and_clean_up() { function boot_macos_and_clean_up() {
echo "The VM will boot from the target virtual disk image." echo "The VM will boot from the target virtual disk image."
VBoxManage startvm "${vmname}" VBoxManage startvm "${vmname}"
echo "" echo ""
echo "macOS Mojave 10.14 will now install and start up." echo "macOS will now install and start up."
echo "" echo ""
# temporary files cleanup # temporary files cleanup
VBoxManage closemedium "BaseSystem.vdi" VBoxManage closemedium "${macOS_release_name}_BaseSystem.vdi"
VBoxManage closemedium "Install ${vmname}.vdi" VBoxManage closemedium "Install ${macOS_release_name}.vdi"
printf 'Temporary files are safe to delete. '${whiteonred}'Delete temporary files?'${defaultcolor} printf 'Temporary files are safe to delete. '${whiteonred}'Delete temporary files?'${defaultcolor}
delete="" delete=""
read -n 1 -p " [y/n] " delete 2>/dev/tty read -n 1 -p " [y/n] " delete 2>/dev/tty
echo "" echo ""
if [ "${delete,,}" == "y" ]; then if [ "${delete,,}" == "y" ]; then
rm "BaseSystem.vdi" "Install ${vmname}.vdi" rm "${macOS_release_name}_"* \
rm "apple.sucatalog.tmp" "applecatalog.tmp.00" "applecatalog.tmp.01" "Install ${macOS_release_name}.vdi" \
"${macOS_release_name}.sucatalog"* \
"ApfsDriverLoader.efi" "AppleImageLoader.efi" \
"AppleSupport-v2.0.4-RELEASE.zip" "AppleUiSupport.efi"
fi fi
printf 'macOS Mojave 10.14 installation should complete in a few minutes. printf 'macOS installation should complete in a few minutes.
After the installation is complete, the virtual disk image may be increased After the installation is complete, the virtual disk image may be increased
through VirtualBox, and then the macOS system APFS container size may be through VirtualBox, and then the macOS system APFS container size may be
@@ -767,6 +809,8 @@ Available stage titles:
check_dependencies check_dependencies
prompt_delete_existing_vm prompt_delete_existing_vm
create_vm create_vm
prepare_macos_installation_files
create_macos_installation_files_viso
create_basesystem_vdi create_basesystem_vdi
create_target_vdi create_target_vdi
create_install_vdi create_install_vdi
@@ -775,8 +819,8 @@ Available stage titles:
populate_virtual_disks populate_virtual_disks
prepare_the_installer_app prepare_the_installer_app
start_the_installer_app start_the_installer_app
manually_install_efi_apfs_drivers place_efi_apfs_drivers
detach_installer_vdi detach_installer_vdi_and_viso
boot_macos_and_clean_up boot_macos_and_clean_up
' '
} }
@@ -786,6 +830,8 @@ if [ -z "${1}" ]; then
check_dependencies check_dependencies
prompt_delete_existing_vm prompt_delete_existing_vm
create_vm create_vm
prepare_macos_installation_files
create_macos_installation_files_viso
create_basesystem_vdi create_basesystem_vdi
create_target_vdi create_target_vdi
create_install_vdi create_install_vdi
@@ -794,8 +840,8 @@ if [ -z "${1}" ]; then
populate_virtual_disks populate_virtual_disks
prepare_the_installer_app prepare_the_installer_app
start_the_installer_app start_the_installer_app
manually_install_efi_apfs_drivers place_efi_apfs_drivers
detach_installer_vdi detach_installer_vdi_and_viso
boot_macos_and_clean_up boot_macos_and_clean_up
else else
if [ "${1}" != "stages" ]; then if [ "${1}" != "stages" ]; then