qemu-patch-raspberry4/hw/smbios/smbios_build.h
Daniel P. Berrange 2d6dcbf93f smbios: support setting OEM strings table
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 allow
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 installers
such as anaconda.

This patch makes it easier to support this with QEMU. e.g.

  $QEMU -smbios type=11,value=Hello,value=World,value=Tricky,,value=test

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=test

It is suggested that any app wanting to make use of this OEM strings capability
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=11,value=cloud-init:ds=nocloud-net;s=http://10.10.0.1:8000/,\
        value=anaconda:method=http://dl.fedoraproject.org/pub/fedora/linux/releases/25/x86_64/os

which would appear as

  Handle 0x0E00, DMI type 11, 5 bytes
  OEM Strings
          String 1: cloud-init:ds=nocloud-net;s=http://10.10.0.1:8000/
          String 2: anaconda:method=http://dl.fedoraproject.org/pub/fedora/linux/releases/25/x86_64/os

Use of such string prefixes means the app won't have to care which string slot
its data appears in.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2017-12-05 19:13:45 +02:00

100 lines
5.5 KiB
C

/*
* SMBIOS Support
*
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
* Copyright (C) 2013 Red Hat, Inc.
*
* Authors:
* Alex Williamson <alex.williamson@hp.com>
* Markus Armbruster <armbru@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#ifndef QEMU_SMBIOS_BUILD_H
#define QEMU_SMBIOS_BUILD_H
bool smbios_skip_table(uint8_t type, bool required_table);
extern uint8_t *smbios_tables;
extern size_t smbios_tables_len;
extern unsigned smbios_table_max;
extern unsigned smbios_table_cnt;
#define SMBIOS_BUILD_TABLE_PRE(tbl_type, tbl_handle, tbl_required) \
struct smbios_type_##tbl_type *t; \
size_t t_off; /* table offset into smbios_tables */ \
int str_index = 0; \
do { \
/* should we skip building this table ? */ \
if (smbios_skip_table(tbl_type, tbl_required)) { \
return; \
} \
\
/* use offset of table t within smbios_tables */ \
/* (pointer must be updated after each realloc) */ \
t_off = smbios_tables_len; \
smbios_tables_len += sizeof(*t); \
smbios_tables = g_realloc(smbios_tables, smbios_tables_len); \
t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
\
t->header.type = tbl_type; \
t->header.length = sizeof(*t); \
t->header.handle = cpu_to_le16(tbl_handle); \
} while (0)
#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \
do { \
int len = (value != NULL) ? strlen(value) + 1 : 0; \
if (len > 1) { \
smbios_tables = g_realloc(smbios_tables, \
smbios_tables_len + len); \
memcpy(smbios_tables + smbios_tables_len, value, len); \
smbios_tables_len += len; \
/* update pointer post-realloc */ \
t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
t->field = ++str_index; \
} else { \
t->field = 0; \
} \
} while (0)
#define SMBIOS_TABLE_SET_STR_LIST(tbl_type, value) \
do { \
int len = (value != NULL) ? strlen(value) + 1 : 0; \
if (len > 1) { \
smbios_tables = g_realloc(smbios_tables, \
smbios_tables_len + len); \
memcpy(smbios_tables + smbios_tables_len, value, len); \
smbios_tables_len += len; \
++str_index; \
} \
} while (0)
#define SMBIOS_BUILD_TABLE_POST \
do { \
size_t term_cnt, t_size; \
\
/* add '\0' terminator (add two if no strings defined) */ \
term_cnt = (str_index == 0) ? 2 : 1; \
smbios_tables = g_realloc(smbios_tables, \
smbios_tables_len + term_cnt); \
memset(smbios_tables + smbios_tables_len, 0, term_cnt); \
smbios_tables_len += term_cnt; \
\
/* update smbios max. element size */ \
t_size = smbios_tables_len - t_off; \
if (t_size > smbios_table_max) { \
smbios_table_max = t_size; \
} \
\
/* update smbios element count */ \
smbios_table_cnt++; \
} while (0)
#endif /* QEMU_SMBIOS_BUILD_H */