qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [ARM SMBIOS V2 PATCH 5/6] smbios: add smbios 3.0 suppor


From: Laszlo Ersek
Subject: Re: [Qemu-devel] [ARM SMBIOS V2 PATCH 5/6] smbios: add smbios 3.0 support
Date: Fri, 7 Aug 2015 19:22:08 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.1.0

comments below

On 08/06/15 19:14, Wei Huang wrote:
> This patch adds support for SMBIOS 3.0 entry point. When caller invokes
> smbios_set_defaults(), it can specify entry point as 2.1 or 3.0. Then
> smbios_get_tables() will return the entry point table in right format.
> 
> Signed-off-by: Wei Huang <address@hidden>
> ---
>  hw/i386/pc_piix.c          |  3 +-
>  hw/i386/pc_q35.c           |  3 +-
>  hw/smbios/smbios.c         | 72 
> +++++++++++++++++++++++++++++++---------------
>  include/hw/smbios/smbios.h | 54 ++++++++++++++++++++++++----------
>  4 files changed, 92 insertions(+), 40 deletions(-)
> 
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 653c710..04636b1 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -173,7 +173,8 @@ static void pc_init1(MachineState *machine)
>          MachineClass *mc = MACHINE_GET_CLASS(machine);
>          /* These values are guest ABI, do not change */
>          smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
> -                            mc->name, smbios_legacy_mode, 
> smbios_uuid_encoded);
> +                            mc->name, smbios_legacy_mode, 
> smbios_uuid_encoded,
> +                            SMBIOS_ENTRY_POINT_21);
>      }
>  
>      /* allocate ram and load rom/bios */
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index d83df14..061507d 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -165,7 +165,8 @@ static void pc_q35_init(MachineState *machine)
>      if (smbios_defaults) {
>          /* These values are guest ABI, do not change */
>          smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
> -                            mc->name, smbios_legacy_mode, 
> smbios_uuid_encoded);
> +                            mc->name, smbios_legacy_mode, 
> smbios_uuid_encoded,
> +                            SMBIOS_ENTRY_POINT_21);
>      }
>  
>      /* allocate ram and load rom/bios */
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 08ba62a..ea3a32d 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -48,6 +48,7 @@ static uint8_t *smbios_entries;
>  static size_t smbios_entries_len;
>  static bool smbios_legacy = true;
>  static bool smbios_uuid_encoded = true;
> +static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_21;

