Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Configuration/QEMUConstant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,24 @@ extension QEMUTarget {
}
}

var hasUsbSharingSupport: Bool {
switch self.rawValue {
case let x where x.hasPrefix("raspi"): return false
default: return true
}
}

var hasAgentSupport: Bool {
switch self.rawValue {
case "isapc": return false
case let x where x.hasPrefix("raspi"): return false
default: return true
}
}

var hasUefiSupport: Bool {
switch self.rawValue {
case let x where x.hasPrefix("raspi"): return false
default: return true
}
}
Expand All @@ -491,6 +506,29 @@ extension QEMUTarget {
default: return true
}
}

var hasHypervisorSupport: Bool {
switch self.rawValue {
case let x where x.hasPrefix("raspi"): return false
default: return true
}
}

var hasBuiltinFramebuffer: Bool {
switch self.rawValue {
case let x where x.hasPrefix("raspi"): return true
default: return false
}
}

var fixedMemorySize: Int? {
switch self.rawValue {
case "raspi0", "raspi1ap", "raspi3ap": return 512
case "raspi2b", "raspi3b": return 1024
case "raspi4b": return 2048
default: return nil
}
}
}

#if WITH_QEMU_TCI
Expand Down
56 changes: 30 additions & 26 deletions Configuration/UTMQemuConfiguration+Arguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ import Virtualization // for getting network interfaces
"vgamem_mb=\(vgaRamSize)"
}
f()
} else if system.target.hasBuiltinFramebuffer {
// Use the board's built-in framebuffer (no arguments)
} else {
for display in displays {
if !shouldSkipDisplay(display) {
Expand Down Expand Up @@ -951,36 +953,38 @@ import Virtualization // for getting network interfaces
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..<buses {
f("-device")
f("\(controller),id=usb-controller-\(i)")
if system.target.hasUsbSharingSupport {
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..<buses {
f("-device")
f("\(controller),id=usb-controller-\(i)")
}
} else {
for i in 0..<buses {
f("-device")
f("ich9-usb-ehci1,id=usb-controller-\(i)")
f("-device")
f("ich9-usb-uhci1,masterbus=usb-controller-\(i).0,firstport=0,multifunction=on")
f("-device")
f("ich9-usb-uhci2,masterbus=usb-controller-\(i).0,firstport=2,multifunction=on")
f("-device")
f("ich9-usb-uhci3,masterbus=usb-controller-\(i).0,firstport=4,multifunction=on")
}
}
} else {
for i in 0..<buses {
f("-device")
f("ich9-usb-ehci1,id=usb-controller-\(i)")
f("-device")
f("ich9-usb-uhci1,masterbus=usb-controller-\(i).0,firstport=0,multifunction=on")
f("-device")
f("ich9-usb-uhci2,masterbus=usb-controller-\(i).0,firstport=2,multifunction=on")
// set up usb forwarding
for i in 0..<maxDevices {
f("-chardev")
f("spicevmc,name=usbredir,id=usbredirchardev\(i)")
f("-device")
f("ich9-usb-uhci3,masterbus=usb-controller-\(i).0,firstport=4,multifunction=on")
f("usb-redir,chardev=usbredirchardev\(i),id=usbredirdev\(i),bus=usb-controller-\(i/3).0")
}
}
// set up usb forwarding
for i in 0..<maxDevices {
f("-chardev")
f("spicevmc,name=usbredir,id=usbredirchardev\(i)")
f("-device")
f("usb-redir,chardev=usbredirchardev\(i),id=usbredirdev\(i),bus=usb-controller-\(i/3).0")
}
#endif
}

Expand Down
3 changes: 3 additions & 0 deletions Configuration/UTMQemuConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ extension UTMQemuConfiguration {
input = .init(forArchitecture: architecture, target: target)
sharing = .init(forArchitecture: architecture, target: target)
system.cpu = architecture.cpuType.default
if let fixedMemorySize = target.fixedMemorySize {
system.memorySize = fixedMemorySize
}
if let display = UTMQemuConfigurationDisplay(forArchitecture: architecture, target: target) {
displays = [display]
} else {
Expand Down
2 changes: 2 additions & 0 deletions Configuration/UTMQemuConfigurationNetwork.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ extension UTMQemuConfigurationNetwork {
hardware = QEMUNetworkDevice_ppc.sungem
} else if architecture == .m68k && rawTarget == QEMUTarget_m68k.q800.rawValue {
hardware = QEMUNetworkDevice_m68k.dp8393x
} else if rawTarget.hasPrefix("raspi") {
return nil
} else {
let cards = architecture.networkDeviceType.allRawValues
if let first = cards.first {
Expand Down
2 changes: 1 addition & 1 deletion Configuration/UTMQemuConfigurationQEMU.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ extension UTMQemuConfigurationQEMU {
hasUefiBoot = true
hasRNGDevice = true
}
hasHypervisor = architecture.hasHypervisorSupport
hasHypervisor = architecture.hasHypervisorSupport && target.hasHypervisorSupport
}
}

Expand Down
2 changes: 2 additions & 0 deletions Configuration/UTMQemuConfigurationSound.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ extension UTMQemuConfigurationSound {
hardware = QEMUSoundDevice_ppc.screamer
} else if architecture == .m68k && rawTarget == QEMUTarget_m68k.q800.rawValue {
hardware = QEMUSoundDevice_m68k.asc
} else if rawTarget.hasPrefix("raspi") {
return nil
} else {
let cards = architecture.soundDeviceType.allRawValues
if let first = cards.first {
Expand Down
11 changes: 10 additions & 1 deletion Platform/Shared/VMConfigDisplayView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@ struct VMConfigDisplayView: View {
VStack {
Form {
Section(header: Text("Hardware")) {
VMConfigConstantPicker("Emulated Display Card", selection: $config.hardware, type: system.architecture.displayDeviceType)
if system.target.hasBuiltinFramebuffer {
HStack {
Text("Emulated Display Card")
Spacer()
Text("Built-in Framebuffer")
.foregroundColor(.secondary)
}
} else {
VMConfigConstantPicker("Emulated Display Card", selection: $config.hardware, type: system.architecture.displayDeviceType)
}

Toggle("GPU Acceleration Supported", isOn: .constant(isGLSupported)).disabled(true)
if isGLSupported {
Expand Down
5 changes: 3 additions & 2 deletions Platform/Shared/VMConfigInputView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import SwiftUI
struct VMConfigInputView: View {
@Binding var config: UTMQemuConfigurationInput
let hasUsbSupport: Bool
let hasUsbSharingSupport: Bool

var body: some View {
VStack {
Expand All @@ -29,7 +30,7 @@ struct VMConfigInputView: View {
}

#if WITH_USB
if config.usbBusSupport != .disabled {
if config.usbBusSupport != .disabled && hasUsbSharingSupport {
Section(header: Text("USB Sharing")) {
if !jb_has_usb_entitlement() {
Text("USB sharing not supported in this build of UTM.")
Expand Down Expand Up @@ -101,7 +102,7 @@ struct VMConfigInputView_Previews: PreviewProvider {
@State static private var config = UTMQemuConfigurationInput()

static var previews: some View {
VMConfigInputView(config: $config, hasUsbSupport: true)
VMConfigInputView(config: $config, hasUsbSupport: true, hasUsbSharingSupport: true)
#if os(macOS)
.scrollable()
#endif
Expand Down
3 changes: 2 additions & 1 deletion Platform/Shared/VMConfigQEMUView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct VMConfigQEMUView: View {

private var supportsUefi: Bool {
UTMQemuConfigurationQEMU.uefiImagePrefix(forArchitecture: system.architecture) != nil
&& system.target.hasUefiSupport
}

private var supportsPs2: Bool {
Expand Down Expand Up @@ -80,7 +81,7 @@ struct VMConfigQEMUView: View {
}
Toggle("Use Hypervisor", isOn: $config.hasHypervisor)
.help("Only available if host architecture matches the target. Otherwise, TCG emulation is used.")
.disabled(!system.architecture.hasHypervisorSupport)
.disabled(!system.architecture.hasHypervisorSupport || !system.target.hasHypervisorSupport)
if config.hasHypervisor {
Toggle("Use TSO", isOn: $config.hasTSO)
.help("Only available when Hypervisor is used on supported hardware. TSO speeds up Intel emulation in the guest at the cost of decreased performance in general.")
Expand Down
4 changes: 4 additions & 0 deletions Platform/Shared/VMConfigSystemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct VMConfigSystemView: View {
Form {
HardwareOptions(config: $config, architecture: $architecture, target: $target, warningMessage: $warningMessage)
RAMSlider(systemMemory: $config.memorySize, onValidate: validateMemorySize)
.disabled(target.fixedMemorySize != nil)
Section(header: Text("CPU")) {
VMConfigConstantPicker(selection: $config.cpu, type: config.architecture.cpuType)
}
Expand Down Expand Up @@ -201,6 +202,9 @@ private struct HardwareOptions: View {
.onChange(of: config.target.rawValue) { newValue in
if newValue != target.rawValue {
target = AnyQEMUConstant(rawValue: newValue)!
if let fixedMemorySize = target.fixedMemorySize {
config.memorySize = fixedMemorySize
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions Platform/Shared/VMWizardHardwareView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,12 @@ struct VMWizardHardwareView: View {

Section {
VMConfigConstantPicker(selection: $wizardState.systemTarget, type: wizardState.systemArchitecture.targetType)
.onChange(of: wizardState.systemTarget.rawValue) { newValue in
let target = AnyQEMUConstant(rawValue: newValue)!
if let fixedMemorySize = target.fixedMemorySize {
wizardState.systemMemoryMib = fixedMemorySize
}
}
} header: {
Text("System")
}
Expand Down Expand Up @@ -240,6 +246,7 @@ struct VMWizardHardwareView: View {
wizardState.systemMemoryMib = validMin
}
}
.disabled(wizardState.systemTarget.fixedMemorySize != nil)
} header: {
Text("Memory")
}
Expand Down
1 change: 1 addition & 0 deletions Platform/Shared/VMWizardOSOtherView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct VMWizardOSOtherView: View {

private var supportsUefi: Bool {
UTMQemuConfigurationQEMU.uefiImagePrefix(forArchitecture: wizardState.systemArchitecture) != nil
&& wizardState.systemTarget.hasUefiSupport
}

var body: some View {
Expand Down
4 changes: 4 additions & 0 deletions Platform/ar.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@
/* No comment provided by engineer. */
"Build" = "بناء";

/* VMConfigDisplayView
VMToolbarDisplayMenuView */
"Built-in Framebuffer" = "مخزن الإطار المدمج";

/* UTMQemuConstants */
"Built-in Terminal" = "وحدة طرفية مدمجة";

Expand Down
4 changes: 4 additions & 0 deletions Platform/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@
/* No comment provided by engineer. */
"Browse…" = "Durchsuchen…";

/* VMConfigDisplayView
VMToolbarDisplayMenuView */
"Built-in Framebuffer" = "Integrierter Framebuffer";

/* UTMQemuConstants */
"Built-in Terminal" = "Integriertes Terminal";

Expand Down
4 changes: 4 additions & 0 deletions Platform/es-419.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@
/* No comment provided by engineer. */
"Browse…" = "Buscar...";

/* VMConfigDisplayView
VMToolbarDisplayMenuView */
"Built-in Framebuffer" = "Búfer de imagen integrado";

/* UTMQemuConstants */
"Built-in Terminal" = "Terminal incorporado";

Expand Down
4 changes: 4 additions & 0 deletions Platform/fi.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,10 @@
/* Left pane. */
"Devices" = "Laitteet";

/* VMConfigDisplayView
VMToolbarDisplayMenuView */
"Built-in Framebuffer" = "Sisäänrakennettu kuvapuskuri";

/* Serial pane. */
"Built-in Terminal" = "Sisäänrakennettu terminaali";

Expand Down
1 change: 1 addition & 0 deletions Platform/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@
"Upscaling" = "Augmentation de la définition (Upscaling)";
"Downscaling" = "Réduction de définition";
"Retina Mode" = "Mode Retina";
"Built-in Framebuffer" = "Tampon d’image intégré";

// VMConfigDisplayConsoleView.swift
"Style" = "Style";
Expand Down
4 changes: 4 additions & 0 deletions Platform/iOS/VMSessionState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ extension VMSessionState: UTMSpiceIODelegate {

nonisolated func spiceDidCreateDisplay(_ display: CSDisplay) {
Task { @MainActor in
guard !self.qemuConfig.system.target.hasBuiltinFramebuffer || !qemuConfig.displays.isEmpty else {
// A `CSDisplay` instance is created if the machine has a built-in framebuffer even if `qemuConfig.displays` is empty.
return
}
assert(display.monitorID < qemuConfig.displays.count)
let device = VMWindowState.Device.display(display, display.monitorID)
devices.append(device)
Expand Down
6 changes: 5 additions & 1 deletion Platform/iOS/VMSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ struct VMSettingsView: View {
.labelStyle(.roundRectIcon)
})
NavigationLink(
destination: VMConfigInputView(config: $config.input, hasUsbSupport: config.system.architecture.hasUsbSupport).navigationTitle("Input"),
destination: VMConfigInputView(
config: $config.input,
hasUsbSupport: config.system.architecture.hasUsbSupport,
hasUsbSharingSupport: config.system.target.hasUsbSharingSupport
).navigationTitle("Input"),
label: {
Label("Input", systemImage: "keyboard")
.labelStyle(.roundRectIcon)
Expand Down
6 changes: 6 additions & 0 deletions Platform/iOS/VMToolbarDisplayMenuView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct VMToolbarDisplayMenuView: View {
switch device {
case .serial(_, let index):
MenuLabel("Serial \(index): \(session.qemuConfig.serials[index].target.prettyValue)", systemImage: "rectangle.connected.to.line.below").tag(device as VMWindowState.Device?)
case .display(_, let index) where session.qemuConfig.system.target.hasBuiltinFramebuffer:
let prettyValue = NSLocalizedString("Built-in Framebuffer", comment: "VMToolbarDisplayMenuView")
MenuLabel("Display \(index): \(prettyValue)", systemImage: "display").tag(device as VMWindowState.Device?)
case .display(_, let index):
MenuLabel("Display \(index): \(session.qemuConfig.displays[index].hardware.prettyValue)", systemImage: "display").tag(device as VMWindowState.Device?)
}
Expand All @@ -59,6 +62,9 @@ struct VMToolbarDisplayMenuView: View {
switch device {
case .serial(_, let index):
MenuLabel("Serial \(index): \(session.qemuConfig.serials[index].target.prettyValue)", systemImage: "rectangle.connected.to.line.below").tag(device as VMWindowState.Device?)
case .display(_, let index) where session.qemuConfig.system.target.hasBuiltinFramebuffer:
let prettyValue = NSLocalizedString("Built-in Framebuffer", comment: "VMToolbarDisplayMenuView")
MenuLabel("Display \(index): \(prettyValue)", systemImage: "display").tag(device as VMWindowState.Device?)
case .display(_, let index):
MenuLabel("Display \(index): \(session.qemuConfig.displays[index].hardware.prettyValue)", systemImage: "display").tag(device as VMWindowState.Device?)
}
Expand Down
4 changes: 4 additions & 0 deletions Platform/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@
/* No comment provided by engineer. */
"Browse…" = "Scegli...";

/* VMConfigDisplayView
VMToolbarDisplayMenuView */
"Built-in Framebuffer" = "Framebuffer integrato";

/* UTMQemuConstants */
"Built-in Terminal" = "Terminale Integrato";

Expand Down
1 change: 1 addition & 0 deletions Platform/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@
"Upscaling" = "拡大";
"Downscaling" = "縮小";
"Retina Mode" = "Retinaモード";
"Built-in Framebuffer" = "内蔵フレームバッファ";

// VMConfigDisplayConsoleView.swift
"Style" = "スタイル";
Expand Down
1 change: 1 addition & 0 deletions Platform/ko.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@
"Upscaling" = "확대";
"Downscaling" = "축소";
"Retina Mode" = "레티나 모드";
"Built-in Framebuffer" = "내장 프레임버퍼";

// VMConfigDisplayConsoleView.swift
"Style" = "스타일";
Expand Down
Loading