diff --git a/CREDITS.md b/CREDITS.md index 6e52aab..87c893e 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -18,6 +18,8 @@ * Evgeny Grin (Karlson2k) - for the original ISO creation script -* Gabriel L. Somlo - for getting things started +* Gabriel L. Somlo - for getting things started and going * http://www.insanelymac.com/ - Enoch bootloader + +* Nicholas Sherlock - UEFI, Clover, and other hacks diff --git a/OVMF-notes.txt b/OVMF-notes.txt new file mode 100644 index 0000000..dd73a9f --- /dev/null +++ b/OVMF-notes.txt @@ -0,0 +1,20 @@ +Building OVMF +------------- + +git clone https://github.com/tianocore/edk2 +cd edk2 +make -C BaseTools +. edksetup.sh BaseTools +build -a X64 -t GCC5 -p OvmfPkg/OvmfPkgX64.dsc -b RELEASE + +The included blobs were built from commit 2913ebb2b550f50a. + +Host OS +------- + +OVMF blobs were built on Ubuntu 14.04.5 LTS (Trusty Tahr) + +References +---------- + +https://www.contrib.andrew.cmu.edu/~somlo/OSXKVM/ diff --git a/OVMF_CODE.fd b/OVMF_CODE.fd new file mode 100644 index 0000000..2303610 Binary files /dev/null and b/OVMF_CODE.fd differ diff --git a/OVMF_VARS.fd b/OVMF_VARS.fd new file mode 100644 index 0000000..efb4f46 Binary files /dev/null and b/OVMF_VARS.fd differ diff --git a/README.md b/README.md index 2e59b14..4d52d01 100644 --- a/README.md +++ b/README.md @@ -67,9 +67,9 @@ Intel VT-x / AMD SVM is required. ### Installation -To install OS X, you can use the included `boot.sh` / `boot-macOS.sh` scripts -for a more solid alternate to the following `virsh` method. Use either the -`boot*.sh` method or the following `virsh` method to install OS X / macOS. +To install OS X, you can use the included `boot-macOS.sh` script for a more +solid alternate to the following `virsh` method. Use either the `boot-macOS.sh` +method or the following `virsh` method to install OS X / macOS. * Edit `macOS-libvirt.xml` file and change file paths for `mac_hdd.qcow2` (HDD), `Install_OS_X_10.11_El_Capitan.iso` (bootable ISO image) and `enoch_rev2839_boot` suitably. @@ -185,7 +185,8 @@ for a more solid alternate to the following `virsh` method. Use either the * If the App Store doesn't work, check the [notes file](notes.md) for instructions on how to solve this. -* If you are getting "Dont_Steal_MacOS" related errors, see `FakeSMC installation` section in [notes file](notes.md). +* If you are getting "Dont_Steal_MacOS" related errors, see `Building QEMU` (recommended option) and + `FakeSMC installation` sections in [notes file](notes.md). * If the boot process is getting stuck on the Apple logo, upgrade your host kernel and QEMU. For example, Linux 3.16.x from Debian 8 is known to be @@ -199,3 +200,5 @@ for a more solid alternate to the following `virsh` method. Use either the * [Mac OS X 10.11 El Capitan – VM on unRAID](https://macosxvirtualmachinekvm.wordpress.com/guide-mac-os-x-10-11-el-capitan-vm-on-unraid/) * http://www.contrib.andrew.cmu.edu/~somlo/OSXKVM/ + +* http://forge.voodooprojects.org/p/chameleon/source/changes/HEAD/ (Enoch source) diff --git a/SmcDumpKey.c b/SmcDumpKey.c new file mode 100644 index 0000000..3d83a4f --- /dev/null +++ b/SmcDumpKey.c @@ -0,0 +1,193 @@ +/* + * prints out 4-character name of the SMC key at given index position; + * + * by Gabriel L. Somlo , Summer 2014 + * + * Compile with: gcc -O2 -o SmcDumpKey SmcDumpKey.c -Wall + * + * You probably want to "modprobe -r applesmc" before running this... + * + * Code bits and pieces shamelessly ripped from the linux kernel driver + * (drivers/hwmon/applesmc.c by N. Boichat and H. Rydberg) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License v2 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define APPLESMC_START 0x300 +#define APPLESMC_RANGE 0x20 + +#define APPLESMC_DATA_PORT (APPLESMC_START + 0x00) +#define APPLESMC_CMD_PORT (APPLESMC_START + 0x04) + +#define APPLESMC_READ_CMD 0x10 +#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 +#define APPLESMC_GET_KEY_TYPE_CMD 0x13 + + +/* wait up to 128 ms for a status change. */ +#define APPLESMC_MIN_WAIT 0x0010 +#define APPLESMC_RETRY_WAIT 0x0100 +#define APPLESMC_MAX_WAIT 0x20000 + + +#define APPLESMC_KEY_NAME_LEN 4 +#define APPLESMC_KEY_TYPE_LEN 4 + +typedef struct key_type { + uint8_t data_len; + uint8_t data_type[APPLESMC_KEY_TYPE_LEN]; + uint8_t flags; +} __attribute__((packed)) key_type; + + +/* wait_read - Wait for a byte to appear on SMC port. */ +static int +wait_read(void) +{ + uint8_t status; + int us; + + for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { + usleep(us); + status = inb(APPLESMC_CMD_PORT); + /* read: wait for smc to settle */ + if (status & 0x01) + return 0; + } + + fprintf(stderr, "wait_read() fail: 0x%02x\n", status); + return -1; +} + +/*send_byte - Write to SMC port, retrying when necessary. */ +static int +send_byte(uint8_t cmd, unsigned short port) +{ + uint8_t status; + int us; + + outb(cmd, port); + for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { + usleep(us); + status = inb(APPLESMC_CMD_PORT); + /* write: wait for smc to settle */ + if (status & 0x02) + continue; + /* ready: cmd accepted, return */ + if (status & 0x04) + return 0; + /* timeout: give up */ + if (us << 1 == APPLESMC_MAX_WAIT) + break; + /* busy: long wait and resend */ + usleep(APPLESMC_RETRY_WAIT); + outb(cmd, port); + } + + fprintf(stderr, + "send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status); + return -1; +} + +static int +send_argument(const uint8_t *key) +{ + int i; + + for (i = 0; i < APPLESMC_KEY_NAME_LEN; i++) + if (send_byte(key[i], APPLESMC_DATA_PORT)) + return -1; + return 0; +} + +static int +read_smc(uint8_t cmd, const uint8_t *key, uint8_t *buf, uint8_t len) +{ + int i; + + if (send_byte(cmd, APPLESMC_CMD_PORT) || send_argument(key)) { + fprintf(stderr, "%.4s: read arg fail\n", key); + return -1; + } + + if (send_byte(len, APPLESMC_DATA_PORT)) { + fprintf(stderr, "%.4s: read len fail\n", key); + return -1; + } + + for (i = 0; i < len; i++) { + if (wait_read()) { + fprintf(stderr, "%.4s: read data[%d] fail\n", key, i); + return -1; + } + buf[i] = inb(APPLESMC_DATA_PORT); + } + + return 0; +} + + +int +main(int argc, char **argv) +{ + key_type kt; + uint8_t data_buf[UCHAR_MAX]; + uint8_t i; + + if (argc != 2 || strlen(argv[1]) != APPLESMC_KEY_NAME_LEN) { + fprintf(stderr, "\nUsage: %s <4-char-key-name>\n\n", argv[0]); + return -1; + } + + if (ioperm(APPLESMC_START, APPLESMC_RANGE, 1) != 0) { + perror("ioperm failed"); + return -2; + } + + if (read_smc(APPLESMC_GET_KEY_TYPE_CMD, + (uint8_t *)argv[1], (uint8_t *)&kt, sizeof(kt)) != 0) { + fprintf(stderr, "\nread_smc get_key_type error\n\n"); + return -3; + } + printf(" type=\""); + for (i = 0; i < APPLESMC_KEY_TYPE_LEN; i++) + printf(isprint(kt.data_type[i]) ? "%c" : "\\x%02x", + (uint8_t)kt.data_type[i]); + printf("\" length=%d flags=%x\n", kt.data_len, kt.flags); + + if (read_smc(APPLESMC_READ_CMD, + (uint8_t *)argv[1], data_buf, kt.data_len) != 0) { + fprintf(stderr, "\nread_smc get_key_data error\n\n"); + return -4; + } + printf(" data=\""); + for (i = 0; i < kt.data_len; i++) + printf(isprint(data_buf[i]) ? "%c" : "\\x%02x", + (uint8_t)data_buf[i]); + printf("\"\n"); + + return 0; +} diff --git a/UEFI/.synergy.conf b/UEFI/.synergy.conf new file mode 100644 index 0000000..ac441b6 --- /dev/null +++ b/UEFI/.synergy.conf @@ -0,0 +1,12 @@ +# Run "synergys" on Linux host + +section: screens + uber: + mac: +end +section: links + uber: + right = mac + mac: + left = uber +end diff --git a/UEFI/Clover_v2.4k_r4152.pkg b/UEFI/Clover_v2.4k_r4152.pkg new file mode 100644 index 0000000..fa0bd00 Binary files /dev/null and b/UEFI/Clover_v2.4k_r4152.pkg differ diff --git a/UEFI/Clover_v2.4k_r4152.pkg.md5 b/UEFI/Clover_v2.4k_r4152.pkg.md5 new file mode 100644 index 0000000..1a0c32b --- /dev/null +++ b/UEFI/Clover_v2.4k_r4152.pkg.md5 @@ -0,0 +1 @@ +MD5 (sym/Clover_v2.4k_r4152.pkg) = adf87b4a9aa182859216dee0722a4dff diff --git a/UEFI/README.md b/UEFI/README.md new file mode 100644 index 0000000..be05c44 --- /dev/null +++ b/UEFI/README.md @@ -0,0 +1,152 @@ +### Setting up UEFI enabled macOS + +**This is under development. No support is provided for OVMF and Clover based +installations at the moment. Experiment at your own risk.** + +* Install macOS by following the usual Enoch method. + +* Build and use QEMU from https://github.com/kholia/qemu/. Use the "macOS" + branch. Clover + macOS will fail to boot without this step. + +* Install the included `Clover_v2*.pkg` on the main macOS disk. + + * Hit the `Customize` button during Clover install. + + * Tick 'Install for UEFI booting only', OsxAptioFix2Drv-64 and + PartitionDxe-64 options. + +* The Clover installer should leave the EFI partition mounted for us. Open that + up in Finder. + + * Replace the `EFI/CLOVER/config.plist` file with `config.plist` included in + this folder. + + * Put the included `q35-acpi-dsdt.aml` file into `EFI/CLOVER/ACPI/origin` + location. + +* You may edit `EFI/CLOVER/config.plist` to change the screen resolution from + `800x600` to a higher **supported** value. + + This change also requires a corresponding change in the OVMF settings. When + using OVMF with a virtual display (without VGA passthrough), you can set the + client resolution in the OVMF menu, which you can reach with a press of the + ESC button during the OVMF boot logo. In the OVMF menu settings, set Device + Manager -> OVMF Platform Configuration -> Change Preferred Resolution for Next + Boot to a supported value. Commit changes and exit the OVMF settings. + Relaunch the `boot-macOS` script. + +* Finally, use `boot-clover.sh` to use OVMF/UEFI to boot macOS with Clover. + +* You can use `Clover Configurator` to modify your Clover configuration, if + required. + + +### GPU passthrough notes + +These steps will need to be adapted for your particular setup. A host machine +with IOMMU support is required. Consult the Arch Wiki article linked to at the +bottom of this file for exact requirements and other details. + +I am running Ubuntu 17.04 on Intel i5-6500 + ASUS Z170-AR motherboard + NVIDIA +1050 Ti. + +* Enable IOMMU support on the host machine. + + Add `iommu=pt intel_iommu=on video=efifb:off` to the `GRUB_CMDLINE_LINUX_DEFAULT` line in `/etc/default/grub` file. + +* Uninstall NVIDIA drivers from the host machine and blacklist the required modules. + + ``` + $ cat /etc/modprobe.d/blacklist.conf + ... + + blacklist radeon + blacklist nouveau + blacklist nvidia + ``` + +* Enable the required kernel modules. + + ``` + # echo "vfio" >> /etc/modules + # echo "vfio_iommu_type1" >> /etc/modules + # echo "vfio_pci" >> /etc/modules + # echo "vfio_virqfd" >> /etc/modules + ``` + +* Isolate the passthrough PCIe devices with vfio-pci, with the help of `lspci + -nnk` command. Adapt these commands to suit your hardware setup. + + ``` + $ lspci -nn + ... + 01:00.0 ... NVIDIA Corporation [GeForce GTX 1050 Ti] [10de:1c82] + 01:00.1 Audio device: NVIDIA Corporation Device [10de:0fb9] + 03:00.0 USB controller: ASMedia ASM1142 USB 3.1 Host Controller [1b21:1242] + ``` + + ``` + # echo "options vfio-pci ids=10de:1c82,10de:0fb9 disable_vga=1" > /etc/modprobe.d/vfio.conf + ``` + +* Update initramfs, GRUB and then reboot. + + ``` + $ sudo update-grub2 + $ sudo update-initramfs -k all -u + ``` + +* Verify that the IOMMU is enabled, and vfio_pci is working as expected. + Consult Arch Wiki again for help on this. + +* On the macOS VM, install a NVIDIA Web Driver version which is appropriate for + the macOS version. Consult http://www.macvidcards.com/drivers.html for more + information. + + For example, macOS 10.12.5 requires version `378.05.05.15f01` whereas macOS + 10.12.6 requires version `378.05.05.25f01`. + +* Boot the macOS VM using the `boot-passthrough.sh` script. At this point, the + display connected to your passthrough PCIe device should turn on, and you + should see the Clover boot screen. Using the keyboard, navigate to Options -> + Graphics Injectord, and enable `Use NVIDIA Web Driver`, then boot macOS. + +* Updating SMBIOS for the macOS to `iMac14,2` might be required. I did not do + so myself. + +* To reuse the keyboard and mouse devices from the host, setup "Automatic + login" in System Preferences in macOS and configure Synergy software. + +### Synergy Notes + +* Get Synergy from https://sourceforge.net/projects/synergy-stable-builds. + + I installed "synergy-v1.8.8-stable-MacOSX-x86_64.dmg" on the macOS guest and + configured it as a client. + + For automatically starting Synergy on macOS, add Synergy to "Login Items", + System Preferences -> Users & Groups -> Select your user account -> Login Items + -> Add a login item + +* On the Linux host machine, install "synergy-v1.8.8-stable-Linux-x86_64.deb" + or newer, configure `~/.synergy.conf` and run `synergys` command. + +* The included `.synergy.conf` will need to be adapted according to your setup. + +#### Credits + +* Nicholas Sherlock and others - UEFI, Clover, and other hacks + +* Kyle Dayton - UEFI, Clover, and GPU passthrough notes + +#### References + +* https://pve.proxmox.com/wiki/Qemu/KVM_Virtual_Machines + +* https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF + +* https://clover-wiki.zetam.org/configuration/smbios + +* https://sourceforge.net/projects/synergy-stable-builds. + +* https://wiki.archlinux.org/index.php/synergy diff --git a/UEFI/action.png b/UEFI/action.png new file mode 100644 index 0000000..b054d83 Binary files /dev/null and b/UEFI/action.png differ diff --git a/UEFI/config.plist b/UEFI/config.plist new file mode 100644 index 0000000..0aedd6e --- /dev/null +++ b/UEFI/config.plist @@ -0,0 +1,172 @@ + + + + + ACPI + + DSDT + + Debug + + DropOEM_DSM + + ATI + + Firewire + + HDA + + HDMI + + IDE + + IntelGFX + + LAN + + LPC + + NVidia + + SATA + + SmBUS + + USB + + WIFI + + + Fixes + + AddPNLF_1000000 + + DeleteUnused_400000 + + FIX_ACST_4000000 + + FIX_ADP1_800000 + + FIX_RTC_20000 + + FIX_S3D_2000000 + + FixRegions_10000000 + + + Name + q35-acpi-dsdt.aml + ReuseFFFF + + + SSDT + + DropOem + + Generate + + + + Boot + + Debug + + DefaultLoader + boot.efi + DefaultVolume + LastBootedVolume + Legacy + PBR + Secure + + Timeout + 5 + XMPDetection + Yes + + CPU + + QEMU + + UseARTFrequency + + + Devices + + USB + + FixOwnership + + Inject + + + + GUI + + Mouse + + DoubleClick + 500 + Enabled + + Mirror + + Speed + 8 + + Scan + + ScreenResolution + 800x600 + Theme + embedded + + Graphics + + Inject + + NvidiaSingle + + + KernelAndKextPatches + + AppleRTC + + AsusAICPUPM + + Debug + + KernelCpu + + KernelHaswellE + + KernelLapic + + KernelPm + + + RtVariables + + BooterConfig + 0x28 + CsrActiveConfig + 0x67 + ROM + UseMacAddr0 + + SMBIOS + + Manufacturer + Apple Inc. + Trust + + + SystemParameters + + InjectKexts + Detect + InjectSystemID + + + + diff --git a/UEFI/q35-acpi-dsdt.aml b/UEFI/q35-acpi-dsdt.aml new file mode 100644 index 0000000..d71b3a3 Binary files /dev/null and b/UEFI/q35-acpi-dsdt.aml differ diff --git a/backups/OVMF_CODE-pure-efi.fd b/backups/OVMF_CODE-pure-efi.fd new file mode 100644 index 0000000..807676d Binary files /dev/null and b/backups/OVMF_CODE-pure-efi.fd differ diff --git a/backups/OVMF_VARS-pure-efi.fd b/backups/OVMF_VARS-pure-efi.fd new file mode 100644 index 0000000..3b8bb9b Binary files /dev/null and b/backups/OVMF_VARS-pure-efi.fd differ diff --git a/backups/README.txt b/backups/README.txt new file mode 100644 index 0000000..86c7583 --- /dev/null +++ b/backups/README.txt @@ -0,0 +1 @@ +OVMF_CODE-pure-efi.fd and OVMF_VARS-pure-efi.fd files are borrowed from Proxmox. diff --git a/boot-clover.sh b/boot-clover.sh new file mode 100755 index 0000000..cdc462c --- /dev/null +++ b/boot-clover.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# See https://www.mail-archive.com/qemu-devel@nongnu.org/msg471657.html thread. +# +# The "pc-q35-2.4" machine type was changed to "pc-q35-2.9" on 06-August-2017. + +qemu-system-x86_64 -enable-kvm -m 3072 -cpu Penryn,kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on \ + -machine pc-q35-2.9 \ + -smp 4,cores=2 \ + -usb -device usb-kbd -device usb-tablet \ + -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" \ + -drive if=pflash,format=raw,readonly,file=OVMF_CODE.fd \ + -drive if=pflash,format=raw,file=OVMF_VARS.fd \ + -smbios type=2 \ + -device ich9-intel-hda -device hda-duplex \ + -device ide-drive,bus=ide.2,drive=MacHDD \ + -drive id=MacHDD,if=none,file=./mac_hdd.img \ + -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000-82545em,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \ + -monitor stdio diff --git a/boot-macOS.sh b/boot-macOS.sh index 3a89efe..8145e42 100755 --- a/boot-macOS.sh +++ b/boot-macOS.sh @@ -1,10 +1,8 @@ #!/bin/bash -# qemu-img create -f qcow2 mac_hdd.img 64G -# echo 1 > /sys/module/kvm/parameters/ignore_msrs +# qemu-img create -f qcow2 mac_hdd.img 128G # -# Type the following after boot, -# -v "KernelBooter_kexts"="Yes" "CsrActiveConfig"="103" +# echo 1 > /sys/module/kvm/parameters/ignore_msrs (this is required) # # printf 'DE:AD:BE:EF:%02X:%02X\n' $((RANDOM%256)) $((RANDOM%256)) # @@ -16,13 +14,16 @@ # # Network device "-device e1000-82545em" can be replaced with "-device vmxnet3" # for possibly better performance. +# +# Use "-device usb-tablet" instead of "-device usb-mouse" for better mouse +# behaviour. This requires QEMU >= 2.9.0. qemu-system-x86_64 -enable-kvm -m 3072 -cpu Penryn,kvm=off,vendor=GenuineIntel \ -machine pc-q35-2.4 \ -smp 4,cores=2 \ -usb -device usb-kbd -device usb-mouse \ -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" \ - -kernel ./enoch_rev2883_boot \ + -kernel ./enoch_rev2889_boot \ -smbios type=2 \ -device ich9-intel-hda -device hda-duplex \ -device ide-drive,bus=ide.2,drive=MacHDD \ @@ -30,7 +31,7 @@ qemu-system-x86_64 -enable-kvm -m 3072 -cpu Penryn,kvm=off,vendor=GenuineIntel \ -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000-82545em,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \ -monitor stdio \ -device ide-drive,bus=ide.0,drive=MacDVD \ - -drive id=MacDVD,if=none,snapshot=on,file=./'Install_macOS_Sierra_(OS_X_10.12).iso' + -drive id=MacDVD,if=none,snapshot=on,file=./'Install_macOS_10.12.6_Sierra.iso' # -vnc 0.0.0.0:0 -k en-us \ # -redir tcp:5901::5900 \ # -netdev user,id=hub0port0 -device e1000-82545em,netdev=hub0port0,id=mac_vnet0 \ diff --git a/boot-passthrough.sh b/boot-passthrough.sh new file mode 100755 index 0000000..6dfad4d --- /dev/null +++ b/boot-passthrough.sh @@ -0,0 +1,18 @@ +#!/bin/bash + + +qemu-system-x86_64 -enable-kvm -m 3072 -cpu Penryn,kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on \ + -machine pc-q35-2.9 \ + -smp 4,cores=2 \ + -vga none \ + -device vfio-pci,host=01:00.0,bus=pcie.0,multifunction=on \ + -device vfio-pci,host=01:00.1,bus=pcie.0 \ + -usb -device usb-kbd -device usb-tablet \ + -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" \ + -drive if=pflash,format=raw,readonly,file=OVMF_CODE.fd \ + -drive if=pflash,format=raw,file=OVMF_VARS.fd \ + -smbios type=2 \ + -device ide-drive,bus=ide.2,drive=MacHDD \ + -drive id=MacHDD,if=none,file=./mac_hdd.img \ + -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000-82545em,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \ + -monitor stdio diff --git a/boot.sh b/boot.sh deleted file mode 100755 index fe074cf..0000000 --- a/boot.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -# qemu-img create -f qcow2 mac_hdd.img 64G -# echo 1 > /sys/module/kvm/parameters/ignore_msrs -# -# Type the following after boot, -# -v "KernelBooter_kexts"="Yes" "CsrActiveConfig"="103" -# -# printf 'DE:AD:BE:EF:%02X:%02X\n' $((RANDOM%256)) $((RANDOM%256)) -# -# no_floppy = 1 is required for OS X guests! -# -# Commit 473a49460db0a90bfda046b8f3662b49f94098eb (qemu) makes "no_floppy = 0" -# for pc-q35-2.3 hardware, and OS X doesn't like this (it hangs at "Waiting for -# DSMOS" message). Hence, we switch to pc-q35-2.4 hardware. -# -# Network device "-device e1000-82545em" can be replaced with "-device vmxnet3" -# for possibly better performance. - -qemu-system-x86_64 -enable-kvm -m 8192 -cpu core2duo,kvm=off \ - -machine pc-q35-2.4 \ - -smp 4,cores=2 \ - -usb -device usb-kbd -device usb-mouse \ - -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" \ - -kernel ./enoch_rev2839_boot \ - -smbios type=2 \ - -device ide-drive,bus=ide.2,drive=MacHDD \ - -drive id=MacHDD,if=none,file=./mac_hdd.img \ - -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000-82545em,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \ - -monitor stdio \ - -device ide-drive,bus=ide.0,drive=MacDVD \ - -drive id=MacDVD,if=none,snapshot=on,file=./Install_OS_X_10.11.6_El_Capitan.iso - # -vnc 0.0.0.0:0 -k en-us \ - # -redir tcp:5901::5900 \ - # -netdev user,id=hub0port0 -device e1000-82545em,netdev=hub0port0,id=mac_vnet0 \ diff --git a/create_install_iso.sh b/create_install_iso.sh index 0c078ee..f7b6163 100755 --- a/create_install_iso.sh +++ b/create_install_iso.sh @@ -1,7 +1,7 @@ #!/bin/bash -# Script for building bootable .iso images from downloaded OS X upgrade -# Copyright (C) 2015-2016 Karlson2k (Evgeny Grin) +# Script for building bootable .iso images from downloaded macOS upgrade +# Copyright (C) 2015-2017 Karlson2k (Evgeny Grin) # # You can run, copy, modify, publish and do whatever you want with this # script as long as this message and copyright string above are preserved. @@ -12,7 +12,7 @@ # Latest version: # https://raw.githubusercontent.com/Karlson2k/k2k-OSX-Tools/master/Create_osx_install_iso/create_osx_install_iso.sh # -# Version 1.0.6 +# Version 1.0.6 + local changes function myreadlink() { ( @@ -177,13 +177,13 @@ script_version="$(sed -n -e '\|^# Version| {s|^# Version \(.*$\)|\1|p; q;}' "${B print_help() { echo "\ -Script for creating .iso images from downloaded OS X upgrade application. +Script for creating .iso images from downloaded macOS upgrade application. Usage:" echo_enh_n " $script_name"; echo " [options] Valid options are: - -a, --app[lication] - Path and name of OS X upgrade application. + -a, --app[lication] + Path and name of macOS upgrade application. Path can be omitted if application is located at default path. -i, --iso @@ -217,6 +217,7 @@ exit_with_cmd_err() { } unset cmd_par_app cmd_par_iso test_name ver_opt cr_method || exit_with_error "Can't unset variable" +# allow_sudo='yes' && ver_opt='--noverify' || exit_with_error "Can't set variable" ver_opt='--noverify' inject_kexts='no' while [[ -n "$1" ]]; do @@ -254,9 +255,9 @@ if [[ -z "$cmd_par_app" ]]; then stage_start "Looking for downloaded OS upgrades" unset test_name || exit_with_error IFS=$'\n' - dirlist=(`ls -d1 /Applications/Install\ {OS\ X,macOS}\ *.app 2>/dev/null`) + dirlist=(`find /Applications -maxdepth 1 -mindepth 1 \( -name 'Install OS X *.app' -or -name 'Install macOS *.app' \)`) || exit_with_error "Can't find downloaded macOS upgrade" IFS="$save_IFS" - [[ ${#dirlist[@]} -eq 0 ]] && exit_with_error "Can't find downloaded OS X upgrade. Use the -a option to specify the path to it manually." + [[ ${#dirlist[@]} -eq 0 ]] && exit_with_error "Can't find downloaded OS X / macOS upgrade. Use the -a option to specify the path to it manually." stage_end_ok "found" if [[ ${#dirlist[@]} -gt 1 ]]; then echo "Several OS upgrades were found." @@ -303,14 +304,16 @@ else OSX_inst_app="/Applications/Install ${test_name}" elif check_intall_app "/Applications/Install OS X ${test_name}"; then OSX_inst_app="/Applications/Install OS X ${test_name}" + elif check_intall_app "/Applications/Install macOS ${test_name}"; then + OSX_inst_app="/Applications/Install macOS ${test_name}" fi fi - [[ -n "$OSX_inst_app" ]] || exit_with_error "\"$cmd_par_app\" is not valid OS X Install application" + [[ -n "$OSX_inst_app" ]] || exit_with_error "\"$cmd_par_app\" is not valid macOS Install application" stage_end_ok "found" echo_enh "Using \"$OSX_inst_app\"." fi -stage_start "Detecting OS X name for installation" +stage_start "Detecting macOS name for installation" unset test_name OSX_inst_prt_name || exit_with_error test_name=$(sed -n -e '\|CFBundleDisplayName| { N; s|^.*\(.\{1,\}\).*$|\1|p; q; }' \ "$OSX_inst_app/Contents/Info.plist" 2>/dev/null) || unset test_name @@ -319,8 +322,8 @@ if [[ -n "$test_name" ]]; then OSX_inst_prt_name="Install $OSX_inst_name" stage_end_ok "$OSX_inst_name" else - OSX_inst_name=$(echo "$OSX_inst_app"|sed -n -e's|^.*Install \(OS X .\{1,\}\)\.app.*$|\1|p' 2>/dev/null) || unset OSX_inst_name || exit_with_error - [[ -z "$OSX_inst_name" ]] && OSX_inst_name="OS X" + OSX_inst_name=$(echo "$OSX_inst_app"|sed -n -e's|^.*Install \(\(macOS|OS X\) .\{1,\}\)\.app.*$|\1|p' 2>/dev/null) || unset OSX_inst_name || exit_with_error + [[ -z "$OSX_inst_name" ]] && OSX_inst_name="macOS" OSX_inst_prt_name="Install $OSX_inst_name" stage_end_warn "guessed \"$OSX_inst_name\"" fi @@ -334,7 +337,7 @@ stage_end_ok "succeed" stage_start_nl "Mounting InstallESD.dmg" OSX_inst_inst_dmg="$OSX_inst_app"'/Contents/SharedSupport/InstallESD.dmg' OSX_inst_inst_dmg_mnt="$tmp_dir/InstallESD_dmg_mnt" -hdiutil attach "$OSX_inst_inst_dmg" -kernel -readonly -nobrowse ${ver_opt+-noverify} -mountpoint "$OSX_inst_inst_dmg_mnt" || exit_with_error "Can't mount installation image" +hdiutil attach "$OSX_inst_inst_dmg" -kernel -readonly -nobrowse ${ver_opt+-noverify} -mountpoint "$OSX_inst_inst_dmg_mnt" || exit_with_error "Can't mount installation image. Reboot recommended before retry." OSX_inst_base_dmg="$OSX_inst_inst_dmg_mnt/BaseSystem.dmg" || exit_with_error stage_end_ok "Mounting succeed" @@ -476,7 +479,6 @@ elif [[ "$cr_method" == "method3" ]]; then OSX_inst_img_rw_mnt="$tmp_dir/OS_X_Install_img_rw_mnt" hdiutil attach "$OSX_inst_img_rw" -readwrite -nobrowse -mountpoint "$OSX_inst_img_rw_mnt" ${ver_opt+-noverify} || exit_with_error "Can't mount writable image" stage_end_ok "Remounting succeed" - else exit_with_error "Unknown creation method" fi @@ -495,7 +497,7 @@ if [[ -n "$custom_boot_plist" ]] ; then stage_end_ok "done" fi -stage_start "Detecting OS X version on image" +stage_start "Detecting macOS version on image" unset OSX_inst_ver || exit_with_error "Can't unset variable" OSX_inst_img_rw_ver_file="$OSX_inst_img_rw_mnt/System/Library/CoreServices/SystemVersion.plist" || exit_with_error "Can't set variable" OSX_inst_ver=`sed -n -e '\|ProductUserVisibleVersion| { N; s|^.*\(.\{1,\}\).*$|\1|p; q; }' "$OSX_inst_img_rw_ver_file"` || unset OSX_inst_ver @@ -505,12 +507,8 @@ else stage_end_ok "$OSX_inst_ver" fi -# if [[ "$OSX_inst_ver" =~ 10.12.[4-9] ]]; then -# exit_with_error "This script might not generate bootable images for versions >= macOS Sierra 10.12.4. Edit this script manually to proceed at your own risk!" -# fi - -[[ "$OSX_inst_ver" == "10.11" ]] || [[ "$OSX_inst_ver" =~ 10.11.[1-6] ]] || \ - echo_warning "Warning! This script is tested only with images of OS X versions 10.11 and 10.11.1-10.11.6. Use at your own risk!" +[[ "$OSX_inst_ver" =~ ^10.11($|.[1-4]$)|^10.12($|.[1-5]$) ]] || \ + echo_warning "Warning! This script is tested only with images of macOS versions 10.11.0-10.11.4 and 10.12.0-10.12.5. Use with your own risk!" stage_start_nl "Renaming partition on writeable image" if ! diskutil rename "$OSX_inst_img_rw_mnt" "$OSX_inst_prt_name"; then @@ -527,7 +525,8 @@ stage_end_ok stage_start "Extracting kernel from Essentials.pkg (very slow step)" cd "$OSX_inst_img_rw_mnt" -"$script_dir/pbzx" "$OSX_inst_inst_dmg_mnt/Packages/Essentials.pkg" | cpio -idmu ./System/Library/Kernels || exit_with_error "Extraction of kernel failed" +# "$script_dir/pbzx" "$OSX_inst_inst_dmg_mnt/Packages/Essentials.pkg" | cpio -idmu ./System/Library/Kernels || exit_with_error "Extraction of kernel failed" +tar -xOf "$OSX_inst_inst_dmg_mnt/Packages/Essentials.pkg" Payload | python "$script_dir/parse_pbzx.py" | cpio -idmu ./System/Library/Kernels || exit_with_error "Extraction of kernel failed" cd "$work_dir" stage_end_ok @@ -586,6 +585,8 @@ insert_version_into_name() { ins_aft="OS X" elif [[ "$name" =~ (^|[[:space:]])"MacOS X"($|[[:space:]]) ]]; then ins_aft="MacOS X" + elif [[ "$name" =~ (^|[[:space:]])"macOS"($|[[:space:]]) ]]; then + ins_aft="macOS" fi if [[ -n "$ins_aft" ]]; then result=$(echo -n "$name" | sed -n -e 's|^\(.*[[:<:]]'"$ins_aft"'[[:>:]]\).*$|\1|p') || return 2 @@ -593,7 +594,7 @@ insert_version_into_name() { result+=" $version" # allow any regex/special symbols in $version result+=$(echo -n "$name" | sed -n -e 's|^.*[[:<:]]'"$ins_aft"'[[:>:]]\(.*\)$|\1|p') || return 2 else - result="$name (OS X $version)" + result="$name (macOS $version)" fi [[ -z "$result" ]] && return 1 echo "$result" @@ -666,7 +667,7 @@ if ! [[ -e "$OSX_inst_result_flag" ]]; then echo_warning "Next command will be executed with sudo, you may be asked for password." $sudo_prf hdiutil makehybrid -o "$OSX_inst_result_image_ro" "$OSX_inst_img_rw" -hfs -udf -default-volume-name "$OSX_inst_prt_name" && touch "$OSX_inst_result_flag" else - echo_warning "Usage os sudo was disabled by command parameter" + echo_warning "Usage of sudo was disabled by command parameter" fi fi fi diff --git a/enoch_rev2839_boot b/enoch_rev2839_boot deleted file mode 100644 index d43474e..0000000 Binary files a/enoch_rev2839_boot and /dev/null differ diff --git a/enoch_rev2848_boot b/enoch_rev2848_boot deleted file mode 100644 index 91105cf..0000000 Binary files a/enoch_rev2848_boot and /dev/null differ diff --git a/enoch_rev2877_boot b/enoch_rev2877_boot deleted file mode 100644 index d958e59..0000000 Binary files a/enoch_rev2877_boot and /dev/null differ diff --git a/enoch_rev2883_boot b/enoch_rev2883_boot deleted file mode 100644 index 5299e6a..0000000 Binary files a/enoch_rev2883_boot and /dev/null differ diff --git a/enoch_rev2889_boot b/enoch_rev2889_boot new file mode 100644 index 0000000..3c35053 Binary files /dev/null and b/enoch_rev2889_boot differ diff --git a/kvm.conf b/kvm.conf new file mode 100644 index 0000000..7540bdd --- /dev/null +++ b/kvm.conf @@ -0,0 +1,3 @@ +options kvm_intel nested=1 +options kvm_intel emulate_invalid_guest_state=0 +options kvm ignore_msrs=1 diff --git a/networking-qemu-kvm-howto.txt b/networking-qemu-kvm-howto.txt index d841200..55f8357 100644 --- a/networking-qemu-kvm-howto.txt +++ b/networking-qemu-kvm-howto.txt @@ -15,7 +15,7 @@ networking devices it is willing to accept, so we need to specify the network configuration to use the e1000 emulated card with SLiRP networking. In order to do this, change the line in your qemu-system-x86_64 command (found -in boot.sh or boot-macOS.sh) to the following: +in boot-macOS.sh) to the following: -netdev user,id=net0 -device e1000-82545em,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \ diff --git a/notes.md b/notes.md index 173be63..1c6816f 100644 --- a/notes.md +++ b/notes.md @@ -29,6 +29,9 @@ App Store problems. ### FakeSMC installation +This option is not recommended. Building latest QEMU from Git repository is +recommended instead. + * Do the following steps as `root` user on the Virtual Machine (VM). ``` @@ -136,8 +139,7 @@ is provided for this unmaintained project! Thanks to Zhang Tong and Kfir Ozer for finding this. -GPU passthrough is out of scope for this project. No support for it is provided -whatsoever. +See `UEFI/README.md` for GPU passthrough notes. ### Virtual Sound Device @@ -156,15 +158,59 @@ to be choppy and distorted. See http://wiki.qemu-project.org/Hosts/Linux for help. ``` -$ git clone https://github.com/qemu/qemu.git +$ git clone https://github.com/kholia/qemu.git $ cd qemu +$ git checkout macOS + $ ./configure --prefix=/home/$(whoami)/QEMU --target-list=x86_64-softmmu --audio-drv-list=pa $ make clean; make; make install ``` +### Connect iPhone / iPad to macOS guest + +Some folks are using https://www.virtualhere.com/ to connect iPhone / iPad to +the macOS guest. + +### Exposing AES-NI instructions to macOS + +Add `+aes` argument to the `-cpu` option in `boot-macOS.sh` file. + +``` diff +diff --git a/boot-macOS.sh b/boot-macOS.sh +index 5948b8a..3acc123 100755 +--- a/boot-macOS.sh ++++ b/boot-macOS.sh +@@ -18,7 +18,7 @@ + # Use "-device usb-tablet" instead of "-device usb-mouse" for better mouse + # behaviour. This requires QEMU >= 2.9.0. + +-qemu-system-x86_64 -enable-kvm -m 3072 -cpu Penryn,kvm=off,vendor=GenuineIntel \ ++qemu-system-x86_64 -enable-kvm -m 3072 -cpu Penryn,kvm=off,vendor=GenuineIntel,+aes \ + -machine pc-q35-2.4 \ + -smp 4,cores=2 \ + -usb -device usb-kbd -device usb-mouse \ +``` + +Other host CPU features can be similarly exposed to the macOS guest. + +The following command can be used on macOS to verify that AES-NI instructions are exposed, + +``` +sysctl -a | grep machdep.features +``` + +On machines with OpenSSL installed, the following two commands can be used to +check AES-NI performance, + +``` +openssl speed aes-128-cbc + +openssl speed -evp aes-128-cbc # uses AES-NI +``` + ### Boot Notes Type the following after boot, @@ -189,7 +235,13 @@ Type the following after boot, ### Post Installation -Put "org.chameleon.Boot.plist" in /Extra folder. +* Put "org.chameleon.Boot.plist" in /Extra folder. + +* System Preferences -> Sharing -> enable Screen Sharing and Remote Login + +* System Preferences -> Energy Saver -> Computer sleep set to Never + +* System Preferences -> Energy Saver -> Display sleep set to Never ### Installer Details (InstallESD.dmg) diff --git a/parse_pbzx.py b/parse_pbzx.py new file mode 100755 index 0000000..ddeffe5 --- /dev/null +++ b/parse_pbzx.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# https://gist.github.com/Lekensteyn (Peter Wu) +# +# Extract .cpio file from a pbzx Payload file. +# +# Based on https://gist.github.com/pudquick/ac29c8c19432f2d200d4. This version +# adds a command-line interface, improves efficiency (1 MiB chunks instead of a +# full copy in memory), adds Python 3 compatibility and automatically +# decompresses stuff (some blocks may not be compressed). +# +# Example usage (from Python): +# +# parse_pbzx(open('PayloadJava', 'rb'), open('PayloadJava.cpio', wb')) +# +# Example usage (from shell): +# +# # These are all equivalent +# ./parse_pbzx.py < PayloadJava > PayloadJava.cpio +# ./parse_pbzx.py PayloadJava > PayloadJava.cpio +# ./parse_pbzx.py PayloadJava PayloadJava.cpio +# +# Another example, extract Payload from a .pkg file, convert it to a cpio.xz +# archive (this script) and list contents (cpio -t): +# +# bsdtar -xOf some.pkg Payload | ./parse_pbzx.py Payload | cpio -t +# +# Kernel extraction example: +# +# tar -xOf Essentials.pkg Payload | ./parse_pbzx.py | cpio -idmu ./System/Library/Kernels + +from __future__ import print_function + +import struct +import sys +from contextlib import contextmanager +import subprocess + + +def dbg_print(*args): + # Uncomment next line for debugging + # print(*args, file=sys.stderr) + pass + + +def read_f(f, count): + """Try to fully read data, raising EOFError on short reads.""" + data = f.read(count) + read_bytes = len(data) + if read_bytes != count: + raise EOFError("Read %d, expected %d" % (read_bytes, count)) + return data + + +def copy_data(f_in, f_out, count): + """Copy in chunks of a megabyte to avoid excess memory waste.""" + while count > 0: + sz = min(count, 1024**2) + f_out.write(read_f(f_in, sz)) + count -= sz + + +@contextmanager +def unxz(f_out): + # proc = subprocess.Popen(["unxz"], stdin=subprocess.PIPE, stdout=f_out) + proc = subprocess.Popen(["zcat"], stdin=subprocess.PIPE, stdout=f_out) + try: + yield proc.stdin + finally: + proc.stdin.close() + ret = proc.wait() + if ret != 0: + raise OSError("Decompression failed with status code %d" % ret) + + +def parse_pbzx(pbzx_file, cpio_file): + magic = read_f(pbzx_file, 4) + if magic != b'pbzx': + raise RuntimeError("Error: Not a pbzx file") + # Read 8 bytes for initial flags + flags = read_f(pbzx_file, 8) + # Interpret the flags as a 64-bit big-endian unsigned int + flags = struct.unpack('>Q', flags)[0] + out_offset, in_offset = 0, 4 + 8 + while (flags & (1 << 24)): + # Read in more flags + flags = read_f(pbzx_file, 8) + flags = struct.unpack('>Q', flags)[0] + # Read in length + f_length = read_f(pbzx_file, 8) + f_length = struct.unpack('>Q', f_length)[0] + + if f_length == 0x1000000: + # Literal copy + copy_data(pbzx_file, cpio_file, f_length) + else: + xzmagic = read_f(pbzx_file, 6) + dbg_print("Flags: %#018x Length: %r Magic: %r" % (flags, f_length, xzmagic)) + if xzmagic != b'\xfd7zXZ\x00': + cpio_file.close() + # raise RuntimeError("Error: Header is not xar file header: offset %d, magic %r" % (offset, xzmagic)) + raise RuntimeError("Error: Header is not xar file header: offset %d, magic %r" % (0, xzmagic)) + else: + with unxz(cpio_file) as unxz_f: + unxz_f.write(xzmagic) + # Do not copy header magic again (-6) + copy_data(pbzx_file, unxz_f, -6 + f_length) + + in_offset += 8 + 8 + f_length + out_offset += f_length + dbg_print("Read %d bytes, wrote %d bytes so far" % (in_offset, out_offset)) + try: + cpio_file.close() + except: + pass + +if __name__ == '__main__': + def open_file(argno, mode, f): + if len(sys.argv) > argno: + return open(sys.argv[argno], mode) + # Access binary stdin/stdout in Python 3 + if hasattr(f, "buffer"): + return f.buffer + else: + return f + in_file = open_file(1, "rb", sys.stdin) + out_file = open_file(2, "wb", sys.stdout) + parse_pbzx(in_file, out_file) diff --git a/pbzx b/pbzx deleted file mode 100755 index 76283c0..0000000 Binary files a/pbzx and /dev/null differ diff --git a/pbzx.md5sum b/pbzx.md5sum deleted file mode 100644 index 8574140..0000000 --- a/pbzx.md5sum +++ /dev/null @@ -1 +0,0 @@ -45ce9f06b0a417f875dbd1f23bc0f860 pbzx diff --git a/pbzx.sha256sum b/pbzx.sha256sum deleted file mode 100644 index 34863c7..0000000 --- a/pbzx.sha256sum +++ /dev/null @@ -1 +0,0 @@ -b6d928432e8837defdec18d1698665f16863432cb499a60ca14d734540ab014c pbzx