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*)supportedBootDevicesPretty; + (NSArray*)supportedBootDevices; + (NSArray*)supportedImageTypesPretty; + (NSArray*)supportedImageTypes; + (NSArray*)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 #if !TARGET_OS_OSX #import #else #import #endif #import "UTMLegacyQemuConfiguration+Constants.h" @implementation UTMLegacyQemuConfiguration (Constants) + (NSString *)diskImagesDirectory { return @"Images"; } #pragma mark - Constant supported values + (NSArray*)supportedBootDevicesPretty { return @[ NSLocalizedString(@"Hard Disk", "Configuration boot device"), NSLocalizedString(@"CD/DVD", "Configuration boot device"), NSLocalizedString(@"Floppy", "Configuration boot device") ]; } + (NSArray*)supportedBootDevices { return @[ @"hdd", @"cd", @"floppy" ]; } + (NSArray*)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*)supportedImageTypes { return @[ @"none", @"disk", @"cd", @"bios", @"kernel", @"initrd", @"dtb" ]; } #if !TARGET_OS_OSX + (NSArray*)supportedConsoleFonts { static NSMutableArray *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*)supportedConsoleFonts { static NSMutableArray *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 #if !TARGET_OS_OSX #import #else #import #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 *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 *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 *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 *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 *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 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 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 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 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 *)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 *_removableDrives; NSMutableDictionary *_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 *)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(_ 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(_ 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" case _745_v1_1 = "745_v1.1" case _755_v1_1 = "755_v1.1" case _745_v2_0 = "745_v2.0" case _755_v2_0 = "755_v2.0" case _745_v2_1 = "745_v2.1" case _755_v2_1 = "755_v2.1" case _745_v2_2 = "745_v2.2" case _755_v2_2 = "755_v2.2" case _745_v2_3 = "745_v2.3" case _755_v2_3 = "755_v2.3" case _745_v2_4 = "745_v2.4" case _755_v2_4 = "755_v2.4" case _745_v2_5 = "745_v2.5" case _755_v2_5 = "755_v2.5" case _745_v2_6 = "745_v2.6" case _755_v2_6 = "755_v2.6" case _745_v2_7 = "745_v2.7" case _755_v2_7 = "755_v2.7" case _745_v2_8 = "745_v2.8" case _755_v2_8 = "755_v2.8" case _750cxe_v2_4b = "750cxe_v2.4b" case _750cxe_v3_1b = "750cxe_v3.1b" case _750cxr = "750cxr" case _750cl_v1_0 = "750cl_v1.0" case _750cl_v2_0 = "750cl_v2.0" case _750l_v2_0 = "750l_v2.0" case _750l_v2_1 = "750l_v2.1" case _750l_v2_2 = "750l_v2.2" case _750l_v3_0 = "750l_v3.0" case _750l_v3_2 = "750l_v3.2" case _604e_v1_0 = "604e_v1.0" case _604e_v2_2 = "604e_v2.2" case _604e_v2_4 = "604e_v2.4" case _604r = "604r" case _7400_v1_0 = "7400_v1.0" case _7400_v1_1 = "7400_v1.1" case _7400_v2_0 = "7400_v2.0" case _7400_v2_1 = "7400_v2.1" case _7400_v2_2 = "7400_v2.2" case _7400_v2_6 = "7400_v2.6" case _7400_v2_7 = "7400_v2.7" case _7400_v2_8 = "7400_v2.8" case _7400_v2_9 = "7400_v2.9" case g2 case mpc603 case g2hip3 case e300c1 case mpc8343 case mpc8343a case mpc8343e case mpc8343ea case mpc8347ap case mpc8347at case mpc8347eap case mpc8347eat case mpc8347ep case mpc8347et case mpc8347p case mpc8347t case mpc8349 case mpc8349a case mpc8349e case mpc8349ea case e300c2 case e300c3 case e300c4 case mpc8377 case mpc8377e case mpc8378 case mpc8378e case mpc8379 case mpc8379e case _740p = "740p" case _750p = "750p" case _460exb = "460exb" case _440epx = "440epx" case _405d2 = "405d2" case x2vp4 case x2vp20 case _405gpa = "405gpa" case _405gpb = "405gpb" case _405cra = "405cra" case _405gpc = "405gpc" case _405gpd = "405gpd" case _405crb = "405crb" case _405crc = "405crc" case stb03 case npe4gs3 case npe405h case npe405h2 case _405ez = "405ez" case npe405l case _405d4 = "405d4" case stb04 case _405lp = "405lp" case _440epa = "440epa" case _440epb = "440epb" case _405gpr = "405gpr" case _405ep = "405ep" case stb25 case _750fx_v1_0 = "750fx_v1.0" case _750fx_v2_0 = "750fx_v2.0" case _750fx_v2_1 = "750fx_v2.1" case _750fx_v2_2 = "750fx_v2.2" case _750fl = "750fl" case _750fx_v2_3 = "750fx_v2.3" case _750gx_v1_0 = "750gx_v1.0" case _750gx_v1_1 = "750gx_v1.1" case _750gl = "750gl" case _750gx_v1_2 = "750gx_v1.2" case _440_xilinx = "440-xilinx" case _440_xilinx_w_dfpu = "440-xilinx-w-dfpu" case _7450_v1_0 = "7450_v1.0" case _7450_v1_1 = "7450_v1.1" case _7450_v1_2 = "7450_v1.2" case _7450_v2_0 = "7450_v2.0" case _7441_v2_1 = "7441_v2.1" case _7450_v2_1 = "7450_v2.1" case _7441_v2_3 = "7441_v2.3" case _7451_v2_3 = "7451_v2.3" case _7441_v2_10 = "7441_v2.10" case _7451_v2_10 = "7451_v2.10" case _7445_v1_0 = "7445_v1.0" case _7455_v1_0 = "7455_v1.0" case _7445_v2_1 = "7445_v2.1" case _7455_v2_1 = "7455_v2.1" case _7445_v3_2 = "7445_v3.2" case _7455_v3_2 = "7455_v3.2" case _7445_v3_3 = "7445_v3.3" case _7455_v3_3 = "7455_v3.3" case _7445_v3_4 = "7445_v3.4" case _7455_v3_4 = "7455_v3.4" case _7447_v1_0 = "7447_v1.0" case _7457_v1_0 = "7457_v1.0" case _7447_v1_1 = "7447_v1.1" case _7457_v1_1 = "7457_v1.1" case _7457_v1_2 = "7457_v1.2" case _7447a_v1_0 = "7447a_v1.0" case _7457a_v1_0 = "7457a_v1.0" case _7447a_v1_1 = "7447a_v1.1" case _7457a_v1_1 = "7457a_v1.1" case _7447a_v1_2 = "7447a_v1.2" case _7457a_v1_2 = "7457a_v1.2" case e600 case mpc8610 case mpc8641 case mpc8641d case _7448_v1_0 = "7448_v1.0" case _7448_v1_1 = "7448_v1.1" case _7448_v2_0 = "7448_v2.0" case _7448_v2_1 = "7448_v2.1" case _7410_v1_0 = "7410_v1.0" case _7410_v1_1 = "7410_v1.1" case _7410_v1_2 = "7410_v1.2" case _7410_v1_3 = "7410_v1.3" case _7410_v1_4 = "7410_v1.4" case e500_v10 case mpc8540_v10 case mpc8560_v10 case e500_v20 case mpc8540_v20 case mpc8540_v21 case mpc8541_v10 case mpc8541_v11 case mpc8541e_v10 case mpc8541e_v11 case mpc8555_v10 case mpc8555_v11 case mpc8555e_v10 case mpc8555e_v11 case mpc8560_v20 case mpc8560_v21 case e500v2_v10 case mpc8543_v10 case mpc8543e_v10 case mpc8548_v10 case mpc8548e_v10 case mpc8543_v11 case mpc8543e_v11 case mpc8548_v11 case mpc8548e_v11 case e500v2_v20 case mpc8543_v20 case mpc8543e_v20 case mpc8545_v20 case mpc8545e_v20 case mpc8547e_v20 case mpc8548_v20 case mpc8548e_v20 case e500v2_v21 case mpc8533_v10 case mpc8533e_v10 case mpc8543_v21 case mpc8543e_v21 case mpc8544_v10 case mpc8544e_v10 case mpc8545_v21 case mpc8545e_v21 case mpc8547e_v21 case mpc8548_v21 case mpc8548e_v21 case e500v2_v22 case mpc8533_v11 case mpc8533e_v11 case mpc8544_v11 case mpc8544e_v11 case mpc8567 case mpc8567e case mpc8568 case mpc8568e case e500v2_v30 case mpc8572 case mpc8572e case e500mc case g2h4 case g2hip4 case g2le case g2gp case g2legp case g2legp1 case mpc5200_v10 case mpc5200_v11 case mpc5200_v12 case mpc5200b_v20 case mpc5200b_v21 case g2legp3 case e200z5 case e200z6 case g2ls case g2lels case apollo6 case apollo7 case apollo7pm case arthur case conan_doyle = "conan/doyle" case e200 case e300 case e500 case e500v1 case e500v2 case g3 case g4 case goldeneye case goldfinger case lonestar case mach5 case mpc5200 case mpc5200b case mpc52xx case mpc8240 case mpc8241 case mpc8245 case mpc8247 case mpc8248 case mpc8250 case mpc8250_hip3 case mpc8250_hip4 case mpc8255 case mpc8255_hip3 case mpc8255_hip4 case mpc8260 case mpc8260_hip3 case mpc8260_hip4 case mpc8264 case mpc8264_hip3 case mpc8264_hip4 case mpc8265 case mpc8265_hip3 case mpc8265_hip4 case mpc8266 case mpc8266_hip3 case mpc8266_hip4 case mpc8270 case mpc8271 case mpc8272 case mpc8275 case mpc8280 case mpc82xx case mpc8347 case mpc8347a case mpc8347e case mpc8347ea case mpc8533 case mpc8533e case mpc8540 case mpc8541 case mpc8541e case mpc8543 case mpc8543e case mpc8544 case mpc8544e case mpc8545 case mpc8545e case mpc8547e case mpc8548 case mpc8548e case mpc8555 case mpc8555e case mpc8560 case nitro case powerquicc_ii = "powerquicc-ii" case ppc case ppc32 case sirocco case stretch case typhoon case vaillant case vanilla case vger case x2vp50 case x2vp7 var prettyValue: String { switch self { case ._405: return "405" case ._405cr: return "405cr" case ._405gp: return "405gp" case ._405gpe: return "405gpe" case ._440ep: return "440ep" case ._460ex: return "460ex" case ._603e: return "603e" case ._603r: return "603r" case ._604e: return "604e" case ._740: return "740" case ._7400: return "7400" case ._7410: return "7410" case ._7441: return "7441" case ._7445: return "7445" case ._7447: return "7447" case ._7447a: return "7447a" case ._7448: return "7448" case ._745: return "745" case ._7450: return "7450" case ._7451: return "7451" case ._7455: return "7455" case ._7457: return "7457" case ._7457a: return "7457a" case ._750: return "750" case ._750cl: return "750cl" case ._750cx: return "750cx" case ._750cxe: return "750cxe" case ._750fx: return "750fx" case ._750gx: return "750gx" case ._750l: return "750l" case ._755: return "755" case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case ._603: return "PVR 00030100 (603)" case ._604: return "PVR 00040103 (604)" case ._603e_v1_1: return "PVR 00060101 (603e_v1.1)" case ._603e_v1_2: return "PVR 00060102 (603e_v1.2)" case ._603e_v1_3: return "PVR 00060103 (603e_v1.3)" case ._603e_v1_4: return "PVR 00060104 (603e_v1.4)" case ._603e_v2_2: return "PVR 00060202 (603e_v2.2)" case ._603e_v3: return "PVR 00060300 (603e_v3)" case ._603e_v4: return "PVR 00060400 (603e_v4)" case ._603e_v4_1: return "PVR 00060401 (603e_v4.1)" case ._603p: return "PVR 00070000 (603p)" case ._603e7v: return "PVR 00070100 (603e7v)" case ._603e7v1: return "PVR 00070101 (603e7v1)" case ._603e7: return "PVR 00070200 (603e7)" case ._603e7v2: return "PVR 00070201 (603e7v2)" case ._603e7t: return "PVR 00071201 (603e7t)" case ._740_v1_0: return "PVR 00080100 (740_v1.0)" case ._740e: return "PVR 00080100 (740e)" case ._750_v1_0: return "PVR 00080100 (750_v1.0)" case ._740_v2_0: return "PVR 00080200 (740_v2.0)" case ._750_v2_0: return "PVR 00080200 (750_v2.0)" case ._750e: return "PVR 00080200 (750e)" case ._740_v2_1: return "PVR 00080201 (740_v2.1)" case ._750_v2_1: return "PVR 00080201 (750_v2.1)" case ._740_v2_2: return "PVR 00080202 (740_v2.2)" case ._750_v2_2: return "PVR 00080202 (750_v2.2)" case ._740_v3_0: return "PVR 00080300 (740_v3.0)" case ._750_v3_0: return "PVR 00080300 (750_v3.0)" case ._740_v3_1: return "PVR 00080301 (740_v3.1)" case ._750_v3_1: return "PVR 00080301 (750_v3.1)" case ._750cx_v1_0: return "PVR 00082100 (750cx_v1.0)" case ._750cx_v2_0: return "PVR 00082200 (750cx_v2.0)" case ._750cx_v2_1: return "PVR 00082201 (750cx_v2.1)" case ._750cx_v2_2: return "PVR 00082202 (750cx_v2.2)" case ._750cxe_v2_1: return "PVR 00082211 (750cxe_v2.1)" case ._750cxe_v2_2: return "PVR 00082212 (750cxe_v2.2)" case ._750cxe_v2_3: return "PVR 00082213 (750cxe_v2.3)" case ._750cxe_v2_4: return "PVR 00082214 (750cxe_v2.4)" case ._750cxe_v3_0: return "PVR 00082310 (750cxe_v3.0)" case ._750cxe_v3_1: return "PVR 00082311 (750cxe_v3.1)" case ._745_v1_0: return "PVR 00083100 (745_v1.0)" case ._755_v1_0: return "PVR 00083100 (755_v1.0)" case ._745_v1_1: return "PVR 00083101 (745_v1.1)" case ._755_v1_1: return "PVR 00083101 (755_v1.1)" case ._745_v2_0: return "PVR 00083200 (745_v2.0)" case ._755_v2_0: return "PVR 00083200 (755_v2.0)" case ._745_v2_1: return "PVR 00083201 (745_v2.1)" case ._755_v2_1: return "PVR 00083201 (755_v2.1)" case ._745_v2_2: return "PVR 00083202 (745_v2.2)" case ._755_v2_2: return "PVR 00083202 (755_v2.2)" case ._745_v2_3: return "PVR 00083203 (745_v2.3)" case ._755_v2_3: return "PVR 00083203 (755_v2.3)" case ._745_v2_4: return "PVR 00083204 (745_v2.4)" case ._755_v2_4: return "PVR 00083204 (755_v2.4)" case ._745_v2_5: return "PVR 00083205 (745_v2.5)" case ._755_v2_5: return "PVR 00083205 (755_v2.5)" case ._745_v2_6: return "PVR 00083206 (745_v2.6)" case ._755_v2_6: return "PVR 00083206 (755_v2.6)" case ._745_v2_7: return "PVR 00083207 (745_v2.7)" case ._755_v2_7: return "PVR 00083207 (755_v2.7)" case ._745_v2_8: return "PVR 00083208 (745_v2.8)" case ._755_v2_8: return "PVR 00083208 (755_v2.8)" case ._750cxe_v2_4b: return "PVR 00083214 (750cxe_v2.4b)" case ._750cxe_v3_1b: return "PVR 00083311 (750cxe_v3.1b)" case ._750cxr: return "PVR 00083410 (750cxr)" case ._750cl_v1_0: return "PVR 00087200 (750cl_v1.0)" case ._750cl_v2_0: return "PVR 00087210 (750cl_v2.0)" case ._750l_v2_0: return "PVR 00088200 (750l_v2.0)" case ._750l_v2_1: return "PVR 00088201 (750l_v2.1)" case ._750l_v2_2: return "PVR 00088202 (750l_v2.2)" case ._750l_v3_0: return "PVR 00088300 (750l_v3.0)" case ._750l_v3_2: return "PVR 00088302 (750l_v3.2)" case ._604e_v1_0: return "PVR 00090100 (604e_v1.0)" case ._604e_v2_2: return "PVR 00090202 (604e_v2.2)" case ._604e_v2_4: return "PVR 00090204 (604e_v2.4)" case ._604r: return "PVR 000a0101 (604r)" case ._7400_v1_0: return "PVR 000c0100 (7400_v1.0)" case ._7400_v1_1: return "PVR 000c0101 (7400_v1.1)" case ._7400_v2_0: return "PVR 000c0200 (7400_v2.0)" case ._7400_v2_1: return "PVR 000c0201 (7400_v2.1)" case ._7400_v2_2: return "PVR 000c0202 (7400_v2.2)" case ._7400_v2_6: return "PVR 000c0206 (7400_v2.6)" case ._7400_v2_7: return "PVR 000c0207 (7400_v2.7)" case ._7400_v2_8: return "PVR 000c0208 (7400_v2.8)" case ._7400_v2_9: return "PVR 000c0209 (7400_v2.9)" case .g2: return "PVR 00810011 (g2)" case .mpc603: return "PVR 00810100 (mpc603)" case .g2hip3: return "PVR 00810101 (g2hip3)" case .e300c1: return "PVR 00830010 (e300c1)" case .mpc8343: return "PVR 00830010 (mpc8343)" case .mpc8343a: return "PVR 00830010 (mpc8343a)" case .mpc8343e: return "PVR 00830010 (mpc8343e)" case .mpc8343ea: return "PVR 00830010 (mpc8343ea)" case .mpc8347ap: return "PVR 00830010 (mpc8347ap)" case .mpc8347at: return "PVR 00830010 (mpc8347at)" case .mpc8347eap: return "PVR 00830010 (mpc8347eap)" case .mpc8347eat: return "PVR 00830010 (mpc8347eat)" case .mpc8347ep: return "PVR 00830010 (mpc8347ep)" case .mpc8347et: return "PVR 00830010 (mpc8347et)" case .mpc8347p: return "PVR 00830010 (mpc8347p)" case .mpc8347t: return "PVR 00830010 (mpc8347t)" case .mpc8349: return "PVR 00830010 (mpc8349)" case .mpc8349a: return "PVR 00830010 (mpc8349a)" case .mpc8349e: return "PVR 00830010 (mpc8349e)" case .mpc8349ea: return "PVR 00830010 (mpc8349ea)" case .e300c2: return "PVR 00840010 (e300c2)" case .e300c3: return "PVR 00850010 (e300c3)" case .e300c4: return "PVR 00860010 (e300c4)" case .mpc8377: return "PVR 00860010 (mpc8377)" case .mpc8377e: return "PVR 00860010 (mpc8377e)" case .mpc8378: return "PVR 00860010 (mpc8378)" case .mpc8378e: return "PVR 00860010 (mpc8378e)" case .mpc8379: return "PVR 00860010 (mpc8379)" case .mpc8379e: return "PVR 00860010 (mpc8379e)" case ._740p: return "PVR 10080000 (740p)" case ._750p: return "PVR 10080000 (750p)" case ._460exb: return "PVR 130218a4 (460exb)" case ._440epx: return "PVR 200008d0 (440epx)" case ._405d2: return "PVR 20010000 (405d2)" case .x2vp4: return "PVR 20010820 (x2vp4)" case .x2vp20: return "PVR 20010860 (x2vp20)" case ._405gpa: return "PVR 40110000 (405gpa)" case ._405gpb: return "PVR 40110040 (405gpb)" case ._405cra: return "PVR 40110041 (405cra)" case ._405gpc: return "PVR 40110082 (405gpc)" case ._405gpd: return "PVR 401100c4 (405gpd)" case ._405crb: return "PVR 401100c5 (405crb)" case ._405crc: return "PVR 40110145 (405crc)" case .stb03: return "PVR 40310000 (stb03)" case .npe4gs3: return "PVR 40b10000 (npe4gs3)" case .npe405h: return "PVR 414100c0 (npe405h)" case .npe405h2: return "PVR 41410140 (npe405h2)" case ._405ez: return "PVR 41511460 (405ez)" case .npe405l: return "PVR 416100c0 (npe405l)" case ._405d4: return "PVR 41810000 (405d4)" case .stb04: return "PVR 41810000 (stb04)" case ._405lp: return "PVR 41f10000 (405lp)" case ._440epa: return "PVR 42221850 (440epa)" case ._440epb: return "PVR 422218d3 (440epb)" case ._405gpr: return "PVR 50910951 (405gpr)" case ._405ep: return "PVR 51210950 (405ep)" case .stb25: return "PVR 51510950 (stb25)" case ._750fx_v1_0: return "PVR 70000100 (750fx_v1.0)" case ._750fx_v2_0: return "PVR 70000200 (750fx_v2.0)" case ._750fx_v2_1: return "PVR 70000201 (750fx_v2.1)" case ._750fx_v2_2: return "PVR 70000202 (750fx_v2.2)" case ._750fl: return "PVR 70000203 (750fl)" case ._750fx_v2_3: return "PVR 70000203 (750fx_v2.3)" case ._750gx_v1_0: return "PVR 70020100 (750gx_v1.0)" case ._750gx_v1_1: return "PVR 70020101 (750gx_v1.1)" case ._750gl: return "PVR 70020102 (750gl)" case ._750gx_v1_2: return "PVR 70020102 (750gx_v1.2)" case ._440_xilinx: return "PVR 7ff21910 (440-xilinx)" case ._440_xilinx_w_dfpu: return "PVR 7ff21910 (440-xilinx-w-dfpu)" case ._7450_v1_0: return "PVR 80000100 (7450_v1.0)" case ._7450_v1_1: return "PVR 80000101 (7450_v1.1)" case ._7450_v1_2: return "PVR 80000102 (7450_v1.2)" case ._7450_v2_0: return "PVR 80000200 (7450_v2.0)" case ._7441_v2_1: return "PVR 80000201 (7441_v2.1)" case ._7450_v2_1: return "PVR 80000201 (7450_v2.1)" case ._7441_v2_3: return "PVR 80000203 (7441_v2.3)" case ._7451_v2_3: return "PVR 80000203 (7451_v2.3)" case ._7441_v2_10: return "PVR 80000210 (7441_v2.10)" case ._7451_v2_10: return "PVR 80000210 (7451_v2.10)" case ._7445_v1_0: return "PVR 80010100 (7445_v1.0)" case ._7455_v1_0: return "PVR 80010100 (7455_v1.0)" case ._7445_v2_1: return "PVR 80010201 (7445_v2.1)" case ._7455_v2_1: return "PVR 80010201 (7455_v2.1)" case ._7445_v3_2: return "PVR 80010302 (7445_v3.2)" case ._7455_v3_2: return "PVR 80010302 (7455_v3.2)" case ._7445_v3_3: return "PVR 80010303 (7445_v3.3)" case ._7455_v3_3: return "PVR 80010303 (7455_v3.3)" case ._7445_v3_4: return "PVR 80010304 (7445_v3.4)" case ._7455_v3_4: return "PVR 80010304 (7455_v3.4)" case ._7447_v1_0: return "PVR 80020100 (7447_v1.0)" case ._7457_v1_0: return "PVR 80020100 (7457_v1.0)" case ._7447_v1_1: return "PVR 80020101 (7447_v1.1)" case ._7457_v1_1: return "PVR 80020101 (7457_v1.1)" case ._7457_v1_2: return "PVR 80020102 (7457_v1.2)" case ._7447a_v1_0: return "PVR 80030100 (7447a_v1.0)" case ._7457a_v1_0: return "PVR 80030100 (7457a_v1.0)" case ._7447a_v1_1: return "PVR 80030101 (7447a_v1.1)" case ._7457a_v1_1: return "PVR 80030101 (7457a_v1.1)" case ._7447a_v1_2: return "PVR 80030102 (7447a_v1.2)" case ._7457a_v1_2: return "PVR 80030102 (7457a_v1.2)" case .e600: return "PVR 80040010 (e600)" case .mpc8610: return "PVR 80040010 (mpc8610)" case .mpc8641: return "PVR 80040010 (mpc8641)" case .mpc8641d: return "PVR 80040010 (mpc8641d)" case ._7448_v1_0: return "PVR 80040100 (7448_v1.0)" case ._7448_v1_1: return "PVR 80040101 (7448_v1.1)" case ._7448_v2_0: return "PVR 80040200 (7448_v2.0)" case ._7448_v2_1: return "PVR 80040201 (7448_v2.1)" case ._7410_v1_0: return "PVR 800c1100 (7410_v1.0)" case ._7410_v1_1: return "PVR 800c1101 (7410_v1.1)" case ._7410_v1_2: return "PVR 800c1102 (7410_v1.2)" case ._7410_v1_3: return "PVR 800c1103 (7410_v1.3)" case ._7410_v1_4: return "PVR 800c1104 (7410_v1.4)" case .e500_v10: return "PVR 80200010 (e500_v10)" case .mpc8540_v10: return "PVR 80200010 (mpc8540_v10)" case .mpc8560_v10: return "PVR 80200010 (mpc8560_v10)" case .e500_v20: return "PVR 80200020 (e500_v20)" case .mpc8540_v20: return "PVR 80200020 (mpc8540_v20)" case .mpc8540_v21: return "PVR 80200020 (mpc8540_v21)" case .mpc8541_v10: return "PVR 80200020 (mpc8541_v10)" case .mpc8541_v11: return "PVR 80200020 (mpc8541_v11)" case .mpc8541e_v10: return "PVR 80200020 (mpc8541e_v10)" case .mpc8541e_v11: return "PVR 80200020 (mpc8541e_v11)" case .mpc8555_v10: return "PVR 80200020 (mpc8555_v10)" case .mpc8555_v11: return "PVR 80200020 (mpc8555_v11)" case .mpc8555e_v10: return "PVR 80200020 (mpc8555e_v10)" case .mpc8555e_v11: return "PVR 80200020 (mpc8555e_v11)" case .mpc8560_v20: return "PVR 80200020 (mpc8560_v20)" case .mpc8560_v21: return "PVR 80200020 (mpc8560_v21)" case .e500v2_v10: return "PVR 80210010 (e500v2_v10)" case .mpc8543_v10: return "PVR 80210010 (mpc8543_v10)" case .mpc8543e_v10: return "PVR 80210010 (mpc8543e_v10)" case .mpc8548_v10: return "PVR 80210010 (mpc8548_v10)" case .mpc8548e_v10: return "PVR 80210010 (mpc8548e_v10)" case .mpc8543_v11: return "PVR 80210011 (mpc8543_v11)" case .mpc8543e_v11: return "PVR 80210011 (mpc8543e_v11)" case .mpc8548_v11: return "PVR 80210011 (mpc8548_v11)" case .mpc8548e_v11: return "PVR 80210011 (mpc8548e_v11)" case .e500v2_v20: return "PVR 80210020 (e500v2_v20)" case .mpc8543_v20: return "PVR 80210020 (mpc8543_v20)" case .mpc8543e_v20: return "PVR 80210020 (mpc8543e_v20)" case .mpc8545_v20: return "PVR 80210020 (mpc8545_v20)" case .mpc8545e_v20: return "PVR 80210020 (mpc8545e_v20)" case .mpc8547e_v20: return "PVR 80210020 (mpc8547e_v20)" case .mpc8548_v20: return "PVR 80210020 (mpc8548_v20)" case .mpc8548e_v20: return "PVR 80210020 (mpc8548e_v20)" case .e500v2_v21: return "PVR 80210021 (e500v2_v21)" case .mpc8533_v10: return "PVR 80210021 (mpc8533_v10)" case .mpc8533e_v10: return "PVR 80210021 (mpc8533e_v10)" case .mpc8543_v21: return "PVR 80210021 (mpc8543_v21)" case .mpc8543e_v21: return "PVR 80210021 (mpc8543e_v21)" case .mpc8544_v10: return "PVR 80210021 (mpc8544_v10)" case .mpc8544e_v10: return "PVR 80210021 (mpc8544e_v10)" case .mpc8545_v21: return "PVR 80210021 (mpc8545_v21)" case .mpc8545e_v21: return "PVR 80210021 (mpc8545e_v21)" case .mpc8547e_v21: return "PVR 80210021 (mpc8547e_v21)" case .mpc8548_v21: return "PVR 80210021 (mpc8548_v21)" case .mpc8548e_v21: return "PVR 80210021 (mpc8548e_v21)" case .e500v2_v22: return "PVR 80210022 (e500v2_v22)" case .mpc8533_v11: return "PVR 80210022 (mpc8533_v11)" case .mpc8533e_v11: return "PVR 80210022 (mpc8533e_v11)" case .mpc8544_v11: return "PVR 80210022 (mpc8544_v11)" case .mpc8544e_v11: return "PVR 80210022 (mpc8544e_v11)" case .mpc8567: return "PVR 80210022 (mpc8567)" case .mpc8567e: return "PVR 80210022 (mpc8567e)" case .mpc8568: return "PVR 80210022 (mpc8568)" case .mpc8568e: return "PVR 80210022 (mpc8568e)" case .e500v2_v30: return "PVR 80210030 (e500v2_v30)" case .mpc8572: return "PVR 80210030 (mpc8572)" case .mpc8572e: return "PVR 80210030 (mpc8572e)" case .e500mc: return "PVR 80230020 (e500mc)" case .g2h4: return "PVR 80811010 (g2h4)" case .g2hip4: return "PVR 80811014 (g2hip4)" case .g2le: return "PVR 80820010 (g2le)" case .g2gp: return "PVR 80821010 (g2gp)" case .g2legp: return "PVR 80822010 (g2legp)" case .g2legp1: return "PVR 80822011 (g2legp1)" case .mpc5200_v10: return "PVR 80822011 (mpc5200_v10)" case .mpc5200_v11: return "PVR 80822011 (mpc5200_v11)" case .mpc5200_v12: return "PVR 80822011 (mpc5200_v12)" case .mpc5200b_v20: return "PVR 80822011 (mpc5200b_v20)" case .mpc5200b_v21: return "PVR 80822011 (mpc5200b_v21)" case .g2legp3: return "PVR 80822013 (g2legp3)" case .e200z5: return "PVR 81000000 (e200z5)" case .e200z6: return "PVR 81120000 (e200z6)" case .g2ls: return "PVR 90810010 (g2ls)" case .g2lels: return "PVR a0822010 (g2lels)" case .apollo6: return "apollo6" case .apollo7: return "apollo7" case .apollo7pm: return "apollo7pm" case .arthur: return "arthur" case .conan_doyle: return "conan/doyle" case .e200: return "e200" case .e300: return "e300" case .e500: return "e500" case .e500v1: return "e500v1" case .e500v2: return "e500v2" case .g3: return "g3" case .g4: return "g4" case .goldeneye: return "goldeneye" case .goldfinger: return "goldfinger" case .lonestar: return "lonestar" case .mach5: return "mach5" case .mpc5200: return "mpc5200" case .mpc5200b: return "mpc5200b" case .mpc52xx: return "mpc52xx" case .mpc8240: return "mpc8240" case .mpc8241: return "mpc8241" case .mpc8245: return "mpc8245" case .mpc8247: return "mpc8247" case .mpc8248: return "mpc8248" case .mpc8250: return "mpc8250" case .mpc8250_hip3: return "mpc8250_hip3" case .mpc8250_hip4: return "mpc8250_hip4" case .mpc8255: return "mpc8255" case .mpc8255_hip3: return "mpc8255_hip3" case .mpc8255_hip4: return "mpc8255_hip4" case .mpc8260: return "mpc8260" case .mpc8260_hip3: return "mpc8260_hip3" case .mpc8260_hip4: return "mpc8260_hip4" case .mpc8264: return "mpc8264" case .mpc8264_hip3: return "mpc8264_hip3" case .mpc8264_hip4: return "mpc8264_hip4" case .mpc8265: return "mpc8265" case .mpc8265_hip3: return "mpc8265_hip3" case .mpc8265_hip4: return "mpc8265_hip4" case .mpc8266: return "mpc8266" case .mpc8266_hip3: return "mpc8266_hip3" case .mpc8266_hip4: return "mpc8266_hip4" case .mpc8270: return "mpc8270" case .mpc8271: return "mpc8271" case .mpc8272: return "mpc8272" case .mpc8275: return "mpc8275" case .mpc8280: return "mpc8280" case .mpc82xx: return "mpc82xx" case .mpc8347: return "mpc8347" case .mpc8347a: return "mpc8347a" case .mpc8347e: return "mpc8347e" case .mpc8347ea: return "mpc8347ea" case .mpc8533: return "mpc8533" case .mpc8533e: return "mpc8533e" case .mpc8540: return "mpc8540" case .mpc8541: return "mpc8541" case .mpc8541e: return "mpc8541e" case .mpc8543: return "mpc8543" case .mpc8543e: return "mpc8543e" case .mpc8544: return "mpc8544" case .mpc8544e: return "mpc8544e" case .mpc8545: return "mpc8545" case .mpc8545e: return "mpc8545e" case .mpc8547e: return "mpc8547e" case .mpc8548: return "mpc8548" case .mpc8548e: return "mpc8548e" case .mpc8555: return "mpc8555" case .mpc8555e: return "mpc8555e" case .mpc8560: return "mpc8560" case .nitro: return "nitro" case .powerquicc_ii: return "powerquicc-ii" case .ppc: return "ppc" case .ppc32: return "ppc32" case .sirocco: return "sirocco" case .stretch: return "stretch" case .typhoon: return "typhoon" case .vaillant: return "vaillant" case .vanilla: return "vanilla" case .vger: return "vger" case .x2vp50: return "x2vp50" case .x2vp7: return "x2vp7" } } } enum QEMUCPU_ppc64: 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 _970 = "970" case _970fx = "970fx" case _970mp = "970mp" 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" case _745_v1_1 = "745_v1.1" case _755_v1_1 = "755_v1.1" case _745_v2_0 = "745_v2.0" case _755_v2_0 = "755_v2.0" case _745_v2_1 = "745_v2.1" case _755_v2_1 = "755_v2.1" case _745_v2_2 = "745_v2.2" case _755_v2_2 = "755_v2.2" case _745_v2_3 = "745_v2.3" case _755_v2_3 = "755_v2.3" case _745_v2_4 = "745_v2.4" case _755_v2_4 = "755_v2.4" case _745_v2_5 = "745_v2.5" case _755_v2_5 = "755_v2.5" case _745_v2_6 = "745_v2.6" case _755_v2_6 = "755_v2.6" case _745_v2_7 = "745_v2.7" case _755_v2_7 = "755_v2.7" case _745_v2_8 = "745_v2.8" case _755_v2_8 = "755_v2.8" case _750cxe_v2_4b = "750cxe_v2.4b" case _750cxe_v3_1b = "750cxe_v3.1b" case _750cxr = "750cxr" case _750cl_v1_0 = "750cl_v1.0" case _750cl_v2_0 = "750cl_v2.0" case _750l_v2_0 = "750l_v2.0" case _750l_v2_1 = "750l_v2.1" case _750l_v2_2 = "750l_v2.2" case _750l_v3_0 = "750l_v3.0" case _750l_v3_2 = "750l_v3.2" case _604e_v1_0 = "604e_v1.0" case _604e_v2_2 = "604e_v2.2" case _604e_v2_4 = "604e_v2.4" case _604r = "604r" case _7400_v1_0 = "7400_v1.0" case _7400_v1_1 = "7400_v1.1" case _7400_v2_0 = "7400_v2.0" case _7400_v2_1 = "7400_v2.1" case _7400_v2_2 = "7400_v2.2" case _7400_v2_6 = "7400_v2.6" case _7400_v2_7 = "7400_v2.7" case _7400_v2_8 = "7400_v2.8" case _7400_v2_9 = "7400_v2.9" case _970_v2_2 = "970_v2.2" case _970fx_v1_0 = "970fx_v1.0" case power5p_v2_1 = "power5p_v2.1" case _970fx_v2_0 = "970fx_v2.0" case _970fx_v2_1 = "970fx_v2.1" case _970fx_v3_0 = "970fx_v3.0" case _970fx_v3_1 = "970fx_v3.1" case power7_v2_3 = "power7_v2.3" case _970mp_v1_0 = "970mp_v1.0" case _970mp_v1_1 = "970mp_v1.1" case power7p_v2_1 = "power7p_v2.1" case power8e_v2_1 = "power8e_v2.1" case power8nvl_v1_0 = "power8nvl_v1.0" case power8_v2_0 = "power8_v2.0" case power9_v2_0 = "power9_v2.0" case power9_v2_2 = "power9_v2.2" case power10_v2_0 = "power10_v2.0" case g2 case mpc603 case g2hip3 case power11_v2_0 = "power11_v2.0" case e300c1 case mpc8343 case mpc8343a case mpc8343e case mpc8343ea case mpc8347ap case mpc8347at case mpc8347eap case mpc8347eat case mpc8347ep case mpc8347et case mpc8347p case mpc8347t case mpc8349 case mpc8349a case mpc8349e case mpc8349ea case e300c2 case e300c3 case e300c4 case mpc8377 case mpc8377e case mpc8378 case mpc8378e case mpc8379 case mpc8379e case _740p = "740p" case _750p = "750p" case _460exb = "460exb" case _440epx = "440epx" case _405d2 = "405d2" case x2vp4 case x2vp20 case _405gpa = "405gpa" case _405gpb = "405gpb" case _405cra = "405cra" case _405gpc = "405gpc" case _405gpd = "405gpd" case _405crb = "405crb" case _405crc = "405crc" case stb03 case npe4gs3 case npe405h case npe405h2 case _405ez = "405ez" case npe405l case _405d4 = "405d4" case stb04 case _405lp = "405lp" case _440epa = "440epa" case _440epb = "440epb" case _405gpr = "405gpr" case _405ep = "405ep" case stb25 case _750fx_v1_0 = "750fx_v1.0" case _750fx_v2_0 = "750fx_v2.0" case _750fx_v2_1 = "750fx_v2.1" case _750fx_v2_2 = "750fx_v2.2" case _750fl = "750fl" case _750fx_v2_3 = "750fx_v2.3" case _750gx_v1_0 = "750gx_v1.0" case _750gx_v1_1 = "750gx_v1.1" case _750gl = "750gl" case _750gx_v1_2 = "750gx_v1.2" case _440_xilinx = "440-xilinx" case _440_xilinx_w_dfpu = "440-xilinx-w-dfpu" case _7450_v1_0 = "7450_v1.0" case _7450_v1_1 = "7450_v1.1" case _7450_v1_2 = "7450_v1.2" case _7450_v2_0 = "7450_v2.0" case _7441_v2_1 = "7441_v2.1" case _7450_v2_1 = "7450_v2.1" case _7441_v2_3 = "7441_v2.3" case _7451_v2_3 = "7451_v2.3" case _7441_v2_10 = "7441_v2.10" case _7451_v2_10 = "7451_v2.10" case _7445_v1_0 = "7445_v1.0" case _7455_v1_0 = "7455_v1.0" case _7445_v2_1 = "7445_v2.1" case _7455_v2_1 = "7455_v2.1" case _7445_v3_2 = "7445_v3.2" case _7455_v3_2 = "7455_v3.2" case _7445_v3_3 = "7445_v3.3" case _7455_v3_3 = "7455_v3.3" case _7445_v3_4 = "7445_v3.4" case _7455_v3_4 = "7455_v3.4" case _7447_v1_0 = "7447_v1.0" case _7457_v1_0 = "7457_v1.0" case _7447_v1_1 = "7447_v1.1" case _7457_v1_1 = "7457_v1.1" case _7457_v1_2 = "7457_v1.2" case _7447a_v1_0 = "7447a_v1.0" case _7457a_v1_0 = "7457a_v1.0" case _7447a_v1_1 = "7447a_v1.1" case _7457a_v1_1 = "7457a_v1.1" case _7447a_v1_2 = "7447a_v1.2" case _7457a_v1_2 = "7457a_v1.2" case e600 case mpc8610 case mpc8641 case mpc8641d case _7448_v1_0 = "7448_v1.0" case _7448_v1_1 = "7448_v1.1" case _7448_v2_0 = "7448_v2.0" case _7448_v2_1 = "7448_v2.1" case _7410_v1_0 = "7410_v1.0" case _7410_v1_1 = "7410_v1.1" case _7410_v1_2 = "7410_v1.2" case _7410_v1_3 = "7410_v1.3" case _7410_v1_4 = "7410_v1.4" case e500_v10 case mpc8540_v10 case mpc8560_v10 case e500_v20 case mpc8540_v20 case mpc8540_v21 case mpc8541_v10 case mpc8541_v11 case mpc8541e_v10 case mpc8541e_v11 case mpc8555_v10 case mpc8555_v11 case mpc8555e_v10 case mpc8555e_v11 case mpc8560_v20 case mpc8560_v21 case e500v2_v10 case mpc8543_v10 case mpc8543e_v10 case mpc8548_v10 case mpc8548e_v10 case mpc8543_v11 case mpc8543e_v11 case mpc8548_v11 case mpc8548e_v11 case e500v2_v20 case mpc8543_v20 case mpc8543e_v20 case mpc8545_v20 case mpc8545e_v20 case mpc8547e_v20 case mpc8548_v20 case mpc8548e_v20 case e500v2_v21 case mpc8533_v10 case mpc8533e_v10 case mpc8543_v21 case mpc8543e_v21 case mpc8544_v10 case mpc8544e_v10 case mpc8545_v21 case mpc8545e_v21 case mpc8547e_v21 case mpc8548_v21 case mpc8548e_v21 case e500v2_v22 case mpc8533_v11 case mpc8533e_v11 case mpc8544_v11 case mpc8544e_v11 case mpc8567 case mpc8567e case mpc8568 case mpc8568e case e500v2_v30 case mpc8572 case mpc8572e case e500mc case e5500 case e6500 case g2h4 case g2hip4 case g2le case g2gp case g2legp case g2legp1 case mpc5200_v10 case mpc5200_v11 case mpc5200_v12 case mpc5200b_v20 case mpc5200b_v21 case g2legp3 case e200z5 case e200z6 case g2ls case g2lels case apollo6 case apollo7 case apollo7pm case arthur case conan_doyle = "conan/doyle" case e200 case e300 case e500 case e500v1 case e500v2 case g3 case g4 case goldeneye case goldfinger case lonestar case mach5 case mpc5200 case mpc5200b case mpc52xx case mpc8240 case mpc8241 case mpc8245 case mpc8247 case mpc8248 case mpc8250 case mpc8250_hip3 case mpc8250_hip4 case mpc8255 case mpc8255_hip3 case mpc8255_hip4 case mpc8260 case mpc8260_hip3 case mpc8260_hip4 case mpc8264 case mpc8264_hip3 case mpc8264_hip4 case mpc8265 case mpc8265_hip3 case mpc8265_hip4 case mpc8266 case mpc8266_hip3 case mpc8266_hip4 case mpc8270 case mpc8271 case mpc8272 case mpc8275 case mpc8280 case mpc82xx case mpc8347 case mpc8347a case mpc8347e case mpc8347ea case mpc8533 case mpc8533e case mpc8540 case mpc8541 case mpc8541e case mpc8543 case mpc8543e case mpc8544 case mpc8544e case mpc8545 case mpc8545e case mpc8547e case mpc8548 case mpc8548e case mpc8555 case mpc8555e case mpc8560 case nitro case power10 case power11 case power5_ = "power5+" case power5_v2_1 = "power5+_v2.1" case power5gs case power7 case power7_ = "power7+" case power7_v2_1 = "power7+_v2.1" case power8 case power8e case power8nvl case power9 case powerquicc_ii = "powerquicc-ii" case ppc case ppc32 case ppc64 case sirocco case stretch case typhoon case vaillant case vanilla case vger case x2vp50 case x2vp7 var prettyValue: String { switch self { case ._405: return "405" case ._405cr: return "405cr" case ._405gp: return "405gp" case ._405gpe: return "405gpe" case ._440ep: return "440ep" case ._460ex: return "460ex" case ._603e: return "603e" case ._603r: return "603r" case ._604e: return "604e" case ._740: return "740" case ._7400: return "7400" case ._7410: return "7410" case ._7441: return "7441" case ._7445: return "7445" case ._7447: return "7447" case ._7447a: return "7447a" case ._7448: return "7448" case ._745: return "745" case ._7450: return "7450" case ._7451: return "7451" case ._7455: return "7455" case ._7457: return "7457" case ._7457a: return "7457a" case ._750: return "750" case ._750cl: return "750cl" case ._750cx: return "750cx" case ._750cxe: return "750cxe" case ._750fx: return "750fx" case ._750gx: return "750gx" case ._750l: return "750l" case ._755: return "755" case ._970: return "970" case ._970fx: return "970fx" case ._970mp: return "970mp" case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case ._603: return "PVR 00030100 (603)" case ._604: return "PVR 00040103 (604)" case ._603e_v1_1: return "PVR 00060101 (603e_v1.1)" case ._603e_v1_2: return "PVR 00060102 (603e_v1.2)" case ._603e_v1_3: return "PVR 00060103 (603e_v1.3)" case ._603e_v1_4: return "PVR 00060104 (603e_v1.4)" case ._603e_v2_2: return "PVR 00060202 (603e_v2.2)" case ._603e_v3: return "PVR 00060300 (603e_v3)" case ._603e_v4: return "PVR 00060400 (603e_v4)" case ._603e_v4_1: return "PVR 00060401 (603e_v4.1)" case ._603p: return "PVR 00070000 (603p)" case ._603e7v: return "PVR 00070100 (603e7v)" case ._603e7v1: return "PVR 00070101 (603e7v1)" case ._603e7: return "PVR 00070200 (603e7)" case ._603e7v2: return "PVR 00070201 (603e7v2)" case ._603e7t: return "PVR 00071201 (603e7t)" case ._740_v1_0: return "PVR 00080100 (740_v1.0)" case ._740e: return "PVR 00080100 (740e)" case ._750_v1_0: return "PVR 00080100 (750_v1.0)" case ._740_v2_0: return "PVR 00080200 (740_v2.0)" case ._750_v2_0: return "PVR 00080200 (750_v2.0)" case ._750e: return "PVR 00080200 (750e)" case ._740_v2_1: return "PVR 00080201 (740_v2.1)" case ._750_v2_1: return "PVR 00080201 (750_v2.1)" case ._740_v2_2: return "PVR 00080202 (740_v2.2)" case ._750_v2_2: return "PVR 00080202 (750_v2.2)" case ._740_v3_0: return "PVR 00080300 (740_v3.0)" case ._750_v3_0: return "PVR 00080300 (750_v3.0)" case ._740_v3_1: return "PVR 00080301 (740_v3.1)" case ._750_v3_1: return "PVR 00080301 (750_v3.1)" case ._750cx_v1_0: return "PVR 00082100 (750cx_v1.0)" case ._750cx_v2_0: return "PVR 00082200 (750cx_v2.0)" case ._750cx_v2_1: return "PVR 00082201 (750cx_v2.1)" case ._750cx_v2_2: return "PVR 00082202 (750cx_v2.2)" case ._750cxe_v2_1: return "PVR 00082211 (750cxe_v2.1)" case ._750cxe_v2_2: return "PVR 00082212 (750cxe_v2.2)" case ._750cxe_v2_3: return "PVR 00082213 (750cxe_v2.3)" case ._750cxe_v2_4: return "PVR 00082214 (750cxe_v2.4)" case ._750cxe_v3_0: return "PVR 00082310 (750cxe_v3.0)" case ._750cxe_v3_1: return "PVR 00082311 (750cxe_v3.1)" case ._745_v1_0: return "PVR 00083100 (745_v1.0)" case ._755_v1_0: return "PVR 00083100 (755_v1.0)" case ._745_v1_1: return "PVR 00083101 (745_v1.1)" case ._755_v1_1: return "PVR 00083101 (755_v1.1)" case ._745_v2_0: return "PVR 00083200 (745_v2.0)" case ._755_v2_0: return "PVR 00083200 (755_v2.0)" case ._745_v2_1: return "PVR 00083201 (745_v2.1)" case ._755_v2_1: return "PVR 00083201 (755_v2.1)" case ._745_v2_2: return "PVR 00083202 (745_v2.2)" case ._755_v2_2: return "PVR 00083202 (755_v2.2)" case ._745_v2_3: return "PVR 00083203 (745_v2.3)" case ._755_v2_3: return "PVR 00083203 (755_v2.3)" case ._745_v2_4: return "PVR 00083204 (745_v2.4)" case ._755_v2_4: return "PVR 00083204 (755_v2.4)" case ._745_v2_5: return "PVR 00083205 (745_v2.5)" case ._755_v2_5: return "PVR 00083205 (755_v2.5)" case ._745_v2_6: return "PVR 00083206 (745_v2.6)" case ._755_v2_6: return "PVR 00083206 (755_v2.6)" case ._745_v2_7: return "PVR 00083207 (745_v2.7)" case ._755_v2_7: return "PVR 00083207 (755_v2.7)" case ._745_v2_8: return "PVR 00083208 (745_v2.8)" case ._755_v2_8: return "PVR 00083208 (755_v2.8)" case ._750cxe_v2_4b: return "PVR 00083214 (750cxe_v2.4b)" case ._750cxe_v3_1b: return "PVR 00083311 (750cxe_v3.1b)" case ._750cxr: return "PVR 00083410 (750cxr)" case ._750cl_v1_0: return "PVR 00087200 (750cl_v1.0)" case ._750cl_v2_0: return "PVR 00087210 (750cl_v2.0)" case ._750l_v2_0: return "PVR 00088200 (750l_v2.0)" case ._750l_v2_1: return "PVR 00088201 (750l_v2.1)" case ._750l_v2_2: return "PVR 00088202 (750l_v2.2)" case ._750l_v3_0: return "PVR 00088300 (750l_v3.0)" case ._750l_v3_2: return "PVR 00088302 (750l_v3.2)" case ._604e_v1_0: return "PVR 00090100 (604e_v1.0)" case ._604e_v2_2: return "PVR 00090202 (604e_v2.2)" case ._604e_v2_4: return "PVR 00090204 (604e_v2.4)" case ._604r: return "PVR 000a0101 (604r)" case ._7400_v1_0: return "PVR 000c0100 (7400_v1.0)" case ._7400_v1_1: return "PVR 000c0101 (7400_v1.1)" case ._7400_v2_0: return "PVR 000c0200 (7400_v2.0)" case ._7400_v2_1: return "PVR 000c0201 (7400_v2.1)" case ._7400_v2_2: return "PVR 000c0202 (7400_v2.2)" case ._7400_v2_6: return "PVR 000c0206 (7400_v2.6)" case ._7400_v2_7: return "PVR 000c0207 (7400_v2.7)" case ._7400_v2_8: return "PVR 000c0208 (7400_v2.8)" case ._7400_v2_9: return "PVR 000c0209 (7400_v2.9)" case ._970_v2_2: return "PVR 00390202 (970_v2.2)" case ._970fx_v1_0: return "PVR 00391100 (970fx_v1.0)" case .power5p_v2_1: return "PVR 003b0201 (power5p_v2.1)" case ._970fx_v2_0: return "PVR 003c0200 (970fx_v2.0)" case ._970fx_v2_1: return "PVR 003c0201 (970fx_v2.1)" case ._970fx_v3_0: return "PVR 003c0300 (970fx_v3.0)" case ._970fx_v3_1: return "PVR 003c0301 (970fx_v3.1)" case .power7_v2_3: return "PVR 003f0203 (power7_v2.3)" case ._970mp_v1_0: return "PVR 00440100 (970mp_v1.0)" case ._970mp_v1_1: return "PVR 00440101 (970mp_v1.1)" case .power7p_v2_1: return "PVR 004a0201 (power7p_v2.1)" case .power8e_v2_1: return "PVR 004b0201 (power8e_v2.1)" case .power8nvl_v1_0: return "PVR 004c0100 (power8nvl_v1.0)" case .power8_v2_0: return "PVR 004d0200 (power8_v2.0)" case .power9_v2_0: return "PVR 004e1200 (power9_v2.0)" case .power9_v2_2: return "PVR 004e1202 (power9_v2.2)" case .power10_v2_0: return "PVR 00801200 (power10_v2.0)" case .g2: return "PVR 00810011 (g2)" case .mpc603: return "PVR 00810100 (mpc603)" case .g2hip3: return "PVR 00810101 (g2hip3)" case .power11_v2_0: return "PVR 00821200 (power11_v2.0)" case .e300c1: return "PVR 00830010 (e300c1)" case .mpc8343: return "PVR 00830010 (mpc8343)" case .mpc8343a: return "PVR 00830010 (mpc8343a)" case .mpc8343e: return "PVR 00830010 (mpc8343e)" case .mpc8343ea: return "PVR 00830010 (mpc8343ea)" case .mpc8347ap: return "PVR 00830010 (mpc8347ap)" case .mpc8347at: return "PVR 00830010 (mpc8347at)" case .mpc8347eap: return "PVR 00830010 (mpc8347eap)" case .mpc8347eat: return "PVR 00830010 (mpc8347eat)" case .mpc8347ep: return "PVR 00830010 (mpc8347ep)" case .mpc8347et: return "PVR 00830010 (mpc8347et)" case .mpc8347p: return "PVR 00830010 (mpc8347p)" case .mpc8347t: return "PVR 00830010 (mpc8347t)" case .mpc8349: return "PVR 00830010 (mpc8349)" case .mpc8349a: return "PVR 00830010 (mpc8349a)" case .mpc8349e: return "PVR 00830010 (mpc8349e)" case .mpc8349ea: return "PVR 00830010 (mpc8349ea)" case .e300c2: return "PVR 00840010 (e300c2)" case .e300c3: return "PVR 00850010 (e300c3)" case .e300c4: return "PVR 00860010 (e300c4)" case .mpc8377: return "PVR 00860010 (mpc8377)" case .mpc8377e: return "PVR 00860010 (mpc8377e)" case .mpc8378: return "PVR 00860010 (mpc8378)" case .mpc8378e: return "PVR 00860010 (mpc8378e)" case .mpc8379: return "PVR 00860010 (mpc8379)" case .mpc8379e: return "PVR 00860010 (mpc8379e)" case ._740p: return "PVR 10080000 (740p)" case ._750p: return "PVR 10080000 (750p)" case ._460exb: return "PVR 130218a4 (460exb)" case ._440epx: return "PVR 200008d0 (440epx)" case ._405d2: return "PVR 20010000 (405d2)" case .x2vp4: return "PVR 20010820 (x2vp4)" case .x2vp20: return "PVR 20010860 (x2vp20)" case ._405gpa: return "PVR 40110000 (405gpa)" case ._405gpb: return "PVR 40110040 (405gpb)" case ._405cra: return "PVR 40110041 (405cra)" case ._405gpc: return "PVR 40110082 (405gpc)" case ._405gpd: return "PVR 401100c4 (405gpd)" case ._405crb: return "PVR 401100c5 (405crb)" case ._405crc: return "PVR 40110145 (405crc)" case .stb03: return "PVR 40310000 (stb03)" case .npe4gs3: return "PVR 40b10000 (npe4gs3)" case .npe405h: return "PVR 414100c0 (npe405h)" case .npe405h2: return "PVR 41410140 (npe405h2)" case ._405ez: return "PVR 41511460 (405ez)" case .npe405l: return "PVR 416100c0 (npe405l)" case ._405d4: return "PVR 41810000 (405d4)" case .stb04: return "PVR 41810000 (stb04)" case ._405lp: return "PVR 41f10000 (405lp)" case ._440epa: return "PVR 42221850 (440epa)" case ._440epb: return "PVR 422218d3 (440epb)" case ._405gpr: return "PVR 50910951 (405gpr)" case ._405ep: return "PVR 51210950 (405ep)" case .stb25: return "PVR 51510950 (stb25)" case ._750fx_v1_0: return "PVR 70000100 (750fx_v1.0)" case ._750fx_v2_0: return "PVR 70000200 (750fx_v2.0)" case ._750fx_v2_1: return "PVR 70000201 (750fx_v2.1)" case ._750fx_v2_2: return "PVR 70000202 (750fx_v2.2)" case ._750fl: return "PVR 70000203 (750fl)" case ._750fx_v2_3: return "PVR 70000203 (750fx_v2.3)" case ._750gx_v1_0: return "PVR 70020100 (750gx_v1.0)" case ._750gx_v1_1: return "PVR 70020101 (750gx_v1.1)" case ._750gl: return "PVR 70020102 (750gl)" case ._750gx_v1_2: return "PVR 70020102 (750gx_v1.2)" case ._440_xilinx: return "PVR 7ff21910 (440-xilinx)" case ._440_xilinx_w_dfpu: return "PVR 7ff21910 (440-xilinx-w-dfpu)" case ._7450_v1_0: return "PVR 80000100 (7450_v1.0)" case ._7450_v1_1: return "PVR 80000101 (7450_v1.1)" case ._7450_v1_2: return "PVR 80000102 (7450_v1.2)" case ._7450_v2_0: return "PVR 80000200 (7450_v2.0)" case ._7441_v2_1: return "PVR 80000201 (7441_v2.1)" case ._7450_v2_1: return "PVR 80000201 (7450_v2.1)" case ._7441_v2_3: return "PVR 80000203 (7441_v2.3)" case ._7451_v2_3: return "PVR 80000203 (7451_v2.3)" case ._7441_v2_10: return "PVR 80000210 (7441_v2.10)" case ._7451_v2_10: return "PVR 80000210 (7451_v2.10)" case ._7445_v1_0: return "PVR 80010100 (7445_v1.0)" case ._7455_v1_0: return "PVR 80010100 (7455_v1.0)" case ._7445_v2_1: return "PVR 80010201 (7445_v2.1)" case ._7455_v2_1: return "PVR 80010201 (7455_v2.1)" case ._7445_v3_2: return "PVR 80010302 (7445_v3.2)" case ._7455_v3_2: return "PVR 80010302 (7455_v3.2)" case ._7445_v3_3: return "PVR 80010303 (7445_v3.3)" case ._7455_v3_3: return "PVR 80010303 (7455_v3.3)" case ._7445_v3_4: return "PVR 80010304 (7445_v3.4)" case ._7455_v3_4: return "PVR 80010304 (7455_v3.4)" case ._7447_v1_0: return "PVR 80020100 (7447_v1.0)" case ._7457_v1_0: return "PVR 80020100 (7457_v1.0)" case ._7447_v1_1: return "PVR 80020101 (7447_v1.1)" case ._7457_v1_1: return "PVR 80020101 (7457_v1.1)" case ._7457_v1_2: return "PVR 80020102 (7457_v1.2)" case ._7447a_v1_0: return "PVR 80030100 (7447a_v1.0)" case ._7457a_v1_0: return "PVR 80030100 (7457a_v1.0)" case ._7447a_v1_1: return "PVR 80030101 (7447a_v1.1)" case ._7457a_v1_1: return "PVR 80030101 (7457a_v1.1)" case ._7447a_v1_2: return "PVR 80030102 (7447a_v1.2)" case ._7457a_v1_2: return "PVR 80030102 (7457a_v1.2)" case .e600: return "PVR 80040010 (e600)" case .mpc8610: return "PVR 80040010 (mpc8610)" case .mpc8641: return "PVR 80040010 (mpc8641)" case .mpc8641d: return "PVR 80040010 (mpc8641d)" case ._7448_v1_0: return "PVR 80040100 (7448_v1.0)" case ._7448_v1_1: return "PVR 80040101 (7448_v1.1)" case ._7448_v2_0: return "PVR 80040200 (7448_v2.0)" case ._7448_v2_1: return "PVR 80040201 (7448_v2.1)" case ._7410_v1_0: return "PVR 800c1100 (7410_v1.0)" case ._7410_v1_1: return "PVR 800c1101 (7410_v1.1)" case ._7410_v1_2: return "PVR 800c1102 (7410_v1.2)" case ._7410_v1_3: return "PVR 800c1103 (7410_v1.3)" case ._7410_v1_4: return "PVR 800c1104 (7410_v1.4)" case .e500_v10: return "PVR 80200010 (e500_v10)" case .mpc8540_v10: return "PVR 80200010 (mpc8540_v10)" case .mpc8560_v10: return "PVR 80200010 (mpc8560_v10)" case .e500_v20: return "PVR 80200020 (e500_v20)" case .mpc8540_v20: return "PVR 80200020 (mpc8540_v20)" case .mpc8540_v21: return "PVR 80200020 (mpc8540_v21)" case .mpc8541_v10: return "PVR 80200020 (mpc8541_v10)" case .mpc8541_v11: return "PVR 80200020 (mpc8541_v11)" case .mpc8541e_v10: return "PVR 80200020 (mpc8541e_v10)" case .mpc8541e_v11: return "PVR 80200020 (mpc8541e_v11)" case .mpc8555_v10: return "PVR 80200020 (mpc8555_v10)" case .mpc8555_v11: return "PVR 80200020 (mpc8555_v11)" case .mpc8555e_v10: return "PVR 80200020 (mpc8555e_v10)" case .mpc8555e_v11: return "PVR 80200020 (mpc8555e_v11)" case .mpc8560_v20: return "PVR 80200020 (mpc8560_v20)" case .mpc8560_v21: return "PVR 80200020 (mpc8560_v21)" case .e500v2_v10: return "PVR 80210010 (e500v2_v10)" case .mpc8543_v10: return "PVR 80210010 (mpc8543_v10)" case .mpc8543e_v10: return "PVR 80210010 (mpc8543e_v10)" case .mpc8548_v10: return "PVR 80210010 (mpc8548_v10)" case .mpc8548e_v10: return "PVR 80210010 (mpc8548e_v10)" case .mpc8543_v11: return "PVR 80210011 (mpc8543_v11)" case .mpc8543e_v11: return "PVR 80210011 (mpc8543e_v11)" case .mpc8548_v11: return "PVR 80210011 (mpc8548_v11)" case .mpc8548e_v11: return "PVR 80210011 (mpc8548e_v11)" case .e500v2_v20: return "PVR 80210020 (e500v2_v20)" case .mpc8543_v20: return "PVR 80210020 (mpc8543_v20)" case .mpc8543e_v20: return "PVR 80210020 (mpc8543e_v20)" case .mpc8545_v20: return "PVR 80210020 (mpc8545_v20)" case .mpc8545e_v20: return "PVR 80210020 (mpc8545e_v20)" case .mpc8547e_v20: return "PVR 80210020 (mpc8547e_v20)" case .mpc8548_v20: return "PVR 80210020 (mpc8548_v20)" case .mpc8548e_v20: return "PVR 80210020 (mpc8548e_v20)" case .e500v2_v21: return "PVR 80210021 (e500v2_v21)" case .mpc8533_v10: return "PVR 80210021 (mpc8533_v10)" case .mpc8533e_v10: return "PVR 80210021 (mpc8533e_v10)" case .mpc8543_v21: return "PVR 80210021 (mpc8543_v21)" case .mpc8543e_v21: return "PVR 80210021 (mpc8543e_v21)" case .mpc8544_v10: return "PVR 80210021 (mpc8544_v10)" case .mpc8544e_v10: return "PVR 80210021 (mpc8544e_v10)" case .mpc8545_v21: return "PVR 80210021 (mpc8545_v21)" case .mpc8545e_v21: return "PVR 80210021 (mpc8545e_v21)" case .mpc8547e_v21: return "PVR 80210021 (mpc8547e_v21)" case .mpc8548_v21: return "PVR 80210021 (mpc8548_v21)" case .mpc8548e_v21: return "PVR 80210021 (mpc8548e_v21)" case .e500v2_v22: return "PVR 80210022 (e500v2_v22)" case .mpc8533_v11: return "PVR 80210022 (mpc8533_v11)" case .mpc8533e_v11: return "PVR 80210022 (mpc8533e_v11)" case .mpc8544_v11: return "PVR 80210022 (mpc8544_v11)" case .mpc8544e_v11: return "PVR 80210022 (mpc8544e_v11)" case .mpc8567: return "PVR 80210022 (mpc8567)" case .mpc8567e: return "PVR 80210022 (mpc8567e)" case .mpc8568: return "PVR 80210022 (mpc8568)" case .mpc8568e: return "PVR 80210022 (mpc8568e)" case .e500v2_v30: return "PVR 80210030 (e500v2_v30)" case .mpc8572: return "PVR 80210030 (mpc8572)" case .mpc8572e: return "PVR 80210030 (mpc8572e)" case .e500mc: return "PVR 80230020 (e500mc)" case .e5500: return "PVR 80240020 (e5500)" case .e6500: return "PVR 80400020 (e6500)" case .g2h4: return "PVR 80811010 (g2h4)" case .g2hip4: return "PVR 80811014 (g2hip4)" case .g2le: return "PVR 80820010 (g2le)" case .g2gp: return "PVR 80821010 (g2gp)" case .g2legp: return "PVR 80822010 (g2legp)" case .g2legp1: return "PVR 80822011 (g2legp1)" case .mpc5200_v10: return "PVR 80822011 (mpc5200_v10)" case .mpc5200_v11: return "PVR 80822011 (mpc5200_v11)" case .mpc5200_v12: return "PVR 80822011 (mpc5200_v12)" case .mpc5200b_v20: return "PVR 80822011 (mpc5200b_v20)" case .mpc5200b_v21: return "PVR 80822011 (mpc5200b_v21)" case .g2legp3: return "PVR 80822013 (g2legp3)" case .e200z5: return "PVR 81000000 (e200z5)" case .e200z6: return "PVR 81120000 (e200z6)" case .g2ls: return "PVR 90810010 (g2ls)" case .g2lels: return "PVR a0822010 (g2lels)" case .apollo6: return "apollo6" case .apollo7: return "apollo7" case .apollo7pm: return "apollo7pm" case .arthur: return "arthur" case .conan_doyle: return "conan/doyle" case .e200: return "e200" case .e300: return "e300" case .e500: return "e500" case .e500v1: return "e500v1" case .e500v2: return "e500v2" case .g3: return "g3" case .g4: return "g4" case .goldeneye: return "goldeneye" case .goldfinger: return "goldfinger" case .lonestar: return "lonestar" case .mach5: return "mach5" case .mpc5200: return "mpc5200" case .mpc5200b: return "mpc5200b" case .mpc52xx: return "mpc52xx" case .mpc8240: return "mpc8240" case .mpc8241: return "mpc8241" case .mpc8245: return "mpc8245" case .mpc8247: return "mpc8247" case .mpc8248: return "mpc8248" case .mpc8250: return "mpc8250" case .mpc8250_hip3: return "mpc8250_hip3" case .mpc8250_hip4: return "mpc8250_hip4" case .mpc8255: return "mpc8255" case .mpc8255_hip3: return "mpc8255_hip3" case .mpc8255_hip4: return "mpc8255_hip4" case .mpc8260: return "mpc8260" case .mpc8260_hip3: return "mpc8260_hip3" case .mpc8260_hip4: return "mpc8260_hip4" case .mpc8264: return "mpc8264" case .mpc8264_hip3: return "mpc8264_hip3" case .mpc8264_hip4: return "mpc8264_hip4" case .mpc8265: return "mpc8265" case .mpc8265_hip3: return "mpc8265_hip3" case .mpc8265_hip4: return "mpc8265_hip4" case .mpc8266: return "mpc8266" case .mpc8266_hip3: return "mpc8266_hip3" case .mpc8266_hip4: return "mpc8266_hip4" case .mpc8270: return "mpc8270" case .mpc8271: return "mpc8271" case .mpc8272: return "mpc8272" case .mpc8275: return "mpc8275" case .mpc8280: return "mpc8280" case .mpc82xx: return "mpc82xx" case .mpc8347: return "mpc8347" case .mpc8347a: return "mpc8347a" case .mpc8347e: return "mpc8347e" case .mpc8347ea: return "mpc8347ea" case .mpc8533: return "mpc8533" case .mpc8533e: return "mpc8533e" case .mpc8540: return "mpc8540" case .mpc8541: return "mpc8541" case .mpc8541e: return "mpc8541e" case .mpc8543: return "mpc8543" case .mpc8543e: return "mpc8543e" case .mpc8544: return "mpc8544" case .mpc8544e: return "mpc8544e" case .mpc8545: return "mpc8545" case .mpc8545e: return "mpc8545e" case .mpc8547e: return "mpc8547e" case .mpc8548: return "mpc8548" case .mpc8548e: return "mpc8548e" case .mpc8555: return "mpc8555" case .mpc8555e: return "mpc8555e" case .mpc8560: return "mpc8560" case .nitro: return "nitro" case .power10: return "power10" case .power11: return "power11" case .power5_: return "power5+" case .power5_v2_1: return "power5+_v2.1" case .power5gs: return "power5gs" case .power7: return "power7" case .power7_: return "power7+" case .power7_v2_1: return "power7+_v2.1" case .power8: return "power8" case .power8e: return "power8e" case .power8nvl: return "power8nvl" case .power9: return "power9" case .powerquicc_ii: return "powerquicc-ii" case .ppc: return "ppc" case .ppc32: return "ppc32" case .ppc64: return "ppc64" case .sirocco: return "sirocco" case .stretch: return "stretch" case .typhoon: return "typhoon" case .vaillant: return "vaillant" case .vanilla: return "vanilla" case .vger: return "vger" case .x2vp50: return "x2vp50" case .x2vp7: return "x2vp7" } } } enum QEMUCPU_riscv32: String, CaseIterable, QEMUCPU { case `default` = "default" case lowrisc_ibex = "lowrisc-ibex" case max case rv32 case rv32e case rv32i case sifive_e31 = "sifive-e31" case sifive_e34 = "sifive-e34" case sifive_u34 = "sifive-u34" var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .lowrisc_ibex: return "lowrisc-ibex" case .max: return "max" case .rv32: return "rv32" case .rv32e: return "rv32e" case .rv32i: return "rv32i" case .sifive_e31: return "sifive-e31" case .sifive_e34: return "sifive-e34" case .sifive_u34: return "sifive-u34" } } } enum QEMUCPU_riscv64: String, CaseIterable, QEMUCPU { case `default` = "default" case lowrisc_ibex = "lowrisc-ibex" case max case max32 case rv32 case rv32e case rv32i case rv64 case rv64e case rv64i case rva22s64 case rva22u64 case rva23s64 case rva23u64 case shakti_c = "shakti-c" case sifive_e31 = "sifive-e31" case sifive_e34 = "sifive-e34" case sifive_e51 = "sifive-e51" case sifive_u34 = "sifive-u34" case sifive_u54 = "sifive-u54" case thead_c906 = "thead-c906" case tt_ascalon = "tt-ascalon" case veyron_v1 = "veyron-v1" case x_rv128 = "x-rv128" case xiangshan_nanhu = "xiangshan-nanhu" var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .lowrisc_ibex: return "lowrisc-ibex" case .max: return "max" case .max32: return "max32" case .rv32: return "rv32" case .rv32e: return "rv32e" case .rv32i: return "rv32i" case .rv64: return "rv64" case .rv64e: return "rv64e" case .rv64i: return "rv64i" case .rva22s64: return "rva22s64" case .rva22u64: return "rva22u64" case .rva23s64: return "rva23s64" case .rva23u64: return "rva23u64" case .shakti_c: return "shakti-c" case .sifive_e31: return "sifive-e31" case .sifive_e34: return "sifive-e34" case .sifive_e51: return "sifive-e51" case .sifive_u34: return "sifive-u34" case .sifive_u54: return "sifive-u54" case .thead_c906: return "thead-c906" case .tt_ascalon: return "tt-ascalon" case .veyron_v1: return "veyron-v1" case .x_rv128: return "x-rv128" case .xiangshan_nanhu: return "xiangshan-nanhu" } } } enum QEMUCPU_rx: String, CaseIterable, QEMUCPU { case `default` = "default" case rx62n var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .rx62n: return "rx62n" } } } enum QEMUCPU_s390x: String, CaseIterable, QEMUCPU { case `default` = "default" case max case gen16a case gen16a_base = "gen16a-base" case gen16b case gen16b_base = "gen16b-base" case gen17a case gen17a_base = "gen17a-base" case gen17b case gen17b_base = "gen17b-base" case z10BC case z10BC_base = "z10BC-base" case z10BC_2 = "z10BC.2" case z10BC_2_base = "z10BC.2-base" case z10EC case z10EC_base = "z10EC-base" case z10EC_2 = "z10EC.2" case z10EC_2_base = "z10EC.2-base" case z10EC_3 = "z10EC.3" case z10EC_3_base = "z10EC.3-base" case z9BC case z9BC_base = "z9BC-base" case z9BC_2 = "z9BC.2" case z9BC_2_base = "z9BC.2-base" case z9EC case z9EC_base = "z9EC-base" case z9EC_2 = "z9EC.2" case z9EC_2_base = "z9EC.2-base" case z9EC_3 = "z9EC.3" case z9EC_3_base = "z9EC.3-base" case z13 case z13_base = "z13-base" case z13_2 = "z13.2" case z13_2_base = "z13.2-base" case z13s case z13s_base = "z13s-base" case z14 case z14_base = "z14-base" case z14_2 = "z14.2" case z14_2_base = "z14.2-base" case z14ZR1 case z14ZR1_base = "z14ZR1-base" case gen15a case gen15a_base = "gen15a-base" case gen15b case gen15b_base = "gen15b-base" case z114 case z114_base = "z114-base" case z196 case z196_base = "z196-base" case z196_2 = "z196.2" case z196_2_base = "z196.2-base" case zBC12 case zBC12_base = "zBC12-base" case zEC12 case zEC12_base = "zEC12-base" case zEC12_2 = "zEC12.2" case zEC12_2_base = "zEC12.2-base" case z800 case z800_base = "z800-base" case z890 case z890_base = "z890-base" case z890_2 = "z890.2" case z890_2_base = "z890.2-base" case z890_3 = "z890.3" case z890_3_base = "z890.3-base" case z900 case z900_base = "z900-base" case z900_2 = "z900.2" case z900_2_base = "z900.2-base" case z900_3 = "z900.3" case z900_3_base = "z900.3-base" case z990 case z990_base = "z990-base" case z990_2 = "z990.2" case z990_2_base = "z990.2-base" case z990_3 = "z990.3" case z990_3_base = "z990.3-base" case z990_4 = "z990.4" case z990_4_base = "z990.4-base" case z990_5 = "z990.5" case z990_5_base = "z990.5-base" case qemu var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .max: return "Enables all features supported by the accelerator in the current host (max)" case .gen16a: return "IBM 3931 GA1 (migration-safe) (gen16a)" case .gen16a_base: return "IBM 3931 GA1 (static, migration-safe) (gen16a-base)" case .gen16b: return "IBM 3932 GA1 (migration-safe) (gen16b)" case .gen16b_base: return "IBM 3932 GA1 (static, migration-safe) (gen16b-base)" case .gen17a: return "IBM 9175 GA1 (migration-safe) (gen17a)" case .gen17a_base: return "IBM 9175 GA1 (static, migration-safe) (gen17a-base)" case .gen17b: return "IBM 9176 GA1 (migration-safe) (gen17b)" case .gen17b_base: return "IBM 9176 GA1 (static, migration-safe) (gen17b-base)" case .z10BC: return "IBM System z10 BC GA1 (migration-safe) (z10BC)" case .z10BC_base: return "IBM System z10 BC GA1 (static, migration-safe) (z10BC-base)" case .z10BC_2: return "IBM System z10 BC GA2 (migration-safe) (z10BC.2)" case .z10BC_2_base: return "IBM System z10 BC GA2 (static, migration-safe) (z10BC.2-base)" case .z10EC: return "IBM System z10 EC GA1 (migration-safe) (z10EC)" case .z10EC_base: return "IBM System z10 EC GA1 (static, migration-safe) (z10EC-base)" case .z10EC_2: return "IBM System z10 EC GA2 (migration-safe) (z10EC.2)" case .z10EC_2_base: return "IBM System z10 EC GA2 (static, migration-safe) (z10EC.2-base)" case .z10EC_3: return "IBM System z10 EC GA3 (migration-safe) (z10EC.3)" case .z10EC_3_base: return "IBM System z10 EC GA3 (static, migration-safe) (z10EC.3-base)" case .z9BC: return "IBM System z9 BC GA1 (migration-safe) (z9BC)" case .z9BC_base: return "IBM System z9 BC GA1 (static, migration-safe) (z9BC-base)" case .z9BC_2: return "IBM System z9 BC GA2 (migration-safe) (z9BC.2)" case .z9BC_2_base: return "IBM System z9 BC GA2 (static, migration-safe) (z9BC.2-base)" case .z9EC: return "IBM System z9 EC GA1 (migration-safe) (z9EC)" case .z9EC_base: return "IBM System z9 EC GA1 (static, migration-safe) (z9EC-base)" case .z9EC_2: return "IBM System z9 EC GA2 (migration-safe) (z9EC.2)" case .z9EC_2_base: return "IBM System z9 EC GA2 (static, migration-safe) (z9EC.2-base)" case .z9EC_3: return "IBM System z9 EC GA3 (migration-safe) (z9EC.3)" case .z9EC_3_base: return "IBM System z9 EC GA3 (static, migration-safe) (z9EC.3-base)" case .z13: return "IBM z13 GA1 (migration-safe) (z13)" case .z13_base: return "IBM z13 GA1 (static, migration-safe) (z13-base)" case .z13_2: return "IBM z13 GA2 (migration-safe) (z13.2)" case .z13_2_base: return "IBM z13 GA2 (static, migration-safe) (z13.2-base)" case .z13s: return "IBM z13s GA1 (migration-safe) (z13s)" case .z13s_base: return "IBM z13s GA1 (static, migration-safe) (z13s-base)" case .z14: return "IBM z14 GA1 (migration-safe) (z14)" case .z14_base: return "IBM z14 GA1 (static, migration-safe) (z14-base)" case .z14_2: return "IBM z14 GA2 (migration-safe) (z14.2)" case .z14_2_base: return "IBM z14 GA2 (static, migration-safe) (z14.2-base)" case .z14ZR1: return "IBM z14 Model ZR1 GA1 (migration-safe) (z14ZR1)" case .z14ZR1_base: return "IBM z14 Model ZR1 GA1 (static, migration-safe) (z14ZR1-base)" case .gen15a: return "IBM z15 T01 GA1 (migration-safe) (gen15a)" case .gen15a_base: return "IBM z15 T01 GA1 (static, migration-safe) (gen15a-base)" case .gen15b: return "IBM z15 T02 GA1 (migration-safe) (gen15b)" case .gen15b_base: return "IBM z15 T02 GA1 (static, migration-safe) (gen15b-base)" case .z114: return "IBM zEnterprise 114 GA1 (migration-safe) (z114)" case .z114_base: return "IBM zEnterprise 114 GA1 (static, migration-safe) (z114-base)" case .z196: return "IBM zEnterprise 196 GA1 (migration-safe) (z196)" case .z196_base: return "IBM zEnterprise 196 GA1 (static, migration-safe) (z196-base)" case .z196_2: return "IBM zEnterprise 196 GA2 (migration-safe) (z196.2)" case .z196_2_base: return "IBM zEnterprise 196 GA2 (static, migration-safe) (z196.2-base)" case .zBC12: return "IBM zEnterprise BC12 GA1 (migration-safe) (zBC12)" case .zBC12_base: return "IBM zEnterprise BC12 GA1 (static, migration-safe) (zBC12-base)" case .zEC12: return "IBM zEnterprise EC12 GA1 (migration-safe) (zEC12)" case .zEC12_base: return "IBM zEnterprise EC12 GA1 (static, migration-safe) (zEC12-base)" case .zEC12_2: return "IBM zEnterprise EC12 GA2 (migration-safe) (zEC12.2)" case .zEC12_2_base: return "IBM zEnterprise EC12 GA2 (static, migration-safe) (zEC12.2-base)" case .z800: return "IBM zSeries 800 GA1 (migration-safe) (z800)" case .z800_base: return "IBM zSeries 800 GA1 (static, migration-safe) (z800-base)" case .z890: return "IBM zSeries 880 GA1 (migration-safe) (z890)" case .z890_base: return "IBM zSeries 880 GA1 (static, migration-safe) (z890-base)" case .z890_2: return "IBM zSeries 880 GA2 (migration-safe) (z890.2)" case .z890_2_base: return "IBM zSeries 880 GA2 (static, migration-safe) (z890.2-base)" case .z890_3: return "IBM zSeries 880 GA3 (migration-safe) (z890.3)" case .z890_3_base: return "IBM zSeries 880 GA3 (static, migration-safe) (z890.3-base)" case .z900: return "IBM zSeries 900 GA1 (migration-safe) (z900)" case .z900_base: return "IBM zSeries 900 GA1 (static, migration-safe) (z900-base)" case .z900_2: return "IBM zSeries 900 GA2 (migration-safe) (z900.2)" case .z900_2_base: return "IBM zSeries 900 GA2 (static, migration-safe) (z900.2-base)" case .z900_3: return "IBM zSeries 900 GA3 (migration-safe) (z900.3)" case .z900_3_base: return "IBM zSeries 900 GA3 (static, migration-safe) (z900.3-base)" case .z990: return "IBM zSeries 990 GA1 (migration-safe) (z990)" case .z990_base: return "IBM zSeries 990 GA1 (static, migration-safe) (z990-base)" case .z990_2: return "IBM zSeries 990 GA2 (migration-safe) (z990.2)" case .z990_2_base: return "IBM zSeries 990 GA2 (static, migration-safe) (z990.2-base)" case .z990_3: return "IBM zSeries 990 GA3 (migration-safe) (z990.3)" case .z990_3_base: return "IBM zSeries 990 GA3 (static, migration-safe) (z990.3-base)" case .z990_4: return "IBM zSeries 990 GA4 (migration-safe) (z990.4)" case .z990_4_base: return "IBM zSeries 990 GA4 (static, migration-safe) (z990.4-base)" case .z990_5: return "IBM zSeries 990 GA5 (migration-safe) (z990.5)" case .z990_5_base: return "IBM zSeries 990 GA5 (static, migration-safe) (z990.5-base)" case .qemu: return "QEMU Virtual CPU version 2.5+ (migration-safe) (qemu)" } } } enum QEMUCPU_sh4: String, CaseIterable, QEMUCPU { case `default` = "default" case sh7750r case sh7751r case sh7785 var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .sh7750r: return "sh7750r" case .sh7751r: return "sh7751r" case .sh7785: return "sh7785" } } } enum QEMUCPU_sh4eb: String, CaseIterable, QEMUCPU { case `default` = "default" case sh7750r case sh7751r case sh7785 var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .sh7750r: return "sh7750r" case .sh7751r: return "sh7751r" case .sh7785: return "sh7785" } } } enum QEMUCPU_sparc: String, CaseIterable, QEMUCPU { case `default` = "default" case Fujitsu_MB86904_ = "Fujitsu-MB86904 " case Fujitsu_MB86907_ = "Fujitsu-MB86907 " case LEON2_ = "LEON2 " case LEON3_ = "LEON3 " case TI_MicroSparc_I_ = "TI-MicroSparc-I " case TI_MicroSparc_II_ = "TI-MicroSparc-II " case TI_MicroSparc_IIep_ = "TI-MicroSparc-IIep " case TI_SuperSparc_40_ = "TI-SuperSparc-40 " case TI_SuperSparc_50_ = "TI-SuperSparc-50 " case TI_SuperSparc_51_ = "TI-SuperSparc-51 " case TI_SuperSparc_60_ = "TI-SuperSparc-60 " case TI_SuperSparc_61_ = "TI-SuperSparc-61 " case TI_SuperSparc_II_ = "TI-SuperSparc-II " var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .Fujitsu_MB86904_: return "Fujitsu-MB86904 " case .Fujitsu_MB86907_: return "Fujitsu-MB86907 " case .LEON2_: return "LEON2 " case .LEON3_: return "LEON3 " case .TI_MicroSparc_I_: return "TI-MicroSparc-I " case .TI_MicroSparc_II_: return "TI-MicroSparc-II " case .TI_MicroSparc_IIep_: return "TI-MicroSparc-IIep " case .TI_SuperSparc_40_: return "TI-SuperSparc-40 " case .TI_SuperSparc_50_: return "TI-SuperSparc-50 " case .TI_SuperSparc_51_: return "TI-SuperSparc-51 " case .TI_SuperSparc_60_: return "TI-SuperSparc-60 " case .TI_SuperSparc_61_: return "TI-SuperSparc-61 " case .TI_SuperSparc_II_: return "TI-SuperSparc-II " } } } enum QEMUCPU_sparc64: String, CaseIterable, QEMUCPU { case `default` = "default" case Fujitsu_Sparc64_ = "Fujitsu-Sparc64 " case Fujitsu_Sparc64_III_ = "Fujitsu-Sparc64-III " case Fujitsu_Sparc64_IV_ = "Fujitsu-Sparc64-IV " case Fujitsu_Sparc64_V_ = "Fujitsu-Sparc64-V " case NEC_UltraSparc_I_ = "NEC-UltraSparc-I " case Sun_UltraSparc_III_ = "Sun-UltraSparc-III " case Sun_UltraSparc_III_Cu = "Sun-UltraSparc-III-Cu" case Sun_UltraSparc_IIIi_ = "Sun-UltraSparc-IIIi " case Sun_UltraSparc_IIIi_plus = "Sun-UltraSparc-IIIi-plus" case Sun_UltraSparc_IV_ = "Sun-UltraSparc-IV " case Sun_UltraSparc_IV_plus = "Sun-UltraSparc-IV-plus" case Sun_UltraSparc_T1_ = "Sun-UltraSparc-T1 " case Sun_UltraSparc_T2_ = "Sun-UltraSparc-T2 " case TI_UltraSparc_I_ = "TI-UltraSparc-I " case TI_UltraSparc_II_ = "TI-UltraSparc-II " case TI_UltraSparc_IIe_ = "TI-UltraSparc-IIe " case TI_UltraSparc_IIi_ = "TI-UltraSparc-IIi " var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .Fujitsu_Sparc64_: return "Fujitsu-Sparc64 " case .Fujitsu_Sparc64_III_: return "Fujitsu-Sparc64-III " case .Fujitsu_Sparc64_IV_: return "Fujitsu-Sparc64-IV " case .Fujitsu_Sparc64_V_: return "Fujitsu-Sparc64-V " case .NEC_UltraSparc_I_: return "NEC-UltraSparc-I " case .Sun_UltraSparc_III_: return "Sun-UltraSparc-III " case .Sun_UltraSparc_III_Cu: return "Sun-UltraSparc-III-Cu" case .Sun_UltraSparc_IIIi_: return "Sun-UltraSparc-IIIi " case .Sun_UltraSparc_IIIi_plus: return "Sun-UltraSparc-IIIi-plus" case .Sun_UltraSparc_IV_: return "Sun-UltraSparc-IV " case .Sun_UltraSparc_IV_plus: return "Sun-UltraSparc-IV-plus" case .Sun_UltraSparc_T1_: return "Sun-UltraSparc-T1 " case .Sun_UltraSparc_T2_: return "Sun-UltraSparc-T2 " case .TI_UltraSparc_I_: return "TI-UltraSparc-I " case .TI_UltraSparc_II_: return "TI-UltraSparc-II " case .TI_UltraSparc_IIe_: return "TI-UltraSparc-IIe " case .TI_UltraSparc_IIi_: return "TI-UltraSparc-IIi " } } } enum QEMUCPU_tricore: String, CaseIterable, QEMUCPU { case `default` = "default" case tc1796 case tc1797 case tc27x case tc37x var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .tc1796: return "tc1796" case .tc1797: return "tc1797" case .tc27x: return "tc27x" case .tc37x: return "tc37x" } } } enum QEMUCPU_x86_64: 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_xtensa: String, CaseIterable, QEMUCPU { case `default` = "default" case dc232b case dc233c case de212 case de233_fpu case dsp3400 case lx106 case sample_controller case test_mmuhifi_c3 var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .dc232b: return "dc232b" case .dc233c: return "dc233c" case .de212: return "de212" case .de233_fpu: return "de233_fpu" case .dsp3400: return "dsp3400" case .lx106: return "lx106" case .sample_controller: return "sample_controller" case .test_mmuhifi_c3: return "test_mmuhifi_c3" } } } enum QEMUCPU_xtensaeb: String, CaseIterable, QEMUCPU { case `default` = "default" case fsf case test_kc705_be var prettyValue: String { switch self { case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated") case .fsf: return "fsf" case .test_kc705_be: return "test_kc705_be" } } } typealias QEMUCPUFlag_alpha = AnyQEMUConstant typealias QEMUCPUFlag_arm = AnyQEMUConstant typealias QEMUCPUFlag_aarch64 = AnyQEMUConstant typealias QEMUCPUFlag_avr = AnyQEMUConstant typealias QEMUCPUFlag_hppa = AnyQEMUConstant enum QEMUCPUFlag_i386: String, CaseIterable, QEMUCPUFlag { case _3dnow = "3dnow" case _3dnowext = "3dnowext" case _3dnowprefetch = "3dnowprefetch" case abm case ace2 case ace2_en = "ace2-en" case acpi case adx case aes case amd_no_ssb = "amd-no-ssb" case amd_psfd = "amd-psfd" case amd_ssbd = "amd-ssbd" case amd_stibp = "amd-stibp" case amx_bf16 = "amx-bf16" case amx_complex = "amx-complex" case amx_fp16 = "amx-fp16" case amx_int8 = "amx-int8" case amx_tile = "amx-tile" case apic case arat case arch_capabilities = "arch-capabilities" case arch_lbr = "arch-lbr" case auto_ibrs = "auto-ibrs" case avic case avx case avx_ifma = "avx-ifma" case avx_ne_convert = "avx-ne-convert" case avx_vnni = "avx-vnni" case avx_vnni_int16 = "avx-vnni-int16" case avx_vnni_int8 = "avx-vnni-int8" case avx10 case avx10_128 = "avx10-128" case avx10_256 = "avx10-256" case avx10_512 = "avx10-512" case avx2 case avx512_4fmaps = "avx512-4fmaps" case avx512_4vnniw = "avx512-4vnniw" case avx512_bf16 = "avx512-bf16" case avx512_fp16 = "avx512-fp16" case avx512_vp2intersect = "avx512-vp2intersect" case avx512_vpopcntdq = "avx512-vpopcntdq" case avx512bitalg case avx512bw case avx512cd case avx512dq case avx512er case avx512f case avx512ifma case avx512pf case avx512vbmi case avx512vbmi2 case avx512vl case avx512vnni case bhi_ctrl = "bhi-ctrl" case bhi_no = "bhi-no" case bmi1 case bmi2 case bus_lock_detect = "bus-lock-detect" case cid case cldemote case clflush case clflushopt case clwb case clzero case cmov case cmp_legacy = "cmp-legacy" case cmpccxadd case core_capability = "core-capability" case cr8legacy case cx16 case cx8 case dca case ddpd_u = "ddpd-u" case de case decodeassists case ds case ds_cpl = "ds-cpl" case dtes64 case eraps case erms case est case extapic case f16c case fb_clear = "fb-clear" case fbsdp_no = "fbsdp-no" case fdp_excptn_only = "fdp-excptn-only" case flush_l1d = "flush-l1d" case flushbyasid case fma case fma4 case fpu case fred case fsgsbase case fsrc case fsrm case fsrs case full_width_write = "full-width-write" case fxsr case fxsr_opt = "fxsr-opt" case fzrm case gds_no = "gds-no" case gfni case hle case ht case hypervisor case ia64 case ibpb case ibpb_brtype = "ibpb-brtype" case ibrs case ibrs_all = "ibrs-all" case ibs case intel_psfd = "intel-psfd" case intel_pt = "intel-pt" case intel_pt_lip = "intel-pt-lip" case invpcid case invtsc case ipred_ctrl = "ipred-ctrl" case kvm_asyncpf = "kvm-asyncpf" case kvm_asyncpf_int = "kvm-asyncpf-int" case kvm_asyncpf_vmexit = "kvm-asyncpf-vmexit" case kvm_hint_dedicated = "kvm-hint-dedicated" case kvm_mmu = "kvm-mmu" case kvm_msi_ext_dest_id = "kvm-msi-ext-dest-id" case kvm_nopiodelay = "kvm-nopiodelay" case kvm_poll_control = "kvm-poll-control" case kvm_pv_eoi = "kvm-pv-eoi" case kvm_pv_ipi = "kvm-pv-ipi" case kvm_pv_sched_yield = "kvm-pv-sched-yield" case kvm_pv_tlb_flush = "kvm-pv-tlb-flush" case kvm_pv_unhalt = "kvm-pv-unhalt" case kvm_steal_time = "kvm-steal-time" case kvmclock case kvmclock_stable_bit = "kvmclock-stable-bit" case la57 case lahf_lm = "lahf-lm" case lam case lbrv case lfence_always_serializing = "lfence-always-serializing" case lkgs case lm case lwp case mca case mcdt_no = "mcdt-no" case mce case md_clear = "md-clear" case mds_no = "mds-no" case misalignsse case mmx case mmxext case monitor case movbe case movdir64b case movdiri case mpx case msr case mtrr case no_nested_data_bp = "no-nested-data-bp" case nodeid_msr = "nodeid-msr" case npt case nrip_save = "nrip-save" case null_sel_clr_base = "null-sel-clr-base" case nx case osvw case overflow_recov = "overflow-recov" case pae case pat case pause_filter = "pause-filter" case pbe case pbrsb_no = "pbrsb-no" case pcid case pclmulqdq case pcommit case pdcm case pdpe1gb case perfctr_core = "perfctr-core" case perfctr_nb = "perfctr-nb" case perfmon_v2 = "perfmon-v2" case pfthreshold case pge case phe case phe_en = "phe-en" case pks case pku case pmm case pmm_en = "pmm-en" case pn case pni case popcnt case prefetchiti case pschange_mc_no = "pschange-mc-no" case psdp_no = "psdp-no" case pse case pse36 case rdctl_no = "rdctl-no" case rdpid case rdrand case rdseed case rdtscp case rfds_clear = "rfds-clear" case rfds_no = "rfds-no" case rrsba_ctrl = "rrsba-ctrl" case rsba case rtm case sbdr_ssdp_no = "sbdr-ssdp-no" case sbpb case sep case serialize case sgx case sgx_aex_notify = "sgx-aex-notify" case sgx_debug = "sgx-debug" case sgx_edeccssa = "sgx-edeccssa" case sgx_exinfo = "sgx-exinfo" case sgx_kss = "sgx-kss" case sgx_mode64 = "sgx-mode64" case sgx_provisionkey = "sgx-provisionkey" case sgx_tokenkey = "sgx-tokenkey" case sgx1 case sgx2 case sgxlc case sha_ni = "sha-ni" case sha512 case skinit case skip_l1dfl_vmentry = "skip-l1dfl-vmentry" case sm3 case sm4 case smap case smep case smx case spec_ctrl = "spec-ctrl" case split_lock_detect = "split-lock-detect" case srso_no = "srso-no" case srso_user_kernel_no = "srso-user-kernel-no" case ss case ssb_no = "ssb-no" case ssbd case sse case sse2 case sse4_1 = "sse4.1" case sse4_2 = "sse4.2" case sse4a case ssse3 case stibp case stibp_always_on = "stibp-always-on" case succor case svm case svm_lock = "svm-lock" case svme_addr_chk = "svme-addr-chk" case syscall case taa_no = "taa-no" case tbm case tce case tm case tm2 case topoext case tsc case tsc_adjust = "tsc-adjust" case tsc_deadline = "tsc-deadline" case tsc_scale = "tsc-scale" case tsx_ctrl = "tsx-ctrl" case tsx_ldtrk = "tsx-ldtrk" case umip case v_vmsave_vmload = "v-vmsave-vmload" case vaes case vgif case virt_ssbd = "virt-ssbd" case vmcb_clean = "vmcb-clean" case vme case vmx case vmx_activity_hlt = "vmx-activity-hlt" case vmx_activity_shutdown = "vmx-activity-shutdown" case vmx_activity_wait_sipi = "vmx-activity-wait-sipi" case vmx_any_errcode = "vmx-any-errcode" case vmx_apicv_register = "vmx-apicv-register" case vmx_apicv_vid = "vmx-apicv-vid" case vmx_apicv_x2apic = "vmx-apicv-x2apic" case vmx_apicv_xapic = "vmx-apicv-xapic" case vmx_cr3_load_noexit = "vmx-cr3-load-noexit" case vmx_cr3_store_noexit = "vmx-cr3-store-noexit" case vmx_cr8_load_exit = "vmx-cr8-load-exit" case vmx_cr8_store_exit = "vmx-cr8-store-exit" case vmx_desc_exit = "vmx-desc-exit" case vmx_enable_user_wait_pause = "vmx-enable-user-wait-pause" case vmx_encls_exit = "vmx-encls-exit" case vmx_entry_ia32e_mode = "vmx-entry-ia32e-mode" case vmx_entry_load_bndcfgs = "vmx-entry-load-bndcfgs" case vmx_entry_load_efer = "vmx-entry-load-efer" case vmx_entry_load_fred = "vmx-entry-load-fred" case vmx_entry_load_pat = "vmx-entry-load-pat" case vmx_entry_load_perf_global_ctrl = "vmx-entry-load-perf-global-ctrl" case vmx_entry_load_pkrs = "vmx-entry-load-pkrs" case vmx_entry_load_rtit_ctl = "vmx-entry-load-rtit-ctl" case vmx_entry_noload_debugctl = "vmx-entry-noload-debugctl" case vmx_ept = "vmx-ept" case vmx_ept_1gb = "vmx-ept-1gb" case vmx_ept_2mb = "vmx-ept-2mb" case vmx_ept_advanced_exitinfo = "vmx-ept-advanced-exitinfo" case vmx_ept_execonly = "vmx-ept-execonly" case vmx_eptad = "vmx-eptad" case vmx_eptp_switching = "vmx-eptp-switching" case vmx_exit_ack_intr = "vmx-exit-ack-intr" case vmx_exit_clear_bndcfgs = "vmx-exit-clear-bndcfgs" case vmx_exit_clear_rtit_ctl = "vmx-exit-clear-rtit-ctl" case vmx_exit_load_efer = "vmx-exit-load-efer" case vmx_exit_load_pat = "vmx-exit-load-pat" case vmx_exit_load_perf_global_ctrl = "vmx-exit-load-perf-global-ctrl" case vmx_exit_load_pkrs = "vmx-exit-load-pkrs" case vmx_exit_nosave_debugctl = "vmx-exit-nosave-debugctl" case vmx_exit_save_efer = "vmx-exit-save-efer" case vmx_exit_save_pat = "vmx-exit-save-pat" case vmx_exit_save_preemption_timer = "vmx-exit-save-preemption-timer" case vmx_exit_secondary_ctls = "vmx-exit-secondary-ctls" case vmx_flexpriority = "vmx-flexpriority" case vmx_hlt_exit = "vmx-hlt-exit" case vmx_ins_outs = "vmx-ins-outs" case vmx_intr_exit = "vmx-intr-exit" case vmx_invept = "vmx-invept" case vmx_invept_all_context = "vmx-invept-all-context" case vmx_invept_single_context = "vmx-invept-single-context" case vmx_invept_single_context_noglobals = "vmx-invept-single-context-noglobals" case vmx_invlpg_exit = "vmx-invlpg-exit" case vmx_invpcid_exit = "vmx-invpcid-exit" case vmx_invvpid = "vmx-invvpid" case vmx_invvpid_all_context = "vmx-invvpid-all-context" case vmx_invvpid_single_addr = "vmx-invvpid-single-addr" case vmx_io_bitmap = "vmx-io-bitmap" case vmx_io_exit = "vmx-io-exit" case vmx_monitor_exit = "vmx-monitor-exit" case vmx_movdr_exit = "vmx-movdr-exit" case vmx_msr_bitmap = "vmx-msr-bitmap" case vmx_mtf = "vmx-mtf" case vmx_mwait_exit = "vmx-mwait-exit" case vmx_nested_exception = "vmx-nested-exception" case vmx_nmi_exit = "vmx-nmi-exit" case vmx_page_walk_4 = "vmx-page-walk-4" case vmx_page_walk_5 = "vmx-page-walk-5" case vmx_pause_exit = "vmx-pause-exit" case vmx_ple = "vmx-ple" case vmx_pml = "vmx-pml" case vmx_posted_intr = "vmx-posted-intr" case vmx_preemption_timer = "vmx-preemption-timer" case vmx_rdpmc_exit = "vmx-rdpmc-exit" case vmx_rdrand_exit = "vmx-rdrand-exit" case vmx_rdseed_exit = "vmx-rdseed-exit" case vmx_rdtsc_exit = "vmx-rdtsc-exit" case vmx_rdtscp_exit = "vmx-rdtscp-exit" case vmx_secondary_ctls = "vmx-secondary-ctls" case vmx_shadow_vmcs = "vmx-shadow-vmcs" case vmx_store_lma = "vmx-store-lma" case vmx_true_ctls = "vmx-true-ctls" case vmx_tsc_offset = "vmx-tsc-offset" case vmx_tsc_scaling = "vmx-tsc-scaling" case vmx_unrestricted_guest = "vmx-unrestricted-guest" case vmx_vintr_pending = "vmx-vintr-pending" case vmx_vmfunc = "vmx-vmfunc" case vmx_vmwrite_vmexit_fields = "vmx-vmwrite-vmexit-fields" case vmx_vnmi = "vmx-vnmi" case vmx_vnmi_pending = "vmx-vnmi-pending" case vmx_vpid = "vmx-vpid" case vmx_wbinvd_exit = "vmx-wbinvd-exit" case vmx_xsaves = "vmx-xsaves" case vmx_zero_len_inject = "vmx-zero-len-inject" case vnmi case vpclmulqdq case waitpkg case wbnoinvd case wdt case wrmsrns case x2apic case xcrypt case xcrypt_en = "xcrypt-en" case xfd case xgetbv1 case xop case xsave case xsavec case xsaveerptr case xsaveopt case xsaves case xstore case xstore_en = "xstore-en" case xtpr case zero_fcs_fds = "zero-fcs-fds" var prettyValue: String { switch self { case ._3dnow: return "3dnow" case ._3dnowext: return "3dnowext" case ._3dnowprefetch: return "3dnowprefetch" case .abm: return "abm" case .ace2: return "ace2" case .ace2_en: return "ace2-en" case .acpi: return "acpi" case .adx: return "adx" case .aes: return "aes" case .amd_no_ssb: return "amd-no-ssb" case .amd_psfd: return "amd-psfd" case .amd_ssbd: return "amd-ssbd" case .amd_stibp: return "amd-stibp" case .amx_bf16: return "amx-bf16" case .amx_complex: return "amx-complex" case .amx_fp16: return "amx-fp16" case .amx_int8: return "amx-int8" case .amx_tile: return "amx-tile" case .apic: return "apic" case .arat: return "arat" case .arch_capabilities: return "arch-capabilities" case .arch_lbr: return "arch-lbr" case .auto_ibrs: return "auto-ibrs" case .avic: return "avic" case .avx: return "avx" case .avx_ifma: return "avx-ifma" case .avx_ne_convert: return "avx-ne-convert" case .avx_vnni: return "avx-vnni" case .avx_vnni_int16: return "avx-vnni-int16" case .avx_vnni_int8: return "avx-vnni-int8" case .avx10: return "avx10" case .avx10_128: return "avx10-128" case .avx10_256: return "avx10-256" case .avx10_512: return "avx10-512" case .avx2: return "avx2" case .avx512_4fmaps: return "avx512-4fmaps" case .avx512_4vnniw: return "avx512-4vnniw" case .avx512_bf16: return "avx512-bf16" case .avx512_fp16: return "avx512-fp16" case .avx512_vp2intersect: return "avx512-vp2intersect" case .avx512_vpopcntdq: return "avx512-vpopcntdq" case .avx512bitalg: return "avx512bitalg" case .avx512bw: return "avx512bw" case .avx512cd: return "avx512cd" case .avx512dq: return "avx512dq" case .avx512er: return "avx512er" case .avx512f: return "avx512f" case .avx512ifma: return "avx512ifma" case .avx512pf: return "avx512pf" case .avx512vbmi: return "avx512vbmi" case .avx512vbmi2: return "avx512vbmi2" case .avx512vl: return "avx512vl" case .avx512vnni: return "avx512vnni" case .bhi_ctrl: return "bhi-ctrl" case .bhi_no: return "bhi-no" case .bmi1: return "bmi1" case .bmi2: return "bmi2" case .bus_lock_detect: return "bus-lock-detect" case .cid: return "cid" case .cldemote: return "cldemote" case .clflush: return "clflush" case .clflushopt: return "clflushopt" case .clwb: return "clwb" case .clzero: return "clzero" case .cmov: return "cmov" case .cmp_legacy: return "cmp-legacy" case .cmpccxadd: return "cmpccxadd" case .core_capability: return "core-capability" case .cr8legacy: return "cr8legacy" case .cx16: return "cx16" case .cx8: return "cx8" case .dca: return "dca" case .ddpd_u: return "ddpd-u" case .de: return "de" case .decodeassists: return "decodeassists" case .ds: return "ds" case .ds_cpl: return "ds-cpl" case .dtes64: return "dtes64" case .eraps: return "eraps" case .erms: return "erms" case .est: return "est" case .extapic: return "extapic" case .f16c: return "f16c" case .fb_clear: return "fb-clear" case .fbsdp_no: return "fbsdp-no" case .fdp_excptn_only: return "fdp-excptn-only" case .flush_l1d: return "flush-l1d" case .flushbyasid: return "flushbyasid" case .fma: return "fma" case .fma4: return "fma4" case .fpu: return "fpu" case .fred: return "fred" case .fsgsbase: return "fsgsbase" case .fsrc: return "fsrc" case .fsrm: return "fsrm" case .fsrs: return "fsrs" case .full_width_write: return "full-width-write" case .fxsr: return "fxsr" case .fxsr_opt: return "fxsr-opt" case .fzrm: return "fzrm" case .gds_no: return "gds-no" case .gfni: return "gfni" case .hle: return "hle" case .ht: return "ht" case .hypervisor: return "hypervisor" case .ia64: return "ia64" case .ibpb: return "ibpb" case .ibpb_brtype: return "ibpb-brtype" case .ibrs: return "ibrs" case .ibrs_all: return "ibrs-all" case .ibs: return "ibs" case .intel_psfd: return "intel-psfd" case .intel_pt: return "intel-pt" case .intel_pt_lip: return "intel-pt-lip" case .invpcid: return "invpcid" case .invtsc: return "invtsc" case .ipred_ctrl: return "ipred-ctrl" case .kvm_asyncpf: return "kvm-asyncpf" case .kvm_asyncpf_int: return "kvm-asyncpf-int" case .kvm_asyncpf_vmexit: return "kvm-asyncpf-vmexit" case .kvm_hint_dedicated: return "kvm-hint-dedicated" case .kvm_mmu: return "kvm-mmu" case .kvm_msi_ext_dest_id: return "kvm-msi-ext-dest-id" case .kvm_nopiodelay: return "kvm-nopiodelay" case .kvm_poll_control: return "kvm-poll-control" case .kvm_pv_eoi: return "kvm-pv-eoi" case .kvm_pv_ipi: return "kvm-pv-ipi" case .kvm_pv_sched_yield: return "kvm-pv-sched-yield" case .kvm_pv_tlb_flush: return "kvm-pv-tlb-flush" case .kvm_pv_unhalt: return "kvm-pv-unhalt" case .kvm_steal_time: return "kvm-steal-time" case .kvmclock: return "kvmclock" case .kvmclock_stable_bit: return "kvmclock-stable-bit" case .la57: return "la57" case .lahf_lm: return "lahf-lm" case .lam: return "lam" case .lbrv: return "lbrv" case .lfence_always_serializing: return "lfence-always-serializing" case .lkgs: return "lkgs" case .lm: return "lm" case .lwp: return "lwp" case .mca: return "mca" case .mcdt_no: return "mcdt-no" case .mce: return "mce" case .md_clear: return "md-clear" case .mds_no: return "mds-no" case .misalignsse: return "misalignsse" case .mmx: return "mmx" case .mmxext: return "mmxext" case .monitor: return "monitor" case .movbe: return "movbe" case .movdir64b: return "movdir64b" case .movdiri: return "movdiri" case .mpx: return "mpx" case .msr: return "msr" case .mtrr: return "mtrr" case .no_nested_data_bp: return "no-nested-data-bp" case .nodeid_msr: return "nodeid-msr" case .npt: return "npt" case .nrip_save: return "nrip-save" case .null_sel_clr_base: return "null-sel-clr-base" case .nx: return "nx" case .osvw: return "osvw" case .overflow_recov: return "overflow-recov" case .pae: return "pae" case .pat: return "pat" case .pause_filter: return "pause-filter" case .pbe: return "pbe" case .pbrsb_no: return "pbrsb-no" case .pcid: return "pcid" case .pclmulqdq: return "pclmulqdq" case .pcommit: return "pcommit" case .pdcm: return "pdcm" case .pdpe1gb: return "pdpe1gb" case .perfctr_core: return "perfctr-core" case .perfctr_nb: return "perfctr-nb" case .perfmon_v2: return "perfmon-v2" case .pfthreshold: return "pfthreshold" case .pge: return "pge" case .phe: return "phe" case .phe_en: return "phe-en" case .pks: return "pks" case .pku: return "pku" case .pmm: return "pmm" case .pmm_en: return "pmm-en" case .pn: return "pn" case .pni: return "pni" case .popcnt: return "popcnt" case .prefetchiti: return "prefetchiti" case .pschange_mc_no: return "pschange-mc-no" case .psdp_no: return "psdp-no" case .pse: return "pse" case .pse36: return "pse36" case .rdctl_no: return "rdctl-no" case .rdpid: return "rdpid" case .rdrand: return "rdrand" case .rdseed: return "rdseed" case .rdtscp: return "rdtscp" case .rfds_clear: return "rfds-clear" case .rfds_no: return "rfds-no" case .rrsba_ctrl: return "rrsba-ctrl" case .rsba: return "rsba" case .rtm: return "rtm" case .sbdr_ssdp_no: return "sbdr-ssdp-no" case .sbpb: return "sbpb" case .sep: return "sep" case .serialize: return "serialize" case .sgx: return "sgx" case .sgx_aex_notify: return "sgx-aex-notify" case .sgx_debug: return "sgx-debug" case .sgx_edeccssa: return "sgx-edeccssa" case .sgx_exinfo: return "sgx-exinfo" case .sgx_kss: return "sgx-kss" case .sgx_mode64: return "sgx-mode64" case .sgx_provisionkey: return "sgx-provisionkey" case .sgx_tokenkey: return "sgx-tokenkey" case .sgx1: return "sgx1" case .sgx2: return "sgx2" case .sgxlc: return "sgxlc" case .sha_ni: return "sha-ni" case .sha512: return "sha512" case .skinit: return "skinit" case .skip_l1dfl_vmentry: return "skip-l1dfl-vmentry" case .sm3: return "sm3" case .sm4: return "sm4" case .smap: return "smap" case .smep: return "smep" case .smx: return "smx" case .spec_ctrl: return "spec-ctrl" case .split_lock_detect: return "split-lock-detect" case .srso_no: return "srso-no" case .srso_user_kernel_no: return "srso-user-kernel-no" case .ss: return "ss" case .ssb_no: return "ssb-no" case .ssbd: return "ssbd" case .sse: return "sse" case .sse2: return "sse2" case .sse4_1: return "sse4.1" case .sse4_2: return "sse4.2" case .sse4a: return "sse4a" case .ssse3: return "ssse3" case .stibp: return "stibp" case .stibp_always_on: return "stibp-always-on" case .succor: return "succor" case .svm: return "svm" case .svm_lock: return "svm-lock" case .svme_addr_chk: return "svme-addr-chk" case .syscall: return "syscall" case .taa_no: return "taa-no" case .tbm: return "tbm" case .tce: return "tce" case .tm: return "tm" case .tm2: return "tm2" case .topoext: return "topoext" case .tsc: return "tsc" case .tsc_adjust: return "tsc-adjust" case .tsc_deadline: return "tsc-deadline" case .tsc_scale: return "tsc-scale" case .tsx_ctrl: return "tsx-ctrl" case .tsx_ldtrk: return "tsx-ldtrk" case .umip: return "umip" case .v_vmsave_vmload: return "v-vmsave-vmload" case .vaes: return "vaes" case .vgif: return "vgif" case .virt_ssbd: return "virt-ssbd" case .vmcb_clean: return "vmcb-clean" case .vme: return "vme" case .vmx: return "vmx" case .vmx_activity_hlt: return "vmx-activity-hlt" case .vmx_activity_shutdown: return "vmx-activity-shutdown" case .vmx_activity_wait_sipi: return "vmx-activity-wait-sipi" case .vmx_any_errcode: return "vmx-any-errcode" case .vmx_apicv_register: return "vmx-apicv-register" case .vmx_apicv_vid: return "vmx-apicv-vid" case .vmx_apicv_x2apic: return "vmx-apicv-x2apic" case .vmx_apicv_xapic: return "vmx-apicv-xapic" case .vmx_cr3_load_noexit: return "vmx-cr3-load-noexit" case .vmx_cr3_store_noexit: return "vmx-cr3-store-noexit" case .vmx_cr8_load_exit: return "vmx-cr8-load-exit" case .vmx_cr8_store_exit: return "vmx-cr8-store-exit" case .vmx_desc_exit: return "vmx-desc-exit" case .vmx_enable_user_wait_pause: return "vmx-enable-user-wait-pause" case .vmx_encls_exit: return "vmx-encls-exit" case .vmx_entry_ia32e_mode: return "vmx-entry-ia32e-mode" case .vmx_entry_load_bndcfgs: return "vmx-entry-load-bndcfgs" case .vmx_entry_load_efer: return "vmx-entry-load-efer" case .vmx_entry_load_fred: return "vmx-entry-load-fred" case .vmx_entry_load_pat: return "vmx-entry-load-pat" case .vmx_entry_load_perf_global_ctrl: return "vmx-entry-load-perf-global-ctrl" case .vmx_entry_load_pkrs: return "vmx-entry-load-pkrs" case .vmx_entry_load_rtit_ctl: return "vmx-entry-load-rtit-ctl" case .vmx_entry_noload_debugctl: return "vmx-entry-noload-debugctl" case .vmx_ept: return "vmx-ept" case .vmx_ept_1gb: return "vmx-ept-1gb" case .vmx_ept_2mb: return "vmx-ept-2mb" case .vmx_ept_advanced_exitinfo: return "vmx-ept-advanced-exitinfo" case .vmx_ept_execonly: return "vmx-ept-execonly" case .vmx_eptad: return "vmx-eptad" case .vmx_eptp_switching: return "vmx-eptp-switching" case .vmx_exit_ack_intr: return "vmx-exit-ack-intr" case .vmx_exit_clear_bndcfgs: return "vmx-exit-clear-bndcfgs" case .vmx_exit_clear_rtit_ctl: return "vmx-exit-clear-rtit-ctl" case .vmx_exit_load_efer: return "vmx-exit-load-efer" case .vmx_exit_load_pat: return "vmx-exit-load-pat" case .vmx_exit_load_perf_global_ctrl: return "vmx-exit-load-perf-global-ctrl" case .vmx_exit_load_pkrs: return "vmx-exit-load-pkrs" case .vmx_exit_nosave_debugctl: return "vmx-exit-nosave-debugctl" case .vmx_exit_save_efer: return "vmx-exit-save-efer" case .vmx_exit_save_pat: return "vmx-exit-save-pat" case .vmx_exit_save_preemption_timer: return "vmx-exit-save-preemption-timer" case .vmx_exit_secondary_ctls: return "vmx-exit-secondary-ctls" case .vmx_flexpriority: return "vmx-flexpriority" case .vmx_hlt_exit: return "vmx-hlt-exit" case .vmx_ins_outs: return "vmx-ins-outs" case .vmx_intr_exit: return "vmx-intr-exit" case .vmx_invept: return "vmx-invept" case .vmx_invept_all_context: return "vmx-invept-all-context" case .vmx_invept_single_context: return "vmx-invept-single-context" case .vmx_invept_single_context_noglobals: return "vmx-invept-single-context-noglobals" case .vmx_invlpg_exit: return "vmx-invlpg-exit" case .vmx_invpcid_exit: return "vmx-invpcid-exit" case .vmx_invvpid: return "vmx-invvpid" case .vmx_invvpid_all_context: return "vmx-invvpid-all-context" case .vmx_invvpid_single_addr: return "vmx-invvpid-single-addr" case .vmx_io_bitmap: return "vmx-io-bitmap" case .vmx_io_exit: return "vmx-io-exit" case .vmx_monitor_exit: return "vmx-monitor-exit" case .vmx_movdr_exit: return "vmx-movdr-exit" case .vmx_msr_bitmap: return "vmx-msr-bitmap" case .vmx_mtf: return "vmx-mtf" case .vmx_mwait_exit: return "vmx-mwait-exit" case .vmx_nested_exception: return "vmx-nested-exception" case .vmx_nmi_exit: return "vmx-nmi-exit" case .vmx_page_walk_4: return "vmx-page-walk-4" case .vmx_page_walk_5: return "vmx-page-walk-5" case .vmx_pause_exit: return "vmx-pause-exit" case .vmx_ple: return "vmx-ple" case .vmx_pml: return "vmx-pml" case .vmx_posted_intr: return "vmx-posted-intr" case .vmx_preemption_timer: return "vmx-preemption-timer" case .vmx_rdpmc_exit: return "vmx-rdpmc-exit" case .vmx_rdrand_exit: return "vmx-rdrand-exit" case .vmx_rdseed_exit: return "vmx-rdseed-exit" case .vmx_rdtsc_exit: return "vmx-rdtsc-exit" case .vmx_rdtscp_exit: return "vmx-rdtscp-exit" case .vmx_secondary_ctls: return "vmx-secondary-ctls" case .vmx_shadow_vmcs: return "vmx-shadow-vmcs" case .vmx_store_lma: return "vmx-store-lma" case .vmx_true_ctls: return "vmx-true-ctls" case .vmx_tsc_offset: return "vmx-tsc-offset" case .vmx_tsc_scaling: return "vmx-tsc-scaling" case .vmx_unrestricted_guest: return "vmx-unrestricted-guest" case .vmx_vintr_pending: return "vmx-vintr-pending" case .vmx_vmfunc: return "vmx-vmfunc" case .vmx_vmwrite_vmexit_fields: return "vmx-vmwrite-vmexit-fields" case .vmx_vnmi: return "vmx-vnmi" case .vmx_vnmi_pending: return "vmx-vnmi-pending" case .vmx_vpid: return "vmx-vpid" case .vmx_wbinvd_exit: return "vmx-wbinvd-exit" case .vmx_xsaves: return "vmx-xsaves" case .vmx_zero_len_inject: return "vmx-zero-len-inject" case .vnmi: return "vnmi" case .vpclmulqdq: return "vpclmulqdq" case .waitpkg: return "waitpkg" case .wbnoinvd: return "wbnoinvd" case .wdt: return "wdt" case .wrmsrns: return "wrmsrns" case .x2apic: return "x2apic" case .xcrypt: return "xcrypt" case .xcrypt_en: return "xcrypt-en" case .xfd: return "xfd" case .xgetbv1: return "xgetbv1" case .xop: return "xop" case .xsave: return "xsave" case .xsavec: return "xsavec" case .xsaveerptr: return "xsaveerptr" case .xsaveopt: return "xsaveopt" case .xsaves: return "xsaves" case .xstore: return "xstore" case .xstore_en: return "xstore-en" case .xtpr: return "xtpr" case .zero_fcs_fds: return "zero-fcs-fds" } } } typealias QEMUCPUFlag_loongarch64 = AnyQEMUConstant typealias QEMUCPUFlag_m68k = AnyQEMUConstant typealias QEMUCPUFlag_microblaze = AnyQEMUConstant typealias QEMUCPUFlag_microblazeel = AnyQEMUConstant typealias QEMUCPUFlag_mips = AnyQEMUConstant typealias QEMUCPUFlag_mipsel = AnyQEMUConstant typealias QEMUCPUFlag_mips64 = AnyQEMUConstant typealias QEMUCPUFlag_mips64el = AnyQEMUConstant typealias QEMUCPUFlag_or1k = AnyQEMUConstant typealias QEMUCPUFlag_ppc = AnyQEMUConstant typealias QEMUCPUFlag_ppc64 = AnyQEMUConstant typealias QEMUCPUFlag_riscv32 = AnyQEMUConstant typealias QEMUCPUFlag_riscv64 = AnyQEMUConstant typealias QEMUCPUFlag_rx = AnyQEMUConstant enum QEMUCPUFlag_s390x: String, CaseIterable, QEMUCPUFlag { case _empty = "" var prettyValue: String { switch self { case ._empty: return "" } } } typealias QEMUCPUFlag_sh4 = AnyQEMUConstant typealias QEMUCPUFlag_sh4eb = AnyQEMUConstant enum QEMUCPUFlag_sparc: String, CaseIterable, QEMUCPUFlag { case div case float128 case fsmuld case mul var prettyValue: String { switch self { case .div: return "div" case .float128: return "float128" case .fsmuld: return "fsmuld" case .mul: return "mul" } } } enum QEMUCPUFlag_sparc64: String, CaseIterable, QEMUCPUFlag { case cmt case float128 case fmaf case gl case hypv case ima case vis1 case vis2 case vis3 case vis4 var prettyValue: String { switch self { case .cmt: return "cmt" case .float128: return "float128" case .fmaf: return "fmaf" case .gl: return "gl" case .hypv: return "hypv" case .ima: return "ima" case .vis1: return "vis1" case .vis2: return "vis2" case .vis3: return "vis3" case .vis4: return "vis4" } } } typealias QEMUCPUFlag_tricore = AnyQEMUConstant enum QEMUCPUFlag_x86_64: String, CaseIterable, QEMUCPUFlag { case _3dnow = "3dnow" case _3dnowext = "3dnowext" case _3dnowprefetch = "3dnowprefetch" case abm case ace2 case ace2_en = "ace2-en" case acpi case adx case aes case amd_no_ssb = "amd-no-ssb" case amd_psfd = "amd-psfd" case amd_ssbd = "amd-ssbd" case amd_stibp = "amd-stibp" case amx_bf16 = "amx-bf16" case amx_complex = "amx-complex" case amx_fp16 = "amx-fp16" case amx_int8 = "amx-int8" case amx_tile = "amx-tile" case apic case arat case arch_capabilities = "arch-capabilities" case arch_lbr = "arch-lbr" case auto_ibrs = "auto-ibrs" case avic case avx case avx_ifma = "avx-ifma" case avx_ne_convert = "avx-ne-convert" case avx_vnni = "avx-vnni" case avx_vnni_int16 = "avx-vnni-int16" case avx_vnni_int8 = "avx-vnni-int8" case avx10 case avx10_128 = "avx10-128" case avx10_256 = "avx10-256" case avx10_512 = "avx10-512" case avx2 case avx512_4fmaps = "avx512-4fmaps" case avx512_4vnniw = "avx512-4vnniw" case avx512_bf16 = "avx512-bf16" case avx512_fp16 = "avx512-fp16" case avx512_vp2intersect = "avx512-vp2intersect" case avx512_vpopcntdq = "avx512-vpopcntdq" case avx512bitalg case avx512bw case avx512cd case avx512dq case avx512er case avx512f case avx512ifma case avx512pf case avx512vbmi case avx512vbmi2 case avx512vl case avx512vnni case bhi_ctrl = "bhi-ctrl" case bhi_no = "bhi-no" case bmi1 case bmi2 case bus_lock_detect = "bus-lock-detect" case cid case cldemote case clflush case clflushopt case clwb case clzero case cmov case cmp_legacy = "cmp-legacy" case cmpccxadd case core_capability = "core-capability" case cr8legacy case cx16 case cx8 case dca case ddpd_u = "ddpd-u" case de case decodeassists case ds case ds_cpl = "ds-cpl" case dtes64 case eraps case erms case est case extapic case f16c case fb_clear = "fb-clear" case fbsdp_no = "fbsdp-no" case fdp_excptn_only = "fdp-excptn-only" case flush_l1d = "flush-l1d" case flushbyasid case fma case fma4 case fpu case fred case fsgsbase case fsrc case fsrm case fsrs case full_width_write = "full-width-write" case fxsr case fxsr_opt = "fxsr-opt" case fzrm case gds_no = "gds-no" case gfni case hle case ht case hypervisor case ia64 case ibpb case ibpb_brtype = "ibpb-brtype" case ibrs case ibrs_all = "ibrs-all" case ibs case intel_psfd = "intel-psfd" case intel_pt = "intel-pt" case intel_pt_lip = "intel-pt-lip" case invpcid case invtsc case ipred_ctrl = "ipred-ctrl" case kvm_asyncpf = "kvm-asyncpf" case kvm_asyncpf_int = "kvm-asyncpf-int" case kvm_asyncpf_vmexit = "kvm-asyncpf-vmexit" case kvm_hint_dedicated = "kvm-hint-dedicated" case kvm_mmu = "kvm-mmu" case kvm_msi_ext_dest_id = "kvm-msi-ext-dest-id" case kvm_nopiodelay = "kvm-nopiodelay" case kvm_poll_control = "kvm-poll-control" case kvm_pv_eoi = "kvm-pv-eoi" case kvm_pv_ipi = "kvm-pv-ipi" case kvm_pv_sched_yield = "kvm-pv-sched-yield" case kvm_pv_tlb_flush = "kvm-pv-tlb-flush" case kvm_pv_unhalt = "kvm-pv-unhalt" case kvm_steal_time = "kvm-steal-time" case kvmclock case kvmclock_stable_bit = "kvmclock-stable-bit" case la57 case lahf_lm = "lahf-lm" case lam case lbrv case lfence_always_serializing = "lfence-always-serializing" case lkgs case lm case lwp case mca case mcdt_no = "mcdt-no" case mce case md_clear = "md-clear" case mds_no = "mds-no" case misalignsse case mmx case mmxext case monitor case movbe case movdir64b case movdiri case mpx case msr case mtrr case no_nested_data_bp = "no-nested-data-bp" case nodeid_msr = "nodeid-msr" case npt case nrip_save = "nrip-save" case null_sel_clr_base = "null-sel-clr-base" case nx case osvw case overflow_recov = "overflow-recov" case pae case pat case pause_filter = "pause-filter" case pbe case pbrsb_no = "pbrsb-no" case pcid case pclmulqdq case pcommit case pdcm case pdpe1gb case perfctr_core = "perfctr-core" case perfctr_nb = "perfctr-nb" case perfmon_v2 = "perfmon-v2" case pfthreshold case pge case phe case phe_en = "phe-en" case pks case pku case pmm case pmm_en = "pmm-en" case pn case pni case popcnt case prefetchiti case pschange_mc_no = "pschange-mc-no" case psdp_no = "psdp-no" case pse case pse36 case rdctl_no = "rdctl-no" case rdpid case rdrand case rdseed case rdtscp case rfds_clear = "rfds-clear" case rfds_no = "rfds-no" case rrsba_ctrl = "rrsba-ctrl" case rsba case rtm case sbdr_ssdp_no = "sbdr-ssdp-no" case sbpb case sep case serialize case sgx case sgx_aex_notify = "sgx-aex-notify" case sgx_debug = "sgx-debug" case sgx_edeccssa = "sgx-edeccssa" case sgx_exinfo = "sgx-exinfo" case sgx_kss = "sgx-kss" case sgx_mode64 = "sgx-mode64" case sgx_provisionkey = "sgx-provisionkey" case sgx_tokenkey = "sgx-tokenkey" case sgx1 case sgx2 case sgxlc case sha_ni = "sha-ni" case sha512 case skinit case skip_l1dfl_vmentry = "skip-l1dfl-vmentry" case sm3 case sm4 case smap case smep case smx case spec_ctrl = "spec-ctrl" case split_lock_detect = "split-lock-detect" case srso_no = "srso-no" case srso_user_kernel_no = "srso-user-kernel-no" case ss case ssb_no = "ssb-no" case ssbd case sse case sse2 case sse4_1 = "sse4.1" case sse4_2 = "sse4.2" case sse4a case ssse3 case stibp case stibp_always_on = "stibp-always-on" case succor case svm case svm_lock = "svm-lock" case svme_addr_chk = "svme-addr-chk" case syscall case taa_no = "taa-no" case tbm case tce case tm case tm2 case topoext case tsc case tsc_adjust = "tsc-adjust" case tsc_deadline = "tsc-deadline" case tsc_scale = "tsc-scale" case tsx_ctrl = "tsx-ctrl" case tsx_ldtrk = "tsx-ldtrk" case umip case v_vmsave_vmload = "v-vmsave-vmload" case vaes case vgif case virt_ssbd = "virt-ssbd" case vmcb_clean = "vmcb-clean" case vme case vmx case vmx_activity_hlt = "vmx-activity-hlt" case vmx_activity_shutdown = "vmx-activity-shutdown" case vmx_activity_wait_sipi = "vmx-activity-wait-sipi" case vmx_any_errcode = "vmx-any-errcode" case vmx_apicv_register = "vmx-apicv-register" case vmx_apicv_vid = "vmx-apicv-vid" case vmx_apicv_x2apic = "vmx-apicv-x2apic" case vmx_apicv_xapic = "vmx-apicv-xapic" case vmx_cr3_load_noexit = "vmx-cr3-load-noexit" case vmx_cr3_store_noexit = "vmx-cr3-store-noexit" case vmx_cr8_load_exit = "vmx-cr8-load-exit" case vmx_cr8_store_exit = "vmx-cr8-store-exit" case vmx_desc_exit = "vmx-desc-exit" case vmx_enable_user_wait_pause = "vmx-enable-user-wait-pause" case vmx_encls_exit = "vmx-encls-exit" case vmx_entry_ia32e_mode = "vmx-entry-ia32e-mode" case vmx_entry_load_bndcfgs = "vmx-entry-load-bndcfgs" case vmx_entry_load_efer = "vmx-entry-load-efer" case vmx_entry_load_fred = "vmx-entry-load-fred" case vmx_entry_load_pat = "vmx-entry-load-pat" case vmx_entry_load_perf_global_ctrl = "vmx-entry-load-perf-global-ctrl" case vmx_entry_load_pkrs = "vmx-entry-load-pkrs" case vmx_entry_load_rtit_ctl = "vmx-entry-load-rtit-ctl" case vmx_entry_noload_debugctl = "vmx-entry-noload-debugctl" case vmx_ept = "vmx-ept" case vmx_ept_1gb = "vmx-ept-1gb" case vmx_ept_2mb = "vmx-ept-2mb" case vmx_ept_advanced_exitinfo = "vmx-ept-advanced-exitinfo" case vmx_ept_execonly = "vmx-ept-execonly" case vmx_eptad = "vmx-eptad" case vmx_eptp_switching = "vmx-eptp-switching" case vmx_exit_ack_intr = "vmx-exit-ack-intr" case vmx_exit_clear_bndcfgs = "vmx-exit-clear-bndcfgs" case vmx_exit_clear_rtit_ctl = "vmx-exit-clear-rtit-ctl" case vmx_exit_load_efer = "vmx-exit-load-efer" case vmx_exit_load_pat = "vmx-exit-load-pat" case vmx_exit_load_perf_global_ctrl = "vmx-exit-load-perf-global-ctrl" case vmx_exit_load_pkrs = "vmx-exit-load-pkrs" case vmx_exit_nosave_debugctl = "vmx-exit-nosave-debugctl" case vmx_exit_save_efer = "vmx-exit-save-efer" case vmx_exit_save_pat = "vmx-exit-save-pat" case vmx_exit_save_preemption_timer = "vmx-exit-save-preemption-timer" case vmx_exit_secondary_ctls = "vmx-exit-secondary-ctls" case vmx_flexpriority = "vmx-flexpriority" case vmx_hlt_exit = "vmx-hlt-exit" case vmx_ins_outs = "vmx-ins-outs" case vmx_intr_exit = "vmx-intr-exit" case vmx_invept = "vmx-invept" case vmx_invept_all_context = "vmx-invept-all-context" case vmx_invept_single_context = "vmx-invept-single-context" case vmx_invept_single_context_noglobals = "vmx-invept-single-context-noglobals" case vmx_invlpg_exit = "vmx-invlpg-exit" case vmx_invpcid_exit = "vmx-invpcid-exit" case vmx_invvpid = "vmx-invvpid" case vmx_invvpid_all_context = "vmx-invvpid-all-context" case vmx_invvpid_single_addr = "vmx-invvpid-single-addr" case vmx_io_bitmap = "vmx-io-bitmap" case vmx_io_exit = "vmx-io-exit" case vmx_monitor_exit = "vmx-monitor-exit" case vmx_movdr_exit = "vmx-movdr-exit" case vmx_msr_bitmap = "vmx-msr-bitmap" case vmx_mtf = "vmx-mtf" case vmx_mwait_exit = "vmx-mwait-exit" case vmx_nested_exception = "vmx-nested-exception" case vmx_nmi_exit = "vmx-nmi-exit" case vmx_page_walk_4 = "vmx-page-walk-4" case vmx_page_walk_5 = "vmx-page-walk-5" case vmx_pause_exit = "vmx-pause-exit" case vmx_ple = "vmx-ple" case vmx_pml = "vmx-pml" case vmx_posted_intr = "vmx-posted-intr" case vmx_preemption_timer = "vmx-preemption-timer" case vmx_rdpmc_exit = "vmx-rdpmc-exit" case vmx_rdrand_exit = "vmx-rdrand-exit" case vmx_rdseed_exit = "vmx-rdseed-exit" case vmx_rdtsc_exit = "vmx-rdtsc-exit" case vmx_rdtscp_exit = "vmx-rdtscp-exit" case vmx_secondary_ctls = "vmx-secondary-ctls" case vmx_shadow_vmcs = "vmx-shadow-vmcs" case vmx_store_lma = "vmx-store-lma" case vmx_true_ctls = "vmx-true-ctls" case vmx_tsc_offset = "vmx-tsc-offset" case vmx_tsc_scaling = "vmx-tsc-scaling" case vmx_unrestricted_guest = "vmx-unrestricted-guest" case vmx_vintr_pending = "vmx-vintr-pending" case vmx_vmfunc = "vmx-vmfunc" case vmx_vmwrite_vmexit_fields = "vmx-vmwrite-vmexit-fields" case vmx_vnmi = "vmx-vnmi" case vmx_vnmi_pending = "vmx-vnmi-pending" case vmx_vpid = "vmx-vpid" case vmx_wbinvd_exit = "vmx-wbinvd-exit" case vmx_xsaves = "vmx-xsaves" case vmx_zero_len_inject = "vmx-zero-len-inject" case vnmi case vpclmulqdq case waitpkg case wbnoinvd case wdt case wrmsrns case x2apic case xcrypt case xcrypt_en = "xcrypt-en" case xfd case xgetbv1 case xop case xsave case xsavec case xsaveerptr case xsaveopt case xsaves case xstore case xstore_en = "xstore-en" case xtpr case zero_fcs_fds = "zero-fcs-fds" var prettyValue: String { switch self { case ._3dnow: return "3dnow" case ._3dnowext: return "3dnowext" case ._3dnowprefetch: return "3dnowprefetch" case .abm: return "abm" case .ace2: return "ace2" case .ace2_en: return "ace2-en" case .acpi: return "acpi" case .adx: return "adx" case .aes: return "aes" case .amd_no_ssb: return "amd-no-ssb" case .amd_psfd: return "amd-psfd" case .amd_ssbd: return "amd-ssbd" case .amd_stibp: return "amd-stibp" case .amx_bf16: return "amx-bf16" case .amx_complex: return "amx-complex" case .amx_fp16: return "amx-fp16" case .amx_int8: return "amx-int8" case .amx_tile: return "amx-tile" case .apic: return "apic" case .arat: return "arat" case .arch_capabilities: return "arch-capabilities" case .arch_lbr: return "arch-lbr" case .auto_ibrs: return "auto-ibrs" case .avic: return "avic" case .avx: return "avx" case .avx_ifma: return "avx-ifma" case .avx_ne_convert: return "avx-ne-convert" case .avx_vnni: return "avx-vnni" case .avx_vnni_int16: return "avx-vnni-int16" case .avx_vnni_int8: return "avx-vnni-int8" case .avx10: return "avx10" case .avx10_128: return "avx10-128" case .avx10_256: return "avx10-256" case .avx10_512: return "avx10-512" case .avx2: return "avx2" case .avx512_4fmaps: return "avx512-4fmaps" case .avx512_4vnniw: return "avx512-4vnniw" case .avx512_bf16: return "avx512-bf16" case .avx512_fp16: return "avx512-fp16" case .avx512_vp2intersect: return "avx512-vp2intersect" case .avx512_vpopcntdq: return "avx512-vpopcntdq" case .avx512bitalg: return "avx512bitalg" case .avx512bw: return "avx512bw" case .avx512cd: return "avx512cd" case .avx512dq: return "avx512dq" case .avx512er: return "avx512er" case .avx512f: return "avx512f" case .avx512ifma: return "avx512ifma" case .avx512pf: return "avx512pf" case .avx512vbmi: return "avx512vbmi" case .avx512vbmi2: return "avx512vbmi2" case .avx512vl: return "avx512vl" case .avx512vnni: return "avx512vnni" case .bhi_ctrl: return "bhi-ctrl" case .bhi_no: return "bhi-no" case .bmi1: return "bmi1" case .bmi2: return "bmi2" case .bus_lock_detect: return "bus-lock-detect" case .cid: return "cid" case .cldemote: return "cldemote" case .clflush: return "clflush" case .clflushopt: return "clflushopt" case .clwb: return "clwb" case .clzero: return "clzero" case .cmov: return "cmov" case .cmp_legacy: return "cmp-legacy" case .cmpccxadd: return "cmpccxadd" case .core_capability: return "core-capability" case .cr8legacy: return "cr8legacy" case .cx16: return "cx16" case .cx8: return "cx8" case .dca: return "dca" case .ddpd_u: return "ddpd-u" case .de: return "de" case .decodeassists: return "decodeassists" case .ds: return "ds" case .ds_cpl: return "ds-cpl" case .dtes64: return "dtes64" case .eraps: return "eraps" case .erms: return "erms" case .est: return "est" case .extapic: return "extapic" case .f16c: return "f16c" case .fb_clear: return "fb-clear" case .fbsdp_no: return "fbsdp-no" case .fdp_excptn_only: return "fdp-excptn-only" case .flush_l1d: return "flush-l1d" case .flushbyasid: return "flushbyasid" case .fma: return "fma" case .fma4: return "fma4" case .fpu: return "fpu" case .fred: return "fred" case .fsgsbase: return "fsgsbase" case .fsrc: return "fsrc" case .fsrm: return "fsrm" case .fsrs: return "fsrs" case .full_width_write: return "full-width-write" case .fxsr: return "fxsr" case .fxsr_opt: return "fxsr-opt" case .fzrm: return "fzrm" case .gds_no: return "gds-no" case .gfni: return "gfni" case .hle: return "hle" case .ht: return "ht" case .hypervisor: return "hypervisor" case .ia64: return "ia64" case .ibpb: return "ibpb" case .ibpb_brtype: return "ibpb-brtype" case .ibrs: return "ibrs" case .ibrs_all: return "ibrs-all" case .ibs: return "ibs" case .intel_psfd: return "intel-psfd" case .intel_pt: return "intel-pt" case .intel_pt_lip: return "intel-pt-lip" case .invpcid: return "invpcid" case .invtsc: return "invtsc" case .ipred_ctrl: return "ipred-ctrl" case .kvm_asyncpf: return "kvm-asyncpf" case .kvm_asyncpf_int: return "kvm-asyncpf-int" case .kvm_asyncpf_vmexit: return "kvm-asyncpf-vmexit" case .kvm_hint_dedicated: return "kvm-hint-dedicated" case .kvm_mmu: return "kvm-mmu" case .kvm_msi_ext_dest_id: return "kvm-msi-ext-dest-id" case .kvm_nopiodelay: return "kvm-nopiodelay" case .kvm_poll_control: return "kvm-poll-control" case .kvm_pv_eoi: return "kvm-pv-eoi" case .kvm_pv_ipi: return "kvm-pv-ipi" case .kvm_pv_sched_yield: return "kvm-pv-sched-yield" case .kvm_pv_tlb_flush: return "kvm-pv-tlb-flush" case .kvm_pv_unhalt: return "kvm-pv-unhalt" case .kvm_steal_time: return "kvm-steal-time" case .kvmclock: return "kvmclock" case .kvmclock_stable_bit: return "kvmclock-stable-bit" case .la57: return "la57" case .lahf_lm: return "lahf-lm" case .lam: return "lam" case .lbrv: return "lbrv" case .lfence_always_serializing: return "lfence-always-serializing" case .lkgs: return "lkgs" case .lm: return "lm" case .lwp: return "lwp" case .mca: return "mca" case .mcdt_no: return "mcdt-no" case .mce: return "mce" case .md_clear: return "md-clear" case .mds_no: return "mds-no" case .misalignsse: return "misalignsse" case .mmx: return "mmx" case .mmxext: return "mmxext" case .monitor: return "monitor" case .movbe: return "movbe" case .movdir64b: return "movdir64b" case .movdiri: return "movdiri" case .mpx: return "mpx" case .msr: return "msr" case .mtrr: return "mtrr" case .no_nested_data_bp: return "no-nested-data-bp" case .nodeid_msr: return "nodeid-msr" case .npt: return "npt" case .nrip_save: return "nrip-save" case .null_sel_clr_base: return "null-sel-clr-base" case .nx: return "nx" case .osvw: return "osvw" case .overflow_recov: return "overflow-recov" case .pae: return "pae" case .pat: return "pat" case .pause_filter: return "pause-filter" case .pbe: return "pbe" case .pbrsb_no: return "pbrsb-no" case .pcid: return "pcid" case .pclmulqdq: return "pclmulqdq" case .pcommit: return "pcommit" case .pdcm: return "pdcm" case .pdpe1gb: return "pdpe1gb" case .perfctr_core: return "perfctr-core" case .perfctr_nb: return "perfctr-nb" case .perfmon_v2: return "perfmon-v2" case .pfthreshold: return "pfthreshold" case .pge: return "pge" case .phe: return "phe" case .phe_en: return "phe-en" case .pks: return "pks" case .pku: return "pku" case .pmm: return "pmm" case .pmm_en: return "pmm-en" case .pn: return "pn" case .pni: return "pni" case .popcnt: return "popcnt" case .prefetchiti: return "prefetchiti" case .pschange_mc_no: return "pschange-mc-no" case .psdp_no: return "psdp-no" case .pse: return "pse" case .pse36: return "pse36" case .rdctl_no: return "rdctl-no" case .rdpid: return "rdpid" case .rdrand: return "rdrand" case .rdseed: return "rdseed" case .rdtscp: return "rdtscp" case .rfds_clear: return "rfds-clear" case .rfds_no: return "rfds-no" case .rrsba_ctrl: return "rrsba-ctrl" case .rsba: return "rsba" case .rtm: return "rtm" case .sbdr_ssdp_no: return "sbdr-ssdp-no" case .sbpb: return "sbpb" case .sep: return "sep" case .serialize: return "serialize" case .sgx: return "sgx" case .sgx_aex_notify: return "sgx-aex-notify" case .sgx_debug: return "sgx-debug" case .sgx_edeccssa: return "sgx-edeccssa" case .sgx_exinfo: return "sgx-exinfo" case .sgx_kss: return "sgx-kss" case .sgx_mode64: return "sgx-mode64" case .sgx_provisionkey: return "sgx-provisionkey" case .sgx_tokenkey: return "sgx-tokenkey" case .sgx1: return "sgx1" case .sgx2: return "sgx2" case .sgxlc: return "sgxlc" case .sha_ni: return "sha-ni" case .sha512: return "sha512" case .skinit: return "skinit" case .skip_l1dfl_vmentry: return "skip-l1dfl-vmentry" case .sm3: return "sm3" case .sm4: return "sm4" case .smap: return "smap" case .smep: return "smep" case .smx: return "smx" case .spec_ctrl: return "spec-ctrl" case .split_lock_detect: return "split-lock-detect" case .srso_no: return "srso-no" case .srso_user_kernel_no: return "srso-user-kernel-no" case .ss: return "ss" case .ssb_no: return "ssb-no" case .ssbd: return "ssbd" case .sse: return "sse" case .sse2: return "sse2" case .sse4_1: return "sse4.1" case .sse4_2: return "sse4.2" case .sse4a: return "sse4a" case .ssse3: return "ssse3" case .stibp: return "stibp" case .stibp_always_on: return "stibp-always-on" case .succor: return "succor" case .svm: return "svm" case .svm_lock: return "svm-lock" case .svme_addr_chk: return "svme-addr-chk" case .syscall: return "syscall" case .taa_no: return "taa-no" case .tbm: return "tbm" case .tce: return "tce" case .tm: return "tm" case .tm2: return "tm2" case .topoext: return "topoext" case .tsc: return "tsc" case .tsc_adjust: return "tsc-adjust" case .tsc_deadline: return "tsc-deadline" case .tsc_scale: return "tsc-scale" case .tsx_ctrl: return "tsx-ctrl" case .tsx_ldtrk: return "tsx-ldtrk" case .umip: return "umip" case .v_vmsave_vmload: return "v-vmsave-vmload" case .vaes: return "vaes" case .vgif: return "vgif" case .virt_ssbd: return "virt-ssbd" case .vmcb_clean: return "vmcb-clean" case .vme: return "vme" case .vmx: return "vmx" case .vmx_activity_hlt: return "vmx-activity-hlt" case .vmx_activity_shutdown: return "vmx-activity-shutdown" case .vmx_activity_wait_sipi: return "vmx-activity-wait-sipi" case .vmx_any_errcode: return "vmx-any-errcode" case .vmx_apicv_register: return "vmx-apicv-register" case .vmx_apicv_vid: return "vmx-apicv-vid" case .vmx_apicv_x2apic: return "vmx-apicv-x2apic" case .vmx_apicv_xapic: return "vmx-apicv-xapic" case .vmx_cr3_load_noexit: return "vmx-cr3-load-noexit" case .vmx_cr3_store_noexit: return "vmx-cr3-store-noexit" case .vmx_cr8_load_exit: return "vmx-cr8-load-exit" case .vmx_cr8_store_exit: return "vmx-cr8-store-exit" case .vmx_desc_exit: return "vmx-desc-exit" case .vmx_enable_user_wait_pause: return "vmx-enable-user-wait-pause" case .vmx_encls_exit: return "vmx-encls-exit" case .vmx_entry_ia32e_mode: return "vmx-entry-ia32e-mode" case .vmx_entry_load_bndcfgs: return "vmx-entry-load-bndcfgs" case .vmx_entry_load_efer: return "vmx-entry-load-efer" case .vmx_entry_load_fred: return "vmx-entry-load-fred" case .vmx_entry_load_pat: return "vmx-entry-load-pat" case .vmx_entry_load_perf_global_ctrl: return "vmx-entry-load-perf-global-ctrl" case .vmx_entry_load_pkrs: return "vmx-entry-load-pkrs" case .vmx_entry_load_rtit_ctl: return "vmx-entry-load-rtit-ctl" case .vmx_entry_noload_debugctl: return "vmx-entry-noload-debugctl" case .vmx_ept: return "vmx-ept" case .vmx_ept_1gb: return "vmx-ept-1gb" case .vmx_ept_2mb: return "vmx-ept-2mb" case .vmx_ept_advanced_exitinfo: return "vmx-ept-advanced-exitinfo" case .vmx_ept_execonly: return "vmx-ept-execonly" case .vmx_eptad: return "vmx-eptad" case .vmx_eptp_switching: return "vmx-eptp-switching" case .vmx_exit_ack_intr: return "vmx-exit-ack-intr" case .vmx_exit_clear_bndcfgs: return "vmx-exit-clear-bndcfgs" case .vmx_exit_clear_rtit_ctl: return "vmx-exit-clear-rtit-ctl" case .vmx_exit_load_efer: return "vmx-exit-load-efer" case .vmx_exit_load_pat: return "vmx-exit-load-pat" case .vmx_exit_load_perf_global_ctrl: return "vmx-exit-load-perf-global-ctrl" case .vmx_exit_load_pkrs: return "vmx-exit-load-pkrs" case .vmx_exit_nosave_debugctl: return "vmx-exit-nosave-debugctl" case .vmx_exit_save_efer: return "vmx-exit-save-efer" case .vmx_exit_save_pat: return "vmx-exit-save-pat" case .vmx_exit_save_preemption_timer: return "vmx-exit-save-preemption-timer" case .vmx_exit_secondary_ctls: return "vmx-exit-secondary-ctls" case .vmx_flexpriority: return "vmx-flexpriority" case .vmx_hlt_exit: return "vmx-hlt-exit" case .vmx_ins_outs: return "vmx-ins-outs" case .vmx_intr_exit: return "vmx-intr-exit" case .vmx_invept: return "vmx-invept" case .vmx_invept_all_context: return "vmx-invept-all-context" case .vmx_invept_single_context: return "vmx-invept-single-context" case .vmx_invept_single_context_noglobals: return "vmx-invept-single-context-noglobals" case .vmx_invlpg_exit: return "vmx-invlpg-exit" case .vmx_invpcid_exit: return "vmx-invpcid-exit" case .vmx_invvpid: return "vmx-invvpid" case .vmx_invvpid_all_context: return "vmx-invvpid-all-context" case .vmx_invvpid_single_addr: return "vmx-invvpid-single-addr" case .vmx_io_bitmap: return "vmx-io-bitmap" case .vmx_io_exit: return "vmx-io-exit" case .vmx_monitor_exit: return "vmx-monitor-exit" case .vmx_movdr_exit: return "vmx-movdr-exit" case .vmx_msr_bitmap: return "vmx-msr-bitmap" case .vmx_mtf: return "vmx-mtf" case .vmx_mwait_exit: return "vmx-mwait-exit" case .vmx_nested_exception: return "vmx-nested-exception" case .vmx_nmi_exit: return "vmx-nmi-exit" case .vmx_page_walk_4: return "vmx-page-walk-4" case .vmx_page_walk_5: return "vmx-page-walk-5" case .vmx_pause_exit: return "vmx-pause-exit" case .vmx_ple: return "vmx-ple" case .vmx_pml: return "vmx-pml" case .vmx_posted_intr: return "vmx-posted-intr" case .vmx_preemption_timer: return "vmx-preemption-timer" case .vmx_rdpmc_exit: return "vmx-rdpmc-exit" case .vmx_rdrand_exit: return "vmx-rdrand-exit" case .vmx_rdseed_exit: return "vmx-rdseed-exit" case .vmx_rdtsc_exit: return "vmx-rdtsc-exit" case .vmx_rdtscp_exit: return "vmx-rdtscp-exit" case .vmx_secondary_ctls: return "vmx-secondary-ctls" case .vmx_shadow_vmcs: return "vmx-shadow-vmcs" case .vmx_store_lma: return "vmx-store-lma" case .vmx_true_ctls: return "vmx-true-ctls" case .vmx_tsc_offset: return "vmx-tsc-offset" case .vmx_tsc_scaling: return "vmx-tsc-scaling" case .vmx_unrestricted_guest: return "vmx-unrestricted-guest" case .vmx_vintr_pending: return "vmx-vintr-pending" case .vmx_vmfunc: return "vmx-vmfunc" case .vmx_vmwrite_vmexit_fields: return "vmx-vmwrite-vmexit-fields" case .vmx_vnmi: return "vmx-vnmi" case .vmx_vnmi_pending: return "vmx-vnmi-pending" case .vmx_vpid: return "vmx-vpid" case .vmx_wbinvd_exit: return "vmx-wbinvd-exit" case .vmx_xsaves: return "vmx-xsaves" case .vmx_zero_len_inject: return "vmx-zero-len-inject" case .vnmi: return "vnmi" case .vpclmulqdq: return "vpclmulqdq" case .waitpkg: return "waitpkg" case .wbnoinvd: return "wbnoinvd" case .wdt: return "wdt" case .wrmsrns: return "wrmsrns" case .x2apic: return "x2apic" case .xcrypt: return "xcrypt" case .xcrypt_en: return "xcrypt-en" case .xfd: return "xfd" case .xgetbv1: return "xgetbv1" case .xop: return "xop" case .xsave: return "xsave" case .xsavec: return "xsavec" case .xsaveerptr: return "xsaveerptr" case .xsaveopt: return "xsaveopt" case .xsaves: return "xsaves" case .xstore: return "xstore" case .xstore_en: return "xstore-en" case .xtpr: return "xtpr" case .zero_fcs_fds: return "zero-fcs-fds" } } } typealias QEMUCPUFlag_xtensa = AnyQEMUConstant typealias QEMUCPUFlag_xtensaeb = AnyQEMUConstant enum QEMUTarget_alpha: String, CaseIterable, QEMUTarget { case clipper case none static var `default`: QEMUTarget_alpha { .clipper } var prettyValue: String { switch self { case .clipper: return "Alpha DP264/CLIPPER (default) (clipper)" case .none: return "empty machine (none)" } } } enum QEMUTarget_arm: String, CaseIterable, QEMUTarget { case integratorcp case kzm case mps2_an385 = "mps2-an385" case mps2_an386 = "mps2-an386" case mps2_an500 = "mps2-an500" case mps2_an505 = "mps2-an505" case mps2_an511 = "mps2-an511" case mps2_an521 = "mps2-an521" case mps3_an524 = "mps3-an524" case mps3_an536 = "mps3-an536" case mps3_an547 = "mps3-an547" case musca_a = "musca-a" case musca_b1 = "musca-b1" case realview_eb_mpcore = "realview-eb-mpcore" case realview_eb = "realview-eb" case realview_pbx_a9 = "realview-pbx-a9" case realview_pb_a8 = "realview-pb-a8" case vexpress_a15 = "vexpress-a15" case vexpress_a9 = "vexpress-a9" case versatileab case versatilepb case imx25_pdk = "imx25-pdk" case ast1030_evb = "ast1030-evb" case ast2500_evb = "ast2500-evb" case ast2600_evb = "ast2600-evb" case b_l475e_iot01a = "b-l475e-iot01a" case microbit case bpim2u case g220a_bmc = "g220a-bmc" case highbank case midway case canon_a1100 = "canon-a1100" case bletchley_bmc = "bletchley-bmc" case fuji_bmc = "fuji-bmc" case tiogapass_bmc = "tiogapass-bmc" case yosemitev2_bmc = "yosemitev2-bmc" case fby35_bmc = "fby35-bmc" case sabrelite case mcimx6ul_evk = "mcimx6ul-evk" case mcimx7d_sabre = "mcimx7d-sabre" case rainier_bmc = "rainier-bmc" case fp5280g2_bmc = "fp5280g2-bmc" case kudo_bmc = "kudo-bmc" case musicpal case fby35 case mori_bmc = "mori-bmc" case netduino2 case netduinoplus2 case npcm750_evb = "npcm750-evb" case sonorapass_bmc = "sonorapass-bmc" case olimex_stm32_h405 = "olimex-stm32-h405" case palmetto_bmc = "palmetto-bmc" case romulus_bmc = "romulus-bmc" case witherspoon_bmc = "witherspoon-bmc" case orangepi_pc = "orangepi-pc" case virt case virt_10_0 = "virt-10.0" case virt_2_10 = "virt-2.10" case virt_2_11 = "virt-2.11" case virt_2_12 = "virt-2.12" case virt_2_6 = "virt-2.6" case virt_2_7 = "virt-2.7" case virt_2_8 = "virt-2.8" case virt_2_9 = "virt-2.9" case virt_3_0 = "virt-3.0" case virt_3_1 = "virt-3.1" case virt_4_0 = "virt-4.0" case virt_4_1 = "virt-4.1" case virt_4_2 = "virt-4.2" case virt_5_0 = "virt-5.0" case virt_5_1 = "virt-5.1" case virt_5_2 = "virt-5.2" case virt_6_0 = "virt-6.0" case virt_6_1 = "virt-6.1" case virt_6_2 = "virt-6.2" case virt_7_0 = "virt-7.0" case virt_7_1 = "virt-7.1" case virt_7_2 = "virt-7.2" case virt_8_0 = "virt-8.0" case virt_8_1 = "virt-8.1" case virt_8_2 = "virt-8.2" case virt_9_0 = "virt-9.0" case virt_9_1 = "virt-9.1" case virt_9_2 = "virt-9.2" case qcom_dc_scm_v1_bmc = "qcom-dc-scm-v1-bmc" case qcom_firework_bmc = "qcom-firework-bmc" case quanta_gbs_bmc = "quanta-gbs-bmc" case quanta_gsj = "quanta-gsj" case quanta_q71l_bmc = "quanta-q71l-bmc" case raspi2b case raspi1ap case raspi0 case stm32vldiscovery case nuri case smdkc210 case collie case sx1_v1 = "sx1-v1" case sx1 case emcraft_sf2 = "emcraft-sf2" case lm3s6965evb case lm3s811evb case supermicrox11_bmc = "supermicrox11-bmc" case supermicro_x11spi_bmc = "supermicro-x11spi-bmc" case xilinx_zynq_a9 = "xilinx-zynq-a9" case cubieboard case none static var `default`: QEMUTarget_arm { .virt } var prettyValue: String { switch self { case .integratorcp: return "ARM Integrator/CP (ARM926EJ-S) (integratorcp)" case .kzm: return "ARM KZM Emulation Baseboard (ARM1136) (kzm)" case .mps2_an385: return "ARM MPS2 with AN385 FPGA image for Cortex-M3 (mps2-an385)" case .mps2_an386: return "ARM MPS2 with AN386 FPGA image for Cortex-M4 (mps2-an386)" case .mps2_an500: return "ARM MPS2 with AN500 FPGA image for Cortex-M7 (mps2-an500)" case .mps2_an505: return "ARM MPS2 with AN505 FPGA image for Cortex-M33 (mps2-an505)" case .mps2_an511: return "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3 (mps2-an511)" case .mps2_an521: return "ARM MPS2 with AN521 FPGA image for dual Cortex-M33 (mps2-an521)" case .mps3_an524: return "ARM MPS3 with AN524 FPGA image for dual Cortex-M33 (mps3-an524)" case .mps3_an536: return "ARM MPS3 with AN536 FPGA image for Cortex-R52 (mps3-an536)" case .mps3_an547: return "ARM MPS3 with AN547 FPGA image for Cortex-M55 (mps3-an547)" case .musca_a: return "ARM Musca-A board (dual Cortex-M33) (musca-a)" case .musca_b1: return "ARM Musca-B1 board (dual Cortex-M33) (musca-b1)" case .realview_eb_mpcore: return "ARM RealView Emulation Baseboard (ARM11MPCore) (realview-eb-mpcore)" case .realview_eb: return "ARM RealView Emulation Baseboard (ARM926EJ-S) (realview-eb)" case .realview_pbx_a9: return "ARM RealView Platform Baseboard Explore for Cortex-A9 (realview-pbx-a9)" case .realview_pb_a8: return "ARM RealView Platform Baseboard for Cortex-A8 (realview-pb-a8)" case .vexpress_a15: return "ARM Versatile Express for Cortex-A15 (vexpress-a15)" case .vexpress_a9: return "ARM Versatile Express for Cortex-A9 (vexpress-a9)" case .versatileab: return "ARM Versatile/AB (ARM926EJ-S) (versatileab)" case .versatilepb: return "ARM Versatile/PB (ARM926EJ-S) (versatilepb)" case .imx25_pdk: return "ARM i.MX25 PDK board (ARM926) (imx25-pdk)" case .ast1030_evb: return "Aspeed AST1030 MiniBMC (Cortex-M4) (ast1030-evb)" case .ast2500_evb: return "Aspeed AST2500 EVB (ARM1176) (ast2500-evb)" case .ast2600_evb: return "Aspeed AST2600 EVB (Cortex-A7) (ast2600-evb)" case .b_l475e_iot01a: return "B-L475E-IOT01A Discovery Kit (Cortex-M4) (b-l475e-iot01a)" case .microbit: return "BBC micro:bit (Cortex-M0) (microbit)" case .bpim2u: return "Bananapi M2U (Cortex-A7) (bpim2u)" case .g220a_bmc: return "Bytedance G220A BMC (ARM1176) (g220a-bmc)" case .highbank: return "Calxeda Highbank (ECX-1000) (highbank)" case .midway: return "Calxeda Midway (ECX-2000) (midway)" case .canon_a1100: return "Canon PowerShot A1100 IS (ARM946) (canon-a1100)" case .bletchley_bmc: return "Facebook Bletchley BMC (Cortex-A7) (bletchley-bmc)" case .fuji_bmc: return "Facebook Fuji BMC (Cortex-A7) (fuji-bmc)" case .tiogapass_bmc: return "Facebook Tiogapass BMC (ARM1176) (tiogapass-bmc)" case .yosemitev2_bmc: return "Facebook YosemiteV2 BMC (ARM1176) (yosemitev2-bmc)" case .fby35_bmc: return "Facebook fby35 BMC (Cortex-A7) (fby35-bmc)" case .sabrelite: return "Freescale i.MX6 Quad SABRE Lite Board (Cortex-A9) (sabrelite)" case .mcimx6ul_evk: return "Freescale i.MX6UL Evaluation Kit (Cortex-A7) (mcimx6ul-evk)" case .mcimx7d_sabre: return "Freescale i.MX7 DUAL SABRE (Cortex-A7) (mcimx7d-sabre)" case .rainier_bmc: return "IBM Rainier BMC (Cortex-A7) (rainier-bmc)" case .fp5280g2_bmc: return "Inspur FP5280G2 BMC (ARM1176) (fp5280g2-bmc)" case .kudo_bmc: return "Kudo BMC (Cortex-A9) (kudo-bmc)" case .musicpal: return "Marvell 88w8618 / MusicPal (ARM926EJ-S) (musicpal)" case .fby35: return "Meta Platforms fby35 (fby35)" case .mori_bmc: return "Mori BMC (Cortex-A9) (mori-bmc)" case .netduino2: return "Netduino 2 Machine (Cortex-M3) (netduino2)" case .netduinoplus2: return "Netduino Plus 2 Machine (Cortex-M4) (netduinoplus2)" case .npcm750_evb: return "Nuvoton NPCM750 Evaluation Board (Cortex-A9) (npcm750-evb)" case .sonorapass_bmc: return "OCP SonoraPass BMC (ARM1176) (sonorapass-bmc)" case .olimex_stm32_h405: return "Olimex STM32-H405 (Cortex-M4) (olimex-stm32-h405)" case .palmetto_bmc: return "OpenPOWER Palmetto BMC (ARM926EJ-S) (palmetto-bmc)" case .romulus_bmc: return "OpenPOWER Romulus BMC (ARM1176) (romulus-bmc)" case .witherspoon_bmc: return "OpenPOWER Witherspoon BMC (ARM1176) (witherspoon-bmc)" case .orangepi_pc: return "Orange Pi PC (Cortex-A7) (orangepi-pc)" case .virt: return "QEMU 10.0 ARM Virtual Machine (alias of virt-10.0) (virt)" case .virt_10_0: return "QEMU 10.0 ARM Virtual Machine (virt-10.0)" case .virt_2_10: return "QEMU 2.10 ARM Virtual Machine (deprecated) (virt-2.10)" case .virt_2_11: return "QEMU 2.11 ARM Virtual Machine (deprecated) (virt-2.11)" case .virt_2_12: return "QEMU 2.12 ARM Virtual Machine (deprecated) (virt-2.12)" case .virt_2_6: return "QEMU 2.6 ARM Virtual Machine (deprecated) (virt-2.6)" case .virt_2_7: return "QEMU 2.7 ARM Virtual Machine (deprecated) (virt-2.7)" case .virt_2_8: return "QEMU 2.8 ARM Virtual Machine (deprecated) (virt-2.8)" case .virt_2_9: return "QEMU 2.9 ARM Virtual Machine (deprecated) (virt-2.9)" case .virt_3_0: return "QEMU 3.0 ARM Virtual Machine (deprecated) (virt-3.0)" case .virt_3_1: return "QEMU 3.1 ARM Virtual Machine (deprecated) (virt-3.1)" case .virt_4_0: return "QEMU 4.0 ARM Virtual Machine (deprecated) (virt-4.0)" case .virt_4_1: return "QEMU 4.1 ARM Virtual Machine (deprecated) (virt-4.1)" case .virt_4_2: return "QEMU 4.2 ARM Virtual Machine (deprecated) (virt-4.2)" case .virt_5_0: return "QEMU 5.0 ARM Virtual Machine (deprecated) (virt-5.0)" case .virt_5_1: return "QEMU 5.1 ARM Virtual Machine (deprecated) (virt-5.1)" case .virt_5_2: return "QEMU 5.2 ARM Virtual Machine (deprecated) (virt-5.2)" case .virt_6_0: return "QEMU 6.0 ARM Virtual Machine (deprecated) (virt-6.0)" case .virt_6_1: return "QEMU 6.1 ARM Virtual Machine (deprecated) (virt-6.1)" case .virt_6_2: return "QEMU 6.2 ARM Virtual Machine (deprecated) (virt-6.2)" case .virt_7_0: return "QEMU 7.0 ARM Virtual Machine (deprecated) (virt-7.0)" case .virt_7_1: return "QEMU 7.1 ARM Virtual Machine (virt-7.1)" case .virt_7_2: return "QEMU 7.2 ARM Virtual Machine (virt-7.2)" case .virt_8_0: return "QEMU 8.0 ARM Virtual Machine (virt-8.0)" case .virt_8_1: return "QEMU 8.1 ARM Virtual Machine (virt-8.1)" case .virt_8_2: return "QEMU 8.2 ARM Virtual Machine (virt-8.2)" case .virt_9_0: return "QEMU 9.0 ARM Virtual Machine (virt-9.0)" case .virt_9_1: return "QEMU 9.1 ARM Virtual Machine (virt-9.1)" case .virt_9_2: return "QEMU 9.2 ARM Virtual Machine (virt-9.2)" case .qcom_dc_scm_v1_bmc: return "Qualcomm DC-SCM V1 BMC (Cortex A7) (qcom-dc-scm-v1-bmc)" case .qcom_firework_bmc: return "Qualcomm DC-SCM V1/Firework BMC (Cortex A7) (qcom-firework-bmc)" case .quanta_gbs_bmc: return "Quanta GBS (Cortex-A9) (quanta-gbs-bmc)" case .quanta_gsj: return "Quanta GSJ (Cortex-A9) (quanta-gsj)" case .quanta_q71l_bmc: return "Quanta-Q71l BMC (ARM926EJ-S) (quanta-q71l-bmc)" case .raspi2b: return "Raspberry Pi 2B (revision 1.1) (raspi2b)" case .raspi1ap: return "Raspberry Pi A+ (revision 1.1) (raspi1ap)" case .raspi0: return "Raspberry Pi Zero (revision 1.2) (raspi0)" case .stm32vldiscovery: return "ST STM32VLDISCOVERY (Cortex-M3) (stm32vldiscovery)" case .nuri: return "Samsung NURI board (Exynos4210) (nuri)" case .smdkc210: return "Samsung SMDKC210 board (Exynos4210) (smdkc210)" case .collie: return "Sharp SL-5500 (Collie) PDA (SA-1110) (collie)" case .sx1_v1: return "Siemens SX1 (OMAP310) V1 (sx1-v1)" case .sx1: return "Siemens SX1 (OMAP310) V2 (sx1)" case .emcraft_sf2: return "SmartFusion2 SOM kit from Emcraft (M2S010) (emcraft-sf2)" case .lm3s6965evb: return "Stellaris LM3S6965EVB (Cortex-M3) (lm3s6965evb)" case .lm3s811evb: return "Stellaris LM3S811EVB (Cortex-M3) (lm3s811evb)" case .supermicrox11_bmc: return "Supermicro X11 BMC (ARM926EJ-S) (supermicrox11-bmc)" case .supermicro_x11spi_bmc: return "Supermicro X11 SPI BMC (ARM1176) (supermicro-x11spi-bmc)" case .xilinx_zynq_a9: return "Xilinx Zynq 7000 Platform Baseboard for Cortex-A9 (xilinx-zynq-a9)" case .cubieboard: return "cubietech cubieboard (Cortex-A8) (cubieboard)" case .none: return "empty machine (none)" } } } enum QEMUTarget_aarch64: String, CaseIterable, QEMUTarget { case integratorcp case kzm case mps2_an385 = "mps2-an385" case mps2_an386 = "mps2-an386" case mps2_an500 = "mps2-an500" case mps2_an505 = "mps2-an505" case mps2_an511 = "mps2-an511" case mps2_an521 = "mps2-an521" case mps3_an524 = "mps3-an524" case mps3_an536 = "mps3-an536" case mps3_an547 = "mps3-an547" case musca_a = "musca-a" case musca_b1 = "musca-b1" case realview_eb_mpcore = "realview-eb-mpcore" case realview_eb = "realview-eb" case realview_pbx_a9 = "realview-pbx-a9" case realview_pb_a8 = "realview-pb-a8" case vexpress_a15 = "vexpress-a15" case vexpress_a9 = "vexpress-a9" case versatileab case versatilepb case imx25_pdk = "imx25-pdk" case vmapple case ast1030_evb = "ast1030-evb" case ast2500_evb = "ast2500-evb" case ast2600_evb = "ast2600-evb" case ast2700_evb = "ast2700-evb" case ast2700a0_evb = "ast2700a0-evb" case ast2700a1_evb = "ast2700a1-evb" case b_l475e_iot01a = "b-l475e-iot01a" case microbit case bpim2u case g220a_bmc = "g220a-bmc" case highbank case midway case canon_a1100 = "canon-a1100" case bletchley_bmc = "bletchley-bmc" case fuji_bmc = "fuji-bmc" case tiogapass_bmc = "tiogapass-bmc" case yosemitev2_bmc = "yosemitev2-bmc" case fby35_bmc = "fby35-bmc" case sabrelite case mcimx6ul_evk = "mcimx6ul-evk" case mcimx7d_sabre = "mcimx7d-sabre" case rainier_bmc = "rainier-bmc" case fp5280g2_bmc = "fp5280g2-bmc" case kudo_bmc = "kudo-bmc" case musicpal case fby35 case mori_bmc = "mori-bmc" case imx8mp_evk = "imx8mp-evk" case netduino2 case netduinoplus2 case npcm750_evb = "npcm750-evb" case npcm845_evb = "npcm845-evb" case sonorapass_bmc = "sonorapass-bmc" case olimex_stm32_h405 = "olimex-stm32-h405" case palmetto_bmc = "palmetto-bmc" case romulus_bmc = "romulus-bmc" case witherspoon_bmc = "witherspoon-bmc" case orangepi_pc = "orangepi-pc" case sbsa_ref = "sbsa-ref" case virt case virt_10_0 = "virt-10.0" case virt_2_10 = "virt-2.10" case virt_2_11 = "virt-2.11" case virt_2_12 = "virt-2.12" case virt_2_6 = "virt-2.6" case virt_2_7 = "virt-2.7" case virt_2_8 = "virt-2.8" case virt_2_9 = "virt-2.9" case virt_3_0 = "virt-3.0" case virt_3_1 = "virt-3.1" case virt_4_0 = "virt-4.0" case virt_4_1 = "virt-4.1" case virt_4_2 = "virt-4.2" case virt_5_0 = "virt-5.0" case virt_5_1 = "virt-5.1" case virt_5_2 = "virt-5.2" case virt_6_0 = "virt-6.0" case virt_6_1 = "virt-6.1" case virt_6_2 = "virt-6.2" case virt_7_0 = "virt-7.0" case virt_7_1 = "virt-7.1" case virt_7_2 = "virt-7.2" case virt_8_0 = "virt-8.0" case virt_8_1 = "virt-8.1" case virt_8_2 = "virt-8.2" case virt_9_0 = "virt-9.0" case virt_9_1 = "virt-9.1" case virt_9_2 = "virt-9.2" case qcom_dc_scm_v1_bmc = "qcom-dc-scm-v1-bmc" case qcom_firework_bmc = "qcom-firework-bmc" case quanta_gbs_bmc = "quanta-gbs-bmc" case quanta_gsj = "quanta-gsj" case quanta_q71l_bmc = "quanta-q71l-bmc" case raspi2b case raspi3ap case raspi3b case raspi4b case raspi1ap case raspi0 case stm32vldiscovery case nuri case smdkc210 case collie case sx1_v1 = "sx1-v1" case sx1 case emcraft_sf2 = "emcraft-sf2" case lm3s6965evb case lm3s811evb case supermicrox11_bmc = "supermicrox11-bmc" case supermicro_x11spi_bmc = "supermicro-x11spi-bmc" case xlnx_versal_virt = "xlnx-versal-virt" case xilinx_zynq_a9 = "xilinx-zynq-a9" case xlnx_zcu102 = "xlnx-zcu102" case cubieboard case none static var `default`: QEMUTarget_aarch64 { .virt } var prettyValue: String { switch self { case .integratorcp: return "ARM Integrator/CP (ARM926EJ-S) (integratorcp)" case .kzm: return "ARM KZM Emulation Baseboard (ARM1136) (kzm)" case .mps2_an385: return "ARM MPS2 with AN385 FPGA image for Cortex-M3 (mps2-an385)" case .mps2_an386: return "ARM MPS2 with AN386 FPGA image for Cortex-M4 (mps2-an386)" case .mps2_an500: return "ARM MPS2 with AN500 FPGA image for Cortex-M7 (mps2-an500)" case .mps2_an505: return "ARM MPS2 with AN505 FPGA image for Cortex-M33 (mps2-an505)" case .mps2_an511: return "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3 (mps2-an511)" case .mps2_an521: return "ARM MPS2 with AN521 FPGA image for dual Cortex-M33 (mps2-an521)" case .mps3_an524: return "ARM MPS3 with AN524 FPGA image for dual Cortex-M33 (mps3-an524)" case .mps3_an536: return "ARM MPS3 with AN536 FPGA image for Cortex-R52 (mps3-an536)" case .mps3_an547: return "ARM MPS3 with AN547 FPGA image for Cortex-M55 (mps3-an547)" case .musca_a: return "ARM Musca-A board (dual Cortex-M33) (musca-a)" case .musca_b1: return "ARM Musca-B1 board (dual Cortex-M33) (musca-b1)" case .realview_eb_mpcore: return "ARM RealView Emulation Baseboard (ARM11MPCore) (realview-eb-mpcore)" case .realview_eb: return "ARM RealView Emulation Baseboard (ARM926EJ-S) (realview-eb)" case .realview_pbx_a9: return "ARM RealView Platform Baseboard Explore for Cortex-A9 (realview-pbx-a9)" case .realview_pb_a8: return "ARM RealView Platform Baseboard for Cortex-A8 (realview-pb-a8)" case .vexpress_a15: return "ARM Versatile Express for Cortex-A15 (vexpress-a15)" case .vexpress_a9: return "ARM Versatile Express for Cortex-A9 (vexpress-a9)" case .versatileab: return "ARM Versatile/AB (ARM926EJ-S) (versatileab)" case .versatilepb: return "ARM Versatile/PB (ARM926EJ-S) (versatilepb)" case .imx25_pdk: return "ARM i.MX25 PDK board (ARM926) (imx25-pdk)" case .vmapple: return "Apple aarch64 Virtual Machine (vmapple)" case .ast1030_evb: return "Aspeed AST1030 MiniBMC (Cortex-M4) (ast1030-evb)" case .ast2500_evb: return "Aspeed AST2500 EVB (ARM1176) (ast2500-evb)" case .ast2600_evb: return "Aspeed AST2600 EVB (Cortex-A7) (ast2600-evb)" case .ast2700_evb: return "Aspeed AST2700 A0 EVB (Cortex-A35) (alias of ast2700a0-evb) (ast2700-evb)" case .ast2700a0_evb: return "Aspeed AST2700 A0 EVB (Cortex-A35) (ast2700a0-evb)" case .ast2700a1_evb: return "Aspeed AST2700 A1 EVB (Cortex-A35) (ast2700a1-evb)" case .b_l475e_iot01a: return "B-L475E-IOT01A Discovery Kit (Cortex-M4) (b-l475e-iot01a)" case .microbit: return "BBC micro:bit (Cortex-M0) (microbit)" case .bpim2u: return "Bananapi M2U (Cortex-A7) (bpim2u)" case .g220a_bmc: return "Bytedance G220A BMC (ARM1176) (g220a-bmc)" case .highbank: return "Calxeda Highbank (ECX-1000) (highbank)" case .midway: return "Calxeda Midway (ECX-2000) (midway)" case .canon_a1100: return "Canon PowerShot A1100 IS (ARM946) (canon-a1100)" case .bletchley_bmc: return "Facebook Bletchley BMC (Cortex-A7) (bletchley-bmc)" case .fuji_bmc: return "Facebook Fuji BMC (Cortex-A7) (fuji-bmc)" case .tiogapass_bmc: return "Facebook Tiogapass BMC (ARM1176) (tiogapass-bmc)" case .yosemitev2_bmc: return "Facebook YosemiteV2 BMC (ARM1176) (yosemitev2-bmc)" case .fby35_bmc: return "Facebook fby35 BMC (Cortex-A7) (fby35-bmc)" case .sabrelite: return "Freescale i.MX6 Quad SABRE Lite Board (Cortex-A9) (sabrelite)" case .mcimx6ul_evk: return "Freescale i.MX6UL Evaluation Kit (Cortex-A7) (mcimx6ul-evk)" case .mcimx7d_sabre: return "Freescale i.MX7 DUAL SABRE (Cortex-A7) (mcimx7d-sabre)" case .rainier_bmc: return "IBM Rainier BMC (Cortex-A7) (rainier-bmc)" case .fp5280g2_bmc: return "Inspur FP5280G2 BMC (ARM1176) (fp5280g2-bmc)" case .kudo_bmc: return "Kudo BMC (Cortex-A9) (kudo-bmc)" case .musicpal: return "Marvell 88w8618 / MusicPal (ARM926EJ-S) (musicpal)" case .fby35: return "Meta Platforms fby35 (fby35)" case .mori_bmc: return "Mori BMC (Cortex-A9) (mori-bmc)" case .imx8mp_evk: return "NXP i.MX 8M Plus EVK Board (imx8mp-evk)" case .netduino2: return "Netduino 2 Machine (Cortex-M3) (netduino2)" case .netduinoplus2: return "Netduino Plus 2 Machine (Cortex-M4) (netduinoplus2)" case .npcm750_evb: return "Nuvoton NPCM750 Evaluation Board (Cortex-A9) (npcm750-evb)" case .npcm845_evb: return "Nuvoton NPCM845 Evaluation Board (Cortex-A35) (npcm845-evb)" case .sonorapass_bmc: return "OCP SonoraPass BMC (ARM1176) (sonorapass-bmc)" case .olimex_stm32_h405: return "Olimex STM32-H405 (Cortex-M4) (olimex-stm32-h405)" case .palmetto_bmc: return "OpenPOWER Palmetto BMC (ARM926EJ-S) (palmetto-bmc)" case .romulus_bmc: return "OpenPOWER Romulus BMC (ARM1176) (romulus-bmc)" case .witherspoon_bmc: return "OpenPOWER Witherspoon BMC (ARM1176) (witherspoon-bmc)" case .orangepi_pc: return "Orange Pi PC (Cortex-A7) (orangepi-pc)" case .sbsa_ref: return "QEMU 'SBSA Reference' ARM Virtual Machine (sbsa-ref)" case .virt: return "QEMU 10.0 ARM Virtual Machine (alias of virt-10.0) (virt)" case .virt_10_0: return "QEMU 10.0 ARM Virtual Machine (virt-10.0)" case .virt_2_10: return "QEMU 2.10 ARM Virtual Machine (deprecated) (virt-2.10)" case .virt_2_11: return "QEMU 2.11 ARM Virtual Machine (deprecated) (virt-2.11)" case .virt_2_12: return "QEMU 2.12 ARM Virtual Machine (deprecated) (virt-2.12)" case .virt_2_6: return "QEMU 2.6 ARM Virtual Machine (deprecated) (virt-2.6)" case .virt_2_7: return "QEMU 2.7 ARM Virtual Machine (deprecated) (virt-2.7)" case .virt_2_8: return "QEMU 2.8 ARM Virtual Machine (deprecated) (virt-2.8)" case .virt_2_9: return "QEMU 2.9 ARM Virtual Machine (deprecated) (virt-2.9)" case .virt_3_0: return "QEMU 3.0 ARM Virtual Machine (deprecated) (virt-3.0)" case .virt_3_1: return "QEMU 3.1 ARM Virtual Machine (deprecated) (virt-3.1)" case .virt_4_0: return "QEMU 4.0 ARM Virtual Machine (deprecated) (virt-4.0)" case .virt_4_1: return "QEMU 4.1 ARM Virtual Machine (deprecated) (virt-4.1)" case .virt_4_2: return "QEMU 4.2 ARM Virtual Machine (deprecated) (virt-4.2)" case .virt_5_0: return "QEMU 5.0 ARM Virtual Machine (deprecated) (virt-5.0)" case .virt_5_1: return "QEMU 5.1 ARM Virtual Machine (deprecated) (virt-5.1)" case .virt_5_2: return "QEMU 5.2 ARM Virtual Machine (deprecated) (virt-5.2)" case .virt_6_0: return "QEMU 6.0 ARM Virtual Machine (deprecated) (virt-6.0)" case .virt_6_1: return "QEMU 6.1 ARM Virtual Machine (deprecated) (virt-6.1)" case .virt_6_2: return "QEMU 6.2 ARM Virtual Machine (deprecated) (virt-6.2)" case .virt_7_0: return "QEMU 7.0 ARM Virtual Machine (deprecated) (virt-7.0)" case .virt_7_1: return "QEMU 7.1 ARM Virtual Machine (virt-7.1)" case .virt_7_2: return "QEMU 7.2 ARM Virtual Machine (virt-7.2)" case .virt_8_0: return "QEMU 8.0 ARM Virtual Machine (virt-8.0)" case .virt_8_1: return "QEMU 8.1 ARM Virtual Machine (virt-8.1)" case .virt_8_2: return "QEMU 8.2 ARM Virtual Machine (virt-8.2)" case .virt_9_0: return "QEMU 9.0 ARM Virtual Machine (virt-9.0)" case .virt_9_1: return "QEMU 9.1 ARM Virtual Machine (virt-9.1)" case .virt_9_2: return "QEMU 9.2 ARM Virtual Machine (virt-9.2)" case .qcom_dc_scm_v1_bmc: return "Qualcomm DC-SCM V1 BMC (Cortex A7) (qcom-dc-scm-v1-bmc)" case .qcom_firework_bmc: return "Qualcomm DC-SCM V1/Firework BMC (Cortex A7) (qcom-firework-bmc)" case .quanta_gbs_bmc: return "Quanta GBS (Cortex-A9) (quanta-gbs-bmc)" case .quanta_gsj: return "Quanta GSJ (Cortex-A9) (quanta-gsj)" case .quanta_q71l_bmc: return "Quanta-Q71l BMC (ARM926EJ-S) (quanta-q71l-bmc)" case .raspi2b: return "Raspberry Pi 2B (revision 1.1) (raspi2b)" case .raspi3ap: return "Raspberry Pi 3A+ (revision 1.0) (raspi3ap)" case .raspi3b: return "Raspberry Pi 3B (revision 1.2) (raspi3b)" case .raspi4b: return "Raspberry Pi 4B (revision 1.5) (raspi4b)" case .raspi1ap: return "Raspberry Pi A+ (revision 1.1) (raspi1ap)" case .raspi0: return "Raspberry Pi Zero (revision 1.2) (raspi0)" case .stm32vldiscovery: return "ST STM32VLDISCOVERY (Cortex-M3) (stm32vldiscovery)" case .nuri: return "Samsung NURI board (Exynos4210) (nuri)" case .smdkc210: return "Samsung SMDKC210 board (Exynos4210) (smdkc210)" case .collie: return "Sharp SL-5500 (Collie) PDA (SA-1110) (collie)" case .sx1_v1: return "Siemens SX1 (OMAP310) V1 (sx1-v1)" case .sx1: return "Siemens SX1 (OMAP310) V2 (sx1)" case .emcraft_sf2: return "SmartFusion2 SOM kit from Emcraft (M2S010) (emcraft-sf2)" case .lm3s6965evb: return "Stellaris LM3S6965EVB (Cortex-M3) (lm3s6965evb)" case .lm3s811evb: return "Stellaris LM3S811EVB (Cortex-M3) (lm3s811evb)" case .supermicrox11_bmc: return "Supermicro X11 BMC (ARM926EJ-S) (supermicrox11-bmc)" case .supermicro_x11spi_bmc: return "Supermicro X11 SPI BMC (ARM1176) (supermicro-x11spi-bmc)" case .xlnx_versal_virt: return "Xilinx Versal Virtual development board (xlnx-versal-virt)" case .xilinx_zynq_a9: return "Xilinx Zynq 7000 Platform Baseboard for Cortex-A9 (xilinx-zynq-a9)" case .xlnx_zcu102: return "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5Fs based on the value of smp (xlnx-zcu102)" case .cubieboard: return "cubietech cubieboard (Cortex-A8) (cubieboard)" case .none: return "empty machine (none)" } } } enum QEMUTarget_avr: String, CaseIterable, QEMUTarget { case _2009 = "2009" case arduino_duemilanove = "arduino-duemilanove" case mega case arduino_mega = "arduino-mega" case mega2560 case arduino_mega_2560_v3 = "arduino-mega-2560-v3" case uno case arduino_uno = "arduino-uno" case none static var `default`: QEMUTarget_avr { .mega } var prettyValue: String { switch self { case ._2009: return "Arduino Duemilanove (ATmega168) (alias of arduino-duemilanove) (2009)" case .arduino_duemilanove: return "Arduino Duemilanove (ATmega168) (arduino-duemilanove)" case .mega: return "Arduino Mega (ATmega1280) (alias of arduino-mega) (mega)" case .arduino_mega: return "Arduino Mega (ATmega1280) (arduino-mega)" case .mega2560: return "Arduino Mega 2560 (ATmega2560) (alias of arduino-mega-2560-v3) (mega2560)" case .arduino_mega_2560_v3: return "Arduino Mega 2560 (ATmega2560) (arduino-mega-2560-v3)" case .uno: return "Arduino UNO (ATmega328P) (alias of arduino-uno) (uno)" case .arduino_uno: return "Arduino UNO (ATmega328P) (arduino-uno)" case .none: return "empty machine (none)" } } } enum QEMUTarget_hppa: String, CaseIterable, QEMUTarget { case B160L case C3700 case none static var `default`: QEMUTarget_hppa { .B160L } var prettyValue: String { switch self { case .B160L: return "HP B160L workstation (default) (B160L)" case .C3700: return "HP C3700 workstation (C3700)" case .none: return "empty machine (none)" } } } enum QEMUTarget_i386: String, CaseIterable, QEMUTarget { case isapc case q35 case pc_q35_2_10 = "pc-q35-2.10" case pc_q35_2_11 = "pc-q35-2.11" case pc_q35_2_12 = "pc-q35-2.12" case pc_q35_2_4 = "pc-q35-2.4" case pc_q35_2_5 = "pc-q35-2.5" case pc_q35_2_6 = "pc-q35-2.6" case pc_q35_2_7 = "pc-q35-2.7" case pc_q35_2_8 = "pc-q35-2.8" case pc_q35_2_9 = "pc-q35-2.9" case pc_q35_3_0 = "pc-q35-3.0" case pc_q35_3_1 = "pc-q35-3.1" case pc_q35_4_0 = "pc-q35-4.0" case pc_q35_4_0_1 = "pc-q35-4.0.1" case pc_q35_4_1 = "pc-q35-4.1" case pc_q35_4_2 = "pc-q35-4.2" case pc_q35_5_0 = "pc-q35-5.0" case pc_q35_5_1 = "pc-q35-5.1" case pc_q35_5_2 = "pc-q35-5.2" case pc_q35_6_0 = "pc-q35-6.0" case pc_q35_6_1 = "pc-q35-6.1" case pc_q35_6_2 = "pc-q35-6.2" case pc_q35_7_0 = "pc-q35-7.0" case pc_q35_10_0 = "pc-q35-10.0" case pc_q35_7_1 = "pc-q35-7.1" case pc_q35_7_2 = "pc-q35-7.2" case pc_q35_8_0 = "pc-q35-8.0" case pc_q35_8_1 = "pc-q35-8.1" case pc_q35_8_2 = "pc-q35-8.2" case pc_q35_9_0 = "pc-q35-9.0" case pc_q35_9_1 = "pc-q35-9.1" case pc_q35_9_2 = "pc-q35-9.2" case pc case pc_i440fx_10_0 = "pc-i440fx-10.0" case pc_i440fx_2_10 = "pc-i440fx-2.10" case pc_i440fx_2_11 = "pc-i440fx-2.11" case pc_i440fx_2_12 = "pc-i440fx-2.12" case pc_i440fx_2_4 = "pc-i440fx-2.4" case pc_i440fx_2_5 = "pc-i440fx-2.5" case pc_i440fx_2_6 = "pc-i440fx-2.6" case pc_i440fx_2_7 = "pc-i440fx-2.7" case pc_i440fx_2_8 = "pc-i440fx-2.8" case pc_i440fx_2_9 = "pc-i440fx-2.9" case pc_i440fx_3_0 = "pc-i440fx-3.0" case pc_i440fx_3_1 = "pc-i440fx-3.1" case pc_i440fx_4_0 = "pc-i440fx-4.0" case pc_i440fx_4_1 = "pc-i440fx-4.1" case pc_i440fx_4_2 = "pc-i440fx-4.2" case pc_i440fx_5_0 = "pc-i440fx-5.0" case pc_i440fx_5_1 = "pc-i440fx-5.1" case pc_i440fx_5_2 = "pc-i440fx-5.2" case pc_i440fx_6_0 = "pc-i440fx-6.0" case pc_i440fx_6_1 = "pc-i440fx-6.1" case pc_i440fx_6_2 = "pc-i440fx-6.2" case pc_i440fx_7_0 = "pc-i440fx-7.0" case pc_i440fx_7_1 = "pc-i440fx-7.1" case pc_i440fx_7_2 = "pc-i440fx-7.2" case pc_i440fx_8_0 = "pc-i440fx-8.0" case pc_i440fx_8_1 = "pc-i440fx-8.1" case pc_i440fx_8_2 = "pc-i440fx-8.2" case pc_i440fx_9_0 = "pc-i440fx-9.0" case pc_i440fx_9_1 = "pc-i440fx-9.1" case pc_i440fx_9_2 = "pc-i440fx-9.2" case none case microvm static var `default`: QEMUTarget_i386 { .q35 } var prettyValue: String { switch self { case .isapc: return "ISA-only PC (isapc)" case .q35: return "Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-10.0) (q35)" case .pc_q35_2_10: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.10)" case .pc_q35_2_11: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.11)" case .pc_q35_2_12: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.12)" case .pc_q35_2_4: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.4)" case .pc_q35_2_5: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.5)" case .pc_q35_2_6: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.6)" case .pc_q35_2_7: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.7)" case .pc_q35_2_8: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.8)" case .pc_q35_2_9: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.9)" case .pc_q35_3_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-3.0)" case .pc_q35_3_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-3.1)" case .pc_q35_4_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.0)" case .pc_q35_4_0_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.0.1)" case .pc_q35_4_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.1)" case .pc_q35_4_2: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.2)" case .pc_q35_5_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-5.0)" case .pc_q35_5_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-5.1)" case .pc_q35_5_2: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-5.2)" case .pc_q35_6_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-6.0)" case .pc_q35_6_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-6.1)" case .pc_q35_6_2: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-6.2)" case .pc_q35_7_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-7.0)" case .pc_q35_10_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-10.0)" case .pc_q35_7_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.1)" case .pc_q35_7_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.2)" case .pc_q35_8_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-8.0)" case .pc_q35_8_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-8.1)" case .pc_q35_8_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-8.2)" case .pc_q35_9_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-9.0)" case .pc_q35_9_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-9.1)" case .pc_q35_9_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-9.2)" case .pc: return "Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-10.0) (pc)" case .pc_i440fx_10_0: return "Standard PC (i440FX + PIIX, 1996) (default) (pc-i440fx-10.0)" case .pc_i440fx_2_10: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.10)" case .pc_i440fx_2_11: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.11)" case .pc_i440fx_2_12: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.12)" case .pc_i440fx_2_4: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.4)" case .pc_i440fx_2_5: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.5)" case .pc_i440fx_2_6: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.6)" case .pc_i440fx_2_7: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.7)" case .pc_i440fx_2_8: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.8)" case .pc_i440fx_2_9: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.9)" case .pc_i440fx_3_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-3.0)" case .pc_i440fx_3_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-3.1)" case .pc_i440fx_4_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-4.0)" case .pc_i440fx_4_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-4.1)" case .pc_i440fx_4_2: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-4.2)" case .pc_i440fx_5_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-5.0)" case .pc_i440fx_5_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-5.1)" case .pc_i440fx_5_2: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-5.2)" case .pc_i440fx_6_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-6.0)" case .pc_i440fx_6_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-6.1)" case .pc_i440fx_6_2: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-6.2)" case .pc_i440fx_7_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-7.0)" case .pc_i440fx_7_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.1)" case .pc_i440fx_7_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.2)" case .pc_i440fx_8_0: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-8.0)" case .pc_i440fx_8_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-8.1)" case .pc_i440fx_8_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-8.2)" case .pc_i440fx_9_0: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-9.0)" case .pc_i440fx_9_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-9.1)" case .pc_i440fx_9_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-9.2)" case .none: return "empty machine (none)" case .microvm: return "microvm (i386) (microvm)" } } } enum QEMUTarget_loongarch64: String, CaseIterable, QEMUTarget { case virt case none static var `default`: QEMUTarget_loongarch64 { .virt } var prettyValue: String { switch self { case .virt: return "QEMU LoongArch Virtual Machine (default) (virt)" case .none: return "empty machine (none)" } } } enum QEMUTarget_m68k: String, CaseIterable, QEMUTarget { case an5206 case mcf5208evb case q800 case next_cube = "next-cube" case virt case virt_10_0 = "virt-10.0" case virt_6_0 = "virt-6.0" case virt_6_1 = "virt-6.1" case virt_6_2 = "virt-6.2" case virt_7_0 = "virt-7.0" case virt_7_1 = "virt-7.1" case virt_7_2 = "virt-7.2" case virt_8_0 = "virt-8.0" case virt_8_1 = "virt-8.1" case virt_8_2 = "virt-8.2" case virt_9_0 = "virt-9.0" case virt_9_1 = "virt-9.1" case virt_9_2 = "virt-9.2" case none static var `default`: QEMUTarget_m68k { .mcf5208evb } var prettyValue: String { switch self { case .an5206: return "Arnewsh 5206 (an5206)" case .mcf5208evb: return "MCF5208EVB (default) (mcf5208evb)" case .q800: return "Macintosh Quadra 800 (q800)" case .next_cube: return "NeXT Cube (next-cube)" case .virt: return "QEMU 10.0 M68K Virtual Machine (alias of virt-10.0) (virt)" case .virt_10_0: return "QEMU 10.0 M68K Virtual Machine (virt-10.0)" case .virt_6_0: return "QEMU 6.0 M68K Virtual Machine (deprecated) (virt-6.0)" case .virt_6_1: return "QEMU 6.1 M68K Virtual Machine (deprecated) (virt-6.1)" case .virt_6_2: return "QEMU 6.2 M68K Virtual Machine (deprecated) (virt-6.2)" case .virt_7_0: return "QEMU 7.0 M68K Virtual Machine (deprecated) (virt-7.0)" case .virt_7_1: return "QEMU 7.1 M68K Virtual Machine (virt-7.1)" case .virt_7_2: return "QEMU 7.2 M68K Virtual Machine (virt-7.2)" case .virt_8_0: return "QEMU 8.0 M68K Virtual Machine (virt-8.0)" case .virt_8_1: return "QEMU 8.1 M68K Virtual Machine (virt-8.1)" case .virt_8_2: return "QEMU 8.2 M68K Virtual Machine (virt-8.2)" case .virt_9_0: return "QEMU 9.0 M68K Virtual Machine (virt-9.0)" case .virt_9_1: return "QEMU 9.1 M68K Virtual Machine (virt-9.1)" case .virt_9_2: return "QEMU 9.2 M68K Virtual Machine (virt-9.2)" case .none: return "empty machine (none)" } } } enum QEMUTarget_microblaze: String, CaseIterable, QEMUTarget { case petalogix_s3adsp1800 = "petalogix-s3adsp1800" case petalogix_ml605 = "petalogix-ml605" case xlnx_zynqmp_pmu = "xlnx-zynqmp-pmu" case none static var `default`: QEMUTarget_microblaze { .petalogix_s3adsp1800 } var prettyValue: String { switch self { case .petalogix_s3adsp1800: return "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800 (default) (petalogix-s3adsp1800)" case .petalogix_ml605: return "PetaLogix linux refdesign for xilinx ml605 (big endian) (deprecated) (petalogix-ml605)" case .xlnx_zynqmp_pmu: return "Xilinx ZynqMP PMU machine (big endian) (deprecated) (xlnx-zynqmp-pmu)" case .none: return "empty machine (none)" } } } enum QEMUTarget_microblazeel: String, CaseIterable, QEMUTarget { case petalogix_s3adsp1800 = "petalogix-s3adsp1800" case petalogix_ml605 = "petalogix-ml605" case xlnx_zynqmp_pmu = "xlnx-zynqmp-pmu" case none static var `default`: QEMUTarget_microblazeel { .petalogix_s3adsp1800 } var prettyValue: String { switch self { case .petalogix_s3adsp1800: return "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800 (default) (petalogix-s3adsp1800)" case .petalogix_ml605: return "PetaLogix linux refdesign for xilinx ml605 (little endian) (petalogix-ml605)" case .xlnx_zynqmp_pmu: return "Xilinx ZynqMP PMU machine (little endian) (xlnx-zynqmp-pmu)" case .none: return "empty machine (none)" } } } enum QEMUTarget_mips: String, CaseIterable, QEMUTarget { case mipssim case malta case none static var `default`: QEMUTarget_mips { .malta } var prettyValue: String { switch self { case .mipssim: return "MIPS MIPSsim platform (mipssim)" case .malta: return "MIPS Malta Core LV (default) (malta)" case .none: return "empty machine (none)" } } } enum QEMUTarget_mipsel: String, CaseIterable, QEMUTarget { case mipssim case malta case none static var `default`: QEMUTarget_mipsel { .malta } var prettyValue: String { switch self { case .mipssim: return "MIPS MIPSsim platform (mipssim)" case .malta: return "MIPS Malta Core LV (default) (malta)" case .none: return "empty machine (none)" } } } enum QEMUTarget_mips64: String, CaseIterable, QEMUTarget { case pica61 case mipssim case magnum case malta case none static var `default`: QEMUTarget_mips64 { .malta } var prettyValue: String { switch self { case .pica61: return "Acer Pica 61 (pica61)" case .mipssim: return "MIPS MIPSsim platform (mipssim)" case .magnum: return "MIPS Magnum (magnum)" case .malta: return "MIPS Malta Core LV (default) (malta)" case .none: return "empty machine (none)" } } } enum QEMUTarget_mips64el: String, CaseIterable, QEMUTarget { case pica61 case fuloong2e case loongson3_virt = "loongson3-virt" case boston case mipssim case magnum case malta case none static var `default`: QEMUTarget_mips64el { .malta } var prettyValue: String { switch self { case .pica61: return "Acer Pica 61 (pica61)" case .fuloong2e: return "Fuloong 2e mini pc (fuloong2e)" case .loongson3_virt: return "Loongson-3 Virtualization Platform (loongson3-virt)" case .boston: return "MIPS Boston (boston)" case .mipssim: return "MIPS MIPSsim platform (mipssim)" case .magnum: return "MIPS Magnum (magnum)" case .malta: return "MIPS Malta Core LV (default) (malta)" case .none: return "empty machine (none)" } } } enum QEMUTarget_or1k: String, CaseIterable, QEMUTarget { case none case or1k_sim = "or1k-sim" case virt static var `default`: QEMUTarget_or1k { .or1k_sim } var prettyValue: String { switch self { case .none: return "empty machine (none)" case .or1k_sim: return "or1k simulation (default) (or1k-sim)" case .virt: return "or1k virtual machine (virt)" } } } enum QEMUTarget_ppc: String, CaseIterable, QEMUTarget { case amigaone case pegasos2 case g3beige case _40p = "40p" case mac99 case virtex_ml507 = "virtex-ml507" case sam460ex case bamboo case none case ppce500 case mpc8544ds static var `default`: QEMUTarget_ppc { .g3beige } var prettyValue: String { switch self { case .amigaone: return "Eyetech AmigaOne/Mai Logic Teron (amigaone)" case .pegasos2: return "Genesi/bPlan Pegasos II (pegasos2)" case .g3beige: return "Heathrow based PowerMac (default) (g3beige)" case ._40p: return "IBM RS/6000 7020 (40p) (40p)" case .mac99: return "Mac99 based PowerMac (mac99)" case .virtex_ml507: return "Xilinx Virtex ML507 reference design (virtex-ml507)" case .sam460ex: return "aCube Sam460ex (sam460ex)" case .bamboo: return "bamboo (bamboo)" case .none: return "empty machine (none)" case .ppce500: return "generic paravirt e500 platform (ppce500)" case .mpc8544ds: return "mpc8544ds (mpc8544ds)" } } } enum QEMUTarget_ppc64: String, CaseIterable, QEMUTarget { case amigaone case pegasos2 case g3beige case powernv case powernv10 case powernv10_rainier = "powernv10-rainier" case powernv8 case powernv9 case _40p = "40p" case mac99 case virtex_ml507 = "virtex-ml507" case sam460ex case bamboo case none case ppce500 case mpc8544ds case pseries case pseries_10_0 = "pseries-10.0" case pseries_3_0 = "pseries-3.0" case pseries_3_1 = "pseries-3.1" case pseries_4_0 = "pseries-4.0" case pseries_4_1 = "pseries-4.1" case pseries_4_2 = "pseries-4.2" case pseries_5_0 = "pseries-5.0" case pseries_5_1 = "pseries-5.1" case pseries_5_2 = "pseries-5.2" case pseries_6_0 = "pseries-6.0" case pseries_6_1 = "pseries-6.1" case pseries_6_2 = "pseries-6.2" case pseries_7_0 = "pseries-7.0" case pseries_7_1 = "pseries-7.1" case pseries_7_2 = "pseries-7.2" case pseries_8_0 = "pseries-8.0" case pseries_8_1 = "pseries-8.1" case pseries_8_2 = "pseries-8.2" case pseries_9_0 = "pseries-9.0" case pseries_9_1 = "pseries-9.1" case pseries_9_2 = "pseries-9.2" static var `default`: QEMUTarget_ppc64 { .pseries_10_0 } var prettyValue: String { switch self { case .amigaone: return "Eyetech AmigaOne/Mai Logic Teron (amigaone)" case .pegasos2: return "Genesi/bPlan Pegasos II (pegasos2)" case .g3beige: return "Heathrow based PowerMac (g3beige)" case .powernv: return "IBM PowerNV (Non-Virtualized) POWER10 (alias of powernv10) (powernv)" case .powernv10: return "IBM PowerNV (Non-Virtualized) POWER10 (powernv10)" case .powernv10_rainier: return "IBM PowerNV (Non-Virtualized) POWER10 Rainier (powernv10-rainier)" case .powernv8: return "IBM PowerNV (Non-Virtualized) POWER8 (powernv8)" case .powernv9: return "IBM PowerNV (Non-Virtualized) POWER9 (powernv9)" case ._40p: return "IBM RS/6000 7020 (40p) (40p)" case .mac99: return "Mac99 based PowerMac (mac99)" case .virtex_ml507: return "Xilinx Virtex ML507 reference design (virtex-ml507)" case .sam460ex: return "aCube Sam460ex (sam460ex)" case .bamboo: return "bamboo (bamboo)" case .none: return "empty machine (none)" case .ppce500: return "generic paravirt e500 platform (ppce500)" case .mpc8544ds: return "mpc8544ds (mpc8544ds)" case .pseries: return "pSeries Logical Partition (PAPR compliant) (alias of pseries-10.0) (pseries)" case .pseries_10_0: return "pSeries Logical Partition (PAPR compliant) (default) (pseries-10.0)" case .pseries_3_0: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-3.0)" case .pseries_3_1: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-3.1)" case .pseries_4_0: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-4.0)" case .pseries_4_1: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-4.1)" case .pseries_4_2: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-4.2)" case .pseries_5_0: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-5.0)" case .pseries_5_1: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-5.1)" case .pseries_5_2: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-5.2)" case .pseries_6_0: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-6.0)" case .pseries_6_1: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-6.1)" case .pseries_6_2: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-6.2)" case .pseries_7_0: return "pSeries Logical Partition (PAPR compliant) (deprecated) (pseries-7.0)" case .pseries_7_1: return "pSeries Logical Partition (PAPR compliant) (pseries-7.1)" case .pseries_7_2: return "pSeries Logical Partition (PAPR compliant) (pseries-7.2)" case .pseries_8_0: return "pSeries Logical Partition (PAPR compliant) (pseries-8.0)" case .pseries_8_1: return "pSeries Logical Partition (PAPR compliant) (pseries-8.1)" case .pseries_8_2: return "pSeries Logical Partition (PAPR compliant) (pseries-8.2)" case .pseries_9_0: return "pSeries Logical Partition (PAPR compliant) (pseries-9.0)" case .pseries_9_1: return "pSeries Logical Partition (PAPR compliant) (pseries-9.1)" case .pseries_9_2: return "pSeries Logical Partition (PAPR compliant) (pseries-9.2)" } } } enum QEMUTarget_riscv32: String, CaseIterable, QEMUTarget { case amd_microblaze_v_generic = "amd-microblaze-v-generic" case opentitan case sifive_e case sifive_u case spike case virt case none static var `default`: QEMUTarget_riscv32 { .spike } var prettyValue: String { switch self { case .amd_microblaze_v_generic: return "AMD Microblaze-V generic platform (amd-microblaze-v-generic)" case .opentitan: return "RISC-V Board compatible with OpenTitan (opentitan)" case .sifive_e: return "RISC-V Board compatible with SiFive E SDK (sifive_e)" case .sifive_u: return "RISC-V Board compatible with SiFive U SDK (sifive_u)" case .spike: return "RISC-V Spike board (default) (spike)" case .virt: return "RISC-V VirtIO board (virt)" case .none: return "empty machine (none)" } } } enum QEMUTarget_riscv64: String, CaseIterable, QEMUTarget { case amd_microblaze_v_generic = "amd-microblaze-v-generic" case microchip_icicle_kit = "microchip-icicle-kit" case shakti_c case sifive_e case sifive_u case spike case virt case none static var `default`: QEMUTarget_riscv64 { .virt } var prettyValue: String { switch self { case .amd_microblaze_v_generic: return "AMD Microblaze-V generic platform (amd-microblaze-v-generic)" case .microchip_icicle_kit: return "Microchip PolarFire SoC Icicle Kit (microchip-icicle-kit)" case .shakti_c: return "RISC-V Board compatible with Shakti SDK (shakti_c)" case .sifive_e: return "RISC-V Board compatible with SiFive E SDK (sifive_e)" case .sifive_u: return "RISC-V Board compatible with SiFive U SDK (sifive_u)" case .spike: return "RISC-V Spike board (default) (spike)" case .virt: return "RISC-V VirtIO board (virt)" case .none: return "empty machine (none)" } } } enum QEMUTarget_rx: String, CaseIterable, QEMUTarget { case none case gdbsim_r5f562n7 = "gdbsim-r5f562n7" case gdbsim_r5f562n8 = "gdbsim-r5f562n8" static var `default`: QEMUTarget_rx { .gdbsim_r5f562n7 } var prettyValue: String { switch self { case .none: return "empty machine (none)" case .gdbsim_r5f562n7: return "gdb simulator (R5F562N7 MCU and external RAM) (gdbsim-r5f562n7)" case .gdbsim_r5f562n8: return "gdb simulator (R5F562N8 MCU and external RAM) (gdbsim-r5f562n8)" } } } enum QEMUTarget_s390x: String, CaseIterable, QEMUTarget { case s390_ccw_virtio = "s390-ccw-virtio" case s390_ccw_virtio_10_0 = "s390-ccw-virtio-10.0" case s390_ccw_virtio_2_10 = "s390-ccw-virtio-2.10" case s390_ccw_virtio_2_11 = "s390-ccw-virtio-2.11" case s390_ccw_virtio_2_12 = "s390-ccw-virtio-2.12" case s390_ccw_virtio_2_9 = "s390-ccw-virtio-2.9" case s390_ccw_virtio_3_0 = "s390-ccw-virtio-3.0" case s390_ccw_virtio_3_1 = "s390-ccw-virtio-3.1" case s390_ccw_virtio_4_0 = "s390-ccw-virtio-4.0" case s390_ccw_virtio_4_1 = "s390-ccw-virtio-4.1" case s390_ccw_virtio_4_2 = "s390-ccw-virtio-4.2" case s390_ccw_virtio_5_0 = "s390-ccw-virtio-5.0" case s390_ccw_virtio_5_1 = "s390-ccw-virtio-5.1" case s390_ccw_virtio_5_2 = "s390-ccw-virtio-5.2" case s390_ccw_virtio_6_0 = "s390-ccw-virtio-6.0" case s390_ccw_virtio_6_1 = "s390-ccw-virtio-6.1" case s390_ccw_virtio_6_2 = "s390-ccw-virtio-6.2" case s390_ccw_virtio_7_0 = "s390-ccw-virtio-7.0" case s390_ccw_virtio_7_1 = "s390-ccw-virtio-7.1" case s390_ccw_virtio_7_2 = "s390-ccw-virtio-7.2" case s390_ccw_virtio_8_0 = "s390-ccw-virtio-8.0" case s390_ccw_virtio_8_1 = "s390-ccw-virtio-8.1" case s390_ccw_virtio_8_2 = "s390-ccw-virtio-8.2" case s390_ccw_virtio_9_0 = "s390-ccw-virtio-9.0" case s390_ccw_virtio_9_1 = "s390-ccw-virtio-9.1" case s390_ccw_virtio_9_2 = "s390-ccw-virtio-9.2" case none static var `default`: QEMUTarget_s390x { .s390_ccw_virtio_10_0 } var prettyValue: String { switch self { case .s390_ccw_virtio: return "Virtual s390x machine (version 10.0) (alias of s390-ccw-virtio-10.0) (s390-ccw-virtio)" case .s390_ccw_virtio_10_0: return "Virtual s390x machine (version 10.0) (default) (s390-ccw-virtio-10.0)" case .s390_ccw_virtio_2_10: return "Virtual s390x machine (version 2.10) (deprecated) (s390-ccw-virtio-2.10)" case .s390_ccw_virtio_2_11: return "Virtual s390x machine (version 2.11) (deprecated) (s390-ccw-virtio-2.11)" case .s390_ccw_virtio_2_12: return "Virtual s390x machine (version 2.12) (deprecated) (s390-ccw-virtio-2.12)" case .s390_ccw_virtio_2_9: return "Virtual s390x machine (version 2.9) (deprecated) (s390-ccw-virtio-2.9)" case .s390_ccw_virtio_3_0: return "Virtual s390x machine (version 3.0) (deprecated) (s390-ccw-virtio-3.0)" case .s390_ccw_virtio_3_1: return "Virtual s390x machine (version 3.1) (deprecated) (s390-ccw-virtio-3.1)" case .s390_ccw_virtio_4_0: return "Virtual s390x machine (version 4.0) (deprecated) (s390-ccw-virtio-4.0)" case .s390_ccw_virtio_4_1: return "Virtual s390x machine (version 4.1) (deprecated) (s390-ccw-virtio-4.1)" case .s390_ccw_virtio_4_2: return "Virtual s390x machine (version 4.2) (deprecated) (s390-ccw-virtio-4.2)" case .s390_ccw_virtio_5_0: return "Virtual s390x machine (version 5.0) (deprecated) (s390-ccw-virtio-5.0)" case .s390_ccw_virtio_5_1: return "Virtual s390x machine (version 5.1) (deprecated) (s390-ccw-virtio-5.1)" case .s390_ccw_virtio_5_2: return "Virtual s390x machine (version 5.2) (deprecated) (s390-ccw-virtio-5.2)" case .s390_ccw_virtio_6_0: return "Virtual s390x machine (version 6.0) (deprecated) (s390-ccw-virtio-6.0)" case .s390_ccw_virtio_6_1: return "Virtual s390x machine (version 6.1) (deprecated) (s390-ccw-virtio-6.1)" case .s390_ccw_virtio_6_2: return "Virtual s390x machine (version 6.2) (deprecated) (s390-ccw-virtio-6.2)" case .s390_ccw_virtio_7_0: return "Virtual s390x machine (version 7.0) (deprecated) (s390-ccw-virtio-7.0)" case .s390_ccw_virtio_7_1: return "Virtual s390x machine (version 7.1) (s390-ccw-virtio-7.1)" case .s390_ccw_virtio_7_2: return "Virtual s390x machine (version 7.2) (s390-ccw-virtio-7.2)" case .s390_ccw_virtio_8_0: return "Virtual s390x machine (version 8.0) (s390-ccw-virtio-8.0)" case .s390_ccw_virtio_8_1: return "Virtual s390x machine (version 8.1) (s390-ccw-virtio-8.1)" case .s390_ccw_virtio_8_2: return "Virtual s390x machine (version 8.2) (s390-ccw-virtio-8.2)" case .s390_ccw_virtio_9_0: return "Virtual s390x machine (version 9.0) (s390-ccw-virtio-9.0)" case .s390_ccw_virtio_9_1: return "Virtual s390x machine (version 9.1) (s390-ccw-virtio-9.1)" case .s390_ccw_virtio_9_2: return "Virtual s390x machine (version 9.2) (s390-ccw-virtio-9.2)" case .none: return "empty machine (none)" } } } enum QEMUTarget_sh4: String, CaseIterable, QEMUTarget { case none case r2d static var `default`: QEMUTarget_sh4 { .none } var prettyValue: String { switch self { case .none: return "empty machine (none)" case .r2d: return "r2d-plus board (r2d)" } } } enum QEMUTarget_sh4eb: String, CaseIterable, QEMUTarget { case none case r2d static var `default`: QEMUTarget_sh4eb { .none } var prettyValue: String { switch self { case .none: return "empty machine (none)" case .r2d: return "r2d-plus board (r2d)" } } } enum QEMUTarget_sparc: String, CaseIterable, QEMUTarget { case leon3_generic case SPARCClassic case SPARCbook case SS_600MP = "SS-600MP" case SS_10 = "SS-10" case SS_20 = "SS-20" case SS_4 = "SS-4" case SS_5 = "SS-5" case LX case Voyager case none static var `default`: QEMUTarget_sparc { .SS_5 } var prettyValue: String { switch self { case .leon3_generic: return "Leon-3 generic (leon3_generic)" case .SPARCClassic: return "Sun4m platform, SPARCClassic (SPARCClassic)" case .SPARCbook: return "Sun4m platform, SPARCbook (SPARCbook)" case .SS_600MP: return "Sun4m platform, SPARCserver 600MP (SS-600MP)" case .SS_10: return "Sun4m platform, SPARCstation 10 (SS-10)" case .SS_20: return "Sun4m platform, SPARCstation 20 (SS-20)" case .SS_4: return "Sun4m platform, SPARCstation 4 (SS-4)" case .SS_5: return "Sun4m platform, SPARCstation 5 (default) (SS-5)" case .LX: return "Sun4m platform, SPARCstation LX (LX)" case .Voyager: return "Sun4m platform, SPARCstation Voyager (Voyager)" case .none: return "empty machine (none)" } } } enum QEMUTarget_sparc64: String, CaseIterable, QEMUTarget { case sun4u case sun4v case niagara case none static var `default`: QEMUTarget_sparc64 { .sun4u } var prettyValue: String { switch self { case .sun4u: return "Sun4u platform (default) (sun4u)" case .sun4v: return "Sun4v platform (sun4v)" case .niagara: return "Sun4v platform, Niagara (niagara)" case .none: return "empty machine (none)" } } } enum QEMUTarget_tricore: String, CaseIterable, QEMUTarget { case KIT_AURIX_TC277_TRB case tricore_testboard case none static var `default`: QEMUTarget_tricore { .tricore_testboard } var prettyValue: String { switch self { case .KIT_AURIX_TC277_TRB: return "Infineon AURIX TriBoard TC277 (D-Step) (KIT_AURIX_TC277_TRB)" case .tricore_testboard: return "a minimal TriCore board (tricore_testboard)" case .none: return "empty machine (none)" } } } enum QEMUTarget_x86_64: String, CaseIterable, QEMUTarget { case isapc case q35 case pc_q35_2_10 = "pc-q35-2.10" case pc_q35_2_11 = "pc-q35-2.11" case pc_q35_2_12 = "pc-q35-2.12" case pc_q35_2_4 = "pc-q35-2.4" case pc_q35_2_5 = "pc-q35-2.5" case pc_q35_2_6 = "pc-q35-2.6" case pc_q35_2_7 = "pc-q35-2.7" case pc_q35_2_8 = "pc-q35-2.8" case pc_q35_2_9 = "pc-q35-2.9" case pc_q35_3_0 = "pc-q35-3.0" case pc_q35_3_1 = "pc-q35-3.1" case pc_q35_4_0 = "pc-q35-4.0" case pc_q35_4_0_1 = "pc-q35-4.0.1" case pc_q35_4_1 = "pc-q35-4.1" case pc_q35_4_2 = "pc-q35-4.2" case pc_q35_5_0 = "pc-q35-5.0" case pc_q35_5_1 = "pc-q35-5.1" case pc_q35_5_2 = "pc-q35-5.2" case pc_q35_6_0 = "pc-q35-6.0" case pc_q35_6_1 = "pc-q35-6.1" case pc_q35_6_2 = "pc-q35-6.2" case pc_q35_7_0 = "pc-q35-7.0" case pc_q35_10_0 = "pc-q35-10.0" case pc_q35_7_1 = "pc-q35-7.1" case pc_q35_7_2 = "pc-q35-7.2" case pc_q35_8_0 = "pc-q35-8.0" case pc_q35_8_1 = "pc-q35-8.1" case pc_q35_8_2 = "pc-q35-8.2" case pc_q35_9_0 = "pc-q35-9.0" case pc_q35_9_1 = "pc-q35-9.1" case pc_q35_9_2 = "pc-q35-9.2" case pc case pc_i440fx_10_0 = "pc-i440fx-10.0" case pc_i440fx_2_10 = "pc-i440fx-2.10" case pc_i440fx_2_11 = "pc-i440fx-2.11" case pc_i440fx_2_12 = "pc-i440fx-2.12" case pc_i440fx_2_4 = "pc-i440fx-2.4" case pc_i440fx_2_5 = "pc-i440fx-2.5" case pc_i440fx_2_6 = "pc-i440fx-2.6" case pc_i440fx_2_7 = "pc-i440fx-2.7" case pc_i440fx_2_8 = "pc-i440fx-2.8" case pc_i440fx_2_9 = "pc-i440fx-2.9" case pc_i440fx_3_0 = "pc-i440fx-3.0" case pc_i440fx_3_1 = "pc-i440fx-3.1" case pc_i440fx_4_0 = "pc-i440fx-4.0" case pc_i440fx_4_1 = "pc-i440fx-4.1" case pc_i440fx_4_2 = "pc-i440fx-4.2" case pc_i440fx_5_0 = "pc-i440fx-5.0" case pc_i440fx_5_1 = "pc-i440fx-5.1" case pc_i440fx_5_2 = "pc-i440fx-5.2" case pc_i440fx_6_0 = "pc-i440fx-6.0" case pc_i440fx_6_1 = "pc-i440fx-6.1" case pc_i440fx_6_2 = "pc-i440fx-6.2" case pc_i440fx_7_0 = "pc-i440fx-7.0" case pc_i440fx_7_1 = "pc-i440fx-7.1" case pc_i440fx_7_2 = "pc-i440fx-7.2" case pc_i440fx_8_0 = "pc-i440fx-8.0" case pc_i440fx_8_1 = "pc-i440fx-8.1" case pc_i440fx_8_2 = "pc-i440fx-8.2" case pc_i440fx_9_0 = "pc-i440fx-9.0" case pc_i440fx_9_1 = "pc-i440fx-9.1" case pc_i440fx_9_2 = "pc-i440fx-9.2" case none case microvm static var `default`: QEMUTarget_x86_64 { .q35 } var prettyValue: String { switch self { case .isapc: return "ISA-only PC (isapc)" case .q35: return "Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-10.0) (q35)" case .pc_q35_2_10: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.10)" case .pc_q35_2_11: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.11)" case .pc_q35_2_12: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.12)" case .pc_q35_2_4: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.4)" case .pc_q35_2_5: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.5)" case .pc_q35_2_6: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.6)" case .pc_q35_2_7: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.7)" case .pc_q35_2_8: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.8)" case .pc_q35_2_9: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-2.9)" case .pc_q35_3_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-3.0)" case .pc_q35_3_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-3.1)" case .pc_q35_4_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.0)" case .pc_q35_4_0_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.0.1)" case .pc_q35_4_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.1)" case .pc_q35_4_2: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-4.2)" case .pc_q35_5_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-5.0)" case .pc_q35_5_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-5.1)" case .pc_q35_5_2: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-5.2)" case .pc_q35_6_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-6.0)" case .pc_q35_6_1: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-6.1)" case .pc_q35_6_2: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-6.2)" case .pc_q35_7_0: return "Standard PC (Q35 + ICH9, 2009) (deprecated) (pc-q35-7.0)" case .pc_q35_10_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-10.0)" case .pc_q35_7_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.1)" case .pc_q35_7_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.2)" case .pc_q35_8_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-8.0)" case .pc_q35_8_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-8.1)" case .pc_q35_8_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-8.2)" case .pc_q35_9_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-9.0)" case .pc_q35_9_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-9.1)" case .pc_q35_9_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-9.2)" case .pc: return "Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-10.0) (pc)" case .pc_i440fx_10_0: return "Standard PC (i440FX + PIIX, 1996) (default) (pc-i440fx-10.0)" case .pc_i440fx_2_10: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.10)" case .pc_i440fx_2_11: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.11)" case .pc_i440fx_2_12: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.12)" case .pc_i440fx_2_4: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.4)" case .pc_i440fx_2_5: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.5)" case .pc_i440fx_2_6: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.6)" case .pc_i440fx_2_7: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.7)" case .pc_i440fx_2_8: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.8)" case .pc_i440fx_2_9: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-2.9)" case .pc_i440fx_3_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-3.0)" case .pc_i440fx_3_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-3.1)" case .pc_i440fx_4_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-4.0)" case .pc_i440fx_4_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-4.1)" case .pc_i440fx_4_2: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-4.2)" case .pc_i440fx_5_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-5.0)" case .pc_i440fx_5_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-5.1)" case .pc_i440fx_5_2: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-5.2)" case .pc_i440fx_6_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-6.0)" case .pc_i440fx_6_1: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-6.1)" case .pc_i440fx_6_2: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-6.2)" case .pc_i440fx_7_0: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-7.0)" case .pc_i440fx_7_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.1)" case .pc_i440fx_7_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.2)" case .pc_i440fx_8_0: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-8.0)" case .pc_i440fx_8_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-8.1)" case .pc_i440fx_8_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-8.2)" case .pc_i440fx_9_0: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-9.0)" case .pc_i440fx_9_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-9.1)" case .pc_i440fx_9_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-9.2)" case .none: return "empty machine (none)" case .microvm: return "microvm (i386) (microvm)" } } } enum QEMUTarget_xtensa: String, CaseIterable, QEMUTarget { case none case kc705 case kc705_nommu = "kc705-nommu" case lx200 case lx200_nommu = "lx200-nommu" case lx60 case lx60_nommu = "lx60-nommu" case ml605 case ml605_nommu = "ml605-nommu" case sim case virt static var `default`: QEMUTarget_xtensa { .sim } var prettyValue: String { switch self { case .none: return "empty machine (none)" case .kc705: return "kc705 EVB (dc232b) (kc705)" case .kc705_nommu: return "kc705 noMMU EVB (de212) (kc705-nommu)" case .lx200: return "lx200 EVB (dc232b) (lx200)" case .lx200_nommu: return "lx200 noMMU EVB (de212) (lx200-nommu)" case .lx60: return "lx60 EVB (dc232b) (lx60)" case .lx60_nommu: return "lx60 noMMU EVB (de212) (lx60-nommu)" case .ml605: return "ml605 EVB (dc232b) (ml605)" case .ml605_nommu: return "ml605 noMMU EVB (de212) (ml605-nommu)" case .sim: return "sim machine (dc232b) (default) (sim)" case .virt: return "virt machine (dc232b) (virt)" } } } enum QEMUTarget_xtensaeb: String, CaseIterable, QEMUTarget { case none case kc705 case kc705_nommu = "kc705-nommu" case lx200 case lx200_nommu = "lx200-nommu" case lx60 case lx60_nommu = "lx60-nommu" case ml605 case ml605_nommu = "ml605-nommu" case sim case virt static var `default`: QEMUTarget_xtensaeb { .sim } var prettyValue: String { switch self { case .none: return "empty machine (none)" case .kc705: return "kc705 EVB (fsf) (kc705)" case .kc705_nommu: return "kc705 noMMU EVB (fsf) (kc705-nommu)" case .lx200: return "lx200 EVB (fsf) (lx200)" case .lx200_nommu: return "lx200 noMMU EVB (fsf) (lx200-nommu)" case .lx60: return "lx60 EVB (fsf) (lx60)" case .lx60_nommu: return "lx60 noMMU EVB (fsf) (lx60-nommu)" case .ml605: return "ml605 EVB (fsf) (ml605)" case .ml605_nommu: return "ml605 noMMU EVB (fsf) (ml605-nommu)" case .sim: return "sim machine (fsf) (default) (sim)" case .virt: return "virt machine (fsf) (virt)" } } } enum QEMUDisplayDevice_alpha: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" } } } enum QEMUDisplayDevice_arm: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case dm163 case led case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case ramfb case secondary_vga = "secondary-vga" case ssd0323 case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_ramfb = "virtio-ramfb" case virtio_ramfb_gl = "virtio-ramfb-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .dm163: return "DM163 8x3-channel constant current LED driver (dm163)" case .led: return "LED (led)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .ramfb: return "ram framebuffer standalone device (ramfb)" case .secondary_vga: return "secondary-vga" case .ssd0323: return "ssd0323" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_ramfb: return "virtio-ramfb" case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)" } } } enum QEMUDisplayDevice_aarch64: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case dm163 case led case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case apple_gfx_pci = "apple-gfx-pci" case ramfb case secondary_vga = "secondary-vga" case ssd0323 case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_ramfb = "virtio-ramfb" case virtio_ramfb_gl = "virtio-ramfb-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .dm163: return "DM163 8x3-channel constant current LED driver (dm163)" case .led: return "LED (led)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .apple_gfx_pci: return "macOS Paravirtualized Graphics PCI Display Controller (apple-gfx-pci)" case .ramfb: return "ram framebuffer standalone device (ramfb)" case .secondary_vga: return "secondary-vga" case .ssd0323: return "ssd0323" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_ramfb: return "virtio-ramfb" case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)" } } } typealias QEMUDisplayDevice_avr = AnyQEMUConstant enum QEMUDisplayDevice_hppa: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" } } } enum QEMUDisplayDevice_i386: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case qxl_vga = "qxl-vga" case qxl case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case isa_cirrus_vga = "isa-cirrus-vga" case isa_vga = "isa-vga" case ramfb case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_ramfb = "virtio-ramfb" case virtio_ramfb_gl = "virtio-ramfb-gl" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" case vmware_svga = "vmware-svga" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .qxl_vga: return "Spice QXL GPU (primary, vga compatible) (qxl-vga)" case .qxl: return "Spice QXL GPU (secondary) (qxl)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .isa_cirrus_vga: return "isa-cirrus-vga" case .isa_vga: return "isa-vga" case .ramfb: return "ram framebuffer standalone device (ramfb)" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_ramfb: return "virtio-ramfb" case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" case .vmware_svga: return "vmware-svga" } } } enum QEMUDisplayDevice_loongarch64: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case ramfb case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_ramfb = "virtio-ramfb" case virtio_ramfb_gl = "virtio-ramfb-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .ramfb: return "ram framebuffer standalone device (ramfb)" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_ramfb: return "virtio-ramfb" case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)" } } } enum QEMUDisplayDevice_m68k: String, CaseIterable, QEMUDisplayDevice { case nubus_macfb = "nubus-macfb" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" var prettyValue: String { switch self { case .nubus_macfb: return "Nubus Macintosh framebuffer (nubus-macfb)" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" } } } typealias QEMUDisplayDevice_microblaze = AnyQEMUConstant typealias QEMUDisplayDevice_microblazeel = AnyQEMUConstant enum QEMUDisplayDevice_mips: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case vmware_svga = "vmware-svga" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .vmware_svga: return "vmware-svga" } } } enum QEMUDisplayDevice_mipsel: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case vmware_svga = "vmware-svga" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .vmware_svga: return "vmware-svga" } } } enum QEMUDisplayDevice_mips64: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case vmware_svga = "vmware-svga" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .vmware_svga: return "vmware-svga" } } } enum QEMUDisplayDevice_mips64el: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case qxl_vga = "qxl-vga" case qxl case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" case vmware_svga = "vmware-svga" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .qxl_vga: return "Spice QXL GPU (primary, vga compatible) (qxl-vga)" case .qxl: return "Spice QXL GPU (secondary) (qxl)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" case .vmware_svga: return "vmware-svga" } } } enum QEMUDisplayDevice_or1k: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" } } } enum QEMUDisplayDevice_ppc: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case sm501 case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .sm501: return "SM501 Display Controller (sm501)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" } } } enum QEMUDisplayDevice_ppc64: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case sm501 case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .sm501: return "SM501 Display Controller (sm501)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" } } } enum QEMUDisplayDevice_riscv32: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case ramfb case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_ramfb = "virtio-ramfb" case virtio_ramfb_gl = "virtio-ramfb-gl" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .ramfb: return "ram framebuffer standalone device (ramfb)" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_ramfb: return "virtio-ramfb" case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" } } } enum QEMUDisplayDevice_riscv64: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case ramfb case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_ramfb = "virtio-ramfb" case virtio_ramfb_gl = "virtio-ramfb-gl" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .ramfb: return "ram framebuffer standalone device (ramfb)" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_ramfb: return "virtio-ramfb" case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" } } } typealias QEMUDisplayDevice_rx = AnyQEMUConstant enum QEMUDisplayDevice_s390x: String, CaseIterable, QEMUDisplayDevice { case virtio_gpu_ccw = "virtio-gpu-ccw" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case x_terminal3270 = "x-terminal3270" var prettyValue: String { switch self { case .virtio_gpu_ccw: return "virtio-gpu-ccw" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .x_terminal3270: return "x-terminal3270" } } } enum QEMUDisplayDevice_sh4: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case sm501 case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .sm501: return "SM501 Display Controller (sm501)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" } } } enum QEMUDisplayDevice_sh4eb: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case sm501 case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .sm501: return "SM501 Display Controller (sm501)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" } } } enum QEMUDisplayDevice_sparc: String, CaseIterable, QEMUDisplayDevice { case tcx case cg3 var prettyValue: String { switch self { case .tcx: return "Sun TCX" case .cg3: return "Sun cgthree" } } } enum QEMUDisplayDevice_sparc64: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" } } } typealias QEMUDisplayDevice_tricore = AnyQEMUConstant enum QEMUDisplayDevice_x86_64: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case qxl_vga = "qxl-vga" case qxl case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case isa_cirrus_vga = "isa-cirrus-vga" case isa_vga = "isa-vga" case ramfb case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" case virtio_ramfb = "virtio-ramfb" case virtio_ramfb_gl = "virtio-ramfb-gl" case virtio_vga = "virtio-vga" case virtio_vga_gl = "virtio-vga-gl" case vmware_svga = "vmware-svga" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .qxl_vga: return "Spice QXL GPU (primary, vga compatible) (qxl-vga)" case .qxl: return "Spice QXL GPU (secondary) (qxl)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .isa_cirrus_vga: return "isa-cirrus-vga" case .isa_vga: return "isa-vga" case .ramfb: return "ram framebuffer standalone device (ramfb)" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" case .virtio_ramfb: return "virtio-ramfb" case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)" case .virtio_vga: return "virtio-vga" case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)" case .vmware_svga: return "vmware-svga" } } } enum QEMUDisplayDevice_xtensa: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" } } } enum QEMUDisplayDevice_xtensaeb: String, CaseIterable, QEMUDisplayDevice { case cirrus_vga = "cirrus-vga" case VGA case ati_vga = "ati-vga" case bochs_display = "bochs-display" case secondary_vga = "secondary-vga" case virtio_gpu_device = "virtio-gpu-device" case virtio_gpu_gl_device = "virtio-gpu-gl-device" case virtio_gpu_gl_pci = "virtio-gpu-gl-pci" case virtio_gpu_pci = "virtio-gpu-pci" var prettyValue: String { switch self { case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)" case .VGA: return "VGA" case .ati_vga: return "ati-vga" case .bochs_display: return "bochs-display" case .secondary_vga: return "secondary-vga" case .virtio_gpu_device: return "virtio-gpu-device" case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)" case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)" case .virtio_gpu_pci: return "virtio-gpu-pci" } } } enum QEMUNetworkDevice_alpha: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_arm: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_aarch64: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } typealias QEMUNetworkDevice_avr = AnyQEMUConstant enum QEMUNetworkDevice_hppa: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_i386: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_loongarch64: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_m68k: String, CaseIterable, QEMUNetworkDevice { case virtio_net_device = "virtio-net-device" case dp8393x = "dp8393x" var prettyValue: String { switch self { case .virtio_net_device: return "virtio-net-device" case .dp8393x: return "SONIC DP8393x (Q800 only)" } } } typealias QEMUNetworkDevice_microblaze = AnyQEMUConstant typealias QEMUNetworkDevice_microblazeel = AnyQEMUConstant enum QEMUNetworkDevice_mips: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_mipsel: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_mips64: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_mips64el: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_or1k: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_ppc: String, CaseIterable, QEMUNetworkDevice { case eTSEC case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case sungem case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .eTSEC: return "Freescale Enhanced Three-Speed Ethernet Controller (eTSEC)" case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .sungem: return "sungem" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_ppc64: String, CaseIterable, QEMUNetworkDevice { case eTSEC case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case spapr_vlan = "spapr-vlan" case sungem case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .eTSEC: return "Freescale Enhanced Three-Speed Ethernet Controller (eTSEC)" case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .spapr_vlan: return "spapr-vlan" case .sungem: return "sungem" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_riscv32: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_riscv64: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } typealias QEMUNetworkDevice_rx = AnyQEMUConstant enum QEMUNetworkDevice_s390x: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case usb_net = "usb-net" case virtio_net_ccw = "virtio-net-ccw" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .usb_net: return "usb-net" case .virtio_net_ccw: return "virtio-net-ccw" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_sh4: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_sh4eb: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_sparc: String, CaseIterable, QEMUNetworkDevice { case lance var prettyValue: String { switch self { case .lance: return "Lance (Am7990)" } } } enum QEMUNetworkDevice_sparc64: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case sunhme case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .sunhme: return "sunhme" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } typealias QEMUNetworkDevice_tricore = AnyQEMUConstant enum QEMUNetworkDevice_x86_64: String, CaseIterable, QEMUNetworkDevice { case e1000e case igb case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case rocker case vmxnet3 case ne2k_isa case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000e: return "Intel 82574L GbE Controller (e1000e)" case .igb: return "Intel 82576 Gigabit Ethernet Controller (igb)" case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .rocker: return "Rocker Switch (rocker)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_isa: return "ne2k_isa" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_xtensa: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUNetworkDevice_xtensaeb: String, CaseIterable, QEMUNetworkDevice { case e1000 case e1000_82544gc = "e1000-82544gc" case e1000_82545em = "e1000-82545em" case i82550 case i82551 case i82557a case i82557b case i82557c case i82558a case i82558b case i82559a case i82559b case i82559c case i82559er case i82562 case i82801 case vmxnet3 case ne2k_pci case pcnet case rtl8139 case tulip case usb_net = "usb-net" case virtio_net_device = "virtio-net-device" case virtio_net_pci = "virtio-net-pci" case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional" case virtio_net_pci_transitional = "virtio-net-pci-transitional" var prettyValue: String { switch self { case .e1000: return "Intel Gigabit Ethernet (e1000)" case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)" case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)" case .i82550: return "Intel i82550 Ethernet (i82550)" case .i82551: return "Intel i82551 Ethernet (i82551)" case .i82557a: return "Intel i82557A Ethernet (i82557a)" case .i82557b: return "Intel i82557B Ethernet (i82557b)" case .i82557c: return "Intel i82557C Ethernet (i82557c)" case .i82558a: return "Intel i82558A Ethernet (i82558a)" case .i82558b: return "Intel i82558B Ethernet (i82558b)" case .i82559a: return "Intel i82559A Ethernet (i82559a)" case .i82559b: return "Intel i82559B Ethernet (i82559b)" case .i82559c: return "Intel i82559C Ethernet (i82559c)" case .i82559er: return "Intel i82559ER Ethernet (i82559er)" case .i82562: return "Intel i82562 Ethernet (i82562)" case .i82801: return "Intel i82801 Ethernet (i82801)" case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)" case .ne2k_pci: return "ne2k_pci" case .pcnet: return "pcnet" case .rtl8139: return "rtl8139" case .tulip: return "tulip" case .usb_net: return "usb-net" case .virtio_net_device: return "virtio-net-device" case .virtio_net_pci: return "virtio-net-pci" case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional" case .virtio_net_pci_transitional: return "virtio-net-pci-transitional" } } } enum QEMUSoundDevice_alpha: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_arm: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_aarch64: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } typealias QEMUSoundDevice_avr = AnyQEMUConstant enum QEMUSoundDevice_hppa: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_i386: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case pcspk case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .pcspk: return "PC Speaker" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_loongarch64: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_m68k: String, CaseIterable, QEMUSoundDevice { case virtio_sound_device = "virtio-sound-device" case asc = "asc" var prettyValue: String { switch self { case .virtio_sound_device: return "virtio-sound-device" case .asc: return "Apple Sound Chip (Q800 only)" } } } typealias QEMUSoundDevice_microblaze = AnyQEMUConstant typealias QEMUSoundDevice_microblazeel = AnyQEMUConstant enum QEMUSoundDevice_mips: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_mipsel: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_mips64: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_mips64el: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_or1k: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_ppc: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case screamer case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .screamer: return "Screamer (Mac99 only)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_ppc64: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case screamer case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .screamer: return "Screamer (Mac99 only)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_riscv32: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_riscv64: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } typealias QEMUSoundDevice_rx = AnyQEMUConstant enum QEMUSoundDevice_s390x: String, CaseIterable, QEMUSoundDevice { case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_sh4: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_sh4eb: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } typealias QEMUSoundDevice_sparc = AnyQEMUConstant enum QEMUSoundDevice_sparc64: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } typealias QEMUSoundDevice_tricore = AnyQEMUConstant enum QEMUSoundDevice_x86_64: String, CaseIterable, QEMUSoundDevice { case sb16 case cs4231a case ES1370 case gus case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case pcspk case virtio_sound_pci = "virtio-sound-pci" case adlib case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .sb16: return "Creative Sound Blaster 16 (sb16)" case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)" case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .gus: return "Gravis Ultrasound GF1 (gus)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .pcspk: return "PC Speaker" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .adlib: return "Yamaha YM3812 (OPL2) (adlib)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_xtensa: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSoundDevice_xtensaeb: String, CaseIterable, QEMUSoundDevice { case ES1370 case AC97 case intel_hda = "intel-hda" case ich9_intel_hda = "ich9-intel-hda" case virtio_sound_pci = "virtio-sound-pci" case usb_audio = "usb-audio" case virtio_sound_device = "virtio-sound-device" var prettyValue: String { switch self { case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)" case .AC97: return "Intel 82801AA AC97 Audio (AC97)" case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)" case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)" case .virtio_sound_pci: return "Virtio Sound (virtio-sound-pci)" case .usb_audio: return "usb-audio" case .virtio_sound_device: return "virtio-sound-device" } } } enum QEMUSerialDevice_alpha: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_arm: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_aarch64: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } typealias QEMUSerialDevice_avr = AnyQEMUConstant enum QEMUSerialDevice_hppa: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_i386: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_loongarch64: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_m68k: String, CaseIterable, QEMUSerialDevice { case virtio_serial_device = "virtio-serial-device" case virtserialport var prettyValue: String { switch self { case .virtio_serial_device: return "virtio-serial-device" case .virtserialport: return "virtserialport" } } } typealias QEMUSerialDevice_microblaze = AnyQEMUConstant typealias QEMUSerialDevice_microblazeel = AnyQEMUConstant enum QEMUSerialDevice_mips: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_mipsel: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_mips64: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_mips64el: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_or1k: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_ppc: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_ppc64: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_riscv32: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_riscv64: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } typealias QEMUSerialDevice_rx = AnyQEMUConstant enum QEMUSerialDevice_s390x: String, CaseIterable, QEMUSerialDevice { case usb_serial = "usb-serial" case virtio_serial_ccw = "virtio-serial-ccw" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .usb_serial: return "usb-serial" case .virtio_serial_ccw: return "virtio-serial-ccw" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_sh4: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_sh4eb: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } typealias QEMUSerialDevice_sparc = AnyQEMUConstant enum QEMUSerialDevice_sparc64: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } typealias QEMUSerialDevice_tricore = AnyQEMUConstant enum QEMUSerialDevice_x86_64: String, CaseIterable, QEMUSerialDevice { case isa_serial = "isa-serial" case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .isa_serial: return "isa-serial" case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_xtensa: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } enum QEMUSerialDevice_xtensaeb: String, CaseIterable, QEMUSerialDevice { case pci_serial = "pci-serial" case pci_serial_2x = "pci-serial-2x" case pci_serial_4x = "pci-serial-4x" case usb_serial = "usb-serial" case virtio_serial_device = "virtio-serial-device" case virtio_serial_pci = "virtio-serial-pci" case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional" case virtio_serial_pci_transitional = "virtio-serial-pci-transitional" case virtserialport var prettyValue: String { switch self { case .pci_serial: return "pci-serial" case .pci_serial_2x: return "pci-serial-2x" case .pci_serial_4x: return "pci-serial-4x" case .usb_serial: return "usb-serial" case .virtio_serial_device: return "virtio-serial-device" case .virtio_serial_pci: return "virtio-serial-pci" case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional" case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional" case .virtserialport: return "virtserialport" } } } extension QEMUArchitecture { var cpuType: any QEMUCPU.Type { switch self { case .alpha: return QEMUCPU_alpha.self case .arm: return QEMUCPU_arm.self case .aarch64: return QEMUCPU_aarch64.self case .avr: return QEMUCPU_avr.self case .hppa: return QEMUCPU_hppa.self case .i386: return QEMUCPU_i386.self case .loongarch64: return QEMUCPU_loongarch64.self case .m68k: return QEMUCPU_m68k.self case .microblaze: return QEMUCPU_microblaze.self case .microblazeel: return QEMUCPU_microblazeel.self case .mips: return QEMUCPU_mips.self case .mipsel: return QEMUCPU_mipsel.self case .mips64: return QEMUCPU_mips64.self case .mips64el: return QEMUCPU_mips64el.self case .or1k: return QEMUCPU_or1k.self case .ppc: return QEMUCPU_ppc.self case .ppc64: return QEMUCPU_ppc64.self case .riscv32: return QEMUCPU_riscv32.self case .riscv64: return QEMUCPU_riscv64.self case .rx: return QEMUCPU_rx.self case .s390x: return QEMUCPU_s390x.self case .sh4: return QEMUCPU_sh4.self case .sh4eb: return QEMUCPU_sh4eb.self case .sparc: return QEMUCPU_sparc.self case .sparc64: return QEMUCPU_sparc64.self case .tricore: return QEMUCPU_tricore.self case .x86_64: return QEMUCPU_x86_64.self case .xtensa: return QEMUCPU_xtensa.self case .xtensaeb: return QEMUCPU_xtensaeb.self } } var cpuFlagType: any QEMUCPUFlag.Type { switch self { case .alpha: return QEMUCPUFlag_alpha.self case .arm: return QEMUCPUFlag_arm.self case .aarch64: return QEMUCPUFlag_aarch64.self case .avr: return QEMUCPUFlag_avr.self case .hppa: return QEMUCPUFlag_hppa.self case .i386: return QEMUCPUFlag_i386.self case .loongarch64: return QEMUCPUFlag_loongarch64.self case .m68k: return QEMUCPUFlag_m68k.self case .microblaze: return QEMUCPUFlag_microblaze.self case .microblazeel: return QEMUCPUFlag_microblazeel.self case .mips: return QEMUCPUFlag_mips.self case .mipsel: return QEMUCPUFlag_mipsel.self case .mips64: return QEMUCPUFlag_mips64.self case .mips64el: return QEMUCPUFlag_mips64el.self case .or1k: return QEMUCPUFlag_or1k.self case .ppc: return QEMUCPUFlag_ppc.self case .ppc64: return QEMUCPUFlag_ppc64.self case .riscv32: return QEMUCPUFlag_riscv32.self case .riscv64: return QEMUCPUFlag_riscv64.self case .rx: return QEMUCPUFlag_rx.self case .s390x: return QEMUCPUFlag_s390x.self case .sh4: return QEMUCPUFlag_sh4.self case .sh4eb: return QEMUCPUFlag_sh4eb.self case .sparc: return QEMUCPUFlag_sparc.self case .sparc64: return QEMUCPUFlag_sparc64.self case .tricore: return QEMUCPUFlag_tricore.self case .x86_64: return QEMUCPUFlag_x86_64.self case .xtensa: return QEMUCPUFlag_xtensa.self case .xtensaeb: return QEMUCPUFlag_xtensaeb.self } } var targetType: any QEMUTarget.Type { switch self { case .alpha: return QEMUTarget_alpha.self case .arm: return QEMUTarget_arm.self case .aarch64: return QEMUTarget_aarch64.self case .avr: return QEMUTarget_avr.self case .hppa: return QEMUTarget_hppa.self case .i386: return QEMUTarget_i386.self case .loongarch64: return QEMUTarget_loongarch64.self case .m68k: return QEMUTarget_m68k.self case .microblaze: return QEMUTarget_microblaze.self case .microblazeel: return QEMUTarget_microblazeel.self case .mips: return QEMUTarget_mips.self case .mipsel: return QEMUTarget_mipsel.self case .mips64: return QEMUTarget_mips64.self case .mips64el: return QEMUTarget_mips64el.self case .or1k: return QEMUTarget_or1k.self case .ppc: return QEMUTarget_ppc.self case .ppc64: return QEMUTarget_ppc64.self case .riscv32: return QEMUTarget_riscv32.self case .riscv64: return QEMUTarget_riscv64.self case .rx: return QEMUTarget_rx.self case .s390x: return QEMUTarget_s390x.self case .sh4: return QEMUTarget_sh4.self case .sh4eb: return QEMUTarget_sh4eb.self case .sparc: return QEMUTarget_sparc.self case .sparc64: return QEMUTarget_sparc64.self case .tricore: return QEMUTarget_tricore.self case .x86_64: return QEMUTarget_x86_64.self case .xtensa: return QEMUTarget_xtensa.self case .xtensaeb: return QEMUTarget_xtensaeb.self } } var displayDeviceType: any QEMUDisplayDevice.Type { switch self { case .alpha: return QEMUDisplayDevice_alpha.self case .arm: return QEMUDisplayDevice_arm.self case .aarch64: return QEMUDisplayDevice_aarch64.self case .avr: return QEMUDisplayDevice_avr.self case .hppa: return QEMUDisplayDevice_hppa.self case .i386: return QEMUDisplayDevice_i386.self case .loongarch64: return QEMUDisplayDevice_loongarch64.self case .m68k: return QEMUDisplayDevice_m68k.self case .microblaze: return QEMUDisplayDevice_microblaze.self case .microblazeel: return QEMUDisplayDevice_microblazeel.self case .mips: return QEMUDisplayDevice_mips.self case .mipsel: return QEMUDisplayDevice_mipsel.self case .mips64: return QEMUDisplayDevice_mips64.self case .mips64el: return QEMUDisplayDevice_mips64el.self case .or1k: return QEMUDisplayDevice_or1k.self case .ppc: return QEMUDisplayDevice_ppc.self case .ppc64: return QEMUDisplayDevice_ppc64.self case .riscv32: return QEMUDisplayDevice_riscv32.self case .riscv64: return QEMUDisplayDevice_riscv64.self case .rx: return QEMUDisplayDevice_rx.self case .s390x: return QEMUDisplayDevice_s390x.self case .sh4: return QEMUDisplayDevice_sh4.self case .sh4eb: return QEMUDisplayDevice_sh4eb.self case .sparc: return QEMUDisplayDevice_sparc.self case .sparc64: return QEMUDisplayDevice_sparc64.self case .tricore: return QEMUDisplayDevice_tricore.self case .x86_64: return QEMUDisplayDevice_x86_64.self case .xtensa: return QEMUDisplayDevice_xtensa.self case .xtensaeb: return QEMUDisplayDevice_xtensaeb.self } } var networkDeviceType: any QEMUNetworkDevice.Type { switch self { case .alpha: return QEMUNetworkDevice_alpha.self case .arm: return QEMUNetworkDevice_arm.self case .aarch64: return QEMUNetworkDevice_aarch64.self case .avr: return QEMUNetworkDevice_avr.self case .hppa: return QEMUNetworkDevice_hppa.self case .i386: return QEMUNetworkDevice_i386.self case .loongarch64: return QEMUNetworkDevice_loongarch64.self case .m68k: return QEMUNetworkDevice_m68k.self case .microblaze: return QEMUNetworkDevice_microblaze.self case .microblazeel: return QEMUNetworkDevice_microblazeel.self case .mips: return QEMUNetworkDevice_mips.self case .mipsel: return QEMUNetworkDevice_mipsel.self case .mips64: return QEMUNetworkDevice_mips64.self case .mips64el: return QEMUNetworkDevice_mips64el.self case .or1k: return QEMUNetworkDevice_or1k.self case .ppc: return QEMUNetworkDevice_ppc.self case .ppc64: return QEMUNetworkDevice_ppc64.self case .riscv32: return QEMUNetworkDevice_riscv32.self case .riscv64: return QEMUNetworkDevice_riscv64.self case .rx: return QEMUNetworkDevice_rx.self case .s390x: return QEMUNetworkDevice_s390x.self case .sh4: return QEMUNetworkDevice_sh4.self case .sh4eb: return QEMUNetworkDevice_sh4eb.self case .sparc: return QEMUNetworkDevice_sparc.self case .sparc64: return QEMUNetworkDevice_sparc64.self case .tricore: return QEMUNetworkDevice_tricore.self case .x86_64: return QEMUNetworkDevice_x86_64.self case .xtensa: return QEMUNetworkDevice_xtensa.self case .xtensaeb: return QEMUNetworkDevice_xtensaeb.self } } var soundDeviceType: any QEMUSoundDevice.Type { switch self { case .alpha: return QEMUSoundDevice_alpha.self case .arm: return QEMUSoundDevice_arm.self case .aarch64: return QEMUSoundDevice_aarch64.self case .avr: return QEMUSoundDevice_avr.self case .hppa: return QEMUSoundDevice_hppa.self case .i386: return QEMUSoundDevice_i386.self case .loongarch64: return QEMUSoundDevice_loongarch64.self case .m68k: return QEMUSoundDevice_m68k.self case .microblaze: return QEMUSoundDevice_microblaze.self case .microblazeel: return QEMUSoundDevice_microblazeel.self case .mips: return QEMUSoundDevice_mips.self case .mipsel: return QEMUSoundDevice_mipsel.self case .mips64: return QEMUSoundDevice_mips64.self case .mips64el: return QEMUSoundDevice_mips64el.self case .or1k: return QEMUSoundDevice_or1k.self case .ppc: return QEMUSoundDevice_ppc.self case .ppc64: return QEMUSoundDevice_ppc64.self case .riscv32: return QEMUSoundDevice_riscv32.self case .riscv64: return QEMUSoundDevice_riscv64.self case .rx: return QEMUSoundDevice_rx.self case .s390x: return QEMUSoundDevice_s390x.self case .sh4: return QEMUSoundDevice_sh4.self case .sh4eb: return QEMUSoundDevice_sh4eb.self case .sparc: return QEMUSoundDevice_sparc.self case .sparc64: return QEMUSoundDevice_sparc64.self case .tricore: return QEMUSoundDevice_tricore.self case .x86_64: return QEMUSoundDevice_x86_64.self case .xtensa: return QEMUSoundDevice_xtensa.self case .xtensaeb: return QEMUSoundDevice_xtensaeb.self } } var serialDeviceType: any QEMUSerialDevice.Type { switch self { case .alpha: return QEMUSerialDevice_alpha.self case .arm: return QEMUSerialDevice_arm.self case .aarch64: return QEMUSerialDevice_aarch64.self case .avr: return QEMUSerialDevice_avr.self case .hppa: return QEMUSerialDevice_hppa.self case .i386: return QEMUSerialDevice_i386.self case .loongarch64: return QEMUSerialDevice_loongarch64.self case .m68k: return QEMUSerialDevice_m68k.self case .microblaze: return QEMUSerialDevice_microblaze.self case .microblazeel: return QEMUSerialDevice_microblazeel.self case .mips: return QEMUSerialDevice_mips.self case .mipsel: return QEMUSerialDevice_mipsel.self case .mips64: return QEMUSerialDevice_mips64.self case .mips64el: return QEMUSerialDevice_mips64el.self case .or1k: return QEMUSerialDevice_or1k.self case .ppc: return QEMUSerialDevice_ppc.self case .ppc64: return QEMUSerialDevice_ppc64.self case .riscv32: return QEMUSerialDevice_riscv32.self case .riscv64: return QEMUSerialDevice_riscv64.self case .rx: return QEMUSerialDevice_rx.self case .s390x: return QEMUSerialDevice_s390x.self case .sh4: return QEMUSerialDevice_sh4.self case .sh4eb: return QEMUSerialDevice_sh4eb.self case .sparc: return QEMUSerialDevice_sparc.self case .sparc64: return QEMUSerialDevice_sparc64.self case .tricore: return QEMUSerialDevice_tricore.self case .x86_64: return QEMUSerialDevice_x86_64.self case .xtensa: return QEMUSerialDevice_xtensa.self case .xtensaeb: return QEMUSerialDevice_xtensaeb.self } } } ================================================ FILE: Configuration/UTMAppleConfiguration.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) final class UTMAppleConfiguration: UTMConfiguration { /// Basic information and icon @Published var _information: UTMConfigurationInfo = .init() @Published private var _system: UTMAppleConfigurationSystem = .init() @Published private var _virtualization: UTMAppleConfigurationVirtualization = .init() @Published private var _sharedDirectories: [UTMAppleConfigurationSharedDirectory] = [] @Published private var _displays: [UTMAppleConfigurationDisplay] = [] @Published private var _drives: [UTMAppleConfigurationDrive] = [] @Published private var _networks: [UTMAppleConfigurationNetwork] = [.init()] @Published private var _serials: [UTMAppleConfigurationSerial] = [] var backend: UTMBackend { .apple } enum CodingKeys: String, CodingKey { case information = "Information" case system = "System" case virtualization = "Virtualization" case sharedDirectories = "SharedDirectory" // legacy case displays = "Display" case drives = "Drive" case networks = "Network" case serials = "Serial" case backend = "Backend" case configurationVersion = "ConfigurationVersion" } init() { } required init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) let backend = try values.decodeIfPresent(UTMBackend.self, forKey: .backend) ?? .unknown guard backend == .apple else { throw UTMConfigurationError.invalidBackend } let version = try values.decodeIfPresent(Int.self, forKey: .configurationVersion) ?? 0 guard version >= Self.oldestVersion else { throw UTMConfigurationError.versionTooLow } guard version <= Self.currentVersion else { throw UTMConfigurationError.versionTooHigh } _information = try values.decode(UTMConfigurationInfo.self, forKey: .information) _system = try values.decode(UTMAppleConfigurationSystem.self, forKey: .system) _virtualization = try values.decode(UTMAppleConfigurationVirtualization.self, forKey: .virtualization) _sharedDirectories = try values.decodeIfPresent([UTMAppleConfigurationSharedDirectory].self, forKey: .sharedDirectories) ?? [] _displays = try values.decode([UTMAppleConfigurationDisplay].self, forKey: .displays) _drives = try values.decode([UTMAppleConfigurationDrive].self, forKey: .drives) _networks = try values.decode([UTMAppleConfigurationNetwork].self, forKey: .networks) _serials = try values.decode([UTMAppleConfigurationSerial].self, forKey: .serials) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(_information, forKey: .information) try container.encode(_system, forKey: .system) try container.encode(_virtualization, forKey: .virtualization) try container.encode(_displays, forKey: .displays) try container.encode(_drives, forKey: .drives) try container.encode(_networks, forKey: .networks) try container.encode(_serials, forKey: .serials) try container.encode(UTMBackend.apple, forKey: .backend) try container.encode(Self.currentVersion, forKey: .configurationVersion) } } enum UTMAppleConfigurationError: Error { case notAppleConfiguration case platformUnsupported case kernelNotSpecified case hardwareModelInvalid case rosettaNotSupported case featureNotSupported } extension UTMAppleConfigurationError: LocalizedError { var errorDescription: String? { switch self { case .notAppleConfiguration: return NSLocalizedString("This is not a valid Apple Virtualization configuration.", comment: "UTMAppleConfiguration") case .platformUnsupported: return NSLocalizedString("This virtual machine cannot run on the current host machine.", comment: "UTMAppleConfiguration") case .kernelNotSpecified: return NSLocalizedString("A valid kernel image must be specified.", comment: "UTMAppleConfiguration") case .hardwareModelInvalid: return NSLocalizedString("This virtual machine contains an invalid hardware model. The configuration may be corrupted or is outdated.", comment: "UTMAppleConfiguration") case .rosettaNotSupported: return NSLocalizedString("Rosetta is not supported on the current host machine.", comment: "UTMAppleConfiguration") case .featureNotSupported: return NSLocalizedString("The host operating system needs to be updated to support one or more features requested by the guest.", comment: "UTMAppleConfiguration") } } } // MARK: - Public accessors @MainActor extension UTMAppleConfiguration { var information: UTMConfigurationInfo { get { _information } set { _information = newValue } } var system: UTMAppleConfigurationSystem { get { _system } set { _system = newValue } } var virtualization: UTMAppleConfigurationVirtualization { get { _virtualization } set { _virtualization = newValue } } var sharedDirectories: [UTMAppleConfigurationSharedDirectory] { get { _sharedDirectories } set { _sharedDirectories = newValue } } var sharedDirectoriesPublisher: Published<[UTMAppleConfigurationSharedDirectory]>.Publisher { get { $_sharedDirectories } } var displays: [UTMAppleConfigurationDisplay] { get { _displays } set { _displays = newValue } } var drives: [UTMAppleConfigurationDrive] { get { _drives } set { _drives = newValue } } var networks: [UTMAppleConfigurationNetwork] { get { _networks } set { _networks = newValue } } var serials: [UTMAppleConfigurationSerial] { get { _serials } set { _serials = newValue } } } // MARK: - Conversion of old config format extension UTMAppleConfiguration { convenience init(migrating oldConfig: UTMLegacyAppleConfiguration, dataURL: URL) { self.init() _information = .init(migrating: oldConfig, dataURL: dataURL) _system = .init(migrating: oldConfig) _virtualization = .init(migrating: oldConfig) if #available(macOS 12, *) { _sharedDirectories = oldConfig.sharedDirectories.map { .init(migrating: $0) } } #if arch(arm64) if #available(macOS 12, *) { _displays = oldConfig.displays.map { .init(migrating: $0) } } #endif _drives = oldConfig.diskImages.map { .init(migrating: $0) } _networks = oldConfig.networkDevices.map { .init(migrating: $0) } if oldConfig.isConsoleDisplay { var serial = UTMAppleConfigurationSerial() serial.terminal = .init(migrating: oldConfig) _serials = [serial] } else if oldConfig.isSerialEnabled { var serial = UTMAppleConfigurationSerial() serial.mode = .ptty _serials = [serial] } } } // MARK: - Creating Apple config @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) @MainActor extension UTMAppleConfiguration { func appleVZConfiguration(ignoringDrives: Bool = false) throws -> VZVirtualMachineConfiguration { let vzconfig = VZVirtualMachineConfiguration() try system.fillVZConfiguration(vzconfig) if #available(macOS 12, *), !sharedDirectories.isEmpty { let fsConfig = VZVirtioFileSystemDeviceConfiguration(tag: shareDirectoryTag) fsConfig.share = UTMAppleConfigurationSharedDirectory.makeDirectoryShare(from: sharedDirectories) vzconfig.directorySharingDevices.append(fsConfig) } else if !sharedDirectories.isEmpty { throw UTMAppleConfigurationError.featureNotSupported } if !ignoringDrives { vzconfig.storageDevices = try drives.compactMap { drive in guard let attachment = try drive.vzDiskImage(useFsWorkAround: system.boot.operatingSystem == .linux) else { return nil } if #available(macOS 13, *), drive.isExternal { if #available(macOS 15, *) { return nil // we will handle removable drives in `UTMAppleVirtualMachine` } else { return VZUSBMassStorageDeviceConfiguration(attachment: attachment) } } else if #available(macOS 14, *), drive.isNvme, system.boot.operatingSystem == .linux { return VZNVMExpressControllerDeviceConfiguration(attachment: attachment) } else { let device = VZVirtioBlockDeviceConfiguration(attachment: attachment) if #available(macOS 12.3, *) { device.blockDeviceIdentifier = drive.serial } return device } } } vzconfig.networkDevices.append(contentsOf: networks.compactMap({ $0.vzNetworking() })) vzconfig.serialPorts.append(contentsOf: serials.compactMap({ $0.vzSerial() })) // add remaining devices try virtualization.fillVZConfiguration(vzconfig, isMacOSGuest: system.boot.operatingSystem == .macOS) #if arch(arm64) if #available(macOS 12, *), system.boot.operatingSystem == .macOS { let graphics = VZMacGraphicsDeviceConfiguration() graphics.displays = displays.map({ display in display.vzMacDisplay() }) if graphics.displays.count > 0 { vzconfig.graphicsDevices = [graphics] } } #endif if #available(macOS 13, *), system.boot.operatingSystem != .macOS { let graphics = VZVirtioGraphicsDeviceConfiguration() graphics.scanouts = displays.map({ display in display.vzVirtioDisplay() }) if graphics.scanouts.count > 0 { vzconfig.graphicsDevices = [graphics] } } else if system.boot.operatingSystem != .macOS && !displays.isEmpty { throw UTMAppleConfigurationError.featureNotSupported } if #available(macOS 15, *) { vzconfig.usbControllers = [VZXHCIControllerConfiguration()] } return vzconfig } var shareDirectoryTag: String { if #available(macOS 13, *), system.boot.operatingSystem == .macOS { return VZVirtioFileSystemDeviceConfiguration.macOSGuestAutomountTag } else { return "share" } } } // MARK: - Saving data @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) @MainActor extension UTMAppleConfiguration { func prepareSave(for packageURL: URL) async throws { try await virtualization.prepareSave(for: packageURL) } func saveData(to dataURL: URL) async throws -> [URL] { var existingDataURLs = [URL]() existingDataURLs += try await _information.saveData(to: dataURL) existingDataURLs += try await _system.boot.saveData(to: dataURL) #if arch(arm64) if #available(macOS 12, *), system.macPlatform != nil { existingDataURLs += try await _system.macPlatform!.saveData(to: dataURL) } #endif // validate before we copy and create drive images try appleVZConfiguration(ignoringDrives: true).validate() for i in 0.. VZBootLoader? { switch operatingSystem { case .none: return nil case .linux: if #available(macOS 13, *), let efiVariableStorageURL = efiVariableStorageURL, hasUefiBoot { let efi = VZEFIBootLoader() efi.variableStore = VZEFIVariableStore(url: efiVariableStorageURL) return efi } guard let linuxKernelURL = linuxKernelURL else { return nil } let linux = VZLinuxBootLoader(kernelURL: linuxKernelURL) linux.initialRamdiskURL = linuxInitialRamdiskURL if let linuxCommandLine = linuxCommandLine { linux.commandLine = linuxCommandLine } return linux case .macOS: #if arch(arm64) if #available(macOS 12, *) { return VZMacOSBootLoader() } #endif return nil } } } // MARK: - Conversion of old config format @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationBoot { init(migrating oldBoot: Bootloader) { switch oldBoot.operatingSystem { case .macOS: operatingSystem = .macOS case .Linux: operatingSystem = .linux } linuxKernelURL = oldBoot.linuxKernelURL linuxCommandLine = oldBoot.linuxCommandLine linuxInitialRamdiskURL = oldBoot.linuxInitialRamdiskURL } } // MARK: - Saving data @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationBoot { @MainActor mutating func saveData(to dataURL: URL) async throws -> [URL] { var urls = [URL]() if operatingSystem == .linux && !hasUefiBoot { guard let linuxKernelURL = linuxKernelURL else { throw UTMAppleConfigurationError.kernelNotSpecified } let kernelUrl = try await UTMAppleConfiguration.copyItemIfChanged(from: linuxKernelURL, to: dataURL) self.linuxKernelURL = kernelUrl urls.append(kernelUrl) if let linuxInitialRamdiskURL = linuxInitialRamdiskURL { let ramdiskUrl = try await UTMAppleConfiguration.copyItemIfChanged(from: linuxInitialRamdiskURL, to: dataURL) self.linuxInitialRamdiskURL = ramdiskUrl urls.append(ramdiskUrl) } self.efiVariableStorageURL = nil } if hasUefiBoot { guard #available(macOS 13, *) else { throw UTMAppleConfigurationError.platformUnsupported } let fileManager = FileManager.default let efiVariableStorageURL = dataURL.appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue) if !fileManager.fileExists(atPath: efiVariableStorageURL.path) { _ = try VZEFIVariableStore(creatingVariableStoreAt: efiVariableStorageURL) } self.linuxKernelURL = nil self.linuxInitialRamdiskURL = nil self.linuxCommandLine = nil self.efiVariableStorageURL = efiVariableStorageURL urls.append(efiVariableStorageURL) } let vmSavedStateURL = dataURL.appendingPathComponent(QEMUPackageFileName.vmState.rawValue) self.vmSavedStateURL = vmSavedStateURL urls.append(vmSavedStateURL) return urls } } ================================================ FILE: Configuration/UTMAppleConfigurationDisplay.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationDisplay: Codable, Identifiable { var widthInPixels: Int = 1920 var heightInPixels: Int = 1200 var pixelsPerInch: Int = 80 var isDynamicResolution: Bool = true let id = UUID() enum CodingKeys: String, CodingKey { case widthInPixels = "WidthPixels" case heightInPixels = "HeightPixels" case pixelsPerInch = "PixelsPerInch" case isDynamicResolution = "DynamicResolution" } init() { } init(width: Int, height: Int, ppi: Int = 80) { widthInPixels = width heightInPixels = height pixelsPerInch = ppi } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) widthInPixels = try values.decode(Int.self, forKey: .widthInPixels) heightInPixels = try values.decode(Int.self, forKey: .heightInPixels) pixelsPerInch = try values.decode(Int.self, forKey: .pixelsPerInch) isDynamicResolution = try values.decodeIfPresent(Bool.self, forKey: .isDynamicResolution) ?? true } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(widthInPixels, forKey: .widthInPixels) try container.encode(heightInPixels, forKey: .heightInPixels) try container.encode(pixelsPerInch, forKey: .pixelsPerInch) try container.encode(isDynamicResolution, forKey: .isDynamicResolution) } #if arch(arm64) @available(macOS 12, *) init(from config: VZMacGraphicsDisplayConfiguration) { widthInPixels = config.widthInPixels heightInPixels = config.heightInPixels pixelsPerInch = config.pixelsPerInch } @available(macOS 12, *) func vzMacDisplay() -> VZMacGraphicsDisplayConfiguration { VZMacGraphicsDisplayConfiguration(widthInPixels: widthInPixels, heightInPixels: heightInPixels, pixelsPerInch: pixelsPerInch) } #endif @available(macOS 13, *) func vzVirtioDisplay() -> VZVirtioGraphicsScanoutConfiguration { VZVirtioGraphicsScanoutConfiguration(widthInPixels: widthInPixels, heightInPixels: heightInPixels) } } // MARK: - Conversion of old config format #if arch(arm64) @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 12, *) extension UTMAppleConfigurationDisplay { init(migrating oldDisplay: Display) { widthInPixels = oldDisplay.widthInPixels heightInPixels = oldDisplay.heightInPixels pixelsPerInch = oldDisplay.pixelsPerInch } } #endif ================================================ FILE: Configuration/UTMAppleConfigurationDrive.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationDrive: UTMConfigurationDrive { private let bytesInMib = 1048576 var sizeMib: Int = 0 var isReadOnly: Bool var isExternal: Bool var isNvme: Bool var imageURL: URL? var imageName: String? var isASIF: Bool = false // not saved private(set) var id = UUID().uuidString var isRawImage: Bool { true // always true for Apple VMs } private enum CodingKeys: String, CodingKey { case isReadOnly = "ReadOnly" case isNvme = "Nvme" case imageName = "ImageName" case bookmark = "Bookmark" // legacy only case identifier = "Identifier" } var sizeString: String { let sizeBytes: Int64 if let attributes = try? imageURL?.resourceValues(forKeys: [.fileSizeKey]), let fileSize = attributes.fileSize { sizeBytes = Int64(fileSize) } else { sizeBytes = Int64(sizeMib) * Int64(bytesInMib) } return ByteCountFormatter.string(fromByteCount: sizeBytes, countStyle: .binary) } init(newSize: Int) { sizeMib = newSize isReadOnly = false isExternal = false isNvme = false } init(existingURL url: URL?, isExternal: Bool = false, isNvme: Bool = false) { self.imageURL = url self.isReadOnly = isExternal self.isExternal = isExternal self.isNvme = isNvme } 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) if let imageName = try container.decodeIfPresent(String.self, forKey: .imageName) { self.imageName = imageName imageURL = dataURL.appendingPathComponent(imageName) isExternal = false } else if let bookmark = try container.decodeIfPresent(Data.self, forKey: .bookmark) { var stale: Bool = false imageURL = try? URL(resolvingBookmarkData: bookmark, options: .withSecurityScope, bookmarkDataIsStale: &stale) imageName = imageURL?.lastPathComponent isExternal = true } else { imageURL = nil imageName = nil isExternal = true } isReadOnly = try container.decodeIfPresent(Bool.self, forKey: .isReadOnly) ?? isExternal isNvme = try container.decodeIfPresent(Bool.self, forKey: .isNvme) ?? false id = try container.decode(String.self, forKey: .identifier) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) if !isExternal { try container.encodeIfPresent(imageName, forKey: .imageName) } try container.encode(isReadOnly, forKey: .isReadOnly) try container.encode(isNvme, forKey: .isNvme) try container.encode(id, forKey: .identifier) } func vzDiskImage(useFsWorkAround: Bool = false) throws -> VZDiskImageStorageDeviceAttachment? { if let imageURL = imageURL { // Use cached caching mode for virtio drive to prevent fs corruption on linux when possible if #available(macOS 12.0, *), !isNvme, useFsWorkAround { return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly, cachingMode: .cached, synchronizationMode: .full) } else { return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly) } } else { return nil } } func hash(into hasher: inout Hasher) { imageName?.hash(into: &hasher) sizeMib.hash(into: &hasher) isReadOnly.hash(into: &hasher) isNvme.hash(into: &hasher) isExternal.hash(into: &hasher) id.hash(into: &hasher) isASIF.hash(into: &hasher) } func clone() -> UTMAppleConfigurationDrive { var cloned = self cloned.id = UUID().uuidString return cloned } } // MARK: - Conversion of old config format @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationDrive { init(migrating oldDrive: DiskImage) { sizeMib = oldDrive.sizeMib isReadOnly = oldDrive.isReadOnly isExternal = oldDrive.isExternal isNvme = false imageURL = oldDrive.imageURL } } ================================================ FILE: Configuration/UTMAppleConfigurationGenericPlatform.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationGenericPlatform: Codable { var machineIdentifier: Data? private enum CodingKeys: String, CodingKey { case machineIdentifier } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) machineIdentifier = try container.decodeIfPresent(Data.self, forKey: .machineIdentifier) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(machineIdentifier, forKey: .machineIdentifier) } init() { if #available(macOS 13, *) { machineIdentifier = VZGenericMachineIdentifier().dataRepresentation } } @available(macOS 12, *) func vzGenericPlatform() -> VZGenericPlatformConfiguration? { let config = VZGenericPlatformConfiguration() if #available(macOS 13, *) { if let machineIdentifier = machineIdentifier, let vzMachineIdentifier = VZGenericMachineIdentifier(dataRepresentation: machineIdentifier) { config.machineIdentifier = vzMachineIdentifier } } if #available(macOS 15, *) { // always enable nestedVirtualization when available config.isNestedVirtualizationEnabled = VZGenericPlatformConfiguration.isNestedVirtualizationSupported } return config } } ================================================ FILE: Configuration/UTMAppleConfigurationMacPlatform.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationMacPlatform: Codable { var hardwareModel: Data var machineIdentifier: Data var auxiliaryStorageURL: URL? private enum CodingKeys: String, CodingKey { case hardwareModel = "HardwareModel" case machineIdentifier = "MachineIdentifier" case auxiliaryStoragePath = "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) } #if arch(arm64) @available(macOS 12, *) init(newHardware: VZMacHardwareModel) { hardwareModel = newHardware.dataRepresentation machineIdentifier = VZMacMachineIdentifier().dataRepresentation } @available(macOS 12, *) init(from config: VZMacPlatformConfiguration) { hardwareModel = config.hardwareModel.dataRepresentation machineIdentifier = config.machineIdentifier.dataRepresentation auxiliaryStorageURL = config.auxiliaryStorage?.url } @available(macOS 12, *) func vzMacPlatform() -> VZMacPlatformConfiguration? { guard let vzHardwareModel = VZMacHardwareModel(dataRepresentation: hardwareModel) else { return nil } guard let vzMachineIdentifier = VZMacMachineIdentifier(dataRepresentation: machineIdentifier) else { return nil } var vzAuxiliaryStorage: VZMacAuxiliaryStorage? if let auxiliaryStorageURL = auxiliaryStorageURL { vzAuxiliaryStorage = VZMacAuxiliaryStorage(contentsOf: auxiliaryStorageURL) } let config = VZMacPlatformConfiguration() config.hardwareModel = vzHardwareModel config.machineIdentifier = vzMachineIdentifier config.auxiliaryStorage = vzAuxiliaryStorage return config } #endif } // MARK: - Conversion of old config format #if arch(arm64) @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 12, *) extension UTMAppleConfigurationMacPlatform { init(migrating oldBoot: MacPlatform) { hardwareModel = oldBoot.hardwareModel machineIdentifier = oldBoot.machineIdentifier auxiliaryStorageURL = oldBoot.auxiliaryStorageURL } } #endif // MARK: - Saving data #if arch(arm64) @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 12, *) extension UTMAppleConfigurationMacPlatform { @MainActor mutating func saveData(to dataURL: URL) async throws -> [URL] { let fileManager = FileManager.default let auxStorageURL = dataURL.appendingPathComponent("AuxiliaryStorage") if !fileManager.fileExists(atPath: auxStorageURL.path) { guard let hwModel = VZMacHardwareModel(dataRepresentation: hardwareModel) else { throw UTMAppleConfigurationError.hardwareModelInvalid } _ = try VZMacAuxiliaryStorage(creatingStorageAt: auxStorageURL, hardwareModel: hwModel, options: []) } auxiliaryStorageURL = auxStorageURL return [auxStorageURL] } } #endif ================================================ FILE: Configuration/UTMAppleConfigurationNetwork.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationNetwork: Codable, Identifiable { enum NetworkMode: String, CaseIterable, QEMUConstant { case shared = "Shared" case bridged = "Bridged" var prettyValue: String { switch self { case .shared: return NSLocalizedString("Shared Network", comment: "UTMAppleConfigurationNetwork") case .bridged: return NSLocalizedString("Bridged (Advanced)", comment: "UTMAppleConfigurationNetwork") } } } var mode: NetworkMode = .shared /// Unique MAC address. var macAddress: String = VZMACAddress.randomLocallyAdministered().string /// In bridged mode this is the physical interface to bridge. var bridgeInterface: String? let id = UUID() enum CodingKeys: String, CodingKey { case mode = "Mode" case macAddress = "MacAddress" case bridgeInterface = "BridgeInterface" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) mode = try values.decode(NetworkMode.self, forKey: .mode) macAddress = try values.decode(String.self, forKey: .macAddress) bridgeInterface = try values.decodeIfPresent(String.self, forKey: .bridgeInterface) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(mode, forKey: .mode) try container.encode(macAddress, forKey: .macAddress) if mode == .bridged { try container.encodeIfPresent(bridgeInterface, forKey: .bridgeInterface) } } init?(from config: VZNetworkDeviceConfiguration) { guard let virtioConfig = config as? VZVirtioNetworkDeviceConfiguration else { return nil } macAddress = virtioConfig.macAddress.string if let attachment = virtioConfig.attachment as? VZBridgedNetworkDeviceAttachment { mode = .bridged bridgeInterface = attachment.interface.identifier } else if let _ = virtioConfig.attachment as? VZNATNetworkDeviceAttachment { mode = .shared } else { return nil } } func vzNetworking() -> VZNetworkDeviceConfiguration? { let config = VZVirtioNetworkDeviceConfiguration() guard let macAddress = VZMACAddress(string: macAddress) else { return nil } config.macAddress = macAddress switch mode { case .shared: let attachment = VZNATNetworkDeviceAttachment() config.attachment = attachment case .bridged: var found: VZBridgedNetworkInterface? if let bridgeInterface = bridgeInterface { for interface in VZBridgedNetworkInterface.networkInterfaces { if interface.identifier == bridgeInterface { found = interface break } } } else { // default to first interface if unspecified found = VZBridgedNetworkInterface.networkInterfaces.first } if let found = found { let attachment = VZBridgedNetworkDeviceAttachment(interface: found) config.attachment = attachment } } return config } } // MARK: - Conversion of old config format @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationNetwork { init(migrating oldNetwork: Network) { switch oldNetwork.networkMode { case .Bridged: mode = .bridged case .Shared: mode = .shared } macAddress = oldNetwork.macAddress bridgeInterface = oldNetwork.bridgeInterfaceIdentifier } } ================================================ FILE: Configuration/UTMAppleConfigurationSerial.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationSerial: Codable, Identifiable { enum SerialMode: String, CaseIterable, QEMUConstant { case builtin = "Terminal" case ptty = "Ptty" var prettyValue: String { switch self { case .builtin: return NSLocalizedString("Built-in Terminal", comment: "UTMAppleConfigurationTerminal") case .ptty: return NSLocalizedString("Pseudo-TTY Device", comment: "UTMAppleConfigurationTerminal") } } } var mode: SerialMode = .builtin /// Terminal settings for built-in mode. var terminal: UTMConfigurationTerminal? = .init() /// Set to read handle before starting VM. Not saved. var fileHandleForReading: FileHandle? /// Set to write handle before starting VM. Not saved. var fileHandleForWriting: FileHandle? /// Serial interface used by the VM. Not saved. var interface: UTMSerialPort? let id = UUID() enum CodingKeys: String, CodingKey { case mode = "Mode" case terminal = "Terminal" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) mode = try values.decode(SerialMode.self, forKey: .mode) terminal = try values.decodeIfPresent(UTMConfigurationTerminal.self, forKey: .terminal) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(mode, forKey: .mode) // only save relevant settings switch mode { case .builtin: try container.encodeIfPresent(terminal, forKey: .terminal) default: break } } func vzSerial() -> VZSerialPortConfiguration? { guard let fileHandleForReading = fileHandleForReading, let fileHandleForWriting = fileHandleForWriting else { return nil } let attachment = VZFileHandleSerialPortAttachment(fileHandleForReading: fileHandleForReading, fileHandleForWriting: fileHandleForWriting) let serialConfig = VZVirtioConsoleDeviceSerialPortConfiguration() serialConfig.attachment = attachment return serialConfig } } ================================================ FILE: Configuration/UTMAppleConfigurationSharedDirectory.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 Virtualization @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) /// Represent a shared directory. This is no longer saved to config.plist in latest versions. struct UTMAppleConfigurationSharedDirectory: Codable, Hashable, Identifiable { var directoryURL: URL? var isReadOnly: Bool let id = UUID() private enum CodingKeys: String, CodingKey { case bookmark = "Bookmark" case isReadOnly = "ReadOnly" } init(directoryURL: URL?, isReadOnly: Bool = false) { self.directoryURL = directoryURL self.isReadOnly = isReadOnly } @available(macOS 12, *) init(from config: VZSharedDirectory) { self.isReadOnly = config.isReadOnly self.directoryURL = config.url } 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: .bookmark) 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: .bookmark) } @available(macOS 12, *) func vzSharedDirectory() -> VZSharedDirectory? { if let directoryURL = directoryURL { return VZSharedDirectory(url: directoryURL, readOnly: isReadOnly) } else { return nil } } @available(macOS 12, *) static func makeDirectoryShare(from sharedDirectories: [UTMAppleConfigurationSharedDirectory]) -> VZDirectoryShare { let vzSharedDirectories = sharedDirectories.compactMap { sharedDirectory in sharedDirectory.vzSharedDirectory() } let directories = vzSharedDirectories.reduce(into: [String: VZSharedDirectory]()) { (dict, share) in let lastPathComponent = share.url.lastPathComponent var name = lastPathComponent var i = 2 while dict.keys.contains(name) { name = "\(lastPathComponent) (\(i))" i += 1 } dict[name] = share } return VZMultipleDirectoryShare(directories: directories) } } // MARK: - Conversion of old config format @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationSharedDirectory { init(migrating oldShare: SharedDirectory) { directoryURL = oldShare.directoryURL isReadOnly = oldShare.isReadOnly } } ================================================ FILE: Configuration/UTMAppleConfigurationSystem.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 Virtualization /// Basic hardware settings. @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationSystem: Codable { private let bytesInMib = UInt64(1048576) static var currentArchitecture: String { #if arch(arm64) "aarch64" #elseif arch(x86_64) "x86_64" #else #error("Unsupported architecture.") #endif } var architecture: String = Self.currentArchitecture /// Number of CPU cores to emulate. Set to 0 to match the number of available cores on the host. var cpuCount: Int = 0 /// The RAM of the guest in MiB. var memorySize: Int = 4096 var boot: UTMAppleConfigurationBoot = try! .init(for: .none) var macPlatform: UTMAppleConfigurationMacPlatform? var genericPlatform: UTMAppleConfigurationGenericPlatform? enum CodingKeys: String, CodingKey { case architecture = "Architecture" case cpuCount = "CPUCount" case memorySize = "MemorySize" case boot = "Boot" case macPlatform = "MacPlatform" case genericPlatform = "GenericPlatform" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) architecture = try values.decode(String.self, forKey: .architecture) cpuCount = try values.decode(Int.self, forKey: .cpuCount) memorySize = try values.decode(Int.self, forKey: .memorySize) boot = try values.decode(UTMAppleConfigurationBoot.self, forKey: .boot) macPlatform = try values.decodeIfPresent(UTMAppleConfigurationMacPlatform.self, forKey: .macPlatform) genericPlatform = try values.decodeIfPresent(UTMAppleConfigurationGenericPlatform.self, forKey: .genericPlatform) if boot.operatingSystem == .linux && genericPlatform == nil { // fix a bug where this was not created genericPlatform = UTMAppleConfigurationGenericPlatform() } } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(architecture, forKey: .architecture) try container.encode(cpuCount, forKey: .cpuCount) try container.encode(memorySize, forKey: .memorySize) try container.encode(boot, forKey: .boot) if boot.operatingSystem == .macOS { try container.encodeIfPresent(macPlatform, forKey: .macPlatform) } else if boot.operatingSystem == .linux { try container.encodeIfPresent(genericPlatform, forKey: .genericPlatform) } } } // MARK: - Conversion of old config format @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationSystem { init(migrating oldConfig: UTMLegacyAppleConfiguration) { self.init() cpuCount = oldConfig.cpuCount memorySize = Int(oldConfig.memorySize / bytesInMib) if let oldBoot = oldConfig.bootLoader { boot = UTMAppleConfigurationBoot(migrating: oldBoot) } #if arch(arm64) if #available(macOS 12, *) { if let oldPlatform = oldConfig.macPlatform { macPlatform = UTMAppleConfigurationMacPlatform(migrating: oldPlatform) } boot.macRecoveryIpswURL = oldConfig.macRecoveryIpswURL } #endif if boot.operatingSystem == .linux { genericPlatform = UTMAppleConfigurationGenericPlatform() } } } // MARK: - Creating Apple config @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationSystem { func fillVZConfiguration(_ vzconfig: VZVirtualMachineConfiguration) throws { if cpuCount > 0 { vzconfig.cpuCount = cpuCount } else { let hostPcorePhysicalCpu = Int(Self.sysctlIntRead("hw.perflevel0.physicalcpu")) let hostPhysicalCpu = Int(Self.sysctlIntRead("hw.physicalcpu")) vzconfig.cpuCount = hostPcorePhysicalCpu > 0 ? hostPcorePhysicalCpu : hostPhysicalCpu } vzconfig.memorySize = UInt64(memorySize) * bytesInMib vzconfig.bootLoader = boot.vzBootloader() if boot.operatingSystem == .macOS { #if arch(arm64) if #available(macOS 12, *), let macPlatform = macPlatform, let platform = macPlatform.vzMacPlatform() { vzconfig.platform = platform } else { throw UTMAppleConfigurationError.platformUnsupported } #else throw UTMAppleConfigurationError.platformUnsupported #endif } if #available(macOS 12, *), let genericPlatform = genericPlatform, let platform = genericPlatform.vzGenericPlatform() { vzconfig.platform = platform } } private static func sysctlIntRead(_ name: String) -> UInt64 { var value: UInt64 = 0 var size = MemoryLayout.size sysctlbyname(name, &value, &size, nil, 0) return value } } ================================================ FILE: Configuration/UTMAppleConfigurationVirtualization.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 Virtualization /// Device settings. @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) struct UTMAppleConfigurationVirtualization: Codable { enum PointerDevice: String, CaseIterable, QEMUConstant { case disabled = "Disabled" case mouse = "Mouse" case trackpad = "Trackpad" var prettyValue: String { switch self { case .disabled: return NSLocalizedString("Disabled", comment: "UTMAppleConfigurationDevices") case .mouse: return NSLocalizedString("Generic Mouse", comment: "UTMAppleConfigurationDevices") case .trackpad: return NSLocalizedString("Mac Trackpad (macOS 13+)", comment: "UTMAppleConfigurationDevices") } } } enum KeyboardDevice: String, CaseIterable, QEMUConstant { case disabled = "Disabled" case generic = "Generic" case mac = "Mac" var prettyValue: String { switch self { case .disabled: return NSLocalizedString("Disabled", comment: "UTMAppleConfigurationDevices") case .generic: return NSLocalizedString("Generic USB", comment: "UTMAppleConfigurationDevices") case .mac: return NSLocalizedString("Mac Keyboard (macOS 14+)", comment: "UTMAppleConfigurationDevices") } } } var hasAudio: Bool = false var hasBalloon: Bool = true var hasEntropy: Bool = true var keyboard: KeyboardDevice = .disabled var pointer: PointerDevice = .disabled var hasRosetta: Bool? var hasClipboardSharing: Bool = false enum CodingKeys: String, CodingKey { case hasAudio = "Audio" case hasBalloon = "Balloon" case hasEntropy = "Entropy" case keyboard = "Keyboard" case pointer = "Pointer" case hasTrackpad = "Trackpad" case rosetta = "Rosetta" case hasClipboardSharing = "ClipboardSharing" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) hasAudio = try values.decode(Bool.self, forKey: .hasAudio) hasBalloon = try values.decode(Bool.self, forKey: .hasBalloon) hasEntropy = try values.decode(Bool.self, forKey: .hasEntropy) if let hasKeyboard = try? values.decode(Bool.self, forKey: .keyboard) { keyboard = hasKeyboard ? .generic : .disabled } else { keyboard = try values.decode(KeyboardDevice.self, forKey: .keyboard) } if let hasPointer = try? values.decode(Bool.self, forKey: .pointer) { let hasTrackpad = try values.decodeIfPresent(Bool.self, forKey: .hasTrackpad) ?? false pointer = hasTrackpad ? .trackpad : hasPointer ? .mouse : .disabled } else { pointer = try values.decode(PointerDevice.self, forKey: .pointer) } if #available(macOS 13, *) { hasRosetta = try values.decodeIfPresent(Bool.self, forKey: .rosetta) hasClipboardSharing = try values.decodeIfPresent(Bool.self, forKey: .hasClipboardSharing) ?? false } } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(hasAudio, forKey: .hasAudio) try container.encode(hasBalloon, forKey: .hasBalloon) try container.encode(hasEntropy, forKey: .hasEntropy) try container.encode(keyboard, forKey: .keyboard) try container.encode(pointer, forKey: .pointer) try container.encodeIfPresent(hasRosetta, forKey: .rosetta) try container.encode(hasClipboardSharing, forKey: .hasClipboardSharing) } } // MARK: - Conversion of old config format @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationVirtualization { init(migrating oldConfig: UTMLegacyAppleConfiguration) { self.init() hasBalloon = oldConfig.isBalloonEnabled hasEntropy = oldConfig.isEntropyEnabled if #available(macOS 12, *) { hasAudio = oldConfig.isAudioEnabled keyboard = oldConfig.isKeyboardEnabled ? .generic : .disabled pointer = oldConfig.isPointingEnabled ? .mouse : .disabled } } } // MARK: - Creating Apple config @available(iOS, unavailable, message: "Apple Virtualization not available on iOS") @available(macOS 11, *) extension UTMAppleConfigurationVirtualization { func fillVZConfiguration(_ vzconfig: VZVirtualMachineConfiguration, isMacOSGuest: Bool = false) throws { if hasBalloon && !isMacOSGuest { vzconfig.memoryBalloonDevices = [VZVirtioTraditionalMemoryBalloonDeviceConfiguration()] } if hasEntropy { vzconfig.entropyDevices = [VZVirtioEntropyDeviceConfiguration()] } if #available(macOS 12, *) { if hasAudio { let audioInputConfiguration = VZVirtioSoundDeviceConfiguration() let audioInput = VZVirtioSoundDeviceInputStreamConfiguration() audioInput.source = VZHostAudioInputStreamSource() audioInputConfiguration.streams = [audioInput] let audioOutputConfiguration = VZVirtioSoundDeviceConfiguration() let audioOutput = VZVirtioSoundDeviceOutputStreamConfiguration() audioOutput.sink = VZHostAudioOutputStreamSink() audioOutputConfiguration.streams = [audioOutput] vzconfig.audioDevices = [audioInputConfiguration, audioOutputConfiguration] } if keyboard != .disabled { vzconfig.keyboards = [VZUSBKeyboardConfiguration()] #if arch(arm64) if #available(macOS 14, *), isMacOSGuest && keyboard == .mac { vzconfig.keyboards = [VZMacKeyboardConfiguration()] } #endif } if pointer != .disabled { vzconfig.pointingDevices = [VZUSBScreenCoordinatePointingDeviceConfiguration()] #if arch(arm64) if #available(macOS 13, *), isMacOSGuest && pointer == .trackpad { // replace with trackpad device vzconfig.pointingDevices = [VZMacTrackpadConfiguration()] } #endif } } else { if hasAudio || keyboard != .disabled || pointer != .disabled { throw UTMAppleConfigurationError.featureNotSupported } } if #available(macOS 13, *) { #if arch(arm64) if hasRosetta == true { let rosettaDirectoryShare = try VZLinuxRosettaDirectoryShare() if #available(macOS 14, *) { // enable cache if possible try? rosettaDirectoryShare.setCachingOptions(.defaultUnixSocket) } let fileSystemDevice = VZVirtioFileSystemDeviceConfiguration(tag: "rosetta") fileSystemDevice.share = rosettaDirectoryShare vzconfig.directorySharingDevices.append(fileSystemDevice) } #else if hasRosetta == true { throw UTMAppleConfigurationError.rosettaNotSupported } #endif if hasClipboardSharing { let spiceClipboardAgent = VZSpiceAgentPortAttachment() spiceClipboardAgent.sharesClipboard = true let consolePort = VZVirtioConsolePortConfiguration() consolePort.name = VZSpiceAgentPortAttachment.spiceAgentPortName consolePort.attachment = spiceClipboardAgent consolePort.isConsole = false let consoleDevice = VZVirtioConsoleDeviceConfiguration() consoleDevice.ports[0] = consolePort vzconfig.consoleDevices.append(consoleDevice) } } else { if hasRosetta == true || hasClipboardSharing { throw UTMAppleConfigurationError.featureNotSupported } } } } // MARK: prepare save extension UTMAppleConfigurationVirtualization { func prepareSave(for packageURL: URL) async throws { if #available(macOS 13, *), hasRosetta == true { try await installRosetta() } } @available(macOS 13, *) private func installRosetta() async throws { #if arch(arm64) let rosettaAvailability = VZLinuxRosettaDirectoryShare.availability if rosettaAvailability == .notSupported { throw UTMAppleConfigurationError.rosettaNotSupported } else if rosettaAvailability == .notInstalled { try await VZLinuxRosettaDirectoryShare.installRosetta() } #else throw UTMAppleConfigurationError.rosettaNotSupported #endif } } ================================================ FILE: Configuration/UTMConfiguration.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 private let kUTMBundleConfigFilename = "config.plist" protocol UTMConfiguration: Codable, ObservableObject { associatedtype Drive: UTMConfigurationDrive static var oldestVersion: Int { get } static var currentVersion: Int { get } var information: UTMConfigurationInfo { get } var drives: [Drive] { get set } var backend: UTMBackend { get } func prepareSave(for packageURL: URL) async throws func saveData(to dataURL: URL) async throws -> [URL] } extension UTMConfiguration { static var oldestVersion: Int { 4 } static var currentVersion: Int { 4 } } extension CodingUserInfoKey { static var dataURL: CodingUserInfoKey { return CodingUserInfoKey(rawValue: "dataURL")! } } enum UTMBackend: String, CaseIterable, Codable { case unknown = "Unknown" case apple = "Apple" case qemu = "QEMU" } enum UTMConfigurationError: Error { case versionTooLow case versionTooHigh case invalidConfigurationValue(String) case invalidBackend case invalidDataURL case invalidDriveConfiguration case customIconInvalid case driveAlreadyExists(URL) case cannotCreateDiskImage } extension UTMConfigurationError: LocalizedError { var errorDescription: String? { switch self { case .versionTooLow: return NSLocalizedString("This configuration is too old and is not supported.", comment: "UTMConfiguration") case .versionTooHigh: return NSLocalizedString("This configuration is saved with a newer version of UTM and is not compatible with this version.", comment: "UTMConfiguration") case .invalidConfigurationValue(let value): return String.localizedStringWithFormat(NSLocalizedString("An invalid value of '%@' is used in the configuration file.", comment: "UTMConfiguration"), value) case .invalidBackend: return NSLocalizedString("The backend for this configuration is not supported.", comment: "UTMConfiguration") case .driveAlreadyExists(let url): return String.localizedStringWithFormat(NSLocalizedString("The drive '%@' already exists and cannot be created.", comment: "UTMConfiguration"), url.lastPathComponent) default: return NSLocalizedString("An internal error has occurred.", comment: "UTMConfiguration") } } } // MARK: - Configuration file parsing private final class UTMConfigurationStub: Decodable { var backend: UTMBackend var configurationVersion: Int enum CodingKeys: String, CodingKey { case backend = "Backend" case configurationVersion = "ConfigurationVersion" } required init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) backend = try values.decodeIfPresent(UTMBackend.self, forKey: .backend) ?? .unknown configurationVersion = try values.decodeIfPresent(Int.self, forKey: .configurationVersion) ?? 0 } } extension UTMConfiguration { static var dataDirectoryName: String { "Data" } static func load(from packageURL: URL) throws -> any UTMConfiguration { let scopedAccess = packageURL.startAccessingSecurityScopedResource() defer { if scopedAccess { packageURL.stopAccessingSecurityScopedResource() } } let dataURL = packageURL.appendingPathComponent(Self.dataDirectoryName) let configURL = packageURL.appendingPathComponent(kUTMBundleConfigFilename) let configData = try Data(contentsOf: configURL) let decoder = PropertyListDecoder() decoder.userInfo = [.dataURL: dataURL] let stub = try decoder.decode(UTMConfigurationStub.self, from: configData) if stub.backend == .unknown { #if os(macOS) // we might be using a legacy configuration do { // is it a legacy apple config? let legacy = try decoder.decode(UTMLegacyAppleConfiguration.self, from: configData) return UTMAppleConfiguration(migrating: legacy, dataURL: dataURL) } catch { guard case UTMAppleConfigurationError.notAppleConfiguration = error else { throw error } } #endif // is it a legacy QEMU config? let dict = try NSDictionary(contentsOf: configURL, error: ()) as! [AnyHashable : Any] let name = ConcreteVirtualMachine.virtualMachineName(for: packageURL) let legacy = UTMLegacyQemuConfiguration(dictionary: dict, name: name, path: packageURL) return UTMQemuConfiguration(migrating: legacy) } else if stub.backend == .qemu { // QEMU configuration return try decoder.decode(UTMQemuConfiguration.self, from: configData) } else if stub.backend == .apple { // Apple configuration #if os(macOS) return try decoder.decode(UTMAppleConfiguration.self, from: configData) #else throw UTMConfigurationError.invalidBackend #endif } else { throw UTMConfigurationError.invalidBackend } } func save(to packageURL: URL) async throws { let fileManager = FileManager.default // let concrete class do any pre-processing try await prepareSave(for: packageURL) // create package directory if !fileManager.fileExists(atPath: packageURL.path) { try fileManager.createDirectory(at: packageURL, withIntermediateDirectories: false) } // create data directory let dataURL = packageURL.appendingPathComponent(Self.dataDirectoryName) if !fileManager.fileExists(atPath: dataURL.path) { try fileManager.createDirectory(at: dataURL, withIntermediateDirectories: false) } // save new and existing data let existingDataURLs = try await saveData(to: dataURL) // cleanup any extra unreferenced files try await Self.cleanupAllFiles(at: dataURL, notIncluding: existingDataURLs) // create config.plist let encoder = PropertyListEncoder() encoder.outputFormat = .xml let settingsData = try encoder.encode(self) try settingsData.write(to: packageURL.appendingPathComponent(kUTMBundleConfigFilename)) } /// Check if a file has changed and if so, copy the new file to the bundle /// - Parameters: /// - sourceURL: File to copy /// - destFolderURL: Destination in bundle's data directory /// - customCopy: If non-nil, a custom copy function is invoked /// - Returns: URL of the updated item in the bundle static func copyItemIfChanged(from sourceURL: URL, to destFolderURL: URL, customCopy: ((_ sourceURL: URL, _ destURL: URL) async throws -> URL)? = nil) async throws -> URL { _ = sourceURL.startAccessingSecurityScopedResource() defer { sourceURL.stopAccessingSecurityScopedResource() } let fileManager = FileManager.default let destURL = destFolderURL.appendingPathComponent(sourceURL.lastPathComponent) // check if both are same file if fileManager.fileExists(atPath: destURL.path) { let sourceRef = try sourceURL.resourceValues(forKeys: [.fileResourceIdentifierKey]).fileResourceIdentifier let destRef = try destURL.resourceValues(forKeys: [.fileResourceIdentifierKey]).fileResourceIdentifier if sourceRef?.isEqual(destRef) ?? false { return destURL } } if let customCopy = customCopy { return try await customCopy(sourceURL, destFolderURL) } else { let newUrl = UTMData.newImage(from: sourceURL, to: destFolderURL) try await Task.detached { try FileManager.default.copyItem(at: sourceURL, to: newUrl) }.value return destURL } } private static func cleanupAllFiles(at dataURL: URL, notIncluding urls: [URL]) async throws { let fileManager = FileManager.default let existingNames = urls.map { url in url.lastPathComponent } let dataFileURLs = try fileManager.contentsOfDirectory(at: dataURL, includingPropertiesForKeys: nil) try await Task.detached { for dataFileURL in dataFileURLs { if !existingNames.contains(dataFileURL.lastPathComponent) { try FileManager.default.removeItem(at: dataFileURL) } } }.value } } ================================================ FILE: Configuration/UTMConfigurationDrive.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 /// Settings for single disk device protocol UTMConfigurationDrive: Codable, Hashable, Identifiable { /// If not removable, this is the name of the file in the bundle. var imageName: String? { get set } /// Size of the image when creating a new image (in MiB). var sizeMib: Int { get } /// If true, the drive image will be mounted as read-only. var isReadOnly: Bool { get } /// If true, a bookmark is stored in the package. var isExternal: Bool { get } /// If true, the created image will be raw format and not QCOW2. Not saved. var isRawImage: Bool { get } /// If valid, will point to the actual location of the drive image. Not saved. var imageURL: URL? { get set } /// Unique identifier for this drive var id: String { get } /// Create a new copy with a unique ID /// - Returns: Copy func clone() -> Self } extension UTMConfigurationDrive { static func == (lhs: Self, rhs: Self) -> Bool { lhs.hashValue == rhs.hashValue } /// Serial number derived from drive identifier var serial: String { String(self.id.replacingOccurrences(of: "-", with: "").prefix(20)) } } // MARK: - Saving data extension UTMConfigurationDrive { private var bytesInMib: UInt64 { 1048576 } @MainActor mutating func saveData(to dataURL: URL) async throws -> [URL] { guard !isExternal else { return [] // nothing to save } let fileManager = FileManager.default if let imageURL = imageURL { #if os(macOS) let newURL = try await UTMQemuConfiguration.copyItemIfChanged(from: imageURL, to: dataURL, customCopy: isRawImage ? nil : convertQcow2Image) #else let newURL = try await UTMQemuConfiguration.copyItemIfChanged(from: imageURL, to: dataURL) #endif self.imageName = newURL.lastPathComponent self.imageURL = newURL return [newURL] } else if imageName == nil { let newName = "\(id).\(isRawImage ? "img" : "qcow2")" let newURL = dataURL.appendingPathComponent(newName) guard !fileManager.fileExists(atPath: newURL.path) else { throw UTMConfigurationError.driveAlreadyExists(newURL) } if isRawImage { #if os(macOS) if let appleDrive = self as? UTMAppleConfigurationDrive, appleDrive.isASIF { guard #available(macOS 13, *) else { throw UTMAppleConfigurationError.featureNotSupported } try await createAsifImage(at: newURL, size: sizeMib) } else { try await createRawImage(at: newURL, size: sizeMib) } #else try await createRawImage(at: newURL, size: sizeMib) #endif } else { try await createQcow2Image(at: newURL, size: sizeMib) } self.imageName = newName self.imageURL = newURL return [newURL] } else { let existingURL = dataURL.appendingPathComponent(imageName!) return [existingURL] } } private func createRawImage(at newURL: URL, size sizeMib: Int) async throws { let size = UInt64(sizeMib) * bytesInMib try await Task.detached { guard FileManager.default.createFile(atPath: newURL.path, contents: nil, attributes: nil) else { throw UTMConfigurationError.cannotCreateDiskImage } let handle = try FileHandle(forWritingTo: newURL) try handle.truncate(atOffset: size) try handle.close() }.value } private func createQcow2Image(at newURL: URL, size sizeMib: Int) async throws { #if WITH_REMOTE fatalError("Not implemented") #else try await Task.detached { if !QEMUGenerateDefaultQcow2File(newURL as CFURL, sizeMib) { throw UTMConfigurationError.cannotCreateDiskImage } }.value #endif } #if os(macOS) @available(macOS 13, *) private func createAsifImage(at newURL: URL, size sizeMib: Int) async throws { let numBlocks = sizeMib * Int(bytesInMib) / 512 guard let asif = UTMASIFImage.sharedInstance() else { throw UTMConfigurationError.cannotCreateDiskImage } try await Task.detached { try asif.createBlank(with: newURL, numBlocks: numBlocks) }.value } private func convertQcow2Image(at sourceURL: URL, to destFolderURL: URL) async throws -> URL { let destQcow2 = UTMData.newImage(from: sourceURL, to: destFolderURL, withExtension: "qcow2") try await UTMQemuImage.convert(from: sourceURL, toQcow2: destQcow2) return destQcow2 } #endif } ================================================ FILE: Configuration/UTMConfigurationHostNetwork.swift ================================================ // // Copyright © 2024 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 /// Host network settings. struct UTMConfigurationHostNetwork: Codable, Identifiable { /// Network name var name: String /// Network UUID var uuid: String = UUID().uuidString let id = UUID() enum CodingKeys: String, CodingKey { case name = "Name" case uuid = "Uuid" } init() { self.name = uuid } init(name: String) { self.name = name } init(name: String, uuid: String) { self.name = name self.uuid = uuid } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) uuid = try values.decodeIfPresent(UUID.self, forKey: .uuid)?.uuidString ?? UUID().uuidString name = try values.decodeIfPresent(String.self, forKey: .name) ?? uuid } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(name, forKey: .name) try container.encode(uuid, forKey: .uuid) } static func parseVMware(from url: URL) -> [UTMConfigurationHostNetwork] { let accessing = url.startAccessingSecurityScopedResource() if !accessing { return [] } defer { if accessing { url.stopAccessingSecurityScopedResource() } } var currentId: String?; var currentName: String?; var currentUuid: String?; var result: [UTMConfigurationHostNetwork] = [] if let content = try? String(contentsOf: url) { for line in content.split(whereSeparator: \.isNewline) { let parts = line.split(separator: " ") if parts.count != 3 || (parts[0] != "answer" && !parts[1].starts(with: "VNET_")) { continue } let name_parts = parts[1].split(separator: "_", maxSplits: 2) if name_parts.count != 3 { continue } if currentId == nil { currentId = String(name_parts[1]) } if let id = currentId { if id != name_parts[1] { if let uuid = currentUuid { result.append(UTMConfigurationHostNetwork(name: currentName ?? "VMware vmnet\(id)", uuid: uuid)) } currentId = String(name_parts[1]) currentName = nil currentUuid = nil } if name_parts[2] == "DISPLAY_NAME" { currentName = String(parts[2]) } if name_parts[2] == "HOSTONLY_UUID" { currentUuid = String(parts[2]) } } } if let id = currentId, let uuid = currentUuid { var newNetwork = UTMConfigurationHostNetwork() newNetwork.name = if let name = currentName { name } else { "VMware vmnet\(id)" } newNetwork.uuid = uuid result.append(newNetwork) } } return result } } ================================================ FILE: Configuration/UTMConfigurationInfo.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 /// Basic information about the VM only used in listing and presenting. struct UTMConfigurationInfo: Codable { /// VM name displayed to user. var name: String = NSLocalizedString("Virtual Machine", comment: "UTMConfigurationInfo") /// Path to the icon. var iconURL: URL? /// If true, the icon is stored in the bundle. Otherwise, the icon is built-in. var isIconCustom: Bool = false /// User specified notes to be displayed when the VM is selected. var notes: String? /// Random identifier not accessible by the user. var uuid: UUID = UUID() enum CodingKeys: String, CodingKey { case name = "Name" case icon = "Icon" case isIconCustom = "IconCustom" case notes = "Notes" case uuid = "UUID" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) name = try values.decode(String.self, forKey: .name) isIconCustom = try values.decode(Bool.self, forKey: .isIconCustom) if isIconCustom { guard let dataURL = decoder.userInfo[.dataURL] as? URL else { throw UTMConfigurationError.invalidDataURL } let iconName = try values.decode(String.self, forKey: .icon) iconURL = dataURL.appendingPathComponent(iconName) } else if let iconName = try values.decodeIfPresent(String.self, forKey: .icon) { iconURL = Self.builtinIcon(named: iconName) } notes = try values.decodeIfPresent(String.self, forKey: .notes) uuid = try values.decode(UUID.self, forKey: .uuid) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(name, forKey: .name) if isIconCustom, let iconURL = iconURL { try container.encode(true, forKey: .isIconCustom) try container.encode(iconURL.lastPathComponent, forKey: .icon) } else if !isIconCustom, let name = iconURL?.deletingPathExtension().lastPathComponent { try container.encode(false, forKey: .isIconCustom) try container.encode(name, forKey: .icon) } else { try container.encode(false, forKey: .isIconCustom) } try container.encodeIfPresent(notes, forKey: .notes) try container.encode(uuid, forKey: .uuid) } static func builtinIcon(named name: String) -> URL? { Bundle.main.url(forResource: name, withExtension: "png", subdirectory: "Icons") } } // MARK: - Conversion of old config format extension UTMConfigurationInfo { init(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() name = oldConfig.name notes = oldConfig.notes if let uuidString = oldConfig.systemUUID, let uuid = UUID(uuidString: uuidString) { self.uuid = uuid } isIconCustom = oldConfig.iconCustom if isIconCustom { if let name = oldConfig.icon, let dataURL = oldConfig.existingPath { iconURL = dataURL.appendingPathComponent(name) } else { isIconCustom = false } } if !isIconCustom, let name = oldConfig.icon { iconURL = Self.builtinIcon(named: name) } } #if os(macOS) init(migrating oldConfig: UTMLegacyAppleConfiguration, dataURL: URL) { self.init() name = oldConfig.name notes = oldConfig.notes uuid = UUID() isIconCustom = oldConfig.iconCustom if isIconCustom { if let name = oldConfig.icon { iconURL = dataURL.appendingPathComponent(name) } else { isIconCustom = false } } if let name = oldConfig.icon { iconURL = Self.builtinIcon(named: name) } } #endif } // MARK: - Saving data extension UTMConfigurationInfo { @MainActor mutating func saveData(to dataURL: URL) async throws -> [URL] { // save new icon if isIconCustom, let iconURL = iconURL { let newIconURL = try await UTMQemuConfiguration.copyItemIfChanged(from: iconURL, to: dataURL) self.iconURL = newIconURL return [newIconURL] } return [] } } ================================================ FILE: Configuration/UTMConfigurationTerminal.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 /// Console mode settings. struct UTMConfigurationTerminal: Codable, Identifiable { /// Terminal color scheme. Mutually exclusive with foreground/background colors. var theme: QEMUTerminalTheme? /// Terminal foreground color if a theme is not used. var foregroundColor: String? = "#ffffff" /// Terminal background color if a theme is not used. var backgroundColor: String? = "#000000" /// Terminal text font. var font: QEMUTerminalFont = .init(rawValue: "Menlo") /// Terminal text font size. var fontSize: Int = 12 /// Command to send when the console is resized. var resizeCommand: String? /// Terminal has a blinking cursor. var hasCursorBlink: Bool = true let id = UUID() enum CodingKeys: String, CodingKey { case theme = "Theme" case foregroundColor = "ForegroundColor" case backgroundColor = "BackgroundColor" case font = "Font" case fontSize = "FontSize" case resizeCommand = "ResizeCommand" case hasCursorBlink = "CursorBlink" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) theme = try values.decodeIfPresent(QEMUTerminalTheme.self, forKey: .theme) foregroundColor = try values.decodeIfPresent(String.self, forKey: .foregroundColor) backgroundColor = try values.decodeIfPresent(String.self, forKey: .backgroundColor) font = try values.decode(QEMUTerminalFont.self, forKey: .font) fontSize = try values.decode(Int.self, forKey: .fontSize) resizeCommand = try values.decodeIfPresent(String.self, forKey: .resizeCommand) hasCursorBlink = try values.decodeIfPresent(Bool.self, forKey: .hasCursorBlink) ?? true } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) if let theme = theme { try container.encode(theme, forKey: .theme) } else { // only save colors if no theme try container.encodeIfPresent(foregroundColor, forKey: .foregroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) } try container.encode(font, forKey: .font) try container.encode(fontSize, forKey: .fontSize) try container.encodeIfPresent(resizeCommand, forKey: .resizeCommand) try container.encode(hasCursorBlink, forKey: .hasCursorBlink) } } // MARK: - Conversion of old config format extension UTMConfigurationTerminal { init(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() foregroundColor = oldConfig.consoleTextColor backgroundColor = oldConfig.consoleBackgroundColor if let fontStr = oldConfig.consoleFont { font = QEMUTerminalFont(rawValue: fontStr) } if let fontSizeNum = oldConfig.consoleFontSize { fontSize = fontSizeNum.intValue } resizeCommand = oldConfig.consoleResizeCommand hasCursorBlink = oldConfig.consoleCursorBlink } #if os(macOS) init(migrating oldConfig: UTMLegacyAppleConfiguration) { self.init() foregroundColor = oldConfig.consoleTextColor backgroundColor = oldConfig.consoleBackgroundColor if let fontStr = oldConfig.consoleFont { font = QEMUTerminalFont(rawValue: fontStr) } if let fontSizeNum = oldConfig.consoleFontSize { fontSize = fontSizeNum.intValue } resizeCommand = oldConfig.consoleResizeCommand hasCursorBlink = oldConfig.consoleCursorBlink } #endif } // MARK: - For VMConfigDisplayConsoleView extension Optional where Wrapped == UTMConfigurationTerminal { var bound: Wrapped { get { return self ?? .init() } set { self = newValue } } } ================================================ FILE: Configuration/UTMQemuConfiguration+Arguments.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 #if os(macOS) import Virtualization // for getting network interfaces #endif /// Build QEMU arguments from config @MainActor extension UTMQemuConfiguration { /// Helper function to generate a final argument /// - Parameter string: Argument fragment /// - Returns: Final argument fragment private func f(_ string: String = "") -> QEMUArgumentFragment { QEMUArgumentFragment(final: string) } /// Shared between helper and main process to store Unix sockets var socketURL: URL { #if os(iOS) || os(visionOS) return FileManager.default.temporaryDirectory #else let appGroup = Bundle.main.infoDictionary?["AppGroupIdentifier"] as? String let helper = Bundle.main.infoDictionary?["HelperIdentifier"] as? String // default to unsigned sandbox path var parentURL: URL = FileManager.default.homeDirectoryForCurrentUser parentURL.deleteLastPathComponent() parentURL.deleteLastPathComponent() parentURL.appendPathComponent(helper ?? "com.utmapp.QEMUHelper") parentURL.appendPathComponent("Data") parentURL.appendPathComponent("tmp") if let appGroup = appGroup, !appGroup.hasPrefix("invalid.") { if let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) { return containerURL } } return parentURL #endif } /// Return the socket file for communicating with SPICE var spiceSocketURL: URL { socketURL.appendingPathComponent(information.uuid.uuidString).appendingPathExtension("spice") } /// Return the socket file for communicating with SWTPM var swtpmSocketURL: URL { socketURL.appendingPathComponent(information.uuid.uuidString).appendingPathExtension("swtpm") } /// Used only if in remote server mode. var monitorPipeURL: URL { socketURL.appendingPathComponent(information.uuid.uuidString).appendingPathExtension("qmp") } /// Used only if in remote server mode. var guestAgentPipeURL: URL { socketURL.appendingPathComponent(information.uuid.uuidString).appendingPathExtension("qga") } /// Used only if in remote server mode. var spiceTlsKeyUrl: URL { socketURL.appendingPathComponent(information.uuid.uuidString).appendingPathExtension("pem") } /// Used only if in remote server mode. var spiceTlsCertUrl: URL { socketURL.appendingPathComponent(information.uuid.uuidString).appendingPathExtension("crt") } /// Used by virglrenderer to allocate shmem var shmemDirectoryURL: URL { socketURL } /// Used for placeholder images var placeholderUrl: URL { #if os(macOS) URL(fileURLWithPath: "/dev/null") #else let empty = FileManager.default.temporaryDirectory.appendingPathComponent("empty") FileManager.default.createFile(atPath: empty.path, contents: nil) return empty #endif } /// Global setting to always use file lock or not private var isUseFileLock: Bool { return UserDefaults.standard.value(forKey: "UseFileLock") == nil || UserDefaults.standard.bool(forKey: "UseFileLock") } /// Special arguments should disable use of bootindex private var shouldDisableBootIndex: Bool { // currently, we only identified this issue in PPC machines guard system.architecture == .ppc || system.architecture == .ppc64 else { return false } let arguments = parsedUserArguments for (index, arg) in arguments.enumerated() { // when user specifies '-prom-env boot-device=hd:,\yaboot' for example, it should inhibit bootindex if arg == "-prom-env" && index != arguments.count - 1 && arguments[index+1].starts(with: "boot-device=") { return true } } return false } /// Combined generated and user specified arguments. @QEMUArgumentBuilder var allArguments: [QEMUArgument] { generatedArguments userArguments } /// Only UTM generated arguments. @QEMUArgumentBuilder var generatedArguments: [QEMUArgument] { f("-L") resourceURL f() f("-S") // startup stopped spiceArguments networkArguments displayArguments serialArguments cpuArguments machineArguments architectureArguments soundArguments if isUsbUsed { usbArguments } otherInputsArguments drivesArguments sharingArguments miscArguments } /// Take user arguments and replace any quotes private var parsedUserArguments: [String] { var list = [String]() let regex = try! NSRegularExpression(pattern: "((?:[^\"\\s]*\"[^\"]*\"[^\"\\s]*)+|[^\"\\s]+)") for arg in qemu.additionalArguments { let argString = arg.string if argString.count > 0 { let range = NSRange(argString.startIndex.. any QEMUDisplayDevice { if isRemoteSpice { let rawValue = display.rawValue if rawValue.hasSuffix("-gl") { return AnyQEMUConstant(rawValue: String(rawValue.dropLast(3)))! } else if rawValue.contains("-gl-") { return AnyQEMUConstant(rawValue: String(rawValue.replacingOccurrences(of: "-gl-", with: "-")))! } else { return display } } else { return display } } private func shouldSkipDisplay(_ display: UTMQemuConfigurationDisplay) -> Bool { return display.hardware.rawValue == QEMUDisplayDevice_m68k.nubus_macfb.rawValue } @QEMUArgumentBuilder private var displayArguments: [QEMUArgument] { if displays.isEmpty { f("-nographic") } else if isSparc { // only one display supported f("-vga") displays[0].hardware if let vgaRamSize = displays[0].vgaRamMib { "vgamem_mb=\(vgaRamSize)" } f() } else { for display in displays { if !shouldSkipDisplay(display) { f("-device") filterDisplayIfRemote(display.hardware) if let vgaRamSize = displays[0].vgaRamMib { "vgamem_mb=\(vgaRamSize)" } if display.hardware.rawValue.lowercased().contains("vga") && isClassicMacNewWorld { "edid=on" } if isDisplayGLSupported(display) && isVulkanSupported { "hostmem=256M" "blob=true" "venus=true" } f() } } } } private func isDisplayGLSupported(_ display: UTMQemuConfigurationDisplay) -> Bool { display.hardware.rawValue.contains("-gl-") || display.hardware.rawValue.hasSuffix("-gl") } private var isGLSupported: Bool { displays.contains { display in isDisplayGLSupported(display) } } private var rendererBackend: UTMQEMURendererBackend { let rawValue = UserDefaults.standard.integer(forKey: "QEMURendererBackend") return UTMQEMURendererBackend(rawValue: rawValue) ?? .qemuRendererBackendDefault } private var glBackend: String { if isGLSupported && !isRemoteSpice { #if os(macOS) if rendererBackend == .qemuRendererBackendCGL { return "core" } else { return "es" } #else return "on" #endif } else { return "off" } } private var vulkanDriver: UTMQEMUVulkanDriver { let rawValue = UserDefaults.standard.integer(forKey: "QEMUVulkanDriver") return UTMQEMUVulkanDriver(rawValue: rawValue) ?? .qemuVulkanDriverDefault } private var isVulkanSupported: Bool { isGLSupported && (rendererBackend == .qemuRendererBackendAngleMetal || rendererBackend == .qemuRendererBackendDefault) && vulkanDriver != .qemuVulkanDriverDisabled } private var isSparc: Bool { system.architecture == .sparc || system.architecture == .sparc64 } private var isRemoteSpice: Bool { qemu.spiceServerPort != nil } private var isClassicMacM68K: Bool { system.architecture == .m68k && system.target.rawValue == QEMUTarget_m68k.q800.rawValue } private var isClassicMacNewWorld: Bool { [.ppc, .ppc64].contains(system.architecture) && system.target.rawValue == QEMUTarget_ppc.mac99.rawValue } @QEMUArgumentBuilder private var serialArguments: [QEMUArgument] { for i in serials.indices { f("-chardev") switch serials[i].mode { case .builtin: f("spiceport,id=term\(i),name=com.utmapp.terminal.\(i)") case .tcpClient: "socket" "id=term\(i)" "port=\(serials[i].tcpPort ?? 1234)" "host=\(serials[i].tcpHostAddress ?? "example.com")" "server=off" f() case .tcpServer: "socket" "id=term\(i)" "port=\(serials[i].tcpPort ?? 1234)" "host=\(serials[i].isRemoteConnectionAllowed == true ? "0.0.0.0" : "127.0.0.1")" "server=on" "wait=\(serials[i].isWaitForConnection == true ? "on" : "off")" f() #if os(macOS) case .ptty: f("pty,id=term\(i)") #endif } switch serials[i].target { case .autoDevice: f("-serial") f("chardev:term\(i)") case .manualDevice: f("-device") f("\(serials[i].hardware?.rawValue ?? "invalid"),chardev=term\(i)") case .monitor: f("-mon") f("chardev=term\(i),mode=readline") case .gdb: f("-gdb") f("chardev:term\(i)") } } } @QEMUArgumentBuilder private var cpuArguments: [QEMUArgument] { if system.cpu.rawValue == system.architecture.cpuType.default.rawValue { // if default and not hypervisor, we don't pass any -cpu argument for x86 and use host for ARM if isHypervisorUsed { #if arch(x86_64) if let cpu = highestIntelCPUConfigurationForHost() { f("-cpu") f(cpu) } #else f("-cpu") f("host") #endif } else if system.architecture == .aarch64 { // ARM64 QEMU does not support "-cpu default" so we hard code a sensible default f("-cpu") f("cortex-a72") } else if system.architecture == .arm { // ARM64 QEMU does not support "-cpu default" so we hard code a sensible default f("-cpu") f("cortex-a15") } else if system.architecture == .x86_64, let cpu = highestIntelCPUConfigurationForHost() { f("-cpu") f(cpu) } } else { f("-cpu") system.cpu for flag in system.cpuFlagsAdd { "+\(flag.rawValue)" } for flag in system.cpuFlagsRemove { "-\(flag.rawValue)" } f() } let emulatedCpuCount = self.emulatedCpuCount f("-smp") "cpus=\(emulatedCpuCount.1)" "sockets=1" "cores=\(emulatedCpuCount.0)" "threads=\(emulatedCpuCount.1/emulatedCpuCount.0)" f() } private static func sysctlIntRead(_ name: String) -> UInt64 { var value: UInt64 = 0 var size = MemoryLayout.size sysctlbyname(name, &value, &size, nil, 0) return value } private var emulatedCpuCount: (Int, Int) { let singleCpu = (1, 1) let hostPhysicalCpu = Int(Self.sysctlIntRead("hw.physicalcpu")) let hostLogicalCpu = Int(Self.sysctlIntRead("hw.logicalcpu")) let userCpu = system.cpuCount if userCpu > 0 || hostPhysicalCpu == 0 { return (userCpu, userCpu) // user override } // SPARC5 defaults to single CPU if isSparc { return singleCpu } #if arch(arm64) let hostPcorePhysicalCpu = Int(Self.sysctlIntRead("hw.perflevel0.physicalcpu")) let hostPcoreLogicalCpu = Int(Self.sysctlIntRead("hw.perflevel0.logicalcpu")) // in ARM we can only emulate other weak architectures let weakArchitectures: [QEMUArchitecture] = [.alpha, .arm, .aarch64, .avr, .mips, .mips64, .mipsel, .mips64el, .ppc, .ppc64, .riscv32, .riscv64, .xtensa, .xtensaeb] if weakArchitectures.contains(system.architecture) { if hostPcorePhysicalCpu > 0 { return (hostPcorePhysicalCpu, hostPcoreLogicalCpu) } else { return (hostPhysicalCpu, hostLogicalCpu) } } else { return singleCpu } #elseif arch(x86_64) // in x86 we can emulate weak on strong return (hostPhysicalCpu, hostLogicalCpu) #else return singleCpu #endif } private var isHypervisorUsed: Bool { system.architecture.hasHypervisorSupport && qemu.hasHypervisor } private var isTSOUsed: Bool { system.architecture.hasTSOSupport && qemu.hasTSO } private var isUsbUsed: Bool { system.architecture.hasUsbSupport && system.target.hasUsbSupport && input.usbBusSupport != .disabled } private var isSecureBootUsed: Bool { system.architecture.hasSecureBootSupport && system.target.hasSecureBootSupport && qemu.hasTPMDevice } @QEMUArgumentBuilder private var machineArguments: [QEMUArgument] { f("-machine") system.target f(machineProperties) if isHypervisorUsed { f("-accel") "hvf" if isTSOUsed { "tso=on" } if isVulkanSupported { "ipa-granule-size=0x1000" } f() } else { f("-accel") "tcg" if system.isForceMulticore { "thread=multi" } let tbSize = system.jitCacheSize > 0 ? system.jitCacheSize : system.memorySize / 4 "tb-size=\(tbSize)" #if WITH_JIT // use mirror mapping when we don't have JIT entitlements if !UTMCapabilities.current.contains(.hasJitEntitlements) { "split-wx=on" } #endif f() } } private var machineProperties: String { let target = system.target.rawValue let architecture = system.architecture.rawValue var properties = qemu.machinePropertyOverride ?? "" if isPcCompatible { properties = properties.appendingDefaultPropertyName("vmport", value: "off") // disable PS/2 emulation if we are not legacy input and it's not explicitly enabled if isUsbUsed && !qemu.hasPS2Controller { properties = properties.appendingDefaultPropertyName("i8042", value: "off") } #if os(macOS) if useCoreAudioBackend && sound.contains(where: { $0.hardware.rawValue == "pcspk" }) { properties = properties.appendingDefaultPropertyName("pcspk-audiodev", value: "audio1") } #endif // disable HPET because it causes issues for some OS and also hinders performance properties = properties.appendingDefaultPropertyName("hpet", value: "off") } if target == "virt" || target.hasPrefix("virt-") && !architecture.hasPrefix("riscv") { if #available(macOS 12.4, iOS 15.5, *, *) { // default highmem value is fine here } else { // a kernel panic is triggered on M1 Max if highmem=on and running < macOS 12.4 properties = properties.appendingDefaultPropertyName("highmem", value: "off") } // required to boot Windows ARM on TCG if system.architecture == .aarch64 && !isHypervisorUsed { properties = properties.appendingDefaultPropertyName("virtualization", value: "on") } // required for > 8 CPUs if system.architecture == .aarch64 && emulatedCpuCount.0 > 8 { properties = properties.appendingDefaultPropertyName("gic-version", value: "3") } } if isClassicMacM68K { if sound.contains(where: { $0.hardware.rawValue == QEMUSoundDevice_m68k.asc.rawValue }) { properties = properties.appendingDefaultPropertyName("audiodev", value: "audio0") } } if isClassicMacNewWorld { properties = properties.appendingDefaultPropertyName("via", value: "pmu") } return properties } @QEMUArgumentBuilder private var architectureArguments: [QEMUArgument] { if system.architecture == .x86_64 || system.architecture == .i386 { f("-global") f("PIIX4_PM.disable_s3=1") // applies for pc-i440fx-* types f("-global") f("ICH9-LPC.disable_s3=1") // applies for pc-q35-* types } if qemu.hasUefiBoot, let prefix = UTMQemuConfigurationQEMU.uefiImagePrefix(forArchitecture: system.architecture) { let secure = isSecureBootUsed ? "-secure" : "" let bios = resourceURL.appendingPathComponent("\(prefix)\(secure)-code.fd") let vars = qemu.efiVarsURL ?? URL(fileURLWithPath: "/\(QEMUPackageFileName.efiVariables.rawValue)") if !hasCustomBios && FileManager.default.fileExists(atPath: bios.path) { f("-drive") "if=pflash" "format=raw" "unit=0" "file.filename=" bios "file.locking=off" "readonly=on" f() f("-drive") "if=pflash" "unit=1" "file.filename=" vars if !isUseFileLock { "file.locking=off" } f() } } if isClassicMacM68K { let declrom = resourceURL.appendingPathComponent("m68k-declrom") f("-device") "nubus-virtio-mmio" "romfile=" declrom f() } if isClassicMacNewWorld { let ndrvloader = resourceURL.appendingPathComponent("ppc-ndrvloader") f("-device") "loader" "addr=0x4000000" "file=" ndrvloader f() f("-prom-env") f("boot-command=init-program go") } f("-m") system.memorySize f() } private var hasCustomBios: Bool { for drive in drives { if drive.imageType == .disk || drive.imageType == .cd { if drive.interface == .pflash { return true } } else if drive.imageType == .bios || drive.imageType == .linuxKernel { return true } } return false } private var resourceURL: URL { FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("qemu", isDirectory: true) } private var soundBackend: UTMQEMUSoundBackend { let value = UserDefaults.standard.integer(forKey: "QEMUSoundBackend") if let backend = UTMQEMUSoundBackend(rawValue: value), backend != .qemuSoundBackendMax { return backend } else { return .qemuSoundBackendDefault } } private var useCoreAudioBackend: Bool { #if os(iOS) || os(visionOS) return false #else // only support SPICE audio if we are running remotely if isRemoteSpice { return false } // pcspk doesn't work with SPICE audio if sound.contains(where: { $0.hardware.rawValue == "pcspk" }) { return true } if soundBackend == .qemuSoundBackendCoreAudio { return true } return false #endif } private func isInternalAudioDevice(_ device: any QEMUSoundDevice) -> Bool { [QEMUSoundDevice_i386.pcspk.rawValue, QEMUSoundDevice_ppc.screamer.rawValue, QEMUSoundDevice_m68k.asc.rawValue].contains(device.rawValue) } @QEMUArgumentBuilder private var soundArguments: [QEMUArgument] { if sound.isEmpty { f("-audio") f("none") } else if sound.contains(where: { $0.hardware.rawValue == "screamer" }) { #if os(iOS) || os(visionOS) f("-audio") f("none") #else // force CoreAudio backend for mac99 which only supports 44100 Hz f("-audio") f("coreaudio") #endif } if useCoreAudioBackend { f("-audiodev") "coreaudio" f("id=audio1") } f("-audiodev") "spice" f("id=audio0") // screamer has no extra device, pcspk is handled in machineProperties for _sound in sound.filter({ !isInternalAudioDevice($0.hardware) }) { f("-device") _sound.hardware if _sound.hardware.rawValue.contains("hda") { f() f("-device") if soundBackend == .qemuSoundBackendCoreAudio && useCoreAudioBackend { "hda-output" "audiodev=audio1" } else { "hda-duplex" "audiodev=audio0" } f() } else { if soundBackend == .qemuSoundBackendCoreAudio && useCoreAudioBackend { f("audiodev=audio1") } else { f("audiodev=audio0") } } } } @QEMUArgumentBuilder private var drivesArguments: [QEMUArgument] { var busInterfaceMap: [String: Int] = [:] let disableBootindex = shouldDisableBootIndex for drive in drives { let hasImage = !drive.isExternal && drive.imageURL != nil if drive.imageType == .disk || drive.imageType == .cd { driveArgument(for: drive, busInterfaceMap: &busInterfaceMap, disableBootIndex: disableBootindex) } else if hasImage { switch drive.imageType { case .bios: f("-bios") drive.imageURL! case .linuxKernel: f("-kernel") drive.imageURL! case .linuxInitrd: f("-initrd") drive.imageURL! case .linuxDtb: f("-dtb") drive.imageURL! default: f() } f() } } } private var isPcCompatible: Bool { guard system.architecture == .x86_64 || system.architecture == .i386 else { return false } return system.target.rawValue.starts(with: "pc") || system.target.rawValue == "q35" || system.target.rawValue == "isapc" } /// These machines are hard coded to have one IDE unit per bus in QEMU private var isIdeInterfaceSingleUnit: Bool { isPcCompatible || system.target.rawValue == "microvm" || system.target.rawValue == "cubieboard" || system.target.rawValue == "highbank" || system.target.rawValue == "midway" || system.target.rawValue == "xlnx_zcu102" } @QEMUArgumentBuilder private func driveArgument(for drive: UTMQemuConfigurationDrive, busInterfaceMap: inout [String: Int], disableBootIndex: Bool = false) -> [QEMUArgument] { let isRemovable = drive.imageType == .cd || drive.isExternal let isCd = drive.imageType == .cd && drive.interface != .floppy var bootindex = busInterfaceMap["boot", default: 0] var busindex = busInterfaceMap[drive.interface.rawValue, default: 0] var realInterface = QEMUDriveInterface.none if drive.interface == .ide { f("-device") if isCd { "ide-cd" } else { "ide-hd" } if drive.interfaceVersion >= 1 && !isIdeInterfaceSingleUnit { "bus=ide.\(busindex / 2)" "unit=\(busindex % 2)" } else { "bus=ide.\(busindex)" } busindex += 1 "drive=drive\(drive.id)" if !disableBootIndex { "bootindex=\(bootindex)" } bootindex += 1 f() } else if drive.interface == .scsi { var bus = "scsi" if system.architecture != .sparc && system.architecture != .sparc64 && system.architecture != .m68k { bus = "scsi0" if busindex == 0 { f("-device") f("lsi53c895a,id=scsi0") } } if system.architecture == .m68k && system.target.rawValue == QEMUTarget_m68k.virt.rawValue { bus = "scsi0" if busindex == 0 { f("-device") f("virtio-scsi-device,id=scsi0") } } f("-device") if isCd { "scsi-cd" } else { "scsi-hd" } "bus=\(bus).0" "channel=0" "scsi-id=\(busindex)" busindex += 1 "drive=drive\(drive.id)" if !disableBootIndex { "bootindex=\(bootindex)" } bootindex += 1 f() } else if drive.interface == .virtio { f("-device") if system.architecture == .s390x { "virtio-blk-ccw" } else if system.architecture == .m68k { "virtio-blk-device" } else { "virtio-blk-pci" } "drive=drive\(drive.id)" "serial=\(drive.serial)" if !disableBootIndex { "bootindex=\(bootindex)" } bootindex += 1 f() } else if drive.interface == .nvme { f("-device") "nvme" "drive=drive\(drive.id)" "serial=\(drive.id)" if !disableBootIndex { "bootindex=\(bootindex)" } bootindex += 1 f() } else if drive.interface == .usb { f("-device") // use usb 3 bus for virt system, unless using legacy input setting (this mirrors the code in argsForUsb) let isUsb3 = isUsbUsed && system.target.rawValue.hasPrefix("virt") "usb-storage" "drive=drive\(drive.id)" "removable=\(isRemovable)" if !disableBootIndex { "bootindex=\(bootindex)" } bootindex += 1 if isUsb3 { "bus=usb-bus.0" } f() } else if drive.interface == .floppy { if isPcCompatible { f("-device") "isa-fdc" "id=fdc\(busindex)" if !disableBootIndex { "bootindexA=\(bootindex)" } bootindex += 1 f() f("-device") "floppy" "unit=0" "bus=fdc\(busindex).0" busindex += 1 "drive=drive\(drive.id)" f() } else { realInterface = drive.interface } } else { realInterface = drive.interface } busInterfaceMap["boot"] = bootindex busInterfaceMap[drive.interface.rawValue] = busindex f("-drive") switch realInterface { case .ide: "if=ide" case .scsi: "if=scsi" case .sd: "if=sd" case .mtd: "if=mtd" case .floppy: "if=floppy" case .pflash: "if=pflash" default: "if=none" } if isCd { "media=cdrom" } else { "media=disk" } "id=drive\(drive.id)" if let imageURL = drive.imageURL { "file.filename=" imageURL } else if !isCd { "file.filename=" placeholderUrl } if drive.isReadOnly || isCd { if drive.imageURL != nil { "file.locking=off" } "readonly=on" } else { "discard=unmap" "detect-zeroes=unmap" } if !isUseFileLock && (!isCd || drive.imageURL != nil) { "file.locking=off" } f() } @QEMUArgumentBuilder private var usbArguments: [QEMUArgument] { if system.target.rawValue.hasPrefix("virt") { f("-device") f("nec-usb-xhci,id=usb-bus") } else { f("-usb") } if !isClassicMacNewWorld { f("-device") f("usb-tablet,bus=usb-bus.0") } if !qemu.hasPS2Controller { f("-device") f("usb-mouse,bus=usb-bus.0") f("-device") f("usb-kbd,bus=usb-bus.0") } #if WITH_USB let maxDevices = input.maximumUsbShare let buses = (maxDevices + 2) / 3 if input.usbBusSupport == .usb3_0 { var controller = "qemu-xhci" if isPcCompatible { controller = "nec-usb-xhci" } for i in 0.. (start: String, end: String, mask: String)? { guard let net = network.vlanGuestAddress else { return nil } let components = net.split(separator: "/") let address: String let binaryMask: UInt32 guard components.count >= 1 else { return nil } if components.count == 2 { var netmaskAddr = in_addr() if inet_pton(AF_INET, String(components[1]), &netmaskAddr) == 1 { binaryMask = UInt32(bigEndian: netmaskAddr.s_addr) } else { let topbits = Int(components[1]) guard let topbits = topbits, topbits >= 0 && topbits < 32 else { return nil } binaryMask = (0xFFFFFFFF as UInt32) << (32 - topbits) } } else { binaryMask = 0xFFFFFF00 } address = String(components[0]) var networkAddr = in_addr() let netmask = in_addr(s_addr: in_addr_t(bigEndian: binaryMask)) guard inet_pton(AF_INET, address, &networkAddr) == 1 else { return nil } let firstAddr = in_addr(s_addr: (in_addr_t(bigEndian: networkAddr.s_addr & netmask.s_addr) + 1).bigEndian) let lastAddr = in_addr(s_addr: (in_addr_t(bigEndian: networkAddr.s_addr | ~netmask.s_addr) - 1).bigEndian) let firstAddrStr = String(cString: inet_ntoa(firstAddr)) let lastAddrStr = String(cString: inet_ntoa(lastAddr)) let netmaskStr = String(cString: inet_ntoa(netmask)) return (network.vlanDhcpStartAddress ?? firstAddrStr, network.vlanDhcpEndAddress ?? lastAddrStr, netmaskStr) } #if os(macOS) private var defaultBridgedInterface: String { VZBridgedNetworkInterface.networkInterfaces.first?.identifier ?? "en0" } #endif @QEMUArgumentBuilder private var networkArguments: [QEMUArgument] { for i in networks.indices { if (isSparc && networks[i].hardware.rawValue == QEMUNetworkDevice_sparc.lance.rawValue) || (isClassicMacM68K && networks[i].hardware.rawValue == QEMUNetworkDevice_m68k.dp8393x.rawValue) { f("-net") "nic" if networks[i].hardware.rawValue == QEMUNetworkDevice_sparc.lance.rawValue { "model=lance" } "macaddr=\(networks[i].macAddress)" "netdev=net\(i)" f() } else { f("-device") networks[i].hardware "mac=\(networks[i].macAddress)" "netdev=net\(i)" f() } f("-netdev") var useVMnet = false #if os(macOS) if networks[i].mode == .shared { useVMnet = true "vmnet-shared" "id=net\(i)" } else if networks[i].mode == .bridged { useVMnet = true "vmnet-bridged" "id=net\(i)" "ifname=\(networks[i].bridgeInterface ?? defaultBridgedInterface)" } else if networks[i].mode == .host { useVMnet = true "vmnet-host" "id=net\(i)" if let netUuid = networks[i].hostNetUuid { "net-uuid=\(netUuid)" } } else { "user" "id=net\(i)" } #else "user" "id=net\(i)" #endif if networks[i].isIsolateFromHost { if useVMnet { "isolated=on" } else { "restrict=on" } } if useVMnet { if let subnet = parseNetworkSubnet(from: networks[i]) { "start-address=\(subnet.start)" "end-address=\(subnet.end)" "subnet-mask=\(subnet.mask)" } if let nat66prefix = networks[i].vlanGuestAddressIPv6 { "nat66-prefix=\(nat66prefix)" } } else { if let guestAddress = networks[i].vlanGuestAddress { "net=\(guestAddress)" } if let hostAddress = networks[i].vlanHostAddress { "host=\(hostAddress)" } if let guestAddressIPv6 = networks[i].vlanGuestAddressIPv6 { "ipv6-net=\(guestAddressIPv6)" } if let hostAddressIPv6 = networks[i].vlanHostAddressIPv6 { "ipv6-host=\(hostAddressIPv6)" } if let dhcpStartAddress = networks[i].vlanDhcpStartAddress { "dhcpstart=\(dhcpStartAddress)" } if let dnsServerAddress = networks[i].vlanDnsServerAddress { "dns=\(dnsServerAddress)" } if let dnsServerAddressIPv6 = networks[i].vlanDnsServerAddressIPv6 { "ipv6-dns=\(dnsServerAddressIPv6)" } if let dnsSearchDomain = networks[i].vlanDnsSearchDomain { "dnssearch=\(dnsSearchDomain)" } if let dhcpDomain = networks[i].vlanDhcpDomain { "domainname=\(dhcpDomain)" } for forward in networks[i].portForward { "hostfwd=\(forward.protocol.rawValue.lowercased()):\(forward.hostAddress ?? ""):\(forward.hostPort)-\(forward.guestAddress ?? ""):\(forward.guestPort)" } } f() } if networks.count == 0 { f("-nic") f("none") } } private var isSpiceAgentUsed: Bool { guard system.architecture.hasAgentSupport && system.target.hasAgentSupport else { return false } return sharing.hasClipboardSharing || sharing.directoryShareMode == .webdav || displays.contains(where: { $0.isDynamicResolution }) } @QEMUArgumentBuilder private var sharingArguments: [QEMUArgument] { if system.architecture.hasAgentSupport && system.target.hasAgentSupport { f("-device") f("virtio-serial") f("-device") f("virtserialport,chardev=org.qemu.guest_agent,name=org.qemu.guest_agent.0") f("-chardev") if isRemoteSpice { "pipe" "path=" guestAgentPipeURL } else { "spiceport" "name=org.qemu.guest_agent.0" } "id=org.qemu.guest_agent" f() } if isSpiceAgentUsed { f("-device") f("virtserialport,chardev=vdagent,name=com.redhat.spice.0") f("-chardev") f("spicevmc,id=vdagent,debug=0,name=vdagent") if sharing.directoryShareMode == .webdav { f("-device") f("virtserialport,chardev=charchannel1,id=channel1,name=org.spice-space.webdav.0") f("-chardev") f("spiceport,name=org.spice-space.webdav.0,id=charchannel1") } } if system.architecture.hasSharingSupport && sharing.directoryShareMode == .virtfs, let url = sharing.directoryShareUrl { f("-fsdev") "local" "id=virtfs0" "path=" url "security_model=mapped-xattr" if sharing.isDirectoryShareReadOnly { "readonly=on" } f() f("-device") if system.architecture == .s390x { "virtio-9p-ccw" } else if system.architecture == .m68k { "virtio-9p-device" } else { "virtio-9p-pci" } "fsdev=virtfs0" if isClassicMacM68K || isClassicMacNewWorld { "mount_tag=share_1" } else { "mount_tag=share" } } } private func cleanupName(_ name: String) -> String { let allowedCharacterSet = CharacterSet.alphanumerics.union(.whitespaces) let filteredString = name.components(separatedBy: allowedCharacterSet.inverted) .joined(separator: "") return filteredString } @QEMUArgumentBuilder private var miscArguments: [QEMUArgument] { f("-name") f(cleanupName(information.name)) if qemu.isDisposable { f("-snapshot") } f("-uuid") f(information.uuid.uuidString) if qemu.hasRTCLocalTime { f("-rtc") f("base=localtime") } if qemu.hasRNGDevice { f("-device") f("virtio-rng-pci") } if qemu.hasBalloonDevice { f("-device") f("virtio-balloon-pci") } if qemu.hasTPMDevice { tpmArguments } } @QEMUArgumentBuilder private var tpmArguments: [QEMUArgument] { f("-chardev") "socket" "id=chrtpm0" "path=\(swtpmSocketURL.lastPathComponent)" f() f("-tpmdev") "emulator" "id=tpm0" "chardev=chrtpm0" f() f("-device") if system.target.rawValue.hasPrefix("virt") { "tpm-crb-device" } else if system.architecture == .ppc64 { "tpm-spapr" } else { "tpm-tis" } "tpmdev=tpm0" f() } } @MainActor private extension UTMQemuConfiguration { #if arch(x86_64) func highestIntelCPUConfigurationForHost() -> String? { let cpufamily = Self.sysctlIntRead("hw.cpufamily") // source: https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/mach/machine.h switch cpufamily { case 0x78ea4fbc: return "Penryn" case 0x6b5a4cd2: return "Nehalem" case 0x573b5eec: return "Westmere" case 0x5490b78c: return "SandyBridge" case 0x1f65e835: return "IvyBridge" case 0x10b282dc: return "Haswell" case 0x582ed09c: return "Broadwell" case 0x37fc219f /* Skylake */, 0x0f817246 /* Kabylake */, 0x1cf8a03e /* Cometlake */: return "Skylake-Client" case 0x38435547 /* Icelake */: return "Icelake-Server" // client doesn't exist default: return nil } } #else func highestIntelCPUConfigurationForHost() -> String? { return "Skylake-Client" } #endif } private extension String { func appendingDefaultPropertyName(_ name: String, value: String) -> String { if !self.contains(name + "=") { return self.appending("\(self.count > 0 ? "," : "")\(name)=\(value)") } else { return self } } } ================================================ FILE: Configuration/UTMQemuConfiguration.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 /// Settings for a QEMU configuration final class UTMQemuConfiguration: UTMConfiguration { /// Basic information and icon @Published var _information: UTMConfigurationInfo = .init() /// System settings @Published var _system: UTMQemuConfigurationSystem = .init() /// Additional QEMU tweaks @Published var _qemu: UTMQemuConfigurationQEMU = .init() /// Input settings @Published var _input: UTMQemuConfigurationInput = .init() /// Sharing settings @Published var _sharing: UTMQemuConfigurationSharing = .init() /// All displays @Published var _displays: [UTMQemuConfigurationDisplay] = [] /// All drives @Published var _drives: [UTMQemuConfigurationDrive] = [] /// All network adapters @Published var _networks: [UTMQemuConfigurationNetwork] = [] /// All serial ouputs @Published var _serials: [UTMQemuConfigurationSerial] = [] /// All audio devices @Published var _sound: [UTMQemuConfigurationSound] = [] /// True if configuration is migrated from a legacy config. Not saved. private(set) var isLegacy: Bool = false var backend: UTMBackend { .qemu } enum CodingKeys: String, CodingKey { case information = "Information" case system = "System" case qemu = "QEMU" case input = "Input" case sharing = "Sharing" case displays = "Display" case drives = "Drive" case networks = "Network" case serials = "Serial" case sound = "Sound" case backend = "Backend" case configurationVersion = "ConfigurationVersion" } init() { reset() } required init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) let backend = try values.decodeIfPresent(UTMBackend.self, forKey: .backend) ?? .qemu guard backend == .qemu else { throw UTMConfigurationError.invalidBackend } let version = try values.decodeIfPresent(Int.self, forKey: .configurationVersion) ?? 0 guard version >= Self.oldestVersion else { throw UTMConfigurationError.versionTooLow } guard version <= Self.currentVersion else { throw UTMConfigurationError.versionTooHigh } _information = try values.decode(UTMConfigurationInfo.self, forKey: .information) _system = try values.decode(UTMQemuConfigurationSystem.self, forKey: .system) _qemu = try values.decode(UTMQemuConfigurationQEMU.self, forKey: .qemu) _input = try values.decode(UTMQemuConfigurationInput.self, forKey: .input) _sharing = try values.decode(UTMQemuConfigurationSharing.self, forKey: .sharing) _displays = try values.decode([UTMQemuConfigurationDisplay].self, forKey: .displays) _drives = try values.decode([UTMQemuConfigurationDrive].self, forKey: .drives) _networks = try values.decode([UTMQemuConfigurationNetwork].self, forKey: .networks) _serials = try values.decode([UTMQemuConfigurationSerial].self, forKey: .serials) _sound = try values.decode([UTMQemuConfigurationSound].self, forKey: .sound) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(_information, forKey: .information) try container.encode(_system, forKey: .system) try container.encode(_qemu, forKey: .qemu) try container.encode(_input, forKey: .input) try container.encode(_sharing, forKey: .sharing) try container.encode(_displays, forKey: .displays) try container.encode(_drives, forKey: .drives) try container.encode(_networks, forKey: .networks) try container.encode(_serials, forKey: .serials) try container.encode(_sound, forKey: .sound) try container.encode(UTMBackend.qemu, forKey: .backend) try container.encode(Self.currentVersion, forKey: .configurationVersion) } } enum UTMQemuConfigurationError: Error { case migrationFailed case uefiNotSupported } extension UTMQemuConfigurationError: LocalizedError { var errorDescription: String? { switch self { case .migrationFailed: return NSLocalizedString("Failed to migrate configuration from a previous UTM version.", comment: "UTMQemuConfigurationError") case .uefiNotSupported: return NSLocalizedString("UEFI is not supported with this architecture.", comment: "UTMQemuConfigurationError") } } } // MARK: - Public accessors @MainActor extension UTMQemuConfiguration { var information: UTMConfigurationInfo { get { _information } set { _information = newValue } } var system: UTMQemuConfigurationSystem { get { _system } set { _system = newValue } } var qemu: UTMQemuConfigurationQEMU { get { _qemu } set { _qemu = newValue } } var input: UTMQemuConfigurationInput { get { _input } set { _input = newValue } } var sharing: UTMQemuConfigurationSharing { get { _sharing } set { _sharing = newValue } } var displays: [UTMQemuConfigurationDisplay] { get { _displays } set { _displays = newValue } } var drives: [UTMQemuConfigurationDrive] { get { _drives } set { _drives = newValue } } var networks: [UTMQemuConfigurationNetwork] { get { _networks } set { _networks = newValue } } var serials: [UTMQemuConfigurationSerial] { get { _serials } set { _serials = newValue } } var sound: [UTMQemuConfigurationSound] { get { _sound } set { _sound = newValue } } } // MARK: - Defaults extension UTMQemuConfiguration { private func reset(all: Bool = true) { if all { _information = .init() _system = .init() _drives = [] } _qemu = .init() _input = .init() _sharing = .init() _displays = [] _networks = [] _serials = [] _sound = [] } @MainActor func reset(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) { reset(all: false) qemu = .init(forArchitecture: architecture, target: target) input = .init(forArchitecture: architecture, target: target) sharing = .init(forArchitecture: architecture, target: target) system.cpu = architecture.cpuType.default if let display = UTMQemuConfigurationDisplay(forArchitecture: architecture, target: target) { displays = [display] } else { serials = [UTMQemuConfigurationSerial()] } if let network = UTMQemuConfigurationNetwork(forArchitecture: architecture, target: target) { networks = [network] } if let _sound = UTMQemuConfigurationSound(forArchitecture: architecture, target: target) { sound = [_sound] } } } // MARK: - Conversion of old config format extension UTMQemuConfiguration { convenience init(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() isLegacy = true _information = .init(migrating: oldConfig) _system = .init(migrating: oldConfig) _qemu = .init(migrating: oldConfig) _input = .init(migrating: oldConfig) _sharing = .init(migrating: oldConfig) if let display = UTMQemuConfigurationDisplay(migrating: oldConfig) { _displays = [display] } _drives = (0.. [URL] { var existingDataURLs = [URL]() existingDataURLs += try await _information.saveData(to: dataURL) existingDataURLs += try await _qemu.saveData(to: dataURL, for: system) for i in 0.. QEMUScaler? { if str == "linear" { return .linear } else if str == "nearest" { return .nearest } else { return nil } } } ================================================ FILE: Configuration/UTMQemuConfigurationDrive.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 /// Settings for single QEMU disk device struct UTMQemuConfigurationDrive: UTMConfigurationDrive { static let latestInterfaceVersion = 1 /// If not removable, this is the name of the file in the bundle. var imageName: String? /// Size of the image when creating a new image (in MiB). Not saved. var sizeMib: Int = 0 /// If true, the drive image will be mounted as read-only. var isReadOnly: Bool = false /// If true, a bookmark is stored in the package. var isExternal: Bool = false /// If valid, will point to the actual location of the drive image. Not saved. var imageURL: URL? /// Unique identifier for this drive private(set) var id: String = UUID().uuidString /// Type of the image. var imageType: QEMUDriveImageType = .none /// Interface of the image (only valid when type is CD/Disk). var interface: QEMUDriveInterface = .none /// Interface version for backwards compatibility var interfaceVersion: Int = Self.latestInterfaceVersion /// If true, the created image will be raw format and not QCOW2. Not saved. var isRawImage: Bool = false /// If initialized, returns a default interface for an image type. Not saved. var defaultInterfaceForImageType: ((QEMUDriveImageType) -> QEMUDriveInterface)? enum CodingKeys: String, CodingKey { case imageName = "ImageName" case imageType = "ImageType" case interface = "Interface" case interfaceVersion = "InterfaceVersion" case identifier = "Identifier" case isReadOnly = "ReadOnly" } init() { } init(from decoder: Decoder) throws { guard let dataURL = decoder.userInfo[.dataURL] as? URL else { throw UTMConfigurationError.invalidDataURL } let values = try decoder.container(keyedBy: CodingKeys.self) if let imageName = try values.decodeIfPresent(String.self, forKey: .imageName) { self.imageName = imageName imageURL = dataURL.appendingPathComponent(imageName) isExternal = false } else { isExternal = true } isReadOnly = try values.decodeIfPresent(Bool.self, forKey: .isReadOnly) ?? isExternal imageType = try values.decode(QEMUDriveImageType.self, forKey: .imageType) interface = try values.decode(QEMUDriveInterface.self, forKey: .interface) interfaceVersion = try values.decodeIfPresent(Int.self, forKey: .interfaceVersion) ?? 0 id = try values.decode(String.self, forKey: .identifier) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) if !isExternal { try container.encodeIfPresent(imageURL?.lastPathComponent, forKey: .imageName) } try container.encode(isReadOnly, forKey: .isReadOnly) try container.encode(imageType, forKey: .imageType) if imageType == .cd || imageType == .disk { try container.encode(interface, forKey: .interface) } else { try container.encode(QEMUDriveInterface.none, forKey: .interface) } try container.encode(interfaceVersion, forKey: .interfaceVersion) try container.encode(id, forKey: .identifier) } func hash(into hasher: inout Hasher) { imageName?.hash(into: &hasher) sizeMib.hash(into: &hasher) isReadOnly.hash(into: &hasher) isExternal.hash(into: &hasher) id.hash(into: &hasher) imageType.hash(into: &hasher) interface.hash(into: &hasher) interfaceVersion.hash(into: &hasher) isRawImage.hash(into: &hasher) } func clone() -> UTMQemuConfigurationDrive { var cloned = self cloned.id = UUID().uuidString return cloned } } // MARK: - Default interface extension UTMQemuConfigurationDrive { static func defaultInterface(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget, imageType: QEMUDriveImageType) -> QEMUDriveInterface { let rawTarget = target.rawValue if rawTarget.hasPrefix("virt-") || rawTarget == "virt" || rawTarget.hasPrefix("pseries") { if imageType == .cd { return .usb } else { return .virtio } } else if architecture == .sparc || architecture == .sparc64 || architecture == .m68k { return .scsi } else { return .ide } } } // MARK: - Conversion of old config format extension UTMQemuConfigurationDrive { init(migrating oldConfig: UTMLegacyQemuConfiguration, at index: Int) { self.init() imageName = oldConfig.driveImagePath(for: index) imageType = convertImageType(from: oldConfig.driveImageType(for: index)) interface = convertInterface(from: oldConfig.driveInterfaceType(for: index)) interfaceVersion = 0 isExternal = oldConfig.driveRemovable(for: index) isReadOnly = isExternal var oldId = oldConfig.driveName(for: index) ?? UUID().uuidString if oldId.hasPrefix("drive") { oldId.removeFirst(5) } if oldId.isEmpty { oldId = UUID().uuidString } id = oldId let dataURL = oldConfig.existingPath?.appendingPathComponent(QEMUPackageFileName.images.rawValue) if let imageName = imageName { imageURL = dataURL?.appendingPathComponent(imageName) } } private func convertImageType(from type: UTMDiskImageType) -> QEMUDriveImageType { switch type { case .none: return .none case .disk: return .disk case .CD: return .cd case .BIOS: return .bios case .kernel: return .linuxKernel case .initrd: return .linuxInitrd case .DTB: return .linuxDtb case .max: return .none @unknown default: return .none } } private func convertInterface(from str: String?) -> QEMUDriveInterface { if str == "ide" { return .ide } else if str == "scsi" { return .scsi } else if str == "sd" { return .sd } else if str == "mtd" { return .mtd } else if str == "floppy" { return .floppy } else if str == "pflash" { return .pflash } else if str == "virtio" { return .virtio } else if str == "nvme" { return .nvme } else if str == "usb" { return .usb } else { return .none } } } // MARK: - New drive extension UTMQemuConfigurationDrive { init(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget, isExternal: Bool = false) { self.isExternal = isExternal self.imageType = isExternal ? .cd : .disk self.isRawImage = false self.imageName = nil self.sizeMib = 10240 self.isReadOnly = isExternal self.imageURL = nil self.id = UUID().uuidString self.defaultInterfaceForImageType = { Self.defaultInterface(forArchitecture: architecture, target: target, imageType: $0) } self.interface = defaultInterfaceForImageType!(imageType) self.interfaceVersion = Self.latestInterfaceVersion } } ================================================ FILE: Configuration/UTMQemuConfigurationInput.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 /// Settings for input devices and USB. struct UTMQemuConfigurationInput: Codable { /// Level of USB support (disabled/2.0/3.0). var usbBusSupport: QEMUUSBBus = .usb2_0 /// If enabled, USB forwarding can be used (if supported by the host). var hasUsbSharing: Bool = false /// The maximum number of USB devices that can be forwarded concurrently. var maximumUsbShare: Int = 3 enum CodingKeys: String, CodingKey { case usbBusSupport = "UsbBusSupport" case hasUsbSharing = "UsbSharing" case maximumUsbShare = "MaximumUsbShare" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) usbBusSupport = try values.decode(QEMUUSBBus.self, forKey: .usbBusSupport) hasUsbSharing = try values.decode(Bool.self, forKey: .hasUsbSharing) maximumUsbShare = try values.decode(Int.self, forKey: .maximumUsbShare) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(usbBusSupport, forKey: .usbBusSupport) try container.encode(hasUsbSharing, forKey: .hasUsbSharing) try container.encode(maximumUsbShare, forKey: .maximumUsbShare) } } // MARK: - Default construction extension UTMQemuConfigurationInput { init(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) { self.init() let rawTarget = target.rawValue if !architecture.hasUsbSupport || !target.hasUsbSupport { usbBusSupport = .disabled } else if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("q35") { usbBusSupport = .usb3_0 } else if (architecture == .arm || architecture == .aarch64) && (rawTarget.hasPrefix("virt-") || rawTarget == "virt") { usbBusSupport = .usb3_0 } } } // MARK: - Conversion of old config format extension UTMQemuConfigurationInput { init(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() if oldConfig.inputLegacy { usbBusSupport = .disabled } else if oldConfig.usb3Support { usbBusSupport = .usb3_0 } else { usbBusSupport = .usb2_0 } if let sharingNum = oldConfig.usbRedirectionMaximumDevices { hasUsbSharing = true maximumUsbShare = sharingNum.intValue } } } ================================================ FILE: Configuration/UTMQemuConfigurationNetwork.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 /// Network settings for a single device. struct UTMQemuConfigurationNetwork: Codable, Identifiable { /// Operating mode of this adapter var mode: QEMUNetworkMode = .emulated /// Hardware model to emulate. var hardware: any QEMUNetworkDevice = QEMUNetworkDevice_x86_64.e1000 /// Unique MAC address. var macAddress: String = UTMQemuConfigurationNetwork.randomMacAddress() /// If true, will attempt to isolate the host in the guest VLAN. var isIsolateFromHost: Bool = false /// List of forwarded ports. var portForward: [UTMQemuConfigurationPortForward] = [] /// In bridged mode this is the physical interface to bridge. var bridgeInterface: String? /// Guest IPv4 for emulated VLAN. var vlanGuestAddress: String? /// Guest IPv6 for emulated VLAN. var vlanGuestAddressIPv6: String? /// Host IPv4 for emulated VLAN. var vlanHostAddress: String? /// Host IPv6 for emulated VLAN. var vlanHostAddressIPv6: String? /// DHCP start address for emulated VLAN. var vlanDhcpStartAddress: String? /// DHCP end address for Apple VLAN var vlanDhcpEndAddress: String? /// DHCP domain for emulated VLAN. var vlanDhcpDomain: String? /// DNS server for emulated VLAN. var vlanDnsServerAddress: String? /// DNS server (IPv6) for emulated VLAN. var vlanDnsServerAddressIPv6: String? /// DNS search domain for emulated VLAN. var vlanDnsSearchDomain: String? /// Network UUID to attach to in host mode var hostNetUuid: String? /// Can be set to be displayed to the user. Not saved. var currentIpAddresses: [String] = [] let id = UUID() /// Generate a random MAC address /// - Returns: A random MAC address static func randomMacAddress() -> String { var bytes = (0..<6).map { _ in arc4random() % 256 } // byte 0 should be local bytes[0] = (bytes[0] & 0xFC) | 0x2 let string = bytes.reduce("") { partialResult, byte in partialResult + String(format: ":%02X", byte) } return String(string.dropFirst()) } enum CodingKeys: String, CodingKey { case mode = "Mode" case hardware = "Hardware" case macAddress = "MacAddress" case isIsolateFromHost = "IsolateFromHost" case portForward = "PortForward" case bridgeInterface = "BridgeInterface" case vlanGuestAddress = "VlanGuestAddress" case vlanGuestAddressIPv6 = "VlanGuestAddressIPv6" case vlanHostAddress = "VlanHostAddress" case vlanHostAddressIPv6 = "VlanHostAddressIPv6" case vlanDhcpStartAddress = "VlanDhcpStartAddress" case vlanDhcpEndAddress = "VlanDhcpEndAddress" case vlanDhcpDomain = "VlanDhcpDomain" case vlanDnsServerAddress = "VlanDnsServerAddress" case vlanDnsServerAddressIPv6 = "VlanDnsServerAddressIPv6" case vlanDnsSearchDomain = "VlanDnsSearchDomain" case hostNetUuid = "HostNetUuid" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) mode = try values.decode(QEMUNetworkMode.self, forKey: .mode) hardware = try values.decode(AnyQEMUConstant.self, forKey: .hardware) macAddress = try values.decode(String.self, forKey: .macAddress) isIsolateFromHost = try values.decode(Bool.self, forKey: .isIsolateFromHost) portForward = try values.decode([UTMQemuConfigurationPortForward].self, forKey: .portForward) bridgeInterface = try values.decodeIfPresent(String.self, forKey: .bridgeInterface) vlanGuestAddress = try values.decodeIfPresent(String.self, forKey: .vlanGuestAddress) vlanGuestAddressIPv6 = try values.decodeIfPresent(String.self, forKey: .vlanGuestAddressIPv6) vlanHostAddress = try values.decodeIfPresent(String.self, forKey: .vlanHostAddress) vlanHostAddressIPv6 = try values.decodeIfPresent(String.self, forKey: .vlanHostAddressIPv6) vlanDhcpStartAddress = try values.decodeIfPresent(String.self, forKey: .vlanDhcpStartAddress) vlanDhcpEndAddress = try values.decodeIfPresent(String.self, forKey: .vlanDhcpEndAddress) vlanDhcpDomain = try values.decodeIfPresent(String.self, forKey: .vlanDhcpDomain) vlanDnsServerAddress = try values.decodeIfPresent(String.self, forKey: .vlanDnsServerAddress) vlanDnsServerAddressIPv6 = try values.decodeIfPresent(String.self, forKey: .vlanDnsServerAddressIPv6) vlanDnsSearchDomain = try values.decodeIfPresent(String.self, forKey: .vlanDnsSearchDomain) hostNetUuid = try values.decodeIfPresent(UUID.self, forKey: .hostNetUuid)?.uuidString } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(mode, forKey: .mode) try container.encode(hardware.asAnyQEMUConstant(), forKey: .hardware) try container.encode(macAddress, forKey: .macAddress) try container.encode(isIsolateFromHost, forKey: .isIsolateFromHost) try container.encode(portForward, forKey: .portForward) if mode == .bridged { try container.encodeIfPresent(bridgeInterface, forKey: .bridgeInterface) } try container.encodeIfPresent(vlanGuestAddress, forKey: .vlanGuestAddress) try container.encodeIfPresent(vlanGuestAddressIPv6, forKey: .vlanGuestAddressIPv6) try container.encodeIfPresent(vlanHostAddress, forKey: .vlanHostAddress) try container.encodeIfPresent(vlanHostAddressIPv6, forKey: .vlanHostAddressIPv6) try container.encodeIfPresent(vlanDhcpStartAddress, forKey: .vlanDhcpStartAddress) try container.encodeIfPresent(vlanDhcpEndAddress, forKey: .vlanDhcpEndAddress) try container.encodeIfPresent(vlanDhcpDomain, forKey: .vlanDhcpDomain) try container.encodeIfPresent(vlanDnsServerAddress, forKey: .vlanDnsServerAddress) try container.encodeIfPresent(vlanDnsServerAddressIPv6, forKey: .vlanDnsServerAddressIPv6) try container.encodeIfPresent(vlanDnsSearchDomain, forKey: .vlanDnsSearchDomain) if mode == .host { try container.encodeIfPresent(hostNetUuid, forKey: .hostNetUuid) } } } // MARK: - Default construction extension UTMQemuConfigurationNetwork { init?(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) { self.init() let rawTarget = target.rawValue if rawTarget.hasPrefix("pc") { if architecture == .i386 { hardware = QEMUNetworkDevice_i386.ne2k_isa } else { hardware = QEMUNetworkDevice_x86_64.rtl8139 } } else if rawTarget.hasPrefix("q35") { hardware = QEMUNetworkDevice_x86_64.e1000 } else if rawTarget == "isapc" { hardware = QEMUNetworkDevice_x86_64.ne2k_isa } else if rawTarget.hasPrefix("virt-") || rawTarget == "virt" { hardware = QEMUNetworkDevice_aarch64.virtio_net_pci } else if [.ppc, .ppc64].contains(architecture) && rawTarget == QEMUTarget_ppc.mac99.rawValue { hardware = QEMUNetworkDevice_ppc.sungem } else if architecture == .m68k && rawTarget == QEMUTarget_m68k.q800.rawValue { hardware = QEMUNetworkDevice_m68k.dp8393x } else { let cards = architecture.networkDeviceType.allRawValues if let first = cards.first { hardware = AnyQEMUConstant(rawValue: first)! } else { return nil } } #if os(macOS) mode = .shared #else mode = .emulated #endif } } // MARK: - Conversion of old config format extension UTMQemuConfigurationNetwork { init?(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() guard oldConfig.networkEnabled else { return nil } guard let oldMode = convertMode(from: oldConfig.networkMode) else { return nil } mode = oldMode if let hardwareStr = oldConfig.networkCard { hardware = AnyQEMUConstant(rawValue: hardwareStr)! } if let macString = oldConfig.networkCardMac { macAddress = macString } isIsolateFromHost = oldConfig.networkIsolate bridgeInterface = oldConfig.networkBridgeInterface vlanGuestAddress = oldConfig.networkAddress vlanGuestAddressIPv6 = oldConfig.networkAddressIPv6 vlanHostAddress = oldConfig.networkHost vlanHostAddressIPv6 = oldConfig.networkHostIPv6 vlanDhcpStartAddress = oldConfig.networkDhcpStart vlanDhcpDomain = oldConfig.networkDhcpDomain vlanDnsServerAddress = oldConfig.networkDnsServer vlanDnsServerAddressIPv6 = oldConfig.networkDnsServerIPv6 vlanDnsSearchDomain = oldConfig.networkDnsSearch for i in 0.. QEMUNetworkMode? { if str == "emulated" { return .emulated } else if str == "shared" { return .shared } else if str == "host" { return .host } else if str == "bridged" { return .bridged } else { return nil } } } ================================================ FILE: Configuration/UTMQemuConfigurationPortForward.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 /// Represent a single port forward struct UTMQemuConfigurationPortForward: Codable, Identifiable, Hashable { /// Socket protocol var `protocol`: QEMUNetworkProtocol = .tcp /// Host address (nil for any address). var hostAddress: String? /// Host port to recieve connection. var hostPort: Int = 0 /// Guest address (nil for any address). var guestAddress: String? /// Guest port where connection is coming from. var guestPort: Int = 0 let id = UUID() enum CodingKeys: String, CodingKey { case `protocol` = "Protocol" case hostAddress = "HostAddress" case hostPort = "HostPort" case guestAddress = "GuestAddress" case guestPort = "GuestPort" } enum CodingKeysOld: String, CodingKey { case `protocol` = "protocol" case hostAddress = "hostAddress" case hostPort = "hostPort" case guestAddress = "guestAddress" case guestPort = "guestPort" } init() { } init(from decoder: Decoder) throws { do { let values = try decoder.container(keyedBy: CodingKeys.self) `protocol` = try values.decode(QEMUNetworkProtocol.self, forKey: .protocol) hostAddress = try values.decodeIfPresent(String.self, forKey: .hostAddress) hostPort = try values.decode(Int.self, forKey: .hostPort) guestAddress = try values.decodeIfPresent(String.self, forKey: .guestAddress) guestPort = try values.decode(Int.self, forKey: .guestPort) } catch is DecodingError { // before UTM v4.4, we mistakingly used camel-case in the config.plist let values = try decoder.container(keyedBy: CodingKeysOld.self) `protocol` = try values.decode(QEMUNetworkProtocol.self, forKey: .protocol) hostAddress = try values.decodeIfPresent(String.self, forKey: .hostAddress) hostPort = try values.decode(Int.self, forKey: .hostPort) guestAddress = try values.decodeIfPresent(String.self, forKey: .guestAddress) guestPort = try values.decode(Int.self, forKey: .guestPort) } } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(`protocol`, forKey: .protocol) try container.encodeIfPresent(hostAddress, forKey: .hostAddress) try container.encode(hostPort, forKey: .hostPort) try container.encodeIfPresent(guestAddress, forKey: .guestAddress) try container.encode(guestPort, forKey: .guestPort) } func hash(into hasher: inout Hasher) { id.hash(into: &hasher) } } // MARK: - Conversion of old config format extension UTMQemuConfigurationPortForward { init(migrating oldForward: UTMLegacyQemuConfigurationPortForward) { self.init() if let oldProtocol = convertProtocol(from: oldForward.protocol) { `protocol` = oldProtocol } hostAddress = oldForward.hostAddress if let portNum = oldForward.guestPort { hostPort = portNum.intValue } guestAddress = oldForward.guestAddress if let portNum = oldForward.guestPort { guestPort = portNum.intValue } } private func convertProtocol(from str: String?) -> QEMUNetworkProtocol? { if str == "tcp" { return .tcp } else if str == "udp" { return .udp } else { return nil } } } ================================================ FILE: Configuration/UTMQemuConfigurationQEMU.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 System /// Tweaks and advanced QEMU settings. struct UTMQemuConfigurationQEMU: Codable { /// Where to store the debug log. File may not exist yet. This property is not saved to file. var debugLogURL: URL? /// EFI variables if EFI boot is enabled. This property is not saved to file. var efiVarsURL: URL? /// TPM data file if TPM is enabled. This property is not saved to file. var tpmDataURL: URL? /// If true, write standard output to debug.log in the VM bundle. var hasDebugLog: Bool = false /// If true, use UEFI boot on supported architectures. var hasUefiBoot: Bool = false /// If true, create a virtio-rng device on supported targets. var hasRNGDevice: Bool = false /// If true, create a virtio-balloon device on supported targets. var hasBalloonDevice: Bool = false /// If true, create a vTPM device with an emulated backend. var hasTPMDevice: Bool = false /// If true, use HVF hypervisor instead of TCG emulation. var hasHypervisor: Bool = false /// If true, enable total store ordering. var hasTSO: Bool = false /// If true, attempt to sync RTC with the local time. var hasRTCLocalTime: Bool = false /// If true, emulate a PS/2 controller instead of relying on USB emulation. var hasPS2Controller: Bool = false /// QEMU machine property that overrides the default property defined by UTM. var machinePropertyOverride: String? /// Additional QEMU arguments. var additionalArguments: [QEMUArgument] = [] /// If true, changes to the VM will not be committed to disk. Not saved. var isDisposable: Bool = false /// Set to true to request UEFI variable reset. Not saved. var isUefiVariableResetRequested: Bool = false /// Set to open a port for remote SPICE session. Not saved. var spiceServerPort: UInt16? /// If true, all SPICE channels will be over TLS. Not saved. var isSpiceServerTlsEnabled: Bool = false /// Set to a password shared with the client. Not saved. var spiceServerPassword: String? /// When resetting UEFI vars, also set up Secure Boot keys var hasPreloadedSecureBootKeys: Bool = false enum CodingKeys: String, CodingKey { case hasDebugLog = "DebugLog" case hasUefiBoot = "UEFIBoot" case hasRNGDevice = "RNGDevice" case hasBalloonDevice = "BalloonDevice" case hasTPMDevice = "TPMDevice" case hasHypervisor = "Hypervisor" case hasTSO = "TSO" case hasRTCLocalTime = "RTCLocalTime" case hasPS2Controller = "PS2Controller" case machinePropertyOverride = "MachinePropertyOverride" case additionalArguments = "AdditionalArguments" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) hasDebugLog = try values.decode(Bool.self, forKey: .hasDebugLog) hasUefiBoot = try values.decode(Bool.self, forKey: .hasUefiBoot) hasRNGDevice = try values.decode(Bool.self, forKey: .hasRNGDevice) hasBalloonDevice = try values.decode(Bool.self, forKey: .hasBalloonDevice) hasTPMDevice = try values.decode(Bool.self, forKey: .hasTPMDevice) hasHypervisor = try values.decode(Bool.self, forKey: .hasHypervisor) hasTSO = try values.decodeIfPresent(Bool.self, forKey: .hasTSO) ?? false hasRTCLocalTime = try values.decode(Bool.self, forKey: .hasRTCLocalTime) hasPS2Controller = try values.decode(Bool.self, forKey: .hasPS2Controller) machinePropertyOverride = try values.decodeIfPresent(String.self, forKey: .machinePropertyOverride) additionalArguments = try values.decode([QEMUArgument].self, forKey: .additionalArguments) if let dataURL = decoder.userInfo[.dataURL] as? URL { debugLogURL = dataURL.appendingPathComponent(QEMUPackageFileName.debugLog.rawValue) efiVarsURL = dataURL.appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue) tpmDataURL = dataURL.appendingPathComponent(QEMUPackageFileName.tpmData.rawValue) } } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(hasDebugLog, forKey: .hasDebugLog) try container.encode(hasUefiBoot, forKey: .hasUefiBoot) try container.encode(hasRNGDevice, forKey: .hasRNGDevice) try container.encode(hasBalloonDevice, forKey: .hasBalloonDevice) try container.encode(hasTPMDevice, forKey: .hasTPMDevice) try container.encode(hasHypervisor, forKey: .hasHypervisor) try container.encode(hasTSO, forKey: .hasTSO) try container.encode(hasRTCLocalTime, forKey: .hasRTCLocalTime) try container.encode(hasPS2Controller, forKey: .hasPS2Controller) try container.encodeIfPresent(machinePropertyOverride, forKey: .machinePropertyOverride) try container.encode(additionalArguments, forKey: .additionalArguments) } static func uefiImagePrefix(forArchitecture architecture: QEMUArchitecture, isVars: Bool = false) -> String? { switch architecture { case .arm: return "edk2-arm" case .aarch64: return isVars ? "edk2-arm" : "edk2-aarch64" case .i386: return "edk2-i386" case .x86_64: return isVars ? "edk2-i386" : "edk2-x86_64" case .loongarch64: return "edk2-loongarch64" case .riscv64: return "edk2-riscv" default: return nil } } } // MARK: - Default construction extension UTMQemuConfigurationQEMU { init(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) { self.init() let rawTarget = target.rawValue if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("q35") { hasUefiBoot = true hasRNGDevice = true } else if Self.uefiImagePrefix(forArchitecture: architecture) != nil && (rawTarget.hasPrefix("virt-") || rawTarget == "virt") { hasUefiBoot = true hasRNGDevice = true } hasHypervisor = architecture.hasHypervisorSupport } } // MARK: - Conversion of old config format extension UTMQemuConfigurationQEMU { init(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() hasDebugLog = oldConfig.debugLogEnabled hasUefiBoot = oldConfig.systemBootUefi hasRNGDevice = oldConfig.systemRngEnabled hasHypervisor = oldConfig.useHypervisor hasRTCLocalTime = oldConfig.rtcUseLocalTime hasPS2Controller = oldConfig.forcePs2Controller machinePropertyOverride = oldConfig.systemMachineProperties if let oldAddArgs = oldConfig.systemArguments { additionalArguments = oldAddArgs.map({ QEMUArgument($0) }) } debugLogURL = oldConfig.existingPath?.appendingPathComponent(QEMUPackageFileName.debugLog.rawValue) efiVarsURL = oldConfig.existingPath?.appendingPathComponent(UTMLegacyQemuConfiguration.diskImagesDirectory).appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue) } } // MARK: - Saving data extension UTMQemuConfigurationQEMU { @MainActor mutating func saveData(to dataURL: URL, for system: UTMQemuConfigurationSystem) async throws -> [URL] { var existing: [URL] = [] if hasUefiBoot { let fileManager = FileManager.default // save EFI variables let resourceURL = Bundle.main.url(forResource: "qemu", withExtension: nil)! let templateVarsURL: URL let secure = hasPreloadedSecureBootKeys ? "-secure" : "" if let prefix = Self.uefiImagePrefix(forArchitecture: system.architecture, isVars: true) { templateVarsURL = resourceURL.appendingPathComponent("\(prefix)\(secure)-vars.fd") } else { throw UTMQemuConfigurationError.uefiNotSupported } let varsURL = dataURL.appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue) let isExisting = fileManager.fileExists(atPath: varsURL.path) if !isExisting || isUefiVariableResetRequested { try await Task.detached { if isExisting { try FileManager.default.removeItem(at: varsURL) } try FileManager.default.copyItem(at: templateVarsURL, to: varsURL) let permissions: FilePermissions = [.ownerReadWrite, .groupRead, .otherRead] try FileManager.default.setAttributes([.posixPermissions: permissions.rawValue], ofItemAtPath: varsURL.path) }.value isUefiVariableResetRequested = false hasPreloadedSecureBootKeys = false } efiVarsURL = varsURL existing.append(varsURL) } let possibleTpmDataURL = dataURL.appendingPathComponent(QEMUPackageFileName.tpmData.rawValue) if hasTPMDevice { tpmDataURL = possibleTpmDataURL existing.append(tpmDataURL!) } else if FileManager.default.fileExists(atPath: possibleTpmDataURL.path) { existing.append(possibleTpmDataURL) // do not delete any existing TPM data } if hasDebugLog { let debugLogURL = dataURL.appendingPathComponent(QEMUPackageFileName.debugLog.rawValue) existing.append(debugLogURL) } return existing } } ================================================ FILE: Configuration/UTMQemuConfigurationSerial.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 Combine /// Settings for single serial device struct UTMQemuConfigurationSerial: Codable, Identifiable { /// The back-end character device (host controlled). var mode: QEMUSerialMode = .builtin /// The front-end serial port target (guest controlled). var target: QEMUSerialTarget = .autoDevice /// Terminal settings for built-in mode. var terminal: UTMConfigurationTerminal? = .init() /// Hardware model to emulate (for manual mode). var hardware: (any QEMUSerialDevice)? /// Path to PTTY (determined after VM starts). Not saved. var pttyDevice: URL? /// TCP server to connect to (for TCP client mode). var tcpHostAddress: String? /// TCP port to listed on or connect to (for TCP client/server mode). var tcpPort: Int? /// Applies only to TCP targets. If true, will wait for connection before starting VM. var isWaitForConnection: Bool? /// Applies only to TCP server. If true, the port will be listened on all interfaces. var isRemoteConnectionAllowed: Bool? let id = UUID() enum CodingKeys: String, CodingKey { case mode = "Mode" case target = "Target" case terminal = "Terminal" case hardware = "Hardware" case tcpHostAddress = "TcpHostAddress" case tcpPort = "TcpPort" case isWaitForConnection = "WaitForConnection" case isRemoteConnectionAllowed = "RemoteConnectionAllowed" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) mode = try values.decode(QEMUSerialMode.self, forKey: .mode) target = try values.decode(QEMUSerialTarget.self, forKey: .target) terminal = try values.decodeIfPresent(UTMConfigurationTerminal.self, forKey: .terminal) hardware = try values.decodeIfPresent(AnyQEMUConstant.self, forKey: .hardware) tcpHostAddress = try values.decodeIfPresent(String.self, forKey: .tcpHostAddress) tcpPort = try values.decodeIfPresent(Int.self, forKey: .tcpPort) isWaitForConnection = try values.decodeIfPresent(Bool.self, forKey: .isWaitForConnection) isRemoteConnectionAllowed = try values.decodeIfPresent(Bool.self, forKey: .isRemoteConnectionAllowed) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(mode, forKey: .mode) try container.encode(target, forKey: .target) try container.encodeIfPresent(hardware?.asAnyQEMUConstant(), forKey: .hardware) // only save relevant settings switch mode { case .builtin: try container.encodeIfPresent(terminal, forKey: .terminal) case .tcpClient: try container.encodeIfPresent(tcpHostAddress, forKey: .tcpHostAddress) try container.encodeIfPresent(tcpPort, forKey: .tcpPort) case .tcpServer: try container.encodeIfPresent(tcpPort, forKey: .tcpPort) try container.encodeIfPresent(isWaitForConnection, forKey: .isWaitForConnection) try container.encodeIfPresent(isRemoteConnectionAllowed, forKey: .isRemoteConnectionAllowed) default: break } } } // MARK: - Default construction extension UTMQemuConfigurationSerial { init?(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) { self.init() } } // MARK: - Conversion of old config format extension UTMQemuConfigurationSerial { init?(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() guard oldConfig.displayConsoleOnly else { return nil } terminal = UTMConfigurationTerminal(migrating: oldConfig) } } ================================================ FILE: Configuration/UTMQemuConfigurationSharing.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 /// Directory and clipboard sharing settings struct UTMQemuConfigurationSharing: Codable { /// SPICE or virtfs sharing. var directoryShareMode: QEMUFileShareMode = .none /// Sharing should be read only var isDirectoryShareReadOnly: Bool = false /// The directory to share. Not saved. var directoryShareUrl: URL? /// SPICE clipboard sharing. var hasClipboardSharing: Bool = false enum CodingKeys: String, CodingKey { case directoryShareMode = "DirectoryShareMode" case isDirectoryShareReadOnly = "DirectoryShareReadOnly" case hasClipboardSharing = "ClipboardSharing" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) directoryShareMode = try values.decode(QEMUFileShareMode.self, forKey: .directoryShareMode) isDirectoryShareReadOnly = try values.decode(Bool.self, forKey: .isDirectoryShareReadOnly) hasClipboardSharing = try values.decode(Bool.self, forKey: .hasClipboardSharing) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(directoryShareMode, forKey: .directoryShareMode) try container.encode(isDirectoryShareReadOnly, forKey: .isDirectoryShareReadOnly) try container.encode(hasClipboardSharing, forKey: .hasClipboardSharing) } } // MARK: - Default construction extension UTMQemuConfigurationSharing { init(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) { self.init() let rawTarget = target.rawValue if !architecture.hasAgentSupport { hasClipboardSharing = false } if !architecture.hasSharingSupport { directoryShareMode = .none } // overrides for specific configurations if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("q35") { directoryShareMode = .webdav hasClipboardSharing = true } else if (architecture == .arm || architecture == .aarch64) && (rawTarget.hasPrefix("virt-") || rawTarget == "virt") { directoryShareMode = .webdav hasClipboardSharing = true } else if architecture == .m68k && rawTarget == QEMUTarget_m68k.q800.rawValue { directoryShareMode = .virtfs } else if [.ppc, .ppc64].contains(architecture) && rawTarget == QEMUTarget_ppc.mac99.rawValue { directoryShareMode = .virtfs } } } // MARK: - Conversion of old config format extension UTMQemuConfigurationSharing { init(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() if oldConfig.shareDirectoryEnabled { directoryShareMode = .webdav } isDirectoryShareReadOnly = oldConfig.shareDirectoryReadOnly hasClipboardSharing = oldConfig.shareClipboardEnabled } } ================================================ FILE: Configuration/UTMQemuConfigurationSound.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 /// Settings for single audio device struct UTMQemuConfigurationSound: Codable, Identifiable { /// Hardware model to emulate. var hardware: any QEMUSoundDevice = QEMUSoundDevice_x86_64.AC97 let id = UUID() enum CodingKeys: String, CodingKey { case hardware = "Hardware" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) hardware = try values.decode(AnyQEMUConstant.self, forKey: .hardware) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(hardware.asAnyQEMUConstant(), forKey: .hardware) } } // MARK: - Default construction extension UTMQemuConfigurationSound { init?(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) { self.init() let rawTarget = target.rawValue if rawTarget.hasPrefix("pc") || rawTarget == "isapc" { hardware = QEMUSoundDevice_i386.sb16 } else if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("pseries") { hardware = QEMUSoundDevice_x86_64.AC97 } else if rawTarget.hasPrefix("q35") || rawTarget.hasPrefix("virt-") || rawTarget == "virt" { hardware = QEMUSoundDevice_x86_64.intel_hda } else if rawTarget == "mac99" { hardware = QEMUSoundDevice_ppc.screamer } else if architecture == .m68k && rawTarget == QEMUTarget_m68k.q800.rawValue { hardware = QEMUSoundDevice_m68k.asc } else { let cards = architecture.soundDeviceType.allRawValues if let first = cards.first { hardware = AnyQEMUConstant(rawValue: first)! } else { return nil } } } } // MARK: - Conversion of old config format extension UTMQemuConfigurationSound { init?(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() guard oldConfig.soundEnabled else { return nil } if oldConfig.soundCard == "ac97" { // change in case for this one device hardware = AnyQEMUConstant(rawValue: "AC97")! } else if let hardwareStr = oldConfig.soundCard { hardware = AnyQEMUConstant(rawValue: hardwareStr)! } } } ================================================ FILE: Configuration/UTMQemuConfigurationSystem.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 /// Basic hardware settings. struct UTMQemuConfigurationSystem: Codable { /// The QEMU architecture to emulate. var architecture: QEMUArchitecture = .x86_64 /// The QEMU machine target to emulate. var target: any QEMUTarget = QEMUTarget_x86_64.q35 /// The QEMU CPU to emulate. Note that `default` will use the default CPU for the architecture. var cpu: any QEMUCPU = QEMUCPU_x86_64.default /// Optional list of CPU flags to add to the target CPU. var cpuFlagsAdd: [any QEMUCPUFlag] = [] /// Optional list of CPU flags to remove from the defaults of the target CPU. Parsed after `cpuFlagsAdd`. var cpuFlagsRemove: [any QEMUCPUFlag] = [] /// Number of CPU cores to emulate. Set to 0 to match the number of available cores on the host. var cpuCount: Int = 0 /// Set to true to force emulation on multiple cores even when the results may be incorrect. var isForceMulticore: Bool = false /// The RAM of the guest in MiB. var memorySize: Int = 512 /// The JIT cache (code cache) in MiB. var jitCacheSize: Int = 0 enum CodingKeys: String, CodingKey { case architecture = "Architecture" case target = "Target" case cpu = "CPU" case cpuFlagsAdd = "CPUFlagsAdd" case cpuFlagsRemove = "CPUFlagsRemove" case cpuCount = "CPUCount" case isForceMulticore = "ForceMulticore" case memorySize = "MemorySize" case jitCacheSize = "JITCacheSize" } init() { } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) architecture = try values.decode(QEMUArchitecture.self, forKey: .architecture) target = try values.decode(architecture.targetType, forKey: .target) do { cpu = try values.decode(architecture.cpuType, forKey: .cpu) } catch UTMConfigurationError.invalidConfigurationValue(let value) { logger.warning("Unable to decode CPU '\(value)', resetting to default CPU") cpu = architecture.cpuType.default } cpuFlagsAdd = try values.decode([AnyQEMUConstant].self, forKey: .cpuFlagsAdd) cpuFlagsRemove = try values.decode([AnyQEMUConstant].self, forKey: .cpuFlagsRemove) cpuCount = try values.decode(Int.self, forKey: .cpuCount) isForceMulticore = try values.decode(Bool.self, forKey: .isForceMulticore) memorySize = try values.decode(Int.self, forKey: .memorySize) jitCacheSize = try values.decode(Int.self, forKey: .jitCacheSize) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(architecture, forKey: .architecture) try container.encode(target.asAnyQEMUConstant(), forKey: .target) try container.encode(cpu.asAnyQEMUConstant(), forKey: .cpu) try container.encode(cpuFlagsAdd.map({ flag in flag.asAnyQEMUConstant() }), forKey: .cpuFlagsAdd) try container.encode(cpuFlagsRemove.map({ flag in flag.asAnyQEMUConstant() }), forKey: .cpuFlagsRemove) try container.encode(cpuCount, forKey: .cpuCount) try container.encode(isForceMulticore, forKey: .isForceMulticore) try container.encode(memorySize, forKey: .memorySize) try container.encode(jitCacheSize, forKey: .jitCacheSize) } } // MARK: - Conversion of old config format extension UTMQemuConfigurationSystem { init(migrating oldConfig: UTMLegacyQemuConfiguration) { self.init() if let archStr = oldConfig.systemArchitecture, let arch = QEMUArchitecture(rawValue: archStr) { architecture = arch } if let targetStr = oldConfig.systemTarget { target = architecture.targetType.init(rawValue: targetStr) ?? architecture.targetType.default } if let cpuStr = oldConfig.systemCPU { cpu = architecture.cpuType.init(rawValue: cpuStr) ?? architecture.cpuType.default } if let cpuCountNum = oldConfig.systemCPUCount { cpuCount = cpuCountNum.intValue } if let oldFlags = oldConfig.systemCPUFlags { for oldFlag in oldFlags { var newFlag = oldFlag let isAdd: Bool if oldFlag.starts(with: "-") { newFlag.removeFirst() isAdd = false } else if oldFlag.starts(with: "+") { newFlag.removeFirst() isAdd = true } else { isAdd = true } let flag = AnyQEMUConstant(rawValue: newFlag)! if isAdd { cpuFlagsAdd.append(flag) } else { cpuFlagsRemove.append(flag) } } } isForceMulticore = oldConfig.systemForceMulticore if let memoryNum = oldConfig.systemMemory { memorySize = memoryNum.intValue } if let jitCacheNum = oldConfig.systemJitCacheSize { jitCacheSize = jitCacheNum.intValue } } } ================================================ FILE: Documentation/Architecture.md ================================================ # Architecture UTM is built upon several pieces of technology, layered to provide compatibility across various host configurations. Below is a simplified diagram of key pieces of UTM with additional details provided below. ``` ┌────────────────────┬──────────────────────┐ │ iOS VM Display │ macOS VM Display │ ├────────────────────┴──────────────────────┤ │ SwiftUI │ ├───────────────────────────────────────────┤ │ UTMVirtualMachine │ ├────────────────┬──────────────────────────┤ │ CocoaSpice │ │ ├────────────────┤ Virtualization.framework │ │ QEMU (TCG/HVF) │ │ └────────────────┴──────────────────────────┘ ``` ## QEMU The backbone of UTM is QEMU, which provides the emulation and virtualization engine. We run a custom [fork][1] which includes several features such as: * Building QEMU as a shared library * APRR support for jailbroken iOS * ARM64 TCTI from @ktemkin (JIT-less iOS support) * SPICE ANGLE backend for hardware GL acceleration These features, along with several others (which are undergoing code review and may not have made the latest stable release), allow our fork to be optimized for Darwin. ### Hypervisor.framework QEMU includes support for the `hvf` accelerator which provides same architecture virtualization (x86 -> x86 or ARM64 -> ARM64) on macOS. This framework is not available on iOS. ### UTMQemu QEMU is linked as a shared library. On iOS, there is no ability to use `fork`, XPC (directly), or any other way of launching a new process. As a result, we run the QEMU main loop in a pthread which for all intents and purposes work like normal (the key exception being that you cannot spawn multiple instances of QEMU and since QEMU does not properly clean up resources, you cannot re-launch QEMU). On macOS, XPC is used to launch QEMU in a new process. `UTMQemu` manages the pthread or XPC implementation. #### XPC Helper On macOS, spawning new processes is permitted but due to App Sandbox security requirements, we need some additional "bootstrapping" code to launch QEMU properly. The added benefit is that we only have to provide a single bundle identifier for the "launcher" executable rather than a different identifier for each QEMU executable (required for App Sandbox). `QEMUHelper` is an XPC helper with its own App Sandbox separate from the UTM main application. This improves security by providing an additional layer of separation. However, due to this extra care has to be taken when passing file handles and other system resources from the main app. For example, the Unix socket file used to communicate with SPICE is stored in a shared App Group directory. For disk images and shared directories that cannot be stored in the App Group, we have to do a complicated sandbox dance to get the right access permissions. 1. The main application opens a `NSOpenPanel`, allowing the user to select a file/directory outside the sandbox. This returns a `NSURL` with the right security scope attached. If we take a regular bookmark of `NSURL` and pass it through XPC, the XPC process should also have access once it reads the bookmark back into a `NSURL`. 2. However, the access to that file is only valid while the app is open. As soon as you close it, the app loses those permissions and must either prompt the user to select the file again or store a "security scoped bookmark." The issue here is that a security scoped bookmark is only valid for the sandbox that created it. If we take a security scoped bookmark and pass it directly to the XPC process, it cannot get back a `NSURL`. 3. So the solution is to take a *standard* bookmark, pass it to the XPC process, have the XPC process then create a *security scoped* bookmark and pass it back to the main process. The main process can now store this bookmark and have it work as intended when it passes it to the XPC process next launch. The XPC helper spawns `QEMULauncher` with an inherited sandbox. This means it can access files that are accessible to the helper XPC. The launcher process is what runs QEMU. When a new file is opened (for example a new disk image is mounted), the main application will pass a bookmark to the helper XPC where it will call `-startAccessingSecurityScopedResource` which also applies to the child process (`QEMULauncher`). This way, QEMU does not have to have any knowledge of the App Sandbox. ### UTMConfiguration VM configuration is stored in a PLIST format. This PLIST maps to either a `UTMQemuConfiguration` or `UTMAppleConfiguration` structure which stores the underlying configuration data in a `Codable` interface for easy serialization. ### UTMQemuSystem `UTMQemuSystem` maps `UTMQemuConfiguration` to command line arguments used to launch QEMU. ### UTMQemuManager After a VM is launched, `UTMQemuManager` provides run-time services though the QMP protocol. These services include stopping/pausing/resuming the VM, taking snapshots, switching between mouse and tablet, mounting removable disk images, and more. The underlying transport for QMP is JSON (over a socket), so `UTMJSONStream` marshals the data to and from `NSDictionary` objects. #### QAPI QMP protocol is defined by the QAPI schema which is provided as a set of JSON files in QEMU. QEMU uses these JSON files to generate wrapper C functions for internal usage. UTM includes a modified function generator derived from QEMU's own script (`qapi-gen.py`) along with modified QAPI C visitors (for `NSDictionary`). This allows UTM to use the same commands, structures, and events that QEMU uses in a transparent way. For example, when UTM makes a call to some QAPI command such as `qmp_blockdev_change_medium`, the generated C functions will automatically marshal the function arguments into a `NSDictionary` object which `UTMJSONStream` converts into JSON and sends it over the QMP socket. When a response is received, `UTMJSONStream` converts the JSON into a `NSDictionary` object, which goes through the generated C functions to unmarshal into some C structure which is returned from `qmp_blockdev_change_medium`. This is all transparent to the caller as long as they understand that the function call will block until the response is received so it must not be called from the main thread. ## Virtualization.framework On Apple Silicon Macs running macOS 12 or later, `Virtualization.framework` is provided by Apple to run macOS 12 guests. ### UTMAppleConfiguration As the backend is different, the configuration format UTM uses is also different and is represented in `UTMAppleConfiguration`. As this configuration is handed in Swift, the Codable protocol is used for serialization instead of a `NSDictionary` backing used in `UTMQemuConfiguration`. The Codable backing is more extendible as it allows more complex data to be represented without a lot of boilerplate. ## CocoaSpice UTM uses the SPICE front-end with QEMU because it has more versatility than VNC to handle things like USB forwarding, multiple displays, and the ability to use a SPICE agent running on the guest to share clipboard and change the resolution. [CocoaSpice][2] is provided as a Swift package and acts as Cocoa/Objective-C bindings for SPICE GTK. CocoaSpice also provides a bridge between the Pixman framebuffer that SPICE uses and Metal textures that is used by MetalKit to render to screen. ### UTMSpiceIO `UTMSpiceIO` connects `CocoaSpice` to UTM and is used by `UTMQemuVirtualMachine` to control the SPICE client and respond to client events. ## UTMVirtualMachine `UTMVirtualMachine` provides file I/O operations for creating and saving .utm VM bundles as well as controls for the platform-specific layer above to do high level tasks like starting and stopping the VM. It is highest level of the "backend", providing a platform independent view of UTM virtual machines. ### UTMQemuVirtualMachine This subclass manages QEMU+CocoaSpice backend VMs. ### UTMAppleVirtualMachine This subclass manages Apple Virtualization.framework backend VMs. ## Frontend ### SwiftUI The frontend for UTM is designed mostly in SwiftUI 2.0. That means the minimum supported operating system is iOS 14 and macOS 11 and is the main reason there are no plans to back-port UTM to earlier versions. Most views are designed to work on both macOS and iOS. #### UTMData `UTMData` is a SwiftUI `ObservableObject` that contains the "state" and is the "single source of truth" for the home view. It stores the list of VMs and functions to create, modify, move, etc VMs on that list. `UTMConfigurable` provides the state for VM configuration views. ### iOS VM Display The VM display uses UIKit as SwiftUI is not mature enough to do everything UTM needs. This includes the custom keyboard accessory view implemented in a NIB for emulating keys that are not available on the standard iOS keyboard. ### macOS VM Display On macOS, the VM display uses AppKit for similar reasons above. [1]: https://github.com/utmapp/qemu [2]: https://github.com/utmapp/CocoaSpice ================================================ FILE: Documentation/Dependencies.md ================================================ # Dependencies UTM is built upon QEMU, SPICE, and various libraries that those projects depend on. To support building as an Xcode project, we designed a custom build system that creates Xcode compatible frameworks from autoconf and meson projects. ## `build_dependencies.sh` The build script sets up a build environment for the target platform and architecture. ``` Usage: [VARIABLE...] build_dependencies.sh [-p platform] [-a architecture] [-q qemu_path] [-d] [-r] -p platform Target platform. Default ios. [ios|ios_simulator|ios-tci|ios_simulator-tci|macos] -a architecture Target architecture. Default arm64. [armv7|armv7s|arm64|i386|x86_64] -q qemu_path Do not download QEMU, use qemu_path instead. -d, --download Force re-download of source even if already downloaded. -r, --rebuild Avoid cleaning build directory. VARIABLEs are: SDKVERSION Target a specific SDK version. CHOST Configure host, set if not deducable by ARCH. CFLAGS CPPFLAGS CXXFLAGS LDFLAGS ``` The build steps are summarized below: 1. It will attempt to detect if your build system has all the required tools before starting. 2. All source archives in [patches/sources](../patches/sources) are downloaded if not found. If the download is a Git repository, it is cloned and the right commit is checked out. 3. If found, the `.patch` file in [patches](../patches/) with the corresponding name is applied to each download. 4. Each dependency is configured, built, and installed to the sysroot directory. 5. Once all libraries are built, they are converted to a .framework. The id and library dependencies are patched to be relative to @rpath (using `install_name_tool`). 6. The QAPI sources are generated using [scripts/qapi-gen.py](../scripts/qapi-gen.py). ## Updating dependencies ### QEMU The steps for updating QEMU is the most involved. UTM maintains a [fork][1] of QEMU which the updated QEMU version must be merged into. This will be the most time consuming part as the fork needs to build and run correctly outside of UTM. Next, the QAPI generator for UTM needs to be updated with the changes from QEMU. The UTM [QAPI script](../scripts/qapi/) is derived from QEMU's `scripts/qapi/*`. Many of the files are unchanged and copied directly from QEMU. However, the key files (commands.py, events.py, types.py) are heavily modified. The best way to approach this is to do a 3-way diff with the UTM files, the version of QEMU where those files are derived from, and the new version of the scripts. Then take the changes from the old version of QEMU to the new version of QEMU and merge it into UTM. For files where there are no changes between UTM and QEMU, the new version from QEMU can be copied to directly. For files where there are changes, some work is required to integrate the changes. From experience, it may be easiest to do incremental changes from QEMU's commits. Also, QAPI does not change often so it is not required to update the scripts after each QEMU update. As a result of the above, the [QAPI support files](../qapi/) may also need to be updated. Check with QEMU `qapi/*.c`'s commit history to see if there's any changes needed there. It will usually correspond to changes in the Python generator code. [UTMQemuConfiguration+ConstantsGenerated.m](../Configuration/UTMQemuConfiguration+ConstantsGenerated.m) needs to be updated by running [const-gen.py](../scripts/const-gen.py). You need to build the [UTM fork of QEMU][1] for macOS and pass the build directory as an argument to const-gen. It will then run each QEMU executable in order to parse the help text to find changes in device support. If QEMU adds or removes a supported architecture, this must be manually changed in the const-gen script. Finally, make sure to rename the [binary patches](../patches/data) directory to the new QEMU version. The code patch for the previous QEMU version can be deleted if all the changes have been integrated into the UTM fork of QEMU. ### Others The other dependencies are more straightforward. Take the latest release tarball and re-integrate the UTM patches if needed. The UTM [GitHub][2] will usually keep forks of projects it depends on with required patches. The UTM changes should be rebased off of the commit corresponding to the latest release of the project. Then `git format-patch` can be used to generate the patch file which will be applied to the release tarball. [1]: https://github.com/utmapp/qemu [2]: https://github.com/utmapp ================================================ FILE: Documentation/Graphics.md ================================================ # Graphics The graphics architecture of UTM involves many separate translation layers. ### GPU Acceleration ``` ┌────────────────────────────────────────────────┐ │ Host │ │ ┌────────────────────────────────┬───────────┐ │ ┌──┼─► virglrenderer │ +Venus† │ gfxstream†│ │ │ │ │ │ │ │ │ │ │ ├──────────┬──────────┬──────────┴───────────┤ │ ┌─────────────────────┐ │ │ │ ANGLE │ ANGLE │ MoltenVK† │ │ │ Guest │ Q │ │ Metal │ OpenGL │ │ │ │ ┌─────────────────┐ │ E │ ├──────────┴──────────┴──────────────────────┤ │ │ │ Userland 3D API │ │ M │ │ CocoaSpice Metal Renderer │ │ │ │ (e.g. Mesa) │ │ U │ │ │ │ │ ├─────────────────┤ │ │ │ ├────────────────────────────────────────────┤ │ │ │ Kernel Driver │ │ │ │ │ Metal Device │ │ │ │ (virtio-gpu) ├─┼───┘ │ │ │ │ │ └─────────────────┘ │ │ └────────────────────────────────────────────┘ │ │ │ │ │ └─────────────────────┘ └────────────────────────────────────────────────┘ ``` †: Future work that is not currently in UTM. ### No GPU Acceleration ``` ┌───────────────────────────────┐ │ Host │ │ ┌─────────────┬─────────────┐ │ ┌─────────────────────┐ ┌──┼─► pixman │ pixman │ │ │ Guest │ │ │ │ EGL Canvas │ Pixel Buffer│ │ │ │ Q │ ├─────────────┴─────────────┤ │ │ │ E │ │ CocoaSpice Metal Renderer │ │ │ │ M │ │ │ │ │ ┌─────────────────┐ │ U │ ├───────────────────────────┤ │ │ │ Framebuffer │ │ │ │ │ Metal Device │ │ │ │ ├─┼───┘ │ │ │ │ │ └─────────────────┘ │ │ └───────────────────────────┘ │ │ │ │ │ └─────────────────────┘ └───────────────────────────────┘ ``` ## Guest Side When GPU acceleration is available, the guest userland will translate the graphics API (OpenGL, Vulkan, etc) to kernel driver commands. The commands goes through QEMU through the VirtIO interface to be decoded by the host. If GPU acceleration is not available, it is typically due to one or more of the following: * The VirtIO GPU device is not used or is not available on the guest architecture * The guest drivers for VirtIO GPU are not available or are incomplete (as is the case with Windows) * The guest userland component (e.g. Mesa) is incompatible with the host side libraries (due to a bug or a missing feature) * The guest application attempts to use a graphics API feature that is not supported by the host side libraries When GPU acceleration is missing, if a `-gl` display hardware is used, then QEMU will handle the blit operations directly to a EGL canvas. This will be slight faster and have lower latency than the alternative, which is for CocoaSpice to do the blit operation AND render to screen. This is why it is worth selecting a `-gl` device even if there is no guest driver support. ## virglrenderer [virglrenderer][1] is the host side library that decodes the draw commands from the guest and calls into OpenGL (on the host side). [Venus][2] is a newer addition to virglrenderer that allows the guest to pass Vulkan commands to the host. ## gfxstream [gfxstream][3] is an alternative library that allows the guest to serialize OpenGL and Vulkan commands, pass them through a communication channel ("pipe") to the host, and the host will deserialize and evaluate the calls. It differs from virglrenderer in that there is no intermediate translation (guest Mesa -> virgl commands -> host OpenGL). Currently this technology is used for Google's Android emulator and not by mainline QEMU so it will take some time for UTM to adopt the code. ## ANGLE [ANGLE][4] is an implementation of OpenGL ES on top of other graphics APIs. UTM uses three ANGLE backends: 1. On macOS, the `cgl` (Core OpenGL) backend is provided 2. On iOS, the `eagl` backend is provided 3. For both macOS and iOS, the `metal` backend is provided The three backends have differing compatibility and there is no "best" backend. QEMU uses ANGLE to draw into an IOSurface instead of directly to screen. ## MoltenVK [MoltenVK][5] is used to translate Vulkan to Metal because Apple devices do not support Vulkan natively. MoltenVK is currently not used in UTM. ## CocoaSpice [CocoaSpice][6] renders the IOSurface as a texture directly to screen with Metal APIs. It also controls the frame time by synchronizing to the display's vblank signal to reduce tearing. As an optimization, CocoaSpice renderer will only draw the last update before a vblank which means that if the guest is drawing multiple times per monitor refresh, the host will consolidate the draws to a single Metal call. On macOS, the IOSurface is passed from QEMULauncher (rendered in a separate process) through a global `IOSurfaceID`. On iOS, because there is no process separation, the IOSurface reference is passed directly from QEMU to CocoaSpice. UTM uses SPICE as a QEMU frontend, which means that all input/output goes through SPICE. SPICE was designed to work remotely over the network but when operating remotely, GPU acceleration is not supported. Instead, all pixel buffer updates must be sent from QEMU which is why it is slower than the EGL canvas rendering. # Debugging Tips ANGLE has an option to enable tracing all GL calls. You can modify `scripts/build_dependencies.sh` to add the following arguments to the ANGLE build: ``` --args angle_enable_trace=true angle_enable_trace_events=true ``` By default, the trace logs are set to the device syslog. If you want it to show up in stderr (especially to sync with log items from other components), modify `src/common/debug.cpp` and change the line `#elif defined(ANGLE_PLATFORM_APPLE)` to `#elif defined(ANGLE_PLATFORM_APPLE_NOT_DEFINED)` as well as the `fprintf` after it to `fprintf(stderr, "%s: %s\n", LogSeverityName(severity),` (in order to force stderr to always be used). virglrenderer also can print debug output. In order to enable it, modify `scripts/build_dependencies.sh` to include `--buildtype debug` to the Meson call. Then you have to add the environment variable `VREND_DEBUG=all` to the process. The easiest way to do that is to modify `UTMQemuSystem.m` and add it to the `setRendererBackend:` method. To enable MoltenVK debug output, modify `scripts/build_dependencies.sh` and change the call to `make $platform` in `build_moltenvk()` to `make ${platform}-debug`. [1]: https://gitlab.freedesktop.org/virgl/virglrenderer [2]: https://www.collabora.com/news-and-blog/blog/2021/11/26/venus-on-qemu-enabling-new-virtual-vulkan-driver/ [3]: https://android.googlesource.com/device/generic/vulkan-cereal/ [4]: https://chromium.googlesource.com/angle/angle [5]: https://github.com/KhronosGroup/MoltenVK [6]: https://github.com/utmapp/CocoaSpice ================================================ FILE: Documentation/MacDevelopment.md ================================================ # macOS Development Because UTM is a sand-boxed Mac app, there are a few extra steps needed for a proper development environment. ## Getting the Source Make sure you perform a recursive clone to get all the submodules: ```sh git clone --recursive https://github.com/utmapp/UTM.git ``` Alternatively, run the following after cloning if you did not do a recursive clone. ```sh git submodule update --init --recursive ``` ## Dependencies The easy way is to get the prebuilt dependencies from [GitHub Actions][1]. Pick the latest release and download all of the `Sysroot-macos-*` artifacts. You need to be logged in to GitHub to download artifacts. If you only intend to run locally, it is alright to just download the sysroot for your architecture. After downloading the prebuilt artifacts of your choice, extract them to the root directory where you cloned the repository. To build UTM, make sure you have the latest version of Xcode installed. ### Building Dependencies (Advanced) If you want to build the dependencies yourself, it is highly recommended that you start with a fresh macOS VM. This is because some of the dependencies attempt to use `/usr/local/lib` even though the architecture does not match. Certain installed packages like `libusb`, `gawk`, and `cmake` will break the build. 1. Install Xcode command line and [Homebrew][1] 2. Install the following build prerequisites ```sh brew install bison pkg-config gettext glib-utils libgpg-error nasm meson ``` ```sh pip3 install six pyparsing ``` Make sure to add `bison` to your `$PATH` environment variable! ```sh export PATH=/usr/local/opt/bison/bin:/opt/homebrew/opt/bison/bin:$PATH ``` 3. Run ```sh ./scripts/build_dependencies.sh -p macos -a ARCH ``` where `ARCH` is either `arm64` or `x86_64`. If you want to build universal binaries, you need to run `build_dependencies.sh` for both `arm64` and `x86_64` and then run ```sh ./scripts/pack_dependencies.sh . macos arm64 x86_64 ``` If you are developing QEMU and wish to pass in a custom path to QEMU, you can use the `-q PATH_TO_QEMU_SOURCE` option to `build_dependencies.sh`. Note that you need to use a UTM compatible fork of QEMU. ## Building UTM ### Command Line You can build UTM with the script: ```sh ./scripts/build_utm.sh -t TEAMID -k macosx -s macOS -a ARCH -o /path/to/output/directory ``` `ARCH` can be `x86_64` or `arm64` or `"arm64 x86_64"` (quotes are required) for a universal binary. The built artifact is an unsigned `.xcarchive` which you can use with the package tool (see below). `TEAMID` is optional and only used if you are going to sign it. ### Packaging Artifacts built with `build_utm.sh` (includes GitHub Actions artifacts) must be re-signed before it can be used. To properly use all features, you must be a paid Apple Developer with access to a provisioning profile with the Hypervisor entitlements. However, non-registered developers can build "unsigned" packages which lack certain features (such as USB and network bridging support). #### Unsigned packages ```sh ./scripts/package_mac.sh unsigned /path/to/UTM.xcarchive /path/to/output ``` where `/path/to/output` is an existing directory. This builds `UTM.dmg` in `/path/to/output` which can be installed to `/Applications`. #### Signed packages ```sh ./scripts/package_mac.sh developer-id /path/to/UTM.xcarchive /path/to/output TEAM_ID PROFILE_UUID HELPER_PROFILE_UUID LAUNCHER_PROFILE_UUID ``` where `/path/to/output` is an existing directory. To build a signed package, you need to be a registered Apple Developer. From the developer portal, create a certificate for "Developer ID Application" (and install it into your Keychain). Also create three provisioning profiles with that certificate with Hypervisor entitlements (you need to manually request these entitlements and be approved by Apple) for UTM, QEMUHelper, and QEMULauncher. `TEAM_ID` should be the same as in the certificate, `PROFILE_UUID` should be the UUID of the profile installed by Xcode (open the profile in Xcode), and `HELPER_PROFILE_UUID` is the UUID of a separate profile for the XPC helper. `LAUNCHER_PROFILE_UUID` is the UUID of a profile for the launcher. Once properly signed, you can ask Apple to notarize the DMG. #### Mac App Store ```sh ./scripts/package_mac.sh app-store /path/to/UTM.xcarchive /path/to/output TEAM_ID PROFILE_UUID HELPER_PROFILE_UUID LAUNCHER_PROFILE_UUID ``` Similar to the above but builds a `UTM.pkg` for submission to the Mac App Store. You need a certificate for "Apple Distribution" and a certificate for "Mac App Distribution" as well as a provisioning profile with the right entitlements. ### Xcode Development By default, Xcode will build UTM unsigned (lacking USB and bridged networking features). If you have a registered developer account with access to Hypervisor entitlements, you should create a `CodeSigning.xcconfig` file with the proper values (see `CodeSigning.xcconfig.sample`). Make sure to set `DEVELOPER_ACCOUNT_VM_ACCESS = YES`. Note that due to a macOS bug, you may get a crash when launching a VM with the debugger attached. The workaround is to start UTM with the debugger detached and attach the debugger with Debug -> Attach to Process after launching a VM. Once you do that, you can start additional VMs without any issues with the debugger. [1]: https://github.com/utmapp/UTM/actions?query=event%3Arelease+workflow%3ABuild [2]: https://brew.sh ================================================ FILE: Documentation/Release.md ================================================ # Release Guide This document details the release procedure for UTM team members. The release procedure is mostly automated by GitHub Actions. In short, when you submit a new "release" on the GitHub repository, the following happens: 1. If UTM dependencies are not cached from a previous run, build it for {iOS,macOS,iOS-TCI,iOS Simulator} X {arm64,x86_64}. 2. Build UTM for all configurations and architectures. 3. Take the {iOS-arm64,iOS-TCI-arm64} build and package it into a fakesigned IPA and post it as a release asset. 4. Take the iOS-arm64 build and package it into a Cydia DEB and post it as a release asset. 5. Update the Cydia repository. 6. Update the AltStore repository. 7. Combine dependencies for macOS-arm64 and macOS-x86_64 into universal binaries. 8. Build UTM as a macOS universal binary. 9. Take the universal binary and sign and package it into a DMG. 10. Notarize the DMG with App Store Connect and post it as a release asset. 11. Take the universal binary and sign and package it for the Mac App Store. 12. Submit the signed package to App Store Connect. For more details see the [build.yml](../.github/workflows/build.yml) file. ## Making a release Once you are ready to make a new release: 1. Modify [Build.xcconfig](../Build.xcconfig) and bump `MARKETING_VERSION` following [semantic versioning][5] and `CURRENT_PROJECT_VERSION` by 1. 2. Commit the change with the commit message `project: bumped version`. Tag the release with `git tag vx.y.z` corresponding to `MARKETING_VERSION`. 3. Push the commit and tag. 4. In GitHub, draft a new release with the template below. Use the title `vx.y.z` or `vx.y.z (Beta)`. Select the tag you just created. Check "This is a pre-release" if it is a beta. Check "Create a discussion for this release" and the "Release" category. 5. When the release is published, the pipeline will run and do everything else. ### Release notes template Make sure to copy all the changes for all beta releases after the last non-beta release. ``` ## Installation Visit [https://getutm.app/install/][1] for the most up to date installation instructions. ## Highlights * Key features * Keep these bullets short ## Notes * List any important changes here * Include anything that deviates significantly from previously defined behaviour ## Changes (vx.y.1) * Third change * (iOS) iOS only change * (iOS) Another iOS only change * (macOS) A macOS only change ## Changes (vx.y.0) * One change * Another change ## Issues Please check the full list on [Github][2] and help report any bug you find that is not listed. ### Known Issues * Optional section. List any known major issues here in bullet points. [1]: https://getutm.app/install/ [2]: https://github.com/utmapp/UTM/issues ``` ### Beta release Beta releases will not show up as the "latest version" in the GitHub home page. It also will not be posted to AltStore and Cydia and will not be distributed to the App Store (exception: TestFlight). ### Re-release In case of issues in post release that warrants a re-release, follow the same steps but do not change `MARKETING_VERSION` (`CURRENT_PROJECT_VERSION` must still be incremented by 1 or App Store Connect rejects the build). The tag should be named `vx.y.z-t` where `t` starts at `2` and increments by 1 for every re-release. Then copy-paste the release notes from the previous release and follow the same steps above. Finally, delete the old release if desired. ## Actions Details ### Secrets Below is a summary of all the variables and secrets used by GitHub Actions in the release process. |Secret |Description | |---------------------------------|-----------------------------------------------------------------------------------| |`PERSONAL_ACCESS_TOKEN` |GitHub personal token with permission for `repository_dispatch` | |`SIGNING_CERTIFICATE_P12_DATA` |Base64 encoded PKCS#12 format containing certificates and private keys for signing | |`SIGNING_CERTIFICATE_PASSWORD` |Password of the PKCS#12 file | |`CONNECT_KEY` |App Store Connect API key for notarizing and submission (base64 encoded .p8) | |Variable |Description | |---------------------------------|-----------------------------------------------------------------------------------| |`DISPATCH_ALTSTORE_REPO_NAME` |`username/repo` path to a [altstore-github][1] repository | |`DISPATCH_CYDIA_REPO_NAME` |`username/repo` path to a [silica-package-github][2] repository | |`SIGNING_TEAM_ID` |Team ID associated with signing certificates | |`CONNECT_ISSUER_ID` |App Store Connect API issuer id | |`CONNECT_KEY_ID` |App Store Connect API key id | |`PROFILE_DATA` |Base64 encoded provisioning profile of main application | |`PROFILE_UUID` |UUID of provisioning profile above | |`HELPER_PROFILE_DATA` |Base64 encoded provisioning profile of QEMUHelper | |`HELPER_PROFILE_UUID` |UUID of provisioning profile above | |`LAUNCHER_PROFILE_DATA` |Base64 encoded provisioning profile of QEMULauncher | |`LAUNCHER_PROFILE_UUID` |UUID of provisioning profile above | |`APP_STORE_PROFILE_DATA` |Base64 encoded provisioning profile of main application for App Store submission | |`APP_STORE_PROFILE_UUID` |UUID of provisioning profile above | |`APP_STORE_HELPER_PROFILE_DATA` |Base64 encoded provisioning profile of QEMUHelper for App Store submission | |`APP_STORE_HELPER_PROFILE_UUID` |UUID of provisioning profile above | |`APP_STORE_LAUNCHER_PROFILE_DATA`|Base64 encoded provisioning profile of QEMULauncher for App Store submission | |`APP_STORE_LAUNCHER_PROFILE_UUID`|UUID of provisioning profile above | |`IOS_REMOTE_PROFILE_DATA` |Base64 encoded provisioning profile of iOS Remote for App Store submission | |`IOS_REMOTE_PROFILE_UUID` |UUID of provisioning profile above | |`IOS_SE_PROFILE_DATA` |Base64 encoded provisioning profile of iOS SE for App Store submission | |`IOS_SE_PROFILE_UUID` |UUID of provisioning profile above | |`IS_SELF_HOSTED_RUNNER` |Set to `true` to use a self hosted macOS runner set up by the owner | ### Signing for release The following certificates (and associated private keys) must be exported from Keychain as a PKCS#12 file (Cmd+click to select multiple and right click to export). * Developer ID Application * 3rd Party Mac Developer Application (Mac App Store) or Apple Distribution * 3rd Party Mac Developer Installer (Mac App Store) Give a password when prompted and save it to the repository secret `SIGNING_CERTIFICATE_PASSWORD`. Then, in Terminal, convert the PKCS#12 file to Base64 and copy it: `cat Certificates.p12 | base64 | pbcopy` and paste it to `SIGNING_CERTIFICATE_P12_DATA`. Next you need to get each provisioning profile {3 profiles for macOS} X {1 for Developer ID, 1 for Mac App Store}. Save each UUID of the profile as `*_PROFILE_UUID` and the Base64 encoded data from `cat name.provisionprofile | base64 | pbcopy` as `*_PROFILE_DATA`. ### AltStore Repository The AltStore repository is generated by [altstore-github][1]. The repository [utmapp/altstore-repo](https://github.com/utmapp/altstore-repo) is created which contains its own GitHub Actions that is triggered on a `repository_dispatch` event. When the event is dispatched by the main repository's release Actions, the other repository will use altstore-github to generate an AltStore compatible JSON repository file from GitHub releases containing the release notes and download links to all the recent releases. The resulting repository file is hosted on GitHub Pages. ### Cydia Repository The Cydia repository is generated by [silica-package-github][2]. The repository [utmapp/cydia-repo](https://github.com/utmapp/cydia-repo) has its own GitHub Actions triggered by a `repository_dispatch` event sent from the main repository during the release GitHub Actions. It generates the repository index and HTML pages and uses GitHub Pages to host everything. ### Debugging release pipeline Go to the [Build workflow][4] and click the "Run workflow" button. Type "true" for "Test release?" and you can test out changes to the release pipeline without making a release. The built assets will be provided as artifacts instead of as release assets. [1]: https://github.com/osy/altstore-github [2]: https://github.com/osy/silica-package-github [3]: https://support.apple.com/en-us/HT204397 [4]: https://github.com/utmapp/UTM/actions/workflows/build.yml [5]: https://semver.org ================================================ FILE: Documentation/TetheredLaunch.md ================================================ # Tethered Launch On iOS 14, Apple [patched][1] the trick we used to get JIT working. As a result, the next best workaround is significantly more involved. This only applies to non-jailbroken devices. If you are jailbroken, you do not need to do this. ## Prerequisites * Xcode * [Latest IPA Release][3] * [iOS App Signer][4] * [Homebrew][2] * [ios-deploy][5] (`brew install ios-deploy`) ## Signing Install and follow the instructions for [iOS App Signer][4]. Make sure your signing certificate and provisioning profiles matches. Select the UTM.ipa release as the input file and press start. Save the signed IPA as `UTM-signed.ipa`. Once the process is completed, rename `UTM-signed.ipa` to `UTM-signed.zip` and open the ZIP file. macOS should extract the files to a new directory named `Payload/`. ## Deploying To deploy UTM, connect your device and run in Terminal: ```sh ios-deploy --bundle /path/to/Payload/UTM.app ``` (Hint: you can drag `Payload/UTM.app` into Terminal to auto-fill in the path.) ## Launching You need to run the following each subsequent time you wish to launch UTM. (You cannot launch UTM from the home screen in iOS 14 or it will not work properly!) ```sh ios-deploy --justlaunch --noinstall --bundle /path/to/Payload/UTM.app ``` (Hint: if you open Xcode and go to Window -> Devices and Simulators and find your device, you can check "Connect via network" in order to deploy/launch without a USB cable. You just need the device unlocked and near your computer.) ## Troubleshooting ### Trust issue If you see the message `The operation couldn’t be completed. Unable to launch xxx because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user.`, you need to open Settings -> General -> Device Management, select the developer profile, and press Trust. ### Failed to register bundle identifier Xcode might show this message when trying to create a signing profile. You need to change the Bundle Identifier and try again. [1]: https://github.com/utmapp/UTM/issues/397 [2]: https://brew.sh [3]: https://github.com/utmapp/UTM/releases [4]: https://dantheman827.github.io/ios-app-signer/ [5]: https://github.com/ios-control/ios-deploy ================================================ FILE: Documentation/TetheredLaunch.zh-HK.md ================================================ # 捆綁式啟動 在 iOS 14 當中,Apple [修複][1]了我們之前令 JIT 工作的「蠱惑招」。因此,下一個最佳變通方法涉及的就更多了。這只限用於未越獄(Jailbreak)的裝置。如你已經越獄,就無需這樣做。 ## 先決條件 * Xcode * [最新版本的 IPA][3] * [iOS App Signer][4] * [Homebrew][2] * [ios-deploy][5] (`brew install ios-deploy`) ## 簽署 安裝並依循 [iOS App Signer][4] 的說明執行操作。確保你的簽署證書與配置檔案匹配。選擇 UTM.ipa 發行版本做為輸入檔案,然後按一下「開始(Start)」。 將已簽署的 IPA 儲存為 `UTM-signed.ipa`,當程序完成之後,重新命名 `UTM-signed.ipa` 為 `UTM-signed.zip`,並開啟 ZIP 檔案。macOS 應當將檔案解壓縮至名為 `Payload/` 的新目錄裡。 ## 部署 如要部署 UTM,連接你的裝置並在終端機中執行: ```sh ios-deploy --bundle /path/to/Payload/UTM.app ``` (貼士:你可以拖放 `Payload/UTM.app` 至終端機以自動填充目錄。) ## 啟動 如你每次希望啟動 UTM,都需要執行以下內容。(在 iOS 14 當中,不應該透過主畫面啟動 UTM,否則它將無法正常工作!) ```sh ios-deploy --justlaunch --noinstall --bundle /path/to/Payload/UTM.app ``` (貼士:如你開啟 Xcode 並轉到 Window > Devices and Simulators 找到你的裝置,則可以選擇「Connect via network」以便於在無 USB 連線的條件下部署/啟動。你只需要解鎖裝置,並令它靠近你的電腦。) ## 疑難排解 ### 信任問題 如你看到訊息:`The operation couldn't be completed. Unable to launch xxx because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user.`,你需要開啟設定 > 一般 > 裝置管理,選擇「開發者描述檔」,然後選擇「信任」。 ### 註冊套裝識別碼失敗(Failed to register bundle identifier) Xcode 可能在嘗試製作簽名設定檔時顯示此訊息,你需要更改套裝識別碼,然後再試。 [1]: https://github.com/utmapp/UTM/issues/397 [2]: https://brew.sh [3]: https://github.com/utmapp/UTM/releases [4]: https://dantheman827.github.io/ios-app-signer/ [5]: https://github.com/ios-control/ios-deploy ================================================ FILE: Documentation/TetheredLaunch.zh-Hans.md ================================================ # 捆绑启动 在 iOS 14 中,Apple [修补][1]了我们用来让 JIT 工作的“把戏”。因此,下一个最佳变通方案所涉及的范围更广。这一操作只适用于未经越狱(Jailbreak)过的设备。若你已经越狱,就不需要这样做了。 ## 前置条件 * Xcode * [最新版本的 IPA][3] * [iOS App Signer][4] * [Homebrew][2] * [ios-deploy][5] (`brew install ios-deploy`) ## 签名 安装并按照 [iOS App Signer][4] 的说明进行操作。确保你的签名证书和配置文件相匹配。选择 UTM.ipa 版本作为输入的文件,然后点击“开始(Start)”。 将已签名的 IPA 保存为 `UTM-signed.ipa`,完成操作后将 `UTM-signed.ipa` 重命名为 `UTM-signed.zip`,打开 ZIP 文件。macOS 会将文件提取到名为`Payload/`的新目录中。 ## 部署 若要部署 UTM,请连接你的设备,然后在终端中运行: ```sh ios-deploy --bundle /path/to/Payload/UTM.app ``` (提示:你可以把 `Payload/UTM.app` 拖放进终端来自动填充目录。) ## 启动 当你每次希望启动 UTM 时,都需要运行如下命令。(在 iOS 14 中,不要从主屏幕启动 UTM,否则它将无法正常工作!) ```sh ios-deploy --justlaunch --noinstall --bundle /path/to/Payload/UTM.app ``` (提示:如果你打开了 Xcode 并转到窗口(Window)> 设备和模拟器(Devices and Simulators)找到你的设备,可以勾选“通过网络连接”,以便在没有 USB 电缆的情况下部署/启动。只需要解锁设备并靠近你的电脑即可。) ## 疑难解答 ### 信任问题 如果你看到了消息 `The operation couldn’t be completed. Unable to launch xxx because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user.(无法完成操作。无法启动 xxx,因为它的代码签名无效,授权不足,或者其配置文件尚未被用户明确信任。)`,你需要打开设置 > 通用 > 设备管理,选择开发者描述文件,然后选择信任。 ### 注册捆绑包标识符失败(Failed to register bundle identifier) Xcode 可能在尝试创建签名配置文件时显示此消息,你需要更改绑定标识符并重试。 [1]: https://github.com/utmapp/UTM/issues/397 [2]: https://brew.sh [3]: https://github.com/utmapp/UTM/releases [4]: https://dantheman827.github.io/ios-app-signer/ [5]: https://github.com/ios-control/ios-deploy ================================================ FILE: Documentation/TetheredLaunch.zh-Hant.md ================================================ # 不完美啟動 在iOS14中,蘋果[修補][1]了我們用來讓JIT工作的“把戲”。 因此,下一個最佳的解決方案所涉及的範圍更廣。 這只適用於非越獄設備。 如果你越獄了,你不需要這樣做。 ## 前置條件 * Xcode * [最新的正式版IPA][3] * [iOS App Signer][4] * [Homebrew][2] * [ios-deploy][5] (`brew install ios-deploy`) ## 簽名 安裝並按照[iOS App Signer][4]的說明進行操作。 請確保您的簽名證書和配置文件匹配。 選擇UTM.ipa正式版作為輸入文件並且按下開始。 將已簽名的IPA保存為`UTM-signed.ipa`,過程完成後將`UTM-signed.ipa`重命名為`UTM-signed.zip`並且打開ZIP文件。 macOS會將文件提取至名為`Payload/`的新目錄。 ## 部署 要部署UTM,連接你的設備然後在終端中運行: ```sh ios-deploy --bundle /path/to/Payload/UTM.app ``` (提示:你可以把 `Payload/UTM.app` 拖放進終端來自動填充目錄。) ## 啟動 當你每次希望啟動UTM時,都需要運行以下命令。 (你無法在iOS14中從主屏幕正常啟動UTM否則它無法正常運行!) ```sh ios-deploy --justlaunch --noinstall --bundle /path/to/Payload/UTM.app ``` (提示:如果您打開Xcode並轉到Window->Devices and Simulators並找到您的設備,那麼您可以選中“Connect via network”(通過網絡連接)以便在沒有USB電纜的情況下部署/啟動。你只 需要解鎖設備並靠近你的電腦。) ## 疑難解答 ### 信任問題 如果你看見了消息:`The operation couldn't be completed. Unable to launch xxx because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user.(無法完成操作。無法啟動xxx, 因為它的代碼簽名無效、授權不足或其配置文件未被用戶明確信任。 )`,你需要打開設置-> 通用-> 設備管理,選擇開發者描述文件,然後選擇信任。 ### 註冊捆綁標識符失敗 Xcode 可能在嘗試創建簽名配置文件時顯示此消息,您需要更改綁定標識符並重試。 [1]: https://github.com/utmapp/UTM/issues/397 [2]: https://brew.sh [3]: https://github.com/utmapp/UTM/releases [4]: https://dantheman827.github.io/ios-app-signer/ [5]: https://github.com/ios-control/ios-deploy ================================================ FILE: Documentation/iOSDevelopment.md ================================================ # iOS Development This document describes the steps to build and debug UTM on iOS and simulator devices. ## Getting the Source Make sure you perform a recursive clone to get all the submodules: ``` git clone --recursive https://github.com/utmapp/UTM.git ``` Alternatively, run `git submodule update --init --recursive` after cloning if you did not do a recursive clone. ## Dependencies The easy way is to get the prebuilt dependences from [GitHub Actions][1]. Pick the latest release and download the `Sysroot-*` artifact for the targets you wish to develop on. You need to be logged in to GitHub to download artifacts. | | Intel | Apple Silicon | |-----------------------|----------------------------|--------------------------------| | iOS | N/A | `ios-arm64` | | iOS SE | N/A | `ios-tci-arm64` | | iOS Simulator | `ios_simulator-x86_64` | `ios_simulator-arm64` | | iOS Simulator SE | `ios_simulator-tci-x86_64` | `ios_simulator-tci-arm64` | | visionOS | N/A | `visionos-arm64` | | visionOS SE | N/A | `visionos-tci-arm64` | | visionOS Simulator | N/A | `visionos_simulator-arm64` | | visionOS Simulator SE | N/A | `visionos_simulator-tci-arm64` | After downloading the prebuilt artifacts of your choice, extract them to the root directory where you cloned the repository. To build UTM, make sure you have the latest version of Xcode installed. ### Building Dependencies (Advanced) If you want to build the dependencies yourself, it is highly recommended that you start with a fresh macOS VM. This is because some of the dependencies attempt to use `/usr/local/lib` even though the architecture does not match. Certain installed packages like `libusb`, `gawk`, and `cmake` will break the build. 1. Install Xcode command line and [Homebrew][1] 2. Install the following build prerequisites `brew install bison pkg-config gettext glib libgpg-error nasm meson` `pip3 install six pyparsing` Make sure to add `bison` to your `$PATH` environment variable! `export PATH=/usr/local/opt/bison/bin:/opt/homebrew/opt/bison/bin:$PATH` 3. Run `./scripts/build_dependencies.sh -p PLATFORM -a ARCHITECTURE` where `ARCHITECTURE` is the last part of the table above (e.g. `x86_64`) and `PLATFORM` is the first part (e.g. `ios_simulator-tci`). 4. Repeat the above for any other platforms and architectures you wish to target. ## Building UTM ### Command Line You can build UTM for iOS with the script (run `./scripts/build_utm.sh` for all options): ``` ./scripts/build_utm.sh -k iphoneos -s iOS -a arm64 -o /path/to/output/directory ``` The built artifact is an unsigned `.xcarchive` which you can use with the package tool (see below). Replace `iOS` with `iOS-SE` to build UTM SE. Replace `iphoneos` with `xros` to build for visionOS. ### Packaging Artifacts built with `build_utm.sh` (includes GitHub Actions artifacts) must be re-signed before it can be used. For stock iOS devices, you can sign with either a free developer account or a paid developer account. Free accounts have a 7 day expire time and must be re-signed every 7 days. For jailbroken iOS devices, you can generate a DEB which is fake-signed. #### Stock signed IPA For a user friendly option, you can use [iOS App Signer][3] to re-sign the `.xcarchive`. Advanced users can use the package.sh script: ``` ./scripts/package.sh signedipa /path/to/UTM.xcarchive /path/to/output TEAM_ID PROFILE_UUID ``` This builds `UTM.ipa` in `/path/to/output` which can be installed by Xcode, iTunes, or AirDrop. Note that you need a "Development" signing certificate and NOT a "Distribution" certificate. This is because UTM requires a provisioning profile with the `get-task-allow` entitlement which Apple only grants for Development signing. #### Unsigned IPA ``` ./scripts/package.sh ipa /path/to/UTM.xcarchive /path/to/output ``` This builds `UTM.ipa` in `/path/to/output` which can be installed by AltStore or a jailbroken device with AppSync Unified installed. #### DEB Package ``` ./scripts/package.sh deb /path/to/UTM.xcarchive /path/to/output ``` This builds `UTM.deb` which is a wrapper for an unsigned `UTM.ipa` which can be installed by Cydia or Sileo along with AppSync Unified. ### Xcode Development Copy `CodeSigning.xcconfig.sample` to `CodeSigning.xcconfig` and modify the file replacing `DEVELOPMENT_TEAM` with your Team ID and `PRODUCT_BUNDLE_PREFIX` with a bundle identifier that is registered to you. If you have a paid Apple Developer account, you can find your Team ID at https://developer.apple.com/account/#/membership If you have a free Apple Developer account, you need to generate a new signing certificate. To do so, follow the steps in [iOS App Signer][3] to create a new Xcode project and generate a provisioning profile. After saving the project, open `project.pbxproj` inside your newly created `.xcproj` and look for `DEVELOPMENT_TEAM`. Copy this value to `CodeSigning.xcconfig` and your unique identifier to `PRODUCT_BUNDLE_PREFIX`. Set `DEVELOPER_ACCOUNT_PAID = YES` if you used a paid Apple Developer account in order to automatically request the increased memory limit entitlement from Apple. ### Tethered Launch For JIT to work on the latest version of iOS, it must be launched through the debugger. You can do it from Xcode (and detach the debugger after launching) or you can follow [these instructions](TetheredLaunch.md) for an easier way. [1]: https://github.com/utmapp/UTM/actions?query=event%3Arelease+workflow%3ABuild [2]: https://brew.sh [3]: https://dantheman827.github.io/ios-app-signer/ ================================================ FILE: Intents/UTMActionIntent.swift ================================================ // // Copyright © 2025 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 AppIntents #if os(macOS) import AppKit #endif @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMStatusActionIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Get Virtual Machine Status" static let description = IntentDescription("Get the status of a virtual machine.") static var parameterSummary: some ParameterSummary { Summary("Get \(\.$vmEntity) status") } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some ReturnsValue { return .result(value: vm.state) } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMStartActionIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Start Virtual Machine" static let description = IntentDescription("Start a virtual machine.") static var parameterSummary: some ParameterSummary { Summary("Start \(\.$vmEntity)") { \.$isRecovery \.$isDisposible } } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @Parameter(title: "Recovery", description: "Boot into recovery mode. Only supported on Apple Virtualization backend.", default: false) var isRecovery: Bool @Parameter(title: "Disposible", description: "Do not save any changes to disk. Only supported on QEMU backend.", default: false) var isDisposible: Bool @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { var options = UTMVirtualMachineStartOptions() if isRecovery { #if os(macOS) guard vm is UTMAppleVirtualMachine else { throw UTMIntentError.unsupportedBackend } options.insert(.bootRecovery) #else throw UTMIntentError.unsupportedBackend #endif } if isDisposible { guard vm is UTMQemuVirtualMachine else { throw UTMIntentError.unsupportedBackend } options.insert(.bootDisposibleMode) } #if os(macOS) // Ensure the app comes to the foreground before presenting VM UI NSApp.activate(ignoringOtherApps: true) #endif data.run(vm: boxed, options: options) // For platforms that support foreground continuation, request it (no-op on older SDKs). if !vm.isHeadless { if #available(iOS 26, macOS 26, tvOS 26, watchOS 26, visionOS 26, *), systemContext.currentMode.canContinueInForeground { try await continueInForeground(alwaysConfirm: false) } } return .result() } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMStopActionIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Stop Virtual Machine" static let description = IntentDescription("Stop a virtual machine.") static var parameterSummary: some ParameterSummary { Summary("Stop \(\.$vmEntity) by \(\.$method)") } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @Parameter(title: "Stop Method", description: "Intensity of the stop action.", default: .force) var method: UTMVirtualMachineStopMethod @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { try await vm.stop(usingMethod: method) return .result() } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) extension UTMVirtualMachineStopMethod: AppEnum { static let typeDisplayRepresentation: TypeDisplayRepresentation = TypeDisplayRepresentation( name: "Stop Method" ) static let caseDisplayRepresentations: [UTMVirtualMachineStopMethod: DisplayRepresentation] = [ .request: DisplayRepresentation(title: "Request", subtitle: "Sends power down request to the guest. This simulates pressing the power button on a PC."), .force: DisplayRepresentation(title: "Force", subtitle: "Tells the VM process to shut down with risk of data corruption. This simulates holding down the power button on a PC."), .kill: DisplayRepresentation(title: "Killing", subtitle: "Force kill the VM process with high risk of data corruption."), ] } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMPauseActionIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Pause Virtual Machine" static let description = IntentDescription("Pause a virtual machine.") static var parameterSummary: some ParameterSummary { Summary("Pause \(\.$vmEntity)") { \.$isSaveState } } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @Parameter(title: "Save State", description: "Create a snapshot of the virtual machine state.", default: false) var isSaveState: Bool @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { try await vm.pause() if isSaveState { try await vm.save() } return .result() } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMResumeActionIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Resume Virtual Machine" static let description = IntentDescription("Resume a virtual machine.") static var parameterSummary: some ParameterSummary { Summary("Resume \(\.$vmEntity)") } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { try await vm.resume() if !vm.isHeadless { if #available(iOS 26, macOS 26, tvOS 26, watchOS 26, visionOS 26, *), systemContext.currentMode.canContinueInForeground { try await continueInForeground(alwaysConfirm: false) } } return .result() } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMRestartActionIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Restart Virtual Machine" static let description = IntentDescription("Restart a virtual machine.") static var parameterSummary: some ParameterSummary { Summary("Restart \(\.$vmEntity)") } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { try await vm.restart() if !vm.isHeadless { if #available(iOS 26, macOS 26, tvOS 26, watchOS 26, visionOS 26, *), systemContext.currentMode.canContinueInForeground { try await continueInForeground(alwaysConfirm: false) } } return .result() } } ================================================ FILE: Intents/UTMInputIntent.swift ================================================ // // Copyright © 2025 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 AppIntents private let kDelayNs: UInt64 = 20000000 @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMSendScanCodeIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Send Scan Code" static let description = IntentDescription("Send a sequence of raw keyboard scan codes to the virtual machine. Only supported on QEMU backend.") static var parameterSummary: some ParameterSummary { Summary("Send scan code to \(\.$vmEntity)") { \.$scanCodes } } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @Parameter(title: "Scan Code", description: "List of PC AT scan codes in decimal (0-65535 inclusive).", controlStyle: .field, inclusiveRange: (0, 0xFFFF)) var scanCodes: [Int] @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { guard let vm = vm as? any UTMSpiceVirtualMachine else { throw UTMIntentError.unsupportedBackend } guard let input = vm.ioService?.primaryInput else { throw UTMIntentError.inputHandlerNotAvailable } for scanCode in scanCodes { var _scanCode = scanCode if (_scanCode & 0xFF00) == 0xE000 { _scanCode = 0x100 | (_scanCode & 0xFF) } if (_scanCode & 0x80) == 0x80 { input.send(.release, code: Int32(_scanCode & 0x17F)) } else { input.send(.press, code: Int32(_scanCode)) } try await Task.sleep(nanoseconds: kDelayNs) } return .result() } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMSendKeystrokesIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Send Keystrokes" static let description = IntentDescription("Send text as a sequence of keystrokes to the virtual machine. Only supported on QEMU backend.") static var parameterSummary: some ParameterSummary { Summary("Send \(\.$keystrokes) to \(\.$vmEntity)") { \.$modifiers } } enum Modifier: Int, CaseIterable, AppEnum { case capsLock case shift case control case option case command case escape static let typeDisplayRepresentation: TypeDisplayRepresentation = TypeDisplayRepresentation( name: "Modifier Key" ) static let caseDisplayRepresentations: [Modifier: DisplayRepresentation] = [ .capsLock: DisplayRepresentation(title: "Caps Lock (⇪)"), .shift: DisplayRepresentation(title: "Shift (⇧)"), .control: DisplayRepresentation(title: "Control (⌃)"), .option: DisplayRepresentation(title: "Option (⌥)"), .command: DisplayRepresentation(title: "Command (⌘)"), .escape: DisplayRepresentation(title: "Escape (⎋)"), ] func toSpiceKeyCode() -> Int32 { switch self { case .capsLock: return 0x3a case .shift: return 0x2a case .control: return 0x1d case .option: return 0x38 case .command: return 0x15b case .escape: return 0x01 } } } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @Parameter(title: "Keystrokes", description: "Text will be converted to a sequence of keystrokes.") var keystrokes: String @Parameter(title: "Modifiers", description: "The modifier keys will be held down while the keystroke sequence is sent.", default: []) var modifiers: [Modifier] @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { guard let vm = vm as? any UTMSpiceVirtualMachine else { throw UTMIntentError.unsupportedBackend } guard let input = vm.ioService?.primaryInput else { throw UTMIntentError.inputHandlerNotAvailable } for modifier in modifiers { input.send(.press, code: modifier.toSpiceKeyCode()) try await Task.sleep(nanoseconds: kDelayNs) } let keyboardMap = VMKeyboardMap() await keyboardMap.mapText(keystrokes) { scanCode in input.send(.release, code: scanCodeToSpice(scanCode)) } keyDown: { scanCode in input.send(.press, code: scanCodeToSpice(scanCode)) } try await Task.sleep(nanoseconds: kDelayNs) for modifier in modifiers { input.send(.release, code: modifier.toSpiceKeyCode()) try await Task.sleep(nanoseconds: kDelayNs) } return .result() } private func scanCodeToSpice(_ scanCode: Int) -> Int32 { var keyCode = scanCode if (keyCode & 0xFF00) == 0xE000 { keyCode = (keyCode & 0xFF) | 0x100 } return Int32(keyCode) } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMMouseClickIntent: AppIntent, UTMIntent { static let title: LocalizedStringResource = "Send Mouse Click" static let description = IntentDescription("Send a mouse position and click to the virtual machine. Only supported on QEMU backend.") static var parameterSummary: some ParameterSummary { Summary("Send mouse click at (\(\.$xPosition), \(\.$yPosition)) to \(\.$vmEntity)") { \.$mouseButton \.$monitorNumber } } enum MouseButton: Int, CaseIterable, AppEnum { case left case right case middle static let typeDisplayRepresentation: TypeDisplayRepresentation = TypeDisplayRepresentation( name: "Mouse Button" ) static let caseDisplayRepresentations: [MouseButton: DisplayRepresentation] = [ .left: DisplayRepresentation(title: "Left"), .right: DisplayRepresentation(title: "Right"), .middle: DisplayRepresentation(title: "Middle"), ] func toSpiceButton() -> CSInputButton { switch self { case .left: return .left case .right: return .right case .middle: return .middle } } } @Dependency var data: UTMData @Parameter(title: "Virtual Machine", requestValueDialog: "Select a virtual machine") var vmEntity: UTMVirtualMachineEntity @Parameter(title: "X Position", description: "X coordinate of the absolute position.", default: 0, controlStyle: .field) var xPosition: Int @Parameter(title: "Y Position", description: "Y coordinate of the absolute position.", default: 0, controlStyle: .field) var yPosition: Int @Parameter(title: "Mouse Button", description: "Mouse button to click.", default: .left) var mouseButton: MouseButton @Parameter(title: "Monitor Number", description: "Which monitor to target (starting at 1).", default: 1, controlStyle: .stepper) var monitorNumber: Int @MainActor func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> some IntentResult { guard let vm = vm as? UTMQemuVirtualMachine else { throw UTMIntentError.unsupportedBackend } guard let input = vm.ioService?.primaryInput else { throw UTMIntentError.inputHandlerNotAvailable } try await vm.changeInputTablet(true) input.sendMousePosition(mouseButton.toSpiceButton(), absolutePoint: CGPoint(x: xPosition, y: yPosition), forMonitorID: monitorNumber-1) try await Task.sleep(nanoseconds: kDelayNs) input.sendMouseButton(mouseButton.toSpiceButton(), mask: [], pressed: true) try await Task.sleep(nanoseconds: kDelayNs) input.sendMouseButton(mouseButton.toSpiceButton(), mask: [], pressed: false) return .result() } } ================================================ FILE: Intents/UTMIntent.swift ================================================ // // Copyright © 2025 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 AppIntents @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) protocol UTMIntent: AppIntent { associatedtype T : IntentResult var data: UTMData { get } var vmEntity: UTMVirtualMachineEntity { get } func perform(with vm: any UTMVirtualMachine, boxed: VMData) async throws -> T } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) @available(*, deprecated) extension UTMIntent { static var openAppWhenRun: Bool { true } } @available(iOS 26, macOS 26, tvOS 26, watchOS 26, visionOS 26, *) extension UTMIntent { static var supportedModes: IntentModes { [.background, .foreground(.dynamic)] } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) extension UTMIntent { @MainActor func perform() async throws -> T { guard let vm = data.virtualMachines.first(where: { $0.id == vmEntity.id }) else { throw UTMIntentError.virtualMachineNotFound } if !vm.isLoaded { do { try vm.load() } catch { throw UTMIntentError.localizedError(error) } } do { return try await perform(with: vm.wrapped!, boxed: vm) } catch { throw UTMIntentError.localizedError(error) } } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) enum UTMIntentError: Error, CustomLocalizedStringResourceConvertible { case localizedError(Error) case virtualMachineNotFound case unsupportedBackend case inputHandlerNotAvailable var localizedStringResource: LocalizedStringResource { switch self { case .localizedError(let wrapped): return "\(wrapped.localizedDescription)" case .virtualMachineNotFound: return "Virtual machine not found." case .unsupportedBackend: return "Operation not supported by the backend." case .inputHandlerNotAvailable: return "Input handler not available." } } } ================================================ FILE: Intents/UTMVirtualMachineEntity.swift ================================================ // // Copyright © 2025 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 AppIntents @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMVirtualMachineEntity: AppEntity { static let defaultQuery = UTMVirtualMachineEntityQuery() let id: UUID var iconURL: URL? @Property(title: "Name") var name: String @Property(title: "Description") var description: String @Property(title: "Status") var state: UTMVirtualMachineState static var typeDisplayRepresentation: TypeDisplayRepresentation { TypeDisplayRepresentation( name: "Virtual Machine", numericFormat: "\(placeholder: .int) virtual machines" ) } var displayRepresentation: DisplayRepresentation { var display = DisplayRepresentation( title: "\(name)", subtitle: "\(description)" ) if let iconURL = iconURL { display.image = DisplayRepresentation.Image(url: iconURL) } return display } @MainActor init(from vm: VMData) { id = vm.id name = vm.detailsTitleLabel description = vm.detailsSubtitleLabel state = vm.state iconURL = vm.detailsIconUrl } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) extension UTMVirtualMachineState: AppEnum { static let typeDisplayRepresentation: TypeDisplayRepresentation = TypeDisplayRepresentation( name: "Status" ) static let caseDisplayRepresentations: [UTMVirtualMachineState: DisplayRepresentation] = [ .stopped: DisplayRepresentation(title: "Stopped"), .starting: DisplayRepresentation(title: "Starting"), .started: DisplayRepresentation(title: "Started"), .pausing: DisplayRepresentation(title: "Pausing"), .paused: DisplayRepresentation(title: "Paused"), .resuming: DisplayRepresentation(title: "Resuming"), .saving: DisplayRepresentation(title: "Saving"), .restoring: DisplayRepresentation(title: "Restoring"), .stopping: DisplayRepresentation(title: "Stopping"), ] } ================================================ FILE: Intents/UTMVirtualMachineEntityQuery.swift ================================================ // // Copyright © 2025 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 AppIntents @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) struct UTMVirtualMachineEntityQuery: EntityQuery, EntityStringQuery { @Dependency var data: UTMData func entities(for identifiers: [UUID]) async throws -> [UTMVirtualMachineEntity] { await MainActor.run { data .virtualMachines .filter({ identifiers.contains($0.id) }) .map({ UTMVirtualMachineEntity(from: $0) }) } } func entities(matching: String) async throws -> [UTMVirtualMachineEntity] { await MainActor.run { data .virtualMachines .filter({ $0.detailsTitleLabel.localizedCaseInsensitiveContains(matching) }) .map({ UTMVirtualMachineEntity(from: $0) }) } } func suggestedEntities() async throws -> [UTMVirtualMachineEntity] { await MainActor.run { data .virtualMachines .map({ UTMVirtualMachineEntity(from: $0) }) } } } @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) extension UTMVirtualMachineEntityQuery: EntityPropertyQuery { /** The type of the comparator to use for the property query. This sample uses `Predicate`, but other apps could use `NSPredicate` (for Core Data) or an entirely custom comparator that works with an existing data model. */ typealias ComparatorMappingType = Predicate /** Declare the entity properties that are available for queries and in the Find intent, along with the comparator the app uses when querying the property. */ static let properties = QueryProperties { Property(\UTMVirtualMachineEntity.$name) { ContainsComparator { searchValue in #Predicate { $0.name.localizedStandardContains(searchValue) } } EqualToComparator { searchValue in #Predicate { $0.name == searchValue } } NotEqualToComparator { searchValue in #Predicate { $0.name != searchValue } } } Property(\UTMVirtualMachineEntity.$state) { EqualToComparator { searchValue in #Predicate { $0.state == searchValue } } NotEqualToComparator { searchValue in #Predicate { $0.state != searchValue } } } } /// Declare the entity properties available as sort criteria in the Find intent. static let sortingOptions = SortingOptions { SortableBy(\UTMVirtualMachineEntity.$name) } /// The text that people see in the Shortcuts app, describing what this intent does. static var findIntentDescription: IntentDescription? { IntentDescription("Search for a virtual machine.", searchKeywords: ["virtual machine", "vm"], resultValueName: "Virtual Machines") } /// Performs the Find intent using the predicates that the individual enters in the Shortcuts app. func entities(matching comparators: [Predicate], mode: ComparatorMode, sortedBy: [EntityQuerySort], limit: Int?) async throws -> [UTMVirtualMachineEntity] { logger.debug("[UTMVirtualMachineEntityQuery] Property query started") /// Get the trail entities that meet the criteria of the comparators. var matchedVms = try await virtualMachines(matching: comparators, mode: mode) /** Apply the requested sort. `EntityQuerySort` specifies the value to sort by using a `PartialKeyPath`. This key path builds a `KeyPathComparator` to use default sorting implementations for the value that the key path provides. For example, this approach uses `SortComparator.localizedStandard` when sorting key paths with a `String` value. */ logger.debug("[UTMVirtualMachineEntityQuery] Sorting results") for sortOperation in sortedBy { switch sortOperation.by { case \.$name: matchedVms.sort(using: KeyPathComparator(\UTMVirtualMachineEntity.name, order: sortOperation.order.sortOrder)) default: break } } /** People can optionally customize a limit to the number of results that a query returns. If your data model supports query limits, you can also use the limit parameter when querying your data model, to allow for faster searches. */ if let limit, matchedVms.count > limit { logger.debug("[UTMVirtualMachineEntityQuery] Limiting results to \(limit)") matchedVms.removeLast(matchedVms.count - limit) } logger.debug("[UTMVirtualMachineEntityQuery] Property query complete") return matchedVms } /// - Returns: The trail entities that meet the criteria of `comparators` and `mode`. @MainActor private func virtualMachines(matching comparators: [Predicate], mode: ComparatorMode) throws -> [UTMVirtualMachineEntity] { try data.virtualMachines.compactMap { vm in let entity = UTMVirtualMachineEntity(from: vm) /** For an AND search (criteria1 AND criteria2 AND ...), this variable starts as `true`. If any of the comparators don't match, the app sets it to `false`, allowing the comparator loop to break early because a comparator doesn't satisfy the AND requirement. For an OR search (criteria1 OR criteria2 OR ...), this variable starts as `false`. If any of the comparators match, the app sets it to `true`, allowing the comparator loop to break early because any comparator that matches satisfies the OR requirement. */ var includeAsResult = mode == .and ? true : false let earlyBreakCondition = includeAsResult logger.debug("[UTMVirtualMachineEntityQuery] Starting to evaluate predicates for \(entity.name)") for comparator in comparators { guard includeAsResult == earlyBreakCondition else { logger.debug("[UTMVirtualMachineEntityQuery] Predicates matched? \(includeAsResult)") break } /// Runs the `Predicate` expression with the specific `TrailEntity` to determine whether the entity matches the conditions. includeAsResult = try comparator.evaluate(entity) } logger.debug("[UTMVirtualMachineEntityQuery] Predicates matched? \(includeAsResult)") return includeAsResult ? entity : nil } } } @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) private extension EntityQuerySort.Ordering { /// Convert sort information from `EntityQuerySort` to Foundation's `SortOrder`. var sortOrder: SortOrder { switch self { case .ascending: return SortOrder.forward case .descending: return SortOrder.reverse } } } ================================================ FILE: JailbreakInterposer/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString 1.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) ================================================ FILE: JailbreakInterposer/JailbreakInterposer.c ================================================ // // 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. // #include #if !TARGET_OS_SIMULATOR #include #include extern int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize); extern kern_return_t _IOServiceSetAuthorizationID(io_service_t service, uint64_t authorizationID); /* bsd/sys/proc_info.h */ struct proc_uniqidentifierinfo { uint8_t p_uuid[16]; /* UUID of the main executable */ uint64_t p_uniqueid; /* 64 bit unique identifier for process */ uint64_t p_puniqueid; /* unique identifier for process's parent */ uint64_t p_reserve2; /* reserved for future use */ uint64_t p_reserve3; /* reserved for future use */ uint64_t p_reserve4; /* reserved for future use */ }; #define PROC_PIDUNIQIDENTIFIERINFO 17 /** * On iOS, IOServiceAuthorizeAgent (XPC) is not defined, so we hook the call and set the authorization ID directly. * This requires the `com.apple.private.iokit.IOServiceSetAuthorizationID` entitlement. */ static kern_return_t IOServiceAuthorizeReplacement(io_service_t service, uint32_t options) { kern_return_t status; pid_t processID; struct proc_uniqidentifierinfo authorizationID = { 0 }; processID = getpid(); proc_pidinfo(processID, PROC_PIDUNIQIDENTIFIERINFO, 0, &authorizationID, sizeof(authorizationID)); status = _IOServiceSetAuthorizationID(service, authorizationID.p_uniqueid); return status; } __attribute__ ((used, section ("__DATA,__interpose"))) static struct { void *replacement, *original; } replace_IOServiceAuthorize = { IOServiceAuthorizeReplacement, IOServiceAuthorize }; #endif ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. ================================================ FILE: Platform/AppIcon-Remote.icon/icon.json ================================================ { "fill-specializations" : [ { "value" : { "linear-gradient" : [ "display-p3:0.46275,0.94118,0.33333,1.00000", "display-p3:0.09020,0.23922,0.11765,1.00000" ] } }, { "appearance" : "dark", "value" : "system-dark" } ], "groups" : [ { "blend-mode" : "normal", "blur-material" : null, "hidden" : false, "layers" : [ { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.46275,0.94118,0.33333,1.00000", "display-p3:0.09020,0.23922,0.11765,1.00000" ] } } ], "image-name" : "InnerCircle.svg", "name" : "InnerCircle", "opacity" : 1 }, { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.46275,0.94118,0.33333,1.00000", "display-p3:0.09020,0.23922,0.11765,1.00000" ] } } ], "image-name" : "Ring3.svg", "name" : "Ring3", "opacity" : 1 }, { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.46275,0.94118,0.33333,1.00000", "display-p3:0.09020,0.23922,0.11765,1.00000" ] } } ], "image-name" : "Ring2.svg", "name" : "Ring2", "opacity" : 1 }, { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.46275,0.94118,0.33333,1.00000", "display-p3:0.09020,0.23922,0.11765,1.00000" ] } } ], "image-name" : "Ring1.svg", "name" : "Ring1", "opacity" : 1 } ], "lighting" : "individual", "opacity" : 1, "position" : { "scale" : 1, "translation-in-points" : [ 0, 0 ] }, "shadow" : { "kind" : "neutral", "opacity" : 0.5 }, "specular" : true, "translucency" : { "enabled" : true, "value" : 0.5 } } ], "supported-platforms" : { "circles" : [ "watchOS" ], "squares" : "shared" } } ================================================ FILE: Platform/AppIcon.icon/icon.json ================================================ { "fill-specializations" : [ { "value" : { "linear-gradient" : [ "display-p3:0.34510,0.56078,0.93725,1.00000", "display-p3:0.00392,0.00784,0.63922,1.00000" ] } }, { "appearance" : "dark", "value" : "system-dark" } ], "groups" : [ { "blend-mode" : "normal", "blur-material" : null, "hidden" : false, "layers" : [ { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.34510,0.56078,0.93725,1.00000", "display-p3:0.00392,0.00784,0.63922,1.00000" ] } } ], "image-name" : "InnerCircle.svg", "name" : "InnerCircle", "opacity" : 1 }, { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.34510,0.56078,0.93725,1.00000", "display-p3:0.00392,0.00784,0.63922,1.00000" ] } } ], "image-name" : "Ring3.svg", "name" : "Ring3", "opacity" : 1 }, { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.34510,0.56078,0.93725,1.00000", "display-p3:0.00392,0.00784,0.63922,1.00000" ] } } ], "image-name" : "Ring2.svg", "name" : "Ring2", "opacity" : 1 }, { "fill-specializations" : [ { "value" : { "solid" : "srgb:1.00000,1.00000,1.00000,1.00000" } }, { "appearance" : "dark", "value" : { "linear-gradient" : [ "display-p3:0.34510,0.56078,0.93725,1.00000", "display-p3:0.00392,0.00784,0.63922,1.00000" ] } } ], "image-name" : "Ring1.svg", "name" : "Ring1", "opacity" : 1 } ], "lighting" : "individual", "opacity" : 1, "position" : { "scale" : 1, "translation-in-points" : [ 0, 0 ] }, "shadow" : { "kind" : "neutral", "opacity" : 0.5 }, "specular" : true, "translucency" : { "enabled" : true, "value" : 0.5 } } ], "supported-platforms" : { "circles" : [ "watchOS" ], "squares" : "shared" } } ================================================ FILE: Platform/Assets.xcassets/AccentColor-Remote.colorset/Contents.json ================================================ { "colors" : [ { "color" : { "color-space" : "srgb", "components" : { "alpha" : "1.000", "blue" : "0.098", "green" : "0.784", "red" : "0.000" } }, "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AccentColor.colorset/Contents.json ================================================ { "colors" : [ { "color" : { "color-space" : "srgb", "components" : { "alpha" : "1.000", "blue" : "0.922", "green" : "0.510", "red" : "0.247" } }, "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.appiconset/Contents.json ================================================ { "images" : [ { "filename" : "icon_20pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "20x20" }, { "filename" : "icon_20pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "20x20" }, { "filename" : "icon_29pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "29x29" }, { "filename" : "icon_29pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "29x29" }, { "filename" : "icon_76pt.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "38x38" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "38x38" }, { "filename" : "icon_40pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "40x40" }, { "filename" : "icon_40pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "40x40" }, { "filename" : "icon_60pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "60x60" }, { "filename" : "icon_60pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "60x60" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "64x64" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "64x64" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "68x68" }, { "filename" : "icon_76pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "76x76" }, { "filename" : "icon_83.5@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "83.5x83.5" }, { "filename" : "Icon.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_20pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_20pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_29pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_29pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_76pt.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_40pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_40pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_60pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_60pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "68x68" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_76pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "76x76" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_83.5@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "83.5x83.5" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "Icon_dark.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "68x68" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "76x76" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "83.5x83.5" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json ================================================ { "images" : [ { "filename" : "Back@2x.png", "idiom" : "vision", "scale" : "2x" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Back.solidimagestacklayer/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 }, "layers" : [ { "filename" : "Front.solidimagestacklayer" }, { "filename" : "Middle.solidimagestacklayer" }, { "filename" : "Back.solidimagestacklayer" } ] } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json ================================================ { "images" : [ { "filename" : "Front@2x.png", "idiom" : "reality", "scale" : "2x" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Front.solidimagestacklayer/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "reality", "scale" : "2x" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon-Remote.solidimagestack/Middle.solidimagestacklayer/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "filename" : "icon_20pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "20x20" }, { "filename" : "icon_20pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "20x20" }, { "filename" : "icon_29pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "29x29" }, { "filename" : "icon_29pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "29x29" }, { "filename" : "icon_76pt.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "38x38" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "38x38" }, { "filename" : "icon_40pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "40x40" }, { "filename" : "icon_40pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "40x40" }, { "filename" : "icon_60pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "60x60" }, { "filename" : "icon_60pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "60x60" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "64x64" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "64x64" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "68x68" }, { "filename" : "icon_76pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "76x76" }, { "filename" : "icon_83.5@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "83.5x83.5" }, { "filename" : "Icon.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_20pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_20pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_29pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_29pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_76pt.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_40pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_40pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_60pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_60pt@3x.png", "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "68x68" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_76pt@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "76x76" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_dark_83.5@2x.png", "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "83.5x83.5" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "Icon_dark.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "20x20" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "29x29" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "38x38" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "40x40" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "60x60" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "64x64" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "68x68" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "76x76" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "83.5x83.5" }, { "appearances" : [ { "appearance" : "luminosity", "value" : "tinted" } ], "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, { "filename" : "icon_16pt.png", "idiom" : "mac", "scale" : "1x", "size" : "16x16" }, { "filename" : "icon_16pt@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "16x16" }, { "filename" : "icon_32pt.png", "idiom" : "mac", "scale" : "1x", "size" : "32x32" }, { "filename" : "icon_32pt@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "32x32" }, { "filename" : "icon_128pt.png", "idiom" : "mac", "scale" : "1x", "size" : "128x128" }, { "filename" : "icon_128pt@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "128x128" }, { "filename" : "icon_256pt.png", "idiom" : "mac", "scale" : "1x", "size" : "256x256" }, { "filename" : "icon_256pt@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, { "filename" : "icon_512pt.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, { "filename" : "icon_512pt@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json ================================================ { "images" : [ { "filename" : "Back@2x.png", "idiom" : "reality", "scale" : "2x" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon.solidimagestack/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 }, "layers" : [ { "filename" : "Front.solidimagestacklayer" }, { "filename" : "Middle.solidimagestacklayer" }, { "filename" : "Back.solidimagestacklayer" } ] } ================================================ FILE: Platform/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json ================================================ { "images" : [ { "filename" : "Front@2x.png", "idiom" : "reality", "scale" : "2x" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "reality", "scale" : "2x" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/Contents.json ================================================ { "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/Keyboard Hide.imageset/Contents.json ================================================ { "images" : [ { "filename" : "chevron.down@1x.png", "idiom" : "universal", "scale" : "1x" }, { "filename" : "chevron.down@2x.png", "idiom" : "universal", "scale" : "2x" }, { "filename" : "chevron.down@3x.png", "idiom" : "universal", "scale" : "3x" } ], "info" : { "author" : "xcode", "version" : 1 }, "properties" : { "template-rendering-intent" : "template" } } ================================================ FILE: Platform/Assets.xcassets/Keyboard Paste.imageset/Contents.json ================================================ { "images" : [ { "filename" : "doc.on.clipboard@1x.png", "idiom" : "universal", "scale" : "1x" }, { "filename" : "doc.on.clipboard@2x.png", "idiom" : "universal", "scale" : "2x" }, { "filename" : "doc.on.clipboard@3x.png", "idiom" : "universal", "scale" : "3x" } ], "info" : { "author" : "xcode", "version" : 1 }, "properties" : { "template-rendering-intent" : "template" } } ================================================ FILE: Platform/Assets.xcassets/Logo-Linux.imageset/Contents.json ================================================ { "images" : [ { "filename" : "linux.pdf", "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/Logo-Windows.imageset/Contents.json ================================================ { "images" : [ { "filename" : "windows.pdf", "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/Logo-macOS.imageset/Contents.json ================================================ { "images" : [ { "filename" : "macos.pdf", "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: Platform/Assets.xcassets/MenuBarExtra.imageset/Contents.json ================================================ { "images" : [ { "filename" : "icon_16pt.png", "idiom" : "mac", "scale" : "1x" }, { "filename" : "icon_16pt@2x.png", "idiom" : "mac", "scale" : "2x" } ], "info" : { "author" : "xcode", "version" : 1 }, "properties" : { "template-rendering-intent" : "template" } } ================================================ FILE: Platform/Assets.xcassets/Toolbar USB.imageset/Contents.json ================================================ { "images" : [ { "filename" : "usb-cable@1x.png", "idiom" : "universal", "scale" : "1x" }, { "filename" : "usb-cable@2x.png", "idiom" : "universal", "scale" : "2x" }, { "filename" : "usb-cable@3x.png", "idiom" : "universal", "scale" : "3x" } ], "info" : { "author" : "xcode", "version" : 1 }, "properties" : { "template-rendering-intent" : "template" } } ================================================ FILE: Platform/Main.swift ================================================ // // 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 Logging import TipKit let logger = Logger(label: "com.utmapp.UTM") { label in var utmLogger = UTMLoggingSwift(label: label) var stdOutLogger = StreamLogHandler.standardOutput(label: label) #if DEBUG utmLogger.logLevel = .debug stdOutLogger.logLevel = .debug #endif return MultiplexLogHandler([ utmLogger, stdOutLogger ]) } @main class Main { static var jitAvailable = true static func main() { #if (os(iOS) || os(visionOS)) && WITH_JIT // check if we have jailbreak if jb_spawn_ptrace_child(CommandLine.argc, CommandLine.unsafeArgv) { logger.info("JIT: ptrace() child spawn trick") } else if jb_has_jit_entitlement() { logger.info("JIT: found entitlement") } else if jb_has_cs_disabled() { logger.info("JIT: CS_KILL disabled") } else if jb_has_cs_execseg_allow_unsigned() { logger.info("JIT: CS_EXECSEG_ALLOW_UNSIGNED set") } else if jb_enable_ptrace_hack() { logger.info("JIT: ptrace() hack supported") } else { logger.info("JIT: ptrace() hack failed") jitAvailable = false } // raise memlimits on jailbroken devices if jb_increase_memlimit() { logger.info("MEM: successfully removed memory limits") } #endif // do patches UTMPatches.patchAll() #if os(iOS) || os(visionOS) // register defaults registerDefaultsFromSettingsBundle() // register tips if #available(iOS 17, macOS 14, *) { try? Tips.configure() } #endif UTMApp.main() } // https://stackoverflow.com/a/44675628 static private func registerDefaultsFromSettingsBundle() { let userDefaults = UserDefaults.standard if let settingsURL = Bundle.main.url(forResource: "Root", withExtension: "plist", subdirectory: "Settings.bundle"), let settings = NSDictionary(contentsOf: settingsURL), let preferences = settings["PreferenceSpecifiers"] as? [NSDictionary] { var defaultsToRegister = [String: AnyObject]() for prefSpecification in preferences { if let key = prefSpecification["Key"] as? String, let value = prefSpecification["DefaultValue"] { defaultsToRegister[key] = value as AnyObject logger.debug("registerDefaultsFromSettingsBundle: (\(key), \(value)) \(type(of: value))") } } // register version numbers if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] { userDefaults.set(version, forKey: "LastBootedVersion") } if let build = Bundle.main.infoDictionary?["CFBundleVersion"] { userDefaults.set(build, forKey: "LastBootedBuild") } userDefaults.register(defaults: defaultsToRegister) } else { logger.debug("registerDefaultsFromSettingsBundle: Could not find Settings.bundle") } } } ================================================ FILE: Platform/Shared/BigButtonStyle.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 SwiftUI struct BigButtonStyle: ButtonStyle { let width: CGFloat? let height: CGFloat? fileprivate struct BigButtonView: View { let width: CGFloat? let height: CGFloat? let configuration: BigButtonStyle.Configuration @Environment(\.isEnabled) private var isEnabled: Bool #if os(macOS) let defaultColor = Color(NSColor.controlColor) let pressedColor = Color(NSColor.controlAccentColor) let foregroundColor = Color(NSColor.controlTextColor) let foregroundDisabledColor = Color(NSColor.disabledControlTextColor) let foregroundPressedColor = Color(NSColor.selectedControlTextColor) #else let defaultColor = Color(UIColor.tertiarySystemFill) let pressedColor = Color(UIColor.systemFill) let foregroundColor = Color(UIColor.label) let foregroundDisabledColor = Color(UIColor.systemGray) let foregroundPressedColor = Color(UIColor.secondaryLabel) #endif var body: some View { ZStack { RoundedRectangle(cornerRadius: 10.0) .fill(configuration.isPressed ? pressedColor : defaultColor) #if os(iOS) || os(visionOS) .hoverEffect() .scaleEffect(configuration.isPressed ? 0.95 : 1) #endif configuration.label .foregroundColor(isEnabled ? (configuration.isPressed ? foregroundPressedColor : foregroundColor) : foregroundDisabledColor) }.frame(width: width, height: height) } } func makeBody(configuration: Configuration) -> some View { BigButtonView(width: width, height: height, configuration: configuration) } } ================================================ FILE: Platform/Shared/BusyIndicator.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 SwiftUI struct BusyIndicator: View { @Binding var progress: Float? init(progress: Binding = .constant(nil)) { _progress = progress } var body: some View { progressView .frame(width: 100, height: 100, alignment: .center) .foregroundColor(.white) .background(Color.gray.opacity(0.5)) .clipShape(RoundedRectangle(cornerRadius: 25.0, style: .continuous)) } #if os(macOS) @ViewBuilder private var progressView: some View { if let progress = progress { ProgressView(value: progress) .progressViewStyle(.circular) .controlSize(.large) } else { Spinner(size: .large) } } #else // TODO: implement progress spinner for iOS @ViewBuilder private var progressView: some View { Spinner(size: .large) } #endif } struct BusyIndicator_Previews: PreviewProvider { static var previews: some View { BusyIndicator() } } ================================================ FILE: Platform/Shared/BusyOverlay.swift ================================================ // // 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 SwiftUI struct BusyOverlay: View { @EnvironmentObject private var data: UTMData var body: some View { Group { if data.busy { BusyIndicator(progress: $data.busyProgress) } else { EmptyView() } } .alert(item: $data.alertItem) { item in switch item { case .downloadUrl(let url): return Alert(title: Text("Download VM"), message: Text("Do you want to download '\(url)'?"), primaryButton: .cancel(), secondaryButton: .default(Text("Download")) { data.downloadUTMZip(from: url) }) case .message(let message): return Alert(title: Text(message)) case .localizedMessage(let message): return Alert(title: Text(message)) } } } } struct BusyOverlay_Previews: PreviewProvider { static var previews: some View { BusyOverlay() } } ================================================ FILE: Platform/Shared/ContentView.swift ================================================ // // 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 SwiftUI import UniformTypeIdentifiers #if os(iOS) import IQKeyboardManagerSwift #endif import TipKit // on visionOS, there is no text to show more than UTM #if WITH_QEMU_TCI && !os(visionOS) let productName = "UTM SE" #elseif WITH_REMOTE && !os(visionOS) let productName = "UTM Remote" #else let productName = "UTM" #endif struct ContentView: View { @State private var editMode = false @EnvironmentObject private var data: UTMData @StateObject private var releaseHelper = UTMReleaseHelper() @State private var openSheetPresented = false @Environment(\.openURL) var openURL @AppStorage("ServerAutostart") private var isServerAutostart: Bool = false var body: some View { VMNavigationListView() .overlay(data.showSettingsModal ? AnyView(EmptyView()) : AnyView(BusyOverlay())) #if os(macOS) || os(visionOS) .frame(minWidth: 800, idealWidth: 1200, minHeight: 600, idealHeight: 800) #endif .disabled(data.busy && !data.showNewVMSheet && !data.showSettingsModal) .sheet(isPresented: $releaseHelper.isReleaseNotesShown, onDismiss: { releaseHelper.closeReleaseNotes() if #available(iOS 17, macOS 14, *) { UTMTipCreateVM.isVMListEmpty = data.virtualMachines.count == 0 } }, content: { VMReleaseNotesView(helper: releaseHelper).padding() }) .onReceive(NSNotification.ShowReleaseNotes) { _ in Task { await releaseHelper.fetchReleaseNotes(force: true) } } .onOpenURL(perform: handleURL) .handlesExternalEvents(preferring: ["*"], allowing: ["*"]) .onReceive(NSNotification.NewVirtualMachine) { _ in data.newVM() }.onReceive(NSNotification.OpenVirtualMachine) { _ in // VMNavigationListView also gets this notification and closes the wizard sheet openSheetPresented = false // FIXME: SwiftUI bug on iOS requires this wait DispatchQueue.main.asyncAfter(deadline: .now() + 0.02) { openSheetPresented = true } }.fileImporter(isPresented: $openSheetPresented, allowedContentTypes: [.UTM, .UTMextension], allowsMultipleSelection: true, onCompletion: selectImportedUTM) .onReceive(NSNotification.InstallGuestTools) { notification in guard let vm = notification.object as? any UTMVirtualMachine else { logger.error("InstallGuestTools notification but no VM object is provided!") return } Task { data.busyWorkAsync { try await data.mountSupportTools(for: vm) } } } .onDrop(of: [.fileURL], delegate: self) .onAppear { Task { await data.listRefresh() await releaseHelper.fetchReleaseNotes() if #available(iOS 17, macOS 14, *) { if !releaseHelper.isReleaseNotesShown { UTMTipCreateVM.isVMListEmpty = data.virtualMachines.count == 0 UTMTipDonate.timesLaunched += 1 } } #if os(macOS) if isServerAutostart { await data.remoteServer.start() } #endif } #if os(macOS) NSWindow.allowsAutomaticWindowTabbing = false #else data.triggeriOSNetworkAccessPrompt() #if !os(visionOS) IQKeyboardManager.shared.enable = true #endif #if WITH_JIT if !Main.jitAvailable { data.busyWorkAsync { let jitStreamerAttach = UserDefaults.standard.bool(forKey: "JitStreamerAttach") if #available(iOS 15, *), jitStreamerAttach { try await data.jitStreamerAttach() return } #if canImport(AltKit) if await data.isAltServerCompatible { try await data.startAltJIT() return } #endif // ignore error when we are running on a HV only build if !UTMCapabilities.current.contains(.hasHypervisorSupport) { throw NSLocalizedString("Your version of iOS does not support running VMs while unmodified. You must either run UTM while jailbroken or with a remote debugger attached. See https://getutm.app/install/ for more details.", comment: "ContentView") } } } #endif #endif } #if WITH_SERVER .onChange(of: isServerAutostart) { newValue in if newValue { Task { if isServerAutostart && !data.remoteServer.state.isServerActive { await data.remoteServer.start() } } } } #endif } private func handleURL(url: URL) { if let components = URLComponents(url: url, resolvingAgainstBaseURL: false), components.scheme?.lowercased() == "utm", components.host == "downloadVM", let urlParameter = components.queryItems?.first(where: { $0.name == "url" })?.value, let url = URL(string: urlParameter) { if data.alertItem == nil { data.showNewVMSheet = false data.alertItem = .downloadUrl(url) } } else if url.isFileURL { data.busyWorkAsync { try await importUTM(url: url) } } } private func importUTM(url: URL) async throws { guard url.isFileURL else { return // ignore } try await data.importUTM(from: url) } private func selectImportedUTM(result: Result<[URL], Error>) { data.busyWorkAsync { let urls = try result.get() for url in urls { try await data.importUTM(from: url) } } } } extension ContentView: DropDelegate { func validateDrop(info: DropInfo) -> Bool { !urlsFrom(info: info).isEmpty } func performDrop(info: DropInfo) -> Bool { let urls = urlsFrom(info: info) data.busyWorkAsync { for url in urls { try await data.importUTM(from: url) } } return true } private func urlsFrom(info: DropInfo) -> [URL] { let providers = info.itemProviders(for: [.fileURL]) var validURLs: [URL] = [] let group = DispatchGroup() providers.forEach { provider in group.enter() _ = provider.loadObject(ofClass: URL.self) { url, _ in if url?.pathExtension == "utm" { validURLs.append(url!) } group.leave() } } group.wait() return validURLs } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } ================================================ FILE: Platform/Shared/DefaultTextField.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 SwiftUI struct DefaultTextField: View { private let titleKey: LocalizedStringKey private let text: Binding private let prompt: LocalizedStringKey private let onEditingChanged: (Bool) -> Void init(_ titleKey: LocalizedStringKey, text: Binding, prompt: LocalizedStringKey = "", onEditingChanged: @escaping (Bool) -> Void = { _ in }) { self.titleKey = titleKey self.text = text self.prompt = prompt self.onEditingChanged = onEditingChanged } var body: some View { let stack = HStack { Text(titleKey) if titleKey.localizedString.count > 0 { Spacer() } TextField(prompt, text: text, onEditingChanged: onEditingChanged) } #if os(macOS) if #available(iOS 15, macOS 12, *) { DefaultTextFieldNew(titleKey, text: text, prompt: prompt, onEditingChanged: onEditingChanged) } else { stack } #else stack #endif } } @available(iOS 15, macOS 12, *) struct DefaultTextFieldNew: View { private let titleKey: LocalizedStringKey @Binding var text: String private let prompt: LocalizedStringKey private let onEditingChanged: (Bool) -> Void @FocusState private var focused: Bool init(_ titleKey: LocalizedStringKey, text: Binding, prompt: LocalizedStringKey = "", onEditingChanged: @escaping (Bool) -> Void = { _ in }) { self.titleKey = titleKey self._text = text self.prompt = prompt self.onEditingChanged = onEditingChanged } var body: some View { TextField(titleKey, text: $text, prompt: Text(prompt)) .focused($focused) .onChange(of: text) { newValue in onEditingChanged(focused) } .onSubmit { focused = false onEditingChanged(false) } } } struct DefaultTextField_Previews: PreviewProvider { static var previews: some View { DefaultTextField("Test", text: .constant("Value"), prompt: "Prompt") } } ================================================ FILE: Platform/Shared/DestructiveButton.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 SwiftUI struct DestructiveButton