Browse Source

project: build iOS hypervisor

osy 2 years ago
parent
commit
f4e6c99285

+ 7 - 7
Configuration/UTMQemuConfigurationQEMU.swift

@@ -92,9 +92,9 @@ struct UTMQemuConfigurationQEMU: Codable {
             debugLogURL = dataURL.appendingPathComponent(QEMUPackageFileName.debugLog.rawValue)
             debugLogURL = dataURL.appendingPathComponent(QEMUPackageFileName.debugLog.rawValue)
             efiVarsURL = dataURL.appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue)
             efiVarsURL = dataURL.appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue)
         }
         }
-        #if os(iOS)
-        hasHypervisor = false // no hypervisor on iOS
-        #endif
+        if !jb_has_hypervisor_entitlement() {
+            hasHypervisor = false
+        }
     }
     }
     
     
     func encode(to encoder: Encoder) throws {
     func encode(to encoder: Encoder) throws {
@@ -125,13 +125,13 @@ extension UTMQemuConfigurationQEMU {
             hasUefiBoot = true
             hasUefiBoot = true
             hasRNGDevice = true
             hasRNGDevice = true
         }
         }
-        #if arch(arm64) && os(macOS)
+        #if arch(arm64)
         if architecture == .aarch64 {
         if architecture == .aarch64 {
-            hasHypervisor = true
+            hasHypervisor = jb_has_hypervisor_entitlement()
         }
         }
-        #elseif arch(x86_64) && os(macOS)
+        #elseif arch(x86_64)
         if architecture == .x86_64 {
         if architecture == .x86_64 {
-            hasHypervisor = true
+            hasHypervisor = jb_has_hypervisor_entitlement()
         }
         }
         #endif
         #endif
     }
     }

+ 3 - 2
Platform/Shared/VMConfigQEMUView.swift

@@ -49,6 +49,9 @@ struct VMConfigQEMUView: View {
     }
     }
     
     
     private var supportsHypervisor: Bool {
     private var supportsHypervisor: Bool {
+        guard jb_has_hypervisor_entitlement() else {
+            return false
+        }
         #if arch(arm64)
         #if arch(arm64)
         return system.architecture == .aarch64
         return system.architecture == .aarch64
         #elseif arch(x86_64)
         #elseif arch(x86_64)
@@ -82,11 +85,9 @@ struct VMConfigQEMUView: View {
                     Toggle("TPM Device", isOn: $config.hasTPMDevice)
                     Toggle("TPM Device", isOn: $config.hasTPMDevice)
                         .help("This is required to boot Windows 11.")
                         .help("This is required to boot Windows 11.")
                     #endif
                     #endif
-                    #if os(macOS)
                     Toggle("Use Hypervisor", isOn: $config.hasHypervisor)
                     Toggle("Use Hypervisor", isOn: $config.hasHypervisor)
                         .disabled(!supportsHypervisor)
                         .disabled(!supportsHypervisor)
                         .help("Only available if host architecture matches the target. Otherwise, TCG emulation is used.")
                         .help("Only available if host architecture matches the target. Otherwise, TCG emulation is used.")
-                    #endif
                     Toggle("Use local time for base clock", isOn: $config.hasRTCLocalTime)
                     Toggle("Use local time for base clock", isOn: $config.hasRTCLocalTime)
                         .help("If checked, use local time for RTC which is required for Windows. Otherwise, use UTC clock.")
                         .help("If checked, use local time for RTC which is required for Windows. Otherwise, use UTC clock.")
                     Toggle("Force PS/2 controller", isOn: $config.hasPS2Controller)
                     Toggle("Force PS/2 controller", isOn: $config.hasPS2Controller)

+ 1 - 1
Platform/Shared/VMWizardStartView.swift

@@ -26,7 +26,7 @@ struct VMWizardStartView: View {
         #if os(macOS)
         #if os(macOS)
         VZVirtualMachine.isSupported && !processIsTranslated()
         VZVirtualMachine.isSupported && !processIsTranslated()
         #else
         #else
-        false
+        jb_has_hypervisor_entitlement()
         #endif
         #endif
     }
     }
     
     

+ 1 - 0
Platform/UTMJailbreak.h

@@ -21,6 +21,7 @@
 
 
 bool jb_has_jit_entitlement(void);
 bool jb_has_jit_entitlement(void);
 bool jb_has_usb_entitlement(void);
 bool jb_has_usb_entitlement(void);
+bool jb_has_hypervisor_entitlement(void);
 bool jb_has_cs_disabled(void);
 bool jb_has_cs_disabled(void);
 bool jb_has_cs_execseg_allow_unsigned(void);
 bool jb_has_cs_execseg_allow_unsigned(void);
 bool jb_enable_ptrace_hack(void);
 bool jb_enable_ptrace_hack(void);

+ 9 - 0
Platform/UTMJailbreak.m

@@ -257,11 +257,20 @@ bool jb_has_usb_entitlement(void) {
     }
     }
     return entitled;
     return entitled;
 }
 }
