[pve-devel] [PATCH qemu-server 07/15] introduce OVMF module

Fabian Grünbichler f.gruenbichler at proxmox.com
Tue Jun 24 12:23:19 CEST 2025


> Fiona Ebner <f.ebner at proxmox.com> hat am 23.06.2025 17:44 CEST geschrieben:

some small nits/questions inline..

> Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
> ---
>  src/PVE/API2/Qemu.pm             |  13 ++-
>  src/PVE/QemuMigrate.pm           |   3 +-
>  src/PVE/QemuServer.pm            | 168 +---------------------------
>  src/PVE/QemuServer/Makefile      |   1 +
>  src/PVE/QemuServer/OVMF.pm       | 186 +++++++++++++++++++++++++++++++
>  src/test/MigrationTest/Shared.pm |   4 +
>  6 files changed, 207 insertions(+), 168 deletions(-)
>  create mode 100644 src/PVE/QemuServer/OVMF.pm
> 
> diff --git a/src/PVE/API2/Qemu.pm b/src/PVE/API2/Qemu.pm
> index ce6f362d..44322db6 100644
> --- a/src/PVE/API2/Qemu.pm
> +++ b/src/PVE/API2/Qemu.pm
> @@ -36,6 +36,7 @@ use PVE::QemuServer::Monitor qw(mon_cmd);
>  use PVE::QemuServer::Machine;
>  use PVE::QemuServer::Memory qw(get_current_memory);
>  use PVE::QemuServer::MetaInfo;
> +use PVE::QemuServer::OVMF;
>  use PVE::QemuServer::PCI;
>  use PVE::QemuServer::QMPHelpers;
>  use PVE::QemuServer::RNG;
> @@ -540,8 +541,10 @@ my sub create_disks : prototype($$$$$$$$$$$) {
>                              format => $disk->{format},
>                          };
>  
> -                        $dest_info->{efisize} = PVE::QemuServer::get_efivars_size($conf, $disk)
> -                            if $ds eq 'efidisk0';
> +                        if ($ds eq 'efidisk0') {
> +                            $dest_info->{efisize} =
> +                                PVE::QemuServer::OVMF::get_efivars_size($conf, $disk);

we could change this to pass in $amd_sev_type (+ some other things, or leave a wrapper around it
in PVE::QemuServer, see below)

> +                        }
>  
>                          eval {
>                              ($dst_volid, $size) =
> @@ -612,7 +615,7 @@ my sub create_disks : prototype($$$$$$$$$$$) {
>                          "SEV-SNP uses consolidated read-only firmware and does not require an EFI disk\n"
>                          if $amd_sev_type && $amd_sev_type eq 'snp';
>  
> -                    ($volid, $size) = PVE::QemuServer::create_efidisk(
> +                    ($volid, $size) = PVE::QemuServer::OVMF::create_efidisk(
>                          $storecfg, $storeid, $vmid, $fmt, $arch, $disk, $smm, $amd_sev_type,

since we already get and pass $amd_sev_type here

>                      );
>                  } elsif ($ds eq 'tpmstate0') {
> @@ -4455,7 +4458,7 @@ __PACKAGE__->register_method({
>                          format => $format,
>                      };
>  
> -                    $dest_info->{efisize} = PVE::QemuServer::get_efivars_size($oldconf)
> +                    $dest_info->{efisize} = PVE::QemuServer::OVMF::get_efivars_size($oldconf)

would need to update this

>                          if $opt eq 'efidisk0';
>  
>                      my $newdrive = PVE::QemuServer::clone_disk(
> @@ -4733,7 +4736,7 @@ __PACKAGE__->register_method({
>                      format => $format,
>                  };
>  
> -                $dest_info->{efisize} = PVE::QemuServer::get_efivars_size($conf)
> +                $dest_info->{efisize} = PVE::QemuServer::OVMF::get_efivars_size($conf)

and this as well though

>                      if $disk eq 'efidisk0';
>  
>                  my $newdrive = PVE::QemuServer::clone_disk(
> diff --git a/src/PVE/QemuMigrate.pm b/src/PVE/QemuMigrate.pm
> index 28d7ac56..9ccaf7e0 100644
> --- a/src/PVE/QemuMigrate.pm
> +++ b/src/PVE/QemuMigrate.pm
> @@ -31,6 +31,7 @@ use PVE::QemuServer::Helpers qw(min_version);
>  use PVE::QemuServer::Machine;
>  use PVE::QemuServer::Monitor qw(mon_cmd);
>  use PVE::QemuServer::Memory qw(get_current_memory);
> +use PVE::QemuServer::OVMF;
>  use PVE::QemuServer::QMPHelpers;
>  use PVE::QemuServer;
>  
> @@ -635,7 +636,7 @@ sub config_update_local_disksizes {
>      # we want to set the efidisk size in the config to the size of the
>      # real OVMF_VARS.fd image, else we can create a too big image, which does not work
>      if (defined($conf->{efidisk0})) {
> -        PVE::QemuServer::update_efidisk_size($conf);
> +        PVE::QemuServer::OVMF::update_efidisk_size($conf);

this already returns immediately if no efidisk is defined, so we
could drop the surrounding if here? this is also the only call site,
and we already do plenty of parsing and printing of drives here,
so maybe we could even inline it instead - the only OVMF specific
thing is a call to get_efivars_size

>      }
>  
>      # TPM state might have an irregular filesize, to avoid problems on transfer
> diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
> index 63b4d469..719687dc 100644
> --- a/src/PVE/QemuServer.pm
> +++ b/src/PVE/QemuServer.pm
> @@ -56,7 +56,7 @@ use PVE::QemuServer::Helpers
>  use PVE::QemuServer::Cloudinit;
>  use PVE::QemuServer::CGroup;
>  use PVE::QemuServer::CPUConfig
> -    qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object get_amd_sev_type);
> +    qw(print_cpu_device get_cpu_options is_native_arch get_amd_sev_object get_amd_sev_type);
>  use PVE::QemuServer::Drive qw(
>      is_valid_drivename
>      checked_volume_format
> @@ -71,6 +71,7 @@ use PVE::QemuServer::Machine;
>  use PVE::QemuServer::Memory qw(get_current_memory);
>  use PVE::QemuServer::MetaInfo;
>  use PVE::QemuServer::Monitor qw(mon_cmd);
> +use PVE::QemuServer::OVMF;
>  use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port parse_hostpci);
>  use PVE::QemuServer::QemuImage;
>  use PVE::QemuServer::QMPHelpers qw(qemu_deviceadd qemu_devicedel qemu_objectadd qemu_objectdel);
> @@ -98,41 +99,6 @@ my sub vm_is_ha_managed {
>      return PVE::HA::Config::vm_is_ha_managed($vmid);
>  }
>  
> -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",
> -        ],
> -        '4m-ms' => [
> -            "$EDK2_FW_BASE/OVMF_CODE_4M.secboot.fd", "$EDK2_FW_BASE/OVMF_VARS_4M.ms.fd",
> -        ],
> -        '4m-sev' => [
> -            "$EDK2_FW_BASE/OVMF_CVM_CODE_4M.fd", "$EDK2_FW_BASE/OVMF_CVM_VARS_4M.fd",
> -        ],
> -        '4m-snp' => [
> -            "$EDK2_FW_BASE/OVMF_CVM_4M.fd",
> -        ],
> -        # FIXME: These are legacy 2MB-sized images that modern OVMF doesn't supports to build
> -        # anymore. how can we deperacate this sanely without breaking existing instances, or using
> -        # older backups and snapshot?
> -        default => [
> -            "$EDK2_FW_BASE/OVMF_CODE.fd", "$EDK2_FW_BASE/OVMF_VARS.fd",
> -        ],
> -    },
> -    aarch64 => {
> -        default => [
> -            "$EDK2_FW_BASE/AAVMF_CODE.fd", "$EDK2_FW_BASE/AAVMF_VARS.fd",
> -        ],
> -    },
> -};
> -
>  my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
>  
>  # Note about locking: we use flock on the config file protect against concurrent actions.
> @@ -3293,36 +3259,6 @@ sub vga_conf_has_spice {
>      return $1 || 1;
>  }
>  
> -sub get_ovmf_files($$$$) {
> -    my ($arch, $efidisk, $smm, $amd_sev_type) = @_;
> -
> -    my $types = $OVMF->{$arch}
> -        or die "no OVMF images known for architecture '$arch'\n";
> -
> -    my $type = 'default';
> -    if ($arch eq 'x86_64') {
> -        if ($amd_sev_type && $amd_sev_type eq 'snp') {
> -            $type = "4m-snp";
> -            my ($ovmf) = $types->{$type}->@*;
> -            die "EFI base image '$ovmf' not found\n" if !-f $ovmf;
> -            return ($ovmf);
> -        } elsif ($amd_sev_type) {
> -            $type = "4m-sev";
> -        } elsif (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
> -            $type = $smm ? "4m" : "4m-no-smm";
> -            $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
> -        } else {
> -            # TODO: log_warn about use of legacy images for x86_64 with Promxox VE 9
> -        }
> -    }
> -
> -    my ($ovmf_code, $ovmf_vars) = $types->{$type}->@*;
> -    die "EFI base image '$ovmf_code' not found\n" if !-f $ovmf_code;
> -    die "EFI vars image '$ovmf_vars' not found\n" if !-f $ovmf_vars;
> -
> -    return ($ovmf_code, $ovmf_vars);
> -}
> -
>  # To use query_supported_cpu_flags and query_understood_cpu_flags to get flags
>  # to use in a QEMU command line (-cpu element), first array_intersect the result
>  # of query_supported_ with query_understood_. This is necessary because:
> @@ -3464,48 +3400,6 @@ my sub should_disable_smm {
>          && $vga->{type} =~ m/^(serial\d+|none)$/;
>  }
>  
> -my sub print_ovmf_drive_commandlines {
> -    my ($conf, $storecfg, $vmid, $arch, $q35, $version_guard) = @_;
> -
> -    my $d = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
> -
> -    my $amd_sev_type = get_amd_sev_type($conf);
> -    die "Attempting to configure SEV-SNP with pflash devices instead of using `-bios`\n"
> -        if $amd_sev_type && $amd_sev_type eq 'snp';
> -
> -    my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35, $amd_sev_type);
> -
> -    my $var_drive_str = "if=pflash,unit=1,id=drive-efidisk0";
> -    if ($d) {
> -        my ($storeid, $volname) = PVE::Storage::parse_volume_id($d->{file}, 1);
> -        my ($path, $format) = $d->@{ 'file', 'format' };
> -        if ($storeid) {
> -            $path = PVE::Storage::path($storecfg, $d->{file});
> -            $format //= checked_volume_format($storecfg, $d->{file});
> -        } elsif (!defined($format)) {
> -            die "efidisk format must be specified\n";
> -        }
> -        # SPI flash does lots of read-modify-write OPs, without writeback this gets really slow #3329
> -        if ($path =~ m/^rbd:/) {
> -            $var_drive_str .= ',cache=writeback';
> -            $path .= ':rbd_cache_policy=writeback'; # avoid write-around, we *need* to cache writes too
> -        }
> -        $var_drive_str .= ",format=$format,file=$path";
> -
> -        $var_drive_str .= ",size=" . (-s $ovmf_vars)
> -            if $format eq 'raw' && $version_guard->(4, 1, 2);
> -        $var_drive_str .= ',readonly=on' if drive_is_read_only($conf, $d);
> -    } else {
> -        log_warn("no efidisk configured! Using temporary efivars disk.");
> -        my $path = "/tmp/$vmid-ovmf.fd";
> -        PVE::Tools::file_copy($ovmf_vars, $path, -s $ovmf_vars);
> -        $var_drive_str .= ",format=raw,file=$path";
> -        $var_drive_str .= ",size=" . (-s $ovmf_vars) if $version_guard->(4, 1, 2);
> -    }
> -
> -    return ("if=pflash,unit=0,format=raw,readonly=on,file=$ovmf_code", $var_drive_str);
> -}
> -
>  my sub get_vga_properties {
>      my ($conf, $arch, $machine_version, $winversion) = @_;
>  
> @@ -3680,21 +3574,10 @@ sub config_to_command {
>      }
>  
>      if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
> -        die "OVMF (UEFI) BIOS is not supported on 32-bit CPU types\n"
> -            if !$forcecpu && get_cpu_bitness($conf->{cpu}, $arch) == 32;
> -
> -        my $amd_sev_type = get_amd_sev_type($conf);

if we keep this

> -        if ($amd_sev_type && $amd_sev_type eq 'snp') {
> -            if (defined($conf->{efidisk0})) {
> -                log_warn("EFI disks are not supported with SEV-SNP and will be ignored");
> -            }
> -            push $cmd->@*, '-bios', get_ovmf_files($arch, undef, undef, $amd_sev_type);
> -        } else {
> -            my ($code_drive_str, $var_drive_str) =
> -                print_ovmf_drive_commandlines($conf, $storecfg, $vmid, $arch, $q35, $version_guard);
> -            push $cmd->@*, '-drive', $code_drive_str;
> -            push $cmd->@*, '-drive', $var_drive_str;
> -        }
> +        my $ovmf_cmd = PVE::QemuServer::OVMF::print_ovmf_commandline(
> +            $conf, $storecfg, $vmid, $arch, $q35, $version_guard, $forcecpu,

and pass it here (maybe combine amd_sev, forcecpu, smm and q35 into an options hash)?

> +        );
> +        push $cmd->@*, $ovmf_cmd->@*;
>      }
>  
>      if ($q35) { # tell QEMU to load q35 config early
> @@ -8853,29 +8736,6 @@ sub qemu_use_old_bios_files {
>      return ($use_old_bios_files, $machine_type);
>  }
>  
> -sub get_efivars_size {
> -    my ($conf, $efidisk) = @_;
> -
> -    my $arch = PVE::QemuServer::Helpers::get_vm_arch($conf);
> -    $efidisk //= $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
> -    my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf);
> -    my $amd_sev_type = get_amd_sev_type($conf);
> -    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
> -    return -s $ovmf_vars;

and maybe move just the last two lines here to OVMF.pm, but leave the $conf to options hash part
here for the call above and for other calls to get_efivars_size ?

> -}
> -
> -sub update_efidisk_size {
> -    my ($conf) = @_;
> -
> -    return if !defined($conf->{efidisk0});
> -
> -    my $disk = PVE::QemuServer::parse_drive('efidisk0', $conf->{efidisk0});
> -    $disk->{size} = get_efivars_size($conf);
> -    $conf->{efidisk0} = print_drive($disk);
> -
> -    return;
> -}
> -
>  sub update_tpmstate_size {
>      my ($conf) = @_;
>  
> @@ -8884,22 +8744,6 @@ sub update_tpmstate_size {
>      $conf->{tpmstate0} = print_drive($disk);
>  }
>  
> -sub create_efidisk($$$$$$$$) {
> -    my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm, $amd_sev_type) = @_;
> -
> -    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
> -
> -    my $vars_size_b = -s $ovmf_vars;
> -    my $vars_size = PVE::Tools::convert_size($vars_size_b, 'b' => 'kb');
> -    my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
> -    PVE::Storage::activate_volumes($storecfg, [$volid]);
> -
> -    PVE::QemuServer::QemuImage::convert($ovmf_vars, $volid, $vars_size_b);
> -    my $size = PVE::Storage::volume_size_info($storecfg, $volid, 3);
> -
> -    return ($volid, $size / 1024);
> -}
> -
>  sub vm_iothreads_list {
>      my ($vmid) = @_;
>  
> diff --git a/src/PVE/QemuServer/Makefile b/src/PVE/QemuServer/Makefile
> index a34ec83b..dd6fe505 100644
> --- a/src/PVE/QemuServer/Makefile
> +++ b/src/PVE/QemuServer/Makefile
> @@ -14,6 +14,7 @@ SOURCES=Agent.pm	\
>  	Memory.pm	\
>  	MetaInfo.pm	\
>  	Monitor.pm	\
> +	OVMF.pm		\
>  	PCI.pm		\
>  	QemuImage.pm	\
>  	QMPHelpers.pm	\
> diff --git a/src/PVE/QemuServer/OVMF.pm b/src/PVE/QemuServer/OVMF.pm
> new file mode 100644
> index 00000000..70c626a5
> --- /dev/null
> +++ b/src/PVE/QemuServer/OVMF.pm
> @@ -0,0 +1,186 @@
> +package PVE::QemuServer::OVMF;
> +
> +use strict;
> +use warnings;
> +
> +use PVE::RESTEnvironment qw(log_warn);
> +use PVE::Storage;
> +use PVE::Tools;
> +
> +use PVE::QemuServer::Drive qw(checked_volume_format drive_is_read_only parse_drive print_drive);
> +use PVE::QemuServer::CPUConfig qw(get_amd_sev_type get_cpu_bitness);

then we could get rid of this import here. get_cpu_bitness is only used
in one place as well, so we could get of that as well..

the entanglement right now is small, but these things tend to grow over
time..

> +use PVE::QemuServer::Helpers;

only used for determining the arch in get_efivars_size

> +use PVE::QemuServer::Machine;

this one's only used to determine whether the config is q35 in
get_efivars_size, could maybe also be moved to the call site?

so these three use statements could maybe be left in PVE::QemuServer..

> +use PVE::QemuServer::QemuImage;
> +
> +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",
> +        ],
> +        '4m-ms' => [
> +            "$EDK2_FW_BASE/OVMF_CODE_4M.secboot.fd", "$EDK2_FW_BASE/OVMF_VARS_4M.ms.fd",
> +        ],
> +        '4m-sev' => [
> +            "$EDK2_FW_BASE/OVMF_CVM_CODE_4M.fd", "$EDK2_FW_BASE/OVMF_CVM_VARS_4M.fd",
> +        ],
> +        '4m-snp' => [
> +            "$EDK2_FW_BASE/OVMF_CVM_4M.fd",
> +        ],
> +        # FIXME: These are legacy 2MB-sized images that modern OVMF doesn't supports to build
> +        # anymore. how can we deperacate this sanely without breaking existing instances, or using
> +        # older backups and snapshot?
> +        default => [
> +            "$EDK2_FW_BASE/OVMF_CODE.fd", "$EDK2_FW_BASE/OVMF_VARS.fd",
> +        ],
> +    },
> +    aarch64 => {
> +        default => [
> +            "$EDK2_FW_BASE/AAVMF_CODE.fd", "$EDK2_FW_BASE/AAVMF_VARS.fd",
> +        ],
> +    },
> +};
> +
> +my sub get_ovmf_files($$$$) {
> +    my ($arch, $efidisk, $smm, $amd_sev_type) = @_;
> +
> +    my $types = $OVMF->{$arch}
> +        or die "no OVMF images known for architecture '$arch'\n";
> +
> +    my $type = 'default';
> +    if ($arch eq 'x86_64') {
> +        if ($amd_sev_type && $amd_sev_type eq 'snp') {
> +            $type = "4m-snp";
> +            my ($ovmf) = $types->{$type}->@*;
> +            die "EFI base image '$ovmf' not found\n" if !-f $ovmf;
> +            return ($ovmf);
> +        } elsif ($amd_sev_type) {
> +            $type = "4m-sev";
> +        } elsif (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
> +            $type = $smm ? "4m" : "4m-no-smm";
> +            $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
> +        } else {
> +            # TODO: log_warn about use of legacy images for x86_64 with Promxox VE 9
> +        }
> +    }
> +
> +    my ($ovmf_code, $ovmf_vars) = $types->{$type}->@*;
> +    die "EFI base image '$ovmf_code' not found\n" if !-f $ovmf_code;
> +    die "EFI vars image '$ovmf_vars' not found\n" if !-f $ovmf_vars;
> +
> +    return ($ovmf_code, $ovmf_vars);
> +}
> +
> +my sub print_ovmf_drive_commandlines {
> +    my ($conf, $storecfg, $vmid, $arch, $q35, $version_guard) = @_;
> +
> +    my $d = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
> +
> +    my $amd_sev_type = get_amd_sev_type($conf);
> +    die "Attempting to configure SEV-SNP with pflash devices instead of using `-bios`\n"
> +        if $amd_sev_type && $amd_sev_type eq 'snp';
> +
> +    my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35, $amd_sev_type);
> +
> +    my $var_drive_str = "if=pflash,unit=1,id=drive-efidisk0";
> +    if ($d) {
> +        my ($storeid, $volname) = PVE::Storage::parse_volume_id($d->{file}, 1);
> +        my ($path, $format) = $d->@{ 'file', 'format' };
> +        if ($storeid) {
> +            $path = PVE::Storage::path($storecfg, $d->{file});
> +            $format //= checked_volume_format($storecfg, $d->{file});
> +        } elsif (!defined($format)) {
> +            die "efidisk format must be specified\n";
> +        }
> +        # SPI flash does lots of read-modify-write OPs, without writeback this gets really slow #3329
> +        if ($path =~ m/^rbd:/) {
> +            $var_drive_str .= ',cache=writeback';
> +            $path .= ':rbd_cache_policy=writeback'; # avoid write-around, we *need* to cache writes too
> +        }
> +        $var_drive_str .= ",format=$format,file=$path";
> +
> +        $var_drive_str .= ",size=" . (-s $ovmf_vars)
> +            if $format eq 'raw' && $version_guard->(4, 1, 2);
> +        $var_drive_str .= ',readonly=on' if drive_is_read_only($conf, $d);
> +    } else {
> +        log_warn("no efidisk configured! Using temporary efivars disk.");
> +        my $path = "/tmp/$vmid-ovmf.fd";
> +        PVE::Tools::file_copy($ovmf_vars, $path, -s $ovmf_vars);
> +        $var_drive_str .= ",format=raw,file=$path";
> +        $var_drive_str .= ",size=" . (-s $ovmf_vars) if $version_guard->(4, 1, 2);
> +    }
> +
> +    return ("if=pflash,unit=0,format=raw,readonly=on,file=$ovmf_code", $var_drive_str);
> +}
> +
> +sub get_efivars_size {
> +    my ($conf, $efidisk) = @_;
> +
> +    my $arch = PVE::QemuServer::Helpers::get_vm_arch($conf);
> +    $efidisk //= $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
> +    my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf);
> +    my $amd_sev_type = get_amd_sev_type($conf);
> +    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
> +    return -s $ovmf_vars;
> +}
> +
> +sub update_efidisk_size {
> +    my ($conf) = @_;
> +
> +    return if !defined($conf->{efidisk0});
> +
> +    my $disk = parse_drive('efidisk0', $conf->{efidisk0});
> +    $disk->{size} = get_efivars_size($conf);
> +    $conf->{efidisk0} = print_drive($disk);
> +
> +    return;
> +}
> +
> +sub create_efidisk($$$$$$$$) {
> +    my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm, $amd_sev_type) = @_;
> +
> +    my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
> +
> +    my $vars_size_b = -s $ovmf_vars;
> +    my $vars_size = PVE::Tools::convert_size($vars_size_b, 'b' => 'kb');
> +    my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
> +    PVE::Storage::activate_volumes($storecfg, [$volid]);
> +
> +    PVE::QemuServer::QemuImage::convert($ovmf_vars, $volid, $vars_size_b);
> +    my $size = PVE::Storage::volume_size_info($storecfg, $volid, 3);
> +
> +    return ($volid, $size / 1024);
> +}
> +
> +sub print_ovmf_commandline {
> +    my ($conf, $storecfg, $vmid, $arch, $q35, $version_guard, $forcecpu) = @_;
> +
> +    my $cmd = [];
> +
> +    die "OVMF (UEFI) BIOS is not supported on 32-bit CPU types\n"
> +        if !$forcecpu && get_cpu_bitness($conf->{cpu}, $arch) == 32;
> +
> +    my $amd_sev_type = get_amd_sev_type($conf);
> +    if ($amd_sev_type && $amd_sev_type eq 'snp') {
> +        if (defined($conf->{efidisk0})) {
> +            log_warn("EFI disks are not supported with SEV-SNP and will be ignored");
> +        }
> +        push $cmd->@*, '-bios', get_ovmf_files($arch, undef, undef, $amd_sev_type);
> +    } else {
> +        my ($code_drive_str, $var_drive_str) =
> +            print_ovmf_drive_commandlines($conf, $storecfg, $vmid, $arch, $q35, $version_guard);
> +        push $cmd->@*, '-drive', $code_drive_str;
> +        push $cmd->@*, '-drive', $var_drive_str;
> +    }
> +
> +    return $cmd;
> +}
> +
> +1;
> diff --git a/src/test/MigrationTest/Shared.pm b/src/test/MigrationTest/Shared.pm
> index 0b1ac7a0..e29cd1df 100644
> --- a/src/test/MigrationTest/Shared.pm
> +++ b/src/test/MigrationTest/Shared.pm
> @@ -150,6 +150,10 @@ $qemu_server_module->mock(
>      vm_stop_cleanup => sub {
>          return;
>      },
> +);
> +
> +our $qemu_server_ovmf_module = Test::MockModule->new("PVE::QemuServer::OVMF");
> +$qemu_server_ovmf_module->mock(
>      get_efivars_size => sub {
>          return 128 * 1024;
>      },
> -- 
> 2.47.2
> 
> 
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel at lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel




More information about the pve-devel mailing list