qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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



  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).