On Wed, Jul 23, 2025 at 12:01:28PM +0300, Daniil Tatianin wrote:
> This is useful to be able to indicate various supported features to the
> guest, or freeze a specific version of SeaBIOS to prevent guest visible
> changes between BIOS updates. This is currently not possible since the
> extension bytes indicated by SeaBIOS are slightly different than those
> QEMU sets by default.
> 
> Signed-off-by: Daniil Tatianin <d-tatia...@yandex-team.ru>
> ---
>  hw/smbios/smbios.c           | 66 +++++++++++++++++++++++++++++++++---
>  include/hw/firmware/smbios.h |  3 ++
>  2 files changed, 64 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index ad4cd6721e..73699e8a62 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -178,6 +178,14 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
>          .name = "uefi",
>          .type = QEMU_OPT_BOOL,
>          .help = "uefi support",
> +    },{
> +        .name = "extension_byte_1",
> +        .type = QEMU_OPT_NUMBER,
> +        .help = "BIOS characteristics extension byte 1"
> +    },{
> +        .name = "extension_byte_2",
> +        .type = QEMU_OPT_NUMBER,
> +        .help = "BIOS characteristics extension byte 2"
>      },
>      { /* end of list */ }
>  };
> @@ -572,10 +580,23 @@ static void smbios_build_type_0_table(void)
>      t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
>  
>      t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
> -    t->bios_characteristics_extension_bytes[0] = 0;
> -    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
> -    if (smbios_type0.uefi) {
> -        t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
> +
> +    if (smbios_type0.have_extension_bytes[0]) {
> +        t->bios_characteristics_extension_bytes[0] =
> +            smbios_type0.extension_bytes[0];
> +    } else {
> +        t->bios_characteristics_extension_bytes[0] = 0;
> +    }
> +
> +    if (smbios_type0.have_extension_bytes[1]) {
> +        t->bios_characteristics_extension_bytes[1] =
> +            smbios_type0.extension_bytes[1];
> +    } else {
> +        t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM 
> */
> +
> +        if (smbios_type0.uefi) {
> +            t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
> +        }

should we not or these in, anyway?

>      }
>  
>      if (smbios_type0.have_major_minor) {
> @@ -1403,7 +1424,42 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>              save_opt(&smbios_type0.vendor, opts, "vendor");
>              save_opt(&smbios_type0.version, opts, "version");
>              save_opt(&smbios_type0.date, opts, "date");
> -            smbios_type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
> +
> +            if (qemu_opt_get(opts, "extension_byte_1")) {
> +                uint64_t ex_val;
> +
> +                ex_val = qemu_opt_get_number(opts, "extension_byte_1", 0);
> +                if (ex_val > 0xFF) {
> +                    error_setg(errp, "Invalid extension_byte_1");
> +                    return;
> +                }
> +
> +                smbios_type0.extension_bytes[0] = ex_val;
> +                smbios_type0.have_extension_bytes[0] = true;
> +            }
> +
> +            if (qemu_opt_get(opts, "extension_byte_2")) {
> +                uint64_t ex_val;
> +
> +                ex_val = qemu_opt_get_number(opts, "extension_byte_2", 0);
> +                if (ex_val > 0xFF) {
> +                    error_setg(errp, "Invalid extension_byte_2");
> +                    return;
> +                }
> +
> +                smbios_type0.extension_bytes[1] = ex_val;
> +                smbios_type0.have_extension_bytes[1] = true;
> +            }
> +
> +            if (qemu_opt_get(opts, "uefi")) {
> +                if (smbios_type0.have_extension_bytes[1]) {
> +                    error_setg(errp, "'uefi' and 'extension_byte_2' are "
> +                                     "mutually exclusive");
> +                    return;
> +                }
> +
> +                smbios_type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
> +            }
>  
>              val = qemu_opt_get(opts, "release");
>              if (val) {
> diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
> index f066ab7262..67b3b28471 100644
> --- a/include/hw/firmware/smbios.h
> +++ b/include/hw/firmware/smbios.h
> @@ -24,6 +24,9 @@ typedef struct {
>      const char *vendor, *version, *date;
>      bool have_major_minor, uefi;
>      uint8_t major, minor;
> +
> +    bool have_extension_bytes[2];
> +    uint8_t extension_bytes[2];
>  } smbios_type0_t;
>  extern smbios_type0_t smbios_type0;
>  
> -- 
> 2.34.1


Reply via email to