All of lore.kernel.org
 help / color / mirror / Atom feed
From: Corey Minyard <minyard@acm.org>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Corey Minyard <cminyard@mvista.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 10/15] smbios: Add a function to directly add an entry
Date: Mon, 13 Apr 2015 11:34:49 -0500	[thread overview]
Message-ID: <552BF029.4040609@acm.org> (raw)
In-Reply-To: <20150413085824-mutt-send-email-mst@redhat.com>

On 04/13/2015 02:00 AM, Michael S. Tsirkin wrote:
> On Sun, Apr 12, 2015 at 08:26:46PM -0500, Corey Minyard wrote:
>> On 04/12/2015 11:05 AM, Michael S. Tsirkin wrote:
>>> On Tue, Apr 07, 2015 at 02:51:39PM -0500, minyard@acm.org wrote:
>>>> From: Corey Minyard <cminyard@mvista.com>
>>>>
>>>> There was no way to directly add a table entry to the SMBIOS table,
>>>> even though the BIOS supports this.  So add a function to do this.
>>>> This is in preparation for the IPMI handler adding it's SMBIOS table
>>>> entry.
>>>>
>>>> Signed-off-by: Corey Minyard <cminyard@mvista.com>
>>> Do we have to use a callback for this?
>>>
>>> It seems that if smbios_table_entry_add just added the table
>>> itself to some array or a linked list, then devices could just call
>>> smbios_table_entry_add instead of registering a handler.
>>>
>>> And smbios_get_tables would scan that and get the tables.
>> Well, there are many ways you could handle this, and it doesn't seem
>> much different in the end to me.  You either have a list of items to add
>> to the table or a list of callbacks to fill in the data.
>>
>> I made this the same as the ACPI code, which you have to have as a
>> callback if you are adding it to a common SSDT.
> Not really I think.

The AML functions require that you have a tree to attach what you are
adding.  If you did your own SSDT, you wouldn't need a callback.  You
could add a binary blob that gets put into the SSDT, but I think that
would require adding some AML functions.

>
>> Plus it reduced the
>> amount of dynamic allocation required.
> Not sure why this matters though.

I'm a kernel guy and we are insane about this kind of stuff :).

>>> On systems without smbios, this function could be a nop stub.
>> One nice things about the callbacks is you can eliminate any stubs.  I
>> find stubs kind of ugly, personally.
>>
>> -corey
> You still need a stub for the register function, don't you?

It depends on how you design it.  I had already redesigned it based on
Paulo's comments to add the firmware to a holding list in the base IPMI
code, then when the callbacks came from SMBIOS and ACPI the code would
iterate that list and add the table entries.  No stubs required. 
Creating a separate SSDT and adding the list to ACPI/SMBIOS code is not
an issue, either, and stubs aren't a big deal.

Thanks,

-corey

