11

Proxmox VE KVM 虚拟化 macOS

 3 years ago
source link: https://azhuge233.com/proxmox-ve-kvm-%e8%99%9a%e6%8b%9f%e5%8c%96-macos/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Proxmox VE KVM 虚拟化 macOS
This website uses cookies to improve your experience. 本站使用 Cookies 以提升您的用户体验。 Learn More
Skip to content

关于 macOS 虚拟机,我最初的尝试是:无头模式的 Debian 10 虚拟机下开启嵌套虚拟化,然后使用 macOS-Simple-KVM,但是效果并不理想:在 High Sierra 和 Mojave 下,安装程序无法连接到恢复服务器(“The recovery server could not be contacted” 中有人切换到 dhcpd 配置网络后成功连接服务器),而 Catalina 完全无法启动安装程序

之后尝试使用 kholia / OSX-KVM ,但依然无法在无头模式的虚拟机下安装 macOS,之后跟随官方推荐的 nicksherlock.com 中的 PVE 的使用教程,成功创建 macOS 虚拟机

macOS 虚拟机本质上是 OpenCore 引导的黑苹果,新建虚拟机后的安装过程也较为相似,OpenCore 相较于 Clover 省去了很多繁琐的配置步骤,适用于 High Sierra、Mojave、Catalina 和 Big Sur

因为 PVE 也是基于 Debian 和 KVM/QEMU,所以理论上应该适用于所有安装了 KVM/QEMU 的 Linux 系统,区别在于安装过程有没有 GUI

强烈建议机器连接显示器,不要使用无头模式,QEMU 的 -nographic 和 -curses 模式并不好用,并且会产生各种问题导致 macOS 无法安装

下文将展示如何在 Proxmox VE 6.2 下新建 macOS Catalina 虚拟机

  • Proxmox VE 6.2
    • 支持 SSE 4.2 的 CPU
    • Nehalem 及之后架构(带 Core 名称)的 Intel CPU 均支持 SSE 4.2 指令集
  • 正常运行的 Linux/Windows 电脑

生成安装镜像

  1. 安装 python3、git
  2. 获取 OSX-KVM
    • 执行
      git clone https://github.com/kholia/OSX-KVM.git
      git clone https://github.com/kholia/OSX-KVM.git
  3. 获取 BaseSystem
    • 执行
      cd OSX-KVM
      ./fetch-macOS.py
      cd OSX-KVM
      ./fetch-macOS.py

      Proxmox VE KVM 虚拟化 macOS

    • 选择 13,下载最新版本 Catalina 10.15.7Proxmox VE KVM 虚拟化 macOS
  4. 转换 BaseSystem.dmg 镜像格式
    • macOS 下执行
      hdiutil convert BaseSystem.dmg -format UDTO -o Catalina-Installer.iso
      mv Catalina-Installer.iso.cdr Catalina-Installer.iso
      hdiutil convert BaseSystem.dmg -format UDTO -o Catalina-Installer.iso
      mv Catalina-Installer.iso.cdr Catalina-Installer.iso
    • Linux 下可以安装 dmg2img
      dmg2img BaseSystem.dmg Catalina-installer.iso
      dmg2img BaseSystem.dmg Catalina-installer.iso

      或者可以使用 qemu-img(需要安装 qemu-utils)

      qemu-img convert BaseSystem.dmg -O raw Catalina-installer.iso
      qemu-img convert BaseSystem.dmg -O raw Catalina-installer.iso
  5. 将 Catalina-installer.iso 镜像上传到 PVE

获取 OpenCore 镜像

访问 thenickdude / KVM-Opencore,下载最新的 OpenCore.iso.gz 文件(目前为 v10),解压得到 OpenCore.iso,上传到 PVE

最终 PVE 中的镜像如下图,应有 Catalina-Installer.iso 和 OpenCore.iso(忽略其他镜像)

Proxmox VE KVM 虚拟化 macOS

新建 Catalina 虚拟机

如图新建虚拟机

Proxmox VE KVM 虚拟化 macOS新建虚拟机

Proxmox VE KVM 虚拟化 macOS镜像选择 OpenCore.iso,操作系统选择其他

Proxmox VE KVM 虚拟化 macOS系统选择 VMWare兼容,BIOS选择 OVMF(UEFI),勾选添加 EFI 磁盘,机器选择 q35

Proxmox VE KVM 虚拟化 macOS硬盘选择 SATA 0,缓存选择 Write back(不安全),勾选 SSD 仿真(建议新建在 SSD 上,体验较好)

Proxmox VE KVM 虚拟化 macOSCPU核心按需选择,类别选择 Penryn

Proxmox VE KVM 虚拟化 macOS内存容量按需设置,取消勾选 Ballooning 设备

Proxmox VE KVM 虚拟化 macOS网络模型选择 VMWare vmxnet3