+
+bool jb_has_hypervisor_entitlement(void) {
+    return true;
+}
 #else
 #else
 bool jb_has_usb_entitlement(void) {
 bool jb_has_usb_entitlement(void) {
     NSDictionary *entitlements = cached_app_entitlements();
     NSDictionary *entitlements = cached_app_entitlements();
     return entitlements[@"com.apple.security.exception.iokit-user-client-class"] != nil;
     return entitlements[@"com.apple.security.exception.iokit-user-client-class"] != nil;
 }
 }
+
+bool jb_has_hypervisor_entitlement(void) {
+    NSDictionary *entitlements = cached_app_entitlements();
+    return entitlements[@"com.apple.private.hypervisor"] != nil;
+}
 #endif
 #endif
 
 
 bool jb_has_cs_execseg_allow_unsigned(void) {
 bool jb_has_cs_execseg_allow_unsigned(void) {

+ 4 - 0
UTM.xcodeproj/project.pbxproj

@@ -243,6 +243,7 @@
 		84C505AC28C588EC007CE8FF /* SizeTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C505AB28C588EC007CE8FF /* SizeTextField.swift */; };
 		84C505AC28C588EC007CE8FF /* SizeTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C505AB28C588EC007CE8FF /* SizeTextField.swift */; };
 		84C505AD28C588EC007CE8FF /* SizeTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C505AB28C588EC007CE8FF /* SizeTextField.swift */; };
 		84C505AD28C588EC007CE8FF /* SizeTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C505AB28C588EC007CE8FF /* SizeTextField.swift */; };
 		84C505AE28C588EC007CE8FF /* SizeTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C505AB28C588EC007CE8FF /* SizeTextField.swift */; };
 		84C505AE28C588EC007CE8FF /* SizeTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C505AB28C588EC007CE8FF /* SizeTextField.swift */; };
+		84C5068728CA5702007CE8FF /* Hypervisor.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 84C5068528CA5702007CE8FF /* Hypervisor.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		84C584E1268E95B3000FCABF /* UTMLegacyAppleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584DE268E95B3000FCABF /* UTMLegacyAppleConfiguration.swift */; };
 		84C584E1268E95B3000FCABF /* UTMLegacyAppleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584DE268E95B3000FCABF /* UTMLegacyAppleConfiguration.swift */; };
 		84C584E3268F8AE7000FCABF /* VMQEMUSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584E2268F8AE7000FCABF /* VMQEMUSettingsView.swift */; };
 		84C584E3268F8AE7000FCABF /* VMQEMUSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584E2268F8AE7000FCABF /* VMQEMUSettingsView.swift */; };
 		84C584E5268F8C65000FCABF /* VMAppleSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584E4268F8C65000FCABF /* VMAppleSettingsView.swift */; };
 		84C584E5268F8C65000FCABF /* VMAppleSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584E4268F8C65000FCABF /* VMAppleSettingsView.swift */; };
@@ -1420,6 +1421,7 @@
 				CE2D938A24AD46670059923A /* gstrtp-1.0.0.framework in Embed Libraries */,
 				CE2D938A24AD46670059923A /* gstrtp-1.0.0.framework in Embed Libraries */,
 				CE2D938B24AD46670059923A /* gstriff-1.0.0.framework in Embed Libraries */,
 				CE2D938B24AD46670059923A /* gstriff-1.0.0.framework in Embed Libraries */,
 				CE2D938C24AD46670059923A /* qemu-ppc-softmmu.framework in Embed Libraries */,
 				CE2D938C24AD46670059923A /* qemu-ppc-softmmu.framework in Embed Libraries */,
