From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: James Bottomley <jejb@linux.ibm.com>
Cc: thomas.lendacky@amd.com, ashish.kalra@amd.com,
brijesh.singh@amd.com, david.kaplan@amd.com, jon.grimm@amd.com,
tobin@ibm.com, qemu-devel@nongnu.org, frankeh@us.ibm.com,
dovmurik@linux.vnet.ibm.com, Dov.Murik1@il.ibm.com,
pbonzini@redhat.com, berrange@redhat.com
Subject: Re: [PATCH v3 1/2] pc: add parser for OVMF reset block
Date: Thu, 4 Feb 2021 19:58:26 +0000 [thread overview]
Message-ID: <20210204195826.GR3039@work-vm> (raw)
In-Reply-To: <20210204193939.16617-2-jejb@linux.ibm.com>
* James Bottomley (jejb@linux.ibm.com) wrote:
> OVMF is developing a mechanism for depositing a GUIDed table just
> below the known location of the reset vector. The table goes
> backwards in memory so all entries are of the form
>
> <data>|len|<GUID>
>
> Where <data> is arbtrary size and type, <len> is a uint16_t and
> describes the entire length of the entry from the beginning of the
> data to the end of the guid.
>
> The foot of the table is of this form and <len> for this case
> describes the entire size of the table. The table foot GUID is
> defined by OVMF as 96b582de-1fb2-45f7-baea-a366c55a082d and if the
> table is present this GUID is just below the reset vector, 48 bytes
> before the end of the firmware file.
>
> Add a parser for the ovmf reset block which takes a copy of the block,
> if the table foot guid is found, minus the footer and a function for
> later traversal to return the data area of any specified GUIDs.
>
> Signed-off-by: James Bottomley <jejb@linux.ibm.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
>
> ---
>
> v2: fix brace warnings and return values
> v3: add bounds checking for flash tables
> ---
> hw/i386/pc_sysfw.c | 112 +++++++++++++++++++++++++++++++++++++++++++
> include/hw/i386/pc.h | 4 ++
> 2 files changed, 116 insertions(+)
>
> diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
> index 92e90ff013..8ef73dbc3a 100644
> --- a/hw/i386/pc_sysfw.c
> +++ b/hw/i386/pc_sysfw.c
> @@ -124,6 +124,113 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms)
> }
> }
>
> +#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d"
> +
> +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_table) {
> + return;
> + }
> +
> + 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;
> +}
> +
> +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;
> +
> + 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,
> @@ -195,6 +302,11 @@ static void pc_system_flash_map(PCMachineState *pcms,
> if (kvm_memcrypt_enabled()) {
> flash_ptr = memory_region_get_ram_ptr(flash_mem);
> flash_size = memory_region_size(flash_mem);
> + /*
> + * OVMF places a GUIDed structures in the flash, so
> + * search for them
> + */
> + pc_system_parse_ovmf_flash(flash_ptr, flash_size);
> ret = kvm_memcrypt_encrypt_data(flash_ptr, flash_size);
> if (ret) {
> error_report("failed to encrypt pflash rom");
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 2aa8797c6e..19a53f745f 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -3,6 +3,7 @@
>
> #include "qemu/notify.h"
> #include "qapi/qapi-types-common.h"
> +#include "qemu/uuid.h"
> #include "hw/boards.h"
> #include "hw/block/fdc.h"
> #include "hw/block/flash.h"
> @@ -188,6 +189,9 @@ ISADevice *pc_find_fdc0(void);
> void pc_system_flash_create(PCMachineState *pcms);
> 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);
> +
>
> /* acpi-build.c */
> void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
> --
> 2.26.2
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
next prev parent reply other threads:[~2021-02-04 20:00 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-04 19:39 [PATCH v3 0/2] sev: enable secret injection to a self described area in OVMF James Bottomley
2021-02-04 19:39 ` [PATCH v3 1/2] pc: add parser for OVMF reset block James Bottomley
2021-02-04 19:58 ` Dr. David Alan Gilbert [this message]
2021-02-04 19:39 ` [PATCH v3 2/2] sev: update sev-inject-launch-secret to make gpa optional James Bottomley
2021-02-04 20:00 ` Dr. David Alan Gilbert
2021-02-05 9:51 ` Daniel P. Berrangé
2021-02-05 10:58 ` Paolo Bonzini
2021-02-05 11:37 ` Daniel P. Berrangé
2021-02-05 11:45 ` Paolo Bonzini
2021-02-05 11:51 ` Daniel P. Berrangé
2021-02-08 9:38 ` Dr. David Alan Gilbert
2021-02-05 10:58 ` [PATCH v3 0/2] sev: enable secret injection to a self described area in OVMF Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210204195826.GR3039@work-vm \
--to=dgilbert@redhat.com \
--cc=Dov.Murik1@il.ibm.com \
--cc=ashish.kalra@amd.com \
--cc=berrange@redhat.com \
--cc=brijesh.singh@amd.com \
--cc=david.kaplan@amd.com \
--cc=dovmurik@linux.vnet.ibm.com \
--cc=frankeh@us.ibm.com \
--cc=jejb@linux.ibm.com \
--cc=jon.grimm@amd.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=thomas.lendacky@amd.com \
--cc=tobin@ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).