[
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "README.md",
    "content": "\n![macOS inside a VirtualBox window with the dock positioned on the left](https://repository-images.githubusercontent.com/156108442/c501b100-0e5a-11eb-8b49-90afd63f5d03 \"macos-guest-virtualbox.sh\")\n\n## Push-button installer of macOS on VirtualBox\n\n[`macos-guest-virtualbox.sh`](https://raw.githubusercontent.com/myspaghetti/macos-guest-virtualbox/master/macos-guest-virtualbox.sh) is a Bash script that creates a macOS virtual machine guest on VirtualBox with unmodified macOS installation files downloaded directly from Apple servers.\n\nA default install only requires the user to sit patiently and, less than ten times, press enter when prompted by the script, without interacting with the virtual machine.\n\nTested on `bash` and `zsh` on [Cygwin](https://cygwin.com/install.html). Works on macOS, CentOS 7, and Windows on x86 CPUs with VT-x or AMD-V. Should work on most modern Linux distros.\n\nmacOS Catalina (10.15), Mojave (10.14), and High Sierra (10.13) currently supported.\n\n## Maintainer wanted\n\nIf you would like to become the maintainer of this repository, please see [issue #645 - maintainer wanted](https://github.com/myspaghetti/macos-virtualbox/issues/645).\n\n## Documentation\n\nDocumentation can be viewed by executing the command `./macos-guest-virtualbox.sh documentation`\n\nThe majority of the script is either documentation, comments, or actionable error messages, which should make the script straightforward to inspect and understand.\n\n## iCloud and iMessage connectivity and NVRAM\n\niCloud, iMessage, and other connected Apple services require a valid device name and serial number, board ID and serial number, and other genuine (or genuine-like) Apple parameters. These can be set in EFI and NVRAM by editing the script. See the [documentation command](#documentation) for further information.\n\n## Storage size\n\nThe script by default assigns a target virtual disk storage size of 80GB, which is populated to about 25GB on the host on initial installation. After the installation is complete, the storage size may be increased. See the [documentation command](#documentation) for further information.\n\n## Primary display resolution\n\nThe following primary display resolutions are supported by macOS on VirtualBox: `5120x2880` `2880x1800` `2560x1600` `2560x1440` `1920x1200` `1600x1200` `1680x1050` `1440x900` `1280x800` `1024x768` `640x480`. See the [documentation command](#documentation) for further information.\n\n## Scope and unsupported features\n\nThe scope of the script is completing a default macOS install process on VirtualBox on supported hardware. Further functioning order of VirtualBox or macOS is beyond the scope of this script. Some features may behave unexpectedly, such as USB device support, audio support, FileVault boot password prompt support, and other features, including critical functionality.\n\n### CPU compatibility\n\nThe script is designed for x86 CPU Mac hardware. macOS guests on VirtualBox are generally incompatible with other CPU models. If the guest macOS boot process hangs on “LoadKernelFromStream”, “EndRandomSeed”, or \"EXITBS\", see the [documentation command](#documentation) regarding VirtualBox CPU profiles and [CPUID settings](https://www.virtualbox.org/manual/ch08.html#vboxmanage-modifyvm-teleport). Some CPU models released in 2020 and later may fail to start or complete the installer, and may require manually adjusting the CPUID settings.\n\n### Upgrading to Big Sur and Monterey \n\nThe virtual machine may be upgraded to the latest macOS Big Sur (11) and macOS Monterey (12) versions through Software Update. Big Sur may be installed in-place. Monterey may require attaching another volume to the virtual machine and selecting the volume as the installation target, otherwise the upgrade is prone to failing and entering a boot loop.\n\n### Performance and deployment\n\nAfter successfully creating a working macOS virtual machine, consider importing it into more performant virtualization software, or packaging it for configuration management platforms for automated deployment. These virtualization and deployment applications require additional configuration that is beyond the scope of the script.\n\nQEMU with KVM is capable of providing virtual machine hardware passthrough for near-native performance. QEMU supports the `VMDK` virtual disk image storage format, which can be configured to be created by the script. See the [documentation command](#documentation) for further information. QEMU and KVM require additional configuration that is beyond the scope of the script.\n\n#### VirtualBox Native Execution Manager (NEM)\n\nThe VirtualBox Native Execution Manager (NEM) is an experimental VirtualBox feature. [VirtualBox uses NEM when access to VT-x and AMD-V is blocked by virtualization software or execution protection features such as Hyper-V, WSL2, WSLg, Windows Sandbox, memory integrity protection, Application Guard, Credential Guard, Device Guard, and other features and software.](https://docs.microsoft.com/en-us/troubleshoot/windows-client/application-management/virtualization-apps-not-work-with-hyper-v) macOS and the macOS installer have memory corruption issues under NEM virtualization. The script checks for NEM and exits with an error message if it is detected.\n\n[VirtualBox can run on WSL2 and WSLg with some kernel module compilation](https://github.com/myspaghetti/macos-virtualbox/issues/525), though performance is extremely low. At the point that kernel module compilation is required, it may be preferable to use QEMU/KVM on WSL2 and WSLg, which is orders of magnitude faster than VirtualBox on WSL2 and WSLg. WSL2, WSLg, QEMU, and KVM require additional configuration that is beyond the scope of the script.\n\n### Bootloaders\n\nThe macOS VirtualBox guest is loaded without extra bootloaders, but it is compatible with [OpenCore](https://github.com/acidanthera/OpenCorePkg/releases). OpenCore requires additional configuration that is beyond the scope of  the script.\n\n### Audio\n\nmacOS may not support any built-in VirtualBox audio controllers. The bootloader [OpenCore](https://github.com/acidanthera/OpenCorePkg/releases) may be able to load open-source or built-in audio drivers in VirtualBox, providing the configuration for STAC9221 (Intel HD Audio) or SigmaTel STAC9700,83,84 (ICH AC97) is available.\n\n### Display scaling\n\nVirtualBox does not supply an EDID for its virtual display, and macOS does not enable display scaling (high PPI) without an EDID. The bootloader OpenCore can [inject an EDID](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.IntelHD.en.md#edid) which enables display scaling.\n\n### FileVault\n\nThe VirtualBox EFI implementation does not properly load the FileVault full disk encryption password prompt upon boot. The bootloader [OpenCore](https://github.com/acidanthera/OpenCorePkg/releases/tag/0.6.9) is able to load the password prompt with the parameter `ProvideConsoleGop` set to `true`. See sample [config.plist](https://github.com/myspaghetti/macos-virtualbox/files/6600860/config.plist.txt)\n\n\n## Dependencies\n\nThe following dependencies should be available through a package manager:  \n`bash` `coreutils` `gzip` `unzip` `wget` `xxd` `dmg2img`  `virtualbox`\n\nThe following optional packages provide optical character recognition that reduces the required interaction with the script:  \n`tesseract-ocr` `tesseract-ocr-eng`\n\nSupported versions:\n\n* [VirtualBox](https://www.virtualbox.org/wiki/Downloads) ≥ 6.1.6, though versions as low as 5.2 may work.\n* GNU `Bash` ≥ 4.3, on Windows run through [Cygwin](https://cygwin.com/install.html) or WSL \"1\", see [NEM](#virtualbox-native-execution-manager-nem)\n* GNU `coreutils` ≥ 8.22, GNU `gzip` ≥ 1.5, Info-ZIP `unzip` ≥ v6.0, GNU `wget` ≥ 1.14, `xxd` ≥ 1.11\n* `dmg2img` ≥ 1.6.5, on Cygwin the package is not available through the package manager so the script downloads it automatically.\n* `tesseract-ocr` ≥ 4\n"
  },
  {
    "path": "macos-guest-virtualbox.sh",
    "content": "#!/bin/bash -i\n# Push-button installer of macOS on VirtualBox\n# (c) myspaghetti, licensed under GPL2.0 or higher\n# url: https://github.com/myspaghetti/macos-virtualbox\n# version 0.99.2.4\n\n#       Dependencies: bash  coreutils  gzip  unzip  wget  xxd  dmg2img\n#  Optional features: tesseract-ocr  tesseract-ocr-eng\n# Supported versions:\n#               VirtualBox >= 6.1.6     dmg2img >= 1.6.5\n#               GNU bash >= 4.3         GNU coreutils >= 8.22\n#               GNU gzip >= 1.5         GNU wget >= 1.14\n#               Info-ZIP unzip >= 6.0   xxd with -e little endian support\n#               tesseract-ocr >= 4\n\nfunction set_variables() {\n# Customize the installation by setting these variables:\nvm_name=\"macOS\"                  # name of the VirtualBox virtual machine\nmacOS_release_name=\"Catalina\"    # install \"HighSierra\" \"Mojave\" or \"Catalina\"\nstorage_size=80000               # VM disk image size in MB, minimum 22000\nstorage_format=\"vdi\"             # VM disk image file format, \"vdi\" or \"vmdk\"\ncpu_profile=\"host\"               # VM CPU profile, see \"CPU profiles\" in docs\ncpu_count=2                      # VM CPU cores, minimum 2\nmemory_size=4096                 # VM RAM in MB, minimum 2048\ngpu_vram=128                     # VM video RAM in MB, minimum 34, maximum 128\nresolution=\"1280x800\"            # VM display resolution\n\n# Values for NVRAM and EFI parameters are required by iCloud, iMessage,\n# and other connected Apple applications, but otherwise not required.\n# Parameters taken from a genuine Mac may result in a \"Call customer support\"\n# message if they do not match the genuine Mac exactly.\n# Non-genuine yet genuine-like parameters usually work.\n\n# Assigning the following parameters is not required when installing or using macOS.\n\nDmiSystemFamily=\"MacBook Pro\"          # Model Name\nDmiSystemProduct=\"MacBookPro11,2\"      # Model Identifier\nDmiBIOSVersion=\"string:MBP7.89\"        # Boot ROM Version\nDmiSystemSerial=\"NO_DEVICE_SN\"         # Serial Number (system)\nDmiSystemUuid=\"CAFECAFE-CAFE-CAFE-CAFE-DECAFFDECAFF\" # Hardware UUID\nROM='%aa*%bbg%cc%dd'                   # ROM identifier\nMLB=\"NO_LOGIC_BOARD_SN\"                # MLB SN stored in NVRAM\nDmiBoardSerial=\"${MLB}\"                # MLB SN stored in EFI\nDmiBoardProduct=\"Mac-3CBD00234E554E41\" # Product (board) identifier\nSystemUUID=\"aabbccddeeff00112233445566778899\" # System UUID\n\n# If the script is running on macOS and \"get_parameters_from_macOS_host\" is\n# set to \"yes\", the script will attempt to get the host's EFI and NVRAM\n# parameters and override the above EFI and NVRAM parameters.\n\nget_parameters_from_macOS_host=\"no\"\n\nif [[ \"$(sw_vers 2>/dev/null)\" && \"${get_parameters_from_macOS_host}\" =~ [Yy] ]]; then\n    # These values are taken from a genuine Mac...\n    hardware_overview=\"$(system_profiler SPHardwareDataType)\"\n    model_name=\"${hardware_overview##*Model Name: }\"; model_name=\"${model_name%%$'\\n'*}\"\n    model_identifier=\"${hardware_overview##*Model Identifier: }\"; model_identifier=\"${model_identifier%%$'\\n'*}\"\n    boot_rom_ver=\"${hardware_overview##*Boot ROM Version: }\"; boot_rom_ver=\"${boot_rom_ver%%$'\\n'*}\"\n    sn_system=\"${hardware_overview##*Serial Number (system): }\"; sn_system=\"${sn_system%%$'\\n'*}\"\n    hardware_uuid=\"${hardware_overview##*Hardware UUID: }\"; hardware_uuid=\"${hardware_uuid%%$'\\n'*}\"\n    nvram_rom=\"$(nvram 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ROM)\"; nvram_rom=\"${nvram_rom##*$'\\t'}\"\n    nvram_mlb=\"$(nvram 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:MLB)\"; nvram_mlb=\"${nvram_mlb##*$'\\t'}\"\n    ioreg_board_id=\"$(ioreg -p \"IODeviceTree\" -r -n / -d 1)\"; ioreg_board_id=\"${ioreg_board_id##*board-id\\\" = <\\\"}\"; ioreg_board_id=\"${ioreg_board_id%%\\\">*}\"\n    ioreg_system_id=\"$(ioreg -p \"IODeviceTree\" -n platform -r)\"; ioreg_system_id=\"${ioreg_system_id##*system-id\\\" = <}\"; ioreg_system_id=\"${ioreg_system_id%%>*}\"\n\n    # ...and set in VirtualBox EFI and NVRAM...\n    DmiSystemFamily=\"${model_name}\"         # Model Name\n    DmiSystemProduct=\"${model_identifier}\"  # Model Identifier\n    DmiBIOSVersion=\"string:${boot_rom_ver}\" # Boot ROM Version\n    DmiSystemSerial=\"${sn_system}\"          # Serial Number (system)\n    DmiSystemUuid=\"${hardware_uuid}\"        # Hardware UUID\n    ROM=\"${nvram_rom}\"                      # ROM identifier, stored in NVRAM\n    MLB=\"${nvram_mlb}\"                      # MLB SN, stored in NVRAM\n    DmiBoardSerial=\"${nvram_mlb}\"           # MLB SN, stored in EFI\n    DmiBoardProduct=\"${ioreg_board_id}\"     # Product (board) identifier\n    SystemUUID=\"${ioreg_system_id}\"         # System UUID, stored in NVRAM\nfi\n\nsystem_integrity_protection='10'  # '10' - enabled, '77' - disabled\n\n# Additional configurations may be saved in external files and loaded with the\n# following command prior to executing the script:\n#   export macos_vm_vars_file=/path/to/variable_assignment_file\n# \"variable_assignment_file\" is a plain text file that contains zero or more\n# lines with a variable assignment for any variable specified above.\n[[ -r \"${macos_vm_vars_file}\" ]] && source \"${macos_vm_vars_file}\"\n}\n\n# welcome message\nfunction welcome() {\necho -ne \"\\n${highlight_color}Push-button installer of macOS on VirtualBox${default_color}\n\nThis script installs only open-source software and unmodified Apple binaries,\nand requires about ${highlight_color}50GB${default_color} of available storage, of which 25GB are for temporary\ninstallation files that may be deleted when the script is finished.\n\nThe script interacts with the virtual machine twice, ${highlight_color}please do not interact${default_color}\n${highlight_color}with the virtual machine manually${default_color} before the script is finished.\n\nDocumentation about optional configuration, ${highlight_color}iCloud and iMessage connectivity${default_color},\nresuming the script by stages, and other topics can be viewed with the\nfollowing command:\n\n\"\nwould_you_like_to_know_less\necho -ne \"\\n${highlight_color}Press enter to review the script configuration${default_color}\"\nclear_input_buffer_then_read\n\nfunction pad_to_33_chars() {\n    local padded=\"${1}                                 \"\n    echo \"${padded:0:33}${2}\"\n}\n\n# custom settings prompt\necho -e \"\\nvm_name=\\\"${vm_name}\\\"\"\npad_to_33_chars \"macOS_release_name=\\\"${macOS_release_name}\\\"\" \"# install \\\"HighSierra\\\" \\\"Mojave\\\" \\\"Catalina\\\"\"\npad_to_33_chars \"storage_size=${storage_size}\"                 \"# VM disk image size in MB, minimum 22000\"\npad_to_33_chars \"storage_format=\\\"${storage_format}\\\"\"         \"# VM disk image file format, \\\"vdi\\\" or \\\"vmdk\\\"\"\npad_to_33_chars \"cpu_profile=\\\"${cpu_profile}\\\"\"               \"# VM CPU profile, see \\\"CPU profiles\\\" in docs\"\npad_to_33_chars \"cpu_count=${cpu_count}\"                       \"# VM CPU cores, minimum 2\"\npad_to_33_chars \"memory_size=${memory_size}\"                   \"# VM RAM in MB, minimum 2048\"\npad_to_33_chars \"gpu_vram=${gpu_vram}\"                         \"# VM video RAM in MB, minimum 34, maximum 128\"\npad_to_33_chars \"resolution=\\\"${resolution}\\\"\"                 \"# VM display resolution\"\necho -ne \"\\nThese values may be customized as described in the documentation.\\n\n${highlight_color}Press enter to continue, CTRL-C to exit${default_color}\"\nclear_input_buffer_then_read\n}\n\n# check dependencies\n\nfunction check_shell() {\nif [[ -n \"${BASH_VERSION}\" && -n \"${ZSH_VERSION}\" ]]; then\n    echo \"The script cannot determine if it is executed on bash or zsh.\"\n    echo \"Please explicitly execute the script on the same shell as the interactive shell,\"\n    echo -e \"for example, for zsh:\\n\"\n    echo \"    ${highlight_color}zsh -i macos-guest-virtualbox.sh${default_color}\"\n    exit\nelif [[ -n \"${BASH_VERSION}\" ]]; then\n    if [[ ! ( \"${BASH_VERSION:0:1}\" -ge 5\n              || \"${BASH_VERSION:0:3}\" =~ 4\\.[3-9]\n              || \"${BASH_VERSION:0:4}\" =~ 4\\.[12][0-9] ) ]]; then\n        echo \"Please execute this script with Bash 4.3 or higher, or zsh 5.5 or higher.\"\n        if [[ -n \"$(sw_vers 2>/dev/null)\" ]]; then\n            echo \"macOS detected. Make sure the script is not executed with the default /bin/bash\"\n            echo \"which is version 3. Explicitly type the executable path, for example for zsh:\"\n            echo \"    ${highlight_color}/path/to/5.5/zsh macos-guest-virtualbox.sh${default_color}\"\n        fi\n        exit\n    fi\nelif [[ -n \"${ZSH_VERSION}\" ]]; then\n    if [[ ( \"${ZSH_VERSION:0:1}\" -ge 6\n            || \"${ZSH_VERSION:0:3}\" =~ 5\\.[5-9]\n            || \"${ZSH_VERSION:0:4}\" =~ 5\\.[1-4][0-9] ) ]]; then\n        # make zsh parse the script (almost) like bash\n        setopt extendedglob sh_word_split ksh_arrays posix_argzero nullglob bsd_echo\n    else\n        echo \"Please execute this script with zsh version 5.5 or higher.\"\n        exit\n    fi\nelse\n    echo \"The script appears to be executed on a shell other than bash or zsh. Exiting.\"\n    exit\nfi\n\nif [[ ! $- =~ i ]]; then  # terminal is not interactive\n    echo \"The shell appears to be executed non-interactively. If this is not the case,\"\n    echo \"please press CTRL-C and run the script under an interactive shell, for example\"\n    echo -e \"${highlight_color}bash -i macos-guest-virtualbox.sh${default_color}    or    ${highlight_color}zsh -i macos-guest-virtualbox.sh${default_color}\\n\"\n    echo \"Otherwise, the script will continue running non-interactively.\"\n    animated_please_wait 5\n    echo \"\"\n    tesseract_ocr=\"$(tesseract --version 2>/dev/null)\"\n    tesseract_lang=\"$(tesseract --list-langs 2>/dev/null)\"\n    regex_ver='[Tt]esseract [45]'  # for zsh quoted regex compatibility\n    if [[ ! ( \"${tesseract_ocr}\" =~ ${regex_ver} ) || -z \"${tesseract_lang}\" ]]; then\n        echo \"Running the script on a non-interactive shell requires the following packages:\"\n        echo -e \"    tesseract-ocr >= 4    tesseract-ocr-eng\\n\"\n        echo \"Exiting.\"\n        animated_please_wait 5\n        echo \"\"\n        exit\n    fi\nfi\n\n}\n\nfunction check_gnu_coreutils_prefix() {\nif [[ -n \"$(gcsplit --help 2>/dev/null)\" ]]; then\n    function base64() {\n        gbase64 \"$@\"\n    }\n    function csplit() {\n        gcsplit \"$@\"\n    }\n    function expr() {\n        gexpr \"$@\"\n    }\n    function ls() {\n        gls \"$@\"\n    }\n    function split() {\n        gsplit \"$@\"\n    }\n    function tac() {\n        gtac \"$@\"\n    }\n    function seq() {\n        gseq \"$@\"\n    }\n    function sort() {\n        gsort \"$@\"\n    }\nfi\n}\n\nfunction check_dependencies() {\n\n# check environment for macOS and non-GNU coreutils\nif [[ -n \"$(sw_vers 2>/dev/null)\" ]]; then\n    # Add Homebrew GNU coreutils to PATH if path exists\n    homebrew_gnubin=\"/usr/local/opt/coreutils/libexec/gnubin\"\n    if [[ -d \"${homebrew_gnubin}\" ]]; then\n        PATH=\"${homebrew_gnubin}:${PATH}\"\n    fi\n    # if csplit isn't GNU variant, exit\n    if [[ -z \"$(csplit --help 2>/dev/null)\" ]]; then\n        echo -e \"\\nmacOS detected.\\nPlease use a package manager such as ${highlight_color}homebrew${default_color}, ${highlight_color}pkgsrc${default_color}, ${highlight_color}nix${default_color}, or ${highlight_color}MacPorts${default_color}\"\n        echo \"Please make sure the following packages are installed and that\"\n        echo \"their path is in the PATH variable:\"\n        echo -e \"    ${highlight_color}bash  coreutils  dmg2img  gzip  unzip  wget  xxd${default_color}\"\n        echo \"Please make sure Bash and coreutils are the GNU variant.\"\n        exit\n    fi\nfi\n\n# check for gzip, unzip, coreutils, wget\nif [[ -z \"$(gzip --help 2>/dev/null)\" ||\n      -z \"$(unzip -hh 2>/dev/null)\" ||\n      -z \"$(csplit --help 2>/dev/null)\" ||\n      -z \"$(wget --version 2>/dev/null)\" ]]; then\n    echo \"Please make sure the following packages are installed\"\n    echo -e \"and that they are of the version specified or newer:\\n\"\n    echo \"    coreutils 8.22   wget 1.14   gzip 1.5   unzip 6.0\"\n    echo -e \"\\nPlease make sure the coreutils and gzip packages are the GNU variant.\"\n    exit\nfi\n\n# check that xxd supports endianness -e flag\nif [[ -z \"$(xxd -e -p -l 16 /dev/urandom 2>/dev/null)\" ]]; then\n    echo \"Please make sure a version of xxd which supports the -e option is installed.\"\n    echo -e \"The -e option should be listed when executing   ${low_contrast_color}xxd --help${default_color}\"\n    echo \"The package vim-common-8 provides a compatible version on most modern distros.\"\n    exit\nfi\n\n# wget supports --show-progress from version 1.16\nregex='1\\.1[6-9]|1\\.[2-9][0-9]'  # for zsh quoted regex compatibility\nif [[ \"$(wget --version 2>/dev/null | head -n 1)\" =~ ${regex} ]]; then\n    wgetargs=\"--quiet --continue --show-progress --timeout=60 --secure-protocol=PFS\"  # pretty\nelse\n    wgetargs=\"--continue\"  # ugly\nfi\n\n# VirtualBox in ${PATH}\n# Cygwin\nif [[ -n \"$(cygcheck -V 2>/dev/null)\" ]]; then\n    if [[ -n \"$(cmd.exe /d/s/c call VBoxManage.exe -v 2>/dev/null)\" ]]; then\n        function VBoxManage() {\n            cmd.exe /d/s/c call VBoxManage.exe \"$@\"\n        }\n    else\n        cmd_path_VBoxManage='C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe'\n        echo \"Can't find VBoxManage in PATH variable,\"\n        echo \"checking ${cmd_path_VBoxManage}\"\n        if [[ -n \"$(cmd.exe /d/s/c call \"${cmd_path_VBoxManage}\" -v 2>/dev/null)\" ]]; then\n            function VBoxManage() {\n                cmd.exe /d/s/c call \"${cmd_path_VBoxManage}\" \"$@\"\n            }\n            echo \"Found VBoxManage\"\n        else\n            echo \"Please make sure VirtualBox version 5.2 or higher is installed, and that\"\n            echo \"the path to the VBoxManage.exe executable is in the PATH variable, or assign\"\n            echo \"in the script the full path including the name of the executable to\"\n            echo -e \"the variable ${highlight_color}cmd_path_VBoxManage${default_color}\"\n            exit\n        fi\n    fi\n# Windows Subsystem for Linux 2 (WSL2 or WSLg)\nelif [[ \"$(cat /proc/sys/kernel/osrelease 2>/dev/null)\" =~ WSL[2Gg] ]]; then  # WSL2 or WSLg\n    if [[ -n \"$(VBoxManage -v 2>/dev/null)\" ]]; then\n        if [[ ! \"$(lsmod)\" =~ vboxdrv ]]; then  # if the vboxdrv kernel module is not present\n            echo \"The script appears to be executed on WSL2 or WSLg.\"\n            echo \"Mind that WSL2 and WSLg require kernel module compilation and\"\n            echo \"custom configuration that is not supported by the script.\"\n            echo \"If the script does not detect the ${highlight_color}vboxdrv${default_color} kernel module, it exits.\"\n            exit\n        fi\n    else\n        echo \"Please make sure VirtualBox version 5.2 or higher and its kernel module\"\n        echo \"are installed, and that the path to the VBoxManage executable\"\n        echo \"is in the PATH variable.\"\n        exit\n    fi\n# Windows Subsystem for Linux (WSL \"1\") \nelif [[ \"$(cat /proc/sys/kernel/osrelease 2>/dev/null)\" =~ [Mm]icrosoft ]]; then\n    if [[ -n \"$(VBoxManage.exe -v 2>/dev/null)\" ]]; then\n        function VBoxManage() {\n            VBoxManage.exe \"$@\"\n        }\n    else\n        wsl_path_VBoxManage='/mnt/c/Program Files/Oracle/VirtualBox/VBoxManage.exe'\n        echo \"Can't find VBoxManage in PATH variable,\"\n        echo \"checking ${wsl_path_VBoxManage}\"\n        if [[ -n \"$(\"${wsl_path_VBoxManage}\" -v 2>/dev/null)\" ]]; then\n            PATH=\"${PATH}:${wsl_path_VBoxManage%/*}\"\n            function VBoxManage() {\n                VBoxManage.exe \"$@\"\n            }\n            echo \"Found VBoxManage\"\n        else\n            echo \"Please make sure VirtualBox is installed on Windows, and that the path to the\"\n            echo \"VBoxManage.exe executable is in the PATH variable, or assigned in the script\"\n            echo -e \"to the variable \\\"${highlight_color}wsl_path_VBoxManage${default_color}\\\" including the name of the executable.\"\n            exit\n        fi\n    fi\n# everything else (not cygwin and not wsl)\nelif [[ -z \"$(VBoxManage -v 2>/dev/null)\" ]]; then\n    echo \"Please make sure VirtualBox version 5.2 or higher and its kernel module\"\n    echo \"are installed, and that the path to the VBoxManage executable\"\n    echo \"is in the PATH variable.\"\n    exit\nfi\n\n# VirtualBox version\nvbox_version=\"$(VBoxManage -v 2>/dev/null)\"\nvbox_version=\"${vbox_version//[$'\\r\\n']/}\"\nif [[ -z \"${vbox_version}\" || -z \"${vbox_version:2:1}\" ]]; then\n    echo \"Can't determine VirtualBox version. Exiting.\"\n    exit\nelif [[ ! ( \"${vbox_version:0:1}\" -gt 5\n         || \"${vbox_version:0:3}\" =~ 5\\.2 ) ]]; then\n    echo -e \"\\nPlease make sure VirtualBox version 5.2 or higher is installed.\"\n    echo \"Exiting.\"\n    exit\nelif [[ \"${vbox_version:0:1}\" = 5 ]]; then\n    echo -e \"\\n${highlight_color}VirtualBox version ${vbox_version} detected.${default_color} Please see the following\"\n    echo -ne \"URL for issues with the VISO filesystem on VirtualBox 5.2 to 5.2.40:\\n\\n\"\n    echo \"  https://github.com/myspaghetti/macos-virtualbox/issues/86\"\n    echo -ne \"\\n${highlight_color}Press enter to continue, CTRL-C to exit${default_color}\"\n    clear_input_buffer_then_read\nfi\n\n# Oracle VM VirtualBox Extension Pack\nextpacks=\"$(VBoxManage list extpacks 2>/dev/null)\"\nif [[ \"$(expr match \"${extpacks}\" '.*Oracle VM VirtualBox Extension Pack')\" -le \"0\" ||\n      \"$(expr match \"${extpacks}\" '.*Usable:[[:blank:]]*false')\" -gt \"0\" ]];\nthen\n    echo -e \"\\nThe command \\\"VBoxManage list extpacks\\\" either does not list the Oracle VM\"\n    echo -e \"VirtualBox Extension Pack, or lists one or more extensions as unusable.\"\n    echo -e \"The virtual machine will be configured without USB xHCI controllers.\"\n    extension_pack_usb3_support=\"--usbxhci off\"\nelse\n    extension_pack_usb3_support=\"--usbxhci on\"\nfi\n\n# dmg2img\nif ! dmg2img >/dev/null 2>&1; then\n    if [[ -z \"$(cygcheck -V 2>/dev/null)\" ]]; then\n        echo -e \"\\nPlease install the package dmg2img.\"\n        exit\n    fi\n    if [[ -z \"$(\"${PWD%%/}/dmg2img.exe\" -d 2>/dev/null)\" ]]; then\n        if [[ -z \"${PWD}\" ]]; then echo \"PWD environment variable is not set. Exiting.\"; exit; fi\n        echo \"Locally installing dmg2img\"\n        wget \"https://web.archive.org/web/20190322013244/http://vu1tur.eu.org/tools/dmg2img-1.6.6-win32.zip\" \\\n             ${wgetargs} \\\n             --output-document=\"dmg2img-1.6.6-win32.zip\"\n        if [[ ! -s dmg2img-1.6.6-win32.zip ]]; then\n             echo \"Error downloading dmg2img. Please provide the package manually.\"\n             exit\n        fi\n        unzip -oj \"dmg2img-1.6.6-win32.zip\" \"dmg2img.exe\"\n        command rm \"dmg2img-1.6.6-win32.zip\"\n        chmod +x \"dmg2img.exe\"\n        [[ ! -x \"dmg2img.exe\" ]] && echo \"Error setting the executable permission for dmg2img.exe. Exiting.\" && exit\n    fi\n    function dmg2img() {\n        \"${PWD%%/}/dmg2img.exe\" \"$@\"\n    }\nfi\n\n# set Apple software update catalog URL according to macOS version\nHighSierra_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'\nMojave_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'\nCatalina_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'\nif [[ \"${macOS_release_name:0:1}\" =~ [Cc] ]]; then\n    if [[ ! ( \"${vbox_version:0:1}\" -gt 6 ||\n              \"${vbox_version}\" =~ ^6\\.1\\.[4-9] ||\n              \"${vbox_version}\" =~ ^6\\.1\\.[123][0-9] ||\n              \"${vbox_version}\" =~ ^6\\.[2-9] ) ]]; then\n        echo -e \"\\nmacOS Catalina requires VirtualBox version 6.1.4 or higher.\"\n        echo \"Exiting.\"\n        exit\n    fi\nfi\nif [[ \"${macOS_release_name:0:1}\" =~ [Cc] ]]; then\n    macOS_release_name=\"Catalina\"\n    CFBundleShortVersionString=\"10.15\"\n    sucatalog=\"${Catalina_sucatalog}\"\nelif [[ \"${macOS_release_name:0:1}\" =~ [Hh] ]]; then\n    macOS_release_name=\"HighSierra\"\n    CFBundleShortVersionString=\"10.13\"\n    sucatalog=\"${HighSierra_sucatalog}\"\nelif [[ \"${macOS_release_name:0:1}\" =~ [Mm] ]]; then\n    macOS_release_name=\"Mojave\"\n    CFBundleShortVersionString=\"10.14\"\n    sucatalog=\"${Mojave_sucatalog}\"\nelse\n    echo \"Can't parse macOS_release_name. Exiting.\"\n    exit\nfi\nprint_dimly \"${macOS_release_name} selected to be downloaded and installed\"\n}\n# Done with dependencies\n\nfunction prompt_delete_existing_vm() {\nprint_dimly \"stage: prompt_delete_existing_vm\"\nif [[ -n \"$(VBoxManage showvminfo \"${vm_name}\" 2>/dev/null)\" ]]; then\n    echo -e \"\\nA virtual machine named \\\"${vm_name}\\\" already exists.\"\n    echo -ne \"${warning_color}Delete existing virtual machine \\\"${vm_name}\\\"?${default_color}\"\n    prompt_delete_y_n\n    if [[ \"${delete}\" == \"y\" ]]; then\n        echo \"Deleting ${vm_name} virtual machine.\"\n        VBoxManage unregistervm \"${vm_name}\" --delete\n    else\n        echo -e \"\\n${highlight_color}Please assign a different VM name to variable \\\"vm_name\\\" by editing the script,${default_color}\"\n        echo \"or skip this check manually as described when executing the following command:\"\n        would_you_like_to_know_less\n        exit\n    fi\nfi\n}\n\n# Attempt to create new virtual machine named \"${vm_name}\"\nfunction create_vm() {\nprint_dimly \"stage: create_vm\"\nif [[ -n \"$( VBoxManage createvm --name \"${vm_name}\" --ostype \"MacOS1013_64\" --register 2>&1 >/dev/null )\" ]]; then\n    echo -e \"\\nError: Could not create virtual machine \\\"${vm_name}\\\".\"\n    echo -e \"${highlight_color}Please delete exising \\\"${vm_name}\\\" VirtualBox configuration files ${warning_color}manually${default_color}.\\n\"\n    echo -e \"Error message:\\n\"\n    VBoxManage createvm --name \"${vm_name}\" --ostype \"MacOS1013_64\" --register 2>/dev/tty\n    exit\nfi\n}\n\nfunction check_default_virtual_machine() {\nprint_dimly \"stage: check_default_virtual_machine\"\necho -e \"\\nChecking that VirtualBox starts the virtual machine without errors.\"\nif [[ -n $(VBoxManage startvm \"${vm_name}\" 2>&1 1>/dev/null) ]]; then\n    echo -e \"Error while starting the virtual machine.\\nExiting.\"\n    exit\nfi\nVBoxManage controlvm \"${vm_name}\" poweroff 2>/dev/null\necho -e \"\\nChecking that VirtualBox uses hardware-supported virtualization.\"\nvbox_log=\"$(VBoxManage showvminfo \"${vm_name}\" --log 0)\"\nregex='Attempting fall back to NEM'  # for zsh quoted regex compatibility\nif [[ \"${vbox_log}\" =~ ${regex} ]]; then\n    echo -e \"\\nVirtualbox is not using hardware-supported virtualization features.\"\n    if [[ -n \"$(cygcheck -V 2>/dev/null)\" ||\n          \"$(cat /proc/sys/kernel/osrelease 2>/dev/null)\" =~ [Mm]icrosoft ]]; then\n        echo \"Check that software such as Hyper-V, Windows Sandbox, WSL2, memory integrity\"\n        echo \"protection, and other Windows features that lock virtualization are turned off.\"\n    fi\n    echo \"Exiting.\"\n    exit\nfi\n}\n\nfunction prepare_macos_installation_files() {\nprint_dimly \"stage: prepare_macos_installation_files\"\n# Find the correct download URL in the Apple catalog\necho -e \"\\nDownloading Apple macOS ${macOS_release_name} software update catalog\"\nwget \"${sucatalog}\" \\\n     ${wgetargs} \\\n     --output-document=\"${macOS_release_name}_sucatalog\"\n\n# if file was not downloaded correctly\nif [[ ! -s \"${macOS_release_name}_sucatalog\" ]]; then\n    wget --debug --timeout=60 -O /dev/null -o \"${macOS_release_name}_wget.log\" \"${sucatalog}\"\n    echo -e \"\\nCouldn't download the Apple software update catalog.\"\n    if [[ \"$(expr match \"$(cat \"${macOS_release_name}_wget.log\")\" '.*ERROR[[:print:]]*is not trusted')\" -gt \"0\" ]]; then\n        echo -e \"\\nMake sure certificates from a certificate authority are installed.\"\n        echo \"Certificates are often installed through the package manager with\"\n        echo \"a package named  ${highlight_color}ca-certificates${default_color}\"\n    fi\n    echo \"Exiting.\"\n    exit\nfi\n\necho \"Trying to find macOS ${macOS_release_name} InstallAssistant download URL\"\ntac \"${macOS_release_name}_sucatalog\" | csplit - '/InstallAssistantAuto.smd/+1' '{*}' -f \"${macOS_release_name}_sucatalog_\" -s\nfor catalog in \"${macOS_release_name}_sucatalog_\"* \"error\"; do\n    if [[ \"${catalog}\" == error ]]; then\n        command rm \"${macOS_release_name}_sucatalog\"*\n        echo \"Couldn't find the requested download URL in the Apple catalog. Exiting.\"\n       exit\n    fi\n    urlbase=\"$(tail -n 1 \"${catalog}\" 2>/dev/null)\"\n    urlbase=\"$(expr match \"${urlbase}\" '.*\\(http://[^<]*/\\)')\"\n    wget \"${urlbase}InstallAssistantAuto.smd\" \\\n    ${wgetargs} \\\n    --output-document=\"${catalog}_InstallAssistantAuto.smd\"\n    if [[ \"$(cat \"${catalog}_InstallAssistantAuto.smd\" )\" =~ Beta ]]; then\n        continue\n    fi\n    found_version=\"$(head -n 6 \"${catalog}_InstallAssistantAuto.smd\" | tail -n 1)\"\n    if [[ \"${found_version}\" == *${CFBundleShortVersionString}* ]]; then\n        echo -e \"Found download URL: ${urlbase}\\n\"\n        command rm \"${macOS_release_name}_sucatalog\"*\n        break\n    fi\ndone\necho \"Downloading macOS installation files from swcdn.apple.com\"\nfor filename in \"BaseSystem.chunklist\" \\\n                \"InstallInfo.plist\" \\\n                \"AppleDiagnostics.dmg\" \\\n                \"AppleDiagnostics.chunklist\" \\\n                \"BaseSystem.dmg\" \\\n                \"InstallESDDmg.pkg\"; \\\n    do wget \"${urlbase}${filename}\" \\\n            ${wgetargs} \\\n            --output-document \"${macOS_release_name}_${filename}\"\ndone\n\necho -e \"\\nSplitting the several-GB InstallESDDmg.pkg into 1GB parts because\"\necho \"VirtualBox hasn't implemented UDF/HFS VISO support yet and macOS\"\necho \"doesn't support ISO 9660 Level 3 with files larger than 2GB.\"\nsplit --verbose -a 2 -d -b 1000000000 \"${macOS_release_name}_InstallESDDmg.pkg\" \"${macOS_release_name}_InstallESD.part\"\n\nif [[ ! -s \"ApfsDriverLoader.efi\" ]]; then\n    echo -e \"\\nDownloading open-source APFS EFI drivers used for VirtualBox 6.0 and 5.2\"\n    [[ \"${vbox_version:0:1}\" -gt 6 || ( \"${vbox_version:0:1}\" = 6 && \"${vbox_version:2:1}\" -ge 1 ) ]] && echo \"...even though VirtualBox version 6.1 or higher is detected.\"\n    wget 'https://github.com/acidanthera/AppleSupportPkg/releases/download/2.0.4/AppleSupport-v2.0.4-RELEASE.zip' \\\n        ${wgetargs} \\\n        --output-document 'AppleSupport-v2.0.4-RELEASE.zip'\n        unzip -oj 'AppleSupport-v2.0.4-RELEASE.zip'\nfi\n}\n\nfunction create_nvram_files() {\nprint_dimly \"stage: create_nvram_files\"\n\n# Each NVRAM file may contain multiple entries.\n# Each entry contains a namesize, datasize, name, guid, attributes, and data.\n# Each entry is immediately followed by a crc32 of the entry.\n# The script creates each file with only one entry for easier editing.\n#\n# The hex strings are stripped by xxd, so they can\n# look like \"0xAB 0xCD\" or \"hAB hCD\" or \"AB CD\" or \"ABCD\" or a mix of formats\n# and have extraneous characters like spaces or minus signs.\n\n# Load the binary files into VirtualBox VM NVRAM with the builtin command dmpstore\n# in the VM EFI Internal Shell, for example:\n# dmpstore -all -l fs0:\\system-id.bin\n#\n# DmpStore code is available at this URL:\n# https://github.com/mdaniel/virtualbox-org-svn-vbox-trunk/blob/master/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c\n\nfunction generate_nvram_bin_file() {\n# input: name data guid (three positional arguments, all required)\n# output: function outputs nothing to stdout\n#         but writes a binary file to working directory\n    local namestring=\"${1}\" # string of chars\n    local filename=\"${namestring}\"\n    # represent string as string-of-hex-bytes, add null byte after every byte,\n    # terminate string with two null bytes\n    local name=\"$( for (( i = 0 ; i < ${#namestring} ; i++ )); do printf -- \"${namestring:${i}:1}\" | xxd -p | tr -d '\\n'; printf '00'; done; printf '0000' )\"\n    # size of string in bytes, represented by eight hex digits, big-endian\n    local namesize=\"$(printf \"%08x\" $(( ${#name} / 2 )) )\"\n    # flip four big-endian bytes byte-order to little-endian\n    local namesize=\"$(printf \"${namesize}\" | xxd -r -p | xxd -e -g 4 | xxd -r | xxd -p)\"\n    # strip string-of-hex-bytes representation of data of spaces, \"x\", \"h\", etc\n    local data=\"$(printf -- \"${2}\" | xxd -r -p | xxd -p)\"\n    # size of data in bytes, represented by eight hex digits, big-endian\n    local datasize=\"$(printf \"%08x\" $(( ${#data} / 2 )) )\"\n    # flip four big-endian bytes byte-order to little-endian\n    local datasize=\"$(printf \"${datasize}\" | xxd -r -p | xxd -e -g 4 | xxd -r | xxd -p)\"\n    # guid string-of-hex-bytes is five fields, 8+4+4+4+12 nibbles long\n    # first three are little-endian, last two big-endian\n    # for example, 0F1A2B3C-4D5E-6A7B-8C9D-A1B2C3D4E5F6\n    # is stored as 3C2B1A0F-5E4D-7B6A-8C9D-A1B2C3D4E5F6\n    local g=\"$( printf -- \"${3}\" | xxd -r -p | xxd -p )\" # strip spaces etc\n    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}\"\n    # attributes in four bytes little-endian\n    local attributes=\"07 00 00 00\"\n    # the data structure\n    local entry=\"${namesize} ${datasize} ${name} ${guid} ${attributes} ${data}\"\n    # calculate crc32 using gzip, flip crc32 bytes into big-endian\n    local crc32=\"$(printf \"${entry}\" | xxd -r -p | gzip -c | tail -c8 | xxd -p -l 4)\"\n    # save binary data\n    printf -- \"${entry} ${crc32}\" | xxd -r -p - \"${vm_name}_${filename}.bin\"\n}\n\n# MLB\nMLB_b16=\"$(printf -- \"${MLB}\" | xxd -p)\"\ngenerate_nvram_bin_file \"MLB\" \"${MLB_b16}\" \"4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14\"\n\n# ROM\n# Convert the mixed-ASCII-and-base16 ROM value\n# into an ASCII string that represents a base16 number.\nROM_b16=\"$(for (( i=0; i<${#ROM}; )); do\n               if [[ \"${ROM:${i}:1}\" == \"%\" ]]; then\n                   let j=i+1\n                   echo -n \"${ROM:${j}:2}\"\n                   let i=i+3\n               else\n                   x=\"$(echo -n \"${ROM:${i}:1}\" | xxd -p | tr -d ' ')\"\n                   echo -n \"${x}\"\n                   let i=i+1\n               fi\n            done)\"\ngenerate_nvram_bin_file \"ROM\" \"${ROM_b16}\" \"4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14\"\n\n# system-id\ngenerate_nvram_bin_file \"system-id\" \"${SystemUUID}\" \"7C436110-AB2A-4BBB-A880-FE41995C9F82\"\n\n# SIP / csr-active-config\ngenerate_nvram_bin_file \"csr-active-config\" \"${system_integrity_protection}\" \"7C436110-AB2A-4BBB-A880-FE41995C9F82\"\n}\n\nfunction create_macos_installation_files_viso() {\nprint_dimly \"stage: create_macos_installation_files_viso\"\necho \"Creating EFI startup script\"\necho 'echo -off' > \"${vm_name}_startup.nsh\"\nif [[ ( \"${vbox_version:0:1}\" -lt 6 ) || ( \"${vbox_version:0:1}\" = 6 && \"${vbox_version:2:1}\" = 0 ) ]]; then\n    echo 'load fs0:\\EFI\\OC\\Drivers\\AppleImageLoader.efi\nload fs0:\\EFI\\OC\\Drivers\\AppleUiSupport.efi\nload fs0:\\EFI\\OC\\Drivers\\ApfsDriverLoader.efi\nmap -r' >> \"${vm_name}_startup.nsh\"\nfi\n# EFI Internal Shell 2.1 (VBox 6.0) doesn't support for-loops that start with 0\necho 'if exist \"fs0:\\EFI\\NVRAM\\MLB.bin\" then\n  dmpstore -all -l fs0:\\EFI\\NVRAM\\MLB.bin\n  dmpstore -all -l fs0:\\EFI\\NVRAM\\ROM.bin\n  dmpstore -all -l fs0:\\EFI\\NVRAM\\csr-active-config.bin\n  dmpstore -all -l fs0:\\EFI\\NVRAM\\system-id.bin\nendif\nfor %a run (1 5)\n  if exist \"fs%a:\\EFI\\NVRAM\\MLB.bin\" then\n    dmpstore -all -l fs%a:\\EFI\\NVRAM\\MLB.bin\n    dmpstore -all -l fs%a:\\EFI\\NVRAM\\ROM.bin\n    dmpstore -all -l fs%a:\\EFI\\NVRAM\\csr-active-config.bin\n    dmpstore -all -l fs%a:\\EFI\\NVRAM\\system-id.bin\n  endif\nendfor\nfor %a run (1 5)\n  if exist \"fs%a:\\macOS Install Data\\Locked Files\\Boot Files\\boot.efi\" then\n    \"fs%a:\\macOS Install Data\\Locked Files\\Boot Files\\boot.efi\"\n  endif\nendfor\nfor %a run (1 5)\n  if exist \"fs%a:\\System\\Library\\CoreServices\\boot.efi\" then\n    \"fs%a:\\System\\Library\\CoreServices\\boot.efi\"\n  endif\nendfor' >> \"${vm_name}_startup.nsh\"\n\necho -e \"\\nCreating VirtualBox 6 virtual ISO containing the\"\necho -e \"installation files from swcdn.apple.com\\n\"\ncreate_viso_header \"${macOS_release_name}_installation_files.viso\" \"${macOS_release_name:0:5}-files\"\n\n# add files to viso\n\n# Apple macOS installation files\nfor filename in \"BaseSystem.chunklist\" \\\n                \"InstallInfo.plist\" \\\n                \"AppleDiagnostics.dmg\" \\\n                \"AppleDiagnostics.chunklist\" \\\n                \"BaseSystem.dmg\" ; do\n    if [[ -s \"${macOS_release_name}_${filename}\" ]]; then\n        echo \"/${filename}=\\\"${macOS_release_name}_${filename}\\\"\" >> \"${macOS_release_name}_installation_files.viso\"\n    fi\ndone\n\nif [[ -s \"${macOS_release_name}_InstallESD.part00\" ]]; then\n    for part in \"${macOS_release_name}_InstallESD.part\"*; do\n        echo \"/InstallESD${part##*InstallESD}=\\\"${part}\\\"\" >> \"${macOS_release_name}_installation_files.viso\"\n    done\nfi\n\n# NVRAM binary files\nfor filename in \"MLB.bin\" \"ROM.bin\" \"csr-active-config.bin\" \"system-id.bin\"; do\n    if [[ -s \"${vm_name}_${filename}\" ]]; then\n        echo \"/ESP/EFI/NVRAM/${filename}=\\\"${vm_name}_${filename}\\\"\" >> \"${macOS_release_name}_installation_files.viso\"\n    fi\ndone\n\n# EFI drivers for VirtualBox 6.0 and 5.2\nfor filename in \"ApfsDriverLoader.efi\" \"AppleImageLoader.efi\" \"AppleUiSupport.efi\"; do\n    if [[ -s \"${filename}\" ]]; then\n        echo \"/ESP/EFI/OC/Drivers/${filename}=\\\"${filename}\\\"\" >> \"${macOS_release_name}_installation_files.viso\"\n    fi\ndone\n\n# EFI startup script\necho \"/ESP/startup.nsh=\\\"${vm_name}_startup.nsh\\\"\" >> \"${macOS_release_name}_installation_files.viso\"\n\n}\n\nfunction configure_vm() {\nprint_dimly \"stage: configure_vm\"\nif [[ -n \"$(\n            VBoxManage modifyvm \"${vm_name}\" --cpu-profile \"${cpu_profile}\" --cpus \"${cpu_count}\" \\\n            --memory \"${memory_size}\" --vram \"${gpu_vram}\" --pae on \\\n            --boot1 none --boot2 none --boot3 none --boot4 none \\\n            --firmware efi --rtcuseutc on --chipset ich9 ${extension_pack_usb3_support} \\\n            --mouse usbtablet --keyboard usb 2>&1 >/dev/null\n           )\" ]]; then\n    echo -e \"\\nError: Could not configure virtual machine \\\"${vm_name}\\\".\"\n    echo -e \"If the VM is powered on, power off the virtual machine and resume the script or\"\n    echo -e \"execute the stage ${low_contrast_color}configure_vm${default_color}\\n\"\n    echo \"Exiting.\"\n    exit\nfi\n\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal2/EfiGraphicsResolution\" \"${resolution}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiSystemFamily\" \"${DmiSystemFamily}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiSystemProduct\" \"${DmiSystemProduct}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiSystemSerial\" \"${DmiSystemSerial}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiSystemUuid\" \"${DmiSystemUuid}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiOEMVBoxVer\" \"${DmiOEMVBoxVer}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiOEMVBoxRev\" \"${DmiOEMVBoxRev}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiBIOSVersion\" \"${DmiBIOSVersion}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiBoardProduct\" \"${DmiBoardProduct}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiBoardSerial\" \"${DmiBoardSerial}\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiSystemVendor\" \"Apple Inc.\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/efi/0/Config/DmiSystemVersion\" \"1.0\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/smc/0/Config/DeviceKey\" \\\n  \"ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc\"\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/Devices/smc/0/Config/GetKeyFromRealSMC\" 0\nVBoxManage setextradata \"${vm_name}\" \\\n \"VBoxInternal/TM/TSCMode\" \"RealTSCOffset\"  # avoid boot loop when upgrading to Monterey\n}\n\n# Create the macOS base system virtual disk image\nfunction populate_basesystem_virtual_disk() {\nprint_dimly \"stage: populate_basesystem_virtual_disk\"\n[[ -s \"${macOS_release_name}_BaseSystem.${storage_format}\" ]] && echo \"${macOS_release_name}_BaseSystem.${storage_format} bootstrap virtual disk image exists.\" && return\n[[ ! -s \"${macOS_release_name}_BaseSystem.dmg\" ]] && echo -e \"\\nCould not find ${macOS_release_name}_BaseSystem.dmg; exiting.\" && exit\necho \"Converting BaseSystem.dmg to BaseSystem.img\"\ndmg2img \"${macOS_release_name}_BaseSystem.dmg\" \"${macOS_release_name}_BaseSystem.img\"\nVBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\nVBoxManage closemedium \"${macOS_release_name}_BaseSystem.${storage_format}\" >/dev/null 2>&1\nlocal success=''\nVBoxManage convertfromraw --format \"${storage_format}\" \"${macOS_release_name}_BaseSystem.img\" \"${macOS_release_name}_BaseSystem.${storage_format}\" && local success=\"True\"\nif [[ \"${success}\" = \"True\" ]]; then\n    command rm \"${macOS_release_name}_BaseSystem.img\" 2>/dev/null\n    return\nfi\necho \"Failed to create \\\"${macOS_release_name}_BaseSystem.${storage_format}\\\".\"\nif [[ \"$(cat /proc/sys/kernel/osrelease 2>/dev/null)\" =~ [Mm]icrosoft ]]; then\n    echo -e \"\\nSome versions of WSL require the script to execute on a Windows filesystem path,\"\n    echo -e \"for example   ${highlight_color}/mnt/c/Users/Public/Documents${default_color}\"\n    echo -e \"Switch to a path on the Windows filesystem if VBoxManage.exe fails to\"\n    echo -e \"create or open a file.\\n\"\nfi\necho \"Exiting.\"\nexit\n}\n\n# Create the installation media virtual disk image\nfunction create_bootable_installer_virtual_disk() {\nprint_dimly \"stage: create_bootable_installer_virtual_disk\"\nif [[ -w \"${macOS_release_name}_bootable_installer.${storage_format}\" ]]; then\n    echo \"\\\"${macOS_release_name}_bootable_installer.${storage_format}\\\" virtual disk image exists.\"\n    echo -ne \"${warning_color}Delete \\\"${macOS_release_name}_bootable_installer.${storage_format}\\\"?${default_color}\"\n    prompt_delete_y_n\n    if [[ \"${delete}\" == \"y\" ]]; then\n        if [[ \"$( VBoxManage list runningvms )\" =~ \\\"\"${vm_name}\"\\\" ]]\n        then\n            echo \"\\\"${macOS_release_name}_bootable_installer.${storage_format}\\\" may be deleted\"\n            echo \"only when the virtual machine is powered off.\"\n            echo \"Exiting.\"\n            exit\n        else\n            VBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\n            VBoxManage closemedium \"${macOS_release_name}_bootable_installer.${storage_format}\" >/dev/null 2>&1\n            command rm \"${macOS_release_name}_bootable_installer.${storage_format}\"\n        fi\n    else\n        echo \"Exiting.\"\n        exit\n    fi\nfi\nif [[ ! -e \"${macOS_release_name}_bootable_installer.${storage_format}\" ]]; then\n    echo \"Creating ${macOS_release_name} installation media virtual disk image.\"\n    VBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\n    VBoxManage closemedium \"${macOS_release_name}_bootable_installer.${storage_format}\" >/dev/null 2>&1\n    VBoxManage createmedium --size=12000 \\\n                            --format \"${storage_format}\" \\\n                            --filename \"${macOS_release_name}_bootable_installer.${storage_format}\" \\\n                            --variant standard 2>/dev/tty\nfi\n}\n\nfunction populate_bootable_installer_virtual_disk() {\nprint_dimly \"stage: populate_bootable_installer_virtual_disk\"\n# Attach virtual disk images of the base system, installation, and target\n# to the virtual machine\nVBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\n\nif [[ -n $(\n           2>&1 VBoxManage storagectl \"${vm_name}\" --add sata --name SATA --hostiocache on >/dev/null\n          ) ]]; then echo \"Could not configure virtual machine storage controller. Exiting.\"; exit; fi\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 1 --hotpluggable on \\\n               --type hdd --nonrotational on --medium \"${macOS_release_name}_bootable_installer.${storage_format}\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${macOS_release_name}_bootable_installer.${storage_format}\\\". Exiting.\"; exit; fi\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 2 \\\n               --type dvddrive --medium \"${macOS_release_name}_installation_files.viso\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${macOS_release_name}_installation_files.viso\\\". Exiting.\"; exit; fi\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 3 --hotpluggable on \\\n               --type hdd --nonrotational on --medium \"${macOS_release_name}_BaseSystem.${storage_format}\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${macOS_release_name}_BaseSystem.${storage_format}\\\". Exiting.\"; exit; fi\n\necho -e \"\\nCreating VirtualBox 6 virtual ISO containing macOS Terminal script\"\necho -e \"for partitioning and populating the bootable installer virtual disk.\\n\"\ncreate_viso_header \"${vm_name}_populate_bootable_installer_virtual_disk.viso\" \"bootinst-sh\"\necho \"/bootinst.sh=\\\"${vm_name}_bootinst.txt\\\"\" >> \"${vm_name}_populate_bootable_installer_virtual_disk.viso\"\n# Assigning \"physical\" disks from largest to smallest to \"${disks[]}\" array\n# Partitioning largest disk as APFS\n# Partition second-largest disk as JHFS+\necho '# this script is executed on the macOS virtual machine' > \"${vm_name}_bootinst.txt\"\necho 'disks=\"$(diskutil list | grep -o \"\\*[0-9][^ ]* [GTP]B *disk[0-9]$\" | grep -o \"[0-9].*\")\" && \\\ndisks=\"$(echo \"${disks}\" | sed -e \"s/\\.[0-9] T/000.0 G/\" -e \"s/\\.[0-9] P/000000.0 G/\" | sort -gr | grep -o disk[0-9] )\" && \\\ndisks=(${disks[@]}) && \\\nif [ -z \"${disks}\" ]; then echo \"Could not find disks\"; fi && \\\n[ -n \"${disks[0]}\" ] && \\\ndiskutil partitionDisk \"/dev/${disks[0]}\" 1 GPT JHFS+ \"Install\" R && \\' >> \"${vm_name}_bootinst.txt\"\n# Create secondary base system on the Install disk\n# and copy macOS install app files to the app directory\necho 'asr restore --source \"/Volumes/'\"${macOS_release_name:0:5}-files\"'/BaseSystem.dmg\" --target /Volumes/Install --erase --noprompt && \\\napp_path=\"$(ls -d \"/Volumes/\"*\"Base System 1/Install\"*.app)\" && \\\ninstall_path=\"${app_path}/Contents/SharedSupport/\" && \\\nmkdir -p \"${install_path}\" && cd \"/Volumes/'\"${macOS_release_name:0:5}-files/\"'\" && \\\ncp *.chunklist *.plist *.dmg \"${install_path}\" && \\\necho \"\" && echo \"Copying the several-GB InstallESD.dmg to the installer app directory\" && echo \"Please wait\" && \\\nif [ -s \"${install_path}/InstallESD.dmg\" ]; then \\\nrm -f \"${install_path}/InstallESD.dmg\" ; fi && \\\nfor part in InstallESD.part*; do echo \"Concatenating ${part}\"; cat \"${part}\" >> \"${install_path}/InstallESD.dmg\"; done && \\\nsed -i.bak -e \"s/InstallESDDmg\\.pkg/InstallESD.dmg/\" -e \"s/pkg\\.InstallESDDmg/dmg.InstallESD/\" \"${install_path}InstallInfo.plist\" && \\\nsed -i.bak2 -e \"/InstallESD\\.dmg/{n;N;N;N;d;}\" \"${install_path}InstallInfo.plist\" && \\' >> \"${vm_name}_bootinst.txt\"\n# shut down the virtual machine\necho 'shutdown -h now' >> \"${vm_name}_bootinst.txt\"\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 4 \\\n               --type dvddrive --medium \"${vm_name}_populate_bootable_installer_virtual_disk.viso\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${vm_name}_populate_bootable_installer_virtual_disk.viso\\\". Exiting.\"; exit; fi\necho -e \"\\nStarting virtual machine \\\"${vm_name}\\\".\nThis should take a couple of minutes. If booting fails, exit the script by\npressing CTRL-C then see the documentation for information about applying\ndifferent CPU profiles in the section ${highlight_color}CPU profiles and CPUID settings${default_color}.\"\n( VBoxManage startvm \"${vm_name}\" >/dev/null 2>&1 )\necho -e \"\\nUntil the script completes, please do not manually interact with\\nthe virtual machine.\"\n[[ -z \"${kscd}\" ]] && declare_scancode_dict\nprompt_lang_utils_terminal\nkbstring='/Volumes/bootinst-sh/bootinst.sh'\nsend_keys\nsend_enter\necho -e \"\\nPartitioning the bootable installer virtual disk; loading base system onto the\ninstaller virtual disk; moving installation files to installer virtual disk;\nupdating the InstallInfo.plist file; and rebooting the virtual machine.\n\nThe virtual machine may report that disk space is critically low; this is fine.\n\nWhen the bootable installer virtual disk is finished being populated, the script\nwill shut down the virtual machine. After shutdown, the initial base system will\nbe detached from the VM and released from VirtualBox.\"\nprint_dimly \"If the partitioning fails, exit the script by pressing CTRL-C\"\nprint_dimly \"Otherwise, please wait.\"\nwhile [[ \"$( VBoxManage list runningvms )\" =~ \\\"\"${vm_name}\"\\\" ]]; do sleep 2 >/dev/null 2>&1; done\necho \"Waiting for the VirtualBox GUI to shut off.\"\nanimated_please_wait 10\n# Detach the original 2GB BaseSystem virtual disk image\n# and release basesystem VDI from VirtualBox configuration\nif [[ -n $(\n    2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 3 --medium none >/dev/null\n    2>&1 VBoxManage closemedium \"${macOS_release_name}_BaseSystem.${storage_format}\" >/dev/null\n    ) ]]; then\n    echo \"Could not detach ${macOS_release_name}_BaseSystem.${storage_format}\"\n    echo \"The script will try to detach the virtual disk image. If this takes more than\"\n    echo \"a few seconds, terminate the script with CTRL-C, manually shut down VirtualBox,\"\n    echo \"and resume with the following stages as described in the documentation:\"\n    echo \"      ${highlight_color}create_target_virtual_disk populate_macos_target_disk${default_color}\"\n    while [[ -n $(\n        2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 3 --medium none >/dev/null\n        2>&1 VBoxManage closemedium \"${macOS_release_name}_BaseSystem.${storage_format}\" >/dev/null\n        ) ]]; do\n        animated_please_wait 10\n    done\nfi\necho -e \"\\n${macOS_release_name}_BaseSystem.${storage_format} successfully detached from\"\necho \"the virtual machine and released from VirtualBox Manager.\"\n}\n\nfunction create_target_virtual_disk() {\nprint_dimly \"stage: create_target_virtual_disk\"\nif [[ -w \"${vm_name}.${storage_format}\" ]]; then\n    echo \"${vm_name}.${storage_format} target system virtual disk image exists.\"\n    echo -ne \"${warning_color}Delete \\\"${vm_name}.${storage_format}\\\"?${default_color}\"\n    prompt_delete_y_n\n    if [[ \"${delete}\" == \"y\" ]]; then\n        if [[ \"$( VBoxManage list runningvms )\" =~ \\\"\"${vm_name}\"\\\" ]]\n        then\n            echo \"\\\"${vm_name}.${storage_format}\\\" may be deleted\"\n            echo \"only when the virtual machine is powered off.\"\n            echo \"Exiting.\"\n            exit\n        else\n            VBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\n            VBoxManage closemedium \"${vm_name}.${storage_format}\" >/dev/null 2>&1\n            command rm \"${vm_name}.${storage_format}\"\n        fi\n    else\n        echo \"Exiting.\"\n        exit\n    fi\nfi\nif [[ \"${macOS_release_name}\" = \"Catalina\" && \"${storage_size}\" -lt 25000 ]]; then\n    echo \"Attempting to install macOS Catalina on a disk smaller than 25000MB will fail.\"\n    echo \"Please assign a larger virtual disk image size. Exiting.\"\n    exit\nelif [[ \"${storage_size}\" -lt 22000 ]]; then\n    echo \"Attempting to install macOS on a disk smaller than 22000MB will fail.\"\n    echo \"Please assign a larger virtual disk image size. Exiting.\"\n    exit\nfi\nif [[ ! -e \"${vm_name}.${storage_format}\" ]]; then\n    echo \"Creating target system virtual disk image for \\\"${vm_name}\\\"\"\n    VBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\n    VBoxManage closemedium \"${vm_name}.${storage_format}\" >/dev/null 2>&1\n    VBoxManage createmedium --size=\"${storage_size}\" \\\n                            --format \"${storage_format}\" \\\n                            --filename \"${vm_name}.${storage_format}\" \\\n                            --variant standard 2>/dev/tty\nfi\n}\n\nfunction populate_macos_target_disk() {\nprint_dimly \"stage: populate_macos_target_disk\"\nif [[ \"$( VBoxManage list runningvms )\" =~ \\\"\"${vm_name}\"\\\" ]]; then\n    echo -e \"${highlight_color}Please ${warning_color}manually${highlight_color} shut down the virtual machine and press enter to continue.${default_color}\"\n    clear_input_buffer_then_read\nfi\nVBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\nif [[ -n $(\n           2>&1 VBoxManage storagectl \"${vm_name}\" --add sata --name SATA --hostiocache on >/dev/null\n          ) ]]; then echo \"Could not configure virtual machine storage controller. Exiting.\"; exit; fi\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 0 \\\n               --type hdd --nonrotational on --medium \"${vm_name}.${storage_format}\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${vm_name}.${storage_format}\\\". Exiting.\"; exit; fi\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 1 --hotpluggable on \\\n               --type hdd --nonrotational on --medium \"${macOS_release_name}_bootable_installer.${storage_format}\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${macOS_release_name}_bootable_installer.${storage_format}\\\". Exiting.\"; exit; fi\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 2 \\\n               --type dvddrive --medium \"${macOS_release_name}_installation_files.viso\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${macOS_release_name}_installation_files.viso\\\". Exiting.\"; exit; fi\n\necho -e \"\\nCreating VirtualBox 6 virtual ISO containing macOS Terminal scripts\"\necho -e \"for partitioning and populating the target virtual disk.\\n\"\ncreate_viso_header \"${vm_name}_populate_macos_target_disk.viso\" \"target-sh\"\necho \"/nvram.sh=\\\"${vm_name}_configure_nvram.txt\\\"\" >> \"${vm_name}_populate_macos_target_disk.viso\"\necho \"/startosinstall.sh=\\\"${vm_name}_startosinstall.txt\\\"\" >> \"${vm_name}_populate_macos_target_disk.viso\"\n# execute script concurrently, catch SIGUSR1 when installer finishes preparing\necho '# this script is executed on the macOS virtual machine' > \"${vm_name}_configure_nvram.txt\"\necho 'printf '\"'\"'trap \"exit 0\" SIGUSR1; while true; do sleep 10; done;'\"'\"' | sh && \\\ndisks=\"$(diskutil list | grep -o \"[0-9][^ ]* [GTP]B *disk[0-9]$\")\" && \\\ndisks=\"$(echo \"${disks}\" | sed -e \"s/\\.[0-9] T/000.0 G/\" -e \"s/\\.[0-9] P/000000.0 G/\" | sort -gr | grep -o disk[0-9])\" && \\\ndisks=(${disks[@]}) && \\\nmkdir -p \"/Volumes/'\"${vm_name}\"'/tmp/mount_efi\" && \\\nmount_msdos /dev/${disks[0]}s1 \"/Volumes/'\"${vm_name}\"'/tmp/mount_efi\" && \\\ncp -r \"/Volumes/'\"${macOS_release_name:0:5}-files\"'/ESP/\"* \"/Volumes/'\"${vm_name}\"'/tmp/mount_efi/\" && \\\ninstaller_pid=$(ps | grep startosinstall | grep -v grep | cut -d '\"'\"' '\"'\"' -f 3) && \\\nkill -SIGUSR1 ${installer_pid}' >> \"${vm_name}_configure_nvram.txt\"\n# Find background process PID, then\n# start the installer, send SIGUSR1 to concurrent bash script,\n# the other script copies files to EFI system partition,\n# then sends SIGUSR1 to the installer which restarts the virtual machine\necho '# this script is executed on the macOS virtual machine' > \"${vm_name}_startosinstall.txt\"\necho 'background_pid=\"$(ps | grep '\"'\"' sh$'\"'\"' | cut -d '\"'\"' '\"'\"' -f 3)\" && \\\n[[ \"${background_pid}\" =~ ^[0-9][0-9]*$ ]] && \\\ndisks=\"$(diskutil list | grep -o \"[0-9][^ ]* [GTP]B *disk[0-9]$\")\" && \\\ndisks=\"$(echo \"${disks}\" | sed -e \"s/\\.[0-9] T/000.0 G/\" -e \"s/\\.[0-9] P/000000.0 G/\" | sort -gr | grep -o disk[0-9])\" && \\\ndisks=(${disks[@]}) && \\\n[ -n \"${disks[0]}\" ] && \\\ndiskutil partitionDisk \"/dev/${disks[0]}\" 1 GPT APFS \"'\"${vm_name}\"'\" R && \\\napp_path=\"$(ls -d /Install*.app)\" && \\\ncd \"/${app_path}/Contents/Resources/\" && \\\n./startosinstall --agreetolicense --pidtosignal ${background_pid} --rebootdelay 90 --volume \"/Volumes/'\"${vm_name}\"'\"' >> \"${vm_name}_startosinstall.txt\"\nif [[ -n $(\n           2>&1 VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 3 \\\n               --type dvddrive --medium \"${vm_name}_populate_macos_target_disk.viso\" >/dev/null\n          ) ]]; then echo \"Could not attach \\\"${vm_name}_populate_macos_target_disk.viso\\\". Exiting.\"; exit; fi\necho \"The VM will boot from the populated installer base system virtual disk.\"\n( VBoxManage startvm \"${vm_name}\" >/dev/null 2>&1 )\n[[ -z \"${kscd}\" ]] && declare_scancode_dict\nprompt_lang_utils_terminal\nadd_another_terminal\necho -e \"\\nThe second open Terminal in the virtual machine copies EFI and NVRAM files\"\necho -e \"to the target EFI system partition when the installer finishes preparing.\"\necho -e \"\\nAfter the installer finishes preparing and the EFI and NVRAM files are copied,\"\necho -ne \"macOS will install and boot up when booting the target disk.\\n\"\nprint_dimly \"Please wait\"\nkbstring='/Volumes/target-sh/nvram.sh'\nsend_keys\nsend_enter\ncycle_through_terminal_windows\nkbstring='/Volumes/target-sh/startosinstall.sh'\nsend_keys\nsend_enter\nif [[ ! ( \"${vbox_version:0:1}\" -gt 6\n        || ( \"${vbox_version:0:1}\" = 6 && \"${vbox_version:2:1}\" -ge 1 ) ) ]]; then\n    echo -e \"\\n${highlight_color}When the installer finishes preparing and reboots the VM, press enter${default_color} so the script\npowers off the virtual machine and detaches the device \\\"${macOS_release_name}_bootable_installer.${storage_format}\\\" to avoid\nbooting into the initial installer environment again.\"\n    clear_input_buffer_then_read\n    VBoxManage controlvm \"${vm_name}\" poweroff >/dev/null 2>&1\n    for (( i=10; i>0; i-- )); do echo -ne \"   \\r${i} \"; sleep 0.5; done; echo -ne \"\\r   \"\n    VBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\n    VBoxManage storagectl \"${vm_name}\" --add sata --name SATA --hostiocache on >/dev/null 2>&1\n    VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 0 \\\n               --type hdd --nonrotational on --medium \"${vm_name}.${storage_format}\"\nfi\necho -e \"\\nFor further information, such as applying EFI and NVRAM variables to enable\niMessage connectivity, see the documentation with the following command:\\n\"\nwould_you_like_to_know_less\necho -e \"\\n${highlight_color}If the Terminal window progress counter reaches 100% and reboots into${default_color}\"\necho -e \"${highlight_color}an Apple macOS installer progress bar, that's it! Enjoy your virtual machine.${default_color}\\n\"\n}\n\nfunction prompt_delete_temporary_files() {\nprint_dimly \"stage: prompt_delete_temporary_files\"\nif [[ ! \"$(VBoxManage showvminfo \"${vm_name}\")\" =~ State:[\\ \\t]*powered\\ off ]]\nthen\n    echo -e \"Temporary files may be deleted when the virtual machine is powered off\nand without a suspended state by executing the following command at the script's\nworking directory:\n\n  ${highlight_color}${0} prompt_delete_temporary_files${default_color}\"\nelse\n    # detach temporary VDIs and attach the macOS target disk\n    VBoxManage storagectl \"${vm_name}\" --remove --name SATA >/dev/null 2>&1\n    VBoxManage storagectl \"${vm_name}\" --add sata --name SATA --hostiocache on >/dev/null 2>&1\n    if [[ -s \"${vm_name}.${storage_format}\" ]]; then\n        VBoxManage storageattach \"${vm_name}\" --storagectl SATA --port 0 \\\n                   --type hdd --nonrotational on --medium \"${vm_name}.${storage_format}\"\n    fi\n    VBoxManage closemedium \"${macOS_release_name}_bootable_installer.${storage_format}\" >/dev/null 2>&1\n    VBoxManage closemedium \"${macOS_release_name}_BaseSystem.${storage_format}\" >/dev/null 2>&1\n    echo -e \"The following temporary files are safe to delete:\\n\"\n    temporary_files=(\"${macOS_release_name}_Apple\"*\n                     \"${macOS_release_name}_BaseSystem\"*\n                     \"${macOS_release_name}_Install\"*\n                     \"${macOS_release_name}_bootable_installer\"*\n                     \"${macOS_release_name}_\"*\".viso\"\n                     \"${vm_name}_\"*\".png\"\n                     \"${vm_name}_\"*\".bin\"\n                     \"${vm_name}_\"*\".txt\"\n                     \"${vm_name}_\"*\".viso\"\n                     \"${vm_name}_startup.nsh\"\n                     \"ApfsDriverLoader.efi\"\n                     \"Apple\"*\".efi\"\n                     \"AppleSupport-v2.0.4-RELEASE.zip\"\n                     \"dmg2img.exe\")\n    ls -d \"${temporary_files[@]}\" 2>/dev/null\n    echo -ne \"\\n${warning_color}Delete temporary files listed above?${default_color}\"\n    prompt_delete_y_n\n    if [[ \"${delete}\" == \"y\" ]]; then\n        command rm -f \"${temporary_files[@]}\" 2>/dev/null\n    fi\nfi\n}\n\nfunction and_all_subsequent_stages() {\n    # if exactly two arguments were specified on the command line, and the first is a stage title,\n    # then perform all stages subsequent to the specified stage, otherwise do nothing.\n    [[ ${#specified_arguments[@]} -ne 2 ]] && return\n    for stage in \"${stages[@]}\"; do\n        [[ \"${stages[0]}\" = \"${specified_arguments[0]}\" ]] && break\n        stages=( \"${stages[@]:1}\" )\n    done\n    for stage in \"${stages[@]:1}\"; do ${stage}; done\n}\n\nfunction documentation() {\nlow_contrast_stages=\"\"\nfor stage in \"${stages[@]}\"; do\n    low_contrast_stages=\"${low_contrast_stages}\"'    '\"${low_contrast_color}${stage}${default_color}\"$'\\n'\ndone\necho -ne \"\\n        ${highlight_color}NAME${default_color}\nPush-button installer of macOS on VirtualBox\n\n        ${highlight_color}DESCRIPTION${default_color}\nThe script downloads macOS High Sierra, Mojave, and Catalina from Apple servers\nand installs them on VirtualBox 5.2, 6.0, and 6.1. The script doesn't install\nany closed-source additions or bootloaders. A default install requires the user\npress enter when prompted, less than ten times, to complete the installation.\nSystems with the package ${low_contrast_color}tesseract-ocr${default_color} may automate the installation completely.\n\n        ${highlight_color}USAGE${default_color}\n    ${low_contrast_color}${0} [STAGE]... ${default_color}\n\nThe installation is divided into stages. Stage titles may be given as command-\nline arguments for the script. When the script is executed with no command-line\narguments, each of the stages is performed in succession in the order listed:\n\n    ${low_contrast_color}check_shell${default_color}\n${low_contrast_stages}\nOther than the stages above, the command-line arguments \\\"${low_contrast_color}documentation${default_color}\\\",\n\\\"${low_contrast_color}troubleshoot${default_color}\\\", and \\\"${low_contrast_color}and_all_subsequent_stages${default_color}\\\" are available. \\\"${low_contrast_color}troubleshoot${default_color}\\\"\ngenerates a file with system information, VirtualBox logs, and checksums for\nsome installation files. \\\"${low_contrast_color}documentation${default_color}\\\" outputs the script's documentation.\nIf \\\"${low_contrast_color}documentation${default_color}\\\" is the first argument, no other arguments are parsed.\nIf the first argument is a stage title and the only other argument is\n\\\"${low_contrast_color}and_all_subsequent_stages${default_color}\\\", then the speficied stage and all subsequent\nstages are performed in succession in the order listed above;\notherwise, \\\"${low_contrast_color}and_all_subsequent_stages${default_color}\\\" does not perform any stages.\n\nThe stage \\\"${low_contrast_color}check_shell${default_color}\\\" is always performed when the script loads.\n\nThe stages \\\"${low_contrast_color}check_gnu_coreutils_prefix${default_color}\\\", \\\"${low_contrast_color}set_variables${default_color}\\\", and\n\\\"${low_contrast_color}check_dependencies${default_color}\\\" are always performed when any stage title other than\n\\\"${low_contrast_color}documentation${default_color}\\\" is specified as the first argument, and the rest of the\nspecified stages are performed only after the checks pass.\n\n        ${highlight_color}EXAMPLES${default_color}\n    ${low_contrast_color}${0} create_vm configure_vm${default_color}\n\nThe above command might be used to create and configure a virtual machine on a\nnew VirtualBox installation, then manually attach to the new virtual machine\nan existing macOS disk image that was previously created by the script.\n\n    ${low_contrast_color}${0} prompt_delete_temporary_files${default_color}\n\nThe above command might be used when no more virtual machines need to be\ninstalled, and the temporary files can be deleted.\n\n    ${low_contrast_color}${0} configure_vm and_all_subsequent_stages${default_color}\n\nThe above command might be used to resume the script stages after the stage\n\\\"${low_contrast_color}configure_vm${default_color}\\\" failed.\n\n    ${low_contrast_color}${0} \"'\\\\'\"${default_color}\n${low_contrast_color}configure_vm create_nvram_files create_macos_installation_files_viso${default_color}\n\nThe above command might be used to update the EFI and NVRAM variables required\nfor iCloud and iMessage connectivity and other Apple-connected apps.\n\n        ${highlight_color}Configuration${default_color}\nThe script's default configuration is stored in the ${low_contrast_color}set_variables()${default_color} function at\nthe top of the script. No manual configuration is required to use the script.\n\nThe configuration may be manually edited either by editing the variable\nassignment in ${low_contrast_color}set_variables()${default_color} or by executing the following command:\n\n    ${low_contrast_color}export macos_vm_vars_file=/path/to/variable_assignment_file${default_color}\n\n\\\"${low_contrast_color}variable_assignment_file${default_color}\\\" is a plain text file that contains zero or more\nlines with a variable assignment for any variable specified in ${low_contrast_color}set_variables()${default_color},\nfor example ${low_contrast_color}macOS_release_name=\\\"HighSierra\\\"${default_color} or ${low_contrast_color}DmiSystemFamily=\\\"iMac\\\"${default_color}\n\n        ${highlight_color}iCloud and iMessage connectivity${default_color}\niCloud, iMessage, and other connected Apple services require a valid device\nname and serial number, board ID and serial number, and other genuine\n(or genuine-like) Apple parameters. Assigning these parameters is ${low_contrast_color}not required${default_color}\nwhen installing or using macOS, only when connecting to the iCloud app,\niMessage, and other apps that authenticate the device with Apple.\n\nThese are the variables that are usually required for iMessage connectivity:\n\n    ${low_contrast_color}DmiSystemFamily    # Model name${default_color}\n    ${low_contrast_color}DmiSystemProduct   # Model identifier${default_color}\n    ${low_contrast_color}DmiBIOSVersion     # Boot ROM version${default_color}\n    ${low_contrast_color}DmiSystemSerial    # System serial number${default_color}\n    ${low_contrast_color}DmiSystemUuid      # Hardware unique identifier${default_color}\n    ${low_contrast_color}ROM                # ROM identifier, stored in NVRAM${default_color}\n    ${low_contrast_color}MLB                # Main Logic Board serial, stored in NVRAM${default_color}\n    ${low_contrast_color}DmiBoardSerial     # Main Logic Board serial, stored in EFI${default_color}\n    ${low_contrast_color}DmiBoardProduct    # Product (board) identifier${default_color}\n    ${low_contrast_color}SystemUUID         # System unique identifier, stored in NVRAM${default_color}\n\nThese parameters may be manually set in the ${low_contrast_color}set_variables()${default_color} function when the\n\\\"${low_contrast_color}get_parameters_from_macOS_host${default_color}\\\" is set to \\\"${low_contrast_color}no${default_color}\\\", which is the default setting. When\nthe script is executed on macOS and the variable \\\"${low_contrast_color}get_parameters_from_macOS_host${default_color}\\\" is\nset to \\\"${low_contrast_color}yes${default_color}\\\", the script copies the parameters from the host.\n\n        ${highlight_color}Applying the EFI and NVRAM parameters${default_color}\nThe EFI and NVRAM parameters may be set in the script before installation by\nediting them at the top of the script. NVRAM parameters may be applied after\nthe last step of the installation by resetting the virtual machine and booting\ninto the EFI Internal Shell. When resetting or powering up the VM, immediately\npress Esc when the VirtualBox logo appears. This boots into the EFI Internal\nShell or the boot menu. If the boot menu appears, select \\\"Boot Manager\\\" and\nthen \\\"EFI Internal Shell\\\" and then allow the ${low_contrast_color}startup.nsh${default_color} script to execute\nautomatically, applying the NVRAM variables before booting macOS.\n\n        ${highlight_color}Changing the EFI and NVRAM parameters after installation${default_color}\nThe variables mentioned above may be edited and applied to an existing macOS\nvirtual machine by deleting the ${low_contrast_color}.nvram${default_color} file from the directory where the\nvirtual machine ${low_contrast_color}.vbox${default_color} file is stored, then executing the following\ncommand and copying the generated files to the macOS EFI System Partition:\n\n    ${low_contrast_color}${0} \"'\\\\'\"${default_color}\n${low_contrast_color}configure_vm create_nvram_files create_macos_installation_files_viso${default_color}\n\nAfter executing the command, attach the resulting VISO file to the virtual\nmachine's storage through VirtualBox Manager or VBoxManage. Power up the VM\nand boot macOS, then start Terminal and execute the following commands, making\nsure to replace \\\"[VISO_mountpoint]\\\" with the correct path:\n\n    ${low_contrast_color}mkdir ESP${default_color}\n    ${low_contrast_color}sudo su # this will prompt for a password${default_color}\n    ${low_contrast_color}diskutil mount -mountPoint ESP disk0s1${default_color}\n    ${low_contrast_color}cp -r /Volumes/[VISO_mountpoint]/ESP/* ESP/${default_color}\n\nAfter copying the files, boot into the EFI Internal Shell as described in the\nsection \\\"Applying the EFI and NVRAM parameters\\\".\n\n        ${highlight_color}Storage format${default_color}\nThe script by default assigns a target virtual disk storage format of VDI. This\nformat can be resized by VirtualBox as explained in the next section. The other\navailable format, VMDK, cannot be resized by VirtualBox but can be attached to\na QEMU virtual machine for use with Linux KVM for better performance.\n\n        ${highlight_color}Storage size${default_color}\nThe script by default assigns a target virtual disk storage size of 80GB, which\nis populated to about 25GB on the host on initial installation. After the\ninstallation is complete, the VDI storage size may be increased. First increase\nthe virtual disk image size through VirtualBox Manager or VBoxManage, then in\nTerminal in the virtual machine execute the following command:\n    ${low_contrast_color}sudo diskutil repairDisk disk0${default_color}\nAfter it completes, open Disk Utility and delete the \\\"Free space\\\" partition so\nit allows the system APFS container to take up the available space, or if that\nfails, execute the following command:\n    ${low_contrast_color}sudo diskutil apfs resizeContainer disk1 0${default_color}\nBoth Disk Utility and ${low_contrast_color}diskutil${default_color} may fail and require successive resize attempts\nseparated by virtual machine reboots.\n\n        ${highlight_color}Primary display resolution${default_color}\nThe following command assigns the virtual machine primary display resolution:\n    ${low_contrast_color}VBoxManage setextradata \\\"\\${vm_name}\\\" \\\\${default_color}\n${low_contrast_color}\\\"VBoxInternal2/EfiGraphicsResolution\\\" \\\"\\${resolution}\\\"${default_color}\nThe following primary display resolutions are supported by macOS on VirtualBox:\n  ${low_contrast_color}5120x2880  2880x1800  2560x1600  2560x1440  1920x1200  1600x1200  1680x1050${default_color}\n  ${low_contrast_color}1440x900   1280x800   1024x768   640x480${default_color}\nSecondary displays can have an arbitrary resolution.\n\n        ${highlight_color}Unsupported features${default_color}\nDeveloping and maintaining VirtualBox or macOS features is beyond the scope of\nthis script. Some features may behave unexpectedly, such as USB device support,\naudio support, FileVault boot password prompt support, and other features.\n\n        ${highlight_color}CPU profiles and CPUID settings${default_color} (unsupported)\nmacOS does not support every CPU supported by VirtualBox. If the macOS Base\nSystem does not boot, try applying different CPU profiles to the virtual\nmachine with the ${low_contrast_color}VBoxManage${default_color} commands described below. First, while the\nVM is powered off, set the guest's CPU profile to the host's CPU profile, then\ntry to boot the virtual machine:\n    ${low_contrast_color}VBoxManage modifyvm \\\"\\${vm_name}\\\" --cpu-profile host${default_color}\n    ${low_contrast_color}VBoxManage modifyvm \\\"\\${vm_name}\\\" --cpuidremoveall${default_color}\nIf booting fails, try assigning each of the preconfigured CPU profiles while\nthe VM is powered off with the following command:\n    ${low_contrast_color}VBoxManage modifyvm \\\"\\${vm_name}\\\" --cpu-profile \\\"\\${cpu_profile}\\\"${default_color}\nAvailable CPU profiles:\n  ${low_contrast_color}\\\"Intel Xeon X5482 3.20GHz\\\"  \\\"Intel Core i7-2635QM\\\"  \\\"Intel Core i7-3960X\\\"${default_color}\n  ${low_contrast_color}\\\"Intel Core i5-3570\\\"  \\\"Intel Core i7-5600U\\\"  \\\"Intel Core i7-6700K\\\"${default_color}\nIf booting fails after trying each preconfigured CPU profile, the host's CPU\nrequires specific ${highlight_color}macOS VirtualBox CPUID settings${default_color}.\n\n        ${highlight_color}Performance and deployment${default_color} (unsupported)\nAfter successfully creating a working macOS virtual machine, consider importing\nthe virtual machine into more performant virtualization software, or packaging\nit for configuration management platforms for automated deployment. These\nvirtualization and deployment applications require additional configuration\nthat is beyond the scope of the script.\n\nQEMU with KVM is capable of providing virtual machine hardware passthrough\nfor near-native performance. QEMU supports the VMDK virtual disk image format,\nwhich can be configured to be created by the script, or converted from the\ndefault VirtualBox VDI format into the VMDK format with the following command:\n    ${low_contrast_color}VBoxManage clonehd --format vmdk source.vdi target.vmdk${default_color}\nQEMU and KVM require additional configuration that is beyond the scope of the\nscript.\n\n        ${highlight_color}VirtualBox Native Execution Manager${default_color} (unsupported)\nThe VirtualBox Native Execution Manager (NEM) is an experimental VirtualBox\nfeature. VirtualBox uses NEM when access to VT-x and AMD-V is blocked by\nvirtualization software or execution protection features such as Hyper-V,\nWindows Sandbox, WSL2, memory integrity protection, and other software.\nmacOS and the macOS installer have memory corruption issues under NEM\nvirtualization. The script checks for NEM and exits with an error message if\nNEM is detected.\n\n        ${highlight_color}Bootloaders${default_color} (unsupported)\nThe macOS VirtualBox guest is loaded without extra bootloaders, but it is\ncompatible with OpenCore. OpenCore requires additional configuration that is\nbeyond the scope of the script.\n\n        ${highlight_color}Display scaling${default_color} (unsupported)\nVirtualBox does not supply an EDID for its virtual display, and macOS does not\nenable display scaling (high PPI) without an EDID. The bootloader OpenCore can\ninject an EDID which enables display scaling.\n\n        ${highlight_color}Audio${default_color} (unsupported)\nmacOS may not support any built-in VirtualBox audio controllers. The bootloader\nOpenCore may be able to load open-source audio drivers in VirtualBox.\n\n        ${highlight_color}FileVault${default_color} (unsupported)\nThe VirtualBox EFI implementation does not properly load the FileVault full disk\nencryption password prompt upon boot. The bootloader OpenCore is be able to\nload the password prompt with the parameter \\\"ProvideConsoleGop\\\" set to \\\"true\\\".\n\n        ${highlight_color}Further information${default_color}\nFurther information is available at the following URL:\n        ${highlight_color}https://github.com/myspaghetti/macos-virtualbox${default_color}\n\n\"\n}\n\nfunction troubleshoot() {\necho -ne \"\\nWriting troubleshooting information to \\\"${highlight_color}${vm_name}_troubleshoot.txt${default_color}\\\"\\n\\n\"\necho \"The file will contain system information, VirtualBox paths, logs, configuration,\"\necho \"macOS virtual machine details including ${highlight_color}serials entered in the script${default_color},\"\necho \"and macOS installation file md5 checksums.\"\necho \"When sharing this file, mind that it contains the above information.\"\necho \"\"\nfor wrapper in 1; do\n    echo \"################################################################################\"\n    head -n 5 \"${0}\"\n    if [[ -n \"$(md5sum --version 2>/dev/null)\" ]]; then\n        tail -n +60 \"${0}\" | md5sum 2>/dev/null\n    else\n        tail -n +60 \"${0}\" | md5 2>/dev/null\n    fi\n    echo \"################################################################################\"\n    echo \"BASH_VERSION ${BASH_VERSION}\"\n    vbox_ver=\"$(VBoxManage -v)\"\n    echo \"VBOX_VERSION ${vbox_ver//[$'\\r\\n']/}\"\n    macos_ver=\"$(sw_vers 2>/dev/null)\"\n    wsl_ver=\"$(cat /proc/sys/kernel/osrelease 2>/dev/null)\"\n    win_ver=\"$(cmd.exe /d/s/c call ver 2>/dev/null)\"\n    echo \"OS VERSION ${macos_ver}${wsl_ver}${win_ver//[$'\\r\\n']/}\"\n    echo \"################################################################################\"\n    echo \"vbox.log\"\n    VBoxManage showvminfo \"${vm_name}\" --log 0 2>&1\n    echo \"################################################################################\"\n    echo \"vminfo\"\n    VBoxManage showvminfo \"${vm_name}\" --machinereadable --details 2>&1\n    VBoxManage getextradata \"${vm_name}\" 2>&1\ndone > \"${vm_name}_troubleshoot.txt\"\necho \"Written configuration and logs to \\\"${highlight_color}${vm_name}_troubleshoot.txt${default_color}\\\"\"\necho \"Press CTRL-C to cancel checksums, or wait for checksumming to complete.\"\nfor wrapper in 1; do\n    echo \"################################################################################\"\n    echo \"md5 hashes\"\n    if [[ -n \"$(md5sum --version 2>/dev/null)\" ]]; then\n        md5sum \"${macOS_release_name}_BaseSystem\"* 2>/dev/null\n        md5sum \"${macOS_release_name}_Install\"* 2>/dev/null\n        md5sum \"${macOS_release_name}_Apple\"* 2>/dev/null\n    else\n        md5 \"${macOS_release_name}_BaseSystem\"* 2>/dev/null\n        md5 \"${macOS_release_name}_Install\"* 2>/dev/null\n        md5 \"${macOS_release_name}_Apple\"* 2>/dev/null\n    fi\n    echo \"################################################################################\"\ndone >> \"${vm_name}_troubleshoot.txt\"\nif [ -s \"${vm_name}_troubleshoot.txt\" ]; then\necho -ne \"\\nFinished writing to \\\"${highlight_color}${vm_name}_troubleshoot.txt${default_color}\\\"\\n\"\nfi\n}\n\n# GLOBAL VARIABLES AND FUNCTIONS THAT MIGHT BE CALLED MORE THAN ONCE\n\n# terminal text colors\nwarning_color=$'\\e[48;2;255;0;0m\\e[38;2;255;255;255m' # white on red\nhighlight_color=$'\\e[48;2;0;0;9m\\e[38;2;255;255;255m' # white on black\nlow_contrast_color=$'\\e[48;2;0;0;9m\\e[38;2;128;128;128m' # grey on black\ndefault_color=$'\\033[0m'\n\n# prints positional parameters in low contrast preceded and followed by newline\nfunction print_dimly() {\necho -e \"\\n${low_contrast_color}$@${default_color}\"\n}\n\n# don't need sleep when we can read!\nfunction sleep() {\n    read -t \"${1}\" >/dev/null 2>&1\n}\n\n# create a viso with no files\nfunction create_viso_header() {\n    # input: filename volume-id (two positional parameters, both required)\n    # output: nothing to stdout, viso file to working directory\n    local uuid=\"$(xxd -p -l 16 /dev/urandom)\"\n    local uuid=\"${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}\"\n    echo \"--iprt-iso-maker-file-marker-bourne-sh ${uuid}\n    --volume-id=${2}\" > \"${1}\"\n}\n\n# QWERTY-to-scancode dictionary. Hex scancodes, keydown and keyup event.\n# Virtualbox Mac scancodes found here:\n# https://wiki.osdev.org/PS/2_Keyboard#Scan_Code_Set_1\n# First half of hex code - press, second half - release, unless otherwise specified\nfunction declare_scancode_dict() {\n    declare -gA kscd\n    kscd=(\n        [\"ESC\"]=\"01 81\"\n        [\"1\"]=\"02 82\"\n        [\"2\"]=\"03 83\"\n        [\"3\"]=\"04 84\"\n        [\"4\"]=\"05 85\"\n        [\"5\"]=\"06 86\"\n        [\"6\"]=\"07 87\"\n        [\"7\"]=\"08 88\"\n        [\"8\"]=\"09 89\"\n        [\"9\"]=\"0A 8A\"\n        [\"0\"]=\"0B 8B\"\n        [\"-\"]=\"0C 8C\"\n        [\"=\"]=\"0D 8D\"\n        [\"BKSP\"]=\"0E 8E\"\n        [\"TAB\"]=\"0F 8F\"\n        [\"q\"]=\"10 90\"\n        [\"w\"]=\"11 91\"\n        [\"e\"]=\"12 92\"\n        [\"r\"]=\"13 93\"\n        [\"t\"]=\"14 94\"\n        [\"y\"]=\"15 95\"\n        [\"u\"]=\"16 96\"\n        [\"i\"]=\"17 97\"\n        [\"o\"]=\"18 98\"\n        [\"p\"]=\"19 99\"\n        [\"[\"]=\"1A 9A\"\n        [\"]\"]=\"1B 9B\"\n        [\"ENTER\"]=\"1C 9C\"\n        [\"CTRLprs\"]=\"1D\"\n        [\"CTRLrls\"]=\"9D\"\n        [\"a\"]=\"1E 9E\"\n        [\"s\"]=\"1F 9F\"\n        [\"d\"]=\"20 A0\"\n        [\"f\"]=\"21 A1\"\n        [\"g\"]=\"22 A2\"\n        [\"h\"]=\"23 A3\"\n        [\"j\"]=\"24 A4\"\n        [\"k\"]=\"25 A5\"\n        [\"l\"]=\"26 A6\"\n        [\";\"]=\"27 A7\"\n        [\"'\"]=\"28 A8\"\n        ['`']=\"29 A9\"\n        [\"LSHIFTprs\"]=\"2A\"\n        [\"LSHIFTrls\"]=\"AA\"\n        ['\\']=\"2B AB\"\n        [\"z\"]=\"2C AC\"\n        [\"x\"]=\"2D AD\"\n        [\"c\"]=\"2E AE\"\n        [\"v\"]=\"2F AF\"\n        [\"b\"]=\"30 B0\"\n        [\"n\"]=\"31 B1\"\n        [\"m\"]=\"32 B2\"\n        [\",\"]=\"33 B3\"\n        [\".\"]=\"34 B4\"\n        [\"/\"]=\"35 B5\"\n        [\"RSHIFTprs\"]=\"36\"\n        [\"RSHIFTrls\"]=\"B6\"\n        [\"ALTprs\"]=\"38\"\n        [\"ALTrls\"]=\"B8\"\n        [\"LALT\"]=\"38 B8\"\n        [\"SPACE\"]=\"39 B9\"\n        [\" \"]=\"39 B9\"\n        [\"CAPS\"]=\"3A BA\"\n        [\"CAPSLOCK\"]=\"3A BA\"\n        [\"F1\"]=\"3B BB\"\n        [\"F2\"]=\"3C BC\"\n        [\"F3\"]=\"3D BD\"\n        [\"F4\"]=\"3E BE\"\n        [\"F5\"]=\"3F BF\"\n        [\"F6\"]=\"40 C0\"\n        [\"F7\"]=\"41 C1\"\n        [\"F8\"]=\"42 C2\"\n        [\"F9\"]=\"43 C3\"\n        [\"F10\"]=\"44 C4\"\n        [\"UP\"]=\"E0 48 E0 C8\"\n        [\"RIGHT\"]=\"E0 4D E0 CD\"\n        [\"LEFT\"]=\"E0 4B E0 CB\"\n        [\"DOWN\"]=\"E0 50 E0 D0\"\n        [\"HOME\"]=\"E0 47 E0 C7\"\n        [\"END\"]=\"E0 4F E0 CF\"\n        [\"PGUP\"]=\"E0 49 E0 C9\"\n        [\"PGDN\"]=\"E0 51 E0 D1\"\n        [\"CMDprs\"]=\"E0 5C\"\n        [\"CMDrls\"]=\"E0 DC\"\n        # all codes below start with LSHIFTprs as commented in first item:\n        [\"!\"]=\"2A 02 82 AA\" # LSHIFTprs 1prs 1rls LSHIFTrls\n        [\"@\"]=\"2A 03 83 AA\"\n        [\"#\"]=\"2A 04 84 AA\"\n        [\"$\"]=\"2A 05 85 AA\"\n        [\"%\"]=\"2A 06 86 AA\"\n        [\"^\"]=\"2A 07 87 AA\"\n        [\"&\"]=\"2A 08 88 AA\"\n        [\"*\"]=\"2A 09 89 AA\"\n        [\"(\"]=\"2A 0A 8A AA\"\n        [\")\"]=\"2A 0B 8B AA\"\n        [\"_\"]=\"2A 0C 8C AA\"\n        [\"+\"]=\"2A 0D 8D AA\"\n        [\"Q\"]=\"2A 10 90 AA\"\n        [\"W\"]=\"2A 11 91 AA\"\n        [\"E\"]=\"2A 12 92 AA\"\n        [\"R\"]=\"2A 13 93 AA\"\n        [\"T\"]=\"2A 14 94 AA\"\n        [\"Y\"]=\"2A 15 95 AA\"\n        [\"U\"]=\"2A 16 96 AA\"\n        [\"I\"]=\"2A 17 97 AA\"\n        [\"O\"]=\"2A 18 98 AA\"\n        [\"P\"]=\"2A 19 99 AA\"\n        [\"{\"]=\"2A 1A 9A AA\"\n        [\"}\"]=\"2A 1B 9B AA\"\n        [\"A\"]=\"2A 1E 9E AA\"\n        [\"S\"]=\"2A 1F 9F AA\"\n        [\"D\"]=\"2A 20 A0 AA\"\n        [\"F\"]=\"2A 21 A1 AA\"\n        [\"G\"]=\"2A 22 A2 AA\"\n        [\"H\"]=\"2A 23 A3 AA\"\n        [\"J\"]=\"2A 24 A4 AA\"\n        [\"K\"]=\"2A 25 A5 AA\"\n        [\"L\"]=\"2A 26 A6 AA\"\n        [\":\"]=\"2A 27 A7 AA\"\n        ['\"']=\"2A 28 A8 AA\"\n        [\"~\"]=\"2A 29 A9 AA\"\n        [\"|\"]=\"2A 2B AB AA\"\n        [\"Z\"]=\"2A 2C AC AA\"\n        [\"X\"]=\"2A 2D AD AA\"\n        [\"C\"]=\"2A 2E AE AA\"\n        [\"V\"]=\"2A 2F AF AA\"\n        [\"B\"]=\"2A 30 B0 AA\"\n        [\"N\"]=\"2A 31 B1 AA\"\n        [\"M\"]=\"2A 32 B2 AA\"\n        [\"<\"]=\"2A 33 B3 AA\"\n        [\">\"]=\"2A 34 B4 AA\"\n        [\"?\"]=\"2A 35 B5 AA\"\n    )\n}\n\nfunction clear_input_buffer_then_read() {\n    while read -d '' -r -t 0; do read -d '' -t 0.1 -n 10000; break; done\n    [[ $- =~ i ]] && read || echo \"\"\n}\n\n# read variable kbstring and convert string to scancodes and send to guest vm\nfunction send_keys() {\n    # It's faster to send all the scancodes at once, but some VM configurations\n    # accept scancodes sent by multiple VBoxManage commands concurrently instead\n    # of sequentially, and there's no built-in method to tell the host to wait\n    # until the scancodes have finished being entered.\n    # This leaves only the slow, keypress-by-keypress method.\n    for (( i=0; i < ${#kbstring}; i++ )); do\n        VBoxManage controlvm \"${vm_name}\" keyboardputscancode ${kscd[${kbstring:${i}:1}]} 1>/dev/null 2>&1\n    done\n}\n\n# read variable kbspecial and send keystrokes by name,\n# for example \"CTRLprs c CTRLrls\", and send to guest vm\nfunction send_special() {\n    for keypress in ${kbspecial}; do\n        VBoxManage controlvm \"${vm_name}\" keyboardputscancode ${kscd[${keypress}]} 1>/dev/null 2>&1\n    done\n}\n\nfunction send_enter() {\n    kbspecial=\"ENTER\"\n    send_special\n}\n\nfunction prompt_lang_utils_terminal() {\n    tesseract_ocr=\"$(tesseract --version 2>/dev/null)\"\n    tesseract_lang=\"$(tesseract --list-langs 2>/dev/null)\"\n    regex_ver='[Tt]esseract [45]'  # for zsh quoted regex compatibility\n    if [[ \"${tesseract_ocr}\" =~ ${regex_ver} && \"${tesseract_lang}\" =~ eng ]]; then\n        echo -e \"\\n${low_contrast_color}Attempting automated recognition of virtual machine graphical user interface.${default_color}\"\n        animated_please_wait 30\n        for i in $(seq 1 60); do  # try automatic ocr for about 5 minutes\n            VBoxManage controlvm \"${vm_name}\" screenshotpng \"${vm_name}_screenshot.png\" 2>&1 1>/dev/null\n            ocr=\"$(tesseract \"${vm_name}_screenshot.png\" - --psm 11 --dpi 72 -l eng 2>/dev/null)\"\n            regex_lang='Language|English|Fran.ais'  # for zsh quoted regex compatibility\n            regex_term='Terminal.Shell|Terminal.*sh.?-'  # for zsh quoted regex compatibility\n            if [[ \"${ocr}\" =~ ${regex_lang} ]]; then\n                animated_please_wait 20\n                send_enter\n                animated_please_wait 20\n            elif [[ \"${ocr}\" =~ Utilities ]]; then\n                animated_please_wait 20\n                kbspecial='CTRLprs F2 CTRLrls u ENTER t ENTER'  # start Terminal\n                send_special\n                animated_please_wait 20\n            elif [[ \"${ocr}\" =~ ${regex_term} ]]; then\n                sleep 2\n                return\n            fi\n            animated_please_wait 10\n        done\n        echo -e \"\\nFailed automated recognition of virtual machine graphical user interface.\\nPlease press enter as directed.\"\n    fi\n    echo -ne \"\\n${highlight_color}Press enter when the Language window is ready.${default_color}\"\n    clear_input_buffer_then_read\n    send_enter\n    echo -ne \"\\n${highlight_color}Press enter when the macOS Utilities window is ready.${default_color}\"\n    clear_input_buffer_then_read\n    kbspecial='CTRLprs F2 CTRLrls u ENTER t ENTER'  # start Terminal\n    send_special\n    echo -ne \"\\n${highlight_color}Press enter when the Terminal command prompt is ready.${default_color}\"\n    clear_input_buffer_then_read\n}\n\nfunction animated_please_wait() {\n    # \"Please wait\" prompt with animated dots.\n    # Accepts one optional positional parameter, an integer\n    # The parameter specifies how many half-seconds to wait\n    echo -ne \"\\r                 \\r${low_contrast_color}Please wait${default_color}\"\n    specified_halfseconds=5\n    [[ \"${1}\" =~ [^0-9] || -z \"${1}\" ]] || specified_halfseconds=${1}\n    for halfsecond in $(seq 1 ${specified_halfseconds}); do\n        echo -ne \"${low_contrast_color}.${default_color}\"\n        sleep 0.5\n        if [[ $(( halfsecond % 5 )) -eq 0 ]]; then\n            echo -ne \"\\r                 \\r${low_contrast_color}Please wait${default_color}\"\n        fi\n    done\n}\n\nfunction add_another_terminal() {\n    # at least one terminal has to be open before calling this function\n    kbspecial='CMDprs n CMDrls'\n    send_special\n    sleep 1\n}\n\nfunction cycle_through_terminal_windows() {\n    kbspecial='CMDprs ` CMDrls'\n    send_special\n    sleep 1\n}\n\nfunction would_you_like_to_know_less() {\n    if [[ -z \"$(less --version 2>/dev/null)\" ]]; then\n        echo -e \"  ${highlight_color}${0} documentation${default_color}\"\n    else\n        echo -e \"  ${highlight_color}${0} documentation | less -R${default_color}\"\n    fi\n}\n\nfunction prompt_delete_y_n() {\n    # workaround for zsh-bash differences in read\n    delete=\"\"\n    if [[ $- =~ i ]]; then  # terminal is interactive\n        if [[ -n \"${ZSH_VERSION}\" ]]; then\n            read -s -q delete\\?' [y/N] '\n            delete=\"${delete:l}\"\n        elif [[ -n \"${BASH_VERSION}\" ]]; then\n            read -n 1 -p ' [y/N] ' delete\n            delete=\"${delete,,}\"\n        fi\n    fi\n    echo \"\"\n}\n\n# command-line argument processing\ncheck_shell\nstages=(\n    check_gnu_coreutils_prefix\n    set_variables\n    welcome\n    check_dependencies\n    prompt_delete_existing_vm\n    create_vm\n    check_default_virtual_machine\n    prepare_macos_installation_files\n    create_nvram_files\n    create_macos_installation_files_viso\n    configure_vm\n    populate_basesystem_virtual_disk\n    create_bootable_installer_virtual_disk\n    populate_bootable_installer_virtual_disk\n    create_target_virtual_disk\n    populate_macos_target_disk\n    prompt_delete_temporary_files\n)\n\nother_commands=(\n    check_shell\n    troubleshoot\n    documentation\n    and_all_subsequent_stages\n)\n\n# script called without arguments\n[[ $# -eq 0 ]] && for stage in \"${stages[@]}\"; do ${stage}; done && exit\n\n# first argument is \"documentation\"\n[[ \"${1}\" == \"documentation\" ]] && documentation && exit\n\nspecified_arguments=(\"$@\")  # this variable is used in the function \"and_all_subsequent_stages\"\nsorted_unique_recognized_arguments=\"$( printf \"%s\\n\" ${stages[@]} ${other_commands[@]} | sort -bu )\"\nsorted_unique_recognized_and_specified_arguments=\"$( printf \"%s\\n\" ${stages[@]} ${other_commands[@]} $@ | sort -bu )\"\n# if a specified argument is different from any recognized argument\nif [[ \"${sorted_unique_recognized_and_specified_arguments}\" != \"${sorted_unique_recognized_arguments}\" ]]; then\n    echo -e \"\\nOne or more specified arguments is not recognized.\"\n    echo -e \"\\nRecognized stages:\\n\"\n    printf '    %s\\n' \"${stages[@]}\"\n    echo -e \"\\nOther recognized arguments:\\n\"\n    printf '    %s\\n' \"${other_commands[@]}\"\n    echo -e \"\\nView documentation by entering the following command:\"\n    would_you_like_to_know_less\n    exit\nfi\ncheck_gnu_coreutils_prefix\nset_variables\ncheck_dependencies\nfor argument; do ${argument}; done\n"
  }
]