配置虚拟机

  1. 在 虚拟机-选项 中开启 使用平板指针Proxmox VE KVM 虚拟化 macOS
  2. 在 虚拟机-硬件 中添加 CD/DVD Drive,总线选择 IDE 0,镜像选择 Catalina-Installer.isoProxmox VE KVM 虚拟化 macOS
  3. 获取 OSK 密钥(需要 macOS,可跳过)
    • 可以直接使用:ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc
    • 或者手动获取(需要先安装 xcode):新建 smc_read.c 文件,写入以下内容
      #include <stdio.h>
      #include <IOKit/IOKitLib.h>
      typedef struct {
      uint32_t key;
      uint8_t __d0[22];
      uint32_t datasize;
      uint8_t __d1[10];
      uint8_t cmd;
      uint32_t __d2;
      uint8_t data[32];
      } AppleSMCBuffer_t;
      main(void)
      io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
      IOServiceMatching("AppleSMC"));
      if (!service)
      return -1;
      io_connect_t port = (io_connect_t)0;
      kern_return_t kr = IOServiceOpen(service, mach_task_self(), 0, &port);
      IOObjectRelease(service);
      if (kr != kIOReturnSuccess)
      return kr;
      AppleSMCBuffer_t inputStruct = { 'OSK0', {0}, 32, {0}, 5, }, outputStruct;
      size_t outputStructCnt = sizeof(outputStruct);
      kr = IOConnectCallStructMethod((mach_port_t)port, (uint32_t)2,
      (const void*)&inputStruct, sizeof(inputStruct),
      (void*)&outputStruct, &outputStructCnt);
      if (kr != kIOReturnSuccess)
      return kr;
      int i = 0;
      for (i = 0; i < 32; i++)
      printf("%c", outputStruct.data[i]);
      inputStruct.key = 'OSK1';
      kr = IOConnectCallStructMethod((mach_port_t)port, (uint32_t)2,
      (const void*)&inputStruct, sizeof(inputStruct),
      (void*)&outputStruct, &outputStructCnt);
      if (kr == kIOReturnSuccess)
      for (i = 0; i < 32; i++)
      printf("%c", outputStruct.data[i]);
      printf("\n");
      return IOServiceClose(port);
      #include <stdio.h>
      #include <IOKit/IOKitLib.h>
      
      typedef struct {
          uint32_t key;
          uint8_t  __d0[22];
          uint32_t datasize;
          uint8_t  __d1[10];
          uint8_t  cmd;
          uint32_t __d2;
          uint8_t  data[32];
      } AppleSMCBuffer_t;
      
      int
      main(void)
      {
          io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
                                     IOServiceMatching("AppleSMC"));
          if (!service)
              return -1;
      
          io_connect_t port = (io_connect_t)0;
          kern_return_t kr = IOServiceOpen(service, mach_task_self(), 0, &port);
          IOObjectRelease(service);
          if (kr != kIOReturnSuccess)
              return kr;
      
          AppleSMCBuffer_t inputStruct = { 'OSK0', {0}, 32, {0}, 5, }, outputStruct;
          size_t outputStructCnt = sizeof(outputStruct);
      
          kr = IOConnectCallStructMethod((mach_port_t)port, (uint32_t)2,
                   (const void*)&inputStruct, sizeof(inputStruct),
                   (void*)&outputStruct, &outputStructCnt);
          if (kr != kIOReturnSuccess)
              return kr;
      
          int i = 0;
          for (i = 0; i < 32; i++)
              printf("%c", outputStruct.data[i]);
      
          inputStruct.key = 'OSK1';
          kr = IOConnectCallStructMethod((mach_port_t)port, (uint32_t)2,
                   (const void*)&inputStruct, sizeof(inputStruct),
                   (void*)&outputStruct, &outputStructCnt);
          if (kr == kIOReturnSuccess)
              for (i = 0; i < 32; i++)
                  printf("%c", outputStruct.data[i]);
      
          printf("\n");
      
          return IOServiceClose(port);
      }
    • 编译并执行 smc_read
      gcc -o smc_read smc_read.c -framework IOKit
      ./smc_read
      gcc -o smc_read smc_read.c -framework IOKit
      ./smc_read

      Proxmox VE KVM 虚拟化 macOS

  4. 编辑虚拟机配置文件
    • SSH 连接 PVE,或者使用 PVE 自带 Web SSH
    • 打开 /etc/pve/qemu-server/[虚拟机ID].conf,添加新行
      args: -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" -smbios type=2 -device usb-kbd,bus=ehci.0,port=2
      args: -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" -smbios type=2 -device usb-kbd,bus=ehci.0,port=2
    • 如果使用 Intel CPU,在 args 新增行的行末添加
      -cpu host,kvm=on,vendor=GenuineIntel,+kvm_pv_unhalt,+kvm_pv_eoi,+hypervisor,+invtsc
       -cpu host,kvm=on,vendor=GenuineIntel,+kvm_pv_unhalt,+kvm_pv_eoi,+hypervisor,+invtsc

      如果使用 AMD CPU,在 args 新增行的行末添加

      -cpu Penryn,kvm=on,vendor=GenuineIntel,+kvm_pv_unhalt,+kvm_pv_eoi,+hypervisor,+invtsc,+pcid,+ssse3,+sse4.2,+popcnt,+avx,+avx2,+aes,+fma,+fma4,+bmi1,+bmi2,+xsave,+xsaveopt,check
      -cpu Penryn,kvm=on,vendor=GenuineIntel,+kvm_pv_unhalt,+kvm_pv_eoi,+hypervisor,+invtsc,+pcid,+ssse3,+sse4.2,+popcnt,+avx,+avx2,+aes,+fma,+fma4,+bmi1,+bmi2,+xsave,+xsaveopt,check
    • 找到两个 CD 驱动器的配置行,将 “media=cdrom” 更改为 “cache=unsafe”
    • 最终的虚拟机配置文件如下Proxmox VE KVM 虚拟化 macOS