+				84C5068728CA5702007CE8FF /* Hypervisor.framework in Embed Libraries */,
 				CE2D938D24AD46670059923A /* phodav-2.0.0.framework in Embed Libraries */,
 				CE2D938D24AD46670059923A /* phodav-2.0.0.framework in Embed Libraries */,
 				CE2D938E24AD46670059923A /* gthread-2.0.0.framework in Embed Libraries */,
 				CE2D938E24AD46670059923A /* gthread-2.0.0.framework in Embed Libraries */,
 				CE2D938F24AD46670059923A /* qemu-aarch64-softmmu.framework in Embed Libraries */,
 				CE2D938F24AD46670059923A /* qemu-aarch64-softmmu.framework in Embed Libraries */,
@@ -1702,6 +1704,7 @@
 		84BB99392899E8D500DF28B2 /* VMHeadlessSessionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMHeadlessSessionState.swift; sourceTree = "<group>"; };
 		84BB99392899E8D500DF28B2 /* VMHeadlessSessionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMHeadlessSessionState.swift; sourceTree = "<group>"; };
 		84C4D9012880CA8A00EC3B2B /* VMSettingsAddDeviceMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMSettingsAddDeviceMenuView.swift; sourceTree = "<group>"; };
 		84C4D9012880CA8A00EC3B2B /* VMSettingsAddDeviceMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMSettingsAddDeviceMenuView.swift; sourceTree = "<group>"; };
 		84C505AB28C588EC007CE8FF /* SizeTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SizeTextField.swift; sourceTree = "<group>"; };
 		84C505AB28C588EC007CE8FF /* SizeTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SizeTextField.swift; sourceTree = "<group>"; };
+		84C5068528CA5702007CE8FF /* Hypervisor.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Hypervisor.framework; path = "$(SYSROOT_DIR)/Frameworks/Hypervisor.framework"; sourceTree = "<group>"; };
 		84C584DC268E70F1000FCABF /* UTMVirtualMachine-Protected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UTMVirtualMachine-Protected.h"; sourceTree = "<group>"; };
 		84C584DC268E70F1000FCABF /* UTMVirtualMachine-Protected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UTMVirtualMachine-Protected.h"; sourceTree = "<group>"; };
 		84C584DE268E95B3000FCABF /* UTMLegacyAppleConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMLegacyAppleConfiguration.swift; sourceTree = "<group>"; };
 		84C584DE268E95B3000FCABF /* UTMLegacyAppleConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMLegacyAppleConfiguration.swift; sourceTree = "<group>"; };
 		84C584E2268F8AE7000FCABF /* VMQEMUSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMQEMUSettingsView.swift; sourceTree = "<group>"; };
 		84C584E2268F8AE7000FCABF /* VMQEMUSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMQEMUSettingsView.swift; sourceTree = "<group>"; };
@@ -2540,6 +2543,7 @@
 		CE2D63D622653C7300FC7E63 /* Frameworks */ = {
 		CE2D63D622653C7300FC7E63 /* Frameworks */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				84C5068528CA5702007CE8FF /* Hypervisor.framework */,
 				84818C0B2898A07A009EDB67 /* AVFAudio.framework */,
 				84818C0B2898A07A009EDB67 /* AVFAudio.framework */,
 				84937EFE28960789003148F4 /* zstd.1.framework */,
 				84937EFE28960789003148F4 /* zstd.1.framework */,
 				848308D4278A1F2200E3E474 /* Virtualization.framework */,
 				848308D4278A1F2200E3E474 /* Virtualization.framework */,

+ 4 - 0
patches/sources

@@ -41,3 +41,7 @@ EPOXY_REPO="https://github.com/utmapp/libepoxy.git"
 EPOXY_COMMIT="266d2290a437c655f7419e85af06bfbb73a720c4"
 EPOXY_COMMIT="266d2290a437c655f7419e85af06bfbb73a720c4"
 VIRGLRENDERER_REPO="https://github.com/utmapp/virglrenderer.git"
 VIRGLRENDERER_REPO="https://github.com/utmapp/virglrenderer.git"
 VIRGLRENDERER_COMMIT="42b176aea0ac55c22e30514a4e28b452fe1ef648"
 VIRGLRENDERER_COMMIT="42b176aea0ac55c22e30514a4e28b452fe1ef648"
+
+# Decompiled Hypervisor for iOS
+HYPERVISOR_REPO="https://github.com/utmapp/Hypervisor.git"
+HYPERVISOR_COMMIT="5ae503b4f3a96c42572bf98a5e4ba4cab4994824"

+ 33 - 6
scripts/build_dependencies.sh

@@ -158,6 +158,7 @@ download_all () {
     clone $ANGLE_REPO $ANGLE_COMMIT
     clone $ANGLE_REPO $ANGLE_COMMIT
     clone $EPOXY_REPO $EPOXY_COMMIT
     clone $EPOXY_REPO $EPOXY_COMMIT
     clone $VIRGLRENDERER_REPO $VIRGLRENDERER_COMMIT
     clone $VIRGLRENDERER_REPO $VIRGLRENDERER_COMMIT
+    clone $HYPERVISOR_REPO $HYPERVISOR_COMMIT
 }
 }
 
 
 copy_private_headers() {
 copy_private_headers() {
@@ -441,6 +442,20 @@ build_angle () {
     export PATH=$OLD_PATH
     export PATH=$OLD_PATH
 }
 }
 
 
+build_hypervisor () {
+    OLD_PATH=$PATH
+    export PATH="$(realpath "$BUILD_DIR/depot_tools.git"):$OLD_PATH"
+    pwd="$(pwd)"
+    cd "$BUILD_DIR/Hypervisor.git"
+
+    echo "${GREEN}Building Hypervisor...${NC}"
+    env -i PATH=$PATH xcodebuild archive -archivePath "Hypervisor" -scheme "Hypervisor" -sdk $SDK -configuration Release
+
+    rsync -a "Hypervisor.xcarchive/Products/Library/Frameworks/" "$PREFIX/Frameworks"
+    cd "$pwd"
+    export PATH=$OLD_PATH
+}
+
 build_qemu_dependencies () {
 build_qemu_dependencies () {
     build $FFI_SRC
     build $FFI_SRC
     build $ICONV_SRC
     build $ICONV_SRC
@@ -469,6 +484,10 @@ build_qemu_dependencies () {
     build_angle
     build_angle
     meson_build $EPOXY_REPO -Dtests=false -Dglx=no -Degl=yes
     meson_build $EPOXY_REPO -Dtests=false -Dglx=no -Degl=yes
     meson_build $VIRGLRENDERER_REPO -Dtests=false
     meson_build $VIRGLRENDERER_REPO -Dtests=false
+    # Hypervisor for iOS
+    if [ "$PLATFORM" == "ios" ]; then
+        build_hypervisor
+    fi
 }
 }
 
 
 build_spice_client () {
 build_spice_client () {
@@ -630,11 +649,13 @@ ios* )
         SDK=iphonesimulator
         SDK=iphonesimulator
         CFLAGS_MINVER="-mios-simulator-version-min=$SDKMINVER"
         CFLAGS_MINVER="-mios-simulator-version-min=$SDKMINVER"
         PLATFORM_FAMILY_PREFIX="iOS_Simulator"
         PLATFORM_FAMILY_PREFIX="iOS_Simulator"
+        HVF_FLAGS="--disable-hvf"
         ;;
         ;;
     * )
     * )
         SDK=iphoneos
         SDK=iphoneos
         CFLAGS_MINVER="-miphoneos-version-min=$SDKMINVER"
         CFLAGS_MINVER="-miphoneos-version-min=$SDKMINVER"
         PLATFORM_FAMILY_PREFIX="iOS"
         PLATFORM_FAMILY_PREFIX="iOS"
+        HVF_FLAGS=""
         ;;
         ;;
     esac
     esac
     CFLAGS_TARGET=
     CFLAGS_TARGET=
@@ -647,12 +668,13 @@ ios* )
         fi
         fi
         PLATFORM_FAMILY_NAME="$PLATFORM_FAMILY_PREFIX-TCI"
         PLATFORM_FAMILY_NAME="$PLATFORM_FAMILY_PREFIX-TCI"
         SKIP_USB_BUILD=1
         SKIP_USB_BUILD=1
