From c7c70fe9b3d67052cec9ec4fef71eb3e488c3e9b Mon Sep 17 00:00:00 2001 From: Jack <31696646+myspaghetti@users.noreply.github.com> Date: Sat, 25 Jan 2020 15:43:58 +0200 Subject: [PATCH] turns out there's a much easier way to set NVRAM vars Removed NVRAM binary file creation. This simplifies things greatly. --- macos-guest-virtualbox.sh | 246 ++++++++------------------------------ 1 file changed, 51 insertions(+), 195 deletions(-) diff --git a/macos-guest-virtualbox.sh b/macos-guest-virtualbox.sh index c86abb8..1ff986c 100755 --- a/macos-guest-virtualbox.sh +++ b/macos-guest-virtualbox.sh @@ -2,10 +2,10 @@ # Semi-automatic installer of macOS on VirtualBox # (c) myspaghetti, licensed under GPL2.0 or higher # url: https://github.com/myspaghetti/macos-guest-virtualbox -# version 0.80.6 +# version 0.81.0 # Requirements: 40GB available storage on host -# Dependencies: bash >= 4.3, xxd, gzip, unzip, wget, dmg2img, +# Dependencies: bash >= 4.3, unzip, wget, dmg2img, # VirtualBox with Extension Pack >= 6.0 function set_variables() { @@ -43,7 +43,7 @@ ROM='%aa*%bbg%cc%dd' # ioreg -l -p IODeviceTree | grep \"system-id SYSTEM_UUID="aabbccddeeff00112233445566778899" # csrutil status -SYSTEM_INTEGRITY_PROTECTION='0x10' # '0x10' - enabled, '0x77' - disabled +SYSTEM_INTEGRITY_PROTECTION='10' # '10' - enabled, '77' - disabled # terminal text colors @@ -163,14 +163,12 @@ if [ -n "$(sw_vers 2>/dev/null)" ]; then fi fi -# check for xxd, gzip, unzip, coreutils, wget -if [ -z "$(echo "xxd" | xxd -p 2>/dev/null)" \ - -o -z "$(gzip --help 2>/dev/null)" \ - -o -z "$(unzip -hh 2>/dev/null)" \ +# check for unzip, coreutils, wget +if [ -z "$(unzip -hh 2>/dev/null)" \ -o -z "$(csplit --help 2>/dev/null)" \ -o -z "$(wget --version 2>/dev/null)" ]; then echo "Please make sure the following packages are installed:" - echo "coreutils gzip unzip xxd wget" + echo "coreutils unzip wget" echo "Please make sure the coreutils package is the GNU variant." exit fi @@ -438,65 +436,10 @@ if [[ ( ( "${vbox_version:0:1}" -lt 6 ) || ( "${vbox_version:0:1}" = 6 && "${vbo fi } -function create_nvram_files() { -print_dimly "stage: create_nvram_files" -# Each NVRAM file may contain multiple entries. -# Each entry contains a namesize, datasize, name, guid, attributes, and data. -# Each entry is immediately followed by a crc32 of the entry. -# The script creates each file with only one entry for easier editing. -# -# The hex strings are stripped by xxd, so they can -# look like "0xAB 0xCD" or "hAB hCD" or "AB CD" or "ABCD" or a mix of formats -# and have extraneous characters like spaces or minus signs. - -# Load the binary files into VirtualBox VM NVRAM with the builtin command dmpstore -# in the VM EFI Internal Shell, for example: -# dmpstore -all -l fs0:\system-id.bin -# -# DmpStore code is available at this URL: -# https://github.com/mdaniel/virtualbox-org-svn-vbox-trunk/blob/master/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c - -function generate_nvram_bin_file() { -# input: name data guid (three positional arguments, all required) -# output: function outputs nothing to stdout -# but writes a binary file to working directory - local namestring="${1}" # string of chars - local filename="${namestring}" - # represent string as string-of-hex-bytes, add null byte after every byte, - # terminate string with two null bytes - local name="$(for (( i=0; i<"${#namestring}"; i++ )); do printf -- "${namestring:${i}:1}" | xxd -p | tr -d '\n'; printf '00'; done; printf '0000' )" - # size of string in bytes, represented by eight hex digits, big-endian - local namesize="$(printf "%08x" $(( ${#name} / 2 )) )" - # flip four big-endian bytes byte-order to little-endian - local namesize="$(printf "${namesize}" | xxd -r -p | od -tx4 -N4 -An --endian=little)" - # strip string-of-hex-bytes representation of data of spaces, "x", "h", etc - local data="$(printf -- "${2}" | xxd -r -p | xxd -p)" - # size of data in bytes, represented by eight hex digits, big-endian - local datasize="$(printf "%08x" $(( ${#data} / 2 )) )" - # flip four big-endian bytes byte-order to little-endian - local datasize="$(printf "${datasize}" | xxd -r -p | od -tx4 -N4 -An --endian=little)" - # guid string-of-hex-bytes is five fields, 8+4+4+4+12 bytes long - # first three are little-endian, last two big-endian - # for example, 00112233-4455-6677-8899-AABBCCDDEEFF - # is stored as 33221100-5544-7766-8899-AABBCCDDEEFF - local g="$( printf -- "${3}" | xxd -r -p | xxd -p )" # strip spaces etc - local guid="${g:6:2} ${g:4:2} ${g:2:2} ${g:0:2} ${g:10:2} ${g:8:2} ${g:14:2} ${g:12:2} ${g:16:16}" - # attributes in four bytes little-endian - local attributes="07 00 00 00" - # the data structure - local entry="${namesize} ${datasize} ${name} ${guid} ${attributes} ${data}" - # calculate crc32 using gzip, flip crc32 bytes into big-endian - local crc32="$(printf "${entry}" | xxd -r -p | gzip -c | tail -c8 | od -tx4 -N4 -An --endian=big)" - # save binary data - printf -- "${entry} ${crc32}" | xxd -r -p - "${vmname}_${filename}.bin" -} - -# MLB -MLB_b16="$(printf -- "${MLB}" | xxd -p)" -generate_nvram_bin_file MLB "${MLB_b16}" "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14" - -# ROM -# Convert the mixed-ASCII-and-base16 ROM value +function create_macos_installation_files_viso() { +print_dimly "stage: create_macos_installation_files_viso" +echo "Creating EFI startup script" +# Convert the mixed-ASCII-and-base16 values # into an ASCII string that represents a base16 number. ROM_b16="$(for (( i=0; i<${#ROM}; )); do let j=i+1; if [ "${ROM:${i}:1}" == "%" ]; then @@ -506,40 +449,19 @@ ROM_b16="$(for (( i=0; i<${#ROM}; )); do let j=i+1; echo -n "${x}"; let i=i+1; fi; done)" -generate_nvram_bin_file ROM "${ROM_b16}" "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14" - -# system-id -generate_nvram_bin_file system-id "${SYSTEM_UUID}" "7C436110-AB2A-4BBB-A880-FE41995C9F82" - -# SIP / csr-active-config -generate_nvram_bin_file csr-active-config "${SYSTEM_INTEGRITY_PROTECTION}" "7C436110-AB2A-4BBB-A880-FE41995C9F82" -} - -function create_macos_installation_files_viso() { -print_dimly "stage: create_macos_installation_files_viso" -echo "Creating EFI startup script" -echo 'echo -off' > "startup.nsh" +echo 'echo -off +setvar MLB -guid 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14 -nv ="'"${MLB}"'" +setvar ROM -guid 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14 -nv ='"${ROM_b16}"' +setvar system-id -guid 7C436110-AB2A-4BBB-A880-FE41995C9F82 -nv ='"${SYSTEM_UUID^^}"' +setvar csr-active-config-guid 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14 -nv ='"${SYSTEM_INTEGRITY_PROTECTION}"' +'> "${vmname}_startup.nsh" if [[ ( "${vbox_version:0:1}" -lt 6 ) || ( "${vbox_version:0:1}" = 6 && "${vbox_version:2:1}" = 0 ) ]]; then echo 'load fs0:\EFI\driver\AppleImageLoader.efi load fs0:\EFI\driver\AppleUiSupport.efi load fs0:\EFI\driver\ApfsDriverLoader.efi -map -r' >> "startup.nsh" +map -r' >> "${vmname}_startup.nsh" fi -echo 'if exist "fs0:\EFI\NVRAM\MLB.bin" then - dmpstore -all -l fs0:\EFI\NVRAM\MLB.bin - dmpstore -all -l fs0:\EFI\NVRAM\ROM.bin - dmpstore -all -l fs0:\EFI\NVRAM\csr-active-config.bin - dmpstore -all -l fs0:\EFI\NVRAM\system-id.bin -endif -for %a run (1 5) - if exist "fs%a:\EFI\NVRAM\MLB.bin" then - dmpstore -all -l fs%a:\EFI\NVRAM\MLB.bin - dmpstore -all -l fs%a:\EFI\NVRAM\ROM.bin - dmpstore -all -l fs%a:\EFI\NVRAM\csr-active-config.bin - dmpstore -all -l fs%a:\EFI\NVRAM\system-id.bin - endif -endfor -for %a run (1 5) +echo 'for %a run (1 5) if exist "fs%a:\macOS Install Data\Locked Files\Boot Files\boot.efi" then "fs%a:\macOS Install Data\Locked Files\Boot Files\boot.efi" endif @@ -548,7 +470,7 @@ for %a run (1 5) if exist "fs%a:\System\Library\CoreServices\boot.efi" then "fs%a:\System\Library\CoreServices\boot.efi" endif -endfor' >> "startup.nsh" +endfor' >> "${vmname}_startup.nsh" echo "" echo "Creating VirtualBox 6 virtual ISO containing the" @@ -590,7 +512,7 @@ for filename in "ApfsDriverLoader.efi" "AppleImageLoader.efi" "AppleUiSupport.ef done # EFI startup script -echo "/startup.nsh=\"startup.nsh\"" >> "${macOS_release_name}_Installation_files.viso" +echo "/startup.nsh=\"${vmname}_startup.nsh\"" >> "${macOS_release_name}_Installation_files.viso" } @@ -939,9 +861,8 @@ send_keys kbstring='shutdown -h now' send_keys send_enter -printf 'Partitioning the optional assistive virtual disk and copying the optional -NVRAM files. Partitioning the target, the installer, and the assistive virtual -disks. Loading base system onto the installer virtual dis. Moving installation +printf 'Partitioning the target virtual disk and the installer virtual disk. +Loading base system onto the installer virtual disk. Moving installation files to installer virtual disk, updating InstallInfo.plist, and rebooting the virtual machine. @@ -962,82 +883,6 @@ echo "${macOS_release_name}_BaseSystem.vdi detached from the virtual machine" echo "and released from VirtualBox Manager." } - -function configure_nvram_parameters() { -print_dimly "stage: configure_nvram_parameters" -echo "Configuring the NVRAM is not required to run macOS." -echo "" -echo "The NVRAM parameter assignment can be edited at the top of the script." -echo "If the NVRAM parameters are set to the defaults, or if the virtual machine" -echo "is powered up, or if the BaseSystem.vdi is not available, the NVRAM" -echo "configuration will be skipped." - -if [[ ! ( "$( VBoxManage list runningvms )" =~ ^\""${vmname}" ) && ( -s "${macOS_release_name}_BaseSystem.vdi") && ! ( "${DmiBoardSerial}" = "NO_LOGIC_BOARD_SN" && "${MLB}" = "${DmiBoardSerial}" && "${ROM}" = '%aa*%bbg%cc%dd' && "${SYSTEM_UUID}" = "aabbccddeeff00112233445566778899" && "${SYSTEM_INTEGRITY_PROTECTION}" = '0x10' ) ]] -then - if [ -w "${vmname}_nvram_files.vdi" ]; then - echo "NVRAM files virtual disk image ready." - else - echo "Creating ${vmname} NVRAM files virtual disk image." - VBoxManage createmedium --size=100 \ - --filename "${vmname}_nvram_files.vdi" \ - --variant standard 2>/dev/tty - fi -print_dimly "The following stages are executed as part of configure_nvram_parameters:" - configure_vm - create_nvram_files - create_macos_installation_files_viso - echo "Attaching the base system disk image, the VISO," - echo "and the NVRAM files disk image to the virtual machine." - VBoxManage storagectl macOS --remove --name SATA >/dev/null 2>&1 - VBoxManage storagectl "${vmname}" --add sata --name SATA --hostiocache on >/dev/null 2>&1 - VBoxManage storageattach "${vmname}" --storagectl SATA --port 1 --hotpluggable on \ - --type hdd --nonrotational on --medium "${macOS_release_name}_BaseSystem.vdi" >/dev/null 2>&1 - VBoxManage storageattach "${vmname}" --storagectl SATA --port 2 \ - --type dvddrive --medium "${macOS_release_name}_Installation_files.viso" >/dev/null 2>&1 - VBoxManage storageattach "${vmname}" --storagectl SATA --port 0 --hotpluggable on \ - --type hdd --nonrotational on --medium "${vmname}_nvram_files.vdi" >/dev/null 2>&1 - - echo "Starting virtual machine ${vmname}. This should take a couple of minutes." - ( VBoxManage startvm "${vmname}" >/dev/null 2>&1 ) - prompt_lang_utils - prompt_terminal_ready - # Find the 104MB nvram files disk and partition as FAT32; not necesasry for installing macOS - kbstring='disks="$(diskutil list | grep -o "104[^ ]* MB *disk[0-9]$" | sort -gr | grep -o disk[0-9] )" && disks=(${disks[@]}) && '\ -'diskutil partitionDisk "/dev/${disks[0]}" 1 GPT FAT32 "NVRAMFILES" R && '\ -'mkdir -p "/Volumes/NVRAMFILES/EFI/NVRAM" && '\ -'cp "/Volumes/'"${macOS_release_name:0:5}-files"'/"*.bin "/Volumes/NVRAMFILES/EFI/NVRAM/" && '\ -'cp "/Volumes/'"${macOS_release_name:0:5}-files"'/"*.nsh "/Volumes/NVRAMFILES/" && '\ -'shutdown -h now' - send_keys - send_enter - -printf ' -'"${highlight_color}"'Please start the "'"${vmname}"'" virtual machine '"${warning_color}"'manually'"${highlight_color}"' and press Esc'"${default_color}"' -'"${highlight_color}"'immediately when the VirtualBox logo appears to enter the boot menu.'"${default_color}"' - -Choose "'"${highlight_color}"'Boot Manager'"${default_color}"'" and then "'"${highlight_color}"'EFI Internal Shell'"${default_color}"'". -The EFI shell startup script will run and update the virtual machine'"'"'s NVRAM -parameters. It is not necessary to allow macOS to continue booting after the -script has run. - -Power off the virtual machine then press enter to continue.' -clear_input_buffer_then_read - -else -printf ' -The following command can be used to create and transfer the NVRAM files to the -fully installed macOS VM at any time: - - '"${0} create_nvram_files create_macos_installation_files_viso"' - -Attach the VISO file to the VM and copy the bin files from the VISO to the -macOS boot EFI partition and run the EFI Internal Shell script. This is only -required if the NVRAM parameters are updated after the installation. Otherwise, -the current NVRAM files will already be present and the script does not need to -be run again.' -fi -} - function populate_macos_target() { print_dimly "stage: populate_macos_target" if [[ "$( VBoxManage list runningvms )" =~ ^\""${vmname}" ]]; then @@ -1058,8 +903,8 @@ prompt_lang_utils prompt_terminal_ready add_another_terminal echo "" -echo "The second open Terminal in the virtual machine copies EFI and NVRAM files" -echo "to the target EFI partition when the installer finishes preparing." +echo "The second open Terminal in the virtual machine copies EFI Internal Shell" +echo "files to the target EFI partition when the installer finishes preparing." # run script concurrently, catch SIGUSR1 when installer finishes preparing kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[0-9]$" | sort -gr | grep -o disk[0-9])"; '\ @@ -1068,10 +913,8 @@ kbstring='disks="$(diskutil list | grep -o "[0-9][^ ]* GB *disk[0-9]$" | sort -g 'mkdir -p "/Volumes/'"${vmname}"'/tmp/mount_efi" && '\ 'mount_msdos /dev/${disks[0]}s1 "/Volumes/'"${vmname}"'/tmp/mount_efi" && '\ 'mkdir -p "/Volumes/'"${vmname}"'/tmp/mount_efi/EFI/driver/" && '\ -'mkdir -p "/Volumes/'"${vmname}"'/tmp/mount_efi/EFI/NVRAM/" && '\ -'[ -a "/Volumes'"${macOS_release_name:0:5}-files"'/ApfsDriverLoader.efi" ] && cp "/Volumes/'"${macOS_release_name:0:5}-files"'/"*.efi "/Volumes/'"${vmname}"'/tmp/mount_efi/EFI/driver/" ; '\ -'cp "/Volumes/'"${macOS_release_name:0:5}-files"'/"*.bin "/Volumes/'"${vmname}"'/tmp/mount_efi/EFI/NVRAM/" && '\ 'cp "/Volumes/'"${macOS_release_name:0:5}-files"'/startup.nsh" "/Volumes/'"${vmname}"'/tmp/mount_efi/startup.nsh" && '\ +'[ -a "/Volumes'"${macOS_release_name:0:5}-files"'/ApfsDriverLoader.efi" ] && cp "/Volumes/'"${macOS_release_name:0:5}-files"'/"*.efi "/Volumes/'"${vmname}"'/tmp/mount_efi/EFI/driver/" ; '\ 'installer_pid=$(ps | grep startosinstall | cut -d '"'"' '"'"' -f 3) && '\ 'kill -SIGUSR1 ${installer_pid}' send_keys @@ -1106,7 +949,18 @@ if [[ ( "${vbox_version:0:1}" -lt 6 ) || ( "${vbox_version:0:1}" = 6 && "${vbox_ fi printf ' +'"${highlight_color}"'Using iMessage and other connected Apple apps:'"${default_color}"' +Set the EFI and NVRAM variables required for iMessage and other connected Apple +apps by powering up the virtual machine and immediately pressing Esc when the +VirtualBox logo appears. Either the boot menu or the EFI Internal Shell will +boot. From the boot menu, select "Boot Manager" then "EFI Internal Shell" and +allow the startup.nsh script to run. This occurs automatically on VirtualBox +versions 6.0 and lower, but is sometimes skipped with versions 6.1 and higher. + +Setting EFI and NVRAM variables is not required to run macOS. + '"${highlight_color}"'That'"'"'s it! Enjoy your virtual machine.'"${default_color}"'\n' + } function delete_temporary_files() { @@ -1130,8 +984,7 @@ printf 'The follwing files are safe to delete: "'"${macOS_release_name}_BaseSystem"*'" "'"${macOS_release_name}_Install"*'" "'"Install ${macOS_release_name}.vdi"'" - "'"${vmname}_"*".bin"'" - "'"startup.nsh"'"\n' + "'"${vmname}_startup.nsh"'"\n' if [ -w "ApfsDriverLoader.efi" ]; then printf ' "'"ApfsDriverLoader.efi"'" "'"Apple"*".efi"'" @@ -1150,8 +1003,7 @@ if [ "${delete,,}" == "y" ]; then "${macOS_release_name}_BaseSystem"* \ "${macOS_release_name}_Install"* \ "Install ${macOS_release_name}.vdi" \ - "${vmname}_"*".bin" \ - "startup.nsh" 2>/dev/null + "${vmname}_startup.nsh" 2>/dev/null rm "ApfsDriverLoader.efi" \ "Apple"*".efi" \ "AppleSupport-v2.0.4-RELEASE.zip" 2>/dev/null @@ -1170,15 +1022,20 @@ Add one or more stage titles to the command line to run the corresponding function. If the first argument is "stages" all others are ignored. Some examples: - "'"${0}"' populate_virtual_disks populate_installer_app" - -These stages might be useful by themselves if the VDI files and the VM are -already initialized. - "'"${0}"' configure_vm" This stage might be useful after copying an existing VM VDI to a different VirtualBox installation and having the script automatically configure the VM. + + "'"${0}"' configure_vm create_macos_installation_files_viso" + +These stages might be useful after editing the EFI and NVRAM parameters at the +top of the script. Using genuine or genuine-like parameters and applying them +allows using iMessage, iCloud, and other connected Apple services. +Apply the parameters by copying the "startup.nsh" file to the root of the +EFI partition and booting into the EFI Internal Shell by pressing Esc +immediately when the VirtualBox logo appears when powering up the VM. + Dependency-checking and variable-setting is always performed first, whether or not these stages are specified. @@ -1190,9 +1047,9 @@ Available stage titles: check_bash_version - configure_vm check_gnu_coreutils_prefix / populate_virtual_disks - set_variables | configure_nvram_parameters - welcome | populate_macos_target - check_dependencies | delete_temporary_files + set_variables | populate_macos_target + welcome | delete_temporary_files + check_dependencies | prompt_delete_existing_vm | create_vm | prepare_macos_installation_files | @@ -1220,7 +1077,6 @@ if [ -z "${1}" ]; then create_install_vdi configure_vm populate_virtual_disks - configure_nvram_parameters populate_macos_target delete_temporary_files else