Kaynağa Gözat

project: build iOS hypervisor

osy 2 yıl önce
ebeveyn
işleme
f4e6c99285

+ 7 - 7
Configuration/UTMQemuConfigurationQEMU.swift

@@ -92,9 +92,9 @@ struct UTMQemuConfigurationQEMU: Codable {
             debugLogURL = dataURL.appendingPathComponent(QEMUPackageFileName.debugLog.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 {
@@ -125,13 +125,13 @@ extension UTMQemuConfigurationQEMU {
             hasUefiBoot = true
             hasRNGDevice = true
         }
-        #if arch(arm64) && os(macOS)
+        #if arch(arm64)
         if architecture == .aarch64 {
-            hasHypervisor = true
+            hasHypervisor = jb_has_hypervisor_entitlement()
         }
-        #elseif arch(x86_64) && os(macOS)
+        #elseif arch(x86_64)
         if architecture == .x86_64 {
-            hasHypervisor = true
+            hasHypervisor = jb_has_hypervisor_entitlement()
         }
         #endif
     }

+ 3 - 2
Platform/Shared/VMConfigQEMUView.swift

@@ -49,6 +49,9 @@ struct VMConfigQEMUView: View {
     }
     
     private var supportsHypervisor: Bool {
+        guard jb_has_hypervisor_entitlement() else {
+            return false
+        }
         #if arch(arm64)
         return system.architecture == .aarch64
         #elseif arch(x86_64)
@@ -82,11 +85,9 @@ struct VMConfigQEMUView: View {
                     Toggle("TPM Device", isOn: $config.hasTPMDevice)
                         .help("This is required to boot Windows 11.")
                     #endif
-                    #if os(macOS)
                     Toggle("Use Hypervisor", isOn: $config.hasHypervisor)
                         .disabled(!supportsHypervisor)
                         .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)
                         .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)

+ 1 - 1
Platform/Shared/VMWizardStartView.swift

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

+ 1 - 0
Platform/UTMJailbreak.h

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

+ 9 - 0
Platform/UTMJailbreak.m

@@ -257,11 +257,20 @@ bool jb_has_usb_entitlement(void) {
     }
     return entitled;
 }
+
+bool jb_has_hypervisor_entitlement(void) {
+    return true;
+}
 #else
 bool jb_has_usb_entitlement(void) {
     NSDictionary *entitlements = cached_app_entitlements();
     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
 
 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 */; };
 		84C505AD28C588EC007CE8FF /* 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 */; };
 		84C584E3268F8AE7000FCABF /* VMQEMUSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584E2268F8AE7000FCABF /* VMQEMUSettingsView.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 */,
 				CE2D938B24AD46670059923A /* gstriff-1.0.0.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 */,
 				CE2D938E24AD46670059923A /* gthread-2.0.0.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>"; };
 		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>"; };
+		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>"; };
 		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>"; };
@@ -2540,6 +2543,7 @@
 		CE2D63D622653C7300FC7E63 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				84C5068528CA5702007CE8FF /* Hypervisor.framework */,
 				84818C0B2898A07A009EDB67 /* AVFAudio.framework */,
 				84937EFE28960789003148F4 /* zstd.1.framework */,
 				848308D4278A1F2200E3E474 /* Virtualization.framework */,

+ 4 - 0
patches/sources

@@ -41,3 +41,7 @@ EPOXY_REPO="https://github.com/utmapp/libepoxy.git"
 EPOXY_COMMIT="266d2290a437c655f7419e85af06bfbb73a720c4"
 VIRGLRENDERER_REPO="https://github.com/utmapp/virglrenderer.git"
 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 $EPOXY_REPO $EPOXY_COMMIT
     clone $VIRGLRENDERER_REPO $VIRGLRENDERER_COMMIT
+    clone $HYPERVISOR_REPO $HYPERVISOR_COMMIT
 }
 
 copy_private_headers() {
@@ -441,6 +442,20 @@ build_angle () {
     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 $FFI_SRC
     build $ICONV_SRC
@@ -469,6 +484,10 @@ build_qemu_dependencies () {
     build_angle
     meson_build $EPOXY_REPO -Dtests=false -Dglx=no -Degl=yes
     meson_build $VIRGLRENDERER_REPO -Dtests=false
+    # Hypervisor for iOS
+    if [ "$PLATFORM" == "ios" ]; then
+        build_hypervisor
+    fi
 }
 
 build_spice_client () {
@@ -630,11 +649,13 @@ ios* )
         SDK=iphonesimulator
         CFLAGS_MINVER="-mios-simulator-version-min=$SDKMINVER"
         PLATFORM_FAMILY_PREFIX="iOS_Simulator"
+        HVF_FLAGS="--disable-hvf"
         ;;
     * )
         SDK=iphoneos
         CFLAGS_MINVER="-miphoneos-version-min=$SDKMINVER"
         PLATFORM_FAMILY_PREFIX="iOS"
+        HVF_FLAGS=""
         ;;
     esac
     CFLAGS_TARGET=
@@ -647,12 +668,13 @@ ios* )
         fi
         PLATFORM_FAMILY_NAME="$PLATFORM_FAMILY_PREFIX-TCI"
         SKIP_USB_BUILD=1
+        HVF_FLAGS="--disable-hvf"
         ;;
     * )
         PLATFORM_FAMILY_NAME="$PLATFORM_FAMILY_PREFIX"
         ;;
     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 )
     if [ -z "$SDKMINVER" ]; then
@@ -732,11 +754,11 @@ export STRIP
 export PREFIX
 
 # 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 CPPFLAGS
 export CXXFLAGS
@@ -765,6 +787,11 @@ build_pkg_config
 build_qemu_dependencies
 build $QEMU_SRC --cross-prefix="" $QEMU_PLATFORM_BUILD_FLAGS
 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
 remove_shared_gst_plugins # another hack...
 generate_qapi $QEMU_SRC

+ 2 - 3
scripts/package.sh

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