+        HVF_FLAGS="--disable-hvf"
         ;;
         ;;
     * )
     * )
         PLATFORM_FAMILY_NAME="$PLATFORM_FAMILY_PREFIX"
         PLATFORM_FAMILY_NAME="$PLATFORM_FAMILY_PREFIX"
         ;;
         ;;
     esac
     esac
-    QEMU_PLATFORM_BUILD_FLAGS="--disable-debug-info --enable-shared-lib --disable-hvf --disable-cocoa --disable-coreaudio --disable-slirp-smbd --enable-ucontext --with-coroutine=libucontext $TCI_BUILD_FLAGS"
+    QEMU_PLATFORM_BUILD_FLAGS="--disable-debug-info --enable-shared-lib --disable-cocoa --disable-coreaudio --disable-slirp-smbd --enable-ucontext --with-coroutine=libucontext $HVF_FLAGS $TCI_BUILD_FLAGS"
     ;;
     ;;
 macos )
 macos )
     if [ -z "$SDKMINVER" ]; then
     if [ -z "$SDKMINVER" ]; then
@@ -732,11 +754,11 @@ export STRIP
 export PREFIX
 export PREFIX
 
 
 # Flags
 # Flags
-CFLAGS="$CFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include $CFLAGS_MINVER $CFLAGS_TARGET"
-CPPFLAGS="$CPPFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include $CFLAGS_MINVER $CFLAGS_TARGET"
-CXXFLAGS="$CXXFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include $CFLAGS_MINVER $CFLAGS_TARGET"
-OBJCFLAGS="$OBJCFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include $CFLAGS_MINVER $CFLAGS_TARGET"
-LDFLAGS="$LDFLAGS -arch $ARCH -isysroot $SDKROOT -L$PREFIX/lib $CFLAGS_MINVER $CFLAGS_TARGET"
+CFLAGS="$CFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include -F$PREFIX/Frameworks $CFLAGS_MINVER $CFLAGS_TARGET"
+CPPFLAGS="$CPPFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include -F$PREFIX/Frameworks $CFLAGS_MINVER $CFLAGS_TARGET"
+CXXFLAGS="$CXXFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include -F$PREFIX/Frameworks $CFLAGS_MINVER $CFLAGS_TARGET"
+OBJCFLAGS="$OBJCFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include -F$PREFIX/Frameworks $CFLAGS_MINVER $CFLAGS_TARGET"
+LDFLAGS="$LDFLAGS -arch $ARCH -isysroot $SDKROOT -L$PREFIX/lib -F$PREFIX/Frameworks $CFLAGS_MINVER $CFLAGS_TARGET"
 export CFLAGS
 export CFLAGS
 export CPPFLAGS
 export CPPFLAGS
 export CXXFLAGS
 export CXXFLAGS
