diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in index 024bceeb61..bc4386ee96 100644 --- a/docs/man/xl.cfg.5.pod.in +++ b/docs/man/xl.cfg.5.pod.in @@ -2079,6 +2079,51 @@ number of vendor defined SMBIOS structures (type 128 - 255). Since SMBIOS structures do not present their overall size, each entry in the file must be preceded by a 32b integer indicating the size of the following structure. +=item B + +Specifies the SMBIOS values to be provided to the guest. These set or +override specific entries in the tables provided to the guest. + +Each B is a C string from the following list: + +=over 4 + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=back + =item B Provide a VM generation ID to the guest. diff --git a/tools/golang/xenlight/helpers.gen.go b/tools/golang/xenlight/helpers.gen.go index 3ac4938858..0a203d2232 100644 --- a/tools/golang/xenlight/helpers.gen.go +++ b/tools/golang/xenlight/helpers.gen.go @@ -589,6 +589,38 @@ xc.build_id = C.CString(x.BuildId)} return nil } +// NewSmbios returns an instance of Smbios initialized with defaults. +func NewSmbios() (*Smbios, error) { +var ( +x Smbios +xc C.libxl_smbios) + +C.libxl_smbios_init(&xc) +defer C.libxl_smbios_dispose(&xc) + +if err := x.fromC(&xc); err != nil { +return nil, err } + +return &x, nil} + +func (x *Smbios) fromC(xc *C.libxl_smbios) error { + x.Key = SmbiosType(xc.key) +x.Value = C.GoString(xc.value) + + return nil} + +func (x *Smbios) toC(xc *C.libxl_smbios) (err error){defer func(){ +if err != nil{ +C.libxl_smbios_dispose(xc)} +}() + +xc.key = C.libxl_smbios_type(x.Key) +if x.Value != "" { +xc.value = C.CString(x.Value)} + + return nil + } + // NewDomainCreateInfo returns an instance of DomainCreateInfo initialized with defaults. func NewDomainCreateInfo() (*DomainCreateInfo, error) { var ( @@ -1183,6 +1215,15 @@ return fmt.Errorf("converting field Altp2M: %v", err) } x.SystemFirmware = C.GoString(tmp.system_firmware) x.SmbiosFirmware = C.GoString(tmp.smbios_firmware) +x.Smbios = nil +if n := int(tmp.num_smbios); n > 0 { +cSmbios := (*[1<<28]C.libxl_smbios)(unsafe.Pointer(tmp.smbios))[:n:n] +x.Smbios = make([]Smbios, n) +for i, v := range cSmbios { +if err := x.Smbios[i].fromC(&v); err != nil { +return fmt.Errorf("converting field Smbios: %v", err) } +} +} x.AcpiFirmware = C.GoString(tmp.acpi_firmware) x.Hdtype = Hdtype(tmp.hdtype) if err := x.Nographic.fromC(&tmp.nographic);err != nil { @@ -1495,6 +1536,16 @@ if tmp.SystemFirmware != "" { hvm.system_firmware = C.CString(tmp.SystemFirmware)} if tmp.SmbiosFirmware != "" { hvm.smbios_firmware = C.CString(tmp.SmbiosFirmware)} +if numSmbios := len(tmp.Smbios); numSmbios > 0 { +hvm.smbios = (*C.libxl_smbios)(C.malloc(C.ulong(numSmbios)*C.sizeof_libxl_smbios)) +hvm.num_smbios = C.int(numSmbios) +cSmbios := (*[1<<28]C.libxl_smbios)(unsafe.Pointer(hvm.smbios))[:numSmbios:numSmbios] +for i,v := range tmp.Smbios { +if err := v.toC(&cSmbios[i]); err != nil { +return fmt.Errorf("converting field Smbios: %v", err) +} +} +} if tmp.AcpiFirmware != "" { hvm.acpi_firmware = C.CString(tmp.AcpiFirmware)} hvm.hdtype = C.libxl_hdtype(tmp.Hdtype) diff --git a/tools/golang/xenlight/types.gen.go b/tools/golang/xenlight/types.gen.go index 16ce879e3f..2d8bc7654a 100644 --- a/tools/golang/xenlight/types.gen.go +++ b/tools/golang/xenlight/types.gen.go @@ -392,6 +392,32 @@ Commandline string BuildId string } +type SmbiosType int +const( +SmbiosTypeBiosVendor SmbiosType = 1 +SmbiosTypeBiosVersion SmbiosType = 2 +SmbiosTypeSystemManufacturer SmbiosType = 3 +SmbiosTypeSystemProductName SmbiosType = 4 +SmbiosTypeSystemVersion SmbiosType = 5 +SmbiosTypeSystemSerialNumber SmbiosType = 6 +SmbiosTypeBaseboardManufacturer SmbiosType = 7 +SmbiosTypeBaseboardProductName SmbiosType = 8 +SmbiosTypeBaseboardVersion SmbiosType = 9 +SmbiosTypeBaseboardSerialNumber SmbiosType = 10 +SmbiosTypeBaseboardAssetTag SmbiosType = 11 +SmbiosTypeBaseboardLocationInChassis SmbiosType = 12 +SmbiosTypeEnclosureManufacturer SmbiosType = 13 +SmbiosTypeEnclosureSerialNumber SmbiosType = 14 +SmbiosTypeEnclosureAssetTag SmbiosType = 15 +SmbiosTypeBatteryManufacturer SmbiosType = 16 +SmbiosTypeBatteryDeviceName SmbiosType = 17 +) + +type Smbios struct { +Key SmbiosType +Value string +} + type DomainCreateInfo struct { Type DomainType Hap Defbool @@ -572,6 +598,7 @@ NestedHvm Defbool Altp2M Defbool SystemFirmware string SmbiosFirmware string +Smbios []Smbios AcpiFirmware string Hdtype Hdtype Nographic Defbool diff --git a/tools/include/libxl.h b/tools/include/libxl.h index d652895075..5c65222f1e 100644 --- a/tools/include/libxl.h +++ b/tools/include/libxl.h @@ -174,6 +174,11 @@ */ #define LIBXL_HAVE_BUILDINFO_HVM_MS_VM_GENID 1 +/* + * libxl_domain_build_info has the u.hvm.smbios field. + */ +#define LIBXL_HAVE_BUILDINFO_HVM_SMBIOS 1 + /* * LIBXL_HAVE_VCPUINFO_SOFT_AFFINITY indicates that a 'cpumap_soft' * field (of libxl_bitmap type) is present in libxl_vcpuinfo, diff --git a/tools/libs/light/libxl_dom.c b/tools/libs/light/libxl_dom.c index f6311eea6e..5433301f70 100644 --- a/tools/libs/light/libxl_dom.c +++ b/tools/libs/light/libxl_dom.c @@ -773,6 +773,27 @@ static int hvm_build_set_xs_values(libxl__gc *gc, goto err; } + for (int i = 0; i < info->u.hvm.num_smbios; i++) { + char *p; + path = GCSPRINTF("/local/domain/%d/"HVM_XS_BIOS_STRINGS"/%s", domid, + libxl_smbios_type_to_string(info->u.hvm.smbios[i].key)); + + /* Convert libxl_smbios_type string to xenstore path that hvmloader + * will use, as defined by HVM_XS_*. That is convert the '_' to '-'. */ + p = strrchr(path, '/'); + for ( ; *p; p++) { + if (*p == '_') + *p = '-'; + } + + LOGD(DEBUG, domid, "Writing %s = \"%s\"", path, + info->u.hvm.smbios[i].value); + ret = libxl__xs_printf(gc, XBT_NULL, path, "%s", + info->u.hvm.smbios[i].value); + if (ret) + goto err; + } + /* Only one module can be passed. PVHv2 guests do not support this. */ if (dom->acpi_modules[0].guest_addr_out && info->type == LIBXL_DOMAIN_TYPE_HVM) { diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl index 0cfad8508d..df4dd36697 100644 --- a/tools/libs/light/libxl_types.idl +++ b/tools/libs/light/libxl_types.idl @@ -423,6 +423,31 @@ libxl_version_info = Struct("version_info", [ ("build_id", string), ], dir=DIR_OUT) +libxl_smbios_type = Enumeration("smbios_type", [ + (1, "bios_vendor"), + (2, "bios_version"), + (3, "system_manufacturer"), + (4, "system_product_name"), + (5, "system_version"), + (6, "system_serial_number"), + (7, "baseboard_manufacturer"), + (8, "baseboard_product_name"), + (9, "baseboard_version"), + (10, "baseboard_serial_number"), + (11, "baseboard_asset_tag"), + (12, "baseboard_location_in_chassis"), + (13, "enclosure_manufacturer"), + (14, "enclosure_serial_number"), + (15, "enclosure_asset_tag"), + (16, "battery_manufacturer"), + (17, "battery_device_name"), + ]) + +libxl_smbios = Struct("smbios", [ + ("key", libxl_smbios_type), + ("value", string), + ], dir=DIR_IN) + libxl_domain_create_info = Struct("domain_create_info",[ ("type", libxl_domain_type), ("hap", libxl_defbool), @@ -609,6 +634,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("altp2m", libxl_defbool), ("system_firmware", string), ("smbios_firmware", string), + ("smbios", Array(libxl_smbios, "num_smbios")), ("acpi_firmware", string), ("hdtype", libxl_hdtype), ("nographic", libxl_defbool), diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c index 853e9f357a..ba219024b6 100644 --- a/tools/xl/xl_parse.c +++ b/tools/xl/xl_parse.c @@ -1297,8 +1297,9 @@ void parse_config_data(const char *config_source, XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *usbctrls, *usbdevs, *p9devs, *vdispls, *pvcallsifs_devs; XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs, - *mca_caps; + *mca_caps, *smbios; int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps; + int num_smbios; int pci_power_mgmt = 0; int pci_msitranslate = 0; int pci_permissive = 0; @@ -1860,6 +1861,61 @@ void parse_config_data(const char *config_source, xlu_cfg_replace_string(config, "acpi_firmware", &b_info->u.hvm.acpi_firmware, 0); + switch (xlu_cfg_get_list(config, "smbios", &smbios, &num_smbios, 0)) + { + case 0: /* Success */ + b_info->u.hvm.num_smbios = num_smbios; + b_info->u.hvm.smbios = xcalloc(num_smbios, sizeof(libxl_smbios)); + for (i = 0; i < num_smbios; i++) { + libxl_smbios_type type; + char *option; + char *value; + + buf = xlu_cfg_get_listitem(smbios, i); + if (!buf) { + fprintf(stderr, + "xl: Unable to get element #%d in smbios list\n", + i); + exit(EXIT_FAILURE); + } + + option = xstrdup(buf); + value = strchr(option, '='); + if (value == NULL) { + fprintf(stderr, "xl: failed to split \"%s\" at '='\n", + option); + exit(EXIT_FAILURE); + } + + *value = '\0'; + value++; + + if (*value == '\0') { + fprintf(stderr, + "xl: empty value not allowed for smbios \"%s=\"\n", + option); + exit(EXIT_FAILURE); + } + + e = libxl_smbios_type_from_string(option, &type); + if (e) { + fprintf(stderr, "xl: unknown smbios type '%s'\n", option); + exit(EXIT_FAILURE); + } + + b_info->u.hvm.smbios[i].key = type; + b_info->u.hvm.smbios[i].value = xstrdup(value); + + free(option); + } + break; + case ESRCH: /* Option not present */ + break; + default: + fprintf(stderr,"xl: Unable to parse smbios options.\n"); + exit(EXIT_FAILURE); + } + if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) { if (!strcmp(buf, "generate")) { e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);