From nobody Sat Nov 1 22:19:01 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1509223997805486.1153092666191; Sat, 28 Oct 2017 13:53:17 -0700 (PDT) Received: from localhost ([::1]:33961 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e8Y6B-00014c-Bm for importer@patchew.org; Sat, 28 Oct 2017 16:52:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45074) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e8Y59-0000lj-CH for qemu-devel@nongnu.org; Sat, 28 Oct 2017 16:51:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e8Y56-0004xv-8l for qemu-devel@nongnu.org; Sat, 28 Oct 2017 16:51:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59090) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1e8Y55-0004wG-Vh for qemu-devel@nongnu.org; Sat, 28 Oct 2017 16:51:48 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9ADD9AC8A for ; Sat, 28 Oct 2017 20:51:46 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-204-17.brq.redhat.com [10.40.204.17]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9C3A6137654; Sat, 28 Oct 2017 20:51:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 9ADD9AC8A Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Sat, 28 Oct 2017 21:51:36 +0100 Message-Id: <20171028205136.8792-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Sat, 28 Oct 2017 20:51:46 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH] smbios: support setting OEM strings table X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Igor Mammedov , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The cloud-init program currently allows fetching of its data by repurposing= of the 'system' type 'serial' field. This is a clear abuse of the serial field= that would clash with other valid usage a virt management app might have for that field. Fortunately the SMBIOS defines an "OEM Strings" table whose puporse is to a= llow exposing of arbitrary vendor specific strings to the operating system. This= is perfect for use with cloud-init, or as a way to pass arguments to OS instal= lers such as anaconda. This patch makes it easier to support this with QEMU. e.g. $QEMU -smbios type=3D11,value=3DHello,value=3DWorld,value=3DTricky,,value= =3Dtest Which results in the guest seeing dmidecode data Handle 0x0E00, DMI type 11, 5 bytes OEM Strings String 1: Hello String 2: World String 3: Tricky,value=3Dtest It is suggested that any app wanting to make use of this OEM strings capabi= lity for accepting data from the host mgmt layer should use its name as a string prefix. e.g. to expose OEM strings targetting both cloud init and anaconda = in parallel the mgmt app could set $QEMU -smbios type=3D11,value=3Dcloud-init:ds=3Dnocloud-net;s=3Dhttp://10= .10.0.1:8000/,\ value=3Danaconda:method=3Dhttp://dl.fedoraproject.org/pub/fedora/li= nux/releases/25/x86_64/os which would appear as Handle 0x0E00, DMI type 11, 5 bytes OEM Strings String 1: cloud-init:ds=3Dnocloud-net;s=3Dhttp://10.10.0.1:8000/ String 2: anaconda:method=3Dhttp://dl.fedoraproject.org/pub/fedor= a/linux/releases/25/x86_64/os Use of such string prefixes means the app won't have to care which string s= lot its data appears in. Signed-off-by: Daniel P. Berrange --- hw/smbios/smbios.c | 72 ++++++++++++++++++++++++++++++++++++++++++= ++++ hw/smbios/smbios_build.h | 12 ++++++++ include/hw/smbios/smbios.h | 6 ++++ 3 files changed, 90 insertions(+) diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index 1a5437a07d..5d11f01874 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -96,6 +96,11 @@ static struct { } type4; =20 static struct { + size_t nvalues; + const char **values; +} type11; + +static struct { const char *loc_pfx, *bank, *manufacturer, *serial, *asset, *part; uint16_t speed; } type17; @@ -282,6 +287,14 @@ static const QemuOptDesc qemu_smbios_type4_opts[] =3D { { /* end of list */ } }; =20 +static const QemuOptDesc qemu_smbios_type11_opts[] =3D { + { + .name =3D "value", + .type =3D QEMU_OPT_STRING, + .help =3D "OEM string data", + }, +}; + static const QemuOptDesc qemu_smbios_type17_opts[] =3D { { .name =3D "type", @@ -590,6 +603,27 @@ static void smbios_build_type_4_table(unsigned instanc= e) smbios_type4_count++; } =20 +static void smbios_build_type_11_table(void) +{ + char count_str[128]; + size_t i; + + if (type11.nvalues =3D=3D 0) { + return; + } + + SMBIOS_BUILD_TABLE_PRE(11, 0xe00, true); /* required */ + + snprintf(count_str, sizeof(count_str), "%zu", type11.nvalues); + t->count =3D type11.nvalues; + + for (i =3D 0; i < type11.nvalues; i++) { + SMBIOS_TABLE_SET_STR_LIST(11, type11.values[i]); + } + + SMBIOS_BUILD_TABLE_POST; +} + #define ONE_KB ((ram_addr_t)1 << 10) #define ONE_MB ((ram_addr_t)1 << 20) #define ONE_GB ((ram_addr_t)1 << 30) @@ -832,6 +866,8 @@ void smbios_get_tables(const struct smbios_phys_mem_are= a *mem_array, smbios_build_type_4_table(i); } =20 + smbios_build_type_11_table(); + #define MAX_DIMM_SZ (16ll * ONE_GB) #define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ : ((ram_size - 1) % MAX_DIMM_SZ) += 1) @@ -882,6 +918,38 @@ static void save_opt(const char **dest, QemuOpts *opts= , const char *name) } } =20 + +struct opt_list { + const char *name; + size_t *ndest; + const char ***dest; +}; + +static int save_opt_one(void *opaque, + const char *name, const char *value, + Error **errp) +{ + struct opt_list *opt =3D opaque; + + if (!g_str_equal(name, opt->name)) { + return 0; + } + + *opt->dest =3D g_renew(const char *, *opt->dest, (*opt->ndest) + 1); + (*opt->dest)[*opt->ndest] =3D value; + (*opt->ndest)++; + return 0; +} + +static void save_opt_list(size_t *ndest, const char ***dest, + QemuOpts *opts, const char *name) +{ + struct opt_list opt =3D { + name, ndest, dest, + }; + qemu_opt_foreach(opts, save_opt_one, &opt, NULL); +} + void smbios_entry_add(QemuOpts *opts, Error **errp) { const char *val; @@ -1035,6 +1103,10 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) save_opt(&type4.asset, opts, "asset"); save_opt(&type4.part, opts, "part"); return; + case 11: + qemu_opts_validate(opts, qemu_smbios_type11_opts, &error_fatal= ); + save_opt_list(&type11.nvalues, &type11.values, opts, "value"); + return; case 17: qemu_opts_validate(opts, qemu_smbios_type17_opts, &error_fatal= ); save_opt(&type17.loc_pfx, opts, "loc_pfx"); diff --git a/hw/smbios/smbios_build.h b/hw/smbios/smbios_build.h index 68b8b72e09..93b360d520 100644 --- a/hw/smbios/smbios_build.h +++ b/hw/smbios/smbios_build.h @@ -63,6 +63,18 @@ extern unsigned smbios_table_cnt; } \ } while (0) =20 +#define SMBIOS_TABLE_SET_STR_LIST(tbl_type, value) \ + do { \ + int len =3D (value !=3D NULL) ? strlen(value) + 1 : 0; = \ + if (len > 1) { \ + smbios_tables =3D g_realloc(smbios_tables, = \ + smbios_tables_len + len); \ + memcpy(smbios_tables + smbios_tables_len, value, len); \ + smbios_tables_len +=3D len; = \ + ++str_index; \ + } \ + } while (0) + #define SMBIOS_BUILD_TABLE_POST \ do { \ size_t term_cnt, t_size; \ diff --git a/include/hw/smbios/smbios.h b/include/hw/smbios/smbios.h index 31e8d5f47e..a83adb93d7 100644 --- a/include/hw/smbios/smbios.h +++ b/include/hw/smbios/smbios.h @@ -195,6 +195,12 @@ struct smbios_type_4 { uint16_t processor_family2; } QEMU_PACKED; =20 +/* SMBIOS type 11 - OEM strings */ +struct smbios_type_11 { + struct smbios_structure_header header; + uint8_t count; +} QEMU_PACKED; + /* SMBIOS type 16 - Physical Memory Array (v2.7) */ struct smbios_type_16 { struct smbios_structure_header header; --=20 2.13.6