From b5099b4f6c581b196b3412c83037dba0327a304d Mon Sep 17 00:00:00 2001 From: Stefan Reiter Date: Tue, 5 Oct 2021 18:02:06 +0200 Subject: [PATCH] ovmf: support secure boot with 4m and 4m-ms efidisk types Provide support for secure boot by using the new "4m" and "4m-ms" variants of the OVMF code/vars templates. This is specified on the efidisk via the 'efitype' and 'ms-keys' parameters. Signed-off-by: Stefan Reiter --- PVE/API2/Qemu.pm | 3 ++- PVE/QemuServer.pm | 60 ++++++++++++++++++++++++++++------------- PVE/QemuServer/Drive.pm | 22 +++++++++++++++ 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index 367d6ca..cc2a543 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -183,7 +183,8 @@ my $create_disks = sub { my $volid; if ($ds eq 'efidisk0') { - ($volid, $size) = PVE::QemuServer::create_efidisk($storecfg, $storeid, $vmid, $fmt, $arch); + ($volid, $size) = PVE::QemuServer::create_efidisk( + $storecfg, $storeid, $vmid, $fmt, $arch, $disk); } elsif ($ds eq 'tpmstate0') { # swtpm can only use raw volumes, and uses a fixed size $size = PVE::Tools::convert_size(PVE::QemuServer::Drive::TPMSTATE_DISK_SIZE, 'b' => 'kb'); diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 076ce59..3c0ecf5 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -63,14 +63,26 @@ eval { my $EDK2_FW_BASE = '/usr/share/pve-edk2-firmware/'; my $OVMF = { - x86_64 => [ - "$EDK2_FW_BASE/OVMF_CODE.fd", - "$EDK2_FW_BASE/OVMF_VARS.fd" - ], - aarch64 => [ - "$EDK2_FW_BASE/AAVMF_CODE.fd", - "$EDK2_FW_BASE/AAVMF_VARS.fd" - ], + x86_64 => { + '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", + ], + 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(); @@ -3140,13 +3152,18 @@ sub get_vm_machine { return $machine; } -sub get_ovmf_files($) { - my ($arch) = @_; +sub get_ovmf_files($$) { + my ($arch, $efidisk) = @_; - my $ovmf = $OVMF->{$arch} + my $types = $OVMF->{$arch} or die "no OVMF images known for architecture '$arch'\n"; - return @$ovmf; + my $type = 'default'; + if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') { + $type = $efidisk->{'ms-keys'} ? "4m-ms" : "4m"; + } + + return $types->{$type}->@*; } my $Arch2Qemu = { @@ -3405,13 +3422,17 @@ sub config_to_command { } if ($conf->{bios} && $conf->{bios} eq 'ovmf') { - my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch); + my $d; + if (my $efidisk = $conf->{efidisk0}) { + $d = parse_drive('efidisk0', $efidisk); + } + + my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d); die "uefi base image '$ovmf_code' not found\n" if ! -f $ovmf_code; my ($path, $format); my $read_only_str = ''; - if (my $efidisk = $conf->{efidisk0}) { - my $d = parse_drive('efidisk0', $efidisk); + if ($d) { my ($storeid, $volname) = PVE::Storage::parse_volume_id($d->{file}, 1); $format = $d->{format}; if ($storeid) { @@ -7516,7 +7537,8 @@ sub qemu_use_old_bios_files { sub get_efivars_size { my ($conf) = @_; my $arch = get_vm_arch($conf); - my (undef, $ovmf_vars) = get_ovmf_files($arch); + my $efidisk = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef; + my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk); die "uefi vars image '$ovmf_vars' not found\n" if ! -f $ovmf_vars; return -s $ovmf_vars; } @@ -7541,10 +7563,10 @@ sub update_tpmstate_size { $conf->{tpmstate0} = print_drive($disk); } -sub create_efidisk($$$$$) { - my ($storecfg, $storeid, $vmid, $fmt, $arch) = @_; +sub create_efidisk($$$$$$) { + my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk) = @_; - my (undef, $ovmf_vars) = get_ovmf_files($arch); + my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk); die "EFI vars default image not found\n" if ! -f $ovmf_vars; my $vars_size_b = -s $ovmf_vars; diff --git a/PVE/QemuServer/Drive.pm b/PVE/QemuServer/Drive.pm index 6389dbb..57d26f5 100644 --- a/PVE/QemuServer/Drive.pm +++ b/PVE/QemuServer/Drive.pm @@ -306,6 +306,26 @@ my $virtiodesc = { }; PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc); +my %efitype_fmt = ( + efitype => { + type => 'string', + enum => [qw(2m 4m)], + description => "Size and type of the OVMF EFI vars. '4m' is newer and recommended," + . " and required for Secure Boot. For backwards compatibility, '2m' is used" + . " if not otherwise specified.", + optional => 1, + default => '2m', + }, + 'ms-keys' => { + type => 'boolean', + description => "Pre-enroll the Microsoft Standard UEFI Secure Boot keys if" + . " used with 'efitype=4m'. Note that this will enable Secure Boot by" + . " default, though it can still be turned off from within the VM.", + optional => 1, + default => 0, + }, +); + my $efidisk_fmt = { volume => { alias => 'file' }, file => { @@ -323,6 +343,7 @@ my $efidisk_fmt = { description => "Disk size. This is purely informational and has no effect.", optional => 1, }, + %efitype_fmt, }; my $efidisk_desc = { @@ -382,6 +403,7 @@ my $alldrive_fmt = { %ssd_fmt, %wwn_fmt, %tpmversion_fmt, + %efitype_fmt, }; my $unused_fmt = { -- 2.39.2