using QemuVmManager.Models; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text.Json; using System.Linq; namespace QemuVmManager.Core; public class QemuCommandBuilder { private readonly VmConfiguration _config; private readonly List _arguments = new(); private readonly VirtualizationType _virtualizationType; public QemuCommandBuilder(VmConfiguration config, VirtualizationType virtualizationType = VirtualizationType.TCG) { _config = config; _virtualizationType = virtualizationType; } public string BuildCommand() { _arguments.Clear(); // Basic QEMU command _arguments.Add("qemu-system-x86_64"); // Machine and CPU configuration AddMachineConfiguration(); AddCpuConfiguration(); AddMemoryConfiguration(); // Storage configuration AddStorageConfiguration(); // OS Detection Debug Console.WriteLine($"Debug: OS Detection - IsMacOS: {OperatingSystem.IsMacOS()}, IsLinux: {OperatingSystem.IsLinux()}, IsWindows: {OperatingSystem.IsWindows()}"); // Network configuration Console.WriteLine("Debug: About to add network configuration"); AddNetworkConfiguration(); Console.WriteLine("Debug: Network configuration added"); // Add port forwarding for bridge networking if needed AddPortForwardingForBridge(); // Display configuration AddDisplayConfiguration(); // Boot configuration AddBootConfiguration(); // Advanced features AddAdvancedConfiguration(); // Extra arguments _arguments.AddRange(_config.Advanced.ExtraArgs); // Handle CPU model based on virtualization type if (_virtualizationType == VirtualizationType.TCG || _virtualizationType == VirtualizationType.HyperV) { // Replace 'host' CPU model with 'qemu64' for TCG compatibility for (int i = 0; i < _arguments.Count; i++) { if (_arguments[i] == "-cpu" && i + 1 < _arguments.Count && _arguments[i + 1] == "host") { _arguments[i + 1] = "qemu64"; } } } // Remove -enable-kvm if not using KVM if (_virtualizationType != VirtualizationType.KVM) { _arguments.RemoveAll(arg => arg == "-enable-kvm"); } // Add WHPX-specific configurations if (_virtualizationType == VirtualizationType.HyperV) { AddWHPXSpecificConfiguration(); } return string.Join(" ", _arguments); } private void AddPortForwardingForBridge() { var customForwards = GetCustomPortForwards(); if (string.IsNullOrEmpty(customForwards)) return; Console.WriteLine($"Info: Bridge networking detected - port forwarding will be configured via iptables"); Console.WriteLine($"Info: Custom port forwards: {customForwards}"); // For bridge networking, we need to wait for the VM to get an IP // Port forwarding will be configured after the VM starts and gets an IP Console.WriteLine($""); Console.WriteLine($"📝 Bridge Networking Port Forwarding:"); Console.WriteLine($" Port forwarding will be configured automatically once the VM gets an IP address."); Console.WriteLine($" The system will use iptables to forward traffic from host ports to the VM."); Console.WriteLine($""); Console.WriteLine($" Configured forwards:"); foreach (var pf in GetPortForwardList()) { Console.WriteLine($" • Port {pf.HostPort} → VM:{pf.VmPort} ({pf.Protocol})"); } Console.WriteLine($""); Console.WriteLine($" To configure port forwarding manually after VM starts:"); Console.WriteLine($" sudo iptables -t nat -A PREROUTING -p tcp --dport 3300 -j DNAT --to-destination :80"); Console.WriteLine($" sudo iptables -A FORWARD -p tcp --dport 80 -d -j ACCEPT"); Console.WriteLine($" (Replace with the VM's actual IP address from the bridge)"); } private void ConfigureIptablesPortForwarding() { try { var configFile = "port-forwards.json"; if (!File.Exists(configFile)) return; var json = File.ReadAllText(configFile); var portForwards = System.Text.Json.JsonSerializer.Deserialize>(json) ?? new List(); // Filter port forwards for this VM var vmForwards = portForwards.Where(pf => pf.VmName == _config.Name).ToList(); if (!vmForwards.Any()) return; Console.WriteLine($"🔧 Automatically configuring iptables port forwarding for VM '{_config.Name}'..."); foreach (var pf in vmForwards) { // Get the VM's IP address from the bridge network var vmIp = GetVmIpFromBridge(); if (string.IsNullOrEmpty(vmIp)) { Console.WriteLine($"⚠️ Warning: Could not determine VM IP for port forward {pf.HostPort}:{pf.VmPort}"); Console.WriteLine($" Port forwarding will be configured once the VM gets an IP address"); continue; } // Configure iptables rules ConfigureIptablesRule(pf.HostPort, pf.VmPort, vmIp, pf.Protocol); } Console.WriteLine($"✅ Port forwarding configuration completed for VM '{_config.Name}'"); } catch (Exception ex) { Console.WriteLine($"❌ Error configuring iptables port forwarding: {ex.Message}"); } } private string? GetVmIpFromBridge() { try { var bridgeName = _config.Network.Bridge ?? "virbr0"; // Method 1: Check libvirt DHCP leases var vmIp = GetVmIpFromLibvirtDhcp(); if (!string.IsNullOrEmpty(vmIp)) { Console.WriteLine($" 📡 Found VM IP {vmIp} from libvirt DHCP leases"); return vmIp; } // Method 2: Check system DHCP leases file vmIp = GetVmIpFromDhcpLeases(); if (!string.IsNullOrEmpty(vmIp)) { Console.WriteLine($" 📡 Found VM IP {vmIp} from system DHCP leases"); return vmIp; } // Method 3: Use ARP to discover VM IP on the bridge vmIp = GetVmIpFromArp(bridgeName); if (!string.IsNullOrEmpty(vmIp)) { Console.WriteLine($" 📡 Found VM IP {vmIp} from ARP table"); return vmIp; } Console.WriteLine($" ⚠️ Could not determine VM IP automatically"); Console.WriteLine($" Port forwarding will be configured once the VM gets an IP address"); return null; } catch (Exception ex) { Console.WriteLine($" ❌ Error getting VM IP: {ex.Message}"); return null; } } private string? GetVmIpFromLibvirtDhcp() { try { // Use virsh to get network information and DHCP leases var process = new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo { FileName = "virsh", Arguments = "net-dhcp-leases default", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true } }; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) return null; var output = process.StandardOutput.ReadToEnd(); // Parse virsh output to find our VM's IP // Example output format: // Expiry Time MAC address Protocol IP address Hostname Client ID or DUID // 2025-09-01 11:00:00 aa:a0:cc:aa:23:b5 ipv4 192.168.122.100 ubuntu-desktop - var lines = output.Split('\n'); foreach (var line in lines) { if (line.Contains("ubuntu-desktop") || line.Contains(_config.Name)) { var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 4) { var ipAddress = parts[3]; if (IsValidIpAddress(ipAddress)) { return ipAddress; } } } } return null; } catch { return null; } } private string? GetVmIpFromDhcpLeases() { try { // Check system DHCP leases file (common locations) var leaseFiles = new[] { "/var/lib/libvirt/dnsmasq/virbr0.status", "/var/lib/dhcp/dhcpd.leases", "/var/lib/dhcpcd/dhcpcd.leases" }; foreach (var leaseFile in leaseFiles) { if (File.Exists(leaseFile)) { var content = File.ReadAllText(leaseFile); var vmIp = ParseDhcpLeaseFile(content); if (!string.IsNullOrEmpty(vmIp)) return vmIp; } } return null; } catch { return null; } } private string? GetVmIpFromArp(string bridgeName) { try { // Use arp command to find devices on the bridge var process = new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo { FileName = "arp", Arguments = $"-n -i {bridgeName}", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true } }; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) return null; var output = process.StandardOutput.ReadToEnd(); // Parse arp output to find VM IPs // Example: Address HWtype HWaddress Flags Mask Iface // 192.168.122.100 ether aa:a0:cc:aa:23:b5 C virbr0 var lines = output.Split('\n'); foreach (var line in lines) { if (line.Contains(bridgeName) && !line.Contains("192.168.122.1")) { var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 1) { var ipAddress = parts[0]; if (IsValidIpAddress(ipAddress) && ipAddress != "192.168.122.1") { return ipAddress; } } } } return null; } catch { return null; } } private string? ParseDhcpLeaseFile(string content) { try { // Simple parsing of DHCP lease files // Look for lease entries with our VM's name or MAC var lines = content.Split('\n'); foreach (var line in lines) { if (line.Contains("lease") && line.Contains("192.168.122.")) { var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (var part in parts) { if (IsValidIpAddress(part) && part != "192.168.122.1") { return part; } } } } return null; } catch { return null; } } private bool IsValidIpAddress(string ip) { try { if (string.IsNullOrWhiteSpace(ip)) return false; var parts = ip.Split('.'); if (parts.Length != 4) return false; foreach (var part in parts) { if (!int.TryParse(part, out var num) || num < 0 || num > 255) return false; } return true; } catch { return false; } } private void ConfigureIptablesRule(int hostPort, int vmPort, string vmIp, string protocol) { try { var protocolLower = protocol.ToLower(); // Create iptables rules for port forwarding var natRule = $"-t nat -A PREROUTING -p {protocolLower} --dport {hostPort} -j DNAT --to-destination {vmIp}:{vmPort}"; var forwardRule = $"-A FORWARD -p {protocolLower} --dport {vmPort} -d {vmIp} -j ACCEPT"; // Execute iptables commands ExecuteIptablesCommand(natRule); ExecuteIptablesCommand(forwardRule); Console.WriteLine($" ✅ Port {hostPort} → {vmIp}:{vmPort} ({protocol})"); } catch (Exception ex) { Console.WriteLine($" ❌ Failed to configure port {hostPort}:{vmPort}: {ex.Message}"); } } private void ExecuteIptablesCommand(string rule) { try { // Use Process.Start to execute iptables command var process = new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo { FileName = "sudo", Arguments = $"iptables {rule}", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true } }; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) { var error = process.StandardError.ReadToEnd(); throw new Exception($"iptables command failed: {error}"); } } catch (Exception ex) { throw new Exception($"Failed to execute iptables command: {ex.Message}"); } } private string GetCustomPortForwards() { try { var configFile = "port-forwards.json"; if (!File.Exists(configFile)) return string.Empty; var json = File.ReadAllText(configFile); var portForwards = System.Text.Json.JsonSerializer.Deserialize>(json) ?? new List(); // Filter port forwards for this VM var vmForwards = portForwards.Where(pf => pf.VmName == _config.Name).ToList(); if (!vmForwards.Any()) return string.Empty; // For bridge networking, we don't use hostfwd - we use iptables instead // This method is only called for macOS user networking var forwardArgs = new List(); foreach (var pf in vmForwards) { forwardArgs.Add($"hostfwd=tcp::{pf.HostPort}-:{pf.VmPort}"); } return string.Join(",", forwardArgs); } catch (Exception ex) { Console.WriteLine($"Warning: Could not load custom port forwards: {ex.Message}"); return string.Empty; } } private List GetPortForwardList() { try { var configFile = "port-forwards.json"; if (!File.Exists(configFile)) return new List(); var json = File.ReadAllText(configFile); var portForwards = System.Text.Json.JsonSerializer.Deserialize>(json) ?? new List(); // Filter port forwards for this VM return portForwards.Where(pf => pf.VmName == _config.Name).ToList(); } catch (Exception ex) { Console.WriteLine($"Warning: Could not load port forward list: {ex.Message}"); return new List(); } } private void AddMachineConfiguration() { _arguments.Add("-machine"); switch (_virtualizationType) { case VirtualizationType.KVM: _arguments.Add("type=q35,accel=kvm:tcg"); break; case VirtualizationType.HyperV: // Use WHPX hardware acceleration _arguments.Add("type=pc-i440fx-10.1,accel=whpx:tcg,kernel-irqchip=off"); break; case VirtualizationType.HAXM: _arguments.Add("type=q35,accel=hax:tcg"); break; case VirtualizationType.HVF: _arguments.Add("type=q35,accel=hvf:tcg"); break; case VirtualizationType.TCG: default: _arguments.Add("type=q35,accel=tcg"); break; } } private void AddCpuConfiguration() { var cpu = _config.Cpu; _arguments.Add("-cpu"); _arguments.Add(cpu.Model); // For WHPX, use simpler CPU configuration to avoid exit code 4 if (_virtualizationType == VirtualizationType.HyperV) { _arguments.Add("-smp"); _arguments.Add($"{Math.Min(cpu.Cores, 2)},cores={Math.Min(cpu.Cores, 2)},sockets=1,threads=1"); } else { _arguments.Add("-smp"); _arguments.Add($"{cpu.Cores},cores={cpu.Cores},sockets={cpu.Sockets},threads={cpu.Threads}"); } } private void AddMemoryConfiguration() { var memory = _config.Memory; // For WHPX, use smaller memory allocation to avoid exit code 4 if (_virtualizationType == VirtualizationType.HyperV) { var whpxMemorySize = Math.Min(memory.Size, 4096); // Limit to 4GB for WHPX _arguments.Add("-m"); _arguments.Add($"{whpxMemorySize}{memory.Unit}"); } else { _arguments.Add("-m"); _arguments.Add($"{memory.Size}{memory.Unit}"); } } private void AddStorageConfiguration() { var storage = _config.Storage; // Add disks for (int i = 0; i < storage.Disks.Count; i++) { var disk = storage.Disks[i]; var driveLetter = (char)('a' + i); _arguments.Add("-drive"); var driveArgs = $"file={disk.Path.Replace('\\', '/')},format={disk.Format},cache={disk.Cache},id=drive{i},if=none"; _arguments.Add(driveArgs); // For WHPX, only use the first disk on IDE to avoid conflicts if (_virtualizationType == VirtualizationType.HyperV && i > 0) { Console.WriteLine($"Warning: Additional disk {i} disabled for WHPX compatibility to avoid IDE conflicts. Disk: {disk.Path}"); continue; } // Add device _arguments.Add("-device"); if (disk.Interface == "virtio" && _virtualizationType != VirtualizationType.HyperV) { // Use virtio for better performance, but avoid with WHPX due to MSI issues _arguments.Add($"virtio-blk-pci,drive=drive{i}"); } else { // Use IDE for WHPX compatibility _arguments.Add($"ide-hd,drive=drive{i}"); } } // Add CD-ROM if specified if (!string.IsNullOrEmpty(storage.Cdrom)) { if (_virtualizationType == VirtualizationType.HyperV) { // For WHPX, use the second IDE controller for CD-ROM _arguments.Add("-drive"); _arguments.Add($"file={storage.Cdrom.Replace('\\', '/')},media=cdrom,if=ide,index=1"); } else { // Use standard CD-ROM for other virtualization types _arguments.Add("-cdrom"); _arguments.Add(storage.Cdrom.Replace('\\', '/')); } } } private void AddNetworkConfiguration() { var network = _config.Network; Console.WriteLine($"Debug: Network configuration - Interfaces count: {network.Interfaces.Count}"); Console.WriteLine($"Debug: Network configuration object: {network}"); Console.WriteLine($"Debug: Network interfaces: {string.Join(", ", network.Interfaces.Select(i => $"{i.Type}:{i.Model}:{i.Bridge}"))}"); for (int i = 0; i < network.Interfaces.Count; i++) { var nic = network.Interfaces[i]; _arguments.Add("-netdev"); string netdevArgs; // Configure network backend based on type if (nic.Type == "bridge" && !string.IsNullOrEmpty(nic.Bridge)) { if (OperatingSystem.IsMacOS()) { // On macOS, use host networking with automatic DHCP (built into QEMU) // The 'net=' parameter automatically enables DHCP server var hostPort = 10000 + i; // Use different ports for multiple interfaces // Build base netdev arguments var baseArgs = $"user,id=net{i},net=192.168.100.0/24,host=192.168.100.1"; // Add built-in port forwards var builtInForwards = $"hostfwd=tcp::{hostPort}-:22,hostfwd=tcp::{hostPort + 1}-:80,hostfwd=tcp::{hostPort + 2}-:443"; // Add custom port forwards from configuration var customForwards = GetCustomPortForwards(); if (!string.IsNullOrEmpty(customForwards)) { netdevArgs = $"{baseArgs},{builtInForwards},{customForwards}"; } else { netdevArgs = $"{baseArgs},{builtInForwards}"; } _arguments.Add(netdevArgs); Console.WriteLine($"Info: Using host-based networking with automatic DHCP on macOS"); Console.WriteLine("Benefits:"); Console.WriteLine("✅ Automatic IP assignment via QEMU's built-in DHCP"); Console.WriteLine("✅ Direct host network access (bypasses QEMU DNS issues)"); Console.WriteLine("✅ DNS requests go directly to host's DNS servers"); Console.WriteLine("✅ Internet access through host network"); Console.WriteLine("✅ Automatic port forwarding for common services"); Console.WriteLine($"✅ Host ports: {hostPort} (SSH), {hostPort + 1} (HTTP), {hostPort + 2} (HTTPS)"); Console.WriteLine(""); Console.WriteLine("📝 Network Configuration (Inside VM):"); Console.WriteLine(" The VM will get an IP automatically via QEMU's DHCP."); Console.WriteLine(" If DHCP fails, manually configure:"); Console.WriteLine(" sudo ip addr add 192.168.100.x/24 dev enp0s3"); Console.WriteLine(" sudo ip route add default via 192.168.100.1"); Console.WriteLine(" DNS: nameserver 192.168.100.1 or 8.8.8.8"); _arguments.Add("-device"); var deviceArgs = ""; // Use different network models based on virtualization type if (nic.Model == "virtio-net-pci" && _virtualizationType == VirtualizationType.HyperV) { // Use e1000 for WHPX compatibility to avoid MSI issues deviceArgs = $"e1000,netdev=net{i}"; } else { deviceArgs = $"{nic.Model},netdev=net{i}"; } if (!string.IsNullOrEmpty(nic.Mac)) { deviceArgs += $",mac={nic.Mac}"; } _arguments.Add(deviceArgs); } else { // Use TAP networking for Linux/Windows netdevArgs = $"tap,id=net{i},script=no,downscript=no"; _arguments.Add(netdevArgs); _arguments.Add("-device"); var deviceArgs = ""; // Use different network models based on virtualization type if (nic.Model == "virtio-net-pci" && _virtualizationType == VirtualizationType.HyperV) { // Use e1000 for WHPX compatibility to avoid MSI issues deviceArgs = $"e1000,netdev=net{i}"; } else { deviceArgs = $"{nic.Model},netdev=net{i}"; } if (!string.IsNullOrEmpty(nic.Mac)) { deviceArgs += $",mac={nic.Mac}"; } _arguments.Add(deviceArgs); } } else { // Use user network as fallback (NAT only) netdevArgs = $"user,id=net{i}"; _arguments.Add(netdevArgs); _arguments.Add("-device"); var deviceArgs = ""; // Use different network models based on virtualization type if (nic.Model == "virtio-net-pci" && _virtualizationType == VirtualizationType.HyperV) { // Use e1000 for WHPX compatibility to avoid MSI issues deviceArgs = $"e1000,netdev=net{i}"; } else { deviceArgs = $"{nic.Model},netdev=net{i}"; } if (!string.IsNullOrEmpty(nic.Mac)) { deviceArgs += $",mac={nic.Mac}"; } _arguments.Add(deviceArgs); } } } private void AddDisplayConfiguration() { var display = _config.Display; _arguments.Add("-display"); // Use appropriate display backend based on OS string displayType = display.Type; if (OperatingSystem.IsMacOS()) { // On macOS, GTK is not available, use cocoa instead if (displayType == "gtk") { displayType = "cocoa"; } } // Handle VNC display type with proper argument if (displayType == "vnc") { var vncPort = display.SpicePort > 0 ? display.SpicePort : 5900; // QEMU VNC display numbering: vnc=0.0.0.0:0 means port 5900, vnc=0.0.0.0:1 means port 5901, etc. // So for port 5900, we use display 0, for port 5901, we use display 1, etc. var displayNumber = vncPort - 5900; if (displayNumber < 0) displayNumber = 0; // Default to display 0 if port < 5900 displayType = $"vnc=0.0.0.0:{displayNumber}"; } _arguments.Add(displayType); // For X11 forwarding compatibility, use std VGA instead of virtio // This avoids GLX/OpenGL issues when forwarding over X11 if (displayType.StartsWith("gtk") || displayType.StartsWith("x11")) { _arguments.Add("-vga"); _arguments.Add("std"); // Use standard VGA for better X11 compatibility // Add software rendering options to avoid GLX issues _arguments.Add("-device"); _arguments.Add("virtio-gpu-pci,edid=off"); // Use virtio-gpu without EDID } else if (displayType.StartsWith("vnc")) { // For VNC, use std VGA for better compatibility _arguments.Add("-vga"); _arguments.Add("std"); } else { _arguments.Add("-vga"); _arguments.Add(display.Vga); } if (display.EnableSpice) { _arguments.Add("-spice"); _arguments.Add($"port={display.SpicePort},addr=127.0.0.1,disable-ticketing=on"); } } private void AddBootConfiguration() { var boot = _config.Boot; if (boot.Order.Count > 0) { _arguments.Add("-boot"); _arguments.Add($"order={string.Join("", boot.Order)}"); } if (!string.IsNullOrEmpty(boot.Kernel)) { _arguments.Add("-kernel"); _arguments.Add(boot.Kernel); } if (!string.IsNullOrEmpty(boot.Initrd)) { _arguments.Add("-initrd"); _arguments.Add(boot.Initrd); } if (!string.IsNullOrEmpty(boot.Cmdline)) { _arguments.Add("-append"); _arguments.Add(boot.Cmdline); } } private void AddAdvancedConfiguration() { var advanced = _config.Advanced; if (advanced.EnableAudio) { _arguments.Add("-device"); _arguments.Add("intel-hda"); _arguments.Add("-device"); _arguments.Add("hda-duplex"); } if (advanced.EnableUsb) { _arguments.Add("-usb"); _arguments.Add("-device"); _arguments.Add("usb-tablet"); } // Disable virtio devices for WHPX to avoid MSI issues if (advanced.EnableBalloon && _virtualizationType != VirtualizationType.HyperV) { _arguments.Add("-device"); _arguments.Add("virtio-balloon-pci"); } if (advanced.EnableVirtioRng && _virtualizationType != VirtualizationType.HyperV) { _arguments.Add("-device"); _arguments.Add("virtio-rng-pci"); } if (advanced.EnableVirtioFs && _virtualizationType != VirtualizationType.HyperV) { _arguments.Add("-device"); _arguments.Add("virtio-fs-pci"); } // Add shared folders (disabled for compatibility) // Note: 9p filesystem support is not available in all QEMU builds // For now, shared folders are disabled to ensure compatibility if (advanced.SharedFolders.Any()) { // Log that shared folders are disabled Console.WriteLine($"Warning: Shared folders are disabled for compatibility. {advanced.SharedFolders.Count} folder(s) configured but not used."); } } private void AddWHPXSpecificConfiguration() { // Add WHPX-specific configurations to avoid MSI issues // Disable MSI for better WHPX compatibility _arguments.Add("-global"); _arguments.Add("pcie-root-port.msi=off"); // Use legacy interrupt mode for better compatibility _arguments.Add("-global"); _arguments.Add("pcie-root-port.msix=off"); // Add additional WHPX optimizations _arguments.Add("-global"); _arguments.Add("pcie-root-port.ari=off"); // Add WHPX-specific optimizations _arguments.Add("-rtc"); _arguments.Add("base=localtime"); // Memory allocation optimizations for WHPX // Note: -mem-path is not needed for WHPX and can cause issues // Memory preallocation is not available in this QEMU build // Add additional WHPX optimizations to avoid exit code 4 _arguments.Add("-no-reboot"); _arguments.Add("-no-shutdown"); // Use simpler interrupt handling (removed KVM-specific option) // Disable some features that might cause issues with WHPX // _arguments.Add("-no-acpi"); // Commented out as it might cause issues } }