From dfc0fd22ce3d219b9194b2b344810662e3068690 Mon Sep 17 00:00:00 2001 From: img2tab <31696646+img2tab@users.noreply.github.com> Date: Fri, 28 Jun 2019 18:11:04 +0300 Subject: [PATCH] implemented VISO for Catalina VISO file format support requires VirtualBox version 6 or higher --- macos-guest-virtualbox.sh | 460 +++++++++++++++++++++----------------- 1 file changed, 253 insertions(+), 207 deletions(-) diff --git a/macos-guest-virtualbox.sh b/macos-guest-virtualbox.sh index 6afd419..a2a3c59 100644 --- a/macos-guest-virtualbox.sh +++ b/macos-guest-virtualbox.sh @@ -2,17 +2,17 @@ # One-key semi-automatic installer of macOS on VirtualBox # (c) img2tab, licensed under GPL2.0 or higher # url: https://github.com/img2tab/macos-guest-virtualbox -# version 0.63.0 +# version 0.65.0 # Requirements: 37.5GB available storage on host -# Dependencies: bash>=4.0, unzip, wget, dmg2img, -# VirtualBox with Extension Pack >=5.2 +# Dependencies: bash >= 4.0, unzip, wget, dmg2img, +# VirtualBox with Extension Pack >= 6.0 # 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 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 resolution="1280x800" # VM display resolution serialnumber="NOTAVALIDSN0" # valid serial required for iCloud, iMessage. @@ -28,7 +28,7 @@ defaultcolor="\033[0m" function welcome() { 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. @@ -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 Apple serial number. macOS will work without it, but not Apple-connected apps. -The installation requires '${whiteonred}'37.5GB'${defaultcolor}' of available storage, -22GB for the virtual machine and 15.5GB for temporary installation files. +The installation requires '${whiteonred}'38GB'${defaultcolor}' of available storage, +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} read # custom settings prompt 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 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 resolution="'"${resolution}"'" # VM display resolution serialnumber="'"${serialnumber}"'" # valid serial required for iCloud, iMessage. @@ -70,7 +71,7 @@ read function check_dependencies() { # check if running on macOS 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 fi @@ -146,8 +147,18 @@ elif [[ "$(cat /proc/sys/kernel/osrelease 2>/dev/null)" =~ Microsoft ]]; then fi # everything else (not cygwin and not wsl) elif [ -z "$(VBoxManage -v 2>/dev/null)" ]; then - echo "Please make sure VirtualBox is installed, and that the path to the" - echo "VBoxManage executable is in the PATH variable." + echo "Please make sure VirtualBox version 6.0 or higher is installed," + 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 fi @@ -180,29 +191,52 @@ if [ -z "$(dmg2img -d 2>/dev/null)" ]; then 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 -echo "Searching Apple macOS Mojave 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' \ +echo "Downloading Apple macOS ${macOS_release_name} software update catalog" +wget "${sucatalog}" \ ${wgetargs} \ - --output-document='apple.sucatalog.tmp' -echo "Trying to find latest macOS InstallAssistant entry" -tac "apple.sucatalog.tmp" | csplit - '/InstallAssistantAuto.smd/+1' -f "applecatalog.tmp." -s -urlbase="$(tail -n 1 "applecatalog.tmp.00")" + --output-document="${macOS_release_name}.sucatalog.tmp" +echo "Trying to find latest macOS InstallAssistant download URL" +tac "${macOS_release_name}.sucatalog.tmp" | csplit - '/InstallAssistantAuto.smd/+1' -f "${macOS_release_name}.sucatalog.tmp." -s +urlbase="$(tail -n 1 "${macOS_release_name}.sucatalog.tmp.00")" urlbase="$(expr match "${urlbase}" '.*\(http://[^<]*/\)')" if [ -z "${urlbase}" ]; then printf "Couldn't find the download URL in the Apple catalog. Please report this issue on https://github.com/img2tab/macos-guest-virtualbox/issues or update the URL yourself from the catalog found -on https://gist.github.com/nuomi1/16133b89c2b38b7eb197 -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" +on https://gist.github.com/nuomi1/16133b89c2b38b7eb197\n" exit fi -echo "Found BaseSystem.dmg URL: ${urlbase}BaseSystem.dmg" +echo "Found download URL: ${urlbase}" } # Done with dependencies -# Prompt to delete existing virtual machine config: function prompt_delete_existing_vm() { if [ -n "$(VBoxManage showvminfo "${vmname}" 2>/dev/null)" ]; then printf '\n"'"${vmname}"'" virtual machine already exists. @@ -233,28 +267,87 @@ Error message: 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: function create_basesystem_vdi() { -if [ -r "BaseSystem.vdi" ]; then - echo "BaseSystem.vdi bootstrap virtual disk image ready." +if [ -r "${macOS_release_name}_BaseSystem.vdi" ]; then + echo "${macOS_release_name}_BaseSystem.vdi bootstrap virtual disk image ready." else echo "Downloading BaseSystem.dmg from swcdn.apple.com" wget "${urlbase}BaseSystem.dmg" \ ${wgetargs} \ - --output-document="BaseSystem.dmg" + --output-document="${macOS_release_name}_BaseSystem.dmg" if [ ! -s BaseSystem.dmg ]; then printf ${whiteonred}'Could not download BaseSystem.dmg'${defaultcolor}'.' exit fi echo "Downloaded BaseSystem.dmg. Converting to BaseSystem.img" 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 - dmg2img "BaseSystem.dmg" "BaseSystem.img" + dmg2img "${macOS_release_name}_BaseSystem.dmg" "BaseSystem.img" fi - VBoxManage convertfromraw --format VDI "BaseSystem.img" "BaseSystem.vdi" - if [ -s BaseSystem.vdi ]; then - rm "BaseSystem.dmg" "BaseSystem.img" 2>/dev/null + VBoxManage convertfromraw --format VDI "${macOS_release_name}_BaseSystem.img" "BaseSystem.vdi" + if [ -s "${macOS_release_name}_BaseSystem.vdi" ]; then + rm "${macOS_release_name}_BaseSystem.img" 2>/dev/null fi fi } @@ -264,7 +357,7 @@ function create_target_vdi() { if [ -w "${vmname}.vdi" ]; then echo "${vmname}.vdi target system virtual disk image ready." 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." exit else @@ -277,13 +370,13 @@ fi # Create the installation media virtual disk image: 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." else - echo "Creating ${vmname} installation media virtual disk image." + echo "Creating ${macOS_release_name} installation media virtual disk image." VBoxManage createmedium --size=12000 \ - --filename "Install ${vmname}.vdi" \ - --variant fixed 2>/dev/tty + --filename "Install ${macOS_release_name}.vdi" \ + --variant standard 2>/dev/tty fi } @@ -294,12 +387,13 @@ VBoxManage storagectl "${vmname}" --add sata --name SATA --hostiocache on VBoxManage storageattach "${vmname}" --storagectl SATA --port 0 \ --type hdd --nonrotational on --medium "${vmname}.vdi" 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 \ - --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() { VBoxManage modifyvm "${vmname}" --cpus "${cpucount}" --memory "${memorysize}" \ --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 declare -A ksc=( ["ESC"]="01 81" - ["1"]="02 82" - ["2"]="03 83" - ["3"]="04 84" - ["4"]="05 85" - ["5"]="06 86" - ["6"]="07 87" - ["7"]="08 88" - ["8"]="09 89" - ["9"]="0A 8A" - ["0"]="0B 8B" - ["-"]="0C 8C" - ["="]="0D 8D" + ["1"]="02 82" + ["2"]="03 83" + ["3"]="04 84" + ["4"]="05 85" + ["5"]="06 86" + ["6"]="07 87" + ["7"]="08 88" + ["8"]="09 89" + ["9"]="0A 8A" + ["0"]="0B 8B" + ["-"]="0C 8C" + ["="]="0D 8D" ["BKSP"]="0E 8E" ["TAB"]="0F 8F" - ["q"]="10 90" - ["w"]="11 91" - ["e"]="12 92" - ["r"]="13 93" - ["t"]="14 94" - ["y"]="15 95" - ["u"]="16 96" - ["i"]="17 97" - ["o"]="18 98" - ["p"]="19 99" - ["["]="1A 9A" - ["]"]="1B 9B" + ["q"]="10 90" + ["w"]="11 91" + ["e"]="12 92" + ["r"]="13 93" + ["t"]="14 94" + ["y"]="15 95" + ["u"]="16 96" + ["i"]="17 97" + ["o"]="18 98" + ["p"]="19 99" + ["["]="1A 9A" + ["]"]="1B 9B" ["ENTER"]="1C 9C" ["CTRLprs"]="1D" ["CTRLrls"]="9D" - ["a"]="1E 9E" - ["s"]="1F 9F" - ["d"]="20 A0" - ["f"]="21 A1" - ["g"]="22 A2" - ["h"]="23 A3" - ["j"]="24 A4" - ["k"]="25 A5" - ["l"]="26 A6" - [";"]="27 A7" - ["'"]="28 A8" - ['`']="29 A9" + ["a"]="1E 9E" + ["s"]="1F 9F" + ["d"]="20 A0" + ["f"]="21 A1" + ["g"]="22 A2" + ["h"]="23 A3" + ["j"]="24 A4" + ["k"]="25 A5" + ["l"]="26 A6" + [";"]="27 A7" + ["'"]="28 A8" + ['`']="29 A9" ["LSHIFTprs"]="2A" ["LSHIFTrls"]="AA" - ['\']="2B AB" - ["z"]="2C AC" - ["x"]="2D AD" - ["c"]="2E AE" - ["v"]="2F AF" - ["b"]="30 B0" - ["n"]="31 B1" - ["m"]="32 B2" - [","]="33 B3" - ["."]="34 B4" - ["/"]="35 B5" + ['\']="2B AB" + ["z"]="2C AC" + ["x"]="2D AD" + ["c"]="2E AE" + ["v"]="2F AF" + ["b"]="30 B0" + ["n"]="31 B1" + ["m"]="32 B2" + [","]="33 B3" + ["."]="34 B4" + ["/"]="35 B5" ["RSHIFTprs"]="36" ["RSHIFTrls"]="B6" ["ALTprs"]="38" @@ -462,50 +556,50 @@ declare -A ksc=( ) # 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 } # 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++ )); do c[i]=${kbstring:i:1}; echo -n ${ksc[${c[i]}]}" "; done) scancode="${scancode} ${ksc['ENTER']}" - clearinputbuffer + clear_input_buffer VBoxManage controlvm "${vmname}" keyboardputscancode ${scancode} } # read variable kbspecial and send keystrokes by name, # for example "CTRLprs c CTRLrls", and send to guest vm -function sendspecial() { +function send_special() { scancode="" for keypress in ${kbspecial}; do scancode="${scancode}${ksc[${keypress}]}"" " done - clearinputbuffer + clear_input_buffer VBoxManage controlvm "${vmname}" keyboardputscancode ${scancode} } -function sendenter() { +function send_enter() { kbspecial="ENTER" - sendspecial + send_special } - -function promptlangutils() { + +function prompt_lang_utils() { printf ${whiteonblack}' Press enter when the Language window is ready.'${defaultcolor} read -p "" - sendenter + send_enter printf ${whiteonblack}' Press enter when the macOS Utilities window is ready.'${defaultcolor} read -p "" kbspecial='CTRLprs F2 CTRLrls u ENTER t ENTER' - sendspecial + send_special } -function promptterminalready() { +function prompt_terminal_ready() { printf ${whiteonblack}' Press enter when the Terminal command prompt is ready.'${defaultcolor} read -p "" @@ -516,48 +610,42 @@ function populate_virtual_disks() { echo "Starting virtual machine ${vmname}. This should take a couple of minutes." VBoxManage startvm "${vmname}" 2>/dev/null -promptlangutils -promptterminalready +prompt_lang_utils +prompt_terminal_ready echo "" echo "Partitioning target virtual disk." # 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[@]})' -sendkeys +send_keys # partition largest disk as APFS kbstring='diskutil partitionDisk "/dev/${disks[0]}" 1 GPT APFS "'"${vmname}"'" R' -sendkeys -promptterminalready +send_keys +prompt_terminal_ready echo "" echo "Partitioning installer virtual disk." # partition second-largest disk as JHFS+ kbstring='diskutil partitionDisk "/dev/${disks[1]}" 1 GPT JHFS+ "Install" R' -sendkeys -promptterminalready -echo "" -echo "Downloading macOS Mojave 10.14 installer." +send_keys +prompt_terminal_ready -# 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 "Loading base system onto installer virtual disk" # Create secondary base system and shut down the virtual machine -kbstring='asr restore --source "/Volumes/'"${vmname}"'/BaseSystem.dmg" --target /Volumes/Install --erase --noprompt' -sendkeys +kbstring='asr restore --source "/Volumes/'"${macOS_installation_files_volume_id}"'/BaseSystem.dmg" --target /Volumes/Install --erase --noprompt' +send_keys -promptterminalready +prompt_terminal_ready kbstring='shutdown -h now' -sendkeys +send_keys printf ${whiteonblack}' -Shutting down virtual machine. +Shutting down the virtual machine. Press enter when the virtual machine shutdown is complete.'${defaultcolor} read -p "" 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." VBoxManage startvm "${vmname}" 2>/dev/null -promptlangutils -promptterminalready +prompt_lang_utils +prompt_terminal_ready echo "" echo "Moving installation files to installer virtual disk." 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}"' -sendkeys +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"' +send_keys -# Rename InstallESDDmg.pkg to InstallESD.dmg and update InstallInfo.plist -promptterminalready -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"' -sendkeys +# update InstallInfo.plist +prompt_terminal_ready +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"' +send_keys # reboot, because the installer does not work when the partition is remounted -promptterminalready +prompt_terminal_ready kbstring='shutdown -h now' -sendkeys +send_keys printf ${whiteonblack}' Shutting down virtual machine. Press enter when the virtual machine shutdown is complete.'${defaultcolor} @@ -596,116 +684,66 @@ read -p "" function start_the_installer_app() { VBoxManage startvm "${vmname}" 2>/dev/null -promptlangutils -promptterminalready +prompt_lang_utils +prompt_terminal_ready # Start the installer. -kbstring='cd "/Install macOS Mojave.app/Contents/Resources/"; ./startosinstall --volume "/Volumes/'"${vmname}"'"' -sendkeys +kbstring='app_path="$(ls -d /Install*.app)" && cd "/${app_path}/Contents/Resources/"; ./startosinstall --volume "/Volumes/'"${vmname}"'"' +send_keys printf ${whiteonblack}' Installer started. Please wait for the license prompt to appear at the bottom of the virtual machine terminal, then press enter here. This will accept the license on the virtual machine.'${defaultcolor} read -p "" kbspecial="A ENTER" -sendspecial +send_special echo "" echo "When the installer finishes preparing, the virtual machine will reboot" echo "into the base system, not the installer." } -function manually_install_efi_apfs_drivers { +function place_efi_apfs_drivers { printf ${whiteonblack}' After the VM boots, press enter when either the Language window'${defaultcolor}' '${whiteonblack}'or Utilities window is ready.'${defaultcolor} read -p "" -sendenter +send_enter printf ${whiteonblack}' Press enter when the macOS Utilities window is ready.'${defaultcolor} 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 kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[012]$" | sort -gr | grep -o disk[012])"; disks=(${disks[@]})' -sendkeys -promptterminalready +send_keys +prompt_terminal_ready echo "" echo "Copying open-source APFS drivers to 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/"' -sendkeys -promptterminalready +kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[012]$" | sort -gr | grep -o disk[012])"; disks=(${disks[@]})' +send_keys +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 "Creating EFI startup script that searches for boot.efi" -kbstring='cd "/Volumes/'"${vmname}"'/mount_efi/" && vim startup.nsh' -sendkeys +echo "Placing EFI startup script that searches for boot.efi on the EFI partition" +kbstring='cp "/Volumes/'"${macOS_installation_files_volume_id}"'/startup.nsh" "/Volumes/'"${vmname}"'/mount_efi/startup.nsh"' +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 printf ${whiteonblack}' Press enter when the terminal is ready.'${defaultcolor} read -p "" kbstring='shutdown -h now' -sendkeys +send_keys echo "" echo "Shutting down virtual machine." @@ -715,28 +753,32 @@ read -p "" # detach installer from virtual machine VBoxManage storageattach "${vmname}" --storagectl SATA --port 1 --medium none +VBoxManage storageattach "${vmname}" --storagectl SATA --port 3 --medium none } function boot_macos_and_clean_up() { echo "The VM will boot from the target virtual disk image." VBoxManage startvm "${vmname}" echo "" -echo "macOS Mojave 10.14 will now install and start up." +echo "macOS will now install and start up." echo "" # temporary files cleanup -VBoxManage closemedium "BaseSystem.vdi" -VBoxManage closemedium "Install ${vmname}.vdi" +VBoxManage closemedium "${macOS_release_name}_BaseSystem.vdi" +VBoxManage closemedium "Install ${macOS_release_name}.vdi" printf 'Temporary files are safe to delete. '${whiteonred}'Delete temporary files?'${defaultcolor} delete="" read -n 1 -p " [y/n] " delete 2>/dev/tty echo "" if [ "${delete,,}" == "y" ]; then - rm "BaseSystem.vdi" "Install ${vmname}.vdi" - rm "apple.sucatalog.tmp" "applecatalog.tmp.00" "applecatalog.tmp.01" + rm "${macOS_release_name}_"* \ + "Install ${macOS_release_name}.vdi" \ + "${macOS_release_name}.sucatalog"* \ + "ApfsDriverLoader.efi" "AppleImageLoader.efi" \ + "AppleSupport-v2.0.4-RELEASE.zip" "AppleUiSupport.efi" 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 through VirtualBox, and then the macOS system APFS container size may be @@ -767,6 +809,8 @@ Available stage titles: check_dependencies prompt_delete_existing_vm create_vm + prepare_macos_installation_files + create_macos_installation_files_viso create_basesystem_vdi create_target_vdi create_install_vdi @@ -775,8 +819,8 @@ Available stage titles: populate_virtual_disks prepare_the_installer_app start_the_installer_app - manually_install_efi_apfs_drivers - detach_installer_vdi + place_efi_apfs_drivers + detach_installer_vdi_and_viso boot_macos_and_clean_up ' } @@ -786,6 +830,8 @@ if [ -z "${1}" ]; then check_dependencies prompt_delete_existing_vm create_vm + prepare_macos_installation_files + create_macos_installation_files_viso create_basesystem_vdi create_target_vdi create_install_vdi @@ -794,8 +840,8 @@ if [ -z "${1}" ]; then populate_virtual_disks prepare_the_installer_app start_the_installer_app - manually_install_efi_apfs_drivers - detach_installer_vdi + place_efi_apfs_drivers + detach_installer_vdi_and_viso boot_macos_and_clean_up else if [ "${1}" != "stages" ]; then