Browse Source

QEMU arguments

Kacper Raczy 5 years ago
parent
commit
1c2ce3b032

+ 4 - 2
Managers/UTMQemuSystem.m

@@ -79,8 +79,10 @@
         [self pushArgv:@"-nographic"];
         // terminal character device
         NSURL* ioFile = [self.configuration terminalInputOutputURL];
-        [self pushArgv: [NSString stringWithFormat: @"-chardev pipe,id=term0,path=%@", ioFile.path]];
-        [self pushArgv: @"-serial chardev:term0"];
+        [self pushArgv: @"-chardev"];
+        [self pushArgv: [NSString stringWithFormat: @"pipe,id=term0,path=%@", ioFile.path]];
+        [self pushArgv: @"-serial"];
+        [self pushArgv: @"chardev:term0"];
     } else {
         [self pushArgv:@"-spice"];
         [self pushArgv:@"port=5930,addr=127.0.0.1,disable-ticketing,image-compression=off,playback-compression=off,streaming-video=off"];

+ 1 - 1
Managers/UTMTerminal.h

@@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, readonly) NSURL* inPipeURL;
 @property (nonatomic, weak, nullable) id<UTMTerminalDelegate> delegate;
 
-- (id)initWithName: (NSString*) name;
+- (id)initWithURL: (NSURL*) url;
 - (BOOL)connectWithError: (NSError** _Nullable) error;
 - (void)disconnect;
 - (BOOL)isConnected;

+ 5 - 9
Managers/UTMTerminal.m

@@ -42,7 +42,7 @@ dispatch_io_t createInputIO(NSURL* url, dispatch_queue_t queue) {
     uint8_t _byteBuffer[kUTMTerminalBufferSize];
 }
 
