]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer.pm
use non SMM ovmf code file for i440fx machines
[qemu-server.git] / PVE / QemuServer.pm
index 14a17af0adb5013425aa0333dc8711a2bca5bdcf..794558bff2471a0e3dabbc4adf49f25618097695 100644 (file)
@@ -64,6 +64,14 @@ eval {
 my $EDK2_FW_BASE = '/usr/share/pve-edk2-firmware/';
 my $OVMF = {
     x86_64 => {
+       '4m-no-smm' => [
+           "$EDK2_FW_BASE/OVMF_CODE_4M.fd",
+           "$EDK2_FW_BASE/OVMF_VARS_4M.fd",
+       ],
+       '4m-no-smm-ms' => [
+           "$EDK2_FW_BASE/OVMF_CODE_4M.fd",
+           "$EDK2_FW_BASE/OVMF_VARS_4M.ms.fd",
+       ],
        '4m' => [
            "$EDK2_FW_BASE/OVMF_CODE_4M.secboot.fd",
            "$EDK2_FW_BASE/OVMF_VARS_4M.fd",
@@ -1844,7 +1852,6 @@ sub print_vga_device {
     my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
     my $vgaid = "vga" . ($id // '');
     my $pciaddr;
-
     if ($q35 && $vgaid eq 'vga') {
        # the first display uses pcie.0 bus on q35 machines
        $pciaddr = print_pcie_addr($vgaid, $bridges, $arch, $machine);
@@ -2112,9 +2119,16 @@ sub verify_usb_device {
 sub json_config_properties {
     my $prop = shift;
 
+    my $skip_json_config_opts = {
+       parent => 1,
+       snaptime => 1,
+       vmstate => 1,
+       runningmachine => 1,
+       runningcpu => 1,
+    };
+
     foreach my $opt (keys %$confdesc) {
-       next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate' ||
-           $opt eq 'runningmachine' || $opt eq 'runningcpu';
+       next if $skip_json_config_opts->{$opt};
        $prop->{$opt} = $confdesc->{$opt};
     }
 
@@ -3159,15 +3173,16 @@ sub get_vm_machine {
     return $machine;
 }
 
-sub get_ovmf_files($$) {
-    my ($arch, $efidisk) = @_;
+sub get_ovmf_files($$$) {
+    my ($arch, $efidisk, $smm) = @_;
 
     my $types = $OVMF->{$arch}
        or die "no OVMF images known for architecture '$arch'\n";
 
     my $type = 'default';
     if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
-       $type = $efidisk->{'pre-enrolled-keys'} ? "4m-ms" : "4m";
+       $type = $smm ? "4m" : "4m-no-smm";
+       $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
     }
 
     return $types->{$type}->@*;
@@ -3313,11 +3328,8 @@ sub config_to_command {
         $pbs_backing) = @_;
 
     my $cmd = [];
-    my $globalFlags = [];
-    my $machineFlags = [];
-    my $rtcFlags = [];
+    my ($globalFlags, $machineFlags, $rtcFlags) = ([], [], []);
     my $devices = [];
-    my $pciaddr = '';
     my $bridges = {};
     my $ostype = $conf->{ostype};
     my $winversion = windows_version($ostype);
@@ -3433,7 +3445,7 @@ sub config_to_command {
            $d = parse_drive('efidisk0', $efidisk);
        }
 
-       my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d);
+       my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35);
        die "uefi base image '$ovmf_code' not found\n" if ! -f $ovmf_code;
 
        my ($path, $format);
@@ -3511,10 +3523,8 @@ sub config_to_command {
     }
 
     # enable absolute mouse coordinates (needed by vnc)
-    my $tablet;
-    if (defined($conf->{tablet})) {
-       $tablet = $conf->{tablet};
-    } else {
+    my $tablet = $conf->{tablet};
+    if (!defined($tablet)) {
        $tablet = $defaults->{tablet};
        $tablet = 0 if $qxlnum; # disable for spice because it is not needed
        $tablet = 0 if $vga->{type} =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
@@ -3542,23 +3552,22 @@ sub config_to_command {
 
     # serial devices
     for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++)  {
-       if (my $path = $conf->{"serial$i"}) {
-           if ($path eq 'socket') {
-               my $socket = "/var/run/qemu-server/${vmid}.serial$i";
-               push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off";
-               # On aarch64, serial0 is the UART device. Qemu only allows
-               # connecting UART devices via the '-serial' command line, as
-               # the device has a fixed slot on the hardware...
-               if ($arch eq 'aarch64' && $i == 0) {
-                   push @$devices, '-serial', "chardev:serial$i";
-               } else {
-                   push @$devices, '-device', "isa-serial,chardev=serial$i";
-               }
+       my $path = $conf->{"serial$i"} or next;
+       if ($path eq 'socket') {
+           my $socket = "/var/run/qemu-server/${vmid}.serial$i";
+           push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off";
+           # On aarch64, serial0 is the UART device. Qemu only allows
+           # connecting UART devices via the '-serial' command line, as
+           # the device has a fixed slot on the hardware...
+           if ($arch eq 'aarch64' && $i == 0) {
+               push @$devices, '-serial', "chardev:serial$i";
            } else {
-               die "no such serial device\n" if ! -c $path;
-               push @$devices, '-chardev', "tty,id=serial$i,path=$path";
                push @$devices, '-device', "isa-serial,chardev=serial$i";
            }
+       } else {
+           die "no such serial device\n" if ! -c $path;
+           push @$devices, '-chardev', "tty,id=serial$i,path=$path";
+           push @$devices, '-device', "isa-serial,chardev=serial$i";
        }
     }
 
@@ -3742,13 +3751,13 @@ sub config_to_command {
 
     # enable balloon by default, unless explicitly disabled
     if (!defined($conf->{balloon}) || $conf->{balloon}) {
-       $pciaddr = print_pci_addr("balloon0", $bridges, $arch, $machine_type);
+       my $pciaddr = print_pci_addr("balloon0", $bridges, $arch, $machine_type);
        push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
     }
 
     if ($conf->{watchdog}) {
        my $wdopts = parse_watchdog($conf->{watchdog});
-       $pciaddr = print_pci_addr("watchdog", $bridges, $arch, $machine_type);
+       my $pciaddr = print_pci_addr("watchdog", $bridges, $arch, $machine_type);
        my $watchdog = $wdopts->{model} || 'i6300esb';
        push @$devices, '-device', "$watchdog$pciaddr";
        push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
@@ -3792,7 +3801,7 @@ sub config_to_command {
            die "scsi$drive->{index}: machine version 4.1~pve2 or higher is required to use more than 14 SCSI disks\n"
                if $drive->{index} > 13 && !&$version_guard(4, 1, 2);
 
-           $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch, $machine_type);
+           my $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch, $machine_type);
            my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
 
            my $iothread = '';
@@ -3815,7 +3824,7 @@ sub config_to_command {
 
         if ($drive->{interface} eq 'sata') {
            my $controller = int($drive->{index} / $PVE::QemuServer::Drive::MAX_SATA_DISKS);
-           $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch, $machine_type);
+           my $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch, $machine_type);
            push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr"
                if !$ahcicontroller->{$controller};
            $ahcicontroller->{$controller}=1;
@@ -3880,15 +3889,12 @@ sub config_to_command {
     # pci.4 is nested in pci.1
     $bridges->{1} = 1 if $bridges->{4};
 
-    if (!$q35) {
-       # add pci bridges
-        if (min_version($machine_version, 2, 3)) {
+    if (!$q35) { # add pci bridges
+       if (min_version($machine_version, 2, 3)) {
           $bridges->{1} = 1;
           $bridges->{2} = 1;
        }
-
        $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
-
     }
 
     for my $k (sort {$b cmp $a} keys %$bridges) {
@@ -3898,11 +3904,10 @@ sub config_to_command {
        if ($k == 2 && $legacy_igd) {
            $k_name = "$k-igd";
        }
-       $pciaddr = print_pci_addr("pci.$k_name", undef, $arch, $machine_type);
-
+       my $pciaddr = print_pci_addr("pci.$k_name", undef, $arch, $machine_type);
        my $devstr = "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr";
-       if ($q35) {
-           # add after -readconfig pve-q35.cfg
+
+       if ($q35) { # add after -readconfig pve-q35.cfg
            splice @$devices, 2, 0, '-device', $devstr;
        } else {
            unshift @$devices, '-device', $devstr if $k > 0;
@@ -4033,43 +4038,33 @@ sub vm_deviceplug {
     qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid, $arch, $machine_type);
 
     if ($deviceid eq 'tablet') {
-
        qemu_deviceadd($vmid, print_tabletdevice_full($conf, $arch));
-
     } elsif ($deviceid eq 'keyboard') {
-
        qemu_deviceadd($vmid, print_keyboarddevice_full($conf, $arch));
-
     } elsif ($deviceid =~ m/^usb(\d+)$/) {
-
        die "usb hotplug currently not reliable\n";
        # since we can't reliably hot unplug all added usb devices and usb
        # passthrough breaks live migration we disable usb hotplugging for now
        #qemu_deviceadd($vmid, PVE::QemuServer::USB::print_usbdevice_full($conf, $deviceid, $device));
-
     } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
-
        qemu_iothread_add($vmid, $deviceid, $device);
 
-        qemu_driveadd($storecfg, $vmid, $device);
-        my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type);
+       qemu_driveadd($storecfg, $vmid, $device);
+       my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type);
 
-        qemu_deviceadd($vmid, $devicefull);
+       qemu_deviceadd($vmid, $devicefull);
        eval { qemu_deviceaddverify($vmid, $deviceid); };
        if (my $err = $@) {
            eval { qemu_drivedel($vmid, $deviceid); };
            warn $@ if $@;
            die $err;
         }
-
     } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
-
-
-        my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
-        my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type);
+       my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
+       my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type);
        my $scsihw_type = $scsihw eq 'virtio-scsi-single' ? "virtio-scsi-pci" : $scsihw;
 
-        my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
+       my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
 
        if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread}) {
            qemu_iothread_add($vmid, $deviceid, $device);
@@ -4080,11 +4075,9 @@ sub vm_deviceplug {
            $devicefull .= ",num_queues=$device->{queues}";
        }
 
-        qemu_deviceadd($vmid, $devicefull);
-        qemu_deviceaddverify($vmid, $deviceid);
-
+       qemu_deviceadd($vmid, $devicefull);
+       qemu_deviceaddverify($vmid, $deviceid);
     } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
-
         qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device, $arch, $machine_type);
         qemu_driveadd($storecfg, $vmid, $device);
 
@@ -4095,9 +4088,7 @@ sub vm_deviceplug {
            warn $@ if $@;
            die $err;
         }
-
     } elsif ($deviceid =~ m/^(net)(\d+)$/) {
-
        return if !qemu_netdevadd($vmid, $conf, $arch, $device, $deviceid);
 
        my $machine_type = PVE::QemuServer::Machine::qemu_machine_pxe($vmid, $conf);
@@ -4116,16 +4107,13 @@ sub vm_deviceplug {
            warn $@ if $@;
            die $err;
        }
-
     } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
-
        my $bridgeid = $2;
        my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type);
        my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
 
        qemu_deviceadd($vmid, $devicefull);
        qemu_deviceaddverify($vmid, $deviceid);
-
     } else {
        die "can't hotplug device '$deviceid'\n";
     }
@@ -7553,7 +7541,8 @@ sub get_efivars_size {
     my ($conf) = @_;
     my $arch = get_vm_arch($conf);
     my $efidisk = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
-    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk);
+    my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf);
+    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm);
     die "uefi vars image '$ovmf_vars' not found\n" if ! -f $ovmf_vars;
     return -s $ovmf_vars;
 }
@@ -7578,10 +7567,10 @@ sub update_tpmstate_size {
     $conf->{tpmstate0} = print_drive($disk);
 }
 
-sub create_efidisk($$$$$$) {
-    my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk) = @_;
+sub create_efidisk($$$$$$$) {
+    my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm) = @_;
 
-    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk);
+    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm);
     die "EFI vars default image not found\n" if ! -f $ovmf_vars;
 
     my $vars_size_b = -s $ovmf_vars;