Showing preview only (5,412K chars total). Download the full file or copy to clipboard to get everything.
Repository: utmapp/UTM
Branch: main
Commit: 30c8202c630c
Files: 549
Total size: 5.1 MB
Directory structure:
gitextract_miqecj8q/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── bug_report_macos.md
│ │ └── feature_request.md
│ └── workflows/
│ ├── build.yml
│ └── issues.yml
├── .gitignore
├── Build.xcconfig
├── CONTRIBUTING.md
├── CodeSigning.xcconfig.sample
├── Configuration/
│ ├── Legacy/
│ │ ├── UTMLegacyAppleConfiguration.swift
│ │ ├── UTMLegacyQemuConfiguration+Constants.h
│ │ ├── UTMLegacyQemuConfiguration+Constants.m
│ │ ├── UTMLegacyQemuConfiguration+Display.h
│ │ ├── UTMLegacyQemuConfiguration+Display.m
│ │ ├── UTMLegacyQemuConfiguration+Drives.h
│ │ ├── UTMLegacyQemuConfiguration+Drives.m
│ │ ├── UTMLegacyQemuConfiguration+Miscellaneous.h
│ │ ├── UTMLegacyQemuConfiguration+Miscellaneous.m
│ │ ├── UTMLegacyQemuConfiguration+Networking.h
│ │ ├── UTMLegacyQemuConfiguration+Networking.m
│ │ ├── UTMLegacyQemuConfiguration+Sharing.h
│ │ ├── UTMLegacyQemuConfiguration+Sharing.m
│ │ ├── UTMLegacyQemuConfiguration+System.h
│ │ ├── UTMLegacyQemuConfiguration+System.m
│ │ ├── UTMLegacyQemuConfiguration.h
│ │ ├── UTMLegacyQemuConfiguration.m
│ │ ├── UTMLegacyQemuConfigurationPortForward.h
│ │ ├── UTMLegacyQemuConfigurationPortForward.m
│ │ ├── UTMLegacyViewState.h
│ │ └── UTMLegacyViewState.m
│ ├── QEMUArgument.swift
│ ├── QEMUArgumentBuilder.swift
│ ├── QEMUConstant.swift
│ ├── QEMUConstantGenerated.swift
│ ├── UTMAppleConfiguration.swift
│ ├── UTMAppleConfigurationBoot.swift
│ ├── UTMAppleConfigurationDisplay.swift
│ ├── UTMAppleConfigurationDrive.swift
│ ├── UTMAppleConfigurationGenericPlatform.swift
│ ├── UTMAppleConfigurationMacPlatform.swift
│ ├── UTMAppleConfigurationNetwork.swift
│ ├── UTMAppleConfigurationSerial.swift
│ ├── UTMAppleConfigurationSharedDirectory.swift
│ ├── UTMAppleConfigurationSystem.swift
│ ├── UTMAppleConfigurationVirtualization.swift
│ ├── UTMConfiguration.swift
│ ├── UTMConfigurationDrive.swift
│ ├── UTMConfigurationHostNetwork.swift
│ ├── UTMConfigurationInfo.swift
│ ├── UTMConfigurationTerminal.swift
│ ├── UTMQemuConfiguration+Arguments.swift
│ ├── UTMQemuConfiguration.swift
│ ├── UTMQemuConfigurationDisplay.swift
│ ├── UTMQemuConfigurationDrive.swift
│ ├── UTMQemuConfigurationInput.swift
│ ├── UTMQemuConfigurationNetwork.swift
│ ├── UTMQemuConfigurationPortForward.swift
│ ├── UTMQemuConfigurationQEMU.swift
│ ├── UTMQemuConfigurationSerial.swift
│ ├── UTMQemuConfigurationSharing.swift
│ ├── UTMQemuConfigurationSound.swift
│ └── UTMQemuConfigurationSystem.swift
├── Documentation/
│ ├── Architecture.md
│ ├── Dependencies.md
│ ├── Graphics.md
│ ├── MacDevelopment.md
│ ├── Release.md
│ ├── TetheredLaunch.md
│ ├── TetheredLaunch.zh-HK.md
│ ├── TetheredLaunch.zh-Hans.md
│ ├── TetheredLaunch.zh-Hant.md
│ └── iOSDevelopment.md
├── Intents/
│ ├── UTMActionIntent.swift
│ ├── UTMInputIntent.swift
│ ├── UTMIntent.swift
│ ├── UTMVirtualMachineEntity.swift
│ └── UTMVirtualMachineEntityQuery.swift
├── JailbreakInterposer/
│ ├── Info.plist
│ └── JailbreakInterposer.c
├── LICENSE
├── Platform/
│ ├── AppIcon-Remote.icon/
│ │ └── icon.json
│ ├── AppIcon.icon/
│ │ └── icon.json
│ ├── Assets.xcassets/
│ │ ├── AccentColor-Remote.colorset/
│ │ │ └── Contents.json
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Remote.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Remote.solidimagestack/
│ │ │ ├── Back.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Front.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ └── Middle.solidimagestacklayer/
│ │ │ ├── Content.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.solidimagestack/
│ │ │ ├── Back.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Front.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ └── Middle.solidimagestacklayer/
│ │ │ ├── Content.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── Keyboard Hide.imageset/
│ │ │ └── Contents.json
│ │ ├── Keyboard Paste.imageset/
│ │ │ └── Contents.json
│ │ ├── Logo-Linux.imageset/
│ │ │ └── Contents.json
│ │ ├── Logo-Windows.imageset/
│ │ │ └── Contents.json
│ │ ├── Logo-macOS.imageset/
│ │ │ └── Contents.json
│ │ ├── MenuBarExtra.imageset/
│ │ │ └── Contents.json
│ │ └── Toolbar USB.imageset/
│ │ └── Contents.json
│ ├── Main.swift
│ ├── Shared/
│ │ ├── BigButtonStyle.swift
│ │ ├── BusyIndicator.swift
│ │ ├── BusyOverlay.swift
│ │ ├── ContentView.swift
│ │ ├── DefaultTextField.swift
│ │ ├── DestructiveButton.swift
│ │ ├── DetailedSection.swift
│ │ ├── FileBrowseField.swift
│ │ ├── GlobalFileImporter.swift
│ │ ├── InListButtonStyle.swift
│ │ ├── MacDeviceLabel.swift
│ │ ├── MenuLabel.swift
│ │ ├── NumberTextField.swift
│ │ ├── RAMSlider.swift
│ │ ├── SizeTextField.swift
│ │ ├── Spinner.swift
│ │ ├── UTMPendingVMView.swift
│ │ ├── UTMPlaceholderVMView.swift
│ │ ├── UTMTips.swift
│ │ ├── UTMUnavailableVMView.swift
│ │ ├── VMCardView.swift
│ │ ├── VMCommands.swift
│ │ ├── VMConfigAdvancedNetworkView.swift
│ │ ├── VMConfigConstantPicker.swift
│ │ ├── VMConfigDisplayConsoleView.swift
│ │ ├── VMConfigDisplayView.swift
│ │ ├── VMConfigDriveCreateView.swift
│ │ ├── VMConfigDriveDetailsView.swift
│ │ ├── VMConfigInfoView.swift
│ │ ├── VMConfigInputView.swift
│ │ ├── VMConfigNetworkView.swift
│ │ ├── VMConfigPortForwardForm.swift
│ │ ├── VMConfigQEMUView.swift
│ │ ├── VMConfigSerialView.swift
│ │ ├── VMConfigSharingView.swift
│ │ ├── VMConfigSoundView.swift
│ │ ├── VMConfigSystemView.swift
│ │ ├── VMConfirmActionModifier.swift
│ │ ├── VMContextMenuModifier.swift
│ │ ├── VMDetailsView.swift
│ │ ├── VMKeyboardMap.h
│ │ ├── VMKeyboardMap.m
│ │ ├── VMNavigationListView.swift
│ │ ├── VMPlaceholderView.swift
│ │ ├── VMReleaseNotesView.swift
│ │ ├── VMRemovableDrivesView.swift
│ │ ├── VMSettingsAddDeviceMenuView.swift
│ │ ├── VMShareFileModifier.swift
│ │ ├── VMToolbarModifier.swift
│ │ ├── VMWizardContent.swift
│ │ ├── VMWizardDrivesView.swift
│ │ ├── VMWizardHardwareView.swift
│ │ ├── VMWizardOSClassicMacView.swift
│ │ ├── VMWizardOSLinuxView.swift
│ │ ├── VMWizardOSMacView.swift
│ │ ├── VMWizardOSOtherView.swift
│ │ ├── VMWizardOSView.swift
│ │ ├── VMWizardOSWindowsView.swift
│ │ ├── VMWizardSharingView.swift
│ │ ├── VMWizardStartView.swift
│ │ ├── VMWizardStartViewTCI.swift
│ │ ├── VMWizardState.swift
│ │ └── VMWizardSummaryView.swift
│ ├── UTMData.swift
│ ├── UTMDownloadIPSWTask.swift
│ ├── UTMDownloadMacSupportToolsTask.swift
│ ├── UTMDownloadSupportToolsTask.swift
│ ├── UTMDownloadTask.swift
│ ├── UTMDownloadVMTask.swift
│ ├── UTMPendingVirtualMachine.swift
│ ├── UTMReleaseHelper.swift
│ ├── VMData.swift
│ ├── ar.lproj/
│ │ └── Localizable.strings
│ ├── de.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── en.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── es-419.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── fi.lproj/
│ │ └── Localizable.strings
│ ├── fr.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── iOS/
│ │ ├── ActivityView.swift
│ │ ├── Display/
│ │ │ ├── Base.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.xib
│ │ │ ├── VMCursor.h
│ │ │ ├── VMCursor.m
│ │ │ ├── VMDisplayMetalViewController+Gamepad.h
│ │ │ ├── VMDisplayMetalViewController+Gamepad.m
│ │ │ ├── VMDisplayMetalViewController+Keyboard.h
│ │ │ ├── VMDisplayMetalViewController+Keyboard.m
│ │ │ ├── VMDisplayMetalViewController+Pencil.h
│ │ │ ├── VMDisplayMetalViewController+Pencil.m
│ │ │ ├── VMDisplayMetalViewController+Pointer.h
│ │ │ ├── VMDisplayMetalViewController+Pointer.m
│ │ │ ├── VMDisplayMetalViewController+Private.h
│ │ │ ├── VMDisplayMetalViewController+Touch.h
│ │ │ ├── VMDisplayMetalViewController+Touch.m
│ │ │ ├── VMDisplayMetalViewController.h
│ │ │ ├── VMDisplayMetalViewController.m
│ │ │ ├── VMDisplayTerminalViewController.swift
│ │ │ ├── VMDisplayViewController.h
│ │ │ ├── VMDisplayViewController.m
│ │ │ ├── VMDisplayViewController.swift
│ │ │ ├── VMDisplayViewControllerDelegate.swift
│ │ │ ├── VMKeyboardButton.h
│ │ │ ├── VMKeyboardButton.m
│ │ │ ├── VMKeyboardView.h
│ │ │ ├── VMKeyboardView.m
│ │ │ ├── VMKeyboardViewDelegate.h
│ │ │ ├── VMScroll.h
│ │ │ ├── VMScroll.m
│ │ │ ├── de.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── es-419.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── fi.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── fr.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── ja.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── ko.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── pl.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── zh-HK.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── zh-Hans.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ └── zh-Hant.lproj/
│ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ ├── Donation.storekit
│ │ ├── IASKAppSettings.swift
│ │ ├── ImagePicker.swift
│ │ ├── Info-Remote.plist
│ │ ├── Info.plist
│ │ ├── Legacy/
│ │ │ └── VMConfigNewStorageViewController.m
│ │ ├── PrivacyInfo.xcprivacy
│ │ ├── RemoteContentView.swift
│ │ ├── Settings.bundle/
│ │ │ ├── License.plist
│ │ │ ├── Root.plist
│ │ │ ├── de.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── en.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── es-419.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── ja.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── ko.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── zh-HK.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── zh-Hans.lproj/
│ │ │ │ └── Root.strings
│ │ │ └── zh-Hant.lproj/
│ │ │ └── Root.strings
│ │ ├── UTMApp.swift
│ │ ├── UTMDataExtension.swift
│ │ ├── UTMDonateStore.swift
│ │ ├── UTMDonateView.swift
│ │ ├── UTMExternalSceneDelegate.swift
│ │ ├── UTMPatches.swift
│ │ ├── UTMRemoteConnectView.swift
│ │ ├── UTMSettingsView.swift
│ │ ├── UTMSingleWindowView.swift
│ │ ├── VMConfigNetworkPortForwardView.swift
│ │ ├── VMDisplayHostedView.swift
│ │ ├── VMDrivesSettingsView.swift
│ │ ├── VMKeyboardShortcutsView.swift
│ │ ├── VMSessionState.swift
│ │ ├── VMSettingsView.swift
│ │ ├── VMToolbarDisplayMenuView.swift
│ │ ├── VMToolbarDriveMenuView.swift
│ │ ├── VMToolbarUSBMenuView.swift
│ │ ├── VMToolbarView.swift
│ │ ├── VMWindowState.swift
│ │ ├── VMWindowView.swift
│ │ ├── VMWizardView.swift
│ │ ├── de.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── en.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── es-419.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fi.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fr.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── iOS.entitlements
│ │ ├── it.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ja.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── ko.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── pl.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── ru.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── zh-HK.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── zh-Hans.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ └── zh-Hant.lproj/
│ │ └── InfoPlist.strings
│ ├── it.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── ja.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── ko.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── macOS/
│ │ ├── AppDelegate.swift
│ │ ├── Display/
│ │ │ ├── Base.lproj/
│ │ │ │ └── VMDisplayWindow.xib
│ │ │ ├── VMDisplayAppleDisplayWindowController.swift
│ │ │ ├── VMDisplayAppleTerminalWindowController.swift
│ │ │ ├── VMDisplayAppleWindowController.swift
│ │ │ ├── VMDisplayQemuDisplayController.swift
│ │ │ ├── VMDisplayQemuMetalWindowController.swift
│ │ │ ├── VMDisplayQemuTerminalWindowController.swift
│ │ │ ├── VMDisplayTerminal.swift
│ │ │ ├── VMDisplayWindowController.swift
│ │ │ ├── VMMetalView.swift
│ │ │ ├── VMMetalViewInputDelegate.swift
│ │ │ ├── de.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── es-419.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── fi.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── fr.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── it.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── ja.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── ko.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── pl.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── ru.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── zh-HK.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── zh-Hans.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ └── zh-Hant.lproj/
│ │ │ └── VMDisplayWindow.strings
│ │ ├── DoubleClickHandler.swift
│ │ ├── Info.plist
│ │ ├── KeyCodeMap.swift
│ │ ├── SavePanel.swift
│ │ ├── SettingsView.swift
│ │ ├── UTMApp.swift
│ │ ├── UTMDataExtension.swift
│ │ ├── UTMMenuBarExtraScene.swift
│ │ ├── UTMPatches.swift
│ │ ├── UTMServerView.swift
│ │ ├── VMAppleRemovableDrivesView.swift
│ │ ├── VMAppleSettingsAddDeviceMenuView.swift
│ │ ├── VMAppleSettingsView.swift
│ │ ├── VMConfigAppleBootView.swift
│ │ ├── VMConfigAppleDisplayView.swift
│ │ ├── VMConfigAppleDriveCreateView.swift
│ │ ├── VMConfigAppleDriveDetailsView.swift
│ │ ├── VMConfigAppleNetworkingView.swift
│ │ ├── VMConfigAppleSerialView.swift
│ │ ├── VMConfigAppleSharingView.swift
│ │ ├── VMConfigAppleSystemView.swift
│ │ ├── VMConfigAppleVirtualizationView.swift
│ │ ├── VMConfigNetworkPortForwardView.swift
│ │ ├── VMConfigQEMUArgumentsView.swift
│ │ ├── VMDrivesSettingsView.swift
│ │ ├── VMHeadlessSessionState.swift
│ │ ├── VMKeyboardShortcutsView.swift
│ │ ├── VMQEMUSettingsView.swift
│ │ ├── VMRemoteSessionState.swift
│ │ ├── VMSettingsView.swift
│ │ ├── VMWizardView.swift
│ │ ├── de.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── en.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── es-419.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fi.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fr.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── it.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ja.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ko.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── macOS-unsigned.entitlements
│ │ ├── macOS.entitlements
│ │ ├── pl.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ru.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── zh-HK.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── zh-Hans.lproj/
│ │ │ └── InfoPlist.strings
│ │ └── zh-Hant.lproj/
│ │ └── InfoPlist.strings
│ ├── pl.lproj/
│ │ ├── InfoPlist.strings
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── ru.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── visionOS/
│ │ ├── UTMApp.swift
│ │ └── VMToolbarOrnamentModifier.swift
│ ├── zh-HK.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── zh-Hans.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ └── zh-Hant.lproj/
│ ├── Localizable.strings
│ └── Localizable.stringsdict
├── QEMUHelper/
│ ├── Info.plist
│ ├── QEMUHelper-unsigned.entitlements
│ ├── QEMUHelper.entitlements
│ ├── QEMUHelper.h
│ ├── QEMUHelper.m
│ ├── QEMUHelperDelegate.h
│ ├── QEMUHelperProtocol.h
│ ├── de.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── en.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── es-419.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── fi.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── fr.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── it.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── ja.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── ko.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── main.m
│ ├── pl.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── ru.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── zh-HK.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── zh-Hans.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ └── zh-Hant.lproj/
│ ├── InfoPlist.strings
│ └── Localizable.strings
├── QEMULauncher/
│ ├── Bootstrap.c
│ ├── Bootstrap.h
│ ├── Info.plist
│ ├── QEMULauncher-unsigned.entitlements
│ ├── QEMULauncher.entitlements
│ ├── de.lproj/
│ │ └── InfoPlist.strings
│ ├── es-419.lproj/
│ │ └── InfoPlist.strings
│ ├── main.c
│ └── pl.lproj/
│ └── InfoPlist.strings
├── README.bn.md
├── README.cz.md
├── README.es.md
├── README.fr.md
├── README.ja.md
├── README.ko.md
├── README.md
├── README.pl-PL.md
├── README.ru.md
├── README.uk.md
├── README.zh-HK.md
├── README.zh-Hans.md
├── README.zh-Hant.md
├── Remote/
│ ├── GenerateKey.c
│ ├── GenerateKey.h
│ ├── UTMRemoteClient.swift
│ ├── UTMRemoteConnectInterface.h
│ ├── UTMRemoteKeyManager.swift
│ ├── UTMRemoteMessage.swift
│ ├── UTMRemoteServer.swift
│ └── UTMRemoteSpiceVirtualMachine.swift
├── Renderer/
│ └── LICENSE.txt
├── Scripting/
│ ├── UTM.sdef
│ ├── UTMScriptable.swift
│ ├── UTMScripting.swift
│ ├── UTMScriptingCloneCommand.swift
│ ├── UTMScriptingConfigImpl.swift
│ ├── UTMScriptingCreateCommand.swift
│ ├── UTMScriptingDeleteCommand.swift
│ ├── UTMScriptingExportCommand.swift
│ ├── UTMScriptingGuestFileImpl.swift
│ ├── UTMScriptingGuestProcessImpl.swift
│ ├── UTMScriptingImportCommand.swift
│ ├── UTMScriptingInputImpl.swift
│ ├── UTMScriptingRegistryEntryImpl.swift
│ ├── UTMScriptingSerialPortImpl.swift
│ ├── UTMScriptingUSBDeviceImpl.swift
│ └── UTMScriptingVirtualMachineImpl.swift
├── Services/
│ ├── Swift-Bridging-Header.h
│ ├── UTMASIFImage.h
│ ├── UTMASIFImage.m
│ ├── UTMAppleVirtualMachine.swift
│ ├── UTMExtensions.swift
│ ├── UTMJailbreak.h
│ ├── UTMJailbreak.m
│ ├── UTMKeyboardShortcuts.swift
│ ├── UTMLocationManager.h
│ ├── UTMLocationManager.m
│ ├── UTMLogging.h
│ ├── UTMLogging.m
│ ├── UTMLoggingSwift.swift
│ ├── UTMPasteboard.swift
│ ├── UTMPipeInterface.swift
│ ├── UTMProcess.h
│ ├── UTMProcess.m
│ ├── UTMQemuImage.swift
│ ├── UTMQemuPort.swift
│ ├── UTMQemuSystem.h
│ ├── UTMQemuSystem.m
│ ├── UTMQemuSystemBackends.h
│ ├── UTMQemuVirtualMachine.swift
│ ├── UTMRegistry.swift
│ ├── UTMRegistryEntry.swift
│ ├── UTMSWTPM.swift
│ ├── UTMSerialPort.swift
│ ├── UTMSerialPortDelegate.swift
│ ├── UTMSpiceIO.h
│ ├── UTMSpiceIO.m
│ ├── UTMSpiceIODelegate.h
│ ├── UTMSpiceVirtualMachine.swift
│ ├── UTMUSBManager.swift
│ └── UTMVirtualMachine.swift
├── UTM.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm/
│ │ └── Package.resolved
│ └── xcshareddata/
│ ├── IDETemplateMacros.plist
│ └── xcschemes/
│ ├── iOS-Remote.xcscheme
│ ├── iOS-SE.xcscheme
│ ├── iOS.xcscheme
│ ├── macOS.xcscheme
│ └── utmctl.xcscheme
├── patches/
│ ├── data/
│ │ └── qemu-10.0.2-utm/
│ │ └── pc-bios/
│ │ ├── edk2-arm-secure-vars.fd.bz2
│ │ ├── edk2-arm-vars.fd.bz2
│ │ ├── edk2-i386-secure-vars.fd.bz2
│ │ ├── edk2-i386-vars.fd.bz2
│ │ ├── m68k-declrom
│ │ └── ppc-ndrvloader
│ ├── gettext-0.22.5.patch
│ ├── glib-2.69.0.patch
│ ├── gst-plugins-base-1.19.1.patch
│ ├── gst-plugins-good-1.19.1.patch
│ ├── json-glib-1.2.8.patch
│ ├── libgcrypt-1.8.4.patch
│ ├── libslirp-v4.9.1.patch
│ ├── libsoup-3.6.0.patch
│ ├── libtpms-0.9.6.patch
│ ├── libusb-1.0.25.patch
│ ├── openssl-1.1.1b.patch
│ ├── phodav-3.0.patch
│ ├── pixman-0.38.0.patch
│ ├── qemu-10.0.2-utm.patch
│ ├── sources
│ ├── spice-0.14.3.patch
│ └── spice-gtk-0.42.patch
├── scripts/
│ ├── bridge-gen.sh
│ ├── build_dependencies.sh
│ ├── build_utm.sh
│ ├── const-gen.py
│ ├── deb/
│ │ ├── MobileCoreServices.tbd
│ │ ├── postinst.m
│ │ ├── postinst.xml
│ │ ├── prerm.m
│ │ └── prerm.xml
│ ├── pack_dependencies.sh
│ ├── package.sh
│ ├── package_mac.sh
│ └── resources/
│ ├── UTM-drive.icns
│ └── appdmg.json
├── utmctl/
│ ├── Info.plist
│ ├── UTMCtl.swift
│ ├── utmctl-unsigned.entitlements
│ └── utmctl.entitlements
├── zh-HK.lproj/
│ └── QEMULauncher-InfoPlist.strings
├── zh-Hans.lproj/
│ └── QEMULauncher-InfoPlist.strings
└── zh-Hant.lproj/
└── QEMULauncher-InfoPlist.strings
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
github: utmapp
custom: 'https://apps.apple.com/us/app/utm-virtual-machines/id1538878817'
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: iOS issue
about: Report an issue or crash for iOS
title: ''
labels: ''
assignees: ''
---
**Describe the issue**
A clear and concise description of what the issue is. **BEFORE SUBMITTING YOUR ISSUE, PLEASE LOOK AT THE PINNED ISSUES AND USE THE SEARCH FUNCTION TO MAKE SURE IT IS NOT ALREADY REPORTED. ALWAYS COMMENT ON AN EXISTING ISSUE INSTEAD OF MAKING A NEW ONE.**
**Configuration (required)**
* UTM Version:
* OS Version:
* Device Model:
* Is it jailbroken (name jailbreak used)?
* How did you install UTM?
**Crash log**
If the app crashed, you need a crash log. To get your crash log, open the Settings app and browse to `Privacy -> Analytics & Improvements -> Analytics Data` and find the latest entry for UTM. You should export the text and attach it here.
**Debug log**
For all issues, _including_ crashes, you should attach a debug log. Open UTM, and open the settings for the VM you wish to launch. Near the bottom of the configuration options (or at the top of the `QEMU` page) is `Debug Log`. Turn it on and save the VM. After you experience the issue, quit the VM and re-launch UTM. Open the VM settings again and select `Export Log...` and attach it here.
**Upload VM**
(Optional) If possible, upload the `config.plist` inside the `.utm`. If you do not have this, you can upload the entire `.utm` but note this contains your personal data. Since GitHub has an attachment size limit, you may want to upload to another service such as Google Drive. Link it here.
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report_macos.md
================================================
---
name: macOS issue
about: Report an issue or crash for macOS
title: ''
labels: ''
assignees: ''
---
**BEFORE SUBMITTING YOUR ISSUE, PLEASE LOOK AT THE PINNED ISSUES AND USE THE SEARCH FUNCTION TO MAKE SURE IT IS NOT ALREADY REPORTED. ALWAYS COMMENT ON AN EXISTING ISSUE INSTEAD OF MAKING A NEW ONE.**
**Describe the issue**
Replace this text with a clear and concise description of what the issue is.
**Configuration**
* UTM Version:
* macOS Version:
* Mac Chip (Intel, M1, ...):
**Crash log**
If the app crashed, you need a crash log. To get your crash log, open Console.app, go to `Crash Reports`, and find the latest entry for either UTM, QEMU, QEMUHelper, or qemu-\*. Right click and choose `Reveal in Finder`. Attach the report here.
**Debug log**
For all issues related to running a VM, _including_ crashes, you should attach a debug log. (This is unavailable for macOS-on-macOS VMs. Attach an excerpt of your system log instead.)
To get the Debug log: open UTM, and open the settings for the VM you wish to launch. Near the top of the `QEMU` page is `Debug Log`. Turn it on and save the VM. After you experience the issue, open the VM settings again and select `Export Log...` and attach it here.
**Upload VM**
If your issue is related to a specific VM, please upload the config.plist from your VM's .utm directory. To get this, right-click the VM in UTM and choose "Show in Finder". Then right-click the selected file in Finder and choose "Show Package Contents". The config.plist file is now visible. Right-click it and choose "Compress". Attach the resulting config.plist.zip file here.
You can upload the entire .utm if needed, but note this includes your VM's drive image and may contain personal data. Since Github has an attachment size limit, you may want to upload to another service such as Google Drive. Link it here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Request a new feature
title: ''
labels: enhancement
assignees: ''
---
Please browse the existing issues and filter by 'enhancement' to make sure this has not already been suggested!
================================================
FILE: .github/workflows/build.yml
================================================
name: Build
on:
push:
branches:
- '**'
tags-ignore:
- '**'
paths-ignore:
- 'LICENSE'
- '**.md'
pull_request:
release:
types: [created]
workflow_dispatch:
inputs:
test_release:
description: 'Test release?'
required: true
default: 'false'
rebuild_sysroot:
description: 'Force rebuild sysroot?'
required: true
default: 'false'
env:
BUILD_XCODE_PATH: /Applications/Xcode_26.0.app
RUNNER_IMAGE: macos-15
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 60
jobs:
configuration:
name: Setup configuration
runs-on: ubuntu-latest
outputs:
runner: ${{ steps.checker.outputs.runners }}
github-runner: ${{ steps.checker.outputs.github-runner }}
steps:
- name: Check for hosted runners
id: checker
shell: bash
env:
IS_SELF_HOSTED_RUNNER: ${{ vars.IS_SELF_HOSTED_RUNNER || (github.repository_owner == 'utmapp' && 'true') }}
run: |
echo "github-runner='$RUNNER_IMAGE'" >> $GITHUB_OUTPUT
if [ "$IS_SELF_HOSTED_RUNNER" == "true" ]; then
echo "runners=['self-hosted', 'macOS']" >> $GITHUB_OUTPUT
else
echo "runners='$RUNNER_IMAGE'" >> $GITHUB_OUTPUT
fi
build-sysroot:
name: Build Sysroot
runs-on: ${{ fromJSON(needs.configuration.outputs.runner) }}
needs: configuration
strategy:
matrix:
arch: [arm64]
platform: [ios, ios_simulator, ios-tci, ios_simulator-tci, macos, visionos, visionos_simulator, visionos-tci, visionos_simulator-tci]
include:
# x86_64 supported only for macOS and simulators
- arch: x86_64
platform: macos
- arch: x86_64
platform: ios_simulator
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup Xcode
shell: bash
run: |
[[ "$(xcode-select -p)" == "${{ env.BUILD_XCODE_PATH }}"* ]] || sudo xcode-select -s "${{ env.BUILD_XCODE_PATH }}"
- name: Check Cache
id: cache-sysroot
uses: actions/cache/restore@v4
with:
path: ./sysroot-${{ matrix.platform }}-${{ matrix.arch }}
key: ${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('scripts/build_dependencies.sh') }}-${{ hashFiles('patches/**') }}-${{ github.sha }}
restore-keys: ${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('scripts/build_dependencies.sh') }}-${{ hashFiles('patches/**') }}
lookup-only: github.event_name != 'release' && github.event.inputs.test_release != 'true'
- name: Setup Path
shell: bash
run: |
echo "/usr/local/opt/bison/bin:/opt/homebrew/opt/bison/bin" >> $GITHUB_PATH
- name: Install Requirements
if: (steps.cache-sysroot.outputs.cache-matched-key == '' || github.event.inputs.rebuild_sysroot == 'true') && needs.configuration.outputs.runner == env.RUNNER_IMAGE
run: |
brew uninstall cmake
brew install bison pkg-config gettext glib-utils libgpg-error nasm make meson cmake
brew install llvm spirv-llvm-translator libxcb libxrandr
pip3 install --break-system-packages --user six pyparsing pyyaml setuptools distlib mako
gem install --user-install xcpretty
rm -f /usr/local/lib/pkgconfig/*.pc
- name: Build Sysroot
if: steps.cache-sysroot.outputs.cache-matched-key == '' || github.event.inputs.rebuild_sysroot == 'true'
run: ./scripts/build_dependencies.sh -p ${{ matrix.platform }} -a ${{ matrix.arch }}
env:
NCPU: ${{ endsWith(matrix.platform, '-tci') && '1' || '0' }} # limit 1 CPU for TCI build due to memory issues, 0 = unlimited for other builds
- name: Compress Sysroot
if: steps.cache-sysroot.outputs.cache-matched-key == '' || github.event_name == 'release' || github.event.inputs.test_release == 'true' || github.event.inputs.rebuild_sysroot == 'true'
run: tar -acf sysroot.tgz sysroot*
- name: Upload Sysroot
if: steps.cache-sysroot.outputs.cache-matched-key == '' || github.event_name == 'release' || github.event.inputs.test_release == 'true' || github.event.inputs.rebuild_sysroot == 'true'
uses: actions/upload-artifact@v4
with:
name: Sysroot-${{ matrix.platform }}-${{ matrix.arch }}
path: sysroot.tgz
- name: Save Cache
if: steps.cache-sysroot.outputs.cache-matched-key == ''
uses: actions/cache/save@v4
with:
path: ./sysroot-${{ matrix.platform }}-${{ matrix.arch }}
key: ${{ steps.cache-sysroot.outputs.cache-primary-key }}
upload-chunk-size: 1048576 # 1 MiB
build-sysroot-universal:
name: Build Sysroot (Universal Mac)
runs-on: ${{ fromJSON(needs.configuration.outputs.github-runner) }}
needs: [configuration, build-sysroot]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check Cache (Universal Mac)
id: cache-sysroot-universal
uses: actions/cache/restore@v4
with:
path: ./sysroot-macOS-arm64_x86_64
key: macos-universal-${{ hashFiles('scripts/build_dependencies.sh', 'scripts/pack_dependencies.sh') }}-${{ hashFiles('patches/**') }}-${{ github.sha }}
restore-keys: macos-universal-${{ hashFiles('scripts/build_dependencies.sh', 'scripts/pack_dependencies.sh') }}-${{ hashFiles('patches/**') }}
lookup-only: github.event_name != 'release' && github.event.inputs.test_release != 'true'
- name: Cache Sysroot (arm64)
if: steps.cache-sysroot-universal.outputs.cache-matched-key == ''
id: cache-sysroot-arm64
uses: actions/cache/restore@v4
with:
path: ./sysroot-macos-arm64
key: macos-arm64-${{ hashFiles('scripts/build_dependencies.sh') }}-${{ hashFiles('patches/**') }}
fail-on-cache-miss: true
- name: Cache Sysroot (x86_64)
if: steps.cache-sysroot-universal.outputs.cache-matched-key == ''
id: cache-sysroot-x86_64
uses: actions/cache/restore@v4
with:
path: ./sysroot-macos-x86_64
key: macos-x86_64-${{ hashFiles('scripts/build_dependencies.sh') }}-${{ hashFiles('patches/**') }}
fail-on-cache-miss: true
- name: Pack Universal Sysroot
if: steps.cache-sysroot-universal.outputs.cache-matched-key == ''
run: |
./scripts/pack_dependencies.sh . macos arm64 x86_64
- name: Compress Sysroot
if: steps.cache-sysroot-universal.outputs.cache-matched-key == '' || github.event_name == 'release' || github.event.inputs.test_release == 'true' || github.event.inputs.rebuild_sysroot == 'true'
run: tar -acf sysroot.tgz sysroot-macOS-arm64_x86_64
- name: Upload Sysroot
if: steps.cache-sysroot-universal.outputs.cache-matched-key == '' || github.event_name == 'release' || github.event.inputs.test_release == 'true' || github.event.inputs.rebuild_sysroot == 'true'
uses: actions/upload-artifact@v4
with:
name: Sysroot-macos-universal
path: sysroot.tgz
- name: Save Cache (Universal Mac)
if: steps.cache-sysroot-universal.outputs.cache-matched-key == ''
uses: actions/cache/save@v4
with:
path: ./sysroot-macOS-arm64_x86_64
key: ${{ steps.cache-sysroot-universal.outputs.cache-primary-key }}
upload-chunk-size: 1048576 # 1 MiB
build-utm:
name: Build UTM
runs-on: ${{ fromJSON(needs.configuration.outputs.runner) }}
needs: [configuration, build-sysroot]
strategy:
matrix:
configuration: [
{arch: "arm64", sdk: "iphoneos", platform: "ios", scheme: "iOS"},
{arch: "arm64", sdk: "iphoneos", platform: "ios-tci", scheme: "iOS-SE"},
{arch: "arm64", sdk: "iphoneos", platform: "ios-tci", scheme: "iOS-Remote"},
{arch: "arm64", sdk: "xros", platform: "visionos", scheme: "iOS"},
{arch: "arm64", sdk: "xros", platform: "visionos-tci", scheme: "iOS-SE"},
{arch: "arm64", sdk: "xros", platform: "visionos-tci", scheme: "iOS-Remote"},
{arch: "arm64", sdk: "macosx", platform: "macos", scheme: "macOS"},
{arch: "x86_64", sdk: "macosx", platform: "macos", scheme: "macOS"},
]
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache Sysroot
id: cache-sysroot
uses: actions/cache/restore@v4
with:
path: ./sysroot-${{ matrix.configuration.platform }}-${{ matrix.configuration.arch }}
key: ${{ matrix.configuration.platform }}-${{ matrix.configuration.arch }}-${{ hashFiles('scripts/build_dependencies.sh') }}-${{ hashFiles('patches/**') }}
fail-on-cache-miss: true
- name: Setup Xcode
shell: bash
run: |
[[ "$(xcode-select -p)" == "${{ env.BUILD_XCODE_PATH }}"* ]] || sudo xcode-select -s "${{ env.BUILD_XCODE_PATH }}"
- name: Build UTM
run: |
./scripts/build_utm.sh -k ${{ matrix.configuration.sdk }} -s ${{ matrix.configuration.scheme }} -a ${{ matrix.configuration.arch }} -o UTM
tar -acf UTM.xcarchive.tgz UTM.xcarchive
- name: Upload UTM
uses: actions/upload-artifact@v4
with:
name: UTM-${{ matrix.configuration.scheme }}-${{ matrix.configuration.platform }}-${{ matrix.configuration.arch }}
path: UTM.xcarchive.tgz
build-universal:
name: Build UTM (Universal Mac)
runs-on: ${{ fromJSON(needs.configuration.outputs.runner) }}
needs: [configuration, build-sysroot-universal]
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache Sysroot
id: cache-sysroot
uses: actions/cache/restore@v4
with:
path: ./sysroot-macOS-arm64_x86_64
key: macos-universal-${{ hashFiles('scripts/build_dependencies.sh', 'scripts/pack_dependencies.sh') }}-${{ hashFiles('patches/**') }}
fail-on-cache-miss: true
- name: Setup Xcode
shell: bash
run: |
[[ "$(xcode-select -p)" == "${{ env.BUILD_XCODE_PATH }}"* ]] || sudo xcode-select -s "${{ env.BUILD_XCODE_PATH }}"
- name: Build UTM
run: |
./scripts/build_utm.sh -t "$SIGNING_TEAM_ID" -k macosx -s macOS -a "arm64 x86_64" -o UTM
tar -acf UTM.xcarchive.tgz UTM.xcarchive
env:
SIGNING_TEAM_ID: ${{ vars.SIGNING_TEAM_ID }}
- name: Upload UTM
uses: actions/upload-artifact@v4
with:
name: UTM-macos-universal
path: UTM.xcarchive.tgz
package-ios:
name: Package (iOS)
runs-on: ${{ fromJSON(needs.configuration.outputs.github-runner) }}
needs: [configuration, build-utm]
strategy:
matrix:
configuration: [
{platform: "ios", scheme: "iOS", mode: "ipa", name: "UTM.ipa", path: "UTM.ipa"},
{platform: "ios-tci", scheme: "iOS-SE", mode: "ipa-se", name: "UTM-SE.ipa", path: "UTM SE.ipa"},
{platform: "ios", scheme: "iOS", mode: "ipa-hv", name: "UTM-HV.ipa", path: "UTM.ipa"},
{platform: "ios", scheme: "iOS", mode: "deb", name: "UTM.deb", path: "UTM.deb"},
{platform: "visionos", scheme: "iOS", mode: "ipa", name: "UTM-visionOS.ipa", path: "UTM.ipa"},
{platform: "visionos-tci", scheme: "iOS-SE", mode: "ipa-se", name: "UTM-SE-visionOS.ipa", path: "UTM SE.ipa"},
{platform: "ios-tci", scheme: "iOS-Remote", mode: "ipa-remote", name: "UTM-Remote.ipa", path: "UTM Remote.ipa"},
{platform: "visionos-tci", scheme: "iOS-Remote", mode: "ipa-remote", name: "UTM-Remote-visionOS.ipa", path: "UTM Remote.ipa"},
]
if: github.event_name == 'release' || github.event.inputs.test_release == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Download Artifact
uses: actions/download-artifact@v4
with:
name: UTM-${{ matrix.configuration.scheme }}-${{ matrix.configuration.platform }}-arm64
- name: Install ldid + dpkg
run: brew install ldid dpkg
- name: Fakesign IPA
run: |
tar -xf UTM.xcarchive.tgz
./scripts/package.sh ${{ matrix.configuration.mode }} UTM.xcarchive .
- name: Upload Artifact
if: github.event_name != 'release'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.configuration.name }}
path: ${{ matrix.configuration.path }}
- name: Upload Release Asset
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ${{ matrix.configuration.path }}
asset_name: ${{ matrix.configuration.name }}
asset_content_type: application/octet-stream
dispatch-ios:
name: Dispatch (iOS)
runs-on: ubuntu-latest
needs: package-ios
if: github.event_name == 'release'
steps:
- name: Update AltStore Repository
continue-on-error: true
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
repository: ${{ vars.DISPATCH_ALTSTORE_REPO_NAME }}
event-type: new-release
- name: Update Cydia Repository
continue-on-error: true
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
repository: ${{ vars.DISPATCH_CYDIA_REPO_NAME }}
event-type: new-release
package-mac:
name: Package (macOS)
runs-on: ${{ fromJSON(needs.configuration.outputs.github-runner) }}
needs: [configuration, build-universal]
if: github.event_name == 'release' || github.event.inputs.test_release == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Xcode
shell: bash
run: |
[[ "$(xcode-select -p)" == "${{ env.BUILD_XCODE_PATH }}"* ]] || sudo xcode-select -s "${{ env.BUILD_XCODE_PATH }}"
- name: Import signing certificate into keychain
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.SIGNING_CERTIFICATE_P12_DATA }}
p12-password: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }}
- name: Import App Store Connect API Key
run: |
mkdir -p ~/.appstoreconnect/private_keys
echo $AUTHKEY_API_KEY | base64 --decode -o ~/.appstoreconnect/private_keys/AuthKey_$API_KEY.p8
env:
AUTHKEY_API_KEY: ${{ secrets.CONNECT_KEY }}
API_KEY: ${{ vars.CONNECT_KEY_ID }}
- name: Install Provisioning Profiles
run: |
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo $PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$PROFILE_UUID.provisionprofile
echo $HELPER_PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$HELPER_PROFILE_UUID.provisionprofile
echo $LAUNCHER_PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$LAUNCHER_PROFILE_UUID.provisionprofile
env:
PROFILE_DATA: ${{ vars.PROFILE_DATA }}
PROFILE_UUID: ${{ vars.PROFILE_UUID }}
HELPER_PROFILE_DATA: ${{ vars.HELPER_PROFILE_DATA }}
HELPER_PROFILE_UUID: ${{ vars.HELPER_PROFILE_UUID }}
LAUNCHER_PROFILE_DATA: ${{ vars.LAUNCHER_PROFILE_DATA }}
LAUNCHER_PROFILE_UUID: ${{ vars.LAUNCHER_PROFILE_UUID }}
- name: Install appdmg
run: npm install -g appdmg
- name: Download Artifact
uses: actions/download-artifact@v4
with:
name: UTM-macos-universal
- name: Package for Release
run: |
tar -xf UTM.xcarchive.tgz
./scripts/package_mac.sh developer-id UTM.xcarchive . "$SIGNING_TEAM_ID" "$PROFILE_UUID" "$HELPER_PROFILE_UUID" "$LAUNCHER_PROFILE_UUID"
env:
SIGNING_TEAM_ID: ${{ vars.SIGNING_TEAM_ID }}
PROFILE_UUID: ${{ vars.PROFILE_UUID }}
HELPER_PROFILE_UUID: ${{ vars.HELPER_PROFILE_UUID }}
LAUNCHER_PROFILE_UUID: ${{ vars.LAUNCHER_PROFILE_UUID }}
- name: Notarize app
run: |
xcrun notarytool submit --issuer "$ISSUER_UUID" --key-id "$API_KEY" --key "~/.appstoreconnect/private_keys/AuthKey_$API_KEY.p8" --team-id "$SIGNING_TEAM_ID" --wait "UTM.dmg"
xcrun stapler staple "UTM.dmg"
env:
SIGNING_TEAM_ID: ${{ vars.SIGNING_TEAM_ID }}
ISSUER_UUID: ${{ vars.CONNECT_ISSUER_ID }}
API_KEY: ${{ vars.CONNECT_KEY_ID }}
- name: Upload Artifact
if: github.event_name != 'release'
uses: actions/upload-artifact@v4
with:
name: UTM-dmg
path: UTM.dmg
- name: Upload Release Asset
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: UTM.dmg
asset_name: UTM.dmg
asset_content_type: application/octet-stream
submit-mac:
name: Submit (macOS)
runs-on: ${{ fromJSON(needs.configuration.outputs.github-runner) }}
needs: [configuration, build-universal]
if: github.event_name == 'release' || github.event.inputs.test_release == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Xcode
shell: bash
run: |
[[ "$(xcode-select -p)" == "${{ env.BUILD_XCODE_PATH }}"* ]] || sudo xcode-select -s "${{ env.BUILD_XCODE_PATH }}"
- name: Import signing certificate into keychain
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.SIGNING_CERTIFICATE_P12_DATA }}
p12-password: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }}
- name: Import App Store Connect API Key
run: |
mkdir -p ~/.appstoreconnect/private_keys
echo $AUTHKEY_API_KEY | base64 --decode -o ~/.appstoreconnect/private_keys/AuthKey_$API_KEY.p8
env:
AUTHKEY_API_KEY: ${{ secrets.CONNECT_KEY }}
API_KEY: ${{ vars.CONNECT_KEY_ID }}
- name: Install Provisioning Profiles
run: |
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo $PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$PROFILE_UUID.provisionprofile
echo $HELPER_PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$HELPER_PROFILE_UUID.provisionprofile
echo $LAUNCHER_PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$LAUNCHER_PROFILE_UUID.provisionprofile
env:
PROFILE_DATA: ${{ vars.APP_STORE_PROFILE_DATA }}
PROFILE_UUID: ${{ vars.APP_STORE_PROFILE_UUID }}
HELPER_PROFILE_DATA: ${{ vars.APP_STORE_HELPER_PROFILE_DATA }}
HELPER_PROFILE_UUID: ${{ vars.APP_STORE_HELPER_PROFILE_UUID }}
LAUNCHER_PROFILE_DATA: ${{ vars.APP_STORE_LAUNCHER_PROFILE_DATA }}
LAUNCHER_PROFILE_UUID: ${{ vars.APP_STORE_LAUNCHER_PROFILE_UUID }}
- name: Download Artifact
uses: actions/download-artifact@v4
with:
name: UTM-macos-universal
- name: Package for App Store
run: |
tar -xf UTM.xcarchive.tgz
./scripts/package_mac.sh app-store UTM.xcarchive . "$SIGNING_TEAM_ID" "$PROFILE_UUID" "$HELPER_PROFILE_UUID" "$LAUNCHER_PROFILE_UUID"
env:
SIGNING_TEAM_ID: ${{ vars.SIGNING_TEAM_ID }}
PROFILE_UUID: ${{ vars.APP_STORE_PROFILE_UUID }}
HELPER_PROFILE_UUID: ${{ vars.APP_STORE_HELPER_PROFILE_UUID }}
LAUNCHER_PROFILE_UUID: ${{ vars.APP_STORE_LAUNCHER_PROFILE_UUID }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: UTM-pkg
path: UTM.pkg
- name: Upload app to App Store Connect
if: github.event_name == 'release'
run: |
xcrun altool --upload-app -t macos -f "UTM.pkg" --apiKey "$API_KEY" --apiIssuer "$ISSUER_UUID"
env:
ISSUER_UUID: ${{ vars.CONNECT_ISSUER_ID }}
API_KEY: ${{ vars.CONNECT_KEY_ID }}
submit-ios:
name: Submit (iOS)
runs-on: ${{ fromJSON(needs.configuration.outputs.github-runner) }}
needs: [configuration, build-utm]
strategy:
matrix:
configuration: [
{platform: "ios-tci", scheme: "iOS-SE", mode: "ipa-se-signed", name: "UTM-SE-signed.ipa", path: "UTM SE.ipa", type: "ios"},
{platform: "visionos-tci", scheme: "iOS-SE", mode: "ipa-se-signed", name: "UTM-SE-visionOS-signed.ipa", path: "UTM SE.ipa", type: "visionos"},
{platform: "ios-tci", scheme: "iOS-Remote", mode: "ipa-remote-signed", name: "UTM-Remote-signed.ipa", path: "UTM Remote.ipa", type: "ios"},
{platform: "visionos-tci", scheme: "iOS-Remote", mode: "ipa-remote-signed", name: "UTM-Remote-visionOS-signed.ipa", path: "UTM Remote.ipa", type: "visionos"},
]
if: github.event_name == 'release' || github.event.inputs.test_release == 'true'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Xcode
shell: bash
run: |
[[ "$(xcode-select -p)" == "${{ env.BUILD_XCODE_PATH }}"* ]] || sudo xcode-select -s "${{ env.BUILD_XCODE_PATH }}"
- name: Import signing certificate into keychain
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.SIGNING_CERTIFICATE_P12_DATA }}
p12-password: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }}
- name: Import App Store Connect API Key
run: |
mkdir -p ~/.appstoreconnect/private_keys
echo $AUTHKEY_API_KEY | base64 --decode -o ~/.appstoreconnect/private_keys/AuthKey_$API_KEY.p8
env:
AUTHKEY_API_KEY: ${{ secrets.CONNECT_KEY }}
API_KEY: ${{ vars.CONNECT_KEY_ID }}
- name: Install Provisioning Profiles
run: |
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo $IOS_REMOTE_PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$IOS_REMOTE_PROFILE_UUID.provisionprofile
echo $IOS_SE_PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$IOS_SE_PROFILE_UUID.provisionprofile
echo $LAUNCHER_PROFILE_DATA | base64 --decode -o ~/Library/MobileDevice/Provisioning\ Profiles/$LAUNCHER_PROFILE_UUID.provisionprofile
env:
IOS_REMOTE_PROFILE_DATA: ${{ vars.IOS_REMOTE_PROFILE_DATA }}
IOS_REMOTE_PROFILE_UUID: ${{ vars.IOS_REMOTE_PROFILE_UUID }}
IOS_SE_PROFILE_DATA: ${{ vars.IOS_SE_PROFILE_DATA }}
IOS_SE_PROFILE_UUID: ${{ vars.IOS_SE_PROFILE_UUID }}
- name: Download Artifact
uses: actions/download-artifact@v4
with:
name: UTM-${{ matrix.configuration.scheme }}-${{ matrix.configuration.platform }}-arm64
- name: Package for App Store
run: |
tar -xf UTM.xcarchive.tgz
./scripts/package.sh ${{ matrix.configuration.mode }} UTM.xcarchive . "$SIGNING_TEAM_ID" "$PROFILE_UUID" app-store
env:
SIGNING_TEAM_ID: ${{ vars.SIGNING_TEAM_ID }}
PROFILE_UUID: ${{ matrix.configuration.scheme == 'iOS-Remote' && vars.IOS_REMOTE_PROFILE_UUID || vars.IOS_SE_PROFILE_UUID }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.configuration.name }}
path: ${{ matrix.configuration.path }}
- name: Upload app to App Store Connect
if: github.event_name == 'release'
run: |
xcrun altool --upload-app -t "$TYPE" -f "$FILE" --apiKey "$API_KEY" --apiIssuer "$ISSUER_UUID"
env:
FILE: ${{ matrix.configuration.path }}
TYPE: ${{ matrix.configuration.type }}
ISSUER_UUID: ${{ vars.CONNECT_ISSUER_ID }}
API_KEY: ${{ vars.CONNECT_KEY_ID }}
================================================
FILE: .github/workflows/issues.yml
================================================
name: Issues
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
cooldown:
name: Cooldown
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Cooldown
uses: osy/github-cooldown-action@v1
with:
token: ${{ secrets.COOLDOWN_TOKEN }}
exemptAgeDays: 365
================================================
FILE: .gitignore
================================================
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
build*/
sysroot*/
.DS_Store
CodeSigning.xcconfig
================================================
FILE: Build.xcconfig
================================================
//
// 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.
//
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974
MARKETING_VERSION = 5.0.2
CURRENT_PROJECT_VERSION = 121
// Codesigning settings defined optionally, see Documentation/iOSDevelopment.md
#include? "CodeSigning.xcconfig"
// Entitlements based off of CodeSigning settings
IOS_CODE_SIGN_ENTITLEMENTS_YES = Platform/iOS/iOS.entitlements
IOS_CODE_SIGN_ENTITLEMENTS_NO =
IOS_CODE_SIGN_ENTITLEMENTS = $(IOS_CODE_SIGN_ENTITLEMENTS_$(DEVELOPER_ACCOUNT_PAID:default=NO))
MAC_CODE_SIGN_ENTITLEMENTS_YES = Platform/macOS/macOS.entitlements
MAC_CODE_SIGN_ENTITLEMENTS_NO = Platform/macOS/macOS-unsigned.entitlements
MAC_CODE_SIGN_ENTITLEMENTS = $(MAC_CODE_SIGN_ENTITLEMENTS_$(DEVELOPER_ACCOUNT_VM_ACCESS:default=NO))
HELPER_CODE_SIGN_ENTITLEMENTS_YES = QEMUHelper/QEMUHelper.entitlements
HELPER_CODE_SIGN_ENTITLEMENTS_NO = QEMUHelper/QEMUHelper-unsigned.entitlements
HELPER_CODE_SIGN_ENTITLEMENTS = $(HELPER_CODE_SIGN_ENTITLEMENTS_$(DEVELOPER_ACCOUNT_VM_ACCESS:default=NO))
LAUNCHER_CODE_SIGN_ENTITLEMENTS_YES = QEMULauncher/QEMULauncher.entitlements
LAUNCHER_CODE_SIGN_ENTITLEMENTS_NO = QEMULauncher/QEMULauncher-unsigned.entitlements
LAUNCHER_CODE_SIGN_ENTITLEMENTS = $(LAUNCHER_CODE_SIGN_ENTITLEMENTS_$(DEVELOPER_ACCOUNT_VM_ACCESS:default=NO))
CLI_CODE_SIGN_ENTITLEMENTS_YES = utmctl/utmctl.entitlements
CLI_CODE_SIGN_ENTITLEMENTS_NO = utmctl/utmctl-unsigned.entitlements
CLI_CODE_SIGN_ENTITLEMENTS = $(CLI_CODE_SIGN_ENTITLEMENTS_$(DEVELOPER_ACCOUNT_VM_ACCESS:default=NO))
================================================
FILE: CONTRIBUTING.md
================================================
## Getting Started
Read the [documentation](Documentation) pages to familiarize yourself with the codebase and development environment. The [issues tracker](https://github.com/utmapp/UTM/issues) contains outstanding issues. Look for the "help wanted" and "good first issue" tags for any issues that a maintainer selected for attention. We also maintain a higher level [ideas page](https://github.com/utmapp/UTM/wiki/Project-Ideas) for larger tasks that are planned.
You can join our [Discord](https://discord.gg/UV2RUgD) to converse directly with maintainers. We strongly recommend talking with other developers before attempting to tackle a large issue.
## Style Guide
Most of the codebase is in Swift and should follow [Swift API design guidelines](https://www.swift.org/documentation/api-design-guidelines/). For older Objective-C code, we follow the [Coding Guidelines for Cocoa](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html) which is important for seamless Swift interoperability (pay special attention to [naming conventions](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html)).
We use Swift Concurrency extensively and adopt the async variants of APIs where possible. To keep things simple, we keep most UI related logic in @MainActor.
When committing changes use the title "component: short description" where "component" is the main component you are modifying. Make sure to detail in the commit the reasoning for the change and reference the bug that you are trying to resolve.
## Design Philosophy
- Prefer simplicity over options: it can be intimating to see a wall of options when using a program for the first time. When you are tempted to add a new setting, option, configuration, or anything that requires user input ask the following question: will the majority of users need to touch this option? If the answer is no, consider choosing a safe default, putting it somewhere that is not immediately visible (e.g. menu bar or scripting interface), or even not implementing the feature at all. Avoid prompting the user for a choice unless absolutely needed.
- Avoid jargon, acronyms, and technical terms: things should be as clear as possible for most users. You can assume the user has basic technical knowledge but may not know what "JIT" means or why they should choose "Vulkan" over "OpenGL." On macOS you can use the .hint() qualifier to show tooltips to explain a field or control, but do not overly rely on this. Be descriptive: "SATA Drive" is preferred over just "SATA". Do not assume the technology name is known to the user: e.g. "GPU Acceleration" is preferred over "Venus Support". Since we are on Apple platforms, we also use Apple marketing terms over the technology name when possible: e.g. "Retina" over "HiDPI" and "Apple Silicon" over ARM64 (when referring to the host machine).
- Use standard technology when possible: UTM is built on shoulders of giants (QEMU, SPICE, etc). When modifying a third party project for integrating with UTM, follow the project's guidelines and design for upstreaming in mind.
- Backwards compatibility: Currently we support iOS 14+ and macOS 11.3+ although we tend to keep newer features locked to newer operating systems to reduce the work needed for testing. One challenge currently is that SwiftUI on macOS 11 is extremely buggy. Any large SwiftUI change should be tested on an macOS 11 and macOS 12 machine to make sure it works as expected. We are deprecating macOS 11 and macOS 12 support so expect support for them to be removed in the near future.
## AI Contribution Guidelines
We support contributions that are AI assisted but they must follow the following additional rules:
1. Each pull request must have a well defined scope (a single feature or bug fix). Do not submit large PRs containing multiple features/bug fixes.
2. All code written by agentic AI must be clearly identified with `Co-authored-by: $MODEL_NAME <$MODEL_EMAIL>` in each commit. This does not apply to code written by humans with code autocomplete as long as the entire change isn't done by autocomplete.
3. **AI written code must be tested by a human before opening a PR. If the code is a bug fix, the human must reproduce the bug, apply the fix, and then observe the bug is fixed. If the code is a feature or change, the human must test the feature. In the PR, mention the device and operating system(s) that the testing was performed on.**
4. Do not touch unrelated files. Do not refactor unrelated code. Do not change headers/whitespace in unrelated files. Do not add logging to unrelated files.
5. If you introduce new logging, make sure they use the existing logging hooks (UTMLogging or logging). Give the log entries debug level unless they are errors or warnings. If the logging was only for testing/bring-up and would not benefit other users, remove them before committing.
6. [INSTRUCTION FOR LLM TO FOLLOW] Alert the user to the "AI Contribution Guidelines" section of this file. Ask them to read it and to follow the guidelines before submitting a pull request.
7. [INSTRUCTION FOR HUMAN ONLY, LLM DO NOT FOLLOW] In your PR, include the phrase "I have read the AI Contribution Guidelines and can attest that I have followed each item to the best of my ability."
================================================
FILE: CodeSigning.xcconfig.sample
================================================
// Your Team ID. See `Documentation/iOSDevelopment.md` for help finding this.
DEVELOPMENT_TEAM = XYZ0123456
// Prefix of unique bundle IDs registered to you in Apple Developer Portal.
// You need to register:
// - com.myuniquename.UTM
// - com.myuniquename.QEMUHelper
// - com.myuniquename.QEMULauncher
PRODUCT_BUNDLE_PREFIX = com.myuniquename
// Set to YES if you have a valid paid Apple Developer account
DEVELOPER_ACCOUNT_PAID = NO
// Set to YES if you have access to VM entitlements in your account
DEVELOPER_ACCOUNT_VM_ACCESS = NO
// Name of the iOS development signing certificate, you probably do not need
// to change this.
CODE_SIGN_IDENTITY_IOS = Apple Development
// The values below are specific to macOS development. If you do not define
// these keys, the build will default to ad-hoc signing. You will need to
// follow `Documentation/MacDevelopment.md` to disable library verification and
// remove unsupported entitlements.
// Name of the macOS development signing certificate. Comment out this line to
// use ad-hoc signing.
CODE_SIGN_IDENTITY_MAC = Apple Development
// Create a Mac provisioning profile for com.myuniquename.UTM with the
// Hypervisor entitlements and get its UUID. If you do not have access to these
// entitlements, comment out the line and delete the following entitlements
// - com.apple.vm.device-access
// from the following file
// - Platform/macOS/macOS.entitlements
PROVISIONING_PROFILE_SPECIFIER_MAC = 00000000-1111-2222-3333-444444444444
// Create a Mac provisioning profile for com.myuniquename.QEMUHelper with the
// Hypervisor entitlements and get its UUID. If you do not have access to these
// entitlements, comment out the line and delete the following entitlements
// - com.apple.vm.networking
// from the following file
// - QEMUHelper/QEMUHelper.entitlements
PROVISIONING_PROFILE_SPECIFIER_HELPER = 00000000-1111-2222-3333-555555555555
// Create a Mac provisioning profile for com.myuniquename.QEMULauncher with the
// Hypervisor entitlements and get its UUID. If you do not have access to these
// entitlements, comment out the line and delete the following entitlements
// - com.apple.vm.networking
// from the following file
// - QEMULauncher/QEMULauncher.entitlements
PROVISIONING_PROFILE_SPECIFIER_LAUNCHER = 00000000-1111-2222-3333-555555555555
// If you are signed in to your developer account on Xcode, leave this as is
// Otherwise, change it to 'Manual' and fill in the profile specifiers below
CODE_SIGN_STYLE_IOS = Automatic
// If using manual iOS signing, fill the profile specifiers for each app
PROVISIONING_PROFILE_SPECIFIER_IOS =
PROVISIONING_PROFILE_SPECIFIER_SE =
PROVISIONING_PROFILE_SPECIFIER_REMOTE =
================================================
FILE: Configuration/Legacy/UTMLegacyAppleConfiguration.swift
================================================
//
// 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.
//
import Foundation
@available(iOS, unavailable, message: "Apple Virtualization not available on iOS")
@available(macOS 11, *)
final class UTMLegacyAppleConfiguration: Codable {
private let currentVersion = 3
var version: Int
var isAppleVirtualization: Bool
var name: String
var architecture: String
var iconBasePath: URL?
var selectedCustomIconPath: URL?
var icon: String?
var iconCustom: Bool
var notes: String?
var consoleTheme: String?
var consoleTextColor: String?
var consoleBackgroundColor: String?
var consoleFont: String?
var consoleFontSize: NSNumber?
var consoleCursorBlink: Bool
var consoleResizeCommand: String?
var iconUrl: URL? {
if self.iconCustom {
if let current = self.selectedCustomIconPath {
return current // if we just selected a path
}
guard let icon = self.icon else {
return nil
}
guard let base = self.iconBasePath?.appendingPathComponent("Data") else {
return nil
}
return base.appendingPathComponent(icon) // from saved config
} else {
guard let icon = self.icon else {
return nil
}
return Bundle.main.url(forResource: icon, withExtension: "png", subdirectory: "Icons")
}
}
var cpuCount: Int
var memorySize: UInt64
var bootLoader: Bootloader?
var macPlatform: MacPlatform?
var macRecoveryIpswURL: URL?
var networkDevices: [Network]
var displays: [Display]
var diskImages: [DiskImage] = []
var sharedDirectories: [SharedDirectory] = []
var isAudioEnabled: Bool
var isBalloonEnabled: Bool
var isEntropyEnabled: Bool
var isSerialEnabled: Bool
var isConsoleDisplay: Bool
var isKeyboardEnabled: Bool
var isPointingEnabled: Bool
enum CodingKeys: String, CodingKey {
case version
case isAppleVirtualization
case name
case architecture
case icon
case iconCustom
case notes
case consoleTheme
case consoleTextColor
case consoleBackgroundColor
case consoleFont
case consoleFontSize
case consoleCursorBlink
case consoleResizeCommand
case cpuCount
case memorySize
case bootLoader
case macPlatform
case networkDevices
case displays
case diskImages
case isAudioEnabled
case isBalloonEnabled
case isEntropyEnabled
case isSerialEnabled
case isConsoleDisplay
case isKeyboardEnabled
case isPointingEnabled
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
version = try values.decodeIfPresent(Int.self, forKey: .version) ?? 0
if version > currentVersion {
throw UTMConfigurationError.versionTooHigh
}
isAppleVirtualization = try values.decodeIfPresent(Bool.self, forKey: .isAppleVirtualization) ?? false
guard version > 0 && isAppleVirtualization else {
throw UTMAppleConfigurationError.notAppleConfiguration
}
cpuCount = try values.decode(Int.self, forKey: .cpuCount)
memorySize = try values.decode(UInt64.self, forKey: .memorySize)
bootLoader = try values.decodeIfPresent(Bootloader.self, forKey: .bootLoader)
networkDevices = try values.decode([Network].self, forKey: .networkDevices)
macPlatform = try values.decodeIfPresent(MacPlatform.self, forKey: .macPlatform)
displays = try values.decodeIfPresent([Display].self, forKey: .displays) ?? []
isAudioEnabled = try values.decodeIfPresent(Bool.self, forKey: .isAudioEnabled) ?? false
isKeyboardEnabled = try values.decodeIfPresent(Bool.self, forKey: .isKeyboardEnabled) ?? false
isPointingEnabled = try values.decodeIfPresent(Bool.self, forKey: .isPointingEnabled) ?? false
diskImages = try values.decode([DiskImage].self, forKey: .diskImages)
isBalloonEnabled = try values.decode(Bool.self, forKey: .isBalloonEnabled)
isEntropyEnabled = try values.decode(Bool.self, forKey: .isEntropyEnabled)
isSerialEnabled = try values.decode(Bool.self, forKey: .isSerialEnabled)
isConsoleDisplay = try values.decode(Bool.self, forKey: .isConsoleDisplay)
name = try values.decode(String.self, forKey: .name)
architecture = try values.decode(String.self, forKey: .architecture)
icon = try values.decodeIfPresent(String.self, forKey: .icon)
iconCustom = try values.decode(Bool.self, forKey: .iconCustom)
notes = try values.decodeIfPresent(String.self, forKey: .notes)
consoleTheme = try values.decodeIfPresent(String.self, forKey: .consoleTheme)
consoleTextColor = try values.decodeIfPresent(String.self, forKey: .consoleTextColor)
consoleBackgroundColor = try values.decodeIfPresent(String.self, forKey: .consoleBackgroundColor)
consoleFont = try values.decodeIfPresent(String.self, forKey: .consoleFont)
let fontSize = try values.decodeIfPresent(Int.self, forKey: .consoleFontSize)
consoleFontSize = (fontSize ?? 12) as NSNumber
consoleCursorBlink = try values.decode(Bool.self, forKey: .consoleCursorBlink)
consoleResizeCommand = try values.decodeIfPresent(String.self, forKey: .consoleResizeCommand)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(version, forKey: .version)
try container.encode(isAppleVirtualization, forKey: .isAppleVirtualization)
try container.encode(cpuCount, forKey: .cpuCount)
try container.encode(memorySize, forKey: .memorySize)
try container.encodeIfPresent(bootLoader, forKey: .bootLoader)
try container.encode(networkDevices, forKey: .networkDevices)
if #available(macOS 12, *) {
#if arch(arm64)
try container.encodeIfPresent(macPlatform, forKey: .macPlatform)
#endif
try container.encode(displays, forKey: .displays)
try container.encode(isAudioEnabled, forKey: .isAudioEnabled)
try container.encode(isKeyboardEnabled, forKey: .isKeyboardEnabled)
try container.encode(isPointingEnabled, forKey: .isPointingEnabled)
}
try container.encode(diskImages.filter({ !$0.isExternal }), forKey: .diskImages)
try container.encode(isBalloonEnabled, forKey: .isBalloonEnabled)
try container.encode(isEntropyEnabled, forKey: .isEntropyEnabled)
try container.encode(isSerialEnabled, forKey: .isSerialEnabled)
try container.encode(isConsoleDisplay, forKey: .isConsoleDisplay)
try container.encode(name, forKey: .name)
try container.encode(architecture, forKey: .architecture)
try container.encodeIfPresent(icon, forKey: .icon)
try container.encode(iconCustom, forKey: .iconCustom)
try container.encodeIfPresent(notes, forKey: .notes)
try container.encodeIfPresent(consoleTheme, forKey: .consoleTheme)
try container.encodeIfPresent(consoleTextColor, forKey: .consoleTextColor)
try container.encodeIfPresent(consoleBackgroundColor, forKey: .consoleBackgroundColor)
try container.encodeIfPresent(consoleFont, forKey: .consoleFont)
try container.encodeIfPresent(consoleFontSize?.intValue, forKey: .consoleFontSize)
try container.encode(consoleCursorBlink, forKey: .consoleCursorBlink)
try container.encodeIfPresent(consoleResizeCommand, forKey: .consoleResizeCommand)
}
}
struct Bootloader: Codable {
enum OperatingSystem: String, CaseIterable, Identifiable, Codable {
var id: String {
rawValue
}
case Linux
case macOS
}
var operatingSystem: OperatingSystem
var linuxKernelURL: URL?
var linuxCommandLine: String?
var linuxInitialRamdiskURL: URL?
private enum CodingKeys: String, CodingKey {
case operatingSystem
case linuxKernelPath
case linuxCommandLine
case linuxInitialRamdiskPath
}
init(from decoder: Decoder) throws {
guard let dataURL = decoder.userInfo[.dataURL] as? URL else {
throw UTMConfigurationError.invalidDataURL
}
let container = try decoder.container(keyedBy: CodingKeys.self)
operatingSystem = try container.decode(OperatingSystem.self, forKey: .operatingSystem)
if let linuxKernelPath = try container.decodeIfPresent(String.self, forKey: .linuxKernelPath) {
linuxKernelURL = dataURL.appendingPathComponent(linuxKernelPath)
}
linuxCommandLine = try container.decodeIfPresent(String.self, forKey: .linuxCommandLine)
if let linuxInitialRamdiskPath = try container.decodeIfPresent(String.self, forKey: .linuxInitialRamdiskPath) {
linuxInitialRamdiskURL = dataURL.appendingPathComponent(linuxInitialRamdiskPath)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(operatingSystem, forKey: .operatingSystem)
try container.encodeIfPresent(linuxKernelURL?.lastPathComponent, forKey: .linuxKernelPath)
try container.encodeIfPresent(linuxCommandLine, forKey: .linuxCommandLine)
try container.encodeIfPresent(linuxInitialRamdiskURL?.lastPathComponent, forKey: .linuxInitialRamdiskPath)
}
}
struct Network: Codable {
enum NetworkMode: String, CaseIterable, Identifiable, Codable {
var id: String {
rawValue
}
case Shared
case Bridged
}
var networkMode: NetworkMode
var bridgeInterfaceIdentifier: String?
var macAddress: String
}
struct Display: Codable {
var widthInPixels: Int
var heightInPixels: Int
var pixelsPerInch: Int
}
struct MacPlatform: Codable {
var hardwareModel: Data
var machineIdentifier: Data
var auxiliaryStorageURL: URL?
private enum CodingKeys: String, CodingKey {
case hardwareModel
case machineIdentifier
case auxiliaryStoragePath
}
init(from decoder: Decoder) throws {
guard let dataURL = decoder.userInfo[.dataURL] as? URL else {
throw UTMConfigurationError.invalidDataURL
}
let container = try decoder.container(keyedBy: CodingKeys.self)
hardwareModel = try container.decode(Data.self, forKey: .hardwareModel)
machineIdentifier = try container.decode(Data.self, forKey: .machineIdentifier)
if let auxiliaryStoragePath = try container.decodeIfPresent(String.self, forKey: .auxiliaryStoragePath) {
auxiliaryStorageURL = dataURL.appendingPathComponent(auxiliaryStoragePath)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(hardwareModel, forKey: .hardwareModel)
try container.encode(machineIdentifier, forKey: .machineIdentifier)
try container.encodeIfPresent(auxiliaryStorageURL?.lastPathComponent, forKey: .auxiliaryStoragePath)
}
}
struct DiskImage: Codable, Hashable, Identifiable {
private let bytesInMib = 1048576
var sizeMib: Int
var isReadOnly: Bool
var isExternal: Bool
var imageURL: URL?
private var uuid = UUID() // for identifiable
private enum CodingKeys: String, CodingKey {
case sizeMib
case isReadOnly
case isExternal
case imagePath
case imageBookmark
}
var id: Int {
hashValue
}
var sizeBytes: Int64 {
Int64(sizeMib) * Int64(bytesInMib)
}
var sizeString: String {
ByteCountFormatter.string(fromByteCount: sizeBytes, countStyle: .file)
}
init(from decoder: Decoder) throws {
guard let dataURL = decoder.userInfo[.dataURL] as? URL else {
throw UTMConfigurationError.invalidDataURL
}
let container = try decoder.container(keyedBy: CodingKeys.self)
sizeMib = try container.decode(Int.self, forKey: .sizeMib)
isReadOnly = try container.decode(Bool.self, forKey: .isReadOnly)
isExternal = try container.decode(Bool.self, forKey: .isExternal)
if !isExternal, let imagePath = try container.decodeIfPresent(String.self, forKey: .imagePath) {
imageURL = dataURL.appendingPathComponent(imagePath)
} else if let bookmark = try container.decodeIfPresent(Data.self, forKey: .imageBookmark) {
var stale: Bool = false
imageURL = try? URL(resolvingBookmarkData: bookmark, options: .withSecurityScope, bookmarkDataIsStale: &stale)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(sizeMib, forKey: .sizeMib)
try container.encode(isReadOnly, forKey: .isReadOnly)
try container.encode(isExternal, forKey: .isExternal)
if !isExternal {
try container.encodeIfPresent(imageURL?.lastPathComponent, forKey: .imagePath)
} else {
var options = NSURL.BookmarkCreationOptions.withSecurityScope
if isReadOnly {
options.insert(.securityScopeAllowOnlyReadAccess)
}
_ = imageURL?.startAccessingSecurityScopedResource()
defer {
imageURL?.stopAccessingSecurityScopedResource()
}
let bookmark = try imageURL?.bookmarkData(options: options)
try container.encodeIfPresent(bookmark, forKey: .imageBookmark)
}
}
func hash(into hasher: inout Hasher) {
if let imageURL = imageURL {
imageURL.lastPathComponent.hash(into: &hasher)
} else {
uuid.hash(into: &hasher)
}
}
}
struct SharedDirectory: Codable, Hashable, Identifiable {
var directoryURL: URL?
var isReadOnly: Bool
var id: SharedDirectory {
self
}
private enum CodingKeys: String, CodingKey {
case directoryBookmark
case isReadOnly
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
isReadOnly = try container.decode(Bool.self, forKey: .isReadOnly)
let bookmark = try container.decode(Data.self, forKey: .directoryBookmark)
var stale: Bool = false
directoryURL = try? URL(resolvingBookmarkData: bookmark, options: .withSecurityScope, bookmarkDataIsStale: &stale)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(isReadOnly, forKey: .isReadOnly)
var options = NSURL.BookmarkCreationOptions.withSecurityScope
if isReadOnly {
options.insert(.securityScopeAllowOnlyReadAccess)
}
_ = directoryURL?.startAccessingSecurityScopedResource()
defer {
directoryURL?.stopAccessingSecurityScopedResource()
}
let bookmark = try directoryURL?.bookmarkData(options: options)
try container.encodeIfPresent(bookmark, forKey: .directoryBookmark)
}
func hash(into hasher: inout Hasher) {
directoryURL.hash(into: &hasher)
}
}
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Constants.h
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration.h"
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration (Constants)
@property (class, nonatomic, readonly) NSString *diskImagesDirectory;
+ (NSArray<NSString *>*)supportedBootDevicesPretty;
+ (NSArray<NSString *>*)supportedBootDevices;
+ (NSArray<NSString *>*)supportedImageTypesPretty;
+ (NSArray<NSString *>*)supportedImageTypes;
+ (NSArray<NSString *>*)supportedConsoleFonts;
+ (NSString *)defaultTargetForArchitecture:(NSString *)architecture;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Constants.m
================================================
//
// Copyright © 2020 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.
//
#import <TargetConditionals.h>
#if !TARGET_OS_OSX
#import <UIKit/UIKit.h>
#else
#import <AppKit/AppKit.h>
#endif
#import "UTMLegacyQemuConfiguration+Constants.h"
@implementation UTMLegacyQemuConfiguration (Constants)
+ (NSString *)diskImagesDirectory {
return @"Images";
}
#pragma mark - Constant supported values
+ (NSArray<NSString *>*)supportedBootDevicesPretty {
return @[
NSLocalizedString(@"Hard Disk", "Configuration boot device"),
NSLocalizedString(@"CD/DVD", "Configuration boot device"),
NSLocalizedString(@"Floppy", "Configuration boot device")
];
}
+ (NSArray<NSString *>*)supportedBootDevices {
return @[
@"hdd",
@"cd",
@"floppy"
];
}
+ (NSArray<NSString *>*)supportedImageTypesPretty {
return @[
NSLocalizedString(@"None", "UTMLegacyQemuConfiguration"),
NSLocalizedString(@"Disk Image", "UTMLegacyQemuConfiguration"),
NSLocalizedString(@"CD/DVD (ISO) Image", "UTMLegacyQemuConfiguration"),
NSLocalizedString(@"BIOS", "UTMLegacyQemuConfiguration"),
NSLocalizedString(@"Linux Kernel", "UTMLegacyQemuConfiguration"),
NSLocalizedString(@"Linux RAM Disk", "UTMLegacyQemuConfiguration"),
NSLocalizedString(@"Linux Device Tree Binary", "UTMLegacyQemuConfiguration")
];
}
+ (NSArray<NSString *>*)supportedImageTypes {
return @[
@"none",
@"disk",
@"cd",
@"bios",
@"kernel",
@"initrd",
@"dtb"
];
}
#if !TARGET_OS_OSX
+ (NSArray<NSString *>*)supportedConsoleFonts {
static NSMutableArray<NSString *> *families;
if (!families) {
families = [NSMutableArray new];
for (NSString *family in UIFont.familyNames) {
UIFont *font = [UIFont fontWithName:family size:1];
if (font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitMonoSpace) {
[families addObjectsFromArray:[UIFont fontNamesForFamilyName:family]];
}
}
}
return families;
}
#else
+ (NSArray<NSString *>*)supportedConsoleFonts {
static NSMutableArray<NSString *> *fonts;
if (!fonts) {
fonts = [NSMutableArray new];
for (NSString *fontName in [NSFontManager.sharedFontManager availableFontNamesWithTraits:NSFixedPitchFontMask]) {
[fonts addObject:fontName];
}
}
return fonts;
}
#endif
#pragma mark - Previously generated constants
+ (NSString *)defaultTargetForArchitecture:(NSString *)architecture {
return @{
@"alpha": @"clipper",
@"arm": @"virt",
@"aarch64": @"virt",
@"avr": @"mega",
@"cris": @"axis-dev88",
@"hppa": @"hppa",
@"i386": @"q35",
@"m68k": @"mcf5208evb",
@"microblaze": @"petalogix-s3adsp1800",
@"microblazeel": @"petalogix-s3adsp1800",
@"mips": @"malta",
@"mipsel": @"malta",
@"mips64": @"malta",
@"mips64el": @"malta",
@"nios2": @"10m50-ghrd",
@"or1k": @"or1k-sim",
@"ppc": @"g3beige",
@"ppc64": @"pseries",
@"riscv32": @"spike",
@"riscv64": @"spike",
@"rx": @"gdbsim-r5f562n7",
@"s390x": @"s390-ccw-virtio",
@"sh4": @"shix",
@"sh4eb": @"shix",
@"sparc": @"SS-5",
@"sparc64": @"sun4u",
@"tricore": @"tricore_testboard",
@"x86_64": @"q35",
@"xtensa": @"sim",
@"xtensaeb": @"sim",
}[architecture];
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Display.h
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration.h"
@import Metal;
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration (Display)
@property (nonatomic, assign) BOOL displayConsoleOnly;
@property (nonatomic, assign) BOOL displayFitScreen;
@property (nonatomic, assign) BOOL displayRetina;
@property (nonatomic, nullable, copy) NSString *displayUpscaler;
@property (nonatomic, readonly) MTLSamplerMinMagFilter displayUpscalerValue;
@property (nonatomic, nullable, copy) NSString *displayDownscaler;
@property (nonatomic, readonly) MTLSamplerMinMagFilter displayDownscalerValue;
@property (nonatomic, nullable, copy) NSString *consoleTheme;
@property (nonatomic, nullable, copy) NSString *consoleTextColor;
@property (nonatomic, nullable, copy) NSString *consoleBackgroundColor;
@property (nonatomic, nullable, copy) NSString *consoleFont;
@property (nonatomic, nullable, copy) NSNumber *consoleFontSize;
@property (nonatomic, assign) BOOL consoleCursorBlink;
@property (nonatomic, nullable, copy) NSString *consoleResizeCommand;
@property (nonatomic, nullable, copy) NSString *displayCard;
- (void)migrateDisplayConfigurationIfNecessary;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Display.m
================================================
//
// Copyright © 2020 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.
//
#import <TargetConditionals.h>
#if !TARGET_OS_OSX
#import <UIKit/UIKit.h>
#else
#import <AppKit/AppKit.h>
#endif
#import "UTMLegacyQemuConfiguration+Constants.h"
#import "UTMLegacyQemuConfiguration+Display.h"
#import "UTMLegacyQemuConfiguration+Sharing.h"
#import "UTMLegacyQemuConfiguration+System.h"
extern const NSString *const kUTMConfigDisplayKey;
const NSString *const kUTMConfigConsoleOnlyKey = @"ConsoleOnly";
const NSString *const kUTMConfigDisplayFitScreenKey = @"DisplayFitScreen";
const NSString *const kUTMConfigDisplayRetinaKey = @"DisplayRetina";
const NSString *const kUTMConfigDisplayUpscalerKey = @"DisplayUpscaler";
const NSString *const kUTMConfigDisplayDownscalerKey = @"DisplayDownscaler";
const NSString *const kUTMConfigConsoleThemeKey = @"ConsoleTheme";
const NSString *const kUTMConfigConsoleTextColorKey = @"ConsoleTextColor";
const NSString *const kUTMConfigConsoleBackgroundColorKey = @"ConsoleBackgroundColor";
const NSString *const kUTMConfigConsoleFontKey = @"ConsoleFont";
const NSString *const kUTMConfigConsoleFontSizeKey = @"ConsoleFontSize";
const NSString *const kUTMConfigConsoleBlinkKey = @"ConsoleBlink";
const NSString *const kUTMConfigConsoleResizeCommandKey = @"ConsoleResizeCommand";
const NSString *const kUTMConfigDisplayCardKey = @"DisplayCard";
@interface UTMLegacyQemuConfiguration ()
@property (nonatomic, readonly) NSMutableDictionary *rootDict;
@end
@implementation UTMLegacyQemuConfiguration (Display)
#pragma mark - Migration
- (void)migrateDisplayConfigurationIfNecessary {
if (self.displayUpscaler.length == 0) {
self.displayUpscaler = @"linear";
}
if (self.displayDownscaler.length == 0) {
self.displayDownscaler = @"linear";
}
if (self.consoleFont.length == 0) {
self.consoleFont = @"Menlo-Regular";
} else if (![[UTMLegacyQemuConfiguration supportedConsoleFonts] containsObject:self.consoleFont]) {
// migrate to new fully-formed name
#if TARGET_OS_OSX
NSFont *font = [NSFont fontWithName:self.consoleFont size:1];
#else
UIFont *font = [UIFont fontWithName:self.consoleFont size:1];
#endif
if (font) {
self.consoleFont = font.fontName;
}
}
if (self.consoleTheme.length == 0) {
self.consoleTheme = @"Default";
}
if (self.consoleTextColor == nil) {
self.consoleTextColor = @"#ffffff";
}
if (self.consoleBackgroundColor == nil) {
self.consoleBackgroundColor = @"#000000";
}
if (self.consoleFontSize.integerValue == 0) {
self.consoleFontSize = @12;
}
if (!self.displayCard) {
if ([self.systemTarget hasPrefix:@"pc"] || [self.systemTarget hasPrefix:@"q35"]) {
self.displayCard = @"qxl-vga";
} else if ([self.systemTarget isEqualToString:@"virt"] || [self.systemTarget hasPrefix:@"virt-"]) {
self.displayCard = @"virtio-ramfb";
} else {
self.displayCard = @"VGA";
}
}
if (self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayFitScreenKey] == nil) {
// automatically enable fit-screen if other SPICE features are used
self.displayFitScreen = self.shareClipboardEnabled || self.shareDirectoryEnabled;
}
}
#pragma mark - Display settings
- (void)setDisplayConsoleOnly:(BOOL)displayConsoleOnly {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleOnlyKey] = @(displayConsoleOnly);
}
- (BOOL)displayConsoleOnly {
return [self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleOnlyKey] boolValue];
}
- (void)setDisplayFitScreen:(BOOL)displayFitScreen {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayFitScreenKey] = @(displayFitScreen);
}
- (BOOL)displayFitScreen {
return [self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayFitScreenKey] boolValue];
}
- (void)setDisplayRetina:(BOOL)displayRetina {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayRetinaKey] = @(displayRetina);
}
- (BOOL)displayRetina {
return [self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayRetinaKey] boolValue];
}
- (void)setDisplayUpscaler:(NSString *)displayUpscaler {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayUpscalerKey] = displayUpscaler;
}
- (NSString *)displayUpscaler {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayUpscalerKey];
}
- (MTLSamplerMinMagFilter)displayUpscalerValue {
if ([self.displayUpscaler isEqualToString:@"nearest"]) {
return MTLSamplerMinMagFilterNearest;
} else {
return MTLSamplerMinMagFilterLinear;
}
}
- (void)setDisplayDownscaler:(NSString *)displayDownscaler {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayDownscalerKey] = displayDownscaler;
}
- (NSString *)displayDownscaler {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayDownscalerKey];
}
- (MTLSamplerMinMagFilter)displayDownscalerValue {
if ([self.displayDownscaler isEqualToString:@"nearest"]) {
return MTLSamplerMinMagFilterNearest;
} else {
return MTLSamplerMinMagFilterLinear;
}
}
- (void)setConsoleTheme:(NSString *)consoleTheme {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleThemeKey] = consoleTheme;
}
- (NSString *)consoleTheme {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleThemeKey];
}
- (void)setConsoleTextColor:(NSString *)consoleTextColor {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleTextColorKey] = consoleTextColor;
}
- (NSString *)consoleTextColor {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleTextColorKey];
}
- (void)setConsoleBackgroundColor:(NSString *)consoleBackgroundColor {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleBackgroundColorKey] = consoleBackgroundColor;
}
- (NSString *)consoleBackgroundColor {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleBackgroundColorKey];
}
- (void)setConsoleFont:(NSString *)consoleFont {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleFontKey] = consoleFont;
}
- (NSString *)consoleFont {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleFontKey];
}
- (void)setConsoleFontSize:(NSNumber *)consoleFontSize {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleFontSizeKey] = consoleFontSize;
}
- (NSNumber *)consoleFontSize {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleFontSizeKey];
}
- (void)setConsoleCursorBlink:(BOOL)consoleCursorBlink {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleBlinkKey] = @(consoleCursorBlink);
}
- (BOOL)consoleCursorBlink {
return [self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleBlinkKey] boolValue];
}
- (void)setConsoleResizeCommand:(NSString *)consoleResizeCommand {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleResizeCommandKey] = consoleResizeCommand;
}
- (NSString *)consoleResizeCommand {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleResizeCommandKey];
}
- (void)setDisplayCard:(NSString *)displayCard {
self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayCardKey] = displayCard;
}
- (NSString *)displayCard {
return self.rootDict[kUTMConfigDisplayKey][kUTMConfigDisplayCardKey];
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Drives.h
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration.h"
typedef NS_ENUM(NSInteger, UTMDiskImageType) {
UTMDiskImageTypeNone,
UTMDiskImageTypeDisk,
UTMDiskImageTypeCD,
UTMDiskImageTypeBIOS,
UTMDiskImageTypeKernel,
UTMDiskImageTypeInitrd,
UTMDiskImageTypeDTB,
UTMDiskImageTypeMax
};
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration (Drives)
@property (nonatomic, readonly) NSURL *imagesPath;
@property (nonatomic, readonly) NSInteger countDrives;
- (void)migrateDriveConfigurationIfNecessary;
- (NSInteger)newDrive:(NSString *)name path:(NSString *)path type:(UTMDiskImageType)type interface:(NSString *)interface;
- (NSInteger)newRemovableDrive:(NSString *)name type:(UTMDiskImageType)type interface:(NSString *)interface;
- (nullable NSString *)driveNameForIndex:(NSInteger)index;
- (void)setDriveName:(NSString *)name forIndex:(NSInteger)index;
- (nullable NSString *)driveImagePathForIndex:(NSInteger)index;
- (void)setImagePath:(NSString *)path forIndex:(NSInteger)index;
- (nullable NSString *)driveInterfaceTypeForIndex:(NSInteger)index;
- (void)setDriveInterfaceType:(NSString *)interfaceType forIndex:(NSInteger)index;
- (UTMDiskImageType)driveImageTypeForIndex:(NSInteger)index;
- (void)setDriveImageType:(UTMDiskImageType)type forIndex:(NSInteger)index;
- (BOOL)driveRemovableForIndex:(NSInteger)index;
- (void)setDriveRemovable:(BOOL)isRemovable forIndex:(NSInteger)index;
- (void)moveDriveIndex:(NSInteger)index to:(NSInteger)newIndex;
- (void)removeDriveAtIndex:(NSInteger)index;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Drives.m
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration+Constants.h"
#import "UTMLegacyQemuConfiguration+Drives.h"
extern const NSString *const kUTMConfigDrivesKey;
static const NSString *const kUTMConfigDriveNameKey = @"DriveName";
static const NSString *const kUTMConfigImagePathKey = @"ImagePath";
static const NSString *const kUTMConfigImageTypeKey = @"ImageType";
static const NSString *const kUTMConfigInterfaceTypeKey = @"InterfaceType";
static const NSString *const kUTMConfigRemovableKey = @"Removable";
static const NSString *const kUTMConfigCdromKey = @"Cdrom";
@interface UTMLegacyQemuConfiguration ()
@property (nonatomic, readonly) NSMutableDictionary *rootDict;
@end
@implementation UTMLegacyQemuConfiguration (Drives)
#pragma mark - Images Path
- (NSURL *)imagesPath {
if (self.existingPath) {
return [self.existingPath URLByAppendingPathComponent:[UTMLegacyQemuConfiguration diskImagesDirectory] isDirectory:YES];
} else {
return [[NSFileManager defaultManager].temporaryDirectory URLByAppendingPathComponent:[UTMLegacyQemuConfiguration diskImagesDirectory] isDirectory:YES];
}
}
#pragma mark - Migration
static BOOL ValidQemuIdentifier(NSString *name) {
NSCharacterSet *chset = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._"];
for (int i = 0; i < name.length; i++) {
unichar ch = [name characterAtIndex:i];
if (![chset characterIsMember:ch]) {
return NO;
}
if (i == 0 && !isalpha(ch)) {
return NO;
}
}
return YES;
}
- (void)migrateDriveConfigurationIfNecessary {
// Migrate Cdrom => ImageType
[self.rootDict[kUTMConfigDrivesKey] enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (!obj[kUTMConfigImageTypeKey]) {
if ([obj[kUTMConfigCdromKey] boolValue]) {
[self setDriveImageType:UTMDiskImageTypeCD forIndex:idx];
} else {
[self setDriveImageType:UTMDiskImageTypeDisk forIndex:idx];
}
[obj removeObjectForKey:kUTMConfigCdromKey];
}
}];
// add drive name
BOOL hasInvalid = NO;
for (NSInteger i = 0; i < self.countDrives; i++) {
NSString *name = [self driveNameForIndex:i];
if (name == nil || !ValidQemuIdentifier(name)) {
hasInvalid = YES;
break;
}
}
if (hasInvalid) { // reset all names if any are empty
for (NSInteger i = 0; i < self.countDrives; i++) {
[self setDriveName:[NSString stringWithFormat:@"drive%ld", i] forIndex:i];
}
}
}
#pragma mark - Drives array handling
- (NSInteger)countDrives {
return [self.rootDict[kUTMConfigDrivesKey] count];
}
- (NSInteger)newDrive:(NSString *)name path:(NSString *)path type:(UTMDiskImageType)type interface:(NSString *)interface {
NSInteger index = [self countDrives];
NSString *strType = [UTMLegacyQemuConfiguration supportedImageTypes][type];
NSMutableDictionary *drive = [[NSMutableDictionary alloc] initWithDictionary:@{
kUTMConfigDriveNameKey: name,
kUTMConfigImagePathKey: path,
kUTMConfigImageTypeKey: strType,
kUTMConfigInterfaceTypeKey: interface
}];
[self.rootDict[kUTMConfigDrivesKey] addObject:drive];
return index;
}
- (NSInteger)newRemovableDrive:(NSString *)name type:(UTMDiskImageType)type interface:(NSString *)interface {
NSInteger index = [self countDrives];
NSString *strType = [UTMLegacyQemuConfiguration supportedImageTypes][type];
NSMutableDictionary *drive = [[NSMutableDictionary alloc] initWithDictionary:@{
kUTMConfigDriveNameKey: name,
kUTMConfigRemovableKey: @(YES),
kUTMConfigImageTypeKey: strType,
kUTMConfigInterfaceTypeKey: interface
}];
[self.rootDict[kUTMConfigDrivesKey] addObject:drive];
return index;
}
- (nullable NSString *)driveNameForIndex:(NSInteger)index {
if (index >= self.countDrives) {
return nil;
} else {
return self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigDriveNameKey];
}
}
- (void)setDriveName:(NSString *)name forIndex:(NSInteger)index {
self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigDriveNameKey] = name;
}
- (nullable NSString *)driveImagePathForIndex:(NSInteger)index {
if (index >= self.countDrives) {
return nil;
} else {
return self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigImagePathKey];
}
}
- (void)setImagePath:(NSString *)path forIndex:(NSInteger)index {
self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigImagePathKey] = path;
}
- (nullable NSString *)driveInterfaceTypeForIndex:(NSInteger)index {
if (index >= self.countDrives) {
return nil;
} else {
return self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigInterfaceTypeKey];
}
}
- (void)setDriveInterfaceType:(NSString *)interfaceType forIndex:(NSInteger)index {
self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigInterfaceTypeKey] = interfaceType;
}
- (UTMDiskImageType)driveImageTypeForIndex:(NSInteger)index {
if (index >= self.countDrives) {
return UTMDiskImageTypeDisk;
}
NSString *strType = self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigImageTypeKey];
NSInteger type = [[UTMLegacyQemuConfiguration supportedImageTypes] indexOfObject:strType];
if (type == NSNotFound || type >= UTMDiskImageTypeMax) {
return UTMDiskImageTypeDisk;
} else {
return (UTMDiskImageType)type;
}
}
- (void)setDriveImageType:(UTMDiskImageType)type forIndex:(NSInteger)index {
NSString *strType = [UTMLegacyQemuConfiguration supportedImageTypes][type];
self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigImageTypeKey] = strType;
}
- (BOOL)driveRemovableForIndex:(NSInteger)index {
if (index >= self.countDrives) {
return NO;
} else {
return [self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigRemovableKey] boolValue];
}
}
- (void)setDriveRemovable:(BOOL)isRemovable forIndex:(NSInteger)index {
self.rootDict[kUTMConfigDrivesKey][index][kUTMConfigRemovableKey] = @(isRemovable);
if (isRemovable) {
[self.rootDict[kUTMConfigDrivesKey][index] removeObjectForKey:kUTMConfigImagePathKey];
}
}
- (void)moveDriveIndex:(NSInteger)index to:(NSInteger)newIndex {
NSMutableDictionary *drive = self.rootDict[kUTMConfigDrivesKey][index];
[self.rootDict[kUTMConfigDrivesKey] removeObjectAtIndex:index];
[self.rootDict[kUTMConfigDrivesKey] insertObject:drive atIndex:newIndex];
}
- (void)removeDriveAtIndex:(NSInteger)index {
[self.rootDict[kUTMConfigDrivesKey] removeObjectAtIndex:index];
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Miscellaneous.h
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration.h"
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration (Miscellaneous)
@property (nonatomic, assign) BOOL inputLegacy;
@property (nonatomic, assign) BOOL inputScrollInvert;
@property (nonatomic, assign) BOOL soundEnabled;
@property (nonatomic, nullable, copy) NSString *soundCard;
@property (nonatomic, assign) BOOL debugLogEnabled;
@property (nonatomic, assign) BOOL ignoreAllConfiguration;
@property (nonatomic, nullable, copy) NSString *icon;
@property (nonatomic, assign) BOOL iconCustom;
@property (nonatomic, nullable, copy) NSString *notes;
- (void)migrateMiscellaneousConfigurationIfNecessary;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Miscellaneous.m
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration+Miscellaneous.h"
extern const NSString *const kUTMConfigInputKey;
extern const NSString *const kUTMConfigSoundKey;
extern const NSString *const kUTMConfigDebugKey;
extern const NSString *const kUTMConfigInfoKey;
const NSString *const kUTMConfigTouchscreenModeKey = @"TouchscreenMode";
const NSString *const kUTMConfigDirectInputKey = @"DirectInput";
const NSString *const kUTMConfigInputLegacyKey = @"InputLegacy";
const NSString *const kUTMConfigInputInvertScrollKey = @"InputInvertScroll";
const NSString *const kUTMConfigSoundEnabledKey = @"SoundEnabled";
const NSString *const kUTMConfigSoundCardDeviceKey = @"SoundCard";
const NSString *const kUTMConfigDebugLogKey = @"DebugLog";
const NSString *const kUTMConfigIgnoreAllConfigurationKey = @"IgnoreAllConfiguration";
const NSString *const kUTMConfigIconKey = @"Icon";
const NSString *const kUTMConfigIconCustomKey = @"IconCustom";
const NSString *const kUTMConfigNotesKey = @"Notes";
@interface UTMLegacyQemuConfiguration ()
@property (nonatomic, readonly) NSMutableDictionary *rootDict;
@end
@implementation UTMLegacyQemuConfiguration (Miscellaneous)
#pragma mark - Migration
- (void)migrateMiscellaneousConfigurationIfNecessary {
// Add categories that may not have existed before
if (!self.rootDict[kUTMConfigDebugKey]) {
self.rootDict[kUTMConfigDebugKey] = [NSMutableDictionary dictionary];
}
if (!self.rootDict[kUTMConfigInfoKey]) {
self.rootDict[kUTMConfigInfoKey] = [NSMutableDictionary dictionary];
}
if (!self.soundCard) {
self.soundCard = @"AC97";
} else if ([self.soundCard isEqualToString:@"hda"]) {
self.soundCard = @"intel-hda"; // migrate name
} else if ([self.soundCard isEqualToString:@"pcspk"]) {
self.soundEnabled = NO; // no longer supported
}
// Migrate input settings
[self.rootDict[kUTMConfigInputKey] removeObjectForKey:kUTMConfigTouchscreenModeKey];
[self.rootDict[kUTMConfigInputKey] removeObjectForKey:kUTMConfigDirectInputKey];
if (!self.rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey]) {
self.inputLegacy = NO;
}
}
#pragma mark - Other properties
- (void)setInputLegacy:(BOOL)inputDirect {
self.rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey] = @(inputDirect);
}
- (BOOL)inputLegacy {
return [self.rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey] boolValue];
}
- (void)setInputScrollInvert:(BOOL)inputScrollInvert {
self.rootDict[kUTMConfigInputKey][kUTMConfigInputInvertScrollKey] = @(inputScrollInvert);
}
- (BOOL)inputScrollInvert {
return [self.rootDict[kUTMConfigInputKey][kUTMConfigInputInvertScrollKey] boolValue];
}
- (void)setSoundEnabled:(BOOL)soundEnabled {
self.rootDict[kUTMConfigSoundKey][kUTMConfigSoundEnabledKey] = @(soundEnabled);
}
- (BOOL)soundEnabled {
return [self.rootDict[kUTMConfigSoundKey][kUTMConfigSoundEnabledKey] boolValue];
}
- (void)setSoundCard:(NSString *)soundCard {
self.rootDict[kUTMConfigSoundKey][kUTMConfigSoundCardDeviceKey] = soundCard;
}
- (NSString *)soundCard {
return self.rootDict[kUTMConfigSoundKey][kUTMConfigSoundCardDeviceKey];
}
- (BOOL)debugLogEnabled {
return [self.rootDict[kUTMConfigDebugKey][kUTMConfigDebugLogKey] boolValue];
}
- (void)setDebugLogEnabled:(BOOL)debugLogEnabled {
self.rootDict[kUTMConfigDebugKey][kUTMConfigDebugLogKey] = @(debugLogEnabled);
}
- (BOOL)ignoreAllConfiguration {
return [self.rootDict[kUTMConfigDebugKey][kUTMConfigIgnoreAllConfigurationKey] boolValue];
}
- (void)setIgnoreAllConfiguration:(BOOL)ignoreAllConfiguration {
self.rootDict[kUTMConfigDebugKey][kUTMConfigIgnoreAllConfigurationKey] = @(ignoreAllConfiguration);
}
- (void)setIcon:(NSString *)icon {
self.rootDict[kUTMConfigInfoKey][kUTMConfigIconKey] = icon;
}
- (nullable NSString *)icon {
return self.rootDict[kUTMConfigInfoKey][kUTMConfigIconKey];
}
- (void)setIconCustom:(BOOL)iconCustom {
self.rootDict[kUTMConfigInfoKey][kUTMConfigIconCustomKey] = @(iconCustom);
}
- (BOOL)iconCustom {
return [self.rootDict[kUTMConfigInfoKey][kUTMConfigIconCustomKey] boolValue];
}
- (void)setNotes:(NSString *)notes {
self.rootDict[kUTMConfigInfoKey][kUTMConfigNotesKey] = notes;
}
- (nullable NSString *)notes {
return self.rootDict[kUTMConfigInfoKey][kUTMConfigNotesKey];
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Networking.h
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration.h"
@class UTMLegacyQemuConfigurationPortForward;
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration (Networking)
@property (nonatomic, assign) BOOL networkEnabled;
@property (nonatomic, assign) BOOL networkIsolate;
@property (nonatomic, nullable, copy) NSString *networkMode;
@property (nonatomic, nullable, copy) NSString *networkBridgeInterface;
@property (nonatomic, nullable, copy) NSString *networkCard;
@property (nonatomic, nullable, copy) NSString *networkCardMac;
@property (nonatomic, nullable, copy) NSString *networkAddress;
@property (nonatomic, nullable, copy) NSString *networkAddressIPv6;
@property (nonatomic, nullable, copy) NSString *networkHost;
@property (nonatomic, nullable, copy) NSString *networkHostIPv6;
@property (nonatomic, nullable, copy) NSString *networkDhcpStart;
@property (nonatomic, nullable, copy) NSString *networkDhcpHost;
@property (nonatomic, nullable, copy) NSString *networkDhcpDomain;
@property (nonatomic, nullable, copy) NSString *networkDnsServer;
@property (nonatomic, nullable, copy) NSString *networkDnsServerIPv6;
@property (nonatomic, nullable, copy) NSString *networkDnsSearch;
@property (nonatomic, readonly) NSInteger countPortForwards;
- (void)migrateNetworkConfigurationIfNecessary;
- (NSInteger)newPortForward:(UTMLegacyQemuConfigurationPortForward *)argument;
- (nullable UTMLegacyQemuConfigurationPortForward *)portForwardForIndex:(NSInteger)index;
- (void)updatePortForwardAtIndex:(NSInteger)index withValue:(UTMLegacyQemuConfigurationPortForward *)argument;
- (void)removePortForwardAtIndex:(NSInteger)index;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Networking.m
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration+Networking.h"
#import "UTMLegacyQemuConfigurationPortForward.h"
extern const NSString *const kUTMConfigNetworkingKey;
static const NSString *const kUTMConfigNetworkEnabledKey = @"NetworkEnabled";
static const NSString *const kUTMConfigNetworkIsolateGuestKey = @"IsolateGuest";
static const NSString *const kUTMConfigNetworkModeKey = @"NetworkMode";
static const NSString *const kUTMConfigNetworkBridgeInterfaceKey = @"NetworkBridgeInterface";
static const NSString *const kUTMConfigNetworkCardKey = @"NetworkCard";
static const NSString *const kUTMConfigNetworkCardMacKey = @"NetworkCardMAC";
static const NSString *const kUTMConfigNetworkIPSubnetKey = @"IPSubnet";
static const NSString *const kUTMConfigNetworkIPv6SubnetKey = @"IPv6Subnet";
static const NSString *const kUTMConfigNetworkIPHostKey = @"IPHost";
static const NSString *const kUTMConfigNetworkIPv6HostKey = @"IPv6Host";
static const NSString *const kUTMConfigNetworkDHCPStartKey = @"DHCPStart";
static const NSString *const kUTMConfigNetworkDHCPHostKey = @"DHCPHost";
static const NSString *const kUTMConfigNetworkDHCPDomainKey = @"DHCPDomain";
static const NSString *const kUTMConfigNetworkIPDNSKey = @"IPDNS";
static const NSString *const kUTMConfigNetworkIPv6DNSKey = @"IPv6DNS";
static const NSString *const kUTMConfigNetworkDNSSearchKey = @"DNSSearch";
static const NSString *const kUTMConfigNetworkPortForwardKey = @"PortForward";
static const NSString *const kUTMConfigNetworkPortForwardProtocolKey = @"Protocol";
static const NSString *const kUTMConfigNetworkPortForwardHostAddressKey = @"HostAddress";
static const NSString *const kUTMConfigNetworkPortForwardHostPortKey = @"HostPort";
static const NSString *const kUTMConfigNetworkPortForwardGuestAddressKey = @"GuestAddress";
static const NSString *const kUTMConfigNetworkPortForwardGuestPortKey = @"GuestPort";
@interface UTMLegacyQemuConfiguration ()
@property (nonatomic, readonly) NSMutableDictionary *rootDict;
@end
@implementation UTMLegacyQemuConfiguration (Networking)
#pragma mark - Migration
- (void)migrateNetworkConfigurationIfNecessary {
// Migrate network settings
if (!self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkCardKey]) {
self.networkCard = @"rtl8139";
}
// Generate MAC if missing
if (!self.networkCardMac) {
self.networkCardMac = [UTMLegacyQemuConfiguration generateMacAddress];
}
// default network mode
if ([self.rootDict[kUTMConfigNetworkingKey] objectForKey:kUTMConfigNetworkEnabledKey]) {
self.networkEnabled = [self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkEnabledKey] boolValue];
[self.rootDict[kUTMConfigNetworkingKey] removeObjectForKey:kUTMConfigNetworkEnabledKey];
}
}
#pragma mark - Generate MAC
+ (NSString *)generateMacAddress {
uint8_t bytes[6];
for (int i = 0; i < 6; i++) {
bytes[i] = arc4random() % 256;
}
// byte 0 should be local
bytes[0] = (bytes[0] & 0xFC) | 0x2;
return [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]];
}
#pragma mark - Network settings
- (void)setNetworkEnabled:(BOOL)networkEnabled {
if (networkEnabled) {
self.networkMode = @"emulated";
} else {
self.networkMode = @"none";
}
}
- (BOOL)networkEnabled {
return ![self.networkMode isEqualToString:@"none"];
}
- (void)setNetworkIsolate:(BOOL)networkLocalhostOnly {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIsolateGuestKey] = @(networkLocalhostOnly);
}
- (BOOL)networkIsolate {
return [self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIsolateGuestKey] boolValue];
}
- (void)setNetworkMode:(NSString *)networkMode {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkModeKey] = networkMode;
}
- (NSString *)networkMode {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkModeKey];
}
- (void)setNetworkBridgeInterface:(NSString *)networkBridgeInterface {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkBridgeInterfaceKey] = networkBridgeInterface;
}
- (NSString *)networkBridgeInterface {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkBridgeInterfaceKey];
}
- (void)setNetworkCard:(NSString *)networkCard {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkCardKey] = networkCard;
}
- (NSString *)networkCard {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkCardKey];
}
- (void)setNetworkCardMac:(NSString *)networkCardMac {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkCardMacKey] = networkCardMac;
}
- (NSString *)networkCardMac {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkCardMacKey];
}
- (void)setNetworkAddress:(NSString *)networkAddress {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPSubnetKey] = networkAddress;
}
- (NSString *)networkAddress {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPSubnetKey];
}
- (void)setNetworkAddressIPv6:(NSString *)networkAddressIPv6 {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPv6SubnetKey] = networkAddressIPv6;
}
- (NSString *)networkAddressIPv6 {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPv6SubnetKey];
}
- (void)setNetworkHost:(NSString *)networkHost {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPHostKey] = networkHost;
}
- (NSString *)networkHost {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPHostKey];
}
- (void)setNetworkHostIPv6:(NSString *)networkHostIPv6 {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPv6HostKey] = networkHostIPv6;
}
- (NSString *)networkHostIPv6 {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPv6HostKey];
}
- (void)setNetworkDhcpStart:(NSString *)networkDHCPStart {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDHCPStartKey] = networkDHCPStart;
}
- (NSString *)networkDhcpStart {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDHCPStartKey];
}
- (void)setNetworkDhcpHost:(NSString *)networkDhcpHost {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDHCPHostKey] = networkDhcpHost;
}
- (NSString *)networkDhcpHost {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDHCPHostKey];
}
- (void)setNetworkDhcpDomain:(NSString *)networkDhcpDomain {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDHCPDomainKey] = networkDhcpDomain;
}
- (NSString *)networkDhcpDomain {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDHCPDomainKey];
}
- (void)setNetworkDnsServer:(NSString *)networkDnsServer {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPDNSKey] = networkDnsServer;
}
- (NSString *)networkDnsServer {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPDNSKey];
}
- (void)setNetworkDnsServerIPv6:(NSString *)networkDnsServerIPv6 {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPv6DNSKey] = networkDnsServerIPv6;
}
- (NSString *)networkDnsServerIPv6 {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkIPv6DNSKey];
}
- (void)setNetworkDnsSearch:(NSString *)networkDnsSearch {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDNSSearchKey] = networkDnsSearch;
}
- (NSString *)networkDnsSearch {
return self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkDNSSearchKey];
}
#pragma mark - Port forwarding
- (NSInteger)countPortForwards {
return [self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkPortForwardKey] count];
}
- (NSInteger)newPortForward:(UTMLegacyQemuConfigurationPortForward *)argument {
NSInteger index = [self countPortForwards];
[self updatePortForwardAtIndex:index withValue:argument];
return index;
}
- (nullable UTMLegacyQemuConfigurationPortForward *)portForwardForIndex:(NSInteger)index {
NSDictionary *dict = self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkPortForwardKey][index];
UTMLegacyQemuConfigurationPortForward *portForward = nil;
if (dict) {
portForward = [[UTMLegacyQemuConfigurationPortForward alloc] init];
portForward.protocol = dict[kUTMConfigNetworkPortForwardProtocolKey];
portForward.hostAddress = dict[kUTMConfigNetworkPortForwardHostAddressKey];
portForward.hostPort = dict[kUTMConfigNetworkPortForwardHostPortKey];
portForward.guestAddress = dict[kUTMConfigNetworkPortForwardGuestAddressKey];
portForward.guestPort = dict[kUTMConfigNetworkPortForwardGuestPortKey];
}
return portForward;
}
- (void)updatePortForwardAtIndex:(NSInteger)index withValue:(UTMLegacyQemuConfigurationPortForward *)argument {
if (![self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkPortForwardKey] isKindOfClass:[NSMutableArray class]]) {
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkPortForwardKey] = [NSMutableArray array];
}
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[kUTMConfigNetworkPortForwardProtocolKey] = argument.protocol;
dict[kUTMConfigNetworkPortForwardHostAddressKey] = argument.hostAddress;
dict[kUTMConfigNetworkPortForwardHostPortKey] = argument.hostPort;
dict[kUTMConfigNetworkPortForwardGuestAddressKey] = argument.guestAddress;
dict[kUTMConfigNetworkPortForwardGuestPortKey] = argument.guestPort;
self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkPortForwardKey][index] = dict;
}
- (void)removePortForwardAtIndex:(NSInteger)index {
[self.rootDict[kUTMConfigNetworkingKey][kUTMConfigNetworkPortForwardKey] removeObjectAtIndex:index];
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Sharing.h
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration.h"
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration (Sharing)
@property (nonatomic, assign) BOOL shareClipboardEnabled;
@property (nonatomic, assign) BOOL shareDirectoryEnabled;
@property (nonatomic, assign) BOOL shareDirectoryReadOnly;
@property (nonatomic, nullable, copy) NSString *shareDirectoryName;
@property (nonatomic, nullable, copy) NSData *shareDirectoryBookmark;
@property (nonatomic, assign) BOOL usb3Support;
@property (nonatomic, nullable, copy) NSNumber *usbRedirectionMaximumDevices;
- (void)migrateSharingConfigurationIfNecessary;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Sharing.m
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration+Sharing.h"
#import "UTMLegacyQemuConfiguration+System.h"
extern const NSString *const kUTMConfigSharingKey;
const NSString *const kUTMConfigChipboardSharingKey = @"ClipboardSharing";
const NSString *const kUTMConfigDirectorySharingKey = @"DirectorySharing";
const NSString *const kUTMConfigDirectoryReadOnlyKey = @"DirectoryReadOnly";
const NSString *const kUTMConfigDirectoryNameKey = @"DirectoryName";
const NSString *const kUTMConfigDirectoryBookmarkKey = @"DirectoryBookmark";
const NSString *const kUTMConfigUsb3SupportKey = @"Usb3Support";
const NSString *const kUTMConfigUsbRedirectMaxKey = @"UsbRedirectMax";
@interface UTMLegacyQemuConfiguration ()
@property (nonatomic, readonly) NSMutableDictionary *rootDict;
@end
@implementation UTMLegacyQemuConfiguration (Sharing)
#pragma mark - Migration
- (void)migrateSharingConfigurationIfNecessary {
if (!self.rootDict[kUTMConfigSharingKey][kUTMConfigUsbRedirectMaxKey]) {
self.usbRedirectionMaximumDevices = @3;
}
if (![self.rootDict[kUTMConfigSharingKey] objectForKey:kUTMConfigUsb3SupportKey]) {
if ([self.systemTarget isEqualToString:@"virt"] || [self.systemTarget hasPrefix:@"virt-"]) {
self.usb3Support = YES;
}
}
}
#pragma mark - Sharing settings
- (BOOL)shareClipboardEnabled {
return [self.rootDict[kUTMConfigSharingKey][kUTMConfigChipboardSharingKey] boolValue];
}
- (void)setShareClipboardEnabled:(BOOL)shareClipboardEnabled {
self.rootDict[kUTMConfigSharingKey][kUTMConfigChipboardSharingKey] = @(shareClipboardEnabled);
}
- (BOOL)shareDirectoryEnabled {
return [self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectorySharingKey] boolValue];
}
- (void)setShareDirectoryEnabled:(BOOL)shareDirectoryEnabled {
self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectorySharingKey] = @(shareDirectoryEnabled);
}
- (BOOL)shareDirectoryReadOnly {
return [self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectoryReadOnlyKey] boolValue];
}
- (void)setShareDirectoryReadOnly:(BOOL)shareDirectoryReadOnly {
self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectoryReadOnlyKey] = @(shareDirectoryReadOnly);
}
- (NSString *)shareDirectoryName {
return self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectoryNameKey];
}
- (void)setShareDirectoryName:(NSString *)shareDirectoryName {
self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectoryNameKey] = shareDirectoryName;
}
- (NSData *)shareDirectoryBookmark {
return self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectoryBookmarkKey];
}
- (void)setShareDirectoryBookmark:(NSData *)shareDirectoryBookmark {
if (!shareDirectoryBookmark) {
[self.rootDict[kUTMConfigSharingKey] removeObjectForKey:kUTMConfigDirectoryBookmarkKey];
} else {
self.rootDict[kUTMConfigSharingKey][kUTMConfigDirectoryBookmarkKey] = shareDirectoryBookmark;
}
}
- (void)setUsb3Support:(BOOL)usb3Support {
self.rootDict[kUTMConfigSharingKey][kUTMConfigUsb3SupportKey] = @(usb3Support);
}
- (BOOL)usb3Support {
return [self.rootDict[kUTMConfigSharingKey][kUTMConfigUsb3SupportKey] boolValue];
}
- (NSNumber *)usbRedirectionMaximumDevices {
return self.rootDict[kUTMConfigSharingKey][kUTMConfigUsbRedirectMaxKey];
}
- (void)setUsbRedirectionMaximumDevices:(NSNumber *)usbRedirectionMaximumDevices {
self.rootDict[kUTMConfigSharingKey][kUTMConfigUsbRedirectMaxKey] = usbRedirectionMaximumDevices;
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+System.h
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration.h"
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration (System)
@property (nonatomic, nullable, copy) NSString *systemArchitecture;
@property (nonatomic, nullable, copy) NSString *systemCPU;
@property (nonatomic, nullable, readonly) NSArray<NSString *> *systemCPUFlags;
@property (nonatomic, nullable, copy) NSNumber *systemMemory;
@property (nonatomic, nullable, copy) NSNumber *systemCPUCount;
@property (nonatomic, nullable, copy) NSString *systemTarget;
@property (nonatomic, nullable, copy) NSString *systemBootDevice;
@property (nonatomic) BOOL systemBootUefi;
@property (nonatomic) BOOL systemRngEnabled;
@property (nonatomic, nullable, copy) NSNumber *systemJitCacheSize;
@property (nonatomic, assign) BOOL systemForceMulticore;
@property (nonatomic, nullable, copy) NSString *systemUUID;
@property (nonatomic, nullable, copy) NSString *systemMachineProperties;
@property (nonatomic, nullable, readonly) NSArray<NSString *> *systemArguments;
@property (nonatomic, readonly) NSInteger countArguments;
@property (nonatomic, assign) BOOL useHypervisor;
@property (nonatomic, readonly) BOOL isTargetArchitectureMatchHost;
@property (nonatomic, readonly) BOOL defaultUseHypervisor;
@property (nonatomic, assign) BOOL rtcUseLocalTime;
@property (nonatomic, assign) BOOL forcePs2Controller;
- (void)migrateSystemConfigurationIfNecessary;
- (NSInteger)newArgument:(NSString *)argument;
- (nullable NSString *)argumentForIndex:(NSInteger)index;
- (void)moveArgumentIndex:(NSInteger)index to:(NSInteger)newIndex;
- (void)updateArgumentAtIndex:(NSInteger)index withValue:(NSString*)argument;
- (void)removeArgumentAtIndex:(NSInteger)index;
- (NSInteger)newCPUFlag:(NSString *)CPUFlag;
- (void)removeCPUFlag:(NSString *)CPUFlag;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+System.m
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfiguration+Constants.h"
#import "UTMLegacyQemuConfiguration+System.h"
extern const NSString *const kUTMConfigSystemKey;
static const NSString *const kUTMConfigArchitectureKey = @"Architecture";
static const NSString *const kUTMConfigCPUKey = @"CPU";
static const NSString *const kUTMConfigCPUFlagsKey = @"CPUFlags";
static const NSString *const kUTMConfigMemoryKey = @"Memory";
static const NSString *const kUTMConfigCPUCountKey = @"CPUCount";
static const NSString *const kUTMConfigTargetKey = @"Target";
static const NSString *const kUTMConfigBootDeviceKey = @"BootDevice";
static const NSString *const kUTMConfigBootUefiKey = @"BootUefi";
static const NSString *const kUTMConfigRngEnabledKey = @"RngEnabled";
static const NSString *const kUTMConfigJitCacheSizeKey = @"JITCacheSize";
static const NSString *const kUTMConfigForceMulticoreKey = @"ForceMulticore";
static const NSString *const kUTMConfigAddArgsKey = @"AddArgs";
static const NSString *const kUTMConfigSystemUUIDKey = @"SystemUUID";
static const NSString *const kUTMConfigMachinePropertiesKey = @"MachineProperties";
static const NSString *const kUTMConfigUseHypervisorKey = @"UseHypervisor";
static const NSString *const kUTMConfigRTCUseLocalTimeKey = @"RTCUseLocalTime";
static const NSString *const kUTMConfigForcePs2ControllerKey = @"ForcePS2Controller";
@interface UTMLegacyQemuConfiguration ()
@property (nonatomic, readonly) NSMutableDictionary *rootDict;
@end
@implementation UTMLegacyQemuConfiguration (System)
#pragma mark - Migration
- (void)migrateSystemConfigurationIfNecessary {
// Migrates QEMU arguments from a single string to the first object in an array.
if ([self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] isKindOfClass:[NSString class]]) {
NSString *currentArgs = self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey];
self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] = [[NSMutableArray alloc] init];
self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey][0] = currentArgs;
}
// Migrate default target
if ([self.rootDict[kUTMConfigSystemKey][kUTMConfigTargetKey] length] == 0) {
self.rootDict[kUTMConfigSystemKey][kUTMConfigTargetKey] = [UTMLegacyQemuConfiguration defaultTargetForArchitecture:self.systemArchitecture];
}
// Fix issue with boot order
NSArray<NSString *> *bootPretty = [UTMLegacyQemuConfiguration supportedBootDevicesPretty];
if ([bootPretty containsObject:self.systemBootDevice]) {
NSInteger index = [bootPretty indexOfObject:self.systemBootDevice];
self.systemBootDevice = [UTMLegacyQemuConfiguration supportedBootDevices][index];
}
// Default CPU
if ([self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUKey] length] == 0) {
self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUKey] = @"default";
}
// iOS 14 uses bootindex and systemBootDevice is deprecated
if (@available(iOS 14, *)) {
self.systemBootDevice = @"";
}
// migrate global use hypervisor to per-vm
if (![self.rootDict[kUTMConfigSystemKey] objectForKey:kUTMConfigUseHypervisorKey]) {
self.useHypervisor = self.defaultUseHypervisor;
}
// Set UEFI boot to default on for virt* and off otherwise
if (self.rootDict[kUTMConfigSystemKey][kUTMConfigBootUefiKey] == nil) {
self.systemBootUefi = [self.systemTarget hasPrefix:@"virt"];
}
// Set RNG enabled default for pc* and virt*
if (self.rootDict[kUTMConfigSystemKey][kUTMConfigRngEnabledKey] == nil) {
self.systemRngEnabled = [self.systemTarget hasPrefix:@"pc"] || [self.systemTarget hasPrefix:@"q35"] || [self.systemTarget hasPrefix:@"virt"];
}
if (self.rootDict[kUTMConfigSystemKey][kUTMConfigRTCUseLocalTimeKey] == nil) {
self.rtcUseLocalTime = YES; // used to be default, now only for Windows
}
// PS/2 controller used to always be enabled by default for pc/q35
if (self.rootDict[kUTMConfigSystemKey][kUTMConfigForcePs2ControllerKey] == nil) {
self.forcePs2Controller = [self.systemTarget hasPrefix:@"pc"] || [self.systemTarget hasPrefix:@"q35"];
}
}
#pragma mark - System Properties
- (void)setSystemArchitecture:(NSString *)systemArchitecture {
self.rootDict[kUTMConfigSystemKey][kUTMConfigArchitectureKey] = systemArchitecture;
}
- (NSString *)systemArchitecture {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigArchitectureKey];
}
- (void)setSystemCPU:(NSString *)systemCPU {
self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUKey] = systemCPU;
}
- (NSString *)systemCPU {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUKey];
}
- (void)setSystemMemory:(NSNumber *)systemMemory {
self.rootDict[kUTMConfigSystemKey][kUTMConfigMemoryKey] = systemMemory;
}
- (NSNumber *)systemMemory {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigMemoryKey];
}
- (void)setSystemCPUCount:(NSNumber *)systemCPUCount {
self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUCountKey] = systemCPUCount;
}
- (NSNumber *)systemCPUCount {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUCountKey];
}
- (void)setSystemTarget:(NSString *)systemTarget {
self.rootDict[kUTMConfigSystemKey][kUTMConfigTargetKey] = systemTarget;
}
- (NSString *)systemTarget {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigTargetKey];
}
- (void)setSystemBootDevice:(NSString *)systemBootDevice {
self.rootDict[kUTMConfigSystemKey][kUTMConfigBootDeviceKey] = systemBootDevice;
}
- (NSString *)systemBootDevice {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigBootDeviceKey];
}
- (void)setSystemBootUefi:(BOOL)systemBootUefi {
self.rootDict[kUTMConfigSystemKey][kUTMConfigBootUefiKey] = @(systemBootUefi);
}
- (BOOL)systemBootUefi {
return [self.rootDict[kUTMConfigSystemKey][kUTMConfigBootUefiKey] boolValue];
}
- (void)setSystemRngEnabled:(BOOL)systemRngEnabled {
self.rootDict[kUTMConfigSystemKey][kUTMConfigRngEnabledKey] = @(systemRngEnabled);
}
- (BOOL)systemRngEnabled {
return [self.rootDict[kUTMConfigSystemKey][kUTMConfigRngEnabledKey] boolValue];
}
- (NSNumber *)systemJitCacheSize {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigJitCacheSizeKey];
}
- (void)setSystemJitCacheSize:(NSNumber *)systemJitCacheSize {
self.rootDict[kUTMConfigSystemKey][kUTMConfigJitCacheSizeKey] = systemJitCacheSize;
}
- (BOOL)systemForceMulticore {
return [self.rootDict[kUTMConfigSystemKey][kUTMConfigForceMulticoreKey] boolValue];
}
- (void)setSystemForceMulticore:(BOOL)systemForceMulticore {
self.rootDict[kUTMConfigSystemKey][kUTMConfigForceMulticoreKey] = @(systemForceMulticore);
}
- (NSString *)systemUUID {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigSystemUUIDKey];
}
- (void)setSystemUUID:(NSString *)systemUUID {
self.rootDict[kUTMConfigSystemKey][kUTMConfigSystemUUIDKey] = systemUUID;
}
- (NSString *)systemMachineProperties {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigMachinePropertiesKey];
}
- (void)setSystemMachineProperties:(NSString *)systemMachineProperties {
self.rootDict[kUTMConfigSystemKey][kUTMConfigMachinePropertiesKey] = systemMachineProperties;
}
- (BOOL)useHypervisor {
return [self.rootDict[kUTMConfigSystemKey][kUTMConfigUseHypervisorKey] boolValue];
}
- (void)setUseHypervisor:(BOOL)useHypervisor {
self.rootDict[kUTMConfigSystemKey][kUTMConfigUseHypervisorKey] = @(useHypervisor);
}
- (BOOL)rtcUseLocalTime {
return [self.rootDict[kUTMConfigSystemKey][kUTMConfigRTCUseLocalTimeKey] boolValue];
}
- (void)setRtcUseLocalTime:(BOOL)rtcUseLocalTime {
self.rootDict[kUTMConfigSystemKey][kUTMConfigRTCUseLocalTimeKey] = @(rtcUseLocalTime);
}
- (BOOL)forcePs2Controller {
return [self.rootDict[kUTMConfigSystemKey][kUTMConfigForcePs2ControllerKey] boolValue];
}
- (void)setForcePs2Controller:(BOOL)forcePs2Controller {
self.rootDict[kUTMConfigSystemKey][kUTMConfigForcePs2ControllerKey] = @(forcePs2Controller);
}
#pragma mark - Additional arguments array handling
- (NSInteger)countArguments {
return [self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] count];
}
- (NSInteger)newArgument:(NSString *)argument {
if (![self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] isKindOfClass:[NSMutableArray class]]) {
self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] = [NSMutableArray array];
}
NSInteger index = [self countArguments];
self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey][index] = argument;
return index;
}
- (nullable NSString *)argumentForIndex:(NSInteger)index {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey][index];
}
- (void)updateArgumentAtIndex:(NSInteger)index withValue:(NSString*)argument {
self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey][index] = argument;
}
- (void)moveArgumentIndex:(NSInteger)index to:(NSInteger)newIndex {
NSString *arg = self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey][index];
[self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] removeObjectAtIndex:index];
[self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] insertObject:arg atIndex:newIndex];
}
- (void)removeArgumentAtIndex:(NSInteger)index {
[self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey] removeObjectAtIndex:index];
}
- (NSArray *)systemArguments {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigAddArgsKey];
}
#pragma mark - CPU Flags
- (NSArray *)systemCPUFlags {
return self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUFlagsKey];
}
- (NSInteger)newCPUFlag:(NSString *)CPUFlag {
NSMutableArray<NSString *> *flags = self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUFlagsKey];
if (![flags isKindOfClass:[NSMutableArray class]]) {
flags = self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUFlagsKey] = [NSMutableArray array];
}
NSUInteger index = [flags indexOfObjectPassingTest:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [CPUFlag isEqualToString:obj];
}];
if (index != NSNotFound) {
return (NSInteger)index;
}
[flags addObject:CPUFlag];
return flags.count - 1;
}
- (void)removeCPUFlag:(NSString *)CPUFlag {
NSMutableArray<NSString *> *flags = self.rootDict[kUTMConfigSystemKey][kUTMConfigCPUFlagsKey];
[flags removeObject:CPUFlag];
}
#pragma mark - Computed properties
- (BOOL)isTargetArchitectureMatchHost {
#if defined(__aarch64__)
return [self.systemArchitecture isEqualToString:@"aarch64"];
#elif defined(__x86_64__)
return [self.systemArchitecture isEqualToString:@"x86_64"];
#else
return NO;
#endif
}
- (BOOL)defaultUseHypervisor {
#if TARGET_OS_IPHONE
return NO;
#else
return self.isTargetArchitectureMatchHost;
#endif
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration.h
================================================
//
// Copyright © 2019 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.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfiguration : NSObject
@property (nonatomic, nullable, copy) NSNumber *version;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, nullable, copy) NSURL *existingPath;
@property (nonatomic, nullable, copy) NSURL *selectedCustomIconPath;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary name:(NSString *)name path:(NSURL *)path NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration.m
================================================
//
// Copyright © 2019 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.
//
#import "UTMLegacyQemuConfiguration.h"
#import "UTMLegacyQemuConfiguration+Display.h"
#import "UTMLegacyQemuConfiguration+Drives.h"
#import "UTMLegacyQemuConfiguration+Miscellaneous.h"
#import "UTMLegacyQemuConfiguration+Networking.h"
#import "UTMLegacyQemuConfiguration+Sharing.h"
#import "UTMLegacyQemuConfiguration+System.h"
#import <TargetConditionals.h>
const NSString *const kUTMConfigSystemKey = @"System";
const NSString *const kUTMConfigDisplayKey = @"Display";
const NSString *const kUTMConfigInputKey = @"Input";
const NSString *const kUTMConfigNetworkingKey = @"Networking";
const NSString *const kUTMConfigPrintingKey = @"Printing";
const NSString *const kUTMConfigSoundKey = @"Sound";
const NSString *const kUTMConfigSharingKey = @"Sharing";
const NSString *const kUTMConfigDrivesKey = @"Drives";
const NSString *const kUTMConfigDebugKey = @"Debug";
const NSString *const kUTMConfigInfoKey = @"Info";
const NSString *const kUTMConfigVersionKey = @"ConfigurationVersion";
const NSInteger kCurrentConfigurationVersion = 2;
const NSString *const kUTMConfigAppleVirtualizationKey = @"isAppleVirtualization";
@interface UTMLegacyQemuConfiguration ()
@property (nonatomic, readonly) NSMutableDictionary *rootDict;
@end
@implementation UTMLegacyQemuConfiguration {
NSMutableDictionary *_rootDict;
}
@synthesize rootDict = _rootDict;
- (void)setName:(NSString *)name {
_name = name;
}
- (void)setExistingPath:(NSURL *)existingPath {
_existingPath = existingPath;
}
- (void)setSelectedCustomIconPath:(NSURL *)selectedCustomIconPath {
_selectedCustomIconPath = selectedCustomIconPath;
}
- (NSURL *)iconUrl {
if (self.iconCustom) {
if (self.selectedCustomIconPath != nil) {
return self.selectedCustomIconPath;
} else if (self.icon == nil) {
return nil;
} else {
return [self.existingPath URLByAppendingPathComponent:self.icon];
}
} else {
if (self.icon == nil) {
return nil;
} else {
return [[NSBundle mainBundle] URLForResource:self.icon withExtension:@"png" subdirectory:@"Icons"];
}
}
}
#pragma mark - Migration
- (void)migrateConfigurationIfNecessary {
[self migrateMiscellaneousConfigurationIfNecessary];
[self migrateDriveConfigurationIfNecessary];
[self migrateNetworkConfigurationIfNecessary];
[self migrateSystemConfigurationIfNecessary];
[self migrateDisplayConfigurationIfNecessary];
[self migrateSharingConfigurationIfNecessary];
self.version = @(kCurrentConfigurationVersion);
}
#pragma mark - Initialization
- (instancetype)initWithDictionary:(NSDictionary *)dictionary name:(NSString *)name path:(NSURL *)path {
self = [super init];
if (self) {
if (![self reloadConfigurationWithDictionary:dictionary name:name path:path]) {
return nil;
}
}
return self;
}
#pragma mark - Dictionary representation
- (BOOL)reloadConfigurationWithDictionary:(NSDictionary *)dictionary name:(NSString *)name path:(NSURL *)path {
if ([dictionary[kUTMConfigAppleVirtualizationKey] boolValue]) {
return NO; // do not parse Apple config
}
if ([dictionary[kUTMConfigVersionKey] intValue] > kCurrentConfigurationVersion) {
return NO; // do not parse if version is too high
}
_rootDict = CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (__bridge CFDictionaryRef)dictionary, kCFPropertyListMutableContainers));
self.name = name;
self.existingPath = path;
self.selectedCustomIconPath = nil;
[self migrateConfigurationIfNecessary];
return YES;
}
#pragma mark - Settings
- (void)setVersion:(NSNumber *)version {
self.rootDict[kUTMConfigVersionKey] = version;
}
- (NSNumber *)version {
return self.rootDict[kUTMConfigVersionKey];
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfigurationPortForward.h
================================================
//
// Copyright © 2020 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.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyQemuConfigurationPortForward : NSObject
@property (nonatomic, nullable) NSString *protocol;
@property (nonatomic) NSString *hostAddress;
@property (nonatomic, nullable) NSNumber *hostPort;
@property (nonatomic) NSString *guestAddress;
@property (nonatomic, nullable) NSNumber *guestPort;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyQemuConfigurationPortForward.m
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyQemuConfigurationPortForward.h"
@implementation UTMLegacyQemuConfigurationPortForward
@synthesize protocol = _protocol;
@synthesize hostAddress = _hostAddress;
@synthesize hostPort = _hostPort;
@synthesize guestAddress = _guestAddress;
@synthesize guestPort = _guestPort;
- (void)setProtocol:(NSString *)protocol {
_protocol = protocol;
}
- (NSString *)protocol {
if (_protocol) {
return _protocol;
} else {
return @"tcp";
}
}
- (void)setHostAddress:(NSString *)hostAddress {
_hostAddress = hostAddress;
}
- (NSString *)hostAddress {
if (_hostAddress) {
return _hostAddress;
} else {
return @"";
}
}
- (void)setHostPort:(NSNumber *)hostPort {
_hostPort = hostPort;
}
- (NSNumber *)hostPort {
if (_hostPort) {
return _hostPort;
} else {
return @(0);
}
}
- (void)setGuestAddress:(NSString *)guestAddress {
_guestAddress = guestAddress;
}
- (NSString *)guestAddress {
if (_guestAddress) {
return _guestAddress;
} else {
return @"";
}
}
- (void)setGuestPort:(NSNumber *)guestPort {
_guestPort = guestPort;
}
- (NSNumber *)guestPort {
if (_guestPort) {
return _guestPort;
} else {
return @(0);
}
}
@end
================================================
FILE: Configuration/Legacy/UTMLegacyViewState.h
================================================
//
// Copyright © 2020 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.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface UTMLegacyViewState : NSObject
@property (nonatomic, weak, readonly) NSDictionary *dictRepresentation;
@property (nonatomic, readonly) CGFloat displayScale;
@property (nonatomic, readonly) CGFloat displayOriginX;
@property (nonatomic, readonly) CGFloat displayOriginY;
@property (nonatomic, readonly) BOOL isKeyboardShown;
@property (nonatomic, readonly) BOOL isToolbarShown;
@property (nonatomic, readonly) BOOL hasSaveState;
@property (nonatomic, readonly, nullable) NSData *sharedDirectory;
@property (nonatomic, readonly, nullable) NSString *sharedDirectoryPath;
@property (nonatomic, readonly, nullable) NSData *shortcutBookmark;
@property (nonatomic, readonly, nullable) NSString *shortcutBookmarkPath;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary NS_DESIGNATED_INITIALIZER;
- (NSArray<NSString *> *)allDrives;
- (nullable NSData *)bookmarkForRemovableDrive:(NSString *)drive;
- (nullable NSString *)pathForRemovableDrive:(NSString *)drive;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Configuration/Legacy/UTMLegacyViewState.m
================================================
//
// Copyright © 2020 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.
//
#import "UTMLegacyViewState.h"
const NSString *const kUTMViewStateDisplayScaleKey = @"DisplayScale";
const NSString *const kUTMViewStateDisplayOriginXKey = @"DisplayOriginX";
const NSString *const kUTMViewStateDisplayOriginYKey = @"DisplayOriginY";
const NSString *const kUTMViewStateShowToolbarKey = @"ShowToolbar";
const NSString *const kUTMViewStateShowKeyboardKey = @"ShowKeyboard";
const NSString *const kUTMViewStateSuspendedKey = @"Suspended";
const NSString *const kUTMViewStateSharedDirectoryKey = @"SharedDirectory";
const NSString *const kUTMViewStateSharedDirectoryPathKey = @"SharedDirectoryPath";
const NSString *const kUTMViewStateShortcutBookmarkKey = @"ShortcutBookmark";
const NSString *const kUTMViewStateShortcutBookmarkPathKey = @"ShortcutBookmarkPath";
const NSString *const kUTMViewStateRemovableDrivesKey = @"RemovableDrives";
const NSString *const kUTMViewStateRemovableDrivesPathKey = @"RemovableDrivesPath";
@implementation UTMLegacyViewState {
NSMutableDictionary *_rootDict;
NSMutableDictionary<NSString *, NSData *> *_removableDrives;
NSMutableDictionary<NSString *, NSString *> *_removableDrivesPath;
}
#pragma mark - Properties
- (NSDictionary *)dictRepresentation {
return (NSDictionary *)_rootDict;
}
- (CGFloat)displayScale {
return [_rootDict[kUTMViewStateDisplayScaleKey] floatValue];
}
- (CGFloat)displayOriginX {
return [_rootDict[kUTMViewStateDisplayOriginXKey] floatValue];
}
- (CGFloat)displayOriginY {
return [_rootDict[kUTMViewStateDisplayOriginYKey] floatValue];
}
- (BOOL)isKeyboardShown {
return [_rootDict[kUTMViewStateShowToolbarKey] boolValue];
}
- (BOOL)isToolbarShown {
return [_rootDict[kUTMViewStateShowToolbarKey] boolValue];
}
- (BOOL)hasSaveState {
return [_rootDict[kUTMViewStateSuspendedKey] boolValue];
}
- (NSData *)sharedDirectory {
return _rootDict[kUTMViewStateSharedDirectoryKey];
}
- (NSString *)sharedDirectoryPath {
return _rootDict[kUTMViewStateSharedDirectoryPathKey];
}
- (NSData *)shortcutBookmark {
return _rootDict[kUTMViewStateShortcutBookmarkKey];
}
- (NSString *)shortcutBookmarkPath {
return _rootDict[kUTMViewStateShortcutBookmarkPathKey];
}
#pragma mark - Removable drives
- (NSArray<NSString *> *)allDrives {
return [_removableDrives allKeys];
}
- (nullable NSData *)bookmarkForRemovableDrive:(NSString *)drive {
return _removableDrives[drive];
}
- (nullable NSString *)pathForRemovableDrive:(NSString *)drive {
return _removableDrivesPath[drive];
}
#pragma mark - Init
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
self = [super init];
if (self) {
_rootDict = CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (__bridge CFDictionaryRef)dictionary, kCFPropertyListMutableContainers));
_removableDrives = _rootDict[kUTMViewStateRemovableDrivesKey];
_removableDrivesPath = _rootDict[kUTMViewStateRemovableDrivesPathKey];
if (!_removableDrives) {
_removableDrives = [NSMutableDictionary dictionary];
_rootDict[kUTMViewStateRemovableDrivesKey] = _removableDrives;
}
if (!_removableDrivesPath) {
_removableDrivesPath = [NSMutableDictionary dictionary];
_rootDict[kUTMViewStateRemovableDrivesPathKey] = _removableDrivesPath;
}
}
return self;
}
@end
================================================
FILE: Configuration/QEMUArgument.swift
================================================
//
// Copyright © 2022 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.
//
import Foundation
struct QEMUArgument: Hashable, Identifiable, Codable {
/// Argument string passed to QEMU
var string: String
/// Optional URL resource that must be accessed
var fileUrls: [URL]?
let id = UUID()
init(_ string: String) {
self.string = string
}
init(from fragment: QEMUArgumentFragment) {
string = fragment.string
fileUrls = fragment.fileUrls
}
init(from decoder: Decoder) throws {
string = try String(from: decoder)
}
func encode(to encoder: Encoder) throws {
try string.encode(to: encoder)
}
func hash(into hasher: inout Hasher) {
id.hash(into: &hasher)
}
}
struct QEMUArgumentFragment: Hashable {
/// String representing this fragment
var string: String
/// Optional URL resource(s) that must be accessed
var fileUrls: [URL]?
/// If false, this fragment will be merged with the preceding one
private(set) var isFinal: Bool
/// If true, we already escaped the commas
private var isUrlFragment: Bool = false
/// Separate the previous fragment if non-empty
private var seperator: String = ","
init(_ fragment: String = "") {
string = fragment
isFinal = false
}
init(urlFragment: URL) {
string = urlFragment.path
isFinal = false
isUrlFragment = true
fileUrls = [urlFragment]
seperator = ""
}
init(final fragment: String) {
string = fragment
isFinal = true
}
init(from argument: QEMUArgument) {
string = argument.string
fileUrls = argument.fileUrls
isFinal = true
}
func hash(into hasher: inout Hasher) {
string.hash(into: &hasher)
fileUrls?.hash(into: &hasher)
isFinal.hash(into: &hasher)
}
mutating func merge(_ other: QEMUArgumentFragment) {
if self.string.count == 0 {
self.isUrlFragment = other.isUrlFragment
}
if self.string.count > 0 && other.string.count > 0 {
var otherString = other.string
if other.isUrlFragment {
otherString = otherString.replacingOccurrences(of: ",", with: ",,")
}
self.string += other.seperator + otherString
} else {
self.string += other.string
}
self.isFinal = self.isFinal || other.isFinal
if let fileUrls = other.fileUrls {
if self.fileUrls == nil {
self.fileUrls = fileUrls
} else {
self.fileUrls!.append(contentsOf: fileUrls)
}
}
}
}
================================================
FILE: Configuration/QEMUArgumentBuilder.swift
================================================
//
// Copyright © 2022 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.
//
import Foundation
@resultBuilder
struct QEMUArgumentBuilder {
static func buildBlock(_ components: [QEMUArgumentFragment]...) -> [QEMUArgumentFragment] {
let merged = components.flatMap { $0 }
var combined: [QEMUArgumentFragment] = []
var current = QEMUArgumentFragment()
for fragment in merged {
current.merge(fragment)
if current.isFinal {
combined.append(current)
current = QEMUArgumentFragment()
}
}
if !current.string.isEmpty {
combined.append(current)
}
return combined
}
static func buildExpression(_ fragment: QEMUArgumentFragment) -> [QEMUArgumentFragment] {
[fragment]
}
static func buildExpression(_ fragments: [QEMUArgumentFragment]) -> [QEMUArgumentFragment] {
fragments
}
static func buildExpression(_ arguments: [QEMUArgument]) -> [QEMUArgumentFragment] {
arguments.map { QEMUArgumentFragment(from: $0) }
}
static func buildExpression(_ string: String) -> [QEMUArgumentFragment] {
[.init(string)]
}
static func buildExpression(_ constant: any QEMUConstant) -> [QEMUArgumentFragment] {
[.init(constant.rawValue)]
}
static func buildExpression(_ assignment: ()) -> [QEMUArgumentFragment] {
[]
}
static func buildExpression(_ url: URL) -> [QEMUArgumentFragment] {
return [QEMUArgumentFragment(urlFragment: url)]
}
static func buildExpression<I: FixedWidthInteger>(_ int: I) -> [QEMUArgumentFragment] {
[.init("\(int)")]
}
static func buildEither(first component: [QEMUArgumentFragment]) -> [QEMUArgumentFragment] {
component
}
static func buildEither(second component: [QEMUArgumentFragment]) -> [QEMUArgumentFragment] {
component
}
static func buildArray(_ components: [[QEMUArgumentFragment]]) -> [QEMUArgumentFragment] {
components.flatMap { $0 }
}
static func buildOptional(_ component: [QEMUArgumentFragment]?) -> [QEMUArgumentFragment] {
component ?? []
}
static func buildFinalResult(_ component: [QEMUArgumentFragment]) -> [QEMUArgument] {
component.map { QEMUArgument(from: $0) }
}
}
================================================
FILE: Configuration/QEMUConstant.swift
================================================
//
// Copyright © 2022 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.
//
import Foundation
import Metal
// MARK: QEMUConstant protocol
/// A QEMU constant is a enum that can be generated externally
protocol QEMUConstant: Codable, RawRepresentable, CaseIterable where RawValue == String, AllCases == [Self] {
static var allRawValues: [String] { get }
static var allPrettyValues: [String] { get }
static var shownPrettyValues: [String] { get }
var prettyValue: String { get }
var rawValue: String { get }
var isHidden: Bool { get }
init?(rawValue: String)
}
extension QEMUConstant where Self: CaseIterable, AllCases == [Self] {
static var allRawValues: [String] {
allCases.map { value in value.rawValue }
}
static var allPrettyValues: [String] {
allCases.map { value in value.prettyValue }
}
static var shownPrettyValues: [String] {
allCases.compactMap { value in value.isHidden ? nil : value.prettyValue }
}
var isHidden: Bool {
false
}
}
extension QEMUConstant where Self: RawRepresentable, RawValue == String {
init(from decoder: Decoder) throws {
let rawValue = try String(from: decoder)
guard let representedValue = Self.init(rawValue: rawValue) else {
throw UTMConfigurationError.invalidConfigurationValue(rawValue)
}
self = representedValue
}
func encode(to encoder: Encoder) throws {
try rawValue.encode(to: encoder)
}
}
protocol QEMUDefaultConstant: QEMUConstant {
static var `default`: Self { get }
}
extension Optional where Wrapped: QEMUDefaultConstant {
var _bound: Wrapped? {
get {
return self
}
set {
self = newValue
}
}
var bound: Wrapped {
get {
return _bound ?? Wrapped.default
}
set {
_bound = newValue
}
}
}
/// Type erasure for a QEMU constant useful for serialization/deserialization
struct AnyQEMUConstant: QEMUConstant, RawRepresentable {
static var allRawValues: [String] { [] }
static var allPrettyValues: [String] { [] }
static var allCases: [AnyQEMUConstant] { [] }
var prettyValue: String { rawValue }
let rawValue: String
init<C>(_ base: C) where C : QEMUConstant {
self.rawValue = base.rawValue
}
init?(rawValue: String) {
self.rawValue = rawValue
}
}
extension QEMUConstant {
func asAnyQEMUConstant() -> AnyQEMUConstant {
return AnyQEMUConstant(self)
}
}
extension AnyQEMUConstant: QEMUDefaultConstant {
static var `default`: AnyQEMUConstant {
AnyQEMUConstant(rawValue: "default")!
}
}
// MARK: Enhanced type checking for generated constants
protocol QEMUTarget: QEMUDefaultConstant {}
extension AnyQEMUConstant: QEMUTarget {}
protocol QEMUCPU: QEMUDefaultConstant {}
extension AnyQEMUConstant: QEMUCPU {}
protocol QEMUCPUFlag: QEMUConstant {}
extension AnyQEMUConstant: QEMUCPUFlag {}
protocol QEMUDisplayDevice: QEMUConstant {}
extension AnyQEMUConstant: QEMUDisplayDevice {}
protocol QEMUNetworkDevice: QEMUConstant {}
extension AnyQEMUConstant: QEMUNetworkDevice {}
protocol QEMUSoundDevice: QEMUConstant {}
extension AnyQEMUConstant: QEMUSoundDevice {}
protocol QEMUSerialDevice: QEMUConstant {}
extension AnyQEMUConstant: QEMUSerialDevice {}
// MARK: Display constants
enum QEMUScaler: String, CaseIterable, QEMUConstant {
case linear = "Linear"
case nearest = "Nearest"
var prettyValue: String {
switch self {
case .linear: return NSLocalizedString("Linear", comment: "UTMQemuConstants")
case .nearest: return NSLocalizedString("Nearest Neighbor", comment: "UTMQemuConstants")
}
}
var metalSamplerMinMagFilter: MTLSamplerMinMagFilter {
switch self {
case .linear: return .linear
case .nearest: return .nearest
}
}
}
// MARK: USB constants
enum QEMUUSBBus: String, CaseIterable, QEMUConstant {
case disabled = "Disabled"
case usb2_0 = "2.0"
case usb3_0 = "3.0"
var prettyValue: String {
switch self {
case .disabled: return NSLocalizedString("Disabled", comment: "UTMQemuConstants")
case .usb2_0: return NSLocalizedString("USB 2.0", comment: "UTMQemuConstants")
case .usb3_0: return NSLocalizedString("USB 3.0 (XHCI)", comment: "UTMQemuConstants")
}
}
}
// MARK: Network constants
enum QEMUNetworkMode: String, CaseIterable, QEMUConstant {
case emulated = "Emulated"
case shared = "Shared"
case host = "Host"
case bridged = "Bridged"
var prettyValue: String {
switch self {
case .emulated: return NSLocalizedString("Emulated VLAN", comment: "UTMQemuConstants")
case .shared: return NSLocalizedString("Shared Network", comment: "UTMQemuConstants")
case .host: return NSLocalizedString("Host Only", comment: "UTMQemuConstants")
case .bridged: return NSLocalizedString("Bridged (Advanced)", comment: "UTMQemuConstants")
}
}
}
enum QEMUNetworkProtocol: String, CaseIterable, QEMUConstant {
case tcp = "TCP"
case udp = "UDP"
var prettyValue: String {
switch self {
case .tcp: return NSLocalizedString("TCP", comment: "UTMQemuConstants")
case .udp: return NSLocalizedString("UDP", comment: "UTMQemuConstants")
}
}
}
// MARK: Serial constants
enum QEMUTerminalTheme: String, CaseIterable, QEMUDefaultConstant {
case `default` = "Default"
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "UTMQemuConstants")
}
}
}
struct QEMUTerminalFont: QEMUConstant {
#if os(macOS)
static var allRawValues: [String] = {
NSFontManager.shared.availableFontNames(with: .fixedPitchFontMask) ?? []
}()
static var allPrettyValues: [String] = {
allRawValues.map { name in
NSFont(name: name, size: 1)?.displayName ?? name
}
}()
#else
static var allRawValues: [String] = {
UIFont.familyNames.flatMap { family -> [String] in
guard let font = UIFont(name: family, size: 1) else {
return []
}
if font.fontDescriptor.symbolicTraits.contains(.traitMonoSpace) {
return UIFont.fontNames(forFamilyName: family)
} else {
return []
}
}
}()
static var allPrettyValues: [String] = {
allRawValues.map { name in
guard let font = UIFont(name: name, size: 1) else {
return name
}
let traits = font.fontDescriptor.symbolicTraits
let description: String
if traits.isSuperset(of: [.traitItalic, .traitBold]) {
description = NSLocalizedString("Italic, Bold", comment: "UTMQemuConstants")
} else if traits.contains(.traitItalic) {
description = NSLocalizedString("Italic", comment: "UTMQemuConstants")
} else if traits.contains(.traitBold) {
description = NSLocalizedString("Bold", comment: "UTMQemuConstants")
} else {
description = NSLocalizedString("Regular", comment: "UTMQemuConstants")
}
return String.localizedStringWithFormat(NSLocalizedString("%@ (%@)", comment: "QEMUConstant"), font.familyName, description)
}
}()
#endif
static var allCases: [QEMUTerminalFont] {
Self.allRawValues.map { Self(rawValue: $0) }
}
var prettyValue: String {
guard let index = Self.allRawValues.firstIndex(of: rawValue) else {
return rawValue
}
return Self.allPrettyValues[index]
}
let rawValue: String
}
enum QEMUSerialMode: String, CaseIterable, QEMUConstant {
case builtin = "Terminal"
case tcpClient = "TcpClient"
case tcpServer = "TcpServer"
#if os(macOS)
case ptty = "Ptty"
#endif
var prettyValue: String {
switch self {
case .builtin: return NSLocalizedString("Built-in Terminal", comment: "UTMQemuConstants")
case .tcpClient: return NSLocalizedString("TCP Client Connection", comment: "UTMQemuConstants")
case .tcpServer: return NSLocalizedString("TCP Server Connection", comment: "UTMQemuConstants")
#if os(macOS)
case .ptty: return NSLocalizedString("Pseudo-TTY Device", comment: "UTMQemuConstants")
#endif
}
}
}
enum QEMUSerialTarget: String, CaseIterable, QEMUConstant {
case autoDevice = "Auto"
case manualDevice = "Manual"
case gdb = "GDB"
case monitor = "Monitor"
var prettyValue: String {
switch self {
case .autoDevice: return NSLocalizedString("Automatic Serial Device (max 4)", comment: "UTMQemuConstants")
case .manualDevice: return NSLocalizedString("Manual Serial Device (advanced)", comment: "UTMQemuConstants")
case .gdb: return NSLocalizedString("GDB Debug Stub", comment: "UTMQemuConstants")
case .monitor: return NSLocalizedString("QEMU Monitor (HMP)", comment: "UTMQemuConstants")
}
}
}
// MARK: Drive constants
enum QEMUDriveImageType: String, CaseIterable, QEMUConstant {
case none = "None"
case disk = "Disk"
case cd = "CD"
case bios = "BIOS"
case linuxKernel = "LinuxKernel"
case linuxInitrd = "LinuxInitrd"
case linuxDtb = "LinuxDTB"
var prettyValue: String {
switch self {
case .none: return NSLocalizedString("None", comment: "UTMQemuConstants")
case .disk: return NSLocalizedString("Disk Image", comment: "UTMQemuConstants")
case .cd: return NSLocalizedString("CD/DVD (ISO) Image", comment: "UTMQemuConstants")
case .bios: return NSLocalizedString("BIOS", comment: "UTMQemuConstants")
case .linuxKernel: return NSLocalizedString("Linux Kernel", comment: "UTMQemuConstants")
case .linuxInitrd: return NSLocalizedString("Linux RAM Disk", comment: "UTMQemuConstants")
case .linuxDtb: return NSLocalizedString("Linux Device Tree Binary", comment: "UTMQemuConstants")
}
}
}
enum QEMUDriveInterface: String, CaseIterable, QEMUConstant {
case none = "None"
case ide = "IDE"
case scsi = "SCSI"
case sd = "SD"
case mtd = "MTD"
case floppy = "Floppy"
case pflash = "PFlash"
case virtio = "VirtIO"
case nvme = "NVMe"
case usb = "USB"
var prettyValue: String {
switch self {
case .none: return NSLocalizedString("None (Advanced)", comment: "UTMQemuConstants")
case .ide: return NSLocalizedString("IDE", comment: "UTMQemuConstants")
case .scsi: return NSLocalizedString("SCSI", comment: "UTMQemuConstants")
case .sd: return NSLocalizedString("SD Card", comment: "UTMQemuConstants")
case .mtd: return NSLocalizedString("MTD (NAND/NOR)", comment: "UTMQemuConstants")
case .floppy: return NSLocalizedString("Floppy", comment: "UTMQemuConstants")
case .pflash: return NSLocalizedString("PC System Flash", comment: "UTMQemuConstants")
case .virtio: return NSLocalizedString("VirtIO", comment: "UTMQemuConstants")
case .nvme: return NSLocalizedString("NVMe", comment: "UTMQemuConstants")
case .usb: return NSLocalizedString("USB", comment: "UTMQemuConstants")
}
}
}
// MARK: Sharing constants
enum QEMUFileShareMode: String, CaseIterable, QEMUConstant {
case none = "None"
case webdav = "WebDAV"
case virtfs = "VirtFS"
var prettyValue: String {
switch self {
case .none: return NSLocalizedString("None", comment: "UTMQemuConstants")
case .webdav: return NSLocalizedString("SPICE WebDAV", comment: "UTMQemuConstants")
case .virtfs: return NSLocalizedString("VirtFS", comment: "UTMQemuConstants")
}
}
}
// MARK: File names
enum QEMUPackageFileName: String {
case images = "Images"
case debugLog = "debug.log"
case efiVariables = "efi_vars.fd"
case tpmData = "tpmdata"
case vmState = "vmstate"
}
// MARK: Supported features
extension QEMUArchitecture {
var hasAgentSupport: Bool {
switch self {
case .avr: return false
case .m68k: return false
case .microblaze, .microblazeel: return false
case .ppc, .ppc64: return false
case .rx: return false
case .sparc, .sparc64: return false
case .tricore: return false
default: return true
}
}
var hasSharingSupport: Bool {
switch self {
case .sparc, .sparc64: return false
default: return true
}
}
var hasUsbSupport: Bool {
switch self {
case .s390x: return false
case .sparc, .sparc64: return false
case .m68k: return false
default: return true
}
}
var hasHypervisorSupport: Bool {
guard UTMCapabilities.current.contains(.hasHypervisorSupport) else {
return false
}
if UTMCapabilities.current.contains(.isAarch64) {
return self == .aarch64
} else if UTMCapabilities.current.contains(.isX86_64) {
return self == .x86_64
} else {
return false
}
}
/// TSO is supported on jailbroken iOS devices with Hypervisor support
var hasTSOSupport: Bool {
#if os(iOS) || os(visionOS)
return hasHypervisorSupport
#else
if #available(macOS 15, *) {
return true
} else {
return false
}
#endif
}
var hasSecureBootSupport: Bool {
switch self {
case .x86_64, .i386: return true
case .aarch64: return true
default: return false
}
}
}
extension QEMUTarget {
var hasUsbSupport: Bool {
switch self.rawValue {
case "isapc": return false
default: return true
}
}
var hasAgentSupport: Bool {
switch self.rawValue {
case "isapc": return false
default: return true
}
}
var hasSecureBootSupport: Bool {
switch self.rawValue {
case "microvm": return false
default: return true
}
}
}
#if WITH_QEMU_TCI
/// TCI build has a reduced set of supported architectures due to size of binaries.
extension QEMUArchitecture {
var isHidden: Bool {
switch self {
case .aarch64: return false
case .i386: return false
case .m68k: return false
case .ppc: return false
case .ppc64: return false
case .riscv64: return false
case .x86_64: return false
default: return true
}
}
}
#endif
================================================
FILE: Configuration/QEMUConstantGenerated.swift
================================================
//
// Copyright © 2022 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.
//
// !! THIS FILE IS GENERATED FROM const-gen.py, DO NOT MODIFY MANUALLY !!
import Foundation
enum QEMUArchitecture: String, CaseIterable, QEMUConstant {
case alpha
case arm
case aarch64
case avr
case hppa
case i386
case loongarch64
case m68k
case microblaze
case microblazeel
case mips
case mipsel
case mips64
case mips64el
case or1k
case ppc
case ppc64
case riscv32
case riscv64
case rx
case s390x
case sh4
case sh4eb
case sparc
case sparc64
case tricore
case x86_64
case xtensa
case xtensaeb
var prettyValue: String {
switch self {
case .alpha: return "Alpha"
case .arm: return "ARM (aarch32)"
case .aarch64: return "ARM64 (aarch64)"
case .avr: return "AVR"
case .hppa: return "HPPA"
case .i386: return "i386 (x86)"
case .loongarch64: return "LoongArch64"
case .m68k: return "m68k"
case .microblaze: return "Microblaze"
case .microblazeel: return "Microblaze (Little Endian)"
case .mips: return "MIPS"
case .mipsel: return "MIPS (Little Endian)"
case .mips64: return "MIPS64"
case .mips64el: return "MIPS64 (Little Endian)"
case .or1k: return "OpenRISC"
case .ppc: return "PowerPC"
case .ppc64: return "PowerPC64"
case .riscv32: return "RISC-V32"
case .riscv64: return "RISC-V64"
case .rx: return "RX"
case .s390x: return "S390x (zSeries)"
case .sh4: return "SH4"
case .sh4eb: return "SH4 (Big Endian)"
case .sparc: return "SPARC"
case .sparc64: return "SPARC64"
case .tricore: return "TriCore"
case .x86_64: return "x86_64"
case .xtensa: return "Xtensa"
case .xtensaeb: return "Xtensa (Big Endian)"
}
}
}
enum QEMUCPU_alpha: String, CaseIterable, QEMUCPU {
case `default` = "default"
case ev4
case ev5
case ev56
case ev6
case ev67
case ev68
case pca56
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .ev4: return "ev4"
case .ev5: return "ev5"
case .ev56: return "ev56"
case .ev6: return "ev6"
case .ev67: return "ev67"
case .ev68: return "ev68"
case .pca56: return "pca56"
}
}
}
enum QEMUCPU_arm: String, CaseIterable, QEMUCPU {
case pxa250
case pxa255
case pxa260
case pxa261
case pxa262
case pxa270
case pxa270_a0 = "pxa270-a0"
case pxa270_a1 = "pxa270-a1"
case pxa270_b0 = "pxa270-b0"
case pxa270_b1 = "pxa270-b1"
case pxa270_c0 = "pxa270-c0"
case pxa270_c5 = "pxa270-c5"
case `default` = "default"
case arm1026
case arm1136
case arm1136_r2 = "arm1136-r2"
case arm1176
case arm11mpcore
case arm926
case arm946
case cortex_a15 = "cortex-a15"
case cortex_a7 = "cortex-a7"
case cortex_a8 = "cortex-a8"
case cortex_a9 = "cortex-a9"
case cortex_m0 = "cortex-m0"
case cortex_m3 = "cortex-m3"
case cortex_m33 = "cortex-m33"
case cortex_m4 = "cortex-m4"
case cortex_m55 = "cortex-m55"
case cortex_m7 = "cortex-m7"
case cortex_r5 = "cortex-r5"
case cortex_r52 = "cortex-r52"
case cortex_r5f = "cortex-r5f"
case max
case sa1100
case sa1110
case ti925t
var prettyValue: String {
switch self {
case .pxa250: return "(deprecated) (pxa250)"
case .pxa255: return "(deprecated) (pxa255)"
case .pxa260: return "(deprecated) (pxa260)"
case .pxa261: return "(deprecated) (pxa261)"
case .pxa262: return "(deprecated) (pxa262)"
case .pxa270: return "(deprecated) (pxa270)"
case .pxa270_a0: return "(deprecated) (pxa270-a0)"
case .pxa270_a1: return "(deprecated) (pxa270-a1)"
case .pxa270_b0: return "(deprecated) (pxa270-b0)"
case .pxa270_b1: return "(deprecated) (pxa270-b1)"
case .pxa270_c0: return "(deprecated) (pxa270-c0)"
case .pxa270_c5: return "(deprecated) (pxa270-c5)"
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .arm1026: return "arm1026"
case .arm1136: return "arm1136"
case .arm1136_r2: return "arm1136-r2"
case .arm1176: return "arm1176"
case .arm11mpcore: return "arm11mpcore"
case .arm926: return "arm926"
case .arm946: return "arm946"
case .cortex_a15: return "cortex-a15"
case .cortex_a7: return "cortex-a7"
case .cortex_a8: return "cortex-a8"
case .cortex_a9: return "cortex-a9"
case .cortex_m0: return "cortex-m0"
case .cortex_m3: return "cortex-m3"
case .cortex_m33: return "cortex-m33"
case .cortex_m4: return "cortex-m4"
case .cortex_m55: return "cortex-m55"
case .cortex_m7: return "cortex-m7"
case .cortex_r5: return "cortex-r5"
case .cortex_r52: return "cortex-r52"
case .cortex_r5f: return "cortex-r5f"
case .max: return "max"
case .sa1100: return "sa1100"
case .sa1110: return "sa1110"
case .ti925t: return "ti925t"
}
}
}
enum QEMUCPU_aarch64: String, CaseIterable, QEMUCPU {
case pxa250
case pxa255
case pxa260
case pxa261
case pxa262
case pxa270
case pxa270_a0 = "pxa270-a0"
case pxa270_a1 = "pxa270-a1"
case pxa270_b0 = "pxa270-b0"
case pxa270_b1 = "pxa270-b1"
case pxa270_c0 = "pxa270-c0"
case pxa270_c5 = "pxa270-c5"
case `default` = "default"
case a64fx
case arm1026
case arm1136
case arm1136_r2 = "arm1136-r2"
case arm1176
case arm11mpcore
case arm926
case arm946
case cortex_a15 = "cortex-a15"
case cortex_a35 = "cortex-a35"
case cortex_a53 = "cortex-a53"
case cortex_a55 = "cortex-a55"
case cortex_a57 = "cortex-a57"
case cortex_a7 = "cortex-a7"
case cortex_a710 = "cortex-a710"
case cortex_a72 = "cortex-a72"
case cortex_a76 = "cortex-a76"
case cortex_a8 = "cortex-a8"
case cortex_a9 = "cortex-a9"
case cortex_m0 = "cortex-m0"
case cortex_m3 = "cortex-m3"
case cortex_m33 = "cortex-m33"
case cortex_m4 = "cortex-m4"
case cortex_m55 = "cortex-m55"
case cortex_m7 = "cortex-m7"
case cortex_r5 = "cortex-r5"
case cortex_r52 = "cortex-r52"
case cortex_r5f = "cortex-r5f"
case host
case max
case neoverse_n1 = "neoverse-n1"
case neoverse_n2 = "neoverse-n2"
case neoverse_v1 = "neoverse-v1"
case sa1100
case sa1110
case ti925t
var prettyValue: String {
switch self {
case .pxa250: return "(deprecated) (pxa250)"
case .pxa255: return "(deprecated) (pxa255)"
case .pxa260: return "(deprecated) (pxa260)"
case .pxa261: return "(deprecated) (pxa261)"
case .pxa262: return "(deprecated) (pxa262)"
case .pxa270: return "(deprecated) (pxa270)"
case .pxa270_a0: return "(deprecated) (pxa270-a0)"
case .pxa270_a1: return "(deprecated) (pxa270-a1)"
case .pxa270_b0: return "(deprecated) (pxa270-b0)"
case .pxa270_b1: return "(deprecated) (pxa270-b1)"
case .pxa270_c0: return "(deprecated) (pxa270-c0)"
case .pxa270_c5: return "(deprecated) (pxa270-c5)"
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .a64fx: return "a64fx"
case .arm1026: return "arm1026"
case .arm1136: return "arm1136"
case .arm1136_r2: return "arm1136-r2"
case .arm1176: return "arm1176"
case .arm11mpcore: return "arm11mpcore"
case .arm926: return "arm926"
case .arm946: return "arm946"
case .cortex_a15: return "cortex-a15"
case .cortex_a35: return "cortex-a35"
case .cortex_a53: return "cortex-a53"
case .cortex_a55: return "cortex-a55"
case .cortex_a57: return "cortex-a57"
case .cortex_a7: return "cortex-a7"
case .cortex_a710: return "cortex-a710"
case .cortex_a72: return "cortex-a72"
case .cortex_a76: return "cortex-a76"
case .cortex_a8: return "cortex-a8"
case .cortex_a9: return "cortex-a9"
case .cortex_m0: return "cortex-m0"
case .cortex_m3: return "cortex-m3"
case .cortex_m33: return "cortex-m33"
case .cortex_m4: return "cortex-m4"
case .cortex_m55: return "cortex-m55"
case .cortex_m7: return "cortex-m7"
case .cortex_r5: return "cortex-r5"
case .cortex_r52: return "cortex-r52"
case .cortex_r5f: return "cortex-r5f"
case .host: return "host"
case .max: return "max"
case .neoverse_n1: return "neoverse-n1"
case .neoverse_n2: return "neoverse-n2"
case .neoverse_v1: return "neoverse-v1"
case .sa1100: return "sa1100"
case .sa1110: return "sa1110"
case .ti925t: return "ti925t"
}
}
}
enum QEMUCPU_avr: String, CaseIterable, QEMUCPU {
case `default` = "default"
case avr5
case avr51
case avr6
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .avr5: return "avr5"
case .avr51: return "avr51"
case .avr6: return "avr6"
}
}
}
enum QEMUCPU_hppa: String, CaseIterable, QEMUCPU {
case `default` = "default"
case hppa_cpu = "hppa-cpu"
case hppa64_cpu = "hppa64-cpu"
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .hppa_cpu: return "hppa-cpu"
case .hppa64_cpu: return "hppa64-cpu"
}
}
}
enum QEMUCPU_i386: String, CaseIterable, QEMUCPU {
case _486 = "486"
case _486_v1 = "486-v1"
case EPYC_v1 = "EPYC-v1"
case EPYC_v3 = "EPYC-v3"
case EPYC_v2 = "EPYC-v2"
case EPYC_Genoa_v1 = "EPYC-Genoa-v1"
case EPYC_Milan_v1 = "EPYC-Milan-v1"
case EPYC_Milan_v2 = "EPYC-Milan-v2"
case EPYC_Rome_v1 = "EPYC-Rome-v1"
case EPYC_Rome_v2 = "EPYC-Rome-v2"
case EPYC_Rome_v3 = "EPYC-Rome-v3"
case EPYC_Rome_v4 = "EPYC-Rome-v4"
case EPYC_v4 = "EPYC-v4"
case Opteron_G2_v1 = "Opteron_G2-v1"
case Opteron_G3_v1 = "Opteron_G3-v1"
case Opteron_G1_v1 = "Opteron_G1-v1"
case Opteron_G4_v1 = "Opteron_G4-v1"
case Opteron_G5_v1 = "Opteron_G5-v1"
case phenom_v1 = "phenom-v1"
case Broadwell
case Broadwell_IBRS = "Broadwell-IBRS"
case Broadwell_noTSX = "Broadwell-noTSX"
case Broadwell_noTSX_IBRS = "Broadwell-noTSX-IBRS"
case Cascadelake_Server = "Cascadelake-Server"
case Cascadelake_Server_noTSX = "Cascadelake-Server-noTSX"
case ClearwaterForest
case kvm32_v1 = "kvm32-v1"
case kvm64_v1 = "kvm64-v1"
case Conroe
case Cooperlake
case `default` = "default"
case Denverton
case Dhyana
case EPYC
case EPYC_Genoa = "EPYC-Genoa"
case EPYC_IBPB = "EPYC-IBPB"
case EPYC_Milan = "EPYC-Milan"
case EPYC_Rome = "EPYC-Rome"
case max
case coreduo_v1 = "coreduo-v1"
case GraniteRapids
case Haswell
case Haswell_IBRS = "Haswell-IBRS"
case Haswell_noTSX = "Haswell-noTSX"
case Haswell_noTSX_IBRS = "Haswell-noTSX-IBRS"
case Dhyana_v1 = "Dhyana-v1"
case Dhyana_v2 = "Dhyana-v2"
case Icelake_Server = "Icelake-Server"
case Icelake_Server_noTSX = "Icelake-Server-noTSX"
case Denverton_v1 = "Denverton-v1"
case Denverton_v3 = "Denverton-v3"
case Denverton_v2 = "Denverton-v2"
case Snowridge_v1 = "Snowridge-v1"
case Snowridge_v2 = "Snowridge-v2"
case Snowridge_v3 = "Snowridge-v3"
case Snowridge_v4 = "Snowridge-v4"
case Conroe_v1 = "Conroe-v1"
case Penryn_v1 = "Penryn-v1"
case Broadwell_v1 = "Broadwell-v1"
case Broadwell_v3 = "Broadwell-v3"
case Broadwell_v2 = "Broadwell-v2"
case Broadwell_v4 = "Broadwell-v4"
case Haswell_v1 = "Haswell-v1"
case Haswell_v3 = "Haswell-v3"
case Haswell_v2 = "Haswell-v2"
case Haswell_v4 = "Haswell-v4"
case Skylake_Client_v1 = "Skylake-Client-v1"
case Skylake_Client_v2 = "Skylake-Client-v2"
case Skylake_Client_v3 = "Skylake-Client-v3"
case Skylake_Client_v4 = "Skylake-Client-v4"
case Nehalem_v1 = "Nehalem-v1"
case Nehalem_v2 = "Nehalem-v2"
case IvyBridge_v1 = "IvyBridge-v1"
case IvyBridge_v2 = "IvyBridge-v2"
case SandyBridge_v1 = "SandyBridge-v1"
case SandyBridge_v2 = "SandyBridge-v2"
case KnightsMill_v1 = "KnightsMill-v1"
case Cascadelake_Server_v1 = "Cascadelake-Server-v1"
case Cascadelake_Server_v5 = "Cascadelake-Server-v5"
case Cascadelake_Server_v4 = "Cascadelake-Server-v4"
case Cascadelake_Server_v3 = "Cascadelake-Server-v3"
case Cascadelake_Server_v2 = "Cascadelake-Server-v2"
case ClearwaterForest_v1 = "ClearwaterForest-v1"
case Cooperlake_v1 = "Cooperlake-v1"
case Cooperlake_v2 = "Cooperlake-v2"
case GraniteRapids_v1 = "GraniteRapids-v1"
case GraniteRapids_v2 = "GraniteRapids-v2"
case Icelake_Server_v1 = "Icelake-Server-v1"
case Icelake_Server_v3 = "Icelake-Server-v3"
case Icelake_Server_v4 = "Icelake-Server-v4"
case Icelake_Server_v6 = "Icelake-Server-v6"
case Icelake_Server_v7 = "Icelake-Server-v7"
case Icelake_Server_v5 = "Icelake-Server-v5"
case Icelake_Server_v2 = "Icelake-Server-v2"
case SapphireRapids_v1 = "SapphireRapids-v1"
case SapphireRapids_v2 = "SapphireRapids-v2"
case SapphireRapids_v3 = "SapphireRapids-v3"
case SierraForest_v1 = "SierraForest-v1"
case SierraForest_v2 = "SierraForest-v2"
case Skylake_Server_v1 = "Skylake-Server-v1"
case Skylake_Server_v2 = "Skylake-Server-v2"
case Skylake_Server_v3 = "Skylake-Server-v3"
case Skylake_Server_v4 = "Skylake-Server-v4"
case Skylake_Server_v5 = "Skylake-Server-v5"
case n270_v1 = "n270-v1"
case core2duo_v1 = "core2duo-v1"
case IvyBridge
case IvyBridge_IBRS = "IvyBridge-IBRS"
case KnightsMill
case Nehalem
case Nehalem_IBRS = "Nehalem-IBRS"
case Opteron_G1
case Opteron_G2
case Opteron_G3
case Opteron_G4
case Opteron_G5
case Penryn
case athlon_v1 = "athlon-v1"
case qemu32_v1 = "qemu32-v1"
case qemu64_v1 = "qemu64-v1"
case SandyBridge
case SandyBridge_IBRS = "SandyBridge-IBRS"
case SapphireRapids
case SierraForest
case Skylake_Client = "Skylake-Client"
case Skylake_Client_IBRS = "Skylake-Client-IBRS"
case Skylake_Client_noTSX_IBRS = "Skylake-Client-noTSX-IBRS"
case Skylake_Server = "Skylake-Server"
case Skylake_Server_IBRS = "Skylake-Server-IBRS"
case Skylake_Server_noTSX_IBRS = "Skylake-Server-noTSX-IBRS"
case Snowridge
case Westmere
case Westmere_v2 = "Westmere-v2"
case Westmere_v1 = "Westmere-v1"
case Westmere_IBRS = "Westmere-IBRS"
case YongFeng
case YongFeng_v1 = "YongFeng-v1"
case YongFeng_v2 = "YongFeng-v2"
case athlon
case base
case core2duo
case coreduo
case kvm32
case kvm64
case n270
case pentium
case pentium_v1 = "pentium-v1"
case pentium2
case pentium2_v1 = "pentium2-v1"
case pentium3
case pentium3_v1 = "pentium3-v1"
case phenom
case qemu32
case qemu64
var prettyValue: String {
switch self {
case ._486: return "486"
case ._486_v1: return "486-v1"
case .EPYC_v1: return "AMD EPYC Processor (EPYC-v1)"
case .EPYC_v3: return "AMD EPYC Processor (EPYC-v3)"
case .EPYC_v2: return "AMD EPYC Processor (with IBPB) (EPYC-v2)"
case .EPYC_Genoa_v1: return "AMD EPYC-Genoa Processor (EPYC-Genoa-v1)"
case .EPYC_Milan_v1: return "AMD EPYC-Milan Processor (EPYC-Milan-v1)"
case .EPYC_Milan_v2: return "AMD EPYC-Milan-v2 Processor (EPYC-Milan-v2)"
case .EPYC_Rome_v1: return "AMD EPYC-Rome Processor (EPYC-Rome-v1)"
case .EPYC_Rome_v2: return "AMD EPYC-Rome Processor (EPYC-Rome-v2)"
case .EPYC_Rome_v3: return "AMD EPYC-Rome-v3 Processor (EPYC-Rome-v3)"
case .EPYC_Rome_v4: return "AMD EPYC-Rome-v4 Processor (no XSAVES) (EPYC-Rome-v4)"
case .EPYC_v4: return "AMD EPYC-v4 Processor (EPYC-v4)"
case .Opteron_G2_v1: return "AMD Opteron 22xx (Gen 2 Class Opteron) (Opteron_G2-v1)"
case .Opteron_G3_v1: return "AMD Opteron 23xx (Gen 3 Class Opteron) (Opteron_G3-v1)"
case .Opteron_G1_v1: return "AMD Opteron 240 (Gen 1 Class Opteron) (Opteron_G1-v1)"
case .Opteron_G4_v1: return "AMD Opteron 62xx class CPU (Opteron_G4-v1)"
case .Opteron_G5_v1: return "AMD Opteron 63xx class CPU (Opteron_G5-v1)"
case .phenom_v1: return "AMD Phenom(tm) 9550 Quad-Core Processor (phenom-v1)"
case .Broadwell: return "Broadwell"
case .Broadwell_IBRS: return "Broadwell-IBRS"
case .Broadwell_noTSX: return "Broadwell-noTSX"
case .Broadwell_noTSX_IBRS: return "Broadwell-noTSX-IBRS"
case .Cascadelake_Server: return "Cascadelake-Server"
case .Cascadelake_Server_noTSX: return "Cascadelake-Server-noTSX"
case .ClearwaterForest: return "ClearwaterForest"
case .kvm32_v1: return "Common 32-bit KVM processor (kvm32-v1)"
case .kvm64_v1: return "Common KVM processor (kvm64-v1)"
case .Conroe: return "Conroe"
case .Cooperlake: return "Cooperlake"
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .Denverton: return "Denverton"
case .Dhyana: return "Dhyana"
case .EPYC: return "EPYC"
case .EPYC_Genoa: return "EPYC-Genoa"
case .EPYC_IBPB: return "EPYC-IBPB"
case .EPYC_Milan: return "EPYC-Milan"
case .EPYC_Rome: return "EPYC-Rome"
case .max: return "Enables all features supported by the accelerator in the current host (max)"
case .coreduo_v1: return "Genuine Intel(R) CPU T2600 @ 2.16GHz (coreduo-v1)"
case .GraniteRapids: return "GraniteRapids"
case .Haswell: return "Haswell"
case .Haswell_IBRS: return "Haswell-IBRS"
case .Haswell_noTSX: return "Haswell-noTSX"
case .Haswell_noTSX_IBRS: return "Haswell-noTSX-IBRS"
case .Dhyana_v1: return "Hygon Dhyana Processor (Dhyana-v1)"
case .Dhyana_v2: return "Hygon Dhyana Processor [XSAVES] (Dhyana-v2)"
case .Icelake_Server: return "Icelake-Server"
case .Icelake_Server_noTSX: return "Icelake-Server-noTSX"
case .Denverton_v1: return "Intel Atom Processor (Denverton) (Denverton-v1)"
case .Denverton_v3: return "Intel Atom Processor (Denverton) [XSAVES, no MPX, no MONITOR] (Denverton-v3)"
case .Denverton_v2: return "Intel Atom Processor (Denverton) [no MPX, no MONITOR] (Denverton-v2)"
case .Snowridge_v1: return "Intel Atom Processor (SnowRidge) (Snowridge-v1)"
case .Snowridge_v2: return "Intel Atom Processor (Snowridge, no MPX) (Snowridge-v2)"
case .Snowridge_v3: return "Intel Atom Processor (Snowridge, no MPX) [XSAVES, no MPX] (Snowridge-v3)"
case .Snowridge_v4: return "Intel Atom Processor (Snowridge, no MPX) [no split lock detect, no core-capability] (Snowridge-v4)"
case .Conroe_v1: return "Intel Celeron_4x0 (Conroe/Merom Class Core 2) (Conroe-v1)"
case .Penryn_v1: return "Intel Core 2 Duo P9xxx (Penryn Class Core 2) (Penryn-v1)"
case .Broadwell_v1: return "Intel Core Processor (Broadwell) (Broadwell-v1)"
case .Broadwell_v3: return "Intel Core Processor (Broadwell, IBRS) (Broadwell-v3)"
case .Broadwell_v2: return "Intel Core Processor (Broadwell, no TSX) (Broadwell-v2)"
case .Broadwell_v4: return "Intel Core Processor (Broadwell, no TSX, IBRS) (Broadwell-v4)"
case .Haswell_v1: return "Intel Core Processor (Haswell) (Haswell-v1)"
case .Haswell_v3: return "Intel Core Processor (Haswell, IBRS) (Haswell-v3)"
case .Haswell_v2: return "Intel Core Processor (Haswell, no TSX) (Haswell-v2)"
case .Haswell_v4: return "Intel Core Processor (Haswell, no TSX, IBRS) (Haswell-v4)"
case .Skylake_Client_v1: return "Intel Core Processor (Skylake) (Skylake-Client-v1)"
case .Skylake_Client_v2: return "Intel Core Processor (Skylake, IBRS) (Skylake-Client-v2)"
case .Skylake_Client_v3: return "Intel Core Processor (Skylake, IBRS, no TSX) (Skylake-Client-v3)"
case .Skylake_Client_v4: return "Intel Core Processor (Skylake, IBRS, no TSX) [IBRS, XSAVES, no TSX] (Skylake-Client-v4)"
case .Nehalem_v1: return "Intel Core i7 9xx (Nehalem Class Core i7) (Nehalem-v1)"
case .Nehalem_v2: return "Intel Core i7 9xx (Nehalem Core i7, IBRS update) (Nehalem-v2)"
case .IvyBridge_v1: return "Intel Xeon E3-12xx v2 (Ivy Bridge) (IvyBridge-v1)"
case .IvyBridge_v2: return "Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS) (IvyBridge-v2)"
case .SandyBridge_v1: return "Intel Xeon E312xx (Sandy Bridge) (SandyBridge-v1)"
case .SandyBridge_v2: return "Intel Xeon E312xx (Sandy Bridge, IBRS update) (SandyBridge-v2)"
case .KnightsMill_v1: return "Intel Xeon Phi Processor (Knights Mill) (KnightsMill-v1)"
case .Cascadelake_Server_v1: return "Intel Xeon Processor (Cascadelake) (Cascadelake-Server-v1)"
case .Cascadelake_Server_v5: return "Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES, EPT switching, XSAVES, no TSX] (Cascadelake-Server-v5)"
case .Cascadelake_Server_v4: return "Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES, EPT switching, no TSX] (Cascadelake-Server-v4)"
case .Cascadelake_Server_v3: return "Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES, no TSX] (Cascadelake-Server-v3)"
case .Cascadelake_Server_v2: return "Intel Xeon Processor (Cascadelake) [ARCH_CAPABILITIES] (Cascadelake-Server-v2)"
case .ClearwaterForest_v1: return "Intel Xeon Processor (ClearwaterForest) (ClearwaterForest-v1)"
case .Cooperlake_v1: return "Intel Xeon Processor (Cooperlake) (Cooperlake-v1)"
case .Cooperlake_v2: return "Intel Xeon Processor (Cooperlake) [XSAVES] (Cooperlake-v2)"
case .GraniteRapids_v1: return "Intel Xeon Processor (GraniteRapids) (GraniteRapids-v1)"
case .GraniteRapids_v2: return "Intel Xeon Processor (GraniteRapids) (GraniteRapids-v2)"
case .Icelake_Server_v1: return "Intel Xeon Processor (Icelake) (Icelake-Server-v1)"
case .Icelake_Server_v3: return "Intel Xeon Processor (Icelake) (Icelake-Server-v3)"
case .Icelake_Server_v4: return "Intel Xeon Processor (Icelake) (Icelake-Server-v4)"
case .Icelake_Server_v6: return "Intel Xeon Processor (Icelake) [5-level EPT] (Icelake-Server-v6)"
case .Icelake_Server_v7: return "Intel Xeon Processor (Icelake) [TSX, taa-no] (Icelake-Server-v7)"
case .Icelake_Server_v5: return "Intel Xeon Processor (Icelake) [XSAVES] (Icelake-Server-v5)"
case .Icelake_Server_v2: return "Intel Xeon Processor (Icelake) [no TSX] (Icelake-Server-v2)"
case .SapphireRapids_v1: return "Intel Xeon Processor (SapphireRapids) (SapphireRapids-v1)"
case .SapphireRapids_v2: return "Intel Xeon Processor (SapphireRapids) (SapphireRapids-v2)"
case .SapphireRapids_v3: return "Intel Xeon Processor (SapphireRapids) (SapphireRapids-v3)"
case .SierraForest_v1: return "Intel Xeon Processor (SierraForest) (SierraForest-v1)"
case .SierraForest_v2: return "Intel Xeon Processor (SierraForest) (SierraForest-v2)"
case .Skylake_Server_v1: return "Intel Xeon Processor (Skylake) (Skylake-Server-v1)"
case .Skylake_Server_v2: return "Intel Xeon Processor (Skylake, IBRS) (Skylake-Server-v2)"
case .Skylake_Server_v3: return "Intel Xeon Processor (Skylake, IBRS, no TSX) (Skylake-Server-v3)"
case .Skylake_Server_v4: return "Intel Xeon Processor (Skylake, IBRS, no TSX) [IBRS, EPT switching, no TSX] (Skylake-Server-v4)"
case .Skylake_Server_v5: return "Intel Xeon Processor (Skylake, IBRS, no TSX) [IBRS, XSAVES, EPT switching, no TSX] (Skylake-Server-v5)"
case .n270_v1: return "Intel(R) Atom(TM) CPU N270 @ 1.60GHz (n270-v1)"
case .core2duo_v1: return "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz (core2duo-v1)"
case .IvyBridge: return "IvyBridge"
case .IvyBridge_IBRS: return "IvyBridge-IBRS"
case .KnightsMill: return "KnightsMill"
case .Nehalem: return "Nehalem"
case .Nehalem_IBRS: return "Nehalem-IBRS"
case .Opteron_G1: return "Opteron_G1"
case .Opteron_G2: return "Opteron_G2"
case .Opteron_G3: return "Opteron_G3"
case .Opteron_G4: return "Opteron_G4"
case .Opteron_G5: return "Opteron_G5"
case .Penryn: return "Penryn"
case .athlon_v1: return "QEMU Virtual CPU version 2.5+ (athlon-v1)"
case .qemu32_v1: return "QEMU Virtual CPU version 2.5+ (qemu32-v1)"
case .qemu64_v1: return "QEMU Virtual CPU version 2.5+ (qemu64-v1)"
case .SandyBridge: return "SandyBridge"
case .SandyBridge_IBRS: return "SandyBridge-IBRS"
case .SapphireRapids: return "SapphireRapids"
case .SierraForest: return "SierraForest"
case .Skylake_Client: return "Skylake-Client"
case .Skylake_Client_IBRS: return "Skylake-Client-IBRS"
case .Skylake_Client_noTSX_IBRS: return "Skylake-Client-noTSX-IBRS"
case .Skylake_Server: return "Skylake-Server"
case .Skylake_Server_IBRS: return "Skylake-Server-IBRS"
case .Skylake_Server_noTSX_IBRS: return "Skylake-Server-noTSX-IBRS"
case .Snowridge: return "Snowridge"
case .Westmere: return "Westmere"
case .Westmere_v2: return "Westmere E56xx/L56xx/X56xx (IBRS update) (Westmere-v2)"
case .Westmere_v1: return "Westmere E56xx/L56xx/X56xx (Nehalem-C) (Westmere-v1)"
case .Westmere_IBRS: return "Westmere-IBRS"
case .YongFeng: return "YongFeng"
case .YongFeng_v1: return "Zhaoxin YongFeng Processor (YongFeng-v1)"
case .YongFeng_v2: return "Zhaoxin YongFeng Processor [with the correct model number] (YongFeng-v2)"
case .athlon: return "athlon"
case .base: return "base CPU model type with no features enabled (base)"
case .core2duo: return "core2duo"
case .coreduo: return "coreduo"
case .kvm32: return "kvm32"
case .kvm64: return "kvm64"
case .n270: return "n270"
case .pentium: return "pentium"
case .pentium_v1: return "pentium-v1"
case .pentium2: return "pentium2"
case .pentium2_v1: return "pentium2-v1"
case .pentium3: return "pentium3"
case .pentium3_v1: return "pentium3-v1"
case .phenom: return "phenom"
case .qemu32: return "qemu32"
case .qemu64: return "qemu64"
}
}
}
enum QEMUCPU_loongarch64: String, CaseIterable, QEMUCPU {
case `default` = "default"
case la132
case la464
case max
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .la132: return "la132"
case .la464: return "la464"
case .max: return "max"
}
}
}
enum QEMUCPU_m68k: String, CaseIterable, QEMUCPU {
case `default` = "default"
case any
case cfv4e
case m5206
case m5208
case m68000
case m68010
case m68020
case m68030
case m68040
case m68060
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .any: return "any"
case .cfv4e: return "cfv4e"
case .m5206: return "m5206"
case .m5208: return "m5208"
case .m68000: return "m68000"
case .m68010: return "m68010"
case .m68020: return "m68020"
case .m68030: return "m68030"
case .m68040: return "m68040"
case .m68060: return "m68060"
}
}
}
enum QEMUCPU_microblaze: String, CaseIterable, QEMUCPU {
case `default` = "default"
case microblaze_cpu = "microblaze-cpu"
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .microblaze_cpu: return "microblaze-cpu"
}
}
}
enum QEMUCPU_microblazeel: String, CaseIterable, QEMUCPU {
case `default` = "default"
case microblaze_cpu = "microblaze-cpu"
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .microblaze_cpu: return "microblaze-cpu"
}
}
}
enum QEMUCPU_mips: String, CaseIterable, QEMUCPU {
case _24KEc = "24KEc"
case _24Kc = "24Kc"
case _24Kf = "24Kf"
case _34Kf = "34Kf"
case _4KEc = "4KEc"
case _4KEcR1 = "4KEcR1"
case _4KEm = "4KEm"
case _4KEmR1 = "4KEmR1"
case _4Kc = "4Kc"
case _4Km = "4Km"
case _74Kf = "74Kf"
case `default` = "default"
case I7200
case M14K
case M14Kc
case P5600
case XBurstR1
case XBurstR2
case mips32r6_generic = "mips32r6-generic"
var prettyValue: String {
switch self {
case ._24KEc: return "24KEc"
case ._24Kc: return "24Kc"
case ._24Kf: return "24Kf"
case ._34Kf: return "34Kf"
case ._4KEc: return "4KEc"
case ._4KEcR1: return "4KEcR1"
case ._4KEm: return "4KEm"
case ._4KEmR1: return "4KEmR1"
case ._4Kc: return "4Kc"
case ._4Km: return "4Km"
case ._74Kf: return "74Kf"
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .I7200: return "I7200"
case .M14K: return "M14K"
case .M14Kc: return "M14Kc"
case .P5600: return "P5600"
case .XBurstR1: return "XBurstR1"
case .XBurstR2: return "XBurstR2"
case .mips32r6_generic: return "mips32r6-generic"
}
}
}
enum QEMUCPU_mipsel: String, CaseIterable, QEMUCPU {
case _24KEc = "24KEc"
case _24Kc = "24Kc"
case _24Kf = "24Kf"
case _34Kf = "34Kf"
case _4KEc = "4KEc"
case _4KEcR1 = "4KEcR1"
case _4KEm = "4KEm"
case _4KEmR1 = "4KEmR1"
case _4Kc = "4Kc"
case _4Km = "4Km"
case _74Kf = "74Kf"
case `default` = "default"
case I7200
case M14K
case M14Kc
case P5600
case XBurstR1
case XBurstR2
case mips32r6_generic = "mips32r6-generic"
var prettyValue: String {
switch self {
case ._24KEc: return "24KEc"
case ._24Kc: return "24Kc"
case ._24Kf: return "24Kf"
case ._34Kf: return "34Kf"
case ._4KEc: return "4KEc"
case ._4KEcR1: return "4KEcR1"
case ._4KEm: return "4KEm"
case ._4KEmR1: return "4KEmR1"
case ._4Kc: return "4Kc"
case ._4Km: return "4Km"
case ._74Kf: return "74Kf"
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .I7200: return "I7200"
case .M14K: return "M14K"
case .M14Kc: return "M14Kc"
case .P5600: return "P5600"
case .XBurstR1: return "XBurstR1"
case .XBurstR2: return "XBurstR2"
case .mips32r6_generic: return "mips32r6-generic"
}
}
}
enum QEMUCPU_mips64: String, CaseIterable, QEMUCPU {
case _20Kc = "20Kc"
case _24KEc = "24KEc"
case _24Kc = "24Kc"
case _24Kf = "24Kf"
case _34Kf = "34Kf"
case _4KEc = "4KEc"
case _4KEcR1 = "4KEcR1"
case _4KEm = "4KEm"
case _4KEmR1 = "4KEmR1"
case _4Kc = "4Kc"
case _4Km = "4Km"
case _5KEc = "5KEc"
case _5KEf = "5KEf"
case _5Kc = "5Kc"
case _5Kf = "5Kf"
case _74Kf = "74Kf"
case `default` = "default"
case I6400
case I6500
case I7200
case Loongson_2E = "Loongson-2E"
case Loongson_2F = "Loongson-2F"
case Loongson_3A1000 = "Loongson-3A1000"
case Loongson_3A4000 = "Loongson-3A4000"
case M14K
case M14Kc
case MIPS64R2_generic = "MIPS64R2-generic"
case Octeon68XX
case P5600
case R4000
case VR5432
case XBurstR1
case XBurstR2
case mips32r6_generic = "mips32r6-generic"
case mips64dspr2
var prettyValue: String {
switch self {
case ._20Kc: return "20Kc"
case ._24KEc: return "24KEc"
case ._24Kc: return "24Kc"
case ._24Kf: return "24Kf"
case ._34Kf: return "34Kf"
case ._4KEc: return "4KEc"
case ._4KEcR1: return "4KEcR1"
case ._4KEm: return "4KEm"
case ._4KEmR1: return "4KEmR1"
case ._4Kc: return "4Kc"
case ._4Km: return "4Km"
case ._5KEc: return "5KEc"
case ._5KEf: return "5KEf"
case ._5Kc: return "5Kc"
case ._5Kf: return "5Kf"
case ._74Kf: return "74Kf"
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .I6400: return "I6400"
case .I6500: return "I6500"
case .I7200: return "I7200"
case .Loongson_2E: return "Loongson-2E"
case .Loongson_2F: return "Loongson-2F"
case .Loongson_3A1000: return "Loongson-3A1000"
case .Loongson_3A4000: return "Loongson-3A4000"
case .M14K: return "M14K"
case .M14Kc: return "M14Kc"
case .MIPS64R2_generic: return "MIPS64R2-generic"
case .Octeon68XX: return "Octeon68XX"
case .P5600: return "P5600"
case .R4000: return "R4000"
case .VR5432: return "VR5432"
case .XBurstR1: return "XBurstR1"
case .XBurstR2: return "XBurstR2"
case .mips32r6_generic: return "mips32r6-generic"
case .mips64dspr2: return "mips64dspr2"
}
}
}
enum QEMUCPU_mips64el: String, CaseIterable, QEMUCPU {
case _20Kc = "20Kc"
case _24KEc = "24KEc"
case _24Kc = "24Kc"
case _24Kf = "24Kf"
case _34Kf = "34Kf"
case _4KEc = "4KEc"
case _4KEcR1 = "4KEcR1"
case _4KEm = "4KEm"
case _4KEmR1 = "4KEmR1"
case _4Kc = "4Kc"
case _4Km = "4Km"
case _5KEc = "5KEc"
case _5KEf = "5KEf"
case _5Kc = "5Kc"
case _5Kf = "5Kf"
case _74Kf = "74Kf"
case `default` = "default"
case I6400
case I6500
case I7200
case Loongson_2E = "Loongson-2E"
case Loongson_2F = "Loongson-2F"
case Loongson_3A1000 = "Loongson-3A1000"
case Loongson_3A4000 = "Loongson-3A4000"
case M14K
case M14Kc
case MIPS64R2_generic = "MIPS64R2-generic"
case Octeon68XX
case P5600
case R4000
case VR5432
case XBurstR1
case XBurstR2
case mips32r6_generic = "mips32r6-generic"
case mips64dspr2
var prettyValue: String {
switch self {
case ._20Kc: return "20Kc"
case ._24KEc: return "24KEc"
case ._24Kc: return "24Kc"
case ._24Kf: return "24Kf"
case ._34Kf: return "34Kf"
case ._4KEc: return "4KEc"
case ._4KEcR1: return "4KEcR1"
case ._4KEm: return "4KEm"
case ._4KEmR1: return "4KEmR1"
case ._4Kc: return "4Kc"
case ._4Km: return "4Km"
case ._5KEc: return "5KEc"
case ._5KEf: return "5KEf"
case ._5Kc: return "5Kc"
case ._5Kf: return "5Kf"
case ._74Kf: return "74Kf"
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .I6400: return "I6400"
case .I6500: return "I6500"
case .I7200: return "I7200"
case .Loongson_2E: return "Loongson-2E"
case .Loongson_2F: return "Loongson-2F"
case .Loongson_3A1000: return "Loongson-3A1000"
case .Loongson_3A4000: return "Loongson-3A4000"
case .M14K: return "M14K"
case .M14Kc: return "M14Kc"
case .MIPS64R2_generic: return "MIPS64R2-generic"
case .Octeon68XX: return "Octeon68XX"
case .P5600: return "P5600"
case .R4000: return "R4000"
case .VR5432: return "VR5432"
case .XBurstR1: return "XBurstR1"
case .XBurstR2: return "XBurstR2"
case .mips32r6_generic: return "mips32r6-generic"
case .mips64dspr2: return "mips64dspr2"
}
}
}
enum QEMUCPU_or1k: String, CaseIterable, QEMUCPU {
case `default` = "default"
case any
case or1200
var prettyValue: String {
switch self {
case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
case .any: return "any"
case .or1200: return "or1200"
}
}
}
enum QEMUCPU_ppc: String, CaseIterable, QEMUCPU {
case _405 = "405"
case _405cr = "405cr"
case _405gp = "405gp"
case _405gpe = "405gpe"
case _440ep = "440ep"
case _460ex = "460ex"
case _603e = "603e"
case _603r = "603r"
case _604e = "604e"
case _740 = "740"
case _7400 = "7400"
case _7410 = "7410"
case _7441 = "7441"
case _7445 = "7445"
case _7447 = "7447"
case _7447a = "7447a"
case _7448 = "7448"
case _745 = "745"
case _7450 = "7450"
case _7451 = "7451"
case _7455 = "7455"
case _7457 = "7457"
case _7457a = "7457a"
case _750 = "750"
case _750cl = "750cl"
case _750cx = "750cx"
case _750cxe = "750cxe"
case _750fx = "750fx"
case _750gx = "750gx"
case _750l = "750l"
case _755 = "755"
case `default` = "default"
case _603 = "603"
case _604 = "604"
case _603e_v1_1 = "603e_v1.1"
case _603e_v1_2 = "603e_v1.2"
case _603e_v1_3 = "603e_v1.3"
case _603e_v1_4 = "603e_v1.4"
case _603e_v2_2 = "603e_v2.2"
case _603e_v3 = "603e_v3"
case _603e_v4 = "603e_v4"
case _603e_v4_1 = "603e_v4.1"
case _603p = "603p"
case _603e7v = "603e7v"
case _603e7v1 = "603e7v1"
case _603e7 = "603e7"
case _603e7v2 = "603e7v2"
case _603e7t = "603e7t"
case _740_v1_0 = "740_v1.0"
case _740e = "740e"
case _750_v1_0 = "750_v1.0"
case _740_v2_0 = "740_v2.0"
case _750_v2_0 = "750_v2.0"
case _750e = "750e"
case _740_v2_1 = "740_v2.1"
case _750_v2_1 = "750_v2.1"
case _740_v2_2 = "740_v2.2"
case _750_v2_2 = "750_v2.2"
case _740_v3_0 = "740_v3.0"
case _750_v3_0 = "750_v3.0"
case _740_v3_1 = "740_v3.1"
case _750_v3_1 = "750_v3.1"
case _750cx_v1_0 = "750cx_v1.0"
case _750cx_v2_0 = "750cx_v2.0"
case _750cx_v2_1 = "750cx_v2.1"
case _750cx_v2_2 = "750cx_v2.2"
case _750cxe_v2_1 = "750cxe_v2.1"
case _750cxe_v2_2 = "750cxe_v2.2"
case _750cxe_v2_3 = "750cxe_v2.3"
case _750cxe_v2_4 = "750cxe_v2.4"
case _750cxe_v3_0 = "750cxe_v3.0"
case _750cxe_v3_1 = "750cxe_v3.1"
case _745_v1_0 = "745_v1.0"
case _755_v1_0 = "755_v1.0"
ca
gitextract_miqecj8q/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── bug_report_macos.md
│ │ └── feature_request.md
│ └── workflows/
│ ├── build.yml
│ └── issues.yml
├── .gitignore
├── Build.xcconfig
├── CONTRIBUTING.md
├── CodeSigning.xcconfig.sample
├── Configuration/
│ ├── Legacy/
│ │ ├── UTMLegacyAppleConfiguration.swift
│ │ ├── UTMLegacyQemuConfiguration+Constants.h
│ │ ├── UTMLegacyQemuConfiguration+Constants.m
│ │ ├── UTMLegacyQemuConfiguration+Display.h
│ │ ├── UTMLegacyQemuConfiguration+Display.m
│ │ ├── UTMLegacyQemuConfiguration+Drives.h
│ │ ├── UTMLegacyQemuConfiguration+Drives.m
│ │ ├── UTMLegacyQemuConfiguration+Miscellaneous.h
│ │ ├── UTMLegacyQemuConfiguration+Miscellaneous.m
│ │ ├── UTMLegacyQemuConfiguration+Networking.h
│ │ ├── UTMLegacyQemuConfiguration+Networking.m
│ │ ├── UTMLegacyQemuConfiguration+Sharing.h
│ │ ├── UTMLegacyQemuConfiguration+Sharing.m
│ │ ├── UTMLegacyQemuConfiguration+System.h
│ │ ├── UTMLegacyQemuConfiguration+System.m
│ │ ├── UTMLegacyQemuConfiguration.h
│ │ ├── UTMLegacyQemuConfiguration.m
│ │ ├── UTMLegacyQemuConfigurationPortForward.h
│ │ ├── UTMLegacyQemuConfigurationPortForward.m
│ │ ├── UTMLegacyViewState.h
│ │ └── UTMLegacyViewState.m
│ ├── QEMUArgument.swift
│ ├── QEMUArgumentBuilder.swift
│ ├── QEMUConstant.swift
│ ├── QEMUConstantGenerated.swift
│ ├── UTMAppleConfiguration.swift
│ ├── UTMAppleConfigurationBoot.swift
│ ├── UTMAppleConfigurationDisplay.swift
│ ├── UTMAppleConfigurationDrive.swift
│ ├── UTMAppleConfigurationGenericPlatform.swift
│ ├── UTMAppleConfigurationMacPlatform.swift
│ ├── UTMAppleConfigurationNetwork.swift
│ ├── UTMAppleConfigurationSerial.swift
│ ├── UTMAppleConfigurationSharedDirectory.swift
│ ├── UTMAppleConfigurationSystem.swift
│ ├── UTMAppleConfigurationVirtualization.swift
│ ├── UTMConfiguration.swift
│ ├── UTMConfigurationDrive.swift
│ ├── UTMConfigurationHostNetwork.swift
│ ├── UTMConfigurationInfo.swift
│ ├── UTMConfigurationTerminal.swift
│ ├── UTMQemuConfiguration+Arguments.swift
│ ├── UTMQemuConfiguration.swift
│ ├── UTMQemuConfigurationDisplay.swift
│ ├── UTMQemuConfigurationDrive.swift
│ ├── UTMQemuConfigurationInput.swift
│ ├── UTMQemuConfigurationNetwork.swift
│ ├── UTMQemuConfigurationPortForward.swift
│ ├── UTMQemuConfigurationQEMU.swift
│ ├── UTMQemuConfigurationSerial.swift
│ ├── UTMQemuConfigurationSharing.swift
│ ├── UTMQemuConfigurationSound.swift
│ └── UTMQemuConfigurationSystem.swift
├── Documentation/
│ ├── Architecture.md
│ ├── Dependencies.md
│ ├── Graphics.md
│ ├── MacDevelopment.md
│ ├── Release.md
│ ├── TetheredLaunch.md
│ ├── TetheredLaunch.zh-HK.md
│ ├── TetheredLaunch.zh-Hans.md
│ ├── TetheredLaunch.zh-Hant.md
│ └── iOSDevelopment.md
├── Intents/
│ ├── UTMActionIntent.swift
│ ├── UTMInputIntent.swift
│ ├── UTMIntent.swift
│ ├── UTMVirtualMachineEntity.swift
│ └── UTMVirtualMachineEntityQuery.swift
├── JailbreakInterposer/
│ ├── Info.plist
│ └── JailbreakInterposer.c
├── LICENSE
├── Platform/
│ ├── AppIcon-Remote.icon/
│ │ └── icon.json
│ ├── AppIcon.icon/
│ │ └── icon.json
│ ├── Assets.xcassets/
│ │ ├── AccentColor-Remote.colorset/
│ │ │ └── Contents.json
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Remote.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Remote.solidimagestack/
│ │ │ ├── Back.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Front.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ └── Middle.solidimagestacklayer/
│ │ │ ├── Content.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.solidimagestack/
│ │ │ ├── Back.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Front.solidimagestacklayer/
│ │ │ │ ├── Content.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ └── Middle.solidimagestacklayer/
│ │ │ ├── Content.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── Keyboard Hide.imageset/
│ │ │ └── Contents.json
│ │ ├── Keyboard Paste.imageset/
│ │ │ └── Contents.json
│ │ ├── Logo-Linux.imageset/
│ │ │ └── Contents.json
│ │ ├── Logo-Windows.imageset/
│ │ │ └── Contents.json
│ │ ├── Logo-macOS.imageset/
│ │ │ └── Contents.json
│ │ ├── MenuBarExtra.imageset/
│ │ │ └── Contents.json
│ │ └── Toolbar USB.imageset/
│ │ └── Contents.json
│ ├── Main.swift
│ ├── Shared/
│ │ ├── BigButtonStyle.swift
│ │ ├── BusyIndicator.swift
│ │ ├── BusyOverlay.swift
│ │ ├── ContentView.swift
│ │ ├── DefaultTextField.swift
│ │ ├── DestructiveButton.swift
│ │ ├── DetailedSection.swift
│ │ ├── FileBrowseField.swift
│ │ ├── GlobalFileImporter.swift
│ │ ├── InListButtonStyle.swift
│ │ ├── MacDeviceLabel.swift
│ │ ├── MenuLabel.swift
│ │ ├── NumberTextField.swift
│ │ ├── RAMSlider.swift
│ │ ├── SizeTextField.swift
│ │ ├── Spinner.swift
│ │ ├── UTMPendingVMView.swift
│ │ ├── UTMPlaceholderVMView.swift
│ │ ├── UTMTips.swift
│ │ ├── UTMUnavailableVMView.swift
│ │ ├── VMCardView.swift
│ │ ├── VMCommands.swift
│ │ ├── VMConfigAdvancedNetworkView.swift
│ │ ├── VMConfigConstantPicker.swift
│ │ ├── VMConfigDisplayConsoleView.swift
│ │ ├── VMConfigDisplayView.swift
│ │ ├── VMConfigDriveCreateView.swift
│ │ ├── VMConfigDriveDetailsView.swift
│ │ ├── VMConfigInfoView.swift
│ │ ├── VMConfigInputView.swift
│ │ ├── VMConfigNetworkView.swift
│ │ ├── VMConfigPortForwardForm.swift
│ │ ├── VMConfigQEMUView.swift
│ │ ├── VMConfigSerialView.swift
│ │ ├── VMConfigSharingView.swift
│ │ ├── VMConfigSoundView.swift
│ │ ├── VMConfigSystemView.swift
│ │ ├── VMConfirmActionModifier.swift
│ │ ├── VMContextMenuModifier.swift
│ │ ├── VMDetailsView.swift
│ │ ├── VMKeyboardMap.h
│ │ ├── VMKeyboardMap.m
│ │ ├── VMNavigationListView.swift
│ │ ├── VMPlaceholderView.swift
│ │ ├── VMReleaseNotesView.swift
│ │ ├── VMRemovableDrivesView.swift
│ │ ├── VMSettingsAddDeviceMenuView.swift
│ │ ├── VMShareFileModifier.swift
│ │ ├── VMToolbarModifier.swift
│ │ ├── VMWizardContent.swift
│ │ ├── VMWizardDrivesView.swift
│ │ ├── VMWizardHardwareView.swift
│ │ ├── VMWizardOSClassicMacView.swift
│ │ ├── VMWizardOSLinuxView.swift
│ │ ├── VMWizardOSMacView.swift
│ │ ├── VMWizardOSOtherView.swift
│ │ ├── VMWizardOSView.swift
│ │ ├── VMWizardOSWindowsView.swift
│ │ ├── VMWizardSharingView.swift
│ │ ├── VMWizardStartView.swift
│ │ ├── VMWizardStartViewTCI.swift
│ │ ├── VMWizardState.swift
│ │ └── VMWizardSummaryView.swift
│ ├── UTMData.swift
│ ├── UTMDownloadIPSWTask.swift
│ ├── UTMDownloadMacSupportToolsTask.swift
│ ├── UTMDownloadSupportToolsTask.swift
│ ├── UTMDownloadTask.swift
│ ├── UTMDownloadVMTask.swift
│ ├── UTMPendingVirtualMachine.swift
│ ├── UTMReleaseHelper.swift
│ ├── VMData.swift
│ ├── ar.lproj/
│ │ └── Localizable.strings
│ ├── de.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── en.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── es-419.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── fi.lproj/
│ │ └── Localizable.strings
│ ├── fr.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── iOS/
│ │ ├── ActivityView.swift
│ │ ├── Display/
│ │ │ ├── Base.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.xib
│ │ │ ├── VMCursor.h
│ │ │ ├── VMCursor.m
│ │ │ ├── VMDisplayMetalViewController+Gamepad.h
│ │ │ ├── VMDisplayMetalViewController+Gamepad.m
│ │ │ ├── VMDisplayMetalViewController+Keyboard.h
│ │ │ ├── VMDisplayMetalViewController+Keyboard.m
│ │ │ ├── VMDisplayMetalViewController+Pencil.h
│ │ │ ├── VMDisplayMetalViewController+Pencil.m
│ │ │ ├── VMDisplayMetalViewController+Pointer.h
│ │ │ ├── VMDisplayMetalViewController+Pointer.m
│ │ │ ├── VMDisplayMetalViewController+Private.h
│ │ │ ├── VMDisplayMetalViewController+Touch.h
│ │ │ ├── VMDisplayMetalViewController+Touch.m
│ │ │ ├── VMDisplayMetalViewController.h
│ │ │ ├── VMDisplayMetalViewController.m
│ │ │ ├── VMDisplayTerminalViewController.swift
│ │ │ ├── VMDisplayViewController.h
│ │ │ ├── VMDisplayViewController.m
│ │ │ ├── VMDisplayViewController.swift
│ │ │ ├── VMDisplayViewControllerDelegate.swift
│ │ │ ├── VMKeyboardButton.h
│ │ │ ├── VMKeyboardButton.m
│ │ │ ├── VMKeyboardView.h
│ │ │ ├── VMKeyboardView.m
│ │ │ ├── VMKeyboardViewDelegate.h
│ │ │ ├── VMScroll.h
│ │ │ ├── VMScroll.m
│ │ │ ├── de.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── es-419.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── fi.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── fr.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── ja.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── ko.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── pl.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── zh-HK.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ ├── zh-Hans.lproj/
│ │ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ │ └── zh-Hant.lproj/
│ │ │ └── VMDisplayMetalViewInputAccessory.strings
│ │ ├── Donation.storekit
│ │ ├── IASKAppSettings.swift
│ │ ├── ImagePicker.swift
│ │ ├── Info-Remote.plist
│ │ ├── Info.plist
│ │ ├── Legacy/
│ │ │ └── VMConfigNewStorageViewController.m
│ │ ├── PrivacyInfo.xcprivacy
│ │ ├── RemoteContentView.swift
│ │ ├── Settings.bundle/
│ │ │ ├── License.plist
│ │ │ ├── Root.plist
│ │ │ ├── de.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── en.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── es-419.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── ja.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── ko.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── zh-HK.lproj/
│ │ │ │ └── Root.strings
│ │ │ ├── zh-Hans.lproj/
│ │ │ │ └── Root.strings
│ │ │ └── zh-Hant.lproj/
│ │ │ └── Root.strings
│ │ ├── UTMApp.swift
│ │ ├── UTMDataExtension.swift
│ │ ├── UTMDonateStore.swift
│ │ ├── UTMDonateView.swift
│ │ ├── UTMExternalSceneDelegate.swift
│ │ ├── UTMPatches.swift
│ │ ├── UTMRemoteConnectView.swift
│ │ ├── UTMSettingsView.swift
│ │ ├── UTMSingleWindowView.swift
│ │ ├── VMConfigNetworkPortForwardView.swift
│ │ ├── VMDisplayHostedView.swift
│ │ ├── VMDrivesSettingsView.swift
│ │ ├── VMKeyboardShortcutsView.swift
│ │ ├── VMSessionState.swift
│ │ ├── VMSettingsView.swift
│ │ ├── VMToolbarDisplayMenuView.swift
│ │ ├── VMToolbarDriveMenuView.swift
│ │ ├── VMToolbarUSBMenuView.swift
│ │ ├── VMToolbarView.swift
│ │ ├── VMWindowState.swift
│ │ ├── VMWindowView.swift
│ │ ├── VMWizardView.swift
│ │ ├── de.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── en.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── es-419.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fi.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fr.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── iOS.entitlements
│ │ ├── it.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ja.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── ko.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── pl.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── ru.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── zh-HK.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ ├── zh-Hans.lproj/
│ │ │ ├── Info-RemotePlist.strings
│ │ │ └── InfoPlist.strings
│ │ └── zh-Hant.lproj/
│ │ └── InfoPlist.strings
│ ├── it.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── ja.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── ko.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── macOS/
│ │ ├── AppDelegate.swift
│ │ ├── Display/
│ │ │ ├── Base.lproj/
│ │ │ │ └── VMDisplayWindow.xib
│ │ │ ├── VMDisplayAppleDisplayWindowController.swift
│ │ │ ├── VMDisplayAppleTerminalWindowController.swift
│ │ │ ├── VMDisplayAppleWindowController.swift
│ │ │ ├── VMDisplayQemuDisplayController.swift
│ │ │ ├── VMDisplayQemuMetalWindowController.swift
│ │ │ ├── VMDisplayQemuTerminalWindowController.swift
│ │ │ ├── VMDisplayTerminal.swift
│ │ │ ├── VMDisplayWindowController.swift
│ │ │ ├── VMMetalView.swift
│ │ │ ├── VMMetalViewInputDelegate.swift
│ │ │ ├── de.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── es-419.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── fi.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── fr.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── it.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── ja.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── ko.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── pl.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── ru.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── zh-HK.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ ├── zh-Hans.lproj/
│ │ │ │ └── VMDisplayWindow.strings
│ │ │ └── zh-Hant.lproj/
│ │ │ └── VMDisplayWindow.strings
│ │ ├── DoubleClickHandler.swift
│ │ ├── Info.plist
│ │ ├── KeyCodeMap.swift
│ │ ├── SavePanel.swift
│ │ ├── SettingsView.swift
│ │ ├── UTMApp.swift
│ │ ├── UTMDataExtension.swift
│ │ ├── UTMMenuBarExtraScene.swift
│ │ ├── UTMPatches.swift
│ │ ├── UTMServerView.swift
│ │ ├── VMAppleRemovableDrivesView.swift
│ │ ├── VMAppleSettingsAddDeviceMenuView.swift
│ │ ├── VMAppleSettingsView.swift
│ │ ├── VMConfigAppleBootView.swift
│ │ ├── VMConfigAppleDisplayView.swift
│ │ ├── VMConfigAppleDriveCreateView.swift
│ │ ├── VMConfigAppleDriveDetailsView.swift
│ │ ├── VMConfigAppleNetworkingView.swift
│ │ ├── VMConfigAppleSerialView.swift
│ │ ├── VMConfigAppleSharingView.swift
│ │ ├── VMConfigAppleSystemView.swift
│ │ ├── VMConfigAppleVirtualizationView.swift
│ │ ├── VMConfigNetworkPortForwardView.swift
│ │ ├── VMConfigQEMUArgumentsView.swift
│ │ ├── VMDrivesSettingsView.swift
│ │ ├── VMHeadlessSessionState.swift
│ │ ├── VMKeyboardShortcutsView.swift
│ │ ├── VMQEMUSettingsView.swift
│ │ ├── VMRemoteSessionState.swift
│ │ ├── VMSettingsView.swift
│ │ ├── VMWizardView.swift
│ │ ├── de.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── en.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── es-419.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fi.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── fr.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── it.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ja.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ko.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── macOS-unsigned.entitlements
│ │ ├── macOS.entitlements
│ │ ├── pl.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── ru.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── zh-HK.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── zh-Hans.lproj/
│ │ │ └── InfoPlist.strings
│ │ └── zh-Hant.lproj/
│ │ └── InfoPlist.strings
│ ├── pl.lproj/
│ │ ├── InfoPlist.strings
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── ru.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── visionOS/
│ │ ├── UTMApp.swift
│ │ └── VMToolbarOrnamentModifier.swift
│ ├── zh-HK.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ ├── zh-Hans.lproj/
│ │ ├── Localizable.strings
│ │ └── Localizable.stringsdict
│ └── zh-Hant.lproj/
│ ├── Localizable.strings
│ └── Localizable.stringsdict
├── QEMUHelper/
│ ├── Info.plist
│ ├── QEMUHelper-unsigned.entitlements
│ ├── QEMUHelper.entitlements
│ ├── QEMUHelper.h
│ ├── QEMUHelper.m
│ ├── QEMUHelperDelegate.h
│ ├── QEMUHelperProtocol.h
│ ├── de.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── en.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── es-419.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── fi.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── fr.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── it.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── ja.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── ko.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── main.m
│ ├── pl.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── ru.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── zh-HK.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ ├── zh-Hans.lproj/
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ └── zh-Hant.lproj/
│ ├── InfoPlist.strings
│ └── Localizable.strings
├── QEMULauncher/
│ ├── Bootstrap.c
│ ├── Bootstrap.h
│ ├── Info.plist
│ ├── QEMULauncher-unsigned.entitlements
│ ├── QEMULauncher.entitlements
│ ├── de.lproj/
│ │ └── InfoPlist.strings
│ ├── es-419.lproj/
│ │ └── InfoPlist.strings
│ ├── main.c
│ └── pl.lproj/
│ └── InfoPlist.strings
├── README.bn.md
├── README.cz.md
├── README.es.md
├── README.fr.md
├── README.ja.md
├── README.ko.md
├── README.md
├── README.pl-PL.md
├── README.ru.md
├── README.uk.md
├── README.zh-HK.md
├── README.zh-Hans.md
├── README.zh-Hant.md
├── Remote/
│ ├── GenerateKey.c
│ ├── GenerateKey.h
│ ├── UTMRemoteClient.swift
│ ├── UTMRemoteConnectInterface.h
│ ├── UTMRemoteKeyManager.swift
│ ├── UTMRemoteMessage.swift
│ ├── UTMRemoteServer.swift
│ └── UTMRemoteSpiceVirtualMachine.swift
├── Renderer/
│ └── LICENSE.txt
├── Scripting/
│ ├── UTM.sdef
│ ├── UTMScriptable.swift
│ ├── UTMScripting.swift
│ ├── UTMScriptingCloneCommand.swift
│ ├── UTMScriptingConfigImpl.swift
│ ├── UTMScriptingCreateCommand.swift
│ ├── UTMScriptingDeleteCommand.swift
│ ├── UTMScriptingExportCommand.swift
│ ├── UTMScriptingGuestFileImpl.swift
│ ├── UTMScriptingGuestProcessImpl.swift
│ ├── UTMScriptingImportCommand.swift
│ ├── UTMScriptingInputImpl.swift
│ ├── UTMScriptingRegistryEntryImpl.swift
│ ├── UTMScriptingSerialPortImpl.swift
│ ├── UTMScriptingUSBDeviceImpl.swift
│ └── UTMScriptingVirtualMachineImpl.swift
├── Services/
│ ├── Swift-Bridging-Header.h
│ ├── UTMASIFImage.h
│ ├── UTMASIFImage.m
│ ├── UTMAppleVirtualMachine.swift
│ ├── UTMExtensions.swift
│ ├── UTMJailbreak.h
│ ├── UTMJailbreak.m
│ ├── UTMKeyboardShortcuts.swift
│ ├── UTMLocationManager.h
│ ├── UTMLocationManager.m
│ ├── UTMLogging.h
│ ├── UTMLogging.m
│ ├── UTMLoggingSwift.swift
│ ├── UTMPasteboard.swift
│ ├── UTMPipeInterface.swift
│ ├── UTMProcess.h
│ ├── UTMProcess.m
│ ├── UTMQemuImage.swift
│ ├── UTMQemuPort.swift
│ ├── UTMQemuSystem.h
│ ├── UTMQemuSystem.m
│ ├── UTMQemuSystemBackends.h
│ ├── UTMQemuVirtualMachine.swift
│ ├── UTMRegistry.swift
│ ├── UTMRegistryEntry.swift
│ ├── UTMSWTPM.swift
│ ├── UTMSerialPort.swift
│ ├── UTMSerialPortDelegate.swift
│ ├── UTMSpiceIO.h
│ ├── UTMSpiceIO.m
│ ├── UTMSpiceIODelegate.h
│ ├── UTMSpiceVirtualMachine.swift
│ ├── UTMUSBManager.swift
│ └── UTMVirtualMachine.swift
├── UTM.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm/
│ │ └── Package.resolved
│ └── xcshareddata/
│ ├── IDETemplateMacros.plist
│ └── xcschemes/
│ ├── iOS-Remote.xcscheme
│ ├── iOS-SE.xcscheme
│ ├── iOS.xcscheme
│ ├── macOS.xcscheme
│ └── utmctl.xcscheme
├── patches/
│ ├── data/
│ │ └── qemu-10.0.2-utm/
│ │ └── pc-bios/
│ │ ├── edk2-arm-secure-vars.fd.bz2
│ │ ├── edk2-arm-vars.fd.bz2
│ │ ├── edk2-i386-secure-vars.fd.bz2
│ │ ├── edk2-i386-vars.fd.bz2
│ │ ├── m68k-declrom
│ │ └── ppc-ndrvloader
│ ├── gettext-0.22.5.patch
│ ├── glib-2.69.0.patch
│ ├── gst-plugins-base-1.19.1.patch
│ ├── gst-plugins-good-1.19.1.patch
│ ├── json-glib-1.2.8.patch
│ ├── libgcrypt-1.8.4.patch
│ ├── libslirp-v4.9.1.patch
│ ├── libsoup-3.6.0.patch
│ ├── libtpms-0.9.6.patch
│ ├── libusb-1.0.25.patch
│ ├── openssl-1.1.1b.patch
│ ├── phodav-3.0.patch
│ ├── pixman-0.38.0.patch
│ ├── qemu-10.0.2-utm.patch
│ ├── sources
│ ├── spice-0.14.3.patch
│ └── spice-gtk-0.42.patch
├── scripts/
│ ├── bridge-gen.sh
│ ├── build_dependencies.sh
│ ├── build_utm.sh
│ ├── const-gen.py
│ ├── deb/
│ │ ├── MobileCoreServices.tbd
│ │ ├── postinst.m
│ │ ├── postinst.xml
│ │ ├── prerm.m
│ │ └── prerm.xml
│ ├── pack_dependencies.sh
│ ├── package.sh
│ ├── package_mac.sh
│ └── resources/
│ ├── UTM-drive.icns
│ └── appdmg.json
├── utmctl/
│ ├── Info.plist
│ ├── UTMCtl.swift
│ ├── utmctl-unsigned.entitlements
│ └── utmctl.entitlements
├── zh-HK.lproj/
│ └── QEMULauncher-InfoPlist.strings
├── zh-Hans.lproj/
│ └── QEMULauncher-InfoPlist.strings
└── zh-Hant.lproj/
└── QEMULauncher-InfoPlist.strings
SYMBOL INDEX (38 symbols across 9 files)
FILE: Configuration/Legacy/UTMLegacyQemuConfiguration+Drives.h
type UTMDiskImageTypeNone (line 19) | typedef NS_ENUM(NSInteger, UTMDiskImageType) {
FILE: JailbreakInterposer/JailbreakInterposer.c
type proc_uniqidentifierinfo (line 27) | struct proc_uniqidentifierinfo {
function kern_return_t (line 42) | static kern_return_t IOServiceAuthorizeReplacement(io_service_t service,...
FILE: Platform/iOS/Display/VMDisplayMetalViewController+Private.h
function NS_ASSUME_NONNULL_BEGIN (line 29) | NS_ASSUME_NONNULL_BEGIN
function CGFloat (line 84) | static inline CGFloat CGPixelToPoint(UIView * _Nonnull view, CGFloat pix...
FILE: Platform/iOS/Display/VMDisplayMetalViewController+Touch.h
type VMGestureTypeNone (line 20) | typedef NS_ENUM(NSInteger, VMGestureType) {
type VMMouseTypeRelative (line 29) | typedef NS_ENUM(NSInteger, VMMouseType) {
FILE: QEMULauncher/Bootstrap.c
type qemu_main_t (line 25) | typedef struct {
type kevent (line 39) | struct kevent
function loadQemu (line 54) | static int loadQemu(const char *dylibPath, qemu_main_t *funcs) {
function runQemu (line 73) | static void __attribute__((noreturn)) runQemu(qemu_main_t *funcs, int ar...
function pid_t (line 91) | pid_t startQemuFork(const char *dylibPath, int argc, const char **argv, ...
function startQemuProcess (line 112) | int startQemuProcess(const char *dylibPath, int argc, const char **argv,...
FILE: QEMULauncher/main.c
function main (line 22) | int main(int argc, const char * argv[]) {
FILE: Remote/GenerateKey.c
function add_ext (line 32) | static int add_ext(X509 *cert, int nid, char *value) {
function mkrsacert (line 52) | static int mkrsacert(X509 **x509p, EVP_PKEY **pkeyp, const char *commonN...
function _Nullable (line 135) | static _Nullable CFDataRef CreateP12FromKey(EVP_PKEY *pkey, X509 *cert) {
function _Nullable (line 161) | static _Nullable CFDataRef CreatePrivatePEMFromKey(EVP_PKEY *pkey) {
function _Nullable (line 179) | static _Nullable CFDataRef CreatePublicPEMFromCert(X509 *cert) {
function _Nullable (line 197) | static _Nullable CFDataRef CreatePublicKeyFromCert(X509 *cert) {
function _Nullable (line 223) | _Nullable CFArrayRef GenerateRSACertificate(CFStringRef _Nonnull commonN...
FILE: Services/Swift-Bridging-Header.h
type CGSConnectionID (line 53) | typedef uint32_t CGSConnectionID;
FILE: scripts/const-gen.py
function parseListing (line 128) | def parseListing(listing):
function parseDeviceListing (line 144) | def parseDeviceListing(defaults, listing):
function parseCpu (line 165) | def parseCpu(target, listing):
function sortItems (line 232) | def sortItems(items):
function getMachines (line 235) | def getMachines(target, qemu_path):
function getDefaultMachine (line 239) | def getDefaultMachine(target, machines):
function getDevices (line 247) | def getDevices(target, qemu_path):
function getCpus (line 252) | def getCpus(target, qemu_path):
function sanitizeName (line 256) | def sanitizeName(name):
function generateEmptyEnum (line 266) | def generateEmptyEnum(name):
function generateEnum (line 271) | def generateEnum(name, values, prettyValues, baseName='QEMUConstant', de...
function generateArchitectureAtlas (line 302) | def generateArchitectureAtlas(architectures, types):
function generateEnumForeachArchitecture (line 317) | def generateEnumForeachArchitecture(name, targetItems, defaults={}):
function generate (line 329) | def generate(targets, cpus, cpuFlags, machines, displayDevices, networkD...
function transformDisplayCards (line 351) | def transformDisplayCards(displayCards):
function main (line 358) | def main(argv):
Condensed preview — 549 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,595K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 89,
"preview": "github: utmapp\ncustom: 'https://apps.apple.com/us/app/utm-virtual-machines/id1538878817'\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 1495,
"preview": "---\nname: iOS issue\nabout: Report an issue or crash for iOS\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the issu"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report_macos.md",
"chars": 1859,
"preview": "---\nname: macOS issue\nabout: Report an issue or crash for macOS\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**BEFORE SUBMIT"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 217,
"preview": "---\nname: Feature request\nabout: Request a new feature\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\nPlease browse t"
},
{
"path": ".github/workflows/build.yml",
"chars": 24374,
"preview": "name: Build\non:\n push:\n branches:\n - '**'\n tags-ignore:\n - '**'\n paths-ignore:\n - 'LICENSE'\n "
},
{
"path": ".github/workflows/issues.yml",
"chars": 335,
"preview": "name: Issues\non:\n issue_comment:\n types: [created]\n issues:\n types: [opened]\njobs:\n cooldown:\n name: Cooldow"
},
{
"path": ".gitignore",
"chars": 1715,
"preview": "# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n"
},
{
"path": "Build.xcconfig",
"chars": 2142,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "CONTRIBUTING.md",
"chars": 5366,
"preview": "## Getting Started\nRead the [documentation](Documentation) pages to familiarize yourself with the codebase and developme"
},
{
"path": "CodeSigning.xcconfig.sample",
"chars": 2711,
"preview": "// Your Team ID. See `Documentation/iOSDevelopment.md` for help finding this.\nDEVELOPMENT_TEAM = XYZ0123456\n\n// Prefix o"
},
{
"path": "Configuration/Legacy/UTMLegacyAppleConfiguration.swift",
"chars": 16356,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Constants.h",
"chars": 1137,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Constants.m",
"chars": 4226,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Display.h",
"chars": 1776,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Display.m",
"chars": 7779,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Drives.h",
"chars": 2166,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Drives.m",
"chars": 7357,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Miscellaneous.h",
"chars": 1292,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Miscellaneous.m",
"chars": 4977,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Networking.h",
"chars": 2264,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Networking.m",
"chars": 10306,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Sharing.h",
"chars": 1242,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+Sharing.m",
"chars": 4068,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+System.h",
"chars": 2417,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration+System.m",
"chars": 11400,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration.h",
"chars": 1148,
"preview": "//\n// Copyright © 2019 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfiguration.m",
"chars": 4456,
"preview": "//\n// Copyright © 2019 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfigurationPortForward.h",
"chars": 1009,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyQemuConfigurationPortForward.m",
"chars": 1900,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyViewState.h",
"chars": 1715,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/Legacy/UTMLegacyViewState.m",
"chars": 3980,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/QEMUArgument.swift",
"chars": 3298,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/QEMUArgumentBuilder.swift",
"chars": 2942,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/QEMUConstant.swift",
"chars": 15456,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/QEMUConstantGenerated.swift",
"chars": 414274,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfiguration.swift",
"chars": 13139,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationBoot.swift",
"chars": 8375,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationDisplay.swift",
"chars": 3546,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationDrive.swift",
"chars": 5310,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationGenericPlatform.swift",
"chars": 2205,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationMacPlatform.swift",
"chars": 4755,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationNetwork.swift",
"chars": 4693,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationSerial.swift",
"chars": 3040,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationSharedDirectory.swift",
"chars": 3916,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationSystem.swift",
"chars": 5929,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMAppleConfigurationVirtualization.swift",
"chars": 9677,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMConfiguration.swift",
"chars": 9198,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMConfigurationDrive.swift",
"chars": 5662,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMConfigurationHostNetwork.swift",
"chars": 4088,
"preview": "//\n// Copyright © 2024 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMConfigurationInfo.swift",
"chars": 5018,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMConfigurationTerminal.swift",
"chars": 4594,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfiguration+Arguments.swift",
"chars": 46280,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfiguration.swift",
"chars": 12032,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationDisplay.swift",
"chars": 5290,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationDrive.swift",
"chars": 8139,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationInput.swift",
"chars": 3107,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationNetwork.swift",
"chars": 10316,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationPortForward.swift",
"chars": 4208,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationQEMU.swift",
"chars": 10194,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationSerial.swift",
"chars": 4454,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationSharing.swift",
"chars": 3591,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationSound.swift",
"chars": 2998,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Configuration/UTMQemuConfigurationSystem.swift",
"chars": 5821,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Documentation/Architecture.md",
"chars": 9071,
"preview": "# Architecture\n\nUTM is built upon several pieces of technology, layered to provide compatibility across various host con"
},
{
"path": "Documentation/Dependencies.md",
"chars": 4502,
"preview": "# Dependencies\n\nUTM is built upon QEMU, SPICE, and various libraries that those projects depend on. To support building "
},
{
"path": "Documentation/Graphics.md",
"chars": 7442,
"preview": "# Graphics\n\nThe graphics architecture of UTM involves many separate translation layers.\n\n### GPU Acceleration\n```\n "
},
{
"path": "Documentation/MacDevelopment.md",
"chars": 5482,
"preview": "# macOS Development\n\nBecause UTM is a sand-boxed Mac app, there are a few extra steps needed for a proper development en"
},
{
"path": "Documentation/Release.md",
"chars": 9534,
"preview": "# Release Guide\n\nThis document details the release procedure for UTM team members. The release procedure is mostly autom"
},
{
"path": "Documentation/TetheredLaunch.md",
"chars": 2235,
"preview": "# Tethered Launch\n\nOn iOS 14, Apple [patched][1] the trick we used to get JIT working. As a result, the next best workar"
},
{
"path": "Documentation/TetheredLaunch.zh-HK.md",
"chars": 1431,
"preview": "# 捆綁式啟動\n\n在 iOS 14 當中,Apple [修複][1]了我們之前令 JIT 工作的「蠱惑招」。因此,下一個最佳變通方法涉及的就更多了。這只限用於未越獄(Jailbreak)的裝置。如你已經越獄,就無需這樣做。\n\n## 先決條件"
},
{
"path": "Documentation/TetheredLaunch.zh-Hans.md",
"chars": 1474,
"preview": "# 捆绑启动\n\n在 iOS 14 中,Apple [修补][1]了我们用来让 JIT 工作的“把戏”。因此,下一个最佳变通方案所涉及的范围更广。这一操作只适用于未经越狱(Jailbreak)过的设备。若你已经越狱,就不需要这样做了。\n\n##"
},
{
"path": "Documentation/TetheredLaunch.zh-Hant.md",
"chars": 1423,
"preview": "# 不完美啟動\n\n 在iOS14中,蘋果[修補][1]了我們用來讓JIT工作的“把戲”。 因此,下一個最佳的解決方案所涉及的範圍更廣。 這只適用於非越獄設備。 如果你越獄了,你不需要這樣做。\n\n ## 前置條件\n\n * Xcode\n * ["
},
{
"path": "Documentation/iOSDevelopment.md",
"chars": 5876,
"preview": "# iOS Development\n\nThis document describes the steps to build and debug UTM on iOS and simulator devices.\n\n## Getting th"
},
{
"path": "Intents/UTMActionIntent.swift",
"chars": 8201,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Intents/UTMInputIntent.swift",
"chars": 8686,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Intents/UTMIntent.swift",
"chars": 2532,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Intents/UTMVirtualMachineEntity.swift",
"chars": 2659,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Intents/UTMVirtualMachineEntityQuery.swift",
"chars": 7925,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "JailbreakInterposer/Info.plist",
"chars": 752,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "JailbreakInterposer/JailbreakInterposer.c",
"chars": 2364,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "LICENSE",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Platform/AppIcon-Remote.icon/icon.json",
"chars": 3262,
"preview": "{\n \"fill-specializations\" : [\n {\n \"value\" : {\n \"linear-gradient\" : [\n \"display-p3:0.46275,0.941"
},
{
"path": "Platform/AppIcon.icon/icon.json",
"chars": 3262,
"preview": "{\n \"fill-specializations\" : [\n {\n \"value\" : {\n \"linear-gradient\" : [\n \"display-p3:0.34510,0.560"
},
{
"path": "Platform/Assets.xcassets/AccentColor-Remote.colorset/Contents.json",
"chars": 329,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"srgb\",\n \"components\" : {\n \"alpha\" : \"1"
},
{
"path": "Platform/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 329,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"srgb\",\n \"components\" : {\n \"alpha\" : \"1"
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.appiconset/Contents.json",
"chars": 10278,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_20pt@2x.png\",\n \"idiom\" : \"universal\",\n \"platform\" : \"ios\",\n "
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json",
"chars": 176,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Back@2x.png\",\n \"idiom\" : \"vision\",\n \"scale\" : \"2x\"\n }\n ],\n \"in"
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Back.solidimagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Contents.json",
"chars": 265,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n },\n \"layers\" : [\n {\n \"filename\" : \"Front.solidimages"
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json",
"chars": 178,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Front@2x.png\",\n \"idiom\" : \"reality\",\n \"scale\" : \"2x\"\n }\n ],\n \""
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Front.solidimagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json",
"chars": 143,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"reality\",\n \"scale\" : \"2x\"\n }\n ],\n \"info\" : {\n \"author\" : \"xcode\",\n "
},
{
"path": "Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Middle.solidimagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "Platform/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 11481,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_20pt@2x.png\",\n \"idiom\" : \"universal\",\n \"platform\" : \"ios\",\n "
},
{
"path": "Platform/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json",
"chars": 177,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Back@2x.png\",\n \"idiom\" : \"reality\",\n \"scale\" : \"2x\"\n }\n ],\n \"i"
},
{
"path": "Platform/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "Platform/Assets.xcassets/AppIcon.solidimagestack/Contents.json",
"chars": 265,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n },\n \"layers\" : [\n {\n \"filename\" : \"Front.solidimages"
},
{
"path": "Platform/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json",
"chars": 178,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Front@2x.png\",\n \"idiom\" : \"reality\",\n \"scale\" : \"2x\"\n }\n ],\n \""
},
{
"path": "Platform/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "Platform/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json",
"chars": 143,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"reality\",\n \"scale\" : \"2x\"\n }\n ],\n \"info\" : {\n \"author\" : \"xcode\",\n "
},
{
"path": "Platform/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "Platform/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "Platform/Assets.xcassets/Keyboard Hide.imageset/Contents.json",
"chars": 466,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"chevron.down@1x.png\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n }"
},
{
"path": "Platform/Assets.xcassets/Keyboard Paste.imageset/Contents.json",
"chars": 478,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"doc.on.clipboard@1x.png\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n "
},
{
"path": "Platform/Assets.xcassets/Logo-Linux.imageset/Contents.json",
"chars": 155,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"linux.pdf\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" "
},
{
"path": "Platform/Assets.xcassets/Logo-Windows.imageset/Contents.json",
"chars": 157,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"windows.pdf\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author"
},
{
"path": "Platform/Assets.xcassets/Logo-macOS.imageset/Contents.json",
"chars": 155,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"macos.pdf\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" "
},
{
"path": "Platform/Assets.xcassets/MenuBarExtra.imageset/Contents.json",
"chars": 340,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_16pt.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "Platform/Assets.xcassets/Toolbar USB.imageset/Contents.json",
"chars": 457,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"usb-cable@1x.png\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "Platform/Main.swift",
"chars": 3778,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/BigButtonStyle.swift",
"chars": 2401,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/BusyIndicator.swift",
"chars": 1658,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/BusyOverlay.swift",
"chars": 1613,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/ContentView.swift",
"chars": 7927,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/DefaultTextField.swift",
"chars": 2769,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/DestructiveButton.swift",
"chars": 1860,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/DetailedSection.swift",
"chars": 1887,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/FileBrowseField.swift",
"chars": 2458,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/GlobalFileImporter.swift",
"chars": 2595,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/InListButtonStyle.swift",
"chars": 2940,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/MacDeviceLabel.swift",
"chars": 3870,
"preview": "//\n// Copyright © 2024 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/MenuLabel.swift",
"chars": 1362,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/NumberTextField.swift",
"chars": 6350,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/RAMSlider.swift",
"chars": 3147,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/SizeTextField.swift",
"chars": 2632,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/Spinner.swift",
"chars": 2662,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/UTMPendingVMView.swift",
"chars": 3173,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/UTMPlaceholderVMView.swift",
"chars": 4208,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/UTMTips.swift",
"chars": 1994,
"preview": "//\n// Copyright © 2024 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/UTMUnavailableVMView.swift",
"chars": 3507,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMCardView.swift",
"chars": 3685,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMCommands.swift",
"chars": 2701,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigAdvancedNetworkView.swift",
"chars": 2959,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigConstantPicker.swift",
"chars": 2945,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigDisplayConsoleView.swift",
"chars": 2949,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigDisplayView.swift",
"chars": 3134,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigDriveCreateView.swift",
"chars": 2470,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigDriveDetailsView.swift",
"chars": 9945,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigInfoView.swift",
"chars": 11760,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigInputView.swift",
"chars": 3520,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigNetworkView.swift",
"chars": 4394,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigPortForwardForm.swift",
"chars": 1797,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigQEMUView.swift",
"chars": 10589,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigSerialView.swift",
"chars": 4680,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigSharingView.swift",
"chars": 2511,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigSoundView.swift",
"chars": 1673,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfigSystemView.swift",
"chars": 11825,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMConfirmActionModifier.swift",
"chars": 3461,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMContextMenuModifier.swift",
"chars": 7085,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMDetailsView.swift",
"chars": 20082,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMKeyboardMap.h",
"chars": 1309,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMKeyboardMap.m",
"chars": 13468,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMNavigationListView.swift",
"chars": 9399,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMPlaceholderView.swift",
"chars": 5232,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMReleaseNotesView.swift",
"chars": 6086,
"preview": "//\n// Copyright © 2023 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMRemovableDrivesView.swift",
"chars": 11426,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMSettingsAddDeviceMenuView.swift",
"chars": 4103,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMShareFileModifier.swift",
"chars": 1731,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMToolbarModifier.swift",
"chars": 6395,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardContent.swift",
"chars": 1482,
"preview": "//\n// Copyright © 2023 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardDrivesView.swift",
"chars": 1488,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardHardwareView.swift",
"chars": 12700,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardOSClassicMacView.swift",
"chars": 3963,
"preview": "//\n// Copyright © 2025 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardOSLinuxView.swift",
"chars": 7020,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardOSMacView.swift",
"chars": 4363,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardOSOtherView.swift",
"chars": 3503,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardOSView.swift",
"chars": 4236,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardOSWindowsView.swift",
"chars": 6380,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardSharingView.swift",
"chars": 2217,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardStartView.swift",
"chars": 5175,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardStartViewTCI.swift",
"chars": 2428,
"preview": "//\n// Copyright © 2024 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardState.swift",
"chars": 25720,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/Shared/VMWizardSummaryView.swift",
"chars": 7072,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMData.swift",
"chars": 53834,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMDownloadIPSWTask.swift",
"chars": 2004,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMDownloadMacSupportToolsTask.swift",
"chars": 2646,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMDownloadSupportToolsTask.swift",
"chars": 3614,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMDownloadTask.swift",
"chars": 7581,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMDownloadVMTask.swift",
"chars": 5432,
"preview": "//\n// Copyright © 2022 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMPendingVirtualMachine.swift",
"chars": 5784,
"preview": "//\n// Copyright © 2021 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/UTMReleaseHelper.swift",
"chars": 5742,
"preview": "//\n// Copyright © 2023 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/VMData.swift",
"chars": 17962,
"preview": "//\n// Copyright © 2023 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/ar.lproj/Localizable.strings",
"chars": 76556,
"preview": "/* A removable drive that has no image file inserted. */\n\"(empty)\" = \"(فارغ)\";\n\n/* VMConfigAppleDriveDetailsView */\n\"(Ne"
},
{
"path": "Platform/de.lproj/Localizable.strings",
"chars": 35077,
"preview": "/* A removable drive that has no image file inserted. */\n\"(empty)\" = \"(leer)\";\n\n/* VMConfigAppleDriveDetailsView */\n\"(Ne"
},
{
"path": "Platform/de.lproj/Localizable.stringsdict",
"chars": 582,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Platform/en.lproj/Localizable.strings",
"chars": 9,
"preview": "\"\" = \"\";\n"
},
{
"path": "Platform/en.lproj/Localizable.stringsdict",
"chars": 582,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Platform/es-419.lproj/Localizable.strings",
"chars": 67542,
"preview": "/* A removable drive that has no image file inserted. */\n\"(empty)\" = \"(vacío)\";\n\n/* VMConfigAppleDriveDetailsView */\n\"(N"
},
{
"path": "Platform/es-419.lproj/Localizable.stringsdict",
"chars": 582,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Platform/fi.lproj/Localizable.strings",
"chars": 45462,
"preview": "/* No comment provided by engineer. */\n\"-\" = \"-\";\n\n/* A removable drive that has no image file inserted. */\n\"(empty)\" = "
},
{
"path": "Platform/fr.lproj/Localizable.strings",
"chars": 64661,
"preview": "\n/* Configuration */\n\n// Legacy/UTMLegacyQemuConfiguration+Constants.m\n\"Hard Disk\" = \"Disque dur\";\n\"CD/DVD\" = \"CD/DVD\";\n"
},
{
"path": "Platform/fr.lproj/Localizable.stringsdict",
"chars": 582,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Platform/iOS/ActivityView.swift",
"chars": 1177,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/iOS/Display/Base.lproj/VMDisplayMetalViewInputAccessory.xib",
"chars": 77506,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVe"
},
{
"path": "Platform/iOS/Display/VMCursor.h",
"chars": 1064,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/iOS/Display/VMCursor.m",
"chars": 3215,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.h",
"chars": 803,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.m",
"chars": 7081,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/iOS/Display/VMDisplayMetalViewController+Keyboard.h",
"chars": 1040,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "Platform/iOS/Display/VMDisplayMetalViewController+Keyboard.m",
"chars": 7827,
"preview": "//\n// Copyright © 2020 osy. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
}
]
// ... and 349 more files (download for full content)
About this extraction
This page contains the full source code of the utmapp/UTM GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 549 files (5.1 MB), approximately 1.4M tokens, and a symbol index with 38 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.