@@ -765,6 +787,11 @@ build_pkg_config
 build_qemu_dependencies
 build_qemu_dependencies
 build $QEMU_SRC --cross-prefix="" $QEMU_PLATFORM_BUILD_FLAGS
 build $QEMU_SRC --cross-prefix="" $QEMU_PLATFORM_BUILD_FLAGS
 build_spice_client
 build_spice_client
+# Fake Hypervisor to get iOS Simulator to build
+if [ "$PLATFORM" == "ios_simulator" ]; then
+    mkdir "$PREFIX/Frameworks/Hypervisor.framework"
+    touch "$PREFIX/Frameworks/Hypervisor.framework/Hypervisor"
+fi
 fixup_all
 fixup_all
 remove_shared_gst_plugins # another hack...
 remove_shared_gst_plugins # another hack...
 generate_qapi $QEMU_SRC
 generate_qapi $QEMU_SRC

+ 2 - 3
scripts/package.sh

@@ -216,8 +216,6 @@ ipa )
 	<true/>
 	<true/>
 	<key>com.apple.developer.kernel.extended-virtual-addressing</key>
 	<key>com.apple.developer.kernel.extended-virtual-addressing</key>
 	<true/>
 	<true/>
-	<!-- https://siguza.github.io/psychicpaper/ -->
-	<!---><!-->
 	<key>dynamic-codesigning</key>
 	<key>dynamic-codesigning</key>
 	<true/>
 	<true/>
 	<key>com.apple.private.iokit.IOServiceSetAuthorizationID</key>
 	<key>com.apple.private.iokit.IOServiceSetAuthorizationID</key>
@@ -231,7 +229,8 @@ ipa )
 	<true/>
 	<true/>
 	<key>com.apple.vm.device-access</key>
 	<key>com.apple.vm.device-access</key>
 	<true/>
 	<true/>
-	<!-- -->
+	<key>com.apple.private.hypervisor</key>
+	<true/>
 </dict>
 </dict>
 </plist>
 </plist>
 EOL
 EOL