-- (id)initWithName:(NSString *)name {
+- (id)initWithURL: (NSURL*) url {
     self = [super init];
     if (self) {
         // serial queues for input/output processing
@@ -50,7 +50,7 @@ dispatch_io_t createInputIO(NSURL* url, dispatch_queue_t queue) {
         self->_inputQueue = dispatch_queue_create("com.osy86.UTM.TerminalInputQueue", NULL);
         
         self->_outPipeFd = -1;
-        if (![self configurePipesUsingName: name]) {
+        if (![self configurePipesUsingURL: url]) {
             NSLog(@"Terminal configutation failed!");
             [self cleanup];
             self = nil;
@@ -68,18 +68,14 @@ dispatch_io_t createInputIO(NSURL* url, dispatch_queue_t queue) {
 
 #pragma mark - Configuration
 
-- (BOOL)configurePipesUsingName: (NSString*) name {
+- (BOOL)configurePipesUsingURL: (NSURL*) url {
     if ([self isConfigured]) {
         return YES;
     }
     
-    // named pipe names
-    NSString* outPipeName = [NSString stringWithFormat: @"%@.out", name];
-    NSString* inPipeName = [NSString stringWithFormat: @"%@.in", name];
     // paths
-    NSURL* tmpDir = [[NSFileManager defaultManager] temporaryDirectory];
-    NSURL* outPipeURL = [tmpDir URLByAppendingPathComponent: outPipeName];
-    NSURL* inPipeURL = [tmpDir URLByAppendingPathComponent: inPipeName];
+    NSURL* outPipeURL = [url URLByAppendingPathExtension: @"out"];
+    NSURL* inPipeURL = [url URLByAppendingPathExtension: @"in"];
     // create named pipes usign mkfifos
     const char* outPipeCPath = [[outPipeURL path] cStringUsingEncoding: NSUTF8StringEncoding];
     if (access(outPipeCPath, F_OK) != -1 && remove(outPipeCPath) != 0) {

+ 6 - 2
UTM.xcodeproj/project.pbxproj

@@ -301,6 +301,7 @@
 		E28394BB240C219F006742E2 /* terminal.js in Resources */ = {isa = PBXBuildFile; fileRef = E28394B9240C219F006742E2 /* terminal.js */; };
 		E28394BE240C22F1006742E2 /* hterm_all.js in Resources */ = {isa = PBXBuildFile; fileRef = E28394BD240C22F1006742E2 /* hterm_all.js */; };
 		E28394C1240C268A006742E2 /* VMTerminalViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E28394C0240C268A006742E2 /* VMTerminalViewController.m */; };
+		E2A798542413F6BD005FADD3 /* UTMTerminalVirtualMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A798532413F6BD005FADD3 /* UTMTerminalVirtualMachine.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -817,7 +818,8 @@
 		E28394BD240C22F1006742E2 /* hterm_all.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = hterm_all.js; path = libapps/hterm/dist/js/hterm_all.js; sourceTree = "<group>"; };
 		E28394BF240C268A006742E2 /* VMTerminalViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VMTerminalViewController.h; sourceTree = "<group>"; };
 		E28394C0240C268A006742E2 /* VMTerminalViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VMTerminalViewController.m; sourceTree = "<group>"; };
-		E2A798512413D405005FADD3 /* UTMInputOutput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMInputOutput.h; sourceTree = "<group>"; };
+		E2A798522413F6BD005FADD3 /* UTMTerminalVirtualMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMTerminalVirtualMachine.h; sourceTree = "<group>"; };
+		E2A798532413F6BD005FADD3 /* UTMTerminalVirtualMachine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UTMTerminalVirtualMachine.m; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -1358,10 +1360,11 @@
 				CE2B89352262B2F600C6D9D8 /* UTMVirtualMachineDelegate.h */,
 				CE2B89332262A21E00C6D9D8 /* UTMVirtualMachine.h */,
 				CE5F165B2261395000F3D56B /* UTMVirtualMachine.m */,
+				E2A798522413F6BD005FADD3 /* UTMTerminalVirtualMachine.h */,
+				E2A798532413F6BD005FADD3 /* UTMTerminalVirtualMachine.m */,
 				E28394B5240C20E1006742E2 /* UTMTerminal.h */,
 				E28394B3240C20E0006742E2 /* UTMTerminal.m */,
 				E28394B4240C20E1006742E2 /* UTMTerminalDelegate.h */,
-				E2A798512413D405005FADD3 /* UTMInputOutput.h */,
 			);
 			path = Managers;
 			sourceTree = "<group>";
@@ -1654,6 +1657,7 @@
 				CE23C19023FCEC0A001177D6 /* qapi-commands-dump.c in Sources */,
 				CEEB66462284B942002737B2 /* VMKeyboardButton.m in Sources */,
 				CE23C1A623FCEC0A001177D6 /* qapi-commands-introspect.c in Sources */,
+				E2A798542413F6BD005FADD3 /* UTMTerminalVirtualMachine.m in Sources */,
 				CE23C1AC23FCEC0A001177D6 /* qapi-types-sockets.c in Sources */,
 				E28394C1240C268A006742E2 /* VMTerminalViewController.m in Sources */,
 				CE23C19A23FCEC0A001177D6 /* qapi-events-block-core.c in Sources */,

+ 4 - 1
UTM/Base.lproj/Main.storyboard

@@ -154,6 +154,7 @@
                     </navigationItem>
                     <connections>
                         <segue destination="ckC-eO-gxn" kind="show" identifier="startVM" id="psC-T5-Ggl"/>
+                        <segue destination="Nen-bt-V44" kind="show" identifier="startVMConsole" id="c3m-ve-cBj"/>
                     </connections>
                 </collectionViewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="gzw-ao-My7" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -2706,6 +2707,7 @@
                                 </variation>
                             </visualEffectView>
                         </subviews>
+                        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                         <gestureRecognizers/>
                         <constraints>
                             <constraint firstAttribute="bottom" secondItem="es2-y2-iG9" secondAttribute="bottom" id="67M-kH-iti"/>
@@ -2720,6 +2722,7 @@
                         </constraints>
                         <viewLayoutGuide key="safeArea" id="Z6B-oG-xjm"/>
                     </view>
+                    <navigationItem key="navigationItem" id="eS3-Hq-J7j"/>
                     <nil key="simulatedTopBarMetrics"/>
                     <nil key="simulatedBottomBarMetrics"/>
                     <connections>
@@ -3179,7 +3182,7 @@
                 </view>
                 <exit id="dnX-hr-5QR" userLabel="Exit" sceneMemberID="exit"/>
             </objects>
-            <point key="canvasLocation" x="1829" y="-1557"/>
+            <point key="canvasLocation" x="887" y="-804"/>
         </scene>
         <!--Navigation Controller-->
         <scene sceneID="2bS-UE-pwf">

+ 2 - 2
Views/HTerm/terminal.js

@@ -7,8 +7,8 @@ function sendInputMessage(str) {
 
 function writeData(data) {
     const term = window.term;
-    const str = new TextDecoder().decode(data);
-    term.interpret(str);
+    const str = String.fromCharCode.apply(null, data);
+    term.io.print(str);
 }
 
 function terminalSetup() {

+ 17 - 7
Views/VMListViewController.m

@@ -20,6 +20,7 @@
 #import "UTMConfiguration.h"
 #import "UTMVirtualMachine.h"
 #import "VMDisplayMetalViewController.h"
+#import "VMTerminalViewController.h"
 
 @interface VMListViewController ()
 
@@ -153,6 +154,11 @@
         VMDisplayMetalViewController *metalView = (VMDisplayMetalViewController *)segue.destinationViewController;
         metalView.vm = self.activeVM;
         self.activeVM.delegate = metalView;
+    } else if ([[segue identifier] isEqualToString:@"startVMConsole"]) {
+        NSLog(@"Hereeeeee");
+        NSAssert([segue.destinationViewController isKindOfClass:[VMTerminalViewController class]], @"Destination not a terminal view");
+        VMTerminalViewController *terminalView = (VMTerminalViewController *)segue.destinationViewController;
+        terminalView.vm = self.activeVM;
     }
 }
 
@@ -217,7 +223,11 @@
             }
             case kVMStarted:
             case kVMResumed: {
-                [self performSegueWithIdentifier:@"startVM" sender:self];
+                if (vm.configuration.displayConsoleOnly) {
+                    [self performSegueWithIdentifier:@"startVMConsole" sender:self];
+                } else {
+                    [self performSegueWithIdentifier:@"startVM" sender:self];
+                }
                 break;
             }
             default: {
@@ -292,9 +302,9 @@
     NSAssert([cell isKindOfClass:[VMListViewCell class]], @"Invalid cell class");
     self.activeVM = [self cachedVMForCell:cell];
     self.activeCell = cell;
-    self.activeVM.delegate = self;
-    [self.activeVM startVM];
-    [self virtualMachine:self.activeVM transitionToState:self.activeVM.state];
+    //self.activeVM.delegate = self;
+    //[self.activeVM startVM];
+    [self virtualMachine:self.activeVM transitionToState:kVMStarted];
 }
 
 - (IBAction)startVMFromScreen:(UIButton *)sender {
@@ -302,9 +312,9 @@
     NSAssert([cell isKindOfClass:[VMListViewCell class]], @"Invalid cell class");
     self.activeVM = [self cachedVMForCell:cell];
     self.activeCell = cell;
-    self.activeVM.delegate = self;
-    [self.activeVM startVM];
-    [self virtualMachine:self.activeVM transitionToState:self.activeVM.state];
+    //self.activeVM.delegate = self;
+    //[self.activeVM startVM];
+    [self virtualMachine:self.activeVM transitionToState:kVMStarted];
 }
 
 @end

+ 75 - 5
Views/VMTerminalViewController.m

@@ -15,17 +15,42 @@
 //
 
 #import "VMTerminalViewController.h"
+#import "UTMConfiguration.h"
 
 NSString *const kVMSendInputHandler = @"UTMSendInput";
 
-@implementation VMTerminalViewController
+@implementation VMTerminalViewController {
+    // status bar
+    BOOL _prefersStatusBarHidden;
+}
+
+- (BOOL)prefersStatusBarHidden {
+    return _prefersStatusBarHidden;
+}
+
+- (void)setPrefersStatusBarHidden:(BOOL)prefersStatusBarHidden {
+    _prefersStatusBarHidden = prefersStatusBarHidden;
+    [self setNeedsStatusBarAppearanceUpdate];
+}
+
+- (BOOL)prefersHomeIndicatorAutoHidden {
+    return YES; // always hide home indicator
+}
 
 - (void)viewDidLoad {
-    [super viewDidLoad];
-    // ...get vm name
+    [super viewDidLoad];    
     // terminal setup
-    _terminal = [[UTMTerminal alloc] initWithName: @"vmName"];
+    NSURL* terminalIOURL = [[_vm configuration] terminalInputOutputURL];
+    _terminal = [[UTMTerminal alloc] initWithURL: terminalIOURL];
     [_terminal setDelegate: self];
+    
+    NSError* error;
+    [_terminal connectWithError: &error];
+    if (error != nil) {
+        NSLog(@"Terminal connection error!");
+    }
+    
+    [_vm startVM];
     // message handlers
     [[[_webView configuration] userContentController] addScriptMessageHandler: self name: kVMSendInputHandler];
     
@@ -33,6 +58,18 @@ NSString *const kVMSendInputHandler = @"UTMSendInput";
     NSURL* resourceURL = [[NSBundle mainBundle] resourceURL];
     NSURL* indexFile = [resourceURL URLByAppendingPathComponent: @"terminal.html"];
     [_webView loadFileURL: indexFile allowingReadAccessToURL: resourceURL];
+    
+    [self updateWebViewScrollOffset: NO];
+}
+
+- (void)viewDidLayoutSubviews {
+    [super viewDidLayoutSubviews];
+    [self updateWebViewScrollOffset: [self.toolbarAccessoryView isHidden]];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear: animated];
+    [self.navigationController setNavigationBarHidden:YES animated:animated];
 }
 
 #pragma mark - WKScriptMessageHandler
@@ -45,7 +82,13 @@ NSString *const kVMSendInputHandler = @"UTMSendInput";
 }
 
 - (void)terminal:(UTMTerminal *)terminal didReceiveData:(NSData *)data {
-    NSString* dataString;
+    NSMutableString* dataString = [NSMutableString stringWithString: @"["];
+    const uint8_t* buf = (uint8_t*) [data bytes];
+    for (size_t i = 0; i < [data length]; i++) {
+        [dataString appendFormat: @"%u,", buf[i]];
+    }
+    [dataString appendString:@"]"];
+    //NSLog(@"Array: %@", dataString);
     NSString* jsString = [NSString stringWithFormat: @"writeData(new Uint8Array(%@));", dataString];
     [_webView evaluateJavaScript: jsString completionHandler:^(id _Nullable _, NSError * _Nullable error) {
         if (error == nil) {
@@ -73,9 +116,36 @@ NSString *const kVMSendInputHandler = @"UTMSendInput";
 }
 
 - (IBAction)showKeyboardPressed:(UIButton *)sender {
+    // set focus on some element in JS 
 }
 
 - (IBAction)hideToolbarPressed:(UIButton *)sender {
+    [self hideToolbar];
+}
+
+#pragma mark - Toolbar actions
+
+- (void)hideToolbar {
+    [UIView transitionWithView:self.view duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
+        self.toolbarAccessoryView.hidden = YES;
+        self.prefersStatusBarHidden = YES;
+    } completion:nil];
+    [self updateWebViewScrollOffset:YES];
+}
+
+- (void)showToolbar {
+    [UIView transitionWithView:self.view duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
+        self.toolbarAccessoryView.hidden = NO;
+        self.prefersStatusBarHidden = NO;
+    } completion:nil];
+    [self updateWebViewScrollOffset:NO];
+}
+
+- (void)updateWebViewScrollOffset: (BOOL) toolbarHidden {
+//    CGFloat offset = 0.0;
+//    if (!toolbarHidden) {
+//        offset = self.toolbarAccessoryView.bounds.size.height;
+//    }
 }
 
 @end