Looks good. This initialization makes sure that smbios_ep_type is set
compatibly even if smbios_set_defaults() is never called. (And allows me
to forego verifying whether smbios_set_defaults() is "always called when
it is needed".) So, good.

>  /* end: legacy structures & constants for <= 2.0 machines */
>  
>  
> @@ -55,7 +56,8 @@ static uint8_t *smbios_tables;
>  static size_t smbios_tables_len;
>  static unsigned smbios_table_max;
>  static unsigned smbios_table_cnt;
> -static struct smbios_entry_point ep;
> +static SmbiosEntryPoint ep;
> +static size_t ep_length;
>  
>  static int smbios_type4_count = 0;
>  static bool smbios_immutable;
> @@ -771,11 +773,12 @@ void smbios_set_cpuid(uint32_t version, uint32_t 
> features)
>  
>  void smbios_set_defaults(const char *manufacturer, const char *product,
>                           const char *version, bool legacy_mode,
> -                         bool uuid_encoded)
> +                         bool uuid_encoded, SmbiosEntryPointType ep_type)
>  {
>      smbios_have_defaults = true;
>      smbios_legacy = legacy_mode;
>      smbios_uuid_encoded = uuid_encoded;
> +    smbios_ep_type = ep_type;
>  
>      /* drop unwanted version of command-line file blob(s) */
>      if (smbios_legacy) {
> @@ -808,26 +811,49 @@ void smbios_set_defaults(const char *manufacturer, 
> const char *product,
>  
>  static void smbios_entry_point_setup(void)
>  {
> -    memcpy(ep.anchor_string, "_SM_", 4);
> -    memcpy(ep.intermediate_anchor_string, "_DMI_", 5);
> -    ep.length = sizeof(struct smbios_entry_point);
> -    ep.entry_point_revision = 0; /* formatted_area reserved, per spec v2.1+ 
> */
> -    memset(ep.formatted_area, 0, 5);
> -
> -    /* compliant with smbios spec v2.8 */
> -    ep.smbios_major_version = 2;
> -    ep.smbios_minor_version = 8;
> -    ep.smbios_bcd_revision = 0x28;
> -
> -    /* set during table construction, but BIOS may override: */
> -    ep.structure_table_length = cpu_to_le16(smbios_tables_len);
> -    ep.max_structure_size = cpu_to_le16(smbios_table_max);
> -    ep.number_of_structures = cpu_to_le16(smbios_table_cnt);
> -
> -    /* BIOS must recalculate: */
> -    ep.checksum = 0;
> -    ep.intermediate_checksum = 0;
> -    ep.structure_table_address = cpu_to_le32(0);
> +    if (smbios_ep_type == SMBIOS_ENTRY_POINT_21) {
> +        memcpy(ep.ep21.anchor_string, "_SM_", 4);
> +        memcpy(ep.ep21.intermediate_anchor_string, "_DMI_", 5);
> +        ep.ep21.length = sizeof(struct smbios_21_entry_point);
> +        ep.ep21.entry_point_revision = 0; /* formatted_area reserved */
> +        memset(ep.ep21.formatted_area, 0, 5);
> +
> +        /* compliant with smbios spec v2.8 */
> +        ep.ep21.smbios_major_version = 2;
> +        ep.ep21.smbios_minor_version = 8;
> +        ep.ep21.smbios_bcd_revision = 0x28;
> +
> +        /* set during table construction, but BIOS may override: */
> +        ep.ep21.structure_table_length = cpu_to_le16(smbios_tables_len);
> +        ep.ep21.max_structure_size = cpu_to_le16(smbios_table_max);
> +        ep.ep21.number_of_structures = cpu_to_le16(smbios_table_cnt);
> +
> +        /* BIOS must recalculate: */
> +        ep.ep21.checksum = 0;
> +        ep.ep21.intermediate_checksum = 0;
> +        ep.ep21.structure_table_address = cpu_to_le32(0);
> +
> +        /* setup the anchor point length */
> +        ep_length = sizeof (struct smbios_21_entry_point);
> +    } else if (smbios_ep_type == SMBIOS_ENTRY_POINT_30) {
> +        memcpy(ep.ep30.anchor_string, "_SM3_", 5);
> +        ep.ep30.length = sizeof(struct smbios_30_entry_point);
> +        ep.ep30.entry_point_revision = 1;
> +
> +        /* compliant with smbios spec 3.0 */
> +        ep.ep30.smbios_major_version = 3;
> +        ep.ep30.smbios_minor_version = 0;
> +        ep.ep30.smbios_doc_rev = 0;
> +
> +        /* set during table construct, but BIOS might override */
> +        ep.ep30.structure_table_max_size = cpu_to_le32(smbios_tables_len);
> +
> +        /* BIOS must recalculate */
> +        ep.ep30.checksum = 0;
> +        ep.ep30.structure_table_address = cpu_to_le64(0);
> +

The _reserved field is not zeroed.

It's not a problem in practice (because "ep" has static storage
duration, and is therefore zero-initialized), but I think zeroing it
explicitly it would be clearer.

> +        ep_length = sizeof (struct smbios_30_entry_point);
> +    }

I think you should assert here that smbios_ep_type has no other value.
(Alternatively, consider turning this into a switch statement, and
assert(false) under the "default" label.)

>  }
>  
>  void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
> @@ -886,7 +912,7 @@ void smbios_get_tables(const struct smbios_phys_mem_area 
> *mem_array,
>      *tables = smbios_tables;
>      *tables_len = smbios_tables_len;
>      *anchor = (uint8_t *)&ep;
> -    *anchor_len = sizeof(struct smbios_entry_point);
> +    *anchor_len = ep_length;
>  }
>  
>  static void save_opt(const char **dest, QemuOpts *opts, const char *name)
> diff --git a/include/hw/smbios/smbios.h b/include/hw/smbios/smbios.h
> index e727233..ba0e68f 100644
> --- a/include/hw/smbios/smbios.h
> +++ b/include/hw/smbios/smbios.h
> @@ -24,26 +24,20 @@ struct smbios_phys_mem_area {
>      uint64_t length;
>  };
>  
> -void smbios_entry_add(QemuOpts *opts);
> -void smbios_set_cpuid(uint32_t version, uint32_t features);
> -void smbios_set_defaults(const char *manufacturer, const char *product,
> -                         const char *version, bool legacy_mode,
> -                         bool uuid_encoded);
> -uint8_t *smbios_get_table_legacy(size_t *length);
> -void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
> -                       const unsigned int mem_array_size,
> -                       const ram_addr_t ram_size,
> -                       uint8_t **tables, size_t *tables_len,
> -                       uint8_t **anchor, size_t *anchor_len);
> -
>  /*
>   * SMBIOS spec defined tables
>   */
> +typedef enum SmbiosEntryPointType {
> +    SMBIOS_ENTRY_POINT_21,
> +    SMBIOS_ENTRY_POINT_30,
> +} SmbiosEntryPointType;
>  
> -/* SMBIOS entry point (anchor).
> - * BIOS must place this at a 16-bit-aligned address between 0xf0000 and 
> 0xfffff.
> +/* SMBIOS entry point
> + * Note: BIOS must place this at a 16-bit-aligned address between 0xf0000
> + * and 0xfffff.
>   */
> -struct smbios_entry_point {
> +/* SMBIOS 2.1 entry point */
> +struct smbios_21_entry_point {
>      uint8_t anchor_string[4];
>      uint8_t checksum;
>      uint8_t length;
> @@ -60,6 +54,25 @@ struct smbios_entry_point {
>      uint8_t smbios_bcd_revision;
>  } QEMU_PACKED;
>  
> +/* SMBIOS 3.0 entry point */
> +struct smbios_30_entry_point {
> +    uint8_t anchor_string[5];
> +    uint8_t checksum;
> +    uint8_t length;
> +    uint8_t smbios_major_version;
> +    uint8_t smbios_minor_version;
> +    uint8_t smbios_doc_rev;
> +    uint8_t entry_point_revision;
> +    uint8_t _reserved;

Please call this field "reserved", not "_reserved".

I'm asking for this *despite* the fact that "_reserved" is valid as a
field name.

>From the standard: "All identifiers that begin with an underscore are
always reserved for use as identifiers with file scope in both the
ordinary and tag name spaces." However, we're not in the ordinary
identifier nor the tag name space here -- "each structure or union has a
separate name space for its members".

But, I still think _reserved is not really idiomatic.

> +    uint32_t structure_table_max_size;
> +    uint64_t structure_table_address;
> +} QEMU_PACKED;
> +
> +typedef union QEMU_PACKED {
> +    struct smbios_21_entry_point ep21;
> +    struct smbios_30_entry_point ep30;
> +} SmbiosEntryPoint;
> +

QEMU_PACKED should come between "}" and "SmbiosEntryPoint", for
consistency with the rest of the code.

>  /* This goes at the beginning of every SMBIOS structure. */
>  struct smbios_structure_header {
>      uint8_t type;
> @@ -234,4 +247,15 @@ struct smbios_type_127 {
>      struct smbios_structure_header header;
>  } QEMU_PACKED;
>  
> +void smbios_entry_add(QemuOpts *opts);
> +void smbios_set_cpuid(uint32_t version, uint32_t features);
> +void smbios_set_defaults(const char *manufacturer, const char *product,
> +                         const char *version, bool legacy_mode,
> +                         bool uuid_encoded, SmbiosEntryPointType ep_type);
> +uint8_t *smbios_get_table_legacy(size_t *length);
> +void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
> +                       const unsigned int mem_array_size,
> +                       const ram_addr_t ram_size,
> +                       uint8_t **tables, size_t *tables_len,
> +                       uint8_t **anchor, size_t *anchor_len);
>  #endif /*QEMU_SMBIOS_H */
> 

Thanks!
Laszlo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]