2010-11-05 15:22:13 +01:00
|
|
|
/*
|
2012-12-13 15:31:53 +00:00
|
|
|
* virsysinfo.c: get SMBIOS/sysinfo information from the host
|
2010-11-05 15:22:13 +01:00
|
|
|
*
|
2014-03-12 18:03:03 -06:00
|
|
|
* Copyright (C) 2010-2014 Red Hat, Inc.
|
2010-11-05 15:22:13 +01:00
|
|
|
* Copyright (C) 2010 Daniel Veillard
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 16:30:55 -06:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 18:06:23 +08:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2010-11-05 15:22:13 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-13 15:31:53 +00:00
|
|
|
#include "virsysinfo.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2018-01-12 12:38:01 +01:00
|
|
|
#include "virlog.h"
|
2013-05-09 14:59:04 -04:00
|
|
|
#include "virfile.h"
|
2013-04-03 12:36:23 +02:00
|
|
|
#include "virstring.h"
|
2021-01-06 12:56:11 +01:00
|
|
|
#include "virxml.h"
|
2010-11-05 15:22:13 +01:00
|
|
|
|
2018-12-13 14:53:50 +00:00
|
|
|
#define LIBVIRT_VIRSYSINFOPRIV_H_ALLOW
|
2017-03-06 15:14:45 +01:00
|
|
|
#include "virsysinfopriv.h"
|
|
|
|
|
2010-11-05 15:22:13 +01:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_SYSINFO
|
|
|
|
|
2018-01-12 12:38:01 +01:00
|
|
|
VIR_LOG_INIT("util.sysinfo");
|
2010-11-05 15:22:13 +01:00
|
|
|
|
2019-03-16 14:20:32 -04:00
|
|
|
VIR_ENUM_IMPL(virSysinfo,
|
|
|
|
VIR_SYSINFO_LAST,
|
2019-01-20 11:30:15 -05:00
|
|
|
"smbios",
|
2020-06-04 14:15:40 +02:00
|
|
|
"fwcfg"
|
2019-01-20 11:30:15 -05:00
|
|
|
);
|
2011-05-27 10:47:30 +01:00
|
|
|
|
2012-12-14 16:08:24 +01:00
|
|
|
static const char *sysinfoSysinfo = "/proc/sysinfo";
|
|
|
|
static const char *sysinfoCpuinfo = "/proc/cpuinfo";
|
|
|
|
|
|
|
|
#define SYSINFO sysinfoSysinfo
|
|
|
|
#define CPUINFO sysinfoCpuinfo
|
2017-10-17 17:05:47 +02:00
|
|
|
#define CPUINFO_FILE_LEN (1024*1024) /* 1MB limit for /proc/cpuinfo file */
|
2012-12-14 16:08:24 +01:00
|
|
|
|
|
|
|
|
2017-03-06 15:25:07 +01:00
|
|
|
void
|
2020-06-08 12:53:04 +02:00
|
|
|
virSysinfoSetup(const char *sysinfo,
|
2017-03-06 15:25:07 +01:00
|
|
|
const char *cpuinfo)
|
2012-12-14 16:08:24 +01:00
|
|
|
{
|
|
|
|
sysinfoSysinfo = sysinfo;
|
|
|
|
sysinfoCpuinfo = cpuinfo;
|
|
|
|
}
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
void virSysinfoBIOSDefFree(virSysinfoBIOSDef *def)
|
2015-05-12 12:02:29 +02:00
|
|
|
{
|
|
|
|
if (def == NULL)
|
|
|
|
return;
|
|
|
|
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->vendor);
|
|
|
|
g_free(def->version);
|
|
|
|
g_free(def->date);
|
|
|
|
g_free(def->release);
|
|
|
|
g_free(def);
|
2015-05-12 12:02:29 +02:00
|
|
|
}
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
void virSysinfoSystemDefFree(virSysinfoSystemDef *def)
|
2015-05-12 14:33:12 +02:00
|
|
|
{
|
|
|
|
if (def == NULL)
|
|
|
|
return;
|
|
|
|
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->manufacturer);
|
|
|
|
g_free(def->product);
|
|
|
|
g_free(def->version);
|
|
|
|
g_free(def->serial);
|
|
|
|
g_free(def->uuid);
|
|
|
|
g_free(def->sku);
|
|
|
|
g_free(def->family);
|
|
|
|
g_free(def);
|
2015-05-12 14:33:12 +02:00
|
|
|
}
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
void virSysinfoBaseBoardDefClear(virSysinfoBaseBoardDef *def)
|
2015-05-12 16:47:49 +02:00
|
|
|
{
|
|
|
|
if (def == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->manufacturer);
|
|
|
|
VIR_FREE(def->product);
|
|
|
|
VIR_FREE(def->version);
|
|
|
|
VIR_FREE(def->serial);
|
|
|
|
VIR_FREE(def->asset);
|
|
|
|
VIR_FREE(def->location);
|
|
|
|
}
|
2015-05-12 14:33:12 +02:00
|
|
|
|
2018-02-14 17:22:38 +08:00
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
void virSysinfoChassisDefFree(virSysinfoChassisDef *def)
|
2018-02-14 17:22:38 +08:00
|
|
|
{
|
|
|
|
if (def == NULL)
|
|
|
|
return;
|
|
|
|
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->manufacturer);
|
|
|
|
g_free(def->version);
|
|
|
|
g_free(def->serial);
|
|
|
|
g_free(def->asset);
|
|
|
|
g_free(def->sku);
|
|
|
|
g_free(def);
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDef *def)
|
2017-10-28 14:56:51 +01:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (def == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < def->nvalues; i++)
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->values[i]);
|
|
|
|
g_free(def->values);
|
2017-10-28 14:56:51 +01:00
|
|
|
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def);
|
2017-10-28 14:56:51 +01:00
|
|
|
}
|
|
|
|
|
2020-06-16 13:01:38 +02:00
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoFWCfgDefClear(virSysinfoFWCfgDef *def)
|
2020-06-16 13:01:38 +02:00
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->name);
|
|
|
|
VIR_FREE(def->value);
|
|
|
|
VIR_FREE(def->file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-05 15:22:13 +01:00
|
|
|
/**
|
|
|
|
* virSysinfoDefFree:
|
|
|
|
* @def: a sysinfo structure
|
|
|
|
*
|
|
|
|
* Free up the sysinfo structure
|
|
|
|
*/
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
void virSysinfoDefFree(virSysinfoDef *def)
|
2010-11-05 15:22:13 +01:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 15:09:33 +01:00
|
|
|
size_t i;
|
2011-06-24 13:42:02 +08:00
|
|
|
|
2010-11-05 15:22:13 +01:00
|
|
|
if (def == NULL)
|
|
|
|
return;
|
|
|
|
|
2015-05-12 12:02:29 +02:00
|
|
|
virSysinfoBIOSDefFree(def->bios);
|
2015-05-12 14:33:12 +02:00
|
|
|
virSysinfoSystemDefFree(def->system);
|
2011-06-24 13:42:02 +08:00
|
|
|
|
2015-05-12 16:47:49 +02:00
|
|
|
for (i = 0; i < def->nbaseBoard; i++)
|
|
|
|
virSysinfoBaseBoardDefClear(def->baseBoard + i);
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->baseBoard);
|
2015-05-12 16:47:49 +02:00
|
|
|
|
2018-02-14 17:22:38 +08:00
|
|
|
virSysinfoChassisDefFree(def->chassis);
|
|
|
|
|
2013-05-24 10:58:25 -06:00
|
|
|
for (i = 0; i < def->nprocessor; i++) {
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->processor[i].processor_socket_destination);
|
|
|
|
g_free(def->processor[i].processor_type);
|
|
|
|
g_free(def->processor[i].processor_family);
|
|
|
|
g_free(def->processor[i].processor_manufacturer);
|
|
|
|
g_free(def->processor[i].processor_signature);
|
|
|
|
g_free(def->processor[i].processor_version);
|
|
|
|
g_free(def->processor[i].processor_external_clock);
|
|
|
|
g_free(def->processor[i].processor_max_speed);
|
|
|
|
g_free(def->processor[i].processor_status);
|
|
|
|
g_free(def->processor[i].processor_serial_number);
|
|
|
|
g_free(def->processor[i].processor_part_number);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->processor);
|
2013-05-24 10:58:25 -06:00
|
|
|
for (i = 0; i < def->nmemory; i++) {
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->memory[i].memory_size);
|
|
|
|
g_free(def->memory[i].memory_form_factor);
|
|
|
|
g_free(def->memory[i].memory_locator);
|
|
|
|
g_free(def->memory[i].memory_bank_locator);
|
|
|
|
g_free(def->memory[i].memory_type);
|
|
|
|
g_free(def->memory[i].memory_type_detail);
|
|
|
|
g_free(def->memory[i].memory_speed);
|
|
|
|
g_free(def->memory[i].memory_manufacturer);
|
|
|
|
g_free(def->memory[i].memory_serial_number);
|
|
|
|
g_free(def->memory[i].memory_part_number);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->memory);
|
2011-06-24 13:42:02 +08:00
|
|
|
|
2017-10-28 14:56:51 +01:00
|
|
|
virSysinfoOEMStringsDefFree(def->oemStrings);
|
|
|
|
|
2020-06-16 13:01:38 +02:00
|
|
|
for (i = 0; i < def->nfw_cfgs; i++)
|
|
|
|
virSysinfoFWCfgDefClear(&def->fw_cfgs[i]);
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def->fw_cfgs);
|
2020-06-16 13:01:38 +02:00
|
|
|
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(def);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
|
2012-03-15 16:05:26 +05:30
|
|
|
|
2019-05-09 16:10:37 +02:00
|
|
|
static bool
|
|
|
|
virSysinfoDefIsEmpty(const virSysinfoDef *def)
|
|
|
|
{
|
|
|
|
return !(def->bios || def->system || def->nbaseBoard > 0 ||
|
|
|
|
def->chassis || def->nprocessor > 0 ||
|
|
|
|
def->nmemory > 0 || def->oemStrings);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-15 16:05:26 +05:30
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParsePPCSystem(const char *base, virSysinfoSystemDef **sysdef)
|
2012-03-15 16:05:26 +05:30
|
|
|
{
|
2015-05-12 14:33:12 +02:00
|
|
|
int ret = -1;
|
2012-03-15 16:05:26 +05:30
|
|
|
char *eol = NULL;
|
|
|
|
const char *cur;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoSystemDef *def;
|
2012-03-15 16:05:26 +05:30
|
|
|
|
|
|
|
if ((cur = strstr(base, "platform")) == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
def = g_new0(virSysinfoSystemDef, 1);
|
2015-05-12 14:33:12 +02:00
|
|
|
|
2012-03-15 16:05:26 +05:30
|
|
|
base = cur;
|
|
|
|
/* Account for format 'platform : XXXX'*/
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->family = g_strndup(cur, eol - cur);
|
2012-03-15 16:05:26 +05:30
|
|
|
|
|
|
|
if ((cur = strstr(base, "model")) != NULL) {
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->serial = g_strndup(cur, eol - cur);
|
2012-03-15 16:05:26 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if ((cur = strstr(base, "machine")) != NULL) {
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->version = g_strndup(cur, eol - cur);
|
2012-03-15 16:05:26 +05:30
|
|
|
}
|
|
|
|
|
2015-05-12 14:33:12 +02:00
|
|
|
if (!def->manufacturer && !def->product && !def->version &&
|
|
|
|
!def->serial && !def->uuid && !def->sku && !def->family) {
|
2022-01-28 18:42:45 +01:00
|
|
|
g_clear_pointer(&def, virSysinfoSystemDefFree);
|
2015-05-12 14:33:12 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 14:58:29 +01:00
|
|
|
*sysdef = g_steal_pointer(&def);
|
2015-05-12 14:33:12 +02:00
|
|
|
ret = 0;
|
|
|
|
virSysinfoSystemDefFree(def);
|
|
|
|
return ret;
|
2012-03-15 16:05:26 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParsePPCProcessor(const char *base, virSysinfoDef *ret)
|
2012-03-15 16:05:26 +05:30
|
|
|
{
|
|
|
|
const char *cur;
|
|
|
|
char *eol, *tmp_base;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoProcessorDef *processor;
|
2012-03-15 16:05:26 +05:30
|
|
|
|
2012-10-17 10:23:12 +01:00
|
|
|
while ((tmp_base = strstr(base, "processor")) != NULL) {
|
2012-03-15 16:05:26 +05:30
|
|
|
base = tmp_base;
|
|
|
|
eol = strchr(base, '\n');
|
|
|
|
cur = strchr(base, ':') + 1;
|
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(ret->processor, ret->nprocessor, 1);
|
2012-03-15 16:05:26 +05:30
|
|
|
processor = &ret->processor[ret->nprocessor - 1];
|
|
|
|
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_socket_destination = g_strndup(cur,
|
|
|
|
eol - cur);
|
2017-03-07 07:01:21 -05:00
|
|
|
base = cur;
|
2012-03-15 16:05:26 +05:30
|
|
|
|
|
|
|
if ((cur = strstr(base, "cpu")) != NULL) {
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_type = g_strndup(cur, eol - cur);
|
2017-03-07 07:01:21 -05:00
|
|
|
base = cur;
|
2012-03-15 16:05:26 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if ((cur = strstr(base, "revision")) != NULL) {
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_version = g_strndup(cur, eol - cur);
|
2017-03-07 07:01:21 -05:00
|
|
|
base = cur;
|
2012-03-15 16:05:26 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virSysinfoRead for PowerPC
|
|
|
|
* Gathers sysinfo data from /proc/cpuinfo */
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoDef *
|
2017-03-06 15:14:45 +01:00
|
|
|
virSysinfoReadPPC(void)
|
2014-03-18 09:14:35 +01:00
|
|
|
{
|
2021-03-11 06:17:07 +01:00
|
|
|
g_autoptr(virSysinfoDef) ret = NULL;
|
2019-12-20 13:43:14 +01:00
|
|
|
g_autofree char *outbuf = NULL;
|
2012-03-15 16:05:26 +05:30
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
ret = g_new0(virSysinfoDef, 1);
|
2012-03-15 16:05:26 +05:30
|
|
|
|
2014-04-04 09:21:06 +08:00
|
|
|
if (virFileReadAll(CPUINFO, CPUINFO_FILE_LEN, &outbuf) < 0) {
|
2012-07-18 11:26:24 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 15:13:48 +01:00
|
|
|
_("Failed to open %1$s"), CPUINFO);
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2012-03-15 16:05:26 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
ret->nprocessor = 0;
|
|
|
|
ret->processor = NULL;
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParsePPCProcessor(outbuf, ret) < 0)
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2012-03-15 16:05:26 +05:30
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParsePPCSystem(outbuf, &ret->system) < 0)
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2012-03-15 16:05:26 +05:30
|
|
|
|
2019-12-20 13:43:14 +01:00
|
|
|
return g_steal_pointer(&ret);
|
2012-03-15 16:05:26 +05:30
|
|
|
}
|
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
|
2013-04-03 18:58:50 +01:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseARMSystem(const char *base, virSysinfoSystemDef **sysdef)
|
2013-04-03 18:58:50 +01:00
|
|
|
{
|
2015-05-12 14:33:12 +02:00
|
|
|
int ret = -1;
|
2013-04-03 18:58:50 +01:00
|
|
|
char *eol = NULL;
|
|
|
|
const char *cur;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoSystemDef *def;
|
2013-04-03 18:58:50 +01:00
|
|
|
|
|
|
|
if ((cur = strstr(base, "platform")) == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
def = g_new0(virSysinfoSystemDef, 1);
|
2015-05-12 14:33:12 +02:00
|
|
|
|
2013-04-03 18:58:50 +01:00
|
|
|
base = cur;
|
|
|
|
/* Account for format 'platform : XXXX'*/
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->family = g_strndup(cur, eol - cur);
|
2013-04-03 18:58:50 +01:00
|
|
|
|
|
|
|
if ((cur = strstr(base, "model")) != NULL) {
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->serial = g_strndup(cur, eol - cur);
|
2013-04-03 18:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((cur = strstr(base, "machine")) != NULL) {
|
|
|
|
cur = strchr(cur, ':') + 1;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->version = g_strndup(cur, eol - cur);
|
2013-04-03 18:58:50 +01:00
|
|
|
}
|
2012-06-22 13:50:14 +02:00
|
|
|
|
2015-05-12 14:33:12 +02:00
|
|
|
if (!def->manufacturer && !def->product && !def->version &&
|
|
|
|
!def->serial && !def->uuid && !def->sku && !def->family) {
|
2022-01-28 18:42:45 +01:00
|
|
|
g_clear_pointer(&def, virSysinfoSystemDefFree);
|
2015-05-12 14:33:12 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 14:58:29 +01:00
|
|
|
*sysdef = g_steal_pointer(&def);
|
2015-05-12 14:33:12 +02:00
|
|
|
ret = 0;
|
|
|
|
virSysinfoSystemDefFree(def);
|
|
|
|
return ret;
|
2013-04-03 18:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseARMProcessor(const char *base, virSysinfoDef *ret)
|
2013-04-03 18:58:50 +01:00
|
|
|
{
|
|
|
|
const char *cur;
|
|
|
|
char *eol, *tmp_base;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoProcessorDef *processor;
|
2013-04-03 18:58:50 +01:00
|
|
|
char *processor_type = NULL;
|
|
|
|
|
2015-05-12 18:21:18 +02:00
|
|
|
if (!(tmp_base = strstr(base, "model name")) &&
|
|
|
|
!(tmp_base = strstr(base, "Processor")))
|
2013-04-03 18:58:50 +01:00
|
|
|
return 0;
|
|
|
|
|
2015-05-12 18:21:18 +02:00
|
|
|
eol = strchr(tmp_base, '\n');
|
|
|
|
cur = strchr(tmp_base, ':') + 1;
|
2013-04-03 18:58:50 +01:00
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor_type = g_strndup(cur, eol - cur);
|
2013-04-03 18:58:50 +01:00
|
|
|
|
|
|
|
while ((tmp_base = strstr(base, "processor")) != NULL) {
|
|
|
|
base = tmp_base;
|
|
|
|
eol = strchr(base, '\n');
|
|
|
|
cur = strchr(base, ':') + 1;
|
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(ret->processor, ret->nprocessor, 1);
|
2013-04-03 18:58:50 +01:00
|
|
|
processor = &ret->processor[ret->nprocessor - 1];
|
|
|
|
|
|
|
|
virSkipSpaces(&cur);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_socket_destination = g_strndup(cur,
|
|
|
|
eol - cur);
|
2013-04-03 18:58:50 +01:00
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
processor->processor_type = g_strdup(processor_type);
|
2013-04-03 18:58:50 +01:00
|
|
|
|
|
|
|
base = cur;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(processor_type);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virSysinfoRead for ARMv7
|
|
|
|
* Gathers sysinfo data from /proc/cpuinfo */
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoDef *
|
2017-03-06 15:14:45 +01:00
|
|
|
virSysinfoReadARM(void)
|
2014-03-18 09:14:35 +01:00
|
|
|
{
|
2021-03-11 06:17:07 +01:00
|
|
|
g_autoptr(virSysinfoDef) ret = NULL;
|
2019-12-20 13:43:14 +01:00
|
|
|
g_autofree char *outbuf = NULL;
|
2013-04-03 18:58:50 +01:00
|
|
|
|
2019-05-09 16:10:37 +02:00
|
|
|
/* Some ARM systems have DMI tables available. */
|
|
|
|
if ((ret = virSysinfoReadDMI())) {
|
|
|
|
if (!virSysinfoDefIsEmpty(ret))
|
2019-12-20 13:43:14 +01:00
|
|
|
return g_steal_pointer(&ret);
|
2019-05-09 16:10:37 +02:00
|
|
|
virSysinfoDefFree(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Well, we've tried. Fall back to parsing cpuinfo */
|
|
|
|
virResetLastError();
|
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
ret = g_new0(virSysinfoDef, 1);
|
2013-04-03 18:58:50 +01:00
|
|
|
|
2014-04-04 09:21:06 +08:00
|
|
|
if (virFileReadAll(CPUINFO, CPUINFO_FILE_LEN, &outbuf) < 0) {
|
2013-04-03 18:58:50 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 15:13:48 +01:00
|
|
|
_("Failed to open %1$s"), CPUINFO);
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2013-04-03 18:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ret->nprocessor = 0;
|
|
|
|
ret->processor = NULL;
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseARMProcessor(outbuf, ret) < 0)
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2013-04-03 18:58:50 +01:00
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseARMSystem(outbuf, &ret->system) < 0)
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2013-04-03 18:58:50 +01:00
|
|
|
|
2019-12-20 13:43:14 +01:00
|
|
|
return g_steal_pointer(&ret);
|
2013-04-03 18:58:50 +01:00
|
|
|
}
|
|
|
|
|
2020-01-14 10:43:37 +00:00
|
|
|
static const char *
|
2017-03-06 15:14:45 +01:00
|
|
|
virSysinfoParseS390Delimited(const char *base, const char *name, char **value,
|
|
|
|
char delim1, char delim2)
|
2012-12-14 16:08:24 +01:00
|
|
|
{
|
|
|
|
const char *start;
|
2020-01-14 10:43:37 +00:00
|
|
|
const char *end;
|
2012-12-14 16:08:24 +01:00
|
|
|
|
|
|
|
if (delim1 != delim2 &&
|
|
|
|
(start = strstr(base, name)) &&
|
|
|
|
(start = strchr(start, delim1))) {
|
|
|
|
start += 1;
|
2020-01-14 10:43:37 +00:00
|
|
|
end = strchr(start, delim2);
|
|
|
|
if (!end)
|
|
|
|
end = start + strlen(start);
|
2012-12-14 16:08:24 +01:00
|
|
|
virSkipSpaces(&start);
|
2019-10-24 19:41:34 +02:00
|
|
|
*value = g_strndup(start, end - start);
|
2012-12-14 16:08:24 +01:00
|
|
|
virTrimSpaces(*value, NULL);
|
|
|
|
return end;
|
2012-06-22 13:50:14 +02:00
|
|
|
}
|
2012-12-14 16:08:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-06-22 13:50:14 +02:00
|
|
|
|
2020-01-14 10:43:37 +00:00
|
|
|
static const char *
|
2017-03-06 15:14:45 +01:00
|
|
|
virSysinfoParseS390Line(const char *base, const char *name, char **value)
|
2012-12-14 16:08:24 +01:00
|
|
|
{
|
2017-03-06 15:14:45 +01:00
|
|
|
return virSysinfoParseS390Delimited(base, name, value, ':', '\n');
|
2012-12-14 16:08:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseS390System(const char *base, virSysinfoSystemDef **sysdef)
|
2012-12-14 16:08:24 +01:00
|
|
|
{
|
2015-05-12 14:33:12 +02:00
|
|
|
int ret = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoSystemDef *def;
|
2015-05-12 14:33:12 +02:00
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
def = g_new0(virSysinfoSystemDef, 1);
|
2015-05-12 14:33:12 +02:00
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (!virSysinfoParseS390Line(base, "Manufacturer", &def->manufacturer))
|
2015-05-12 14:33:12 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (!virSysinfoParseS390Line(base, "Type", &def->family))
|
2015-05-12 14:33:12 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (!virSysinfoParseS390Line(base, "Sequence Code", &def->serial))
|
2015-05-12 14:33:12 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!def->manufacturer && !def->product && !def->version &&
|
|
|
|
!def->serial && !def->uuid && !def->sku && !def->family) {
|
2022-01-28 18:42:45 +01:00
|
|
|
g_clear_pointer(&def, virSysinfoSystemDefFree);
|
2015-05-12 14:33:12 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 14:58:29 +01:00
|
|
|
*sysdef = g_steal_pointer(&def);
|
2015-05-12 14:33:12 +02:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virSysinfoSystemDefFree(def);
|
|
|
|
return ret;
|
2012-06-22 13:50:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseS390Processor(const char *base, virSysinfoDef *ret)
|
2012-06-22 13:50:14 +02:00
|
|
|
{
|
2020-01-14 10:43:37 +00:00
|
|
|
const char *tmp_base;
|
2012-12-14 16:08:24 +01:00
|
|
|
char *manufacturer = NULL;
|
|
|
|
char *procline = NULL;
|
2018-01-12 12:38:01 +01:00
|
|
|
char *ncpu = NULL;
|
2012-12-14 16:08:24 +01:00
|
|
|
int result = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoProcessorDef *processor;
|
2012-06-22 13:50:14 +02:00
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (!(tmp_base = virSysinfoParseS390Line(base, "vendor_id", &manufacturer)))
|
2018-01-12 12:38:01 +01:00
|
|
|
goto error;
|
2012-06-22 13:50:14 +02:00
|
|
|
|
2012-12-14 16:08:24 +01:00
|
|
|
/* Find processor N: line and gather the processor manufacturer,
|
|
|
|
version, serial number, and family */
|
|
|
|
while ((tmp_base = strstr(tmp_base, "processor "))
|
2017-03-06 15:14:45 +01:00
|
|
|
&& (tmp_base = virSysinfoParseS390Line(tmp_base, "processor ",
|
|
|
|
&procline))) {
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(ret->processor, ret->nprocessor, 1);
|
2012-06-22 13:50:14 +02:00
|
|
|
processor = &ret->processor[ret->nprocessor - 1];
|
2019-10-20 13:49:46 +02:00
|
|
|
processor->processor_manufacturer = g_strdup(manufacturer);
|
2017-03-06 15:14:45 +01:00
|
|
|
if (!virSysinfoParseS390Delimited(procline, "version",
|
|
|
|
&processor->processor_version,
|
|
|
|
'=', ',') ||
|
|
|
|
!virSysinfoParseS390Delimited(procline, "identification",
|
|
|
|
&processor->processor_serial_number,
|
|
|
|
'=', ',') ||
|
|
|
|
!virSysinfoParseS390Delimited(procline, "machine",
|
|
|
|
&processor->processor_family,
|
|
|
|
'=', '\n'))
|
2018-01-12 12:38:01 +01:00
|
|
|
goto error;
|
2017-04-09 12:49:24 +02:00
|
|
|
|
|
|
|
VIR_FREE(procline);
|
2012-06-22 13:50:14 +02:00
|
|
|
}
|
2018-01-12 12:38:01 +01:00
|
|
|
|
|
|
|
/* now, for each processor found, extract the frequency information */
|
2020-01-14 10:43:37 +00:00
|
|
|
tmp_base = base;
|
2018-01-12 12:38:01 +01:00
|
|
|
|
|
|
|
while ((tmp_base = strstr(tmp_base, "cpu number")) &&
|
|
|
|
(tmp_base = virSysinfoParseS390Line(tmp_base, "cpu number", &ncpu))) {
|
|
|
|
unsigned int n;
|
|
|
|
char *mhz = NULL;
|
|
|
|
|
|
|
|
if (virStrToLong_uip(ncpu, NULL, 10, &n) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (n >= ret->nprocessor) {
|
|
|
|
VIR_DEBUG("CPU number '%u' out of range", n);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(tmp_base = strstr(tmp_base, "cpu MHz static")) ||
|
|
|
|
!virSysinfoParseS390Line(tmp_base, "cpu MHz static", &mhz))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret->processor[n].processor_max_speed = mhz;
|
|
|
|
|
|
|
|
VIR_FREE(ncpu);
|
|
|
|
}
|
2012-06-22 13:50:14 +02:00
|
|
|
|
2014-03-25 07:53:22 +01:00
|
|
|
cleanup:
|
2018-01-12 12:38:01 +01:00
|
|
|
result = 0;
|
|
|
|
|
|
|
|
error:
|
2012-12-14 16:08:24 +01:00
|
|
|
VIR_FREE(manufacturer);
|
|
|
|
VIR_FREE(procline);
|
2018-01-12 12:38:01 +01:00
|
|
|
VIR_FREE(ncpu);
|
2012-12-14 16:08:24 +01:00
|
|
|
return result;
|
2012-06-22 13:50:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virSysinfoRead for s390x
|
|
|
|
* Gathers sysinfo data from /proc/sysinfo and /proc/cpuinfo */
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoDef *
|
2017-03-06 15:14:45 +01:00
|
|
|
virSysinfoReadS390(void)
|
2014-03-18 09:14:35 +01:00
|
|
|
{
|
2021-03-11 06:17:07 +01:00
|
|
|
g_autoptr(virSysinfoDef) ret = NULL;
|
2019-12-20 13:43:14 +01:00
|
|
|
g_autofree char *outbuf = NULL;
|
2012-06-22 13:50:14 +02:00
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
ret = g_new0(virSysinfoDef, 1);
|
2012-06-22 13:50:14 +02:00
|
|
|
|
|
|
|
/* Gather info from /proc/cpuinfo */
|
2014-04-04 09:21:06 +08:00
|
|
|
if (virFileReadAll(CPUINFO, CPUINFO_FILE_LEN, &outbuf) < 0) {
|
2012-07-18 11:26:24 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 15:13:48 +01:00
|
|
|
_("Failed to open %1$s"), CPUINFO);
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2012-06-22 13:50:14 +02:00
|
|
|
}
|
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseS390Processor(outbuf, ret) < 0)
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2012-06-22 13:50:14 +02:00
|
|
|
|
|
|
|
/* Free buffer before reading next file */
|
|
|
|
VIR_FREE(outbuf);
|
|
|
|
|
|
|
|
/* Gather info from /proc/sysinfo */
|
2012-10-05 15:59:08 +02:00
|
|
|
if (virFileReadAll(SYSINFO, 8192, &outbuf) < 0) {
|
2012-07-18 11:26:24 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 15:13:48 +01:00
|
|
|
_("Failed to open %1$s"), SYSINFO);
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2012-06-22 13:50:14 +02:00
|
|
|
}
|
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseS390System(outbuf, &ret->system) < 0)
|
2019-12-20 13:43:14 +01:00
|
|
|
return NULL;
|
2012-06-22 13:50:14 +02:00
|
|
|
|
2019-12-20 13:43:14 +01:00
|
|
|
return g_steal_pointer(&ret);
|
2012-06-22 13:50:14 +02:00
|
|
|
}
|
|
|
|
|
2011-02-07 16:16:04 -07:00
|
|
|
|
2012-02-07 15:35:03 -07:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseBIOS(const char *base, virSysinfoBIOSDef **bios)
|
2011-06-23 18:04:26 +08:00
|
|
|
{
|
2015-05-12 12:02:29 +02:00
|
|
|
int ret = -1;
|
2018-03-13 16:03:13 +01:00
|
|
|
const char *cur;
|
|
|
|
char *eol = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBIOSDef *def;
|
2010-11-05 15:22:13 +01:00
|
|
|
|
2011-06-29 13:33:22 +09:00
|
|
|
if ((cur = strstr(base, "BIOS Information")) == NULL)
|
2012-02-07 15:35:03 -07:00
|
|
|
return 0;
|
2011-06-29 13:33:22 +09:00
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
def = g_new0(virSysinfoBIOSDef, 1);
|
2015-05-12 12:02:29 +02:00
|
|
|
|
2011-06-29 13:33:22 +09:00
|
|
|
base = cur;
|
2010-11-05 15:22:13 +01:00
|
|
|
if ((cur = strstr(base, "Vendor: ")) != NULL) {
|
|
|
|
cur += 8;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->vendor = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Version: ")) != NULL) {
|
|
|
|
cur += 9;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->version = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Release Date: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->date = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "BIOS Revision: ")) != NULL) {
|
|
|
|
cur += 15;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->release = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2015-05-12 12:02:29 +02:00
|
|
|
if (!def->vendor && !def->version &&
|
|
|
|
!def->date && !def->release) {
|
2022-01-28 18:42:45 +01:00
|
|
|
g_clear_pointer(&def, virSysinfoBIOSDefFree);
|
2015-05-12 12:02:29 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 14:58:29 +01:00
|
|
|
*bios = g_steal_pointer(&def);
|
2015-05-12 12:02:29 +02:00
|
|
|
ret = 0;
|
|
|
|
virSysinfoBIOSDefFree(def);
|
|
|
|
return ret;
|
2011-06-23 18:04:26 +08:00
|
|
|
}
|
|
|
|
|
2012-02-07 15:35:03 -07:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseX86System(const char *base, virSysinfoSystemDef **sysdef)
|
2011-06-23 18:04:26 +08:00
|
|
|
{
|
2015-05-12 14:33:12 +02:00
|
|
|
int ret = -1;
|
2018-03-13 16:03:13 +01:00
|
|
|
const char *cur;
|
|
|
|
char *eol = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoSystemDef *def;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2011-06-29 13:33:22 +09:00
|
|
|
if ((cur = strstr(base, "System Information")) == NULL)
|
2012-02-07 15:35:03 -07:00
|
|
|
return 0;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
def = g_new0(virSysinfoSystemDef, 1);
|
2015-05-12 14:33:12 +02:00
|
|
|
|
2011-06-29 13:33:22 +09:00
|
|
|
base = cur;
|
2010-11-05 15:22:13 +01:00
|
|
|
if ((cur = strstr(base, "Manufacturer: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->manufacturer = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Product Name: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->product = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Version: ")) != NULL) {
|
|
|
|
cur += 9;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->version = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Serial Number: ")) != NULL) {
|
|
|
|
cur += 15;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->serial = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "UUID: ")) != NULL) {
|
|
|
|
cur += 6;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->uuid = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "SKU Number: ")) != NULL) {
|
|
|
|
cur += 12;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->sku = g_strndup(cur, eol - cur);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
2010-12-01 17:07:41 -07:00
|
|
|
if ((cur = strstr(base, "Family: ")) != NULL) {
|
|
|
|
cur += 8;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->family = g_strndup(cur, eol - cur);
|
2010-12-01 17:07:41 -07:00
|
|
|
}
|
2010-11-05 15:22:13 +01:00
|
|
|
|
2015-05-12 14:33:12 +02:00
|
|
|
if (!def->manufacturer && !def->product && !def->version &&
|
|
|
|
!def->serial && !def->uuid && !def->sku && !def->family) {
|
2022-01-28 18:42:45 +01:00
|
|
|
g_clear_pointer(&def, virSysinfoSystemDefFree);
|
2015-05-12 14:33:12 +02:00
|
|
|
}
|
|
|
|
|
2021-02-23 14:58:29 +01:00
|
|
|
*sysdef = g_steal_pointer(&def);
|
2015-05-12 14:33:12 +02:00
|
|
|
ret = 0;
|
|
|
|
virSysinfoSystemDefFree(def);
|
|
|
|
return ret;
|
2011-06-23 18:04:26 +08:00
|
|
|
}
|
|
|
|
|
2015-05-12 16:47:49 +02:00
|
|
|
static int
|
2017-03-06 15:14:45 +01:00
|
|
|
virSysinfoParseX86BaseBoard(const char *base,
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBaseBoardDef **baseBoard,
|
2017-03-06 15:14:45 +01:00
|
|
|
size_t *nbaseBoard)
|
2015-05-12 16:47:49 +02:00
|
|
|
{
|
2018-03-13 16:03:13 +01:00
|
|
|
const char *cur;
|
|
|
|
char *eol = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBaseBoardDef *boards = NULL;
|
2015-05-12 16:47:49 +02:00
|
|
|
size_t nboards = 0;
|
|
|
|
|
|
|
|
while (base && (cur = strstr(base, "Base Board Information"))) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBaseBoardDef *def;
|
2015-05-12 16:47:49 +02:00
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(boards, nboards, 1);
|
2015-05-12 16:47:49 +02:00
|
|
|
|
|
|
|
def = &boards[nboards - 1];
|
|
|
|
|
|
|
|
base = cur + 22;
|
|
|
|
if ((cur = strstr(base, "Manufacturer: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->manufacturer = g_strndup(cur, eol - cur);
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Product Name: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->product = g_strndup(cur, eol - cur);
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Version: ")) != NULL) {
|
|
|
|
cur += 9;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->version = g_strndup(cur, eol - cur);
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Serial Number: ")) != NULL) {
|
|
|
|
cur += 15;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->serial = g_strndup(cur, eol - cur);
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Asset Tag: ")) != NULL) {
|
|
|
|
cur += 11;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->asset = g_strndup(cur, eol - cur);
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Location In Chassis: ")) != NULL) {
|
|
|
|
cur += 21;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->location = g_strndup(cur, eol - cur);
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!def->manufacturer && !def->product && !def->version &&
|
|
|
|
!def->serial && !def->asset && !def->location)
|
|
|
|
nboards--;
|
|
|
|
}
|
|
|
|
|
2019-05-09 15:59:33 +02:00
|
|
|
if (nboards == 0) {
|
|
|
|
VIR_FREE(boards);
|
|
|
|
} else {
|
2021-03-20 00:37:05 +01:00
|
|
|
VIR_REALLOC_N(boards, nboards);
|
2019-05-09 15:59:33 +02:00
|
|
|
}
|
2015-05-12 16:47:49 +02:00
|
|
|
|
|
|
|
*nbaseBoard = nboards;
|
2021-02-23 14:58:29 +01:00
|
|
|
*baseBoard = g_steal_pointer(&boards);
|
2021-03-20 00:37:03 +01:00
|
|
|
return 0;
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
|
2018-02-14 17:22:38 +08:00
|
|
|
|
|
|
|
static int
|
|
|
|
virSysinfoParseX86Chassis(const char *base,
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoChassisDef **chassisdef)
|
2018-02-14 17:22:38 +08:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2018-03-13 16:03:13 +01:00
|
|
|
const char *cur;
|
|
|
|
char *eol = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoChassisDef *def;
|
2018-02-14 17:22:38 +08:00
|
|
|
|
|
|
|
if ((cur = strstr(base, "Chassis Information")) == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
def = g_new0(virSysinfoChassisDef, 1);
|
2018-02-14 17:22:38 +08:00
|
|
|
|
|
|
|
base = cur;
|
|
|
|
if ((cur = strstr(base, "Manufacturer: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->manufacturer = g_strndup(cur, eol - cur);
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Version: ")) != NULL) {
|
|
|
|
cur += 9;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->version = g_strndup(cur, eol - cur);
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Serial Number: ")) != NULL) {
|
|
|
|
cur += 15;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->serial = g_strndup(cur, eol - cur);
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Asset Tag: ")) != NULL) {
|
|
|
|
cur += 11;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->asset = g_strndup(cur, eol - cur);
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "SKU Number: ")) != NULL) {
|
|
|
|
cur += 12;
|
|
|
|
eol = strchr(cur, '\n');
|
2018-03-13 16:03:13 +01:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
def->sku = g_strndup(cur, eol - cur);
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!def->manufacturer && !def->version &&
|
|
|
|
!def->serial && !def->asset && !def->sku) {
|
2022-01-28 18:42:45 +01:00
|
|
|
g_clear_pointer(&def, virSysinfoChassisDefFree);
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
|
2021-02-23 14:58:29 +01:00
|
|
|
*chassisdef = g_steal_pointer(&def);
|
2018-02-14 17:22:38 +08:00
|
|
|
ret = 0;
|
|
|
|
virSysinfoChassisDefFree(def);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-02 10:15:38 +02:00
|
|
|
static int
|
2024-07-18 15:09:22 +02:00
|
|
|
virSysinfoDMIDecodeOEMString(unsigned int idx,
|
2020-06-02 10:15:38 +02:00
|
|
|
char **str)
|
|
|
|
{
|
|
|
|
g_autofree char *err = NULL;
|
|
|
|
g_autoptr(virCommand) cmd = virCommandNewArgList(DMIDECODE, "--dump",
|
|
|
|
"--oem-string", NULL);
|
2024-07-18 15:09:22 +02:00
|
|
|
virCommandAddArgFormat(cmd, "%u", idx);
|
2020-06-02 10:15:38 +02:00
|
|
|
virCommandSetOutputBuffer(cmd, str);
|
|
|
|
virCommandSetErrorBuffer(cmd, &err);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Unfortunately, dmidecode returns 0 even if OEM String index is out
|
|
|
|
* of bounds, but it prints an error message in that case. Check stderr
|
virsysinfo: Be more forgiving when decoding OEM strings
On some systems, there are two or even more 'OEM Strings'
sections in DMI table. Here's an example of dmidecode output on
such system:
# dmidecode -q -t 11
OEM Strings
String 1: Default string
OEM Strings
String 1: ThunderX2 System
String 2: cavium.com
String 3: Comanche
Now, this poses a problem, because when one tries to obtain
individual strings, they get:
# dmidecode -q --oem-string 1
Default string
ThunderX2 System
# dmidecode -q --oem-string 2
No OEM string number 2
cavium.com
NB, the "No OEM string number 2" is printed onto stderr and
everything else onto stdout. Oh, and trying to get OEM strings
from just one section doesn't fly:
# dmidecode -q -H 0x1d --oem-string 2
Options --string, --type, --handle and --dump-bin are mutually exclusive
This means two things:
1) we have no way of distinguishing OEM strings at the same index
but in different sections,
2) because of how virSysinfoDMIDecodeOEMString() is written, we
fail in querying OEM string that exists in one section but not
in the others (for instance string #2 from example above).
While there's not much we can do about 1), there is something
that can be done about 2) - refine the error condition and make
the function return an error iff there's nothing on stdout and
there's something on stderr.
Resolves: https://issues.redhat.com/browse/RHEL-45952
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
2024-07-18 09:39:05 +02:00
|
|
|
* and return success/failure accordingly.
|
|
|
|
* To make matters worse, if there are two or more 'OEM String'
|
|
|
|
* sections then:
|
|
|
|
*
|
|
|
|
* a) we have no way of distinguishing them as dmidecode prints
|
|
|
|
* strings from all sections,
|
|
|
|
* b) if one section contains a valid string, but the other doesn't,
|
|
|
|
* then stdout contains the valid string and stderr contains the
|
|
|
|
* error "No OEM string number X*.
|
|
|
|
*
|
|
|
|
* Let's just hope there is not many systems like that.
|
|
|
|
*/
|
|
|
|
if ((!*str || **str == '\0') && err && *err != '\0')
|
2020-06-02 10:15:38 +02:00
|
|
|
return -1;
|
|
|
|
|
2024-07-18 15:13:30 +02:00
|
|
|
virStringTrimOptionalNewline(*str);
|
|
|
|
|
2020-06-02 10:15:38 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSysinfoParseOEMStrings(const char *base,
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoOEMStringsDef **stringsRet)
|
2020-06-02 10:15:38 +02:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoOEMStringsDef *strings = NULL;
|
2020-06-02 10:15:38 +02:00
|
|
|
int ret = -1;
|
|
|
|
const char *cur;
|
|
|
|
|
|
|
|
if (!(cur = strstr(base, "OEM Strings")))
|
|
|
|
return 0;
|
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
strings = g_new0(virSysinfoOEMStringsDef, 1);
|
2020-06-02 10:15:38 +02:00
|
|
|
|
|
|
|
while ((cur = strstr(cur, "String "))) {
|
2024-07-18 15:09:22 +02:00
|
|
|
char *collon = NULL;
|
|
|
|
unsigned int idx = 0;
|
2020-06-02 10:15:38 +02:00
|
|
|
char *eol;
|
|
|
|
|
|
|
|
cur += 7;
|
|
|
|
|
|
|
|
if (!(eol = strchr(cur, '\n'))) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Malformed output of dmidecode"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2024-07-18 15:09:22 +02:00
|
|
|
if (virStrToLong_ui(cur, &collon, 10, &idx) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Malformed output of dmidecode"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = collon;
|
2020-06-02 10:15:38 +02:00
|
|
|
|
|
|
|
if (*cur != ':') {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Malformed output of dmidecode"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur += 2;
|
|
|
|
|
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
|
|
|
if (!eol)
|
|
|
|
continue;
|
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(strings->values, strings->nvalues, 1);
|
2020-06-02 10:15:38 +02:00
|
|
|
|
|
|
|
/* If OEM String contains newline, dmidecode escapes it as a dot.
|
|
|
|
* If this is the case then run dmidecode again to get raw string.
|
2020-07-09 12:42:21 +08:00
|
|
|
* Unfortunately, we can't dinstinguish between dot an new line at
|
2020-06-02 10:15:38 +02:00
|
|
|
* this level. */
|
|
|
|
if (memchr(cur, '.', eol - cur)) {
|
|
|
|
char *str;
|
|
|
|
|
2024-07-18 15:09:22 +02:00
|
|
|
if (virSysinfoDMIDecodeOEMString(idx, &str) < 0)
|
2020-06-02 10:15:38 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
strings->values[strings->nvalues - 1] = g_steal_pointer(&str);
|
|
|
|
} else {
|
|
|
|
strings->values[strings->nvalues - 1] = g_strndup(cur, eol - cur);
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = eol;
|
|
|
|
}
|
|
|
|
|
|
|
|
*stringsRet = g_steal_pointer(&strings);
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virSysinfoOEMStringsDefFree(strings);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-07 15:35:03 -07:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseX86Processor(const char *base, virSysinfoDef *ret)
|
2011-06-24 13:42:02 +08:00
|
|
|
{
|
2012-02-07 15:35:03 -07:00
|
|
|
const char *cur, *tmp_base;
|
|
|
|
char *eol;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoProcessorDef *processor;
|
2011-06-24 13:42:02 +08:00
|
|
|
|
2012-10-17 10:23:12 +01:00
|
|
|
while ((tmp_base = strstr(base, "Processor Information")) != NULL) {
|
2011-06-24 13:42:02 +08:00
|
|
|
base = tmp_base;
|
2011-06-28 11:56:08 -06:00
|
|
|
eol = NULL;
|
2011-06-24 13:42:02 +08:00
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(ret->processor, ret->nprocessor, 1);
|
2011-06-24 13:42:02 +08:00
|
|
|
processor = &ret->processor[ret->nprocessor - 1];
|
|
|
|
|
|
|
|
if ((cur = strstr(base, "Socket Designation: ")) != NULL) {
|
|
|
|
cur += 20;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_socket_destination = g_strndup(cur,
|
|
|
|
eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Type: ")) != NULL) {
|
|
|
|
cur += 6;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_type = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Family: ")) != NULL) {
|
|
|
|
cur += 8;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_family = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Manufacturer: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_manufacturer = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Signature: ")) != NULL) {
|
|
|
|
cur += 11;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_signature = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Version: ")) != NULL) {
|
|
|
|
cur += 9;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_version = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "External Clock: ")) != NULL) {
|
|
|
|
cur += 16;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_external_clock = g_strndup(cur,
|
|
|
|
eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Max Speed: ")) != NULL) {
|
|
|
|
cur += 11;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_max_speed = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Status: ")) != NULL) {
|
|
|
|
cur += 8;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_status = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Serial Number: ")) != NULL) {
|
|
|
|
cur += 15;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_serial_number = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Part Number: ")) != NULL) {
|
|
|
|
cur += 13;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
processor->processor_part_number = g_strndup(cur, eol - cur);
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
|
2011-06-29 13:33:22 +09:00
|
|
|
base += strlen("Processor Information");
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
|
2012-02-07 15:35:03 -07:00
|
|
|
return 0;
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
|
2012-02-07 15:35:03 -07:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoParseX86Memory(const char *base, virSysinfoDef *ret)
|
2011-06-24 14:05:48 +08:00
|
|
|
{
|
2012-02-07 15:35:03 -07:00
|
|
|
const char *cur, *tmp_base;
|
|
|
|
char *eol;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoMemoryDef *memory;
|
2011-06-24 14:05:48 +08:00
|
|
|
|
|
|
|
while ((tmp_base = strstr(base, "Memory Device")) != NULL) {
|
|
|
|
base = tmp_base;
|
2011-06-28 11:56:08 -06:00
|
|
|
eol = NULL;
|
2011-06-24 14:05:48 +08:00
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(ret->memory, ret->nmemory, 1);
|
2011-06-24 14:05:48 +08:00
|
|
|
memory = &ret->memory[ret->nmemory - 1];
|
|
|
|
|
|
|
|
if ((cur = strstr(base, "Size: ")) != NULL) {
|
|
|
|
cur += 6;
|
|
|
|
eol = strchr(cur, '\n');
|
|
|
|
if (STREQLEN(cur, "No Module Installed", eol - cur))
|
|
|
|
goto next;
|
|
|
|
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_size = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Form Factor: ")) != NULL) {
|
|
|
|
cur += 13;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_form_factor = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Locator: ")) != NULL) {
|
|
|
|
cur += 9;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_locator = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Bank Locator: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_bank_locator = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Type: ")) != NULL) {
|
|
|
|
cur += 6;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_type = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Type Detail: ")) != NULL) {
|
|
|
|
cur += 13;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_type_detail = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Speed: ")) != NULL) {
|
|
|
|
cur += 7;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_speed = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Manufacturer: ")) != NULL) {
|
|
|
|
cur += 14;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_manufacturer = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Serial Number: ")) != NULL) {
|
|
|
|
cur += 15;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_serial_number = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
if ((cur = strstr(base, "Part Number: ")) != NULL) {
|
|
|
|
cur += 13;
|
|
|
|
eol = strchr(cur, '\n');
|
2011-06-29 13:43:35 +09:00
|
|
|
virSkipSpacesBackwards(cur, &eol);
|
2019-10-24 19:32:35 +02:00
|
|
|
if (eol)
|
|
|
|
memory->memory_part_number = g_strndup(cur, eol - cur);
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
next:
|
2011-06-29 13:33:22 +09:00
|
|
|
base += strlen("Memory Device");
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
|
2012-02-07 15:35:03 -07:00
|
|
|
return 0;
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoDef *
|
2019-05-10 14:08:09 +02:00
|
|
|
virSysinfoReadDMI(void)
|
2014-03-18 09:14:35 +01:00
|
|
|
{
|
2021-03-11 06:17:07 +01:00
|
|
|
g_autoptr(virSysinfoDef) ret = NULL;
|
2020-06-08 10:44:19 +02:00
|
|
|
g_autofree char *outbuf = NULL;
|
|
|
|
g_autoptr(virCommand) cmd = NULL;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2020-06-02 10:15:38 +02:00
|
|
|
cmd = virCommandNewArgList(DMIDECODE, "-q", "-t", "0,1,2,3,4,11,17", NULL);
|
2011-06-23 18:04:26 +08:00
|
|
|
virCommandSetOutputBuffer(cmd, &outbuf);
|
2012-09-18 17:34:25 -06:00
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
2020-06-08 10:44:19 +02:00
|
|
|
return NULL;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2020-10-05 19:07:18 +02:00
|
|
|
ret = g_new0(virSysinfoDef, 1);
|
2011-06-23 18:04:26 +08:00
|
|
|
|
|
|
|
ret->type = VIR_SYSINFO_SMBIOS;
|
|
|
|
|
2015-05-12 12:02:29 +02:00
|
|
|
if (virSysinfoParseBIOS(outbuf, &ret->bios) < 0)
|
2020-06-08 10:44:19 +02:00
|
|
|
return NULL;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseX86System(outbuf, &ret->system) < 0)
|
2020-06-08 10:44:19 +02:00
|
|
|
return NULL;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseX86BaseBoard(outbuf, &ret->baseBoard, &ret->nbaseBoard) < 0)
|
2020-06-08 10:44:19 +02:00
|
|
|
return NULL;
|
2015-05-12 16:47:49 +02:00
|
|
|
|
2018-02-14 17:22:38 +08:00
|
|
|
if (virSysinfoParseX86Chassis(outbuf, &ret->chassis) < 0)
|
2020-06-08 10:44:19 +02:00
|
|
|
return NULL;
|
2018-02-14 17:22:38 +08:00
|
|
|
|
2020-06-02 10:15:38 +02:00
|
|
|
if (virSysinfoParseOEMStrings(outbuf, &ret->oemStrings) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2011-06-24 13:42:02 +08:00
|
|
|
ret->nprocessor = 0;
|
|
|
|
ret->processor = NULL;
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseX86Processor(outbuf, ret) < 0)
|
2020-06-08 10:44:19 +02:00
|
|
|
return NULL;
|
2011-06-24 13:42:02 +08:00
|
|
|
|
2011-06-24 14:05:48 +08:00
|
|
|
ret->nmemory = 0;
|
|
|
|
ret->memory = NULL;
|
2017-03-06 15:14:45 +01:00
|
|
|
if (virSysinfoParseX86Memory(outbuf, ret) < 0)
|
2020-06-08 10:44:19 +02:00
|
|
|
return NULL;
|
2010-11-05 15:22:13 +01:00
|
|
|
|
2020-06-08 10:44:19 +02:00
|
|
|
return g_steal_pointer(&ret);
|
2010-11-05 15:22:13 +01:00
|
|
|
}
|
2017-03-06 15:14:45 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSysinfoRead:
|
|
|
|
*
|
|
|
|
* Tries to read the SMBIOS information from the current host
|
|
|
|
*
|
|
|
|
* Returns: a filled up sysinfo structure or NULL in case of error
|
|
|
|
*/
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoDef *
|
2017-03-06 15:14:45 +01:00
|
|
|
virSysinfoRead(void)
|
|
|
|
{
|
|
|
|
#if defined(__powerpc__)
|
|
|
|
return virSysinfoReadPPC();
|
|
|
|
#elif defined(__arm__) || defined(__aarch64__)
|
|
|
|
return virSysinfoReadARM();
|
|
|
|
#elif defined(__s390__) || defined(__s390x__)
|
|
|
|
return virSysinfoReadS390();
|
2019-05-07 16:10:21 +02:00
|
|
|
#elif !defined(WIN32) && \
|
|
|
|
(defined(__x86_64__) || \
|
|
|
|
defined(__i386__) || \
|
2024-03-21 11:30:28 +08:00
|
|
|
defined(__amd64__) || \
|
2024-03-26 14:38:50 -05:00
|
|
|
defined(__riscv__) || \
|
|
|
|
defined(__mips__) || \
|
2024-03-21 11:30:28 +08:00
|
|
|
defined(__loongarch__))
|
2019-05-10 14:08:09 +02:00
|
|
|
return virSysinfoReadDMI();
|
2019-05-07 16:10:21 +02:00
|
|
|
#else /* WIN32 || not supported arch */
|
2017-03-06 15:14:45 +01:00
|
|
|
/*
|
|
|
|
* this can probably be extracted from Windows using API or registry
|
2020-08-26 00:44:00 +02:00
|
|
|
* https://www.microsoft.com/whdc/system/platform/firmware/SMBIOS.mspx
|
2017-03-06 15:14:45 +01:00
|
|
|
*/
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("Host sysinfo extraction not supported on this platform"));
|
|
|
|
return NULL;
|
2019-05-07 16:10:21 +02:00
|
|
|
#endif /* WIN32 || not supported arch */
|
2017-03-06 15:14:45 +01:00
|
|
|
}
|
|
|
|
|
2011-02-07 16:16:04 -07:00
|
|
|
|
2011-06-23 18:04:26 +08:00
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBIOSFormat(virBuffer *buf, virSysinfoBIOSDef *def)
|
2011-02-07 16:16:04 -07:00
|
|
|
{
|
2015-05-12 12:02:29 +02:00
|
|
|
if (!def)
|
2011-09-21 17:28:01 -06:00
|
|
|
return;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAddLit(buf, "<bios>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
virBufferEscapeString(buf, "<entry name='vendor'>%s</entry>\n",
|
2015-05-12 12:02:29 +02:00
|
|
|
def->vendor);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n",
|
2015-05-12 12:02:29 +02:00
|
|
|
def->version);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='date'>%s</entry>\n",
|
2015-05-12 12:02:29 +02:00
|
|
|
def->date);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='release'>%s</entry>\n",
|
2015-05-12 12:02:29 +02:00
|
|
|
def->release);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</bios>\n");
|
2011-06-23 18:04:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoSystemFormat(virBuffer *buf, virSysinfoSystemDef *def)
|
2011-06-23 18:04:26 +08:00
|
|
|
{
|
2015-05-12 14:33:12 +02:00
|
|
|
if (!def)
|
2011-09-21 17:28:01 -06:00
|
|
|
return;
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAddLit(buf, "<system>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n",
|
2015-05-12 14:33:12 +02:00
|
|
|
def->manufacturer);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='product'>%s</entry>\n",
|
2015-05-12 14:33:12 +02:00
|
|
|
def->product);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n",
|
2015-05-12 14:33:12 +02:00
|
|
|
def->version);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='serial'>%s</entry>\n",
|
2015-05-12 14:33:12 +02:00
|
|
|
def->serial);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='uuid'>%s</entry>\n",
|
2015-05-12 14:33:12 +02:00
|
|
|
def->uuid);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='sku'>%s</entry>\n",
|
2015-05-12 14:33:12 +02:00
|
|
|
def->sku);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='family'>%s</entry>\n",
|
2015-05-12 14:33:12 +02:00
|
|
|
def->family);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</system>\n");
|
2011-06-23 18:04:26 +08:00
|
|
|
}
|
|
|
|
|
2015-05-12 16:47:49 +02:00
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBaseBoardFormat(virBuffer *buf,
|
|
|
|
virSysinfoBaseBoardDef *baseBoard,
|
2015-05-12 16:47:49 +02:00
|
|
|
size_t nbaseBoard)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBaseBoardDef *def;
|
2015-05-12 16:47:49 +02:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < nbaseBoard; i++) {
|
|
|
|
def = baseBoard + i;
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "<baseBoard>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n",
|
|
|
|
def->manufacturer);
|
|
|
|
virBufferEscapeString(buf, "<entry name='product'>%s</entry>\n",
|
|
|
|
def->product);
|
|
|
|
virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n",
|
|
|
|
def->version);
|
|
|
|
virBufferEscapeString(buf, "<entry name='serial'>%s</entry>\n",
|
|
|
|
def->serial);
|
|
|
|
virBufferEscapeString(buf, "<entry name='asset'>%s</entry>\n",
|
|
|
|
def->asset);
|
|
|
|
virBufferEscapeString(buf, "<entry name='location'>%s</entry>\n",
|
|
|
|
def->location);
|
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</baseBoard>\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-14 17:22:38 +08:00
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoChassisFormat(virBuffer *buf,
|
|
|
|
virSysinfoChassisDef *def)
|
2018-02-14 17:22:38 +08:00
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "<chassis>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n",
|
|
|
|
def->manufacturer);
|
|
|
|
virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n",
|
|
|
|
def->version);
|
|
|
|
virBufferEscapeString(buf, "<entry name='serial'>%s</entry>\n",
|
|
|
|
def->serial);
|
|
|
|
virBufferEscapeString(buf, "<entry name='asset'>%s</entry>\n",
|
|
|
|
def->asset);
|
|
|
|
virBufferEscapeString(buf, "<entry name='sku'>%s</entry>\n",
|
|
|
|
def->sku);
|
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</chassis>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-24 13:42:02 +08:00
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoProcessorFormat(virBuffer *buf, virSysinfoDef *def)
|
2011-06-24 13:42:02 +08:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 15:09:33 +01:00
|
|
|
size_t i;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoProcessorDef *processor;
|
2011-06-24 13:42:02 +08:00
|
|
|
|
|
|
|
for (i = 0; i < def->nprocessor; i++) {
|
|
|
|
processor = &def->processor[i];
|
|
|
|
|
2011-09-21 17:28:01 -06:00
|
|
|
if (!processor->processor_socket_destination &&
|
|
|
|
!processor->processor_type &&
|
|
|
|
!processor->processor_family &&
|
|
|
|
!processor->processor_manufacturer &&
|
|
|
|
!processor->processor_signature &&
|
|
|
|
!processor->processor_version &&
|
|
|
|
!processor->processor_external_clock &&
|
|
|
|
!processor->processor_max_speed &&
|
|
|
|
!processor->processor_status &&
|
|
|
|
!processor->processor_serial_number &&
|
|
|
|
!processor->processor_part_number)
|
|
|
|
continue;
|
|
|
|
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAddLit(buf, "<processor>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
2011-09-21 17:28:01 -06:00
|
|
|
virBufferEscapeString(buf,
|
|
|
|
"<entry name='socket_destination'>%s</entry>\n",
|
|
|
|
processor->processor_socket_destination);
|
|
|
|
virBufferEscapeString(buf, "<entry name='type'>%s</entry>\n",
|
|
|
|
processor->processor_type);
|
|
|
|
virBufferEscapeString(buf, "<entry name='family'>%s</entry>\n",
|
|
|
|
processor->processor_family);
|
|
|
|
virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n",
|
|
|
|
processor->processor_manufacturer);
|
|
|
|
virBufferEscapeString(buf, "<entry name='signature'>%s</entry>\n",
|
|
|
|
processor->processor_signature);
|
|
|
|
virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n",
|
|
|
|
processor->processor_version);
|
|
|
|
virBufferEscapeString(buf, "<entry name='external_clock'>%s</entry>\n",
|
|
|
|
processor->processor_external_clock);
|
|
|
|
virBufferEscapeString(buf, "<entry name='max_speed'>%s</entry>\n",
|
|
|
|
processor->processor_max_speed);
|
|
|
|
virBufferEscapeString(buf, "<entry name='status'>%s</entry>\n",
|
|
|
|
processor->processor_status);
|
|
|
|
virBufferEscapeString(buf, "<entry name='serial_number'>%s</entry>\n",
|
|
|
|
processor->processor_serial_number);
|
|
|
|
virBufferEscapeString(buf, "<entry name='part_number'>%s</entry>\n",
|
|
|
|
processor->processor_part_number);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</processor>\n");
|
2011-06-24 13:42:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-24 14:05:48 +08:00
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoMemoryFormat(virBuffer *buf, virSysinfoDef *def)
|
2011-06-24 14:05:48 +08:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 15:09:33 +01:00
|
|
|
size_t i;
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoMemoryDef *memory;
|
2011-06-24 14:05:48 +08:00
|
|
|
|
|
|
|
for (i = 0; i < def->nmemory; i++) {
|
|
|
|
memory = &def->memory[i];
|
|
|
|
|
2011-09-21 17:28:01 -06:00
|
|
|
if (!memory->memory_size &&
|
|
|
|
!memory->memory_form_factor &&
|
|
|
|
!memory->memory_locator &&
|
|
|
|
!memory->memory_bank_locator &&
|
|
|
|
!memory->memory_type &&
|
|
|
|
!memory->memory_type_detail &&
|
|
|
|
!memory->memory_speed &&
|
|
|
|
!memory->memory_manufacturer &&
|
|
|
|
!memory->memory_serial_number &&
|
|
|
|
!memory->memory_part_number)
|
|
|
|
continue;
|
|
|
|
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAddLit(buf, "<memory_device>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
virBufferEscapeString(buf, "<entry name='size'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_size);
|
|
|
|
virBufferEscapeString(buf,
|
2014-03-12 18:03:03 -06:00
|
|
|
"<entry name='form_factor'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_form_factor);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='locator'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_locator);
|
|
|
|
virBufferEscapeString(buf,
|
2014-03-12 18:03:03 -06:00
|
|
|
"<entry name='bank_locator'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_bank_locator);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='type'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_type);
|
|
|
|
virBufferEscapeString(buf,
|
2014-03-12 18:03:03 -06:00
|
|
|
"<entry name='type_detail'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_type_detail);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferEscapeString(buf, "<entry name='speed'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_speed);
|
|
|
|
virBufferEscapeString(buf,
|
2014-03-12 18:03:03 -06:00
|
|
|
"<entry name='manufacturer'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_manufacturer);
|
|
|
|
virBufferEscapeString(buf,
|
2014-03-12 18:03:03 -06:00
|
|
|
"<entry name='serial_number'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_serial_number);
|
|
|
|
virBufferEscapeString(buf,
|
2014-03-12 18:03:03 -06:00
|
|
|
"<entry name='part_number'>%s</entry>\n",
|
2011-09-21 17:28:01 -06:00
|
|
|
memory->memory_part_number);
|
2014-03-12 18:03:03 -06:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</memory_device>\n");
|
2011-06-24 14:05:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-28 14:56:51 +01:00
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoOEMStringsFormat(virBuffer *buf, virSysinfoOEMStringsDef *def)
|
2017-10-28 14:56:51 +01:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "<oemStrings>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
for (i = 0; i < def->nvalues; i++) {
|
|
|
|
virBufferEscapeString(buf, "<entry>%s</entry>\n",
|
|
|
|
def->values[i]);
|
|
|
|
}
|
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</oemStrings>\n");
|
|
|
|
}
|
|
|
|
|
2020-06-04 14:15:40 +02:00
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoFormatSMBIOS(virBuffer *buf,
|
|
|
|
virSysinfoDef *def)
|
2020-06-04 14:15:40 +02:00
|
|
|
{
|
|
|
|
virSysinfoBIOSFormat(buf, def->bios);
|
|
|
|
virSysinfoSystemFormat(buf, def->system);
|
|
|
|
virSysinfoBaseBoardFormat(buf, def->baseBoard, def->nbaseBoard);
|
|
|
|
virSysinfoChassisFormat(buf, def->chassis);
|
|
|
|
virSysinfoProcessorFormat(buf, def);
|
|
|
|
virSysinfoMemoryFormat(buf, def);
|
|
|
|
virSysinfoOEMStringsFormat(buf, def->oemStrings);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoFormatFWCfg(virBuffer *buf,
|
|
|
|
virSysinfoDef *def)
|
2020-06-04 14:15:40 +02:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < def->nfw_cfgs; i++) {
|
|
|
|
const virSysinfoFWCfgDef *f = &def->fw_cfgs[i];
|
|
|
|
|
|
|
|
virBufferAsprintf(buf, "<entry name='%s'", f->name);
|
|
|
|
|
|
|
|
if (f->file)
|
|
|
|
virBufferEscapeString(buf, " file='%s'/>\n", f->file);
|
|
|
|
else
|
|
|
|
virBufferEscapeString(buf, ">%s</entry>\n", f->value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-23 18:04:26 +08:00
|
|
|
/**
|
|
|
|
* virSysinfoFormat:
|
2011-09-21 17:28:01 -06:00
|
|
|
* @buf: buffer to append output to (may use auto-indentation)
|
2011-06-23 18:04:26 +08:00
|
|
|
* @def: structure to convert to xml string
|
|
|
|
*
|
2011-09-21 17:28:01 -06:00
|
|
|
* Returns 0 on success, -1 on failure after generating an error message.
|
2011-06-23 18:04:26 +08:00
|
|
|
*/
|
2011-09-21 17:28:01 -06:00
|
|
|
int
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoFormat(virBuffer *buf, virSysinfoDef *def)
|
2011-06-23 18:04:26 +08:00
|
|
|
{
|
2020-07-02 22:30:20 -04:00
|
|
|
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
|
|
|
|
g_auto(virBuffer) childrenBuf = VIR_BUFFER_INIT_CHILD(buf);
|
2011-06-23 18:04:26 +08:00
|
|
|
const char *type = virSysinfoTypeToString(def->type);
|
|
|
|
|
|
|
|
if (!type) {
|
2012-07-18 11:26:24 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 15:13:48 +01:00
|
|
|
_("unexpected sysinfo type model %1$d"),
|
2012-07-18 11:26:24 +01:00
|
|
|
def->type);
|
2019-10-24 12:44:01 +02:00
|
|
|
return -1;
|
2011-02-07 16:16:04 -07:00
|
|
|
}
|
|
|
|
|
2020-06-04 14:15:40 +02:00
|
|
|
switch (def->type) {
|
|
|
|
case VIR_SYSINFO_SMBIOS:
|
|
|
|
virSysinfoFormatSMBIOS(&childrenBuf, def);
|
|
|
|
break;
|
|
|
|
case VIR_SYSINFO_FWCFG:
|
|
|
|
virSysinfoFormatFWCfg(&childrenBuf, def);
|
|
|
|
break;
|
|
|
|
case VIR_SYSINFO_LAST:
|
|
|
|
break;
|
|
|
|
}
|
2011-06-23 18:04:26 +08:00
|
|
|
|
2019-10-24 12:44:01 +02:00
|
|
|
virBufferAsprintf(&attrBuf, " type='%s'", type);
|
|
|
|
|
2019-10-24 15:50:50 +02:00
|
|
|
virXMLFormatElement(buf, "sysinfo", &attrBuf, &childrenBuf);
|
2011-02-07 16:16:04 -07:00
|
|
|
|
2019-10-24 12:44:01 +02:00
|
|
|
return 0;
|
2011-02-07 16:16:04 -07:00
|
|
|
}
|
|
|
|
|
2017-11-03 13:09:47 +01:00
|
|
|
#define CHECK_FIELD(name, desc) \
|
|
|
|
do { \
|
|
|
|
if (STRNEQ_NULLABLE(src->name, dst->name)) { \
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
|
2023-03-09 15:13:48 +01:00
|
|
|
_("Target sysinfo %1$s %2$s does not match source %3$s"), \
|
2015-05-12 12:02:29 +02:00
|
|
|
desc, NULLSTR(dst->name), NULLSTR(src->name)); \
|
2020-01-06 18:57:45 -03:00
|
|
|
return false; \
|
2017-11-03 13:09:47 +01:00
|
|
|
} \
|
2015-05-12 12:02:29 +02:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static bool
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBIOSIsEqual(virSysinfoBIOSDef *src,
|
|
|
|
virSysinfoBIOSDef *dst)
|
2015-05-12 12:02:29 +02:00
|
|
|
{
|
|
|
|
if (!src && !dst)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ((src && !dst) || (!src && dst)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Target sysinfo does not match source"));
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2015-05-12 12:02:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_FIELD(vendor, "BIOS vendor");
|
|
|
|
CHECK_FIELD(version, "BIOS version");
|
|
|
|
CHECK_FIELD(date, "BIOS date");
|
|
|
|
CHECK_FIELD(release, "BIOS release");
|
|
|
|
|
2020-01-06 18:57:45 -03:00
|
|
|
return true;
|
2015-05-12 12:02:29 +02:00
|
|
|
}
|
|
|
|
|
2015-05-12 14:33:12 +02:00
|
|
|
static bool
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoSystemIsEqual(virSysinfoSystemDef *src,
|
|
|
|
virSysinfoSystemDef *dst)
|
2015-05-12 14:33:12 +02:00
|
|
|
{
|
|
|
|
if (!src && !dst)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ((src && !dst) || (!src && dst)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Target sysinfo does not match source"));
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2015-05-12 14:33:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_FIELD(manufacturer, "system vendor");
|
|
|
|
CHECK_FIELD(product, "system product");
|
|
|
|
CHECK_FIELD(version, "system version");
|
|
|
|
CHECK_FIELD(serial, "system serial");
|
|
|
|
CHECK_FIELD(uuid, "system uuid");
|
|
|
|
CHECK_FIELD(sku, "system sku");
|
|
|
|
CHECK_FIELD(family, "system family");
|
|
|
|
|
2020-01-06 18:57:45 -03:00
|
|
|
return true;
|
2015-05-12 14:33:12 +02:00
|
|
|
}
|
|
|
|
|
2015-05-12 16:47:49 +02:00
|
|
|
static bool
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoBaseBoardIsEqual(virSysinfoBaseBoardDef *src,
|
|
|
|
virSysinfoBaseBoardDef *dst)
|
2015-05-12 16:47:49 +02:00
|
|
|
{
|
|
|
|
if (!src && !dst)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ((src && !dst) || (!src && dst)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Target base board does not match source"));
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_FIELD(manufacturer, "base board vendor");
|
|
|
|
CHECK_FIELD(product, "base board product");
|
|
|
|
CHECK_FIELD(version, "base board version");
|
|
|
|
CHECK_FIELD(serial, "base board serial");
|
|
|
|
CHECK_FIELD(asset, "base board asset");
|
|
|
|
CHECK_FIELD(location, "base board location");
|
|
|
|
|
2020-01-06 18:57:45 -03:00
|
|
|
return true;
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
|
2018-02-14 17:22:38 +08:00
|
|
|
|
|
|
|
static bool
|
2021-03-11 08:16:13 +01:00
|
|
|
virSysinfoChassisIsEqual(virSysinfoChassisDef *src,
|
|
|
|
virSysinfoChassisDef *dst)
|
2018-02-14 17:22:38 +08:00
|
|
|
{
|
|
|
|
if (!src && !dst)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ((src && !dst) || (!src && dst)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Target chassis does not match source"));
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_FIELD(manufacturer, "chassis vendor");
|
|
|
|
CHECK_FIELD(version, "chassis version");
|
|
|
|
CHECK_FIELD(serial, "chassis serial");
|
|
|
|
CHECK_FIELD(asset, "chassis asset");
|
|
|
|
CHECK_FIELD(sku, "chassis sku");
|
|
|
|
|
2020-01-06 18:57:45 -03:00
|
|
|
return true;
|
2018-02-14 17:22:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-12 14:33:12 +02:00
|
|
|
#undef CHECK_FIELD
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
bool virSysinfoIsEqual(virSysinfoDef *src,
|
|
|
|
virSysinfoDef *dst)
|
2011-05-27 10:47:30 +01:00
|
|
|
{
|
2015-05-12 16:47:49 +02:00
|
|
|
size_t i;
|
2011-05-27 10:47:30 +01:00
|
|
|
|
|
|
|
if (!src && !dst)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ((src && !dst) || (!src && dst)) {
|
2012-07-18 11:26:24 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Target sysinfo does not match source"));
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2011-05-27 10:47:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (src->type != dst->type) {
|
2012-07-18 11:26:24 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 15:13:48 +01:00
|
|
|
_("Target sysinfo %1$s does not match source %2$s"),
|
2012-07-18 11:26:24 +01:00
|
|
|
virSysinfoTypeToString(dst->type),
|
|
|
|
virSysinfoTypeToString(src->type));
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2011-05-27 10:47:30 +01:00
|
|
|
}
|
|
|
|
|
2015-05-12 12:02:29 +02:00
|
|
|
if (!virSysinfoBIOSIsEqual(src->bios, dst->bios))
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2011-05-27 10:47:30 +01:00
|
|
|
|
2015-05-12 14:33:12 +02:00
|
|
|
if (!virSysinfoSystemIsEqual(src->system, dst->system))
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2011-05-27 10:47:30 +01:00
|
|
|
|
2015-05-12 16:47:49 +02:00
|
|
|
if (src->nbaseBoard != dst->nbaseBoard) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2023-03-09 15:13:48 +01:00
|
|
|
_("Target sysinfo base board count '%1$zu' does not match source '%2$zu'"),
|
2015-05-12 16:47:49 +02:00
|
|
|
dst->nbaseBoard, src->nbaseBoard);
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2015-05-12 16:47:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < src->nbaseBoard; i++)
|
|
|
|
if (!virSysinfoBaseBoardIsEqual(src->baseBoard + i,
|
|
|
|
dst->baseBoard + i))
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2015-05-12 16:47:49 +02:00
|
|
|
|
2018-02-14 17:22:38 +08:00
|
|
|
if (!virSysinfoChassisIsEqual(src->chassis, dst->chassis))
|
2020-01-06 18:57:45 -03:00
|
|
|
return false;
|
2018-02-14 17:22:38 +08:00
|
|
|
|
2020-01-06 18:57:45 -03:00
|
|
|
return true;
|
2011-05-27 10:47:30 +01:00
|
|
|
}
|