配置 Proxmox VE

启动虚拟机前的最后操作

  1. 防止 macOS 无限重启
    echo 1 > /sys/module/kvm/parameters/ignore_msrs
    echo 1 > /sys/module/kvm/parameters/ignore_msrs
  2. 使设置持续生效
    echo "options kvm ignore_msrs=Y" >> /etc/modprobe.d/kvm.conf && update-initramfs -k all -u
    echo "options kvm ignore_msrs=Y" >> /etc/modprobe.d/kvm.conf && update-initramfs -k all -u

安装 Catalina

  1. 启动虚拟机,进入 OpenCore 启动界面Proxmox VE KVM 虚拟化 macOS
  2. 选择进入 macOS Base SystemProxmox VE KVM 虚拟化 macOS
  3. 进入 磁盘工具 格式化硬盘Proxmox VE KVM 虚拟化 macOS
  4. 安装 CatalinaProxmox VE KVM 虚拟化 macOS
  5. 安装完毕后会重启,再次进入 OpenCore 启动界面,选择进入 macOS Install 磁盘(通常为第二个选项),不要再次进入 macOS Base System
  6. 等待安装完毕,系统再次重启,这次选择格式化时的磁盘名称,进入 macOS 的欢迎界面,选择跳过登录 Apple IDProxmox VE KVM 虚拟化 macOS
  7. 成功安装 macOSProxmox VE KVM 虚拟化 macOS

配置 OpenCore

以下两步将解决 macOS 的 EFI 启动问题并开启自启动

复制 OpenCore EFI

此时虚拟机的启动依赖于挂载的 OpenCore.iso 镜像,此步骤会将 OpenCore 的 EFI 复制到 macOS 所在磁盘

  1. 进入 macOS 后,打开 终端,查看所有磁盘和分区
    diskutil list
     diskutil list

    Proxmox VE KVM 虚拟化 macOS如图所示,OpenCore.iso 磁盘内只有一个 EFI 分区,大小约为 150 MB

  2. 将 OpenCore 磁盘内的 EFI 分区复制到 macOS 的 EFI 分区
    sudo dd if=/dev/disk1s1 of=/dev/disk2s1
    sudo dd if=/dev/disk1s1 of=/dev/disk2s1

    /dev/disk1s1 为 OpenCore 的 EFI 分区,/dev/disk2s1 为 macOS 磁盘的 EFI 分区Proxmox VE KVM 虚拟化 macOS

  3. 关机,在 虚拟机-硬件 中删除 OpenCore.iso 和 Catalina-Installer.iso 两个 CD 驱动器

OpenCore 自动启动

经过以上步骤,macOS 虚拟机启动时可以不需要挂载 OpenCore.iso 镜像,但是仍然需要手动选择启动磁盘,以下步骤将开启 OpenCore 自启动

  1. 进入 macOS,挂载 EFI 分区
    • 查看 EFI 分区路径
      diskutil list
      # 找到 EFI 分区路径
      diskutil list
      # 找到 EFI 分区路径
    • 挂载分区
      sudo mkdir /Volumes/EFI
      sudo mount -t msdos /dev/[EFI 分区路径] /Volumes/EFI
      sudo mkdir /Volumes/EFI
      sudo mount -t msdos /dev/[EFI 分区路径] /Volumes/EFI
    • 编辑 OC 文件夹下的 config.plist 配置文件Proxmox VE KVM 虚拟化 macOS
    • 将 Misc -> Boot -> Timeout 值设置为非 0,以开启自动启动Proxmox VE KVM 虚拟化 macOS

Proxmox VE KVM 虚拟化 macOS

macOS, 所有macOS, PVE

发表评论 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

评论

显示名称 *

电子邮箱地址 *

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK