Prechádzať zdrojové kódy

vm(apple): load/save VM

osy 4 rokov pred
rodič
commit
28fadb4b63

+ 4 - 7
AppleVirtualization/UTMAppleConfiguration.swift

@@ -362,6 +362,8 @@ final class UTMAppleConfiguration: UTMConfigurable, Codable, ObservableObject {
         consoleCursorBlink = true
         version = currentVersion
         isAppleVirtualization = true
+        memorySize = 4 * 1024 * 1024 * 1024
+        cpuCount = 4
     }
     
     required convenience init(from decoder: Decoder) throws {
@@ -445,14 +447,9 @@ final class UTMAppleConfiguration: UTMConfigurable, Codable, ObservableObject {
         try container.encodeIfPresent(consoleResizeCommand, forKey: .consoleResizeCommand)
     }
     
-    func resetDefaults() {
-        memorySize = 4 * 1024 * 1024 * 1024
-        cpuCount = 4
-    }
-    
     static func load(from packageURL: URL) throws -> UTMAppleConfiguration {
         let dataURL = packageURL.appendingPathComponent("Data")
-        let configURL = packageURL.appendingPathComponent("config.plist")
+        let configURL = packageURL.appendingPathComponent(kUTMBundleConfigFilename)
         let configData = try Data(contentsOf: configURL)
         let decoder = PropertyListDecoder()
         decoder.userInfo = [.dataURL: dataURL]
@@ -481,7 +478,7 @@ final class UTMAppleConfiguration: UTMConfigurable, Codable, ObservableObject {
         // create config.plist
         let encoder = PropertyListEncoder()
         let settingsData = try encoder.encode(self)
-        try settingsData.write(to: packageURL.appendingPathComponent("config.plist"))
+        try settingsData.write(to: packageURL.appendingPathComponent(kUTMBundleConfigFilename))
     }
     
     private func copyItemIfChanged(from sourceURL: URL, to destFolderURL: URL) throws -> URL {

+ 1 - 1
Configuration/UTMConfigurable.h

@@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, assign) BOOL consoleCursorBlink;
 @property (nonatomic, nullable, copy) NSString *consoleResizeCommand;
 
-- (void)resetDefaults;
+@property (nonatomic, readonly, assign) BOOL isAppleVirtualization;
 
 @end
 

+ 4 - 0
Configuration/UTMQemuConfiguration.m

@@ -153,4 +153,8 @@ const NSInteger kCurrentConfigurationVersion = 2;
     return self.rootDict[kUTMConfigVersionKey];
 }
 
+- (BOOL)isAppleVirtualization {
+    return NO;
+}
+
 @end

+ 53 - 0
Managers/UTMAppleVirtualMachine.swift

@@ -0,0 +1,53 @@
+//
+// Copyright © 2021 osy. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+@available(macOS 12, *)
+@objc class UTMAppleVirtualMachine: UTMVirtualMachine {
+    var appleConfig: UTMAppleConfiguration! {
+        config as? UTMAppleConfiguration
+    }
+    
+    override static func isAppleVM(forPath path: URL) -> Bool {
+        do {
+            _ = try UTMAppleConfiguration.load(from: path)
+            return true
+        } catch {
+            return false
+        }
+    }
+    
+    override func loadConfiguration(withReload reload: Bool) throws {
+        config = try UTMAppleConfiguration.load(from: path!)
+    }
+    
+    override func saveUTM() throws {
+        let fileManager = FileManager.default
+        let newPath = packageURL(forName: appleConfig.name)
+        let savePath: URL
+        if let existingPath = path {
+            savePath = existingPath
+        } else {
+            savePath = newPath
+        }
+        try appleConfig.save(to: savePath)
+        if let existingPath = path, existingPath.lastPathComponent != newPath.lastPathComponent {
+            try fileManager.moveItem(at: existingPath, to: newPath)
+            path = newPath
+        } else {
+            path = savePath
+        }
+    }
+}

+ 1 - 4
Managers/UTMQemuVirtualMachine.m

@@ -15,6 +15,7 @@
 //
 
 #import <TargetConditionals.h>
+#import "UTMVirtualMachine-Protected.h"
 #import "UTMVirtualMachine-Private.h"
 #import "UTMQemuVirtualMachine.h"
 #import "UTMQemuVirtualMachine+Drives.h"
@@ -106,10 +107,6 @@ NSString *const kSuspendSnapshotName = @"suspend";
     return YES;
 }
 
-- (BOOL)reloadConfigurationWithError:(NSError * _Nullable *)err {
-    return [self loadConfigurationWithReload:YES error:err];
-}
-
 - (BOOL)saveConfigurationWithError:(NSError * _Nullable __autoreleasing *)err {
     NSURL *url = [self packageURLForName:self.qemuConfig.name];
     if (![self savePlist:[url URLByAppendingPathComponent:kUTMBundleConfigFilename]

+ 0 - 7
Managers/UTMVirtualMachine-Private.h

@@ -20,24 +20,17 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface UTMVirtualMachine ()
 
-@property (nonatomic, readwrite, nullable) NSURL *path;
 @property (nonatomic, strong) NSURL *parentPath;
-@property (nonatomic, readwrite, copy) id<UTMConfigurable> config;
 @property (nonatomic, readwrite) UTMViewState *viewState;
 @property (nonatomic) UTMLogging *logging;
 @property (nonatomic, readwrite) BOOL busy;
-@property (nonatomic, readwrite, nullable) UTMScreenshot *screenshot;
 @property (nonatomic, assign, readwrite) UTMVMState state;
 
 - (instancetype)init;
 - (nullable instancetype)initWithURL:(NSURL *)url;
 - (instancetype)initWithConfiguration:(id<UTMConfigurable>)configuration withDestinationURL:(NSURL *)dstUrl;
 
-- (NSURL *)packageURLForName:(NSString *)name;
-- (void)changeState:(UTMVMState)state;
-- (void)errorTriggered:(nullable NSString *)msg;
 - (BOOL)loadConfigurationWithReload:(BOOL)reload error:(NSError * _Nullable __autoreleasing *)err;
-
 - (NSDictionary *)loadPlist:(NSURL *)path withError:(NSError **)err;
 - (BOOL)savePlist:(NSURL *)path dict:(NSDictionary *)dict withError:(NSError **)err;
 - (void)syncViewState;

+ 13 - 0
Managers/UTMVirtualMachine-Protected.h

@@ -18,6 +18,8 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+extern NSString *const kUTMBundleConfigFilename;
+
 @interface UTMVirtualMachine ()
 
 @property (nonatomic, readonly) NSString *title;
@@ -30,6 +32,17 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, readonly) NSString *systemArchitecture;
 @property (nonatomic, readonly) NSString *systemMemory;
 
+@property (nonatomic, readwrite, nullable) NSURL *path;
+@property (nonatomic, readwrite, copy) id<UTMConfigurable> config;
+@property (nonatomic, readwrite, nullable) UTMScreenshot *screenshot;
+
++ (BOOL)isAppleVMForPath:(NSURL *)path;
+- (NSURL *)packageURLForName:(NSString *)name;
+- (void)changeState:(UTMVMState)state;
+- (void)errorTriggered:(nullable NSString *)msg;
+
+- (BOOL)loadConfigurationWithReload:(BOOL)reload error:(NSError * _Nullable __autoreleasing *)err;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 18 - 0
Managers/UTMVirtualMachine.m

@@ -79,13 +79,27 @@ NSString *const kUTMBundleScreenshotFilename = @"screenshot.png";
 }
 
 + (nullable UTMVirtualMachine *)virtualMachineWithURL:(NSURL *)url {
+    if (@available(macOS 12, *)) {
+        if ([self isAppleVMForPath:url]) {
+            return [[UTMAppleVirtualMachine alloc] initWithURL:url];
+        }
+    }
     return [[UTMQemuVirtualMachine alloc] initWithURL:url];
 }
 
 + (UTMVirtualMachine *)virtualMachineWithConfiguration:(id<UTMConfigurable>)configuration withDestinationURL:(NSURL *)dstUrl {
+    if (@available(macOS 12, *)) {
+        if (configuration.isAppleVirtualization) {
+            return [[UTMAppleVirtualMachine alloc] initWithConfiguration:configuration withDestinationURL:dstUrl];
+        }
+    }
     return [[UTMQemuVirtualMachine alloc] initWithConfiguration:configuration withDestinationURL:dstUrl];
 }
 
++ (BOOL)isAppleVMForPath:(NSURL *)path {
+    return NO;
+}
+
 - (instancetype)init {
     self = [super init];
     if (self) {
@@ -154,6 +168,10 @@ NSString *const kUTMBundleScreenshotFilename = @"screenshot.png";
     }
 }
 
+- (BOOL)reloadConfigurationWithError:(NSError * _Nullable *)err {
+    return [self loadConfigurationWithReload:YES error:err];
+}
+
 #define notImplemented @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass.", __PRETTY_FUNCTION__] userInfo:nil]
 
 - (BOOL)loadConfigurationWithReload:(BOOL)reload error:(NSError * _Nullable __autoreleasing *)err {

+ 4 - 0
UTM.xcodeproj/project.pbxproj

@@ -693,6 +693,7 @@
 		CE900B9F25FC2869007533FD /* CSUSBManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE900B9D25FC2869007533FD /* CSUSBManager.m */; };
 		CE900BAF25FC3E65007533FD /* CSUSBDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = CE900BAE25FC3E65007533FD /* CSUSBDevice.m */; };
 		CE900BB025FC3E65007533FD /* CSUSBDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = CE900BAE25FC3E65007533FD /* CSUSBDevice.m */; };
+		CE928C2A26ABE6690099F293 /* UTMAppleVirtualMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE928C2926ABE6690099F293 /* UTMAppleVirtualMachine.swift */; };
 		CE93758924B930270074066F /* BusyOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7D972B24B2B17D0080CB69 /* BusyOverlay.swift */; };
 		CE93759624BB7EA00074066F /* UTMTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE93759524BB7E9F0074066F /* UTMTabViewController.swift */; };
 		CE93759924BB821F0074066F /* IQKeyboardManagerSwift in Frameworks */ = {isa = PBXBuildFile; productRef = CE93759824BB821F0074066F /* IQKeyboardManagerSwift */; };
@@ -1995,6 +1996,7 @@
 		CE900BA225FC31E4007533FD /* CSUSBManagerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSUSBManagerDelegate.h; sourceTree = "<group>"; };
 		CE900BAD25FC3E65007533FD /* CSUSBDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSUSBDevice.h; sourceTree = "<group>"; };
 		CE900BAE25FC3E65007533FD /* CSUSBDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSUSBDevice.m; sourceTree = "<group>"; };
+		CE928C2926ABE6690099F293 /* UTMAppleVirtualMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMAppleVirtualMachine.swift; sourceTree = "<group>"; };
 		CE93759524BB7E9F0074066F /* UTMTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMTabViewController.swift; sourceTree = "<group>"; };
 		CE9375A024BBDDD10074066F /* VMConfigDriveDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMConfigDriveDetailsView.swift; sourceTree = "<group>"; };
 		CE9A352D26533A51005077CF /* JailbreakInterposer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JailbreakInterposer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -2996,6 +2998,7 @@
 				84C584DC268E70F1000FCABF /* UTMVirtualMachine-Protected.h */,
 				84FCABC8268D17E70036196C /* UTMVirtualMachine+IO.h */,
 				84FCABC9268D17E70036196C /* UTMVirtualMachine+IO.m */,
+				CE928C2926ABE6690099F293 /* UTMAppleVirtualMachine.swift */,
 				E28394B5240C20E1006742E2 /* UTMTerminal.h */,
 				E28394B3240C20E0006742E2 /* UTMTerminal.m */,
 				E28394B4240C20E1006742E2 /* UTMTerminalDelegate.h */,
@@ -3995,6 +3998,7 @@
 				CEF0306026A2AFDF00667B63 /* VMWizardState.swift in Sources */,
 				CEF0300826A25A6900667B63 /* VMWizardView.swift in Sources */,
 				CE0B6D4924AD584C00FE012D /* qapi-types-trace.c in Sources */,
+				CE928C2A26ABE6690099F293 /* UTMAppleVirtualMachine.swift in Sources */,
 				CE0B6D7724AD584D00FE012D /* qapi-events-misc-target.c in Sources */,
 				CE0B6CF524AD568400FE012D /* UTMQemuConfiguration+Miscellaneous.m in Sources */,
 				CE0B6CFB24AD568400FE012D /* UTMQemuConfiguration+Networking.m in Sources */,