>>> Did I miss something?
>>>
>>>> ---
>>>>  hw/i386/smbios.c         | 149 ++++++++++++++++++++++++++++++-----------------
>>>>  include/hw/i386/smbios.h |  13 +++++
>>>>  2 files changed, 110 insertions(+), 52 deletions(-)
>>>>
>>>> diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
>>>> index 1341e02..fe15325 100644
>>>> --- a/hw/i386/smbios.c
>>>> +++ b/hw/i386/smbios.c
>>>> @@ -831,6 +831,25 @@ static void smbios_entry_point_setup(void)
>>>>      ep.structure_table_address = cpu_to_le32(0);
>>>>  }
>>>>  
>>>> +struct smbios_device_handler {
>>>> +    void (*handle_device_table)(void *opaque);
>>>> +    void *opaque;
>>>> +    struct smbios_device_handler *prev;
>>>> +};
>>>> +static struct smbios_device_handler *device_handlers;
>>>> +
>>>> +void smbios_register_device_table_handler(void (*handle_device_table)
>>>> +                                                (void *opaque),
>>>> +                                          void *opaque)
>>>> +{
>>>> +    struct smbios_device_handler *handler = g_malloc(sizeof(*handler));
>>>> +
>>>> +    handler->handle_device_table = handle_device_table;
>>>> +    handler->opaque = opaque;
>>>> +    handler->prev = device_handlers;
>>>> +    device_handlers = handler;
>>>> +}
>>>> +
>>>>  void smbios_get_tables(uint8_t **tables, size_t *tables_len,
>>>>                         uint8_t **anchor, size_t *anchor_len)
>>>>  {
>>>> @@ -875,6 +894,14 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len,
>>>>          }
>>>>  
>>>>          smbios_build_type_32_table();
>>>> +
>>>> +        while (device_handlers) {
>>>> +            struct smbios_device_handler *handler = device_handlers;
>>>> +            device_handlers = handler->prev;
>>>> +            handler->handle_device_table(handler->opaque);
>>>> +            g_free(handler);
>>>> +        }
>>>> +
>>>>          smbios_build_type_127_table();
>>>>  
>>>>          smbios_validate_table();
>>>> @@ -898,6 +925,71 @@ static void save_opt(const char **dest, QemuOpts *opts, const char *name)
>>>>      }
>>>>  }
>>>>  
>>>> +int smbios_table_entry_add(void *data, int size, bool append_zeros)
>>>> +{
>>>> +    struct smbios_structure_header *header;
>>>> +    struct smbios_table *table; /* legacy mode only */
>>>> +
>>>> +    /*
>>>> +     * NOTE: standard double '\0' terminator expected, per smbios spec.
>>>> +     * (except in legacy mode, where the second '\0' is implicit and
>>>> +     *  will be inserted by the BIOS).
>>>> +     */
>>>> +    if (append_zeros) {
>>>> +        size += 2;
>>>> +    }
>>>> +    smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size);
>>>> +    header = (struct smbios_structure_header *)(smbios_tables +
>>>> +                                                smbios_tables_len);
>>>> +
>>>> +    memcpy(header, data, size);
>>>> +
>>>> +    if (test_bit(header->type, have_fields_bitmap)) {
>>>> +        error_report("can't load type %d struct, fields already specified!",
>>>> +                     header->type);
>>>> +        exit(1);
>>>> +    }
>>>> +    set_bit(header->type, have_binfile_bitmap);
>>>> +
>>>> +    if (header->type == 4) {
>>>> +        smbios_type4_count++;
>>>> +    }
>>>> +
>>>> +    smbios_tables_len += size;
>>>> +    if (size > smbios_table_max) {
>>>> +        smbios_table_max = size;
>>>> +    }
>>>> +    smbios_table_cnt++;
>>>> +
>>>> +    /* add a copy of the newly loaded blob to legacy smbios_entries */
>>>> +    /* NOTE: This code runs before smbios_set_defaults(), so we don't
>>>> +     *       yet know which mode (legacy vs. aggregate-table) will be
>>>> +     *       required. We therefore add the binary blob to both legacy
>>>> +     *       (smbios_entries) and aggregate (smbios_tables) tables, and
>>>> +     *       delete the one we don't need from smbios_set_defaults(),
>>>> +     *       once we know which machine version has been requested.
>>>> +     */
>>>> +    if (!smbios_entries) {
>>>> +        smbios_entries_len = sizeof(uint16_t);
>>>> +        smbios_entries = g_malloc0(smbios_entries_len);
>>>> +    }
>>>> +    if (append_zeros) {
>>>> +        size -= 1; /* The BIOS adds the second zero in legacy mode. */
>>>> +    }
>>>> +    smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
>>>> +                               size + sizeof(*table));
>>>> +    table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
>>>> +    table->header.type = SMBIOS_TABLE_ENTRY;
>>>> +    table->header.length = cpu_to_le16(sizeof(*table) + size);
>>>> +    memcpy(table->data, header, size);
>>>> +    smbios_entries_len += sizeof(*table) + size;
>>>> +    (*(uint16_t *)smbios_entries) =
>>>> +                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
>>>> +    /* end: add a copy of the newly loaded blob to legacy smbios_entries */
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>  void smbios_entry_add(QemuOpts *opts)
>>>>  {
>>>>      Error *local_err = NULL;
>>>> @@ -907,9 +999,8 @@ void smbios_entry_add(QemuOpts *opts)
>>>>  
>>>>      val = qemu_opt_get(opts, "file");
>>>>      if (val) {
>>>> -        struct smbios_structure_header *header;
>>>>          int size;
>>>> -        struct smbios_table *table; /* legacy mode only */
>>>> +        uint8_t *data;
>>>>  
>>>>          qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
>>>>          if (local_err) {
>>>> @@ -923,60 +1014,14 @@ void smbios_entry_add(QemuOpts *opts)
>>>>              exit(1);
>>>>          }
>>>>  
>>>> -        /*
>>>> -         * NOTE: standard double '\0' terminator expected, per smbios spec.
>>>> -         * (except in legacy mode, where the second '\0' is implicit and
>>>> -         *  will be inserted by the BIOS).
>>>> -         */
>>>> -        smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size);
>>>> -        header = (struct smbios_structure_header *)(smbios_tables +
>>>> -                                                    smbios_tables_len);
>>>> -
>>>> -        if (load_image(val, (uint8_t *)header) != size) {
>>>> +        data = g_malloc(size);
>>>> +        if (load_image(val, data) != size) {
>>>>              error_report("Failed to load SMBIOS file %s", val);
>>>>              exit(1);
>>>>          }
>>>>  
>>>> -        if (test_bit(header->type, have_fields_bitmap)) {
>>>> -            error_report("can't load type %d struct, fields already specified!",
>>>> -                         header->type);
>>>> -            exit(1);
>>>> -        }
>>>> -        set_bit(header->type, have_binfile_bitmap);
>>>> -
>>>> -        if (header->type == 4) {
>>>> -            smbios_type4_count++;
>>>> -        }
>>>> -
>>>> -        smbios_tables_len += size;
>>>> -        if (size > smbios_table_max) {
>>>> -            smbios_table_max = size;
>>>> -        }
>>>> -        smbios_table_cnt++;
>>>> -
>>>> -        /* add a copy of the newly loaded blob to legacy smbios_entries */
>>>> -        /* NOTE: This code runs before smbios_set_defaults(), so we don't
>>>> -         *       yet know which mode (legacy vs. aggregate-table) will be
>>>> -         *       required. We therefore add the binary blob to both legacy
>>>> -         *       (smbios_entries) and aggregate (smbios_tables) tables, and
>>>> -         *       delete the one we don't need from smbios_set_defaults(),
>>>> -         *       once we know which machine version has been requested.
>>>> -         */
>>>> -        if (!smbios_entries) {
>>>> -            smbios_entries_len = sizeof(uint16_t);
>>>> -            smbios_entries = g_malloc0(smbios_entries_len);
>>>> -        }
>>>> -        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
>>>> -                                                   size + sizeof(*table));
>>>> -        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
>>>> -        table->header.type = SMBIOS_TABLE_ENTRY;
>>>> -        table->header.length = cpu_to_le16(sizeof(*table) + size);
>>>> -        memcpy(table->data, header, size);
>>>> -        smbios_entries_len += sizeof(*table) + size;
>>>> -        (*(uint16_t *)smbios_entries) =
>>>> -                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
>>>> -        /* end: add a copy of the newly loaded blob to legacy smbios_entries */
>>>> -
>>>> +        smbios_table_entry_add(data, size, false);
>>>> +        g_free(data);
>>>>          return;
>>>>      }
>>>>  
>>>> diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
>>>> index d2850be..656327d 100644
>>>> --- a/include/hw/i386/smbios.h
>>>> +++ b/include/hw/i386/smbios.h
>>>> @@ -27,6 +27,19 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len,
>>>>                         uint8_t **anchor, size_t *anchor_len);
>>>>  
>>>>  /*
>>>> + * Add an external entry to the SMBIOS table.  Can only be called
>>>> + * from a registered device table handler.
>>>> + */
>>>> +int smbios_table_entry_add(void *data, int size, bool append_zeros);
>>>> +
>>>> +/*
>>>> + * When constructing SMBIOS tables, call a function at the end of the
>>>> + * add process to allow devices to add their own SMBIOS table entries.
>>>> + */
>>>> +void smbios_register_device_table_handler(void (*handle_device_table)
>>>> +                                                (void *opaque),
>>>> +                                          void *opaque);
>>>> +/*
>>>>   * SMBIOS spec defined tables
>>>>   */
>>>>  
>>>> -- 
>>>> 1.8.3.1
>>>>

  reply	other threads:[~2015-04-13 16:34 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-07 19:51 [Qemu-devel] [PATCH 00/15] IPMI device for qemu minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 01/15] Add a base IPMI interface minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 02/15] ipmi: Add a PC ISA type structure minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 03/15] ipmi: Add a KCS low-level interface minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 04/15] ipmi: Add a BT " minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 05/15] ipmi: Add a local BMC simulation minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 06/15] ipmi: Add an external connection simulation interface minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 07/15] ipmi: Add tests minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 08/15] ipmi: Add documentation minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 09/15] ipmi: Add migration capability to the IPMI device minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 10/15] smbios: Add a function to directly add an entry minyard
