From ac0595cf6b36cc39f2a926bd519416c32cb5667d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 14 Jul 2021 11:56:02 +0200 Subject: [PATCH 1/5] gitlab-ci: Extract EDK2 job rules to reusable section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All jobs depending on 'docker-edk2' job must use at most all the rules that triggers it. The simplest way to ensure that is to always use the same rules. Extract all the rules to a reusable section, and include this section (with the 'extends' keyword) in both 'docker-edk2' and 'build-edk2' jobs. The problem was introduced in commit 71920809cea ("gitlab-ci.yml: Add jobs to build EDK2 firmware binaries"), but was revealed in commit 1925468ddbf ("docker: EDK2 build job depends on EDK2 container") and eventually failed on CI: https://gitlab.com/qemu-project/qemu/-/pipelines/335995843 Reported-by: Daniel P. Berrangé Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel P. Berrangé Reviewed-by: Willian Rampazzo Message-Id: <20210714101003.3113726-1-philmd@redhat.com> --- .gitlab-ci.d/edk2.yml | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.d/edk2.yml b/.gitlab-ci.d/edk2.yml index ba7280605c..aae2f7ad88 100644 --- a/.gitlab-ci.d/edk2.yml +++ b/.gitlab-ci.d/edk2.yml @@ -1,10 +1,22 @@ -docker-edk2: - stage: containers - rules: # Only run this job when the Dockerfile is modified +# All jobs needing docker-edk2 must use the same rules it uses. +.edk2_job_rules: + rules: # Only run this job when ... - changes: + # this file is modified - .gitlab-ci.d/edk2.yml + # or the Dockerfile is modified - .gitlab-ci.d/edk2/Dockerfile + # or roms/edk2/ is modified (submodule updated) + - roms/edk2/* when: always + - if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2' + when: always + - if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2' + when: always + +docker-edk2: + extends: .edk2_job_rules + stage: containers image: docker:19.03.1 services: - docker:19.03.1-dind @@ -24,16 +36,9 @@ docker-edk2: - docker push $IMAGE_TAG build-edk2: + extends: .edk2_job_rules stage: build needs: ['docker-edk2'] - rules: # Only run this job when ... - - changes: # ... roms/edk2/ is modified (submodule updated) - - roms/edk2/* - when: always - - if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2' - when: always - - if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2' - when: always artifacts: paths: # 'artifacts.zip' will contains the following files: - pc-bios/edk2*bz2 From 35ebc321b476c0b9e573bc6fb412d773fb4a36d5 Mon Sep 17 00:00:00 2001 From: Dov Murik Date: Thu, 1 Jul 2021 05:27:48 +0000 Subject: [PATCH 2/5] hw/i386/pc: pc_system_ovmf_table_find: Assert that flash was parsed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add assertion in pc_system_ovmf_table_find that verifies that the flash was indeed previously parsed (looking for the OVMF table) by pc_system_parse_ovmf_flash. Now pc_system_ovmf_table_find distinguishes between "no one called pc_system_parse_ovmf_flash" (which will abort due to assertion failure) and "the flash was parsed but no OVMF table was found, or it is invalid" (which will return false). Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Dov Murik Reviewed-by: Tom Lendacky Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210701052749.934744-2-dovmurik@linux.ibm.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc_sysfw.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 6ce37a2b05..e353f2a4e9 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -126,6 +126,7 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms) #define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d" +static bool ovmf_flash_parsed; static uint8_t *ovmf_table; static int ovmf_table_len; @@ -136,10 +137,12 @@ static void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) int tot_len; /* should only be called once */ - if (ovmf_table) { + if (ovmf_flash_parsed) { return; } + ovmf_flash_parsed = true; + if (flash_size < TARGET_PAGE_SIZE) { return; } @@ -183,6 +186,8 @@ bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int tot_len = ovmf_table_len; QemuUUID entry_guid; + assert(ovmf_flash_parsed); + if (qemu_uuid_parse(entry, &entry_guid) < 0) { return false; } From 2165542c8d21c01d1f470560ab7d86b3fee8eac4 Mon Sep 17 00:00:00 2001 From: Dov Murik Date: Thu, 1 Jul 2021 05:27:49 +0000 Subject: [PATCH 3/5] hw/i386/pc: Document pc_system_ovmf_table_find MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Dov Murik Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210701052749.934744-3-dovmurik@linux.ibm.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc_sysfw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index e353f2a4e9..6ddce92a86 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -179,6 +179,17 @@ static void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) ovmf_table += tot_len; } +/** + * pc_system_ovmf_table_find - Find the data associated with an entry in OVMF's + * reset vector GUIDed table. + * + * @entry: GUID string of the entry to lookup + * @data: Filled with a pointer to the entry's value (if not NULL) + * @data_len: Filled with the length of the entry's value (if not NULL). Pass + * NULL here if the length of data is known. + * + * Return: true if the entry was found in the OVMF table; false otherwise. + */ bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len) { From b5b318608e20464c7136eb5a5f5f3307e9f90510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 21 May 2021 15:34:07 +0200 Subject: [PATCH 4/5] hw/i386: Introduce X86_FW_OVMF Kconfig symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce the X86_FW_OVMF Kconfig symbol for OVMF-specific code. Move the OVMF-specific code from pc_sysfw.c to pc_sysfw_ovmf.c, adding a pair of stubs. Update MAINTAINERS to reach OVMF maintainers when these new files are modified. This fixes when building the microvm machine standalone: /usr/bin/ld: libqemu-i386-softmmu.fa.p/target_i386_monitor.c.o: in function `qmp_sev_inject_launch_secret': target/i386/monitor.c:749: undefined reference to `pc_system_ovmf_table_find' Fixes: f522cef9b35 ("sev: update sev-inject-launch-secret to make gpa optional") Signed-off-by: Philippe Mathieu-Daudé Acked-by: Michael S. Tsirkin Message-Id: <20210616204328.2611406-22-philmd@redhat.com> --- MAINTAINERS | 1 + hw/i386/Kconfig | 4 + hw/i386/meson.build | 2 + hw/i386/pc_sysfw.c | 123 --------------------------- hw/i386/pc_sysfw_ovmf-stubs.c | 26 ++++++ hw/i386/pc_sysfw_ovmf.c | 151 ++++++++++++++++++++++++++++++++++ include/hw/i386/pc.h | 1 + 7 files changed, 185 insertions(+), 123 deletions(-) create mode 100644 hw/i386/pc_sysfw_ovmf-stubs.c create mode 100644 hw/i386/pc_sysfw_ovmf.c diff --git a/MAINTAINERS b/MAINTAINERS index 148153d74f..2250cd1b36 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2945,6 +2945,7 @@ EDK2 Firmware M: Laszlo Ersek M: Philippe Mathieu-Daudé S: Supported +F: hw/i386/*ovmf* F: pc-bios/descriptors/??-edk2-*.json F: pc-bios/edk2-* F: roms/Makefile.edk2 diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index aacb6f6d96..bad6cf5b4e 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -1,5 +1,9 @@ +config X86_FW_OVMF + bool + config SEV bool + select X86_FW_OVMF depends on KVM config PC diff --git a/hw/i386/meson.build b/hw/i386/meson.build index e5d109f5c6..80dad29f2b 100644 --- a/hw/i386/meson.build +++ b/hw/i386/meson.build @@ -24,6 +24,8 @@ i386_ss.add(when: 'CONFIG_PC', if_true: files( 'pc_sysfw.c', 'acpi-build.c', 'port92.c')) +i386_ss.add(when: 'CONFIG_X86_FW_OVMF', if_true: files('pc_sysfw_ovmf.c'), + if_false: files('pc_sysfw_ovmf-stubs.c')) subdir('kvm') subdir('xen') diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 6ddce92a86..68d6b1f783 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -124,129 +124,6 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms) } } -#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d" - -static bool ovmf_flash_parsed; -static uint8_t *ovmf_table; -static int ovmf_table_len; - -static void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) -{ - uint8_t *ptr; - QemuUUID guid; - int tot_len; - - /* should only be called once */ - if (ovmf_flash_parsed) { - return; - } - - ovmf_flash_parsed = true; - - if (flash_size < TARGET_PAGE_SIZE) { - return; - } - - /* - * if this is OVMF there will be a table footer - * guid 48 bytes before the end of the flash file. If it's - * not found, silently abort the flash parsing. - */ - qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid); - guid = qemu_uuid_bswap(guid); /* guids are LE */ - ptr = flash_ptr + flash_size - 48; - if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) { - return; - } - - /* if found, just before is two byte table length */ - ptr -= sizeof(uint16_t); - tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t); - - if (tot_len <= 0) { - return; - } - - ovmf_table = g_malloc(tot_len); - ovmf_table_len = tot_len; - - /* - * ptr is the foot of the table, so copy it all to the newly - * allocated ovmf_table and then set the ovmf_table pointer - * to the table foot - */ - memcpy(ovmf_table, ptr - tot_len, tot_len); - ovmf_table += tot_len; -} - -/** - * pc_system_ovmf_table_find - Find the data associated with an entry in OVMF's - * reset vector GUIDed table. - * - * @entry: GUID string of the entry to lookup - * @data: Filled with a pointer to the entry's value (if not NULL) - * @data_len: Filled with the length of the entry's value (if not NULL). Pass - * NULL here if the length of data is known. - * - * Return: true if the entry was found in the OVMF table; false otherwise. - */ -bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, - int *data_len) -{ - uint8_t *ptr = ovmf_table; - int tot_len = ovmf_table_len; - QemuUUID entry_guid; - - assert(ovmf_flash_parsed); - - if (qemu_uuid_parse(entry, &entry_guid) < 0) { - return false; - } - - if (!ptr) { - return false; - } - - entry_guid = qemu_uuid_bswap(entry_guid); /* guids are LE */ - while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) { - int len; - QemuUUID *guid; - - /* - * The data structure is - * arbitrary length data - * 2 byte length of entire entry - * 16 byte guid - */ - guid = (QemuUUID *)(ptr - sizeof(QemuUUID)); - len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) - - sizeof(uint16_t))); - - /* - * just in case the table is corrupt, wouldn't want to spin in - * the zero case - */ - if (len < sizeof(QemuUUID) + sizeof(uint16_t)) { - return false; - } else if (len > tot_len) { - return false; - } - - ptr -= len; - tot_len -= len; - if (qemu_uuid_is_equal(guid, &entry_guid)) { - if (data) { - *data = ptr; - } - if (data_len) { - *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t); - } - return true; - } - } - return false; -} - /* * Map the pcms->flash[] from 4GiB downward, and realize. * Map them in descending order, i.e. pcms->flash[0] at the top, diff --git a/hw/i386/pc_sysfw_ovmf-stubs.c b/hw/i386/pc_sysfw_ovmf-stubs.c new file mode 100644 index 0000000000..aabe78b271 --- /dev/null +++ b/hw/i386/pc_sysfw_ovmf-stubs.c @@ -0,0 +1,26 @@ +/* + * QEMU PC System Firmware (OVMF stubs) + * + * Copyright (c) 2021 Red Hat, Inc. + * + * Author: + * Philippe Mathieu-Daudé + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/i386/pc.h" + +bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len) +{ + g_assert_not_reached(); +} + +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) +{ + g_assert_not_reached(); +} diff --git a/hw/i386/pc_sysfw_ovmf.c b/hw/i386/pc_sysfw_ovmf.c new file mode 100644 index 0000000000..f4dd92c588 --- /dev/null +++ b/hw/i386/pc_sysfw_ovmf.c @@ -0,0 +1,151 @@ +/* + * QEMU PC System Firmware (OVMF specific) + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2011-2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/i386/pc.h" +#include "cpu.h" + +#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d" + +static bool ovmf_flash_parsed; +static uint8_t *ovmf_table; +static int ovmf_table_len; + +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) +{ + uint8_t *ptr; + QemuUUID guid; + int tot_len; + + /* should only be called once */ + if (ovmf_flash_parsed) { + return; + } + + ovmf_flash_parsed = true; + + if (flash_size < TARGET_PAGE_SIZE) { + return; + } + + /* + * if this is OVMF there will be a table footer + * guid 48 bytes before the end of the flash file. If it's + * not found, silently abort the flash parsing. + */ + qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid); + guid = qemu_uuid_bswap(guid); /* guids are LE */ + ptr = flash_ptr + flash_size - 48; + if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) { + return; + } + + /* if found, just before is two byte table length */ + ptr -= sizeof(uint16_t); + tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t); + + if (tot_len <= 0) { + return; + } + + ovmf_table = g_malloc(tot_len); + ovmf_table_len = tot_len; + + /* + * ptr is the foot of the table, so copy it all to the newly + * allocated ovmf_table and then set the ovmf_table pointer + * to the table foot + */ + memcpy(ovmf_table, ptr - tot_len, tot_len); + ovmf_table += tot_len; +} + +/** + * pc_system_ovmf_table_find - Find the data associated with an entry in OVMF's + * reset vector GUIDed table. + * + * @entry: GUID string of the entry to lookup + * @data: Filled with a pointer to the entry's value (if not NULL) + * @data_len: Filled with the length of the entry's value (if not NULL). Pass + * NULL here if the length of data is known. + * + * Return: true if the entry was found in the OVMF table; false otherwise. + */ +bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, + int *data_len) +{ + uint8_t *ptr = ovmf_table; + int tot_len = ovmf_table_len; + QemuUUID entry_guid; + + assert(ovmf_flash_parsed); + + if (qemu_uuid_parse(entry, &entry_guid) < 0) { + return false; + } + + if (!ptr) { + return false; + } + + entry_guid = qemu_uuid_bswap(entry_guid); /* guids are LE */ + while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) { + int len; + QemuUUID *guid; + + /* + * The data structure is + * arbitrary length data + * 2 byte length of entire entry + * 16 byte guid + */ + guid = (QemuUUID *)(ptr - sizeof(QemuUUID)); + len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) - + sizeof(uint16_t))); + + /* + * just in case the table is corrupt, wouldn't want to spin in + * the zero case + */ + if (len < sizeof(QemuUUID) + sizeof(uint16_t)) { + return false; + } else if (len > tot_len) { + return false; + } + + ptr -= len; + tot_len -= len; + if (qemu_uuid_is_equal(guid, &entry_guid)) { + if (data) { + *data = ptr; + } + if (data_len) { + *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t); + } + return true; + } + } + return false; +} diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 87294f2632..0775f945d7 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -188,6 +188,7 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms); void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory); bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len); +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size); /* acpi-build.c */ From 2669350db2c3df33f4e68c518e9f31f91502a83d Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Thu, 8 Jul 2021 09:14:09 +0200 Subject: [PATCH 5/5] MAINTAINERS: remove Laszlo Ersek's entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've relinquished my edk2 roles with the following commit message [1] [2] [3]: > Maintainers.txt: remove Laszlo Ersek's entries > > I'm relinquishing all my roles listed in "Maintainers.txt", for personal > reasons. > > My email address remains functional. > > To my understanding, my employer is working to assign others engineers > to the edk2 project (at their discretion). [1] https://edk2.groups.io/g/devel/message/77585 [2] https://listman.redhat.com/archives/edk2-devel-archive/2021-July/msg00202.html [3] http://mid.mail-archive.com/20210708070916.8937-1-lersek@redhat.com Accordingly, remove my entries from QEMU's MAINTAINERS file as well, which all relate to guest firmware. Cc: Daniel P. Berrange Cc: Gerd Hoffmann Cc: Kashyap Chamarthy Cc: Peter Maydell Cc: Philippe Mathieu-Daudé Signed-off-by: Laszlo Ersek Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210708071409.9671-1-lersek@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 3 --- 1 file changed, 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2250cd1b36..4181ee75ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2202,7 +2202,6 @@ F: include/hw/southbridge/piix.h Firmware configuration (fw_cfg) M: Philippe Mathieu-Daudé -R: Laszlo Ersek R: Gerd Hoffmann S: Supported F: docs/specs/fw_cfg.txt @@ -2934,7 +2933,6 @@ F: include/hw/i2c/smbus_slave.h F: include/hw/i2c/smbus_eeprom.h Firmware schema specifications -M: Laszlo Ersek M: Philippe Mathieu-Daudé R: Daniel P. Berrange R: Kashyap Chamarthy @@ -2942,7 +2940,6 @@ S: Maintained F: docs/interop/firmware.json EDK2 Firmware -M: Laszlo Ersek M: Philippe Mathieu-Daudé S: Supported F: hw/i386/*ovmf*