2015-04-12 16:05   ` Michael S. Tsirkin
2015-04-13  1:26     ` Corey Minyard
2015-04-13  7:00       ` Michael S. Tsirkin
2015-04-13 16:34         ` Corey Minyard [this message]
2015-04-13 16:40           ` Paolo Bonzini
2015-04-14  6:31             ` Michael S. Tsirkin
2015-04-14 15:30               ` Corey Minyard
2015-04-14 16:31               ` Paolo Bonzini
2015-04-14  6:41           ` Michael S. Tsirkin
2015-04-07 19:51 ` [Qemu-devel] [PATCH 11/15] pc: Postpone SMBIOS table installation to post machine init minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 12/15] ipmi: Add SMBIOS table entry minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 13/15] configure: Copy some items from default configs to target configs minyard
2015-04-10 11:47   ` Paolo Bonzini
2015-04-07 19:51 ` [Qemu-devel] [PATCH 14/15] acpi: Add hooks for adding things to the SSDT table minyard
2015-04-10 11:29   ` Paolo Bonzini
2015-04-12 16:17   ` Michael S. Tsirkin
2015-04-13  1:30     ` Corey Minyard
2015-04-13  6:36       ` Michael S. Tsirkin
2015-04-13  8:39         ` Paolo Bonzini
2015-04-13 11:32           ` Michael S. Tsirkin
2015-04-13 13:47             ` Paolo Bonzini
2015-04-13 13:44       ` Paolo Bonzini
2015-04-13 16:00         ` Corey Minyard
2015-04-13 16:41           ` Paolo Bonzini
2015-04-10 11:48 ` [Qemu-devel] [PATCH 00/15] IPMI device for qemu 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=552BF029.4040609@acm.org \
    --to=minyard@acm.org \
    --cc=cminyard@mvista.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.