summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPeter Schiffer <pschiffe@redhat.com>2013-03-06 13:16:25 +0100
committerPeter Schiffer <pschiffe@redhat.com>2013-03-06 13:16:25 +0100
commit7a0b251bcd55a26679bb99480f02948105947d05 (patch)
tree5b836c12b12ff900d1a069d44306b09189cb70c7 /src
parent72f6010fc7dd68ea2ecd9431f906d077a7c20181 (diff)
downloadopenlmi-providers-7a0b251bcd55a26679bb99480f02948105947d05.tar.gz
openlmi-providers-7a0b251bcd55a26679bb99480f02948105947d05.tar.xz
openlmi-providers-7a0b251bcd55a26679bb99480f02948105947d05.zip
Created LMI_ProcessorProvider providing basic information about CPU. Main source
of information is dmidecode program, with additional information from lscpu program and /proc/cpuinfo file. If no output from dmidecode program is available, fallback with only lscpu and /proc/cpuinfo is used.
Diffstat (limited to 'src')
-rw-r--r--src/hardware/CMakeLists.txt11
-rw-r--r--src/hardware/LMI_ProcessorProvider.c1153
-rw-r--r--src/hardware/cpuinfo.c145
-rw-r--r--src/hardware/cpuinfo.h54
-rw-r--r--src/hardware/dmidecode.c343
-rw-r--r--src/hardware/dmidecode.h66
-rw-r--r--src/hardware/lscpu.c151
-rw-r--r--src/hardware/lscpu.h55
-rw-r--r--src/hardware/utils.c382
-rw-r--r--src/hardware/utils.h111
10 files changed, 2467 insertions, 4 deletions
diff --git a/src/hardware/CMakeLists.txt b/src/hardware/CMakeLists.txt
index 27e8df2..ebf79fb 100644
--- a/src/hardware/CMakeLists.txt
+++ b/src/hardware/CMakeLists.txt
@@ -1,11 +1,14 @@
-
set(PROVIDER_NAME Hardware)
set(LIBRARY_NAME cmpiLMI_${PROVIDER_NAME})
set(MOF LMI_Hardware.mof)
-#set(provider_SRCS
-# util/serviceutil.c
-#)
+set(provider_SRCS
+ utils.c
+ dmidecode.c
+ lscpu.c
+ cpuinfo.c
+ LMI_ProcessorProvider.c
+)
konkretcmpi_generate(${MOF}
CIM_PROVIDERS
diff --git a/src/hardware/LMI_ProcessorProvider.c b/src/hardware/LMI_ProcessorProvider.c
new file mode 100644
index 0000000..8e92fdd
--- /dev/null
+++ b/src/hardware/LMI_ProcessorProvider.c
@@ -0,0 +1,1153 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include <konkret/konkret.h>
+#include <sys/utsname.h>
+#include <string.h>
+#include "LMI_Processor.h"
+#include "globals.h"
+#include "dmidecode.h"
+#include "lscpu.h"
+#include "cpuinfo.h"
+
+CMPIUint16 get_family(const char *family);
+CMPIUint16 get_cpustatus(const char *status);
+CMPIUint16 get_enabledstate(const CMPIUint16 status);
+CMPIUint16 get_upgrade_method(const char *dmi_upgrade);
+CMPIUint16 get_characteristic(const char *dmi_charact);
+CMPIUint16 get_flag(const char *flag, short *stat);
+
+static const CMPIBroker* _cb = NULL;
+
+static void LMI_ProcessorInitialize()
+{
+}
+
+static CMPIStatus LMI_ProcessorCleanup(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ProcessorEnumInstanceNames(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ return KDefaultEnumerateInstanceNames(
+ _cb, mi, cc, cr, cop);
+}
+
+static CMPIStatus LMI_ProcessorEnumInstances(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ LMI_Processor lmi_cpu;
+ const char *ns = KNameSpace(cop);
+ CMPICount count;
+ CMPIUint16 cpustatus, enabledstate, family, charact, enabled_cores;
+ CMPIUint32 current_speed = 0, max_speed = 0, external_clock = 0;
+ unsigned i, j, cpus_nb = 0;
+ char *other_family = NULL, *architecture = NULL, *cpu_id = NULL,
+ *cpu_name = NULL, *stepping = NULL, *error_msg = NULL;
+ struct utsname utsname_buf;
+ DmiProcessor *dmi_cpus;
+ unsigned dmi_cpus_nb;
+ LscpuProcessor lscpu;
+ CpuinfoProcessor proc_cpu;
+
+ if (dmi_get_processors(&dmi_cpus, &dmi_cpus_nb) != 0 || dmi_cpus_nb < 1) {
+ dmi_free_processors(&dmi_cpus, &dmi_cpus_nb);
+ }
+
+ if (lscpu_get_processor(&lscpu) != 0) {
+ error_msg = "Unable to get processor information.";
+ goto done;
+ }
+
+ if (cpuinfo_get_processor(&proc_cpu) != 0) {
+ error_msg = "Unable to get processor information.";
+ goto done;
+ }
+
+ if (uname(&utsname_buf) == 0) {
+ architecture = strdup(utsname_buf.machine);
+ if (!architecture) {
+ error_msg = "Not enough available memory.";
+ goto done;
+ }
+ }
+
+ if (dmi_cpus_nb > 0) {
+ cpus_nb = dmi_cpus_nb;
+ } else if (lscpu.processors > 0) {
+ cpus_nb = lscpu.processors;
+ } else {
+ error_msg = "Unable to get processor information.";
+ goto done;
+ }
+
+ for (i = 0; i < cpus_nb; i++) {
+ LMI_Processor_Init(&lmi_cpu, _cb, ns);
+
+ LMI_Processor_Set_SystemCreationClassName(&lmi_cpu,
+ get_system_creation_class_name());
+ LMI_Processor_Set_SystemName(&lmi_cpu, get_system_name());
+ LMI_Processor_Set_CreationClassName(&lmi_cpu, "LMI_Processor");
+ LMI_Processor_Set_Caption(&lmi_cpu, "Processor");
+ LMI_Processor_Set_Description(&lmi_cpu,
+ "This object represents one processor in system.");
+
+ /* do we have output from dmidecode program? */
+ if (dmi_cpus_nb > 0) {
+ family = get_family(dmi_cpus[i].family);
+ if (family == 1) {
+ other_family = dmi_cpus[i].family;
+ }
+ cpustatus = get_cpustatus(dmi_cpus[i].status);
+ enabledstate = get_enabledstate(cpustatus);
+ if (enabledstate == 2) {
+ current_speed = dmi_cpus[i].current_speed;
+ max_speed = dmi_cpus[i].max_speed;
+ external_clock = dmi_cpus[i].external_clock;
+ }
+ cpu_name = dmi_cpus[i].name;
+ enabled_cores = dmi_cpus[i].enabled_cores;
+ stepping = dmi_cpus[i].stepping;
+
+ LMI_Processor_Set_DeviceID(&lmi_cpu, dmi_cpus[i].id);
+ LMI_Processor_Set_Family(&lmi_cpu, family);
+ LMI_Processor_Set_OtherFamilyDescription(&lmi_cpu, other_family);
+ LMI_Processor_Set_UpgradeMethod(&lmi_cpu,
+ get_upgrade_method(dmi_cpus[i].upgrade));
+ if (dmi_cpus[i].type && strlen(dmi_cpus[i].type)) {
+ LMI_Processor_Set_Role(&lmi_cpu, dmi_cpus[i].type);
+ }
+ /* CPU Characteristics */
+ if (dmi_cpus[i].charact_nb > 0) {
+ count = 0;
+ LMI_Processor_Init_Characteristics(&lmi_cpu,
+ dmi_cpus[i].charact_nb);
+ LMI_Processor_Init_EnabledProcessorCharacteristics(&lmi_cpu,
+ dmi_cpus[i].charact_nb);
+ for (j = 0; j < dmi_cpus[i].charact_nb; j++) {
+ charact = get_characteristic(
+ dmi_cpus[i].characteristics[j]);
+ if (charact) {
+ LMI_Processor_Set_Characteristics(&lmi_cpu, count,
+ charact);
+ LMI_Processor_Set_EnabledProcessorCharacteristics(
+ &lmi_cpu, count, 0);
+ count++;
+ }
+ }
+ }
+ } else {
+ cpu_id = (char *)malloc(10 * sizeof(char));
+ if (!cpu_id) {
+ error_msg = "Not enough available memory.";
+ goto done;
+ }
+ snprintf(cpu_id, 10, "%u", i);
+ LMI_Processor_Set_DeviceID(&lmi_cpu, cpu_id);
+ free(cpu_id);
+ cpu_id = NULL;
+
+ cpustatus = get_cpustatus("Enabled");
+ enabledstate = get_enabledstate(cpustatus);
+ if (enabledstate == 2) {
+ current_speed = lscpu.current_speed;
+ }
+
+ cpu_name = proc_cpu.model_name;
+ enabled_cores = lscpu.cores;
+ stepping = lscpu.stepping;
+ }
+
+ LMI_Processor_Set_CPUStatus(&lmi_cpu, cpustatus);
+ LMI_Processor_Set_EnabledState(&lmi_cpu, enabledstate);
+ LMI_Processor_Set_NumberOfEnabledCores(&lmi_cpu, enabled_cores);
+ if (current_speed) {
+ LMI_Processor_Set_CurrentClockSpeed(&lmi_cpu, current_speed);
+ }
+ if (max_speed) {
+ LMI_Processor_Set_MaxClockSpeed(&lmi_cpu, max_speed);
+ }
+ if (external_clock) {
+ LMI_Processor_Set_ExternalBusClockSpeed(&lmi_cpu, external_clock);
+ }
+ if (cpu_name && strlen(cpu_name)) {
+ LMI_Processor_Set_Name(&lmi_cpu, cpu_name);
+ LMI_Processor_Set_UniqueID(&lmi_cpu, cpu_name);
+ LMI_Processor_Set_ElementName(&lmi_cpu, cpu_name);
+ }
+ if (stepping && strlen(stepping)) {
+ LMI_Processor_Set_Stepping(&lmi_cpu, stepping);
+ }
+ if (lscpu.data_width) {
+ LMI_Processor_Set_DataWidth(&lmi_cpu, lscpu.data_width);
+ }
+ /* CPU Flags */
+ if (proc_cpu.flags_nb > 0) {
+ short stat = -1;
+ CMPIUint16 flag;
+ LMI_Processor_Init_Flags(&lmi_cpu, proc_cpu.flags_nb);
+ count = 0;
+ for (j = 0; j < proc_cpu.flags_nb; j++) {
+ flag = get_flag(proc_cpu.flags[j], &stat);
+ if (stat == 0) {
+ LMI_Processor_Set_Flags(&lmi_cpu, count, flag);
+ count++;
+ }
+ }
+ }
+ if (proc_cpu.address_size) {
+ LMI_Processor_Set_AddressWidth(&lmi_cpu, proc_cpu.address_size);
+ }
+ if (architecture && strlen(architecture)) {
+ LMI_Processor_Set_Architecture(&lmi_cpu, architecture);
+ }
+
+ KReturnInstance(cr, lmi_cpu);
+ }
+
+done:
+ if (architecture) {
+ free(architecture);
+ }
+ architecture = NULL;
+
+ dmi_free_processors(&dmi_cpus, &dmi_cpus_nb);
+ lscpu_free_processor(&lscpu);
+ cpuinfo_free_processor(&proc_cpu);
+
+ if (error_msg) {
+ KReturn2(_cb, ERR_FAILED, error_msg);
+ }
+
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ProcessorGetInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ return KDefaultGetInstance(
+ _cb, mi, cc, cr, cop, properties);
+}
+
+static CMPIStatus LMI_ProcessorCreateInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_ProcessorModifyInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci,
+ const char** properties)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_ProcessorDeleteInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_ProcessorExecQuery(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* lang,
+ const char* query)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+CMInstanceMIStub(
+ LMI_Processor,
+ LMI_Processor,
+ _cb,
+ LMI_ProcessorInitialize())
+
+static CMPIStatus LMI_ProcessorMethodCleanup(
+ CMPIMethodMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ProcessorInvokeMethod(
+ CMPIMethodMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* meth,
+ const CMPIArgs* in,
+ CMPIArgs* out)
+{
+ return LMI_Processor_DispatchMethod(
+ _cb, mi, cc, cr, cop, meth, in, out);
+}
+
+CMMethodMIStub(
+ LMI_Processor,
+ LMI_Processor,
+ _cb,
+ LMI_ProcessorInitialize())
+
+KUint32 LMI_Processor_RequestStateChange(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ const KUint16* RequestedState,
+ KRef* Job,
+ const KDateTime* TimeoutPeriod,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_Processor_SetPowerState(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ const KUint16* PowerState,
+ const KDateTime* Time,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_Processor_Reset(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_Processor_EnableDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ const KBoolean* Enabled,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_Processor_OnlineDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ const KBoolean* Online,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_Processor_QuiesceDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ const KBoolean* Quiesce,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_Processor_SaveProperties(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_Processor_RestoreProperties(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_ProcessorRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+/*
+ * Get CPU status according to the dmidecode.
+ * @param status from dmidecode
+ * @return CIM id of CPU status
+ */
+CMPIUint16 get_cpustatus(const char *status)
+{
+ if (!status) {
+ return 0; /* Unknown */
+ }
+
+ static struct {
+ CMPIUint16 val; /* CIM value */
+ char *stat; /* dmidecode status */
+ } statuses[] = {
+ {0, "Unknown"},
+ {1, "Enabled"},
+ {2, "Disabled By User"},
+ {3, "Disabled By BIOS"},
+ {4, "Idle"},
+ };
+
+ size_t i, st_length = sizeof(statuses) / sizeof(statuses[0]);
+
+ for (i = 0; i < st_length; i++) {
+ if (strcmp(status, statuses[i].stat) == 0) {
+ return statuses[i].val;
+ }
+ }
+
+ return 0; /* Unknown */
+}
+
+/*
+ * Get enabled state according to the cpu status.
+ * @param status by CIM
+ * @return CIM id of enabled state
+ */
+CMPIUint16 get_enabledstate(const CMPIUint16 status)
+{
+ static struct {
+ CMPIUint16 cpustatus; /* CIM cpu status */
+ CMPIUint16 enabledstate; /* CIM enabled state */
+ } statuses[] = {
+ {0, 0},
+ {1, 2},
+ {2, 3},
+ {3, 3},
+ {4, 2},
+ };
+
+ size_t i, st_length = sizeof(statuses) / sizeof(statuses[0]);
+
+ for (i = 0; i < st_length; i++) {
+ if (status == statuses[i].cpustatus) {
+ return statuses[i].enabledstate;
+ }
+ }
+
+ return 0; /* Unknown */
+}
+
+/*
+ * Get CPU characteristics according to the dmidecode output.
+ * @param dmi_charact characteristics from dmidecode
+ * @return characteristic defined by CIM
+ */
+CMPIUint16 get_characteristic(const char *dmi_charact)
+{
+ if (!dmi_charact) {
+ return 0; /* Unknown */
+ }
+
+ /* CIM characteristics based on
+ cim_schema_2.35.0Final-MOFs/Device/CIM_Processor.mof */
+ /* Dmidecode characts based on dmidecode 2.11 */
+ static struct {
+ CMPIUint16 value_map; /* ValueMap defined by CIM */
+ char *value; /* Value defined by CIM (just for reference) */
+ char *search; /* String used to match the dmidecode charact */
+ } characts[] = {
+ /*
+ {0, "Unknown", ""},
+ {1, "DMTF Reserved", ""},
+ */
+ {2, "64-bit Capable", "64-bit capable"},
+ /*
+ {3, "32-bit Capable", ""},
+ */
+ {4, "Enhanced Virtualization", "Enhanced Virtualization"},
+ {5, "Hardware Thread", "Hardware Thread"},
+ {6, "NX-bit", "Execute Protection"},
+ {7, "Power/Performance Control", "Power/Performance Control"},
+ /*
+ {8, "Core Frequency Boosting", ""},
+ */
+ {32568, "Multi-Core", "Multi-Core"},
+ };
+
+ size_t i, characts_length = sizeof(characts) / sizeof(characts[0]);
+
+ for (i = 0; i < characts_length; i++) {
+ if (strcmp(dmi_charact, characts[i].search) == 0) {
+ return characts[i].value_map;
+ }
+ }
+
+ return 0; /* Unknown */
+}
+
+/*
+ * Get CPU upgrade method according to the dmidecode upgrade.
+ * @param dmi_upgrade socket string from dmidecode program
+ * @return upgrade method id defined by CIM
+ */
+CMPIUint16 get_upgrade_method(const char *dmi_upgrade)
+{
+ if (!dmi_upgrade) {
+ return 2; /* Unknown */
+ }
+
+ /* CIM upgrade method based on
+ cim_schema_2.35.0Final-MOFs/Device/CIM_Processor.mof */
+ /* Dmidecode upgrade based on dmidecode 2.11 */
+ static struct {
+ CMPIUint16 value_map; /* ValueMap defined by CIM */
+ char *value; /* Value defined by CIM (just for reference) */
+ char *search; /* String used to match the dmidecode upgrade */
+ } sockets[] = {
+ {1, "Other", "Other"},
+ {2, "Unknown", "Unknown"},
+ {3, "Daughter Board", "Daughter Board"},
+ {4, "ZIF Socket", "ZIF Socket"},
+ {5, "Replacement/Piggy Back", "Replaceable Piggy Back"},
+ {6, "None", "None"},
+ {7, "LIF Socket", "LIF Socket"},
+ {8, "Slot 1", "Slot 1"},
+ {9, "Slot 2", "Slot 2"},
+ {10, "370 Pin Socket", "370-pin Socket"},
+ {11, "Slot A", "Slot A"},
+ {12, "Slot M", "Slot M"},
+ {13, "Socket 423", "Socket 423"},
+ {14, "Socket A (Socket 462)", "Socket A (Socket 462)"},
+ {15, "Socket 478", "Socket 478"},
+ {16, "Socket 754", "Socket 754"},
+ {17, "Socket 940", "Socket 940"},
+ {18, "Socket 939", "Socket 939"},
+ {19, "Socket mPGA604", "Socket mPGA604"},
+ {20, "Socket LGA771", "Socket LGA771"},
+ {21, "Socket LGA775", "Socket LGA775"},
+ {22, "Socket S1", "Socket S1"},
+ {23, "Socket AM2", "Socket AM2"},
+ {24, "Socket F (1207)", "Socket F (1207)"},
+ {25, "Socket LGA1366", "Socket LGA1366"},
+ {26, "Socket G34", "Socket G34"},
+ {27, "Socket AM3", "Socket AM3"},
+ {28, "Socket C32", "Socket C32"},
+ {29, "Socket LGA1156", "Socket LGA1156"},
+ {30, "Socket LGA1567", "Socket LGA1567"},
+ {31, "Socket PGA988A", "Socket PGA988A"},
+ {32, "Socket BGA1288", "Socket BGA1288"},
+ {33, "rPGA988B", "Socket rPGA988B"},
+ {34, "BGA1023", "Socket BGA1023"},
+ {35, "BGA1224", "Socket BGA1024"},
+ {36, "LGA1155", "Socket BGA1155"},
+ {37, "LGA1356", "Socket LGA1356"},
+ {38, "LGA2011", "Socket LGA2011"},
+ {39, "Socket FS1", "Socket FS1"},
+ {40, "Socket FS2", "Socket FS2"},
+ {41, "Socket FM1", "Socket FM1"},
+ {42, "Socket FM2", "Socket FM2"},
+ /*
+ {43, "Socket LGA2011-3", ""},
+ {44, "Socket LGA1356-3", ""},
+ */
+ };
+
+ size_t i, sockets_length = sizeof(sockets) / sizeof(sockets[0]);
+
+ for (i = 0; i < sockets_length; i++) {
+ if (strcmp(dmi_upgrade, sockets[i].search) == 0) {
+ return sockets[i].value_map;
+ }
+ }
+
+ return 1; /* Other */
+}
+
+/*
+ * Get CPU flag id.
+ * @param flag from /proc/cpuinfo file
+ * @param stat 0 if flag found, negative value otherwise
+ * @return CIM id of flag
+ */
+CMPIUint16 get_flag(const char *flag, short *stat)
+{
+ if (!flag) {
+ *stat = -1;
+ return 0;
+ }
+
+ /* Flag IDs and names are based on:
+ linux-3.8/arch/x86/include/asm/cpufeature.h */
+ static struct {
+ CMPIUint16 val; /* CIM value */
+ char *flag; /* flag name */
+ } flags[] = {
+ /* 0*32 */
+ {0, "fpu"},
+ {1, "vme"},
+ {2, "de"},
+ {3, "pse"},
+ {4, "tsc"},
+ {5, "msr"},
+ {6, "pae"},
+ {7, "mce"},
+ {8, "cx8"},
+ {9, "apic"},
+ {11, "sep"},
+ {12, "mtrr"},
+ {13, "pge"},
+ {14, "mca"},
+ {15, "cmov"},
+ {16, "pat"},
+ {17, "pse36"},
+ {18, "pn"},
+ {19, "clflush"},
+ {21, "dts"},
+ {22, "acpi"},
+ {23, "mmx"},
+ {24, "fxsr"},
+ {25, "sse"},
+ {26, "sse2"},
+ {27, "ss"},
+ {28, "ht"},
+ {29, "tm"},
+ {30, "ia64"},
+ {31, "pbe"},
+ /* 1*32 */
+ {43, "syscall"},
+ {51, "mp"},
+ {52, "nx"},
+ {54, "mmxext"},
+ {57, "fxsr_opt"},
+ {58, "pdpe1gb"},
+ {59, "rdtscp"},
+ {61, "lm"},
+ {62, "3dnowext"},
+ {63, "3dnow"},
+ /* 2*32 */
+ {64, "recovery"},
+ {65, "longrun"},
+ {67, "lrti"},
+ /* 3*32 */
+ {96, "cxmmx"},
+ {97, "k6_mtrr"},
+ {98, "cyrix_arr"},
+ {99, "centaur_mcr"},
+ {100, "k8"},
+ {101, "k7"},
+ {102, "p3"},
+ {103, "p4"},
+ {104, "constant_tsc"},
+ {105, "up"},
+ {106, "fxsave_leak"},
+ {107, "arch_perfmon"},
+ {108, "pebs"},
+ {109, "bts"},
+ {110, "syscall32"},
+ {111, "sysenter32"},
+ {112, "rep_good"},
+ {113, "mfence_rdtsc"},
+ {114, "lfence_rdtsc"},
+ {115, "11ap"},
+ {116, "nopl"},
+ {118, "xtopology"},
+ {119, "tsc_reliable"},
+ {120, "nonstop_tsc"},
+ {121, "clflush_monitor"},
+ {122, "extd_apicid"},
+ {123, "amd_dcm"},
+ {124, "aperfmperf"},
+ {125, "eagerfpu"},
+ /* 4*32 */
+ {128, "pni"},
+ {129, "pclmulqdq"},
+ {130, "dtes64"},
+ {131, "monitor"},
+ {132, "ds_cpl"},
+ {133, "vmx"},
+ {134, "smx"},
+ {135, "est"},
+ {136, "tm2"},
+ {137, "ssse3"},
+ {138, "cid"},
+ {140, "fma"},
+ {141, "cx16"},
+ {142, "xtpr"},
+ {143, "pdcm"},
+ {145, "pcid"},
+ {146, "dca"},
+ {147, "sse4_1"},
+ {148, "sse4_2"},
+ {149, "x2apic"},
+ {150, "movbe"},
+ {151, "popcnt"},
+ {152, "tsc_deadline_timer"},
+ {153, "aes"},
+ {154, "xsave"},
+ {155, "osxsave"},
+ {156, "avx"},
+ {157, "f16c"},
+ {158, "rdrand"},
+ {159, "hypervisor"},
+ /* 5*32*/
+ {162, "rng"},
+ {163, "rng_en"},
+ {166, "ace"},
+ {167, "ace_en"},
+ {168, "ace2"},
+ {169, "ace2_en"},
+ {170, "phe"},
+ {171, "phe_en"},
+ {172, "pmm"},
+ {173, "pmm_en"},
+ /* 6*32 */
+ {192, "lahf_lm"},
+ {193, "cmp_legacy"},
+ {194, "svm"},
+ {195, "extapic"},
+ {196, "cr8_legacy"},
+ {197, "abm"},
+ {198, "sse4a"},
+ {199, "misalignsse"},
+ {200, "3dnowprefetch"},
+ {201, "osvw"},
+ {202, "ibs"},
+ {203, "xop"},
+ {204, "skinit"},
+ {205, "wdt"},
+ {207, "lwp"},
+ {208, "fma4"},
+ {209, "tce"},
+ {211, "nodeid_msr"},
+ {213, "tbm"},
+ {214, "topoext"},
+ {215, "perfctr_core"},
+ /* 7*32 */
+ {224, "ida"},
+ {225, "arat"},
+ {226, "cpb"},
+ {227, "epb"},
+ {228, "xsaveopt"},
+ {229, "pln"},
+ {230, "pts"},
+ {231, "dtherm"},
+ {232, "hw_pstate"},
+ /* 8*32 */
+ {256, "tpr_shadow"},
+ {257, "vnmi"},
+ {258, "flexpriority"},
+ {259, "ept"},
+ {260, "vpid"},
+ {261, "npt"},
+ {262, "lbrv"},
+ {263, "svm_lock"},
+ {264, "nrip_save"},
+ {265, "tsc_scale"},
+ {266, "vmcb_clean"},
+ {267, "flushbyasid"},
+ {268, "decodeassists"},
+ {269, "pausefilter"},
+ {270, "pfthreshold"},
+ /* 9*32 */
+ {288, "fsgsbase"},
+ {289, "tsc_adjust"},
+ {291, "bmi1"},
+ {292, "hle"},
+ {293, "avx2"},
+ {295, "smep"},
+ {296, "bmi2"},
+ {297, "erms"},
+ {298, "invpcid"},
+ {299, "rtm"},
+ {306, "rdseed"},
+ {307, "adx"},
+ {308, "smap"},
+ };
+
+ size_t i, st_length = sizeof(flags) / sizeof(flags[0]);
+
+ for (i = 0; i < st_length; i++) {
+ if (strcmp(flag, flags[i].flag) == 0) {
+ *stat = 0;
+ return flags[i].val;
+ }
+ }
+
+ *stat = -2;
+ return 0;
+}
+
+/*
+ * Get CPU family id according to the dmidecode family.
+ * @param dmi_family family string from dmidecode program
+ * @return family id defined by CIM
+ */
+CMPIUint16 get_family(const char *dmi_family)
+{
+ if (!dmi_family) {
+ return 2; /* Unknown */
+ }
+
+ /* CIM CPU families based on
+ cim_schema_2.35.0Final-MOFs/Device/CIM_Processor.mof */
+ /* Dmidecode families based on dmidecode 2.11 */
+ static struct {
+ CMPIUint16 value_map; /* ValueMap defined by CIM */
+ char *value; /* Value defined by CIM (just for reference) */
+ char *search; /* String used to match the dmidecode family */
+ } fm[] = {
+ {1, "Other", "Other"},
+ {2, "Unknown", "Unknown"},
+ {3, "8086", "8086"},
+ {4, "80286", "80286"},
+ {5, "80386", "80386"},
+ {6, "80486", "80486"},
+ {7, "8087", "8087"},
+ {8, "80287", "80287"},
+ {9, "80387", "80387"},
+ {10, "80487", "80487"},
+ {11, "Pentium(R) brand", "Pentium"},
+ {12, "Pentium(R) Pro", "Pentium Pro"},
+ {13, "Pentium(R) II", "Pentium II"},
+ {14, "Pentium(R) processor with MMX(TM) technology", "Pentium MMX"},
+ {15, "Celeron(TM)", "Celeron"},
+ {16, "Pentium(R) II Xeon(TM)", "Pentium II Xeon"},
+ {17, "Pentium(R) III", "Pentium III"},
+ {18, "M1 Family", "M1"},
+ {19, "M2 Family", "M2"},
+ {20, "Intel(R) Celeron(R) M processor", "Celeron M"},
+ {21, "Intel(R) Pentium(R) 4 HT processor", "Pentium 4 HT"},
+
+ {24, "K5 Family", "K5"},
+ {25, "K6 Family", "K6"},
+ {26, "K6-2", "K6-2"},
+ {27, "K6-3", "K6-3"},
+ {28, "AMD Athlon(TM) Processor Family", "Athlon"},
+ {29, "AMD(R) Duron(TM) Processor", "Duron"},
+ {30, "AMD29000 Family", "AMD29000"},
+ {31, "K6-2+", "K6-2+"},
+ {32, "Power PC Family", "Power PC"},
+ {33, "Power PC 601", "Power PC 601"},
+ {34, "Power PC 603", "Power PC 603"},
+ {35, "Power PC 603+", "Power PC 603+"},
+ {36, "Power PC 604", "Power PC 604"},
+ {37, "Power PC 620", "Power PC 620"},
+ {38, "Power PC X704", "Power PC x704"},
+ {39, "Power PC 750", "Power PC 750"},
+ {40, "Intel(R) Core(TM) Duo processor", "Core Duo"},
+ {41, "Intel(R) Core(TM) Duo mobile processor", "Core Duo Mobile"},
+ {42, "Intel(R) Core(TM) Solo mobile processor", "Core Solo Mobile"},
+ {43, "Intel(R) Atom(TM) processor", "Atom"},
+
+ {48, "Alpha Family", "Alpha"},
+ {49, "Alpha 21064", "Alpha 21064"},
+ {50, "Alpha 21066", "Alpha 21066"},
+ {51, "Alpha 21164", "Alpha 21164"},
+ {52, "Alpha 21164PC", "Alpha 21164PC"},
+ {53, "Alpha 21164a", "Alpha 21164a"},
+ {54, "Alpha 21264", "Alpha 21264"},
+ {55, "Alpha 21364", "Alpha 21364"},
+ {56, "AMD Turion(TM) II Ultra Dual-Core Mobile M Processor Family",
+ "Turion II Ultra Dual-Core Mobile M"},
+ {57, "AMD Turion(TM) II Dual-Core Mobile M Processor Family",
+ "Turion II Dual-Core Mobile M"},
+ {58, "AMD Athlon(TM) II Dual-Core Mobile M Processor Family",
+ "Athlon II Dual-Core M"},
+ {59, "AMD Opteron(TM) 6100 Series Processor", "Opteron 6100"},
+ {60, "AMD Opteron(TM) 4100 Series Processor", "Opteron 4100"},
+ {61, "AMD Opteron(TM) 6200 Series Processor", "Opteron 6200"},
+ {62, "AMD Opteron(TM) 4200 Series Processor", "Opteron 4200"},
+
+ /*
+ {63, "AMD FX(TM) Series Processor", ""},
+ */
+ {64, "MIPS Family", "MIPS"},
+ {65, "MIPS R4000", "MIPS R4000"},
+ {66, "MIPS R4200", "MIPS R4200"},
+ {67, "MIPS R4400", "MIPS R4400"},
+ {68, "MIPS R4600", "MIPS R4600"},
+ {69, "MIPS R10000", "MIPS R10000"},
+ {70, "AMD C-Series Processor", "C-Series"},
+ {71, "AMD E-Series Processor", "E-Series"},
+ /*
+ {72, "AMD A-Series Processor", ""},
+ */
+ {73, "AMD G-Series Processor", "G-Series"},
+ /*
+ {74, "AMD Z-Series Processor", ""},
+ {75, "AMD R-Series Processor", ""},
+ {76, "AMD Opteron(TM) 4300 Series Processor", ""},
+ {77, "AMD Opteron(TM) 6300 Series Processor", ""},
+ {78, "AMD Opteron(TM) 3300 Series Processor", ""},
+ {79, "AMD FirePro(TM) Series Processor", ""},
+ */
+
+ {80, "SPARC Family", "SPARC"},
+ {81, "SuperSPARC", "SuperSPARC"},
+ {82, "microSPARC II", "MicroSPARC II"},
+ {83, "microSPARC IIep", "MicroSPARC IIep"},
+ {84, "UltraSPARC", "UltraSPARC"},
+ {85, "UltraSPARC II", "UltraSPARC II"},
+ {86, "UltraSPARC IIi", "UltraSPARC IIi"},
+ {87, "UltraSPARC III", "UltraSPARC III"},
+ {88, "UltraSPARC IIIi", "UltraSPARC IIIi"},
+
+ {96, "68040", "68040"},
+ {97, "68xxx Family", "68xxx"},
+ {98, "68000", "68000"},
+ {99, "68010", "68010"},
+ {100, "68020", "68020"},
+ {101, "68030", "68030"},
+
+ {112, "Hobbit Family", "Hobbit"},
+
+ {120, "Crusoe(TM) TM5000 Family", "Crusoe TM5000"},
+ {121, "Crusoe(TM) TM3000 Family", "Crusoe TM3000"},
+ {122, "Efficeon(TM) TM8000 Family", "Efficeon TM8000"},
+
+ {128, "Weitek", "Weitek"},
+
+ {130, "Itanium(TM) Processor", "Itanium"},
+ {131, "AMD Athlon(TM) 64 Processor Family", "Athlon 64"},
+ {132, "AMD Opteron(TM) Processor Family", "Opteron"},
+ {133, "AMD Sempron(TM) Processor Family", "Sempron"},
+ {134, "AMD Turion(TM) 64 Mobile Technology", "Turion 64"},
+ {135, "Dual-Core AMD Opteron(TM) Processor Family",
+ "Dual-Core Opteron"},
+ {136, "AMD Athlon(TM) 64 X2 Dual-Core Processor Family",
+ "Athlon 64 X2"},
+ {137, "AMD Turion(TM) 64 X2 Mobile Technology", "Turion 64 X2"},
+ {138, "Quad-Core AMD Opteron(TM) Processor Family",
+ "Quad-Core Opteron"},
+ {139, "Third-Generation AMD Opteron(TM) Processor Family",
+ "Third-Generation Opteron"},
+ {140, "AMD Phenom(TM) FX Quad-Core Processor Family", "Phenom FX"},
+ {141, "AMD Phenom(TM) X4 Quad-Core Processor Family", "Phenom X4"},
+ {142, "AMD Phenom(TM) X2 Dual-Core Processor Family", "Phenom X2"},
+ {143, "AMD Athlon(TM) X2 Dual-Core Processor Family", "Athlon X2"},
+ {144, "PA-RISC Family", "PA-RISC"},
+ {145, "PA-RISC 8500", "PA-RISC 8500"},
+ {146, "PA-RISC 8000", "PA-RISC 8000"},
+ {147, "PA-RISC 7300LC", "PA-RISC 7300LC"},
+ {148, "PA-RISC 7200", "PA-RISC 7200"},
+ {149, "PA-RISC 7100LC", "PA-RISC 7100LC"},
+ {150, "PA-RISC 7100", "PA-RISC 7100"},
+
+ {161, "Quad-Core Intel(R) Xeon(R) processor 3200 Series",
+ "Quad-Core Xeon 3200"},
+ {162, "Dual-Core Intel(R) Xeon(R) processor 3000 Series",
+ "Dual-Core Xeon 3000"},
+ {163, "Quad-Core Intel(R) Xeon(R) processor 5300 Series",
+ "Quad-Core Xeon 5300"},
+ {164, "Dual-Core Intel(R) Xeon(R) processor 5100 Series",
+ "Dual-Core Xeon 5100"},
+ {165, "Dual-Core Intel(R) Xeon(R) processor 5000 Series",
+ "Dual-Core Xeon 5000"},
+ {166, "Dual-Core Intel(R) Xeon(R) processor LV", "Dual-Core Xeon LV"},
+ {167, "Dual-Core Intel(R) Xeon(R) processor ULV",
+ "Dual-Core Xeon ULV"},
+ {168, "Dual-Core Intel(R) Xeon(R) processor 7100 Series",
+ "Dual-Core Xeon 7100"},
+ {169, "Quad-Core Intel(R) Xeon(R) processor 5400 Series",
+ "Quad-Core Xeon 5400"},
+ {170, "Quad-Core Intel(R) Xeon(R) processor", "Quad-Core Xeon"},
+ {171, "Dual-Core Intel(R) Xeon(R) processor 5200 Series",
+ "Dual-Core Xeon 5200"},
+ {172, "Dual-Core Intel(R) Xeon(R) processor 7200 Series",
+ "Dual-Core Xeon 7200"},
+ {173, "Quad-Core Intel(R) Xeon(R) processor 7300 Series",
+ "Quad-Core Xeon 7300"},
+ {174, "Quad-Core Intel(R) Xeon(R) processor 7400 Series",
+ "Quad-Core Xeon 7400"},
+ {175, "Multi-Core Intel(R) Xeon(R) processor 7400 Series",
+ "Multi-Core Xeon 7400"},
+ {176, "Pentium(R) III Xeon(TM)", "Pentium III Xeon"},
+ {177, "Pentium(R) III Processor with Intel(R) SpeedStep(TM) Technology",
+ "Pentium III Speedstep"},
+ {178, "Pentium(R) 4", "Pentium 4"},
+ {179, "Intel(R) Xeon(TM)", "Xeon"},
+ {180, "AS400 Family", "AS400"},
+ {181, "Intel(R) Xeon(TM) processor MP", "Xeon MP"},
+ {182, "AMD Athlon(TM) XP Family", "Athlon XP"},
+ {183, "AMD Athlon(TM) MP Family", "Athlon MP"},
+ {184, "Intel(R) Itanium(R) 2", "Itanium 2"},
+ {185, "Intel(R) Pentium(R) M processor", "Pentium M"},
+ {186, "Intel(R) Celeron(R) D processor", "Celeron D"},
+ {187, "Intel(R) Pentium(R) D processor", "Pentium D"},
+ {188, "Intel(R) Pentium(R) Processor Extreme Edition", "Pentium EE"},
+ {189, "Intel(R) Core(TM) Solo Processor", "Core Solo"},
+ {190, "K7", "K7"},
+ {191, "Intel(R) Core(TM)2 Duo Processor", "Core 2 Duo"},
+ {192, "Intel(R) Core(TM)2 Solo processor", "Core 2 Solo"},
+ {193, "Intel(R) Core(TM)2 Extreme processor", "Core 2 Extreme"},
+ {194, "Intel(R) Core(TM)2 Quad processor", "Core 2 Quad"},
+ {195, "Intel(R) Core(TM)2 Extreme mobile processor",
+ "Core 2 Extreme Mobile"},
+ {196, "Intel(R) Core(TM)2 Duo mobile processor", "Core 2 Duo Mobile"},
+ {197, "Intel(R) Core(TM)2 Solo mobile processor",
+ "Core 2 Solo Mobile"},
+ {198, "Intel(R) Core(TM) i7 processor", "Core i7"},
+ {199, "Dual-Core Intel(R) Celeron(R) Processor", "Dual-Core Celeron"},
+ {200, "S/390 and zSeries Family", "IBM390"},
+ {201, "ESA/390 G4", "G4"},
+ {202, "ESA/390 G5", "G5"},
+ {203, "ESA/390 G6", "ESA/390 G6"},
+ {204, "z/Architectur base", "z/Architectur"}, /* this is not typo */
+ {205, "Intel(R) Core(TM) i5 processor", "Core i5"},
+ {206, "Intel(R) Core(TM) i3 processor", "Core i3"},
+
+ {210, "VIA C7(TM)-M Processor Family", "C7-M"},
+ {211, "VIA C7(TM)-D Processor Family", "C7-D"},
+ {212, "VIA C7(TM) Processor Family", "C7"},
+ {213, "VIA Eden(TM) Processor Family", "Eden"},
+ {214, "Multi-Core Intel(R) Xeon(R) processor", "Multi-Core Xeon"},
+ {215, "Dual-Core Intel(R) Xeon(R) processor 3xxx Series",
+ "Dual-Core Xeon 3xxx"},
+ {216, "Quad-Core Intel(R) Xeon(R) processor 3xxx Series",
+ "Quad-Core Xeon 3xxx"},
+ {217, "VIA Nano(TM) Processor Family", "Nano"},
+ {218, "Dual-Core Intel(R) Xeon(R) processor 5xxx Series",
+ "Dual-Core Xeon 5xxx"},
+ {219, "Quad-Core Intel(R) Xeon(R) processor 5xxx Series",
+ "Quad-Core Xeon 5xxx"},
+
+ {221, "Dual-Core Intel(R) Xeon(R) processor 7xxx Series",
+ "Dual-Core Xeon 7xxx"},
+ {222, "Quad-Core Intel(R) Xeon(R) processor 7xxx Series",
+ "Quad-Core Xeon 7xxx"},
+ {223, "Multi-Core Intel(R) Xeon(R) processor 7xxx Series",
+ "Multi-Core Xeon 7xxx"},
+ {224, "Multi-Core Intel(R) Xeon(R) processor 3400 Series",
+ "Multi-Core Xeon 3400"},
+
+ /*
+ {228, "AMD Opteron(TM) 3000 Series Processor", ""},
+ {229, "AMD Sempron(TM) II Processor Family", ""},
+ */
+ {230, "Embedded AMD Opteron(TM) Quad-Core Processor Family",
+ "Embedded Opteron Quad-Core"},
+ {231, "AMD Phenom(TM) Triple-Core Processor Family",
+ "Phenom Triple-Core"},
+ {232, "AMD Turion(TM) Ultra Dual-Core Mobile Processor Family",
+ "Turion Ultra Dual-Core Mobile"},
+ {233, "AMD Turion(TM) Dual-Core Mobile Processor Family",
+ "Turion Dual-Core Mobile"},
+ {234, "AMD Athlon(TM) Dual-Core Processor Family", "Athlon Dual-Core"},
+ {235, "AMD Sempron(TM) SI Processor Family", "Sempron SI"},
+ {236, "AMD Phenom(TM) II Processor Family", "Phenom II"},
+ {237, "AMD Athlon(TM) II Processor Family", "Athlon II"},
+ {238, "Six-Core AMD Opteron(TM) Processor Family", "Six-Core Opteron"},
+ {239, "AMD Sempron(TM) M Processor Family", "Sempron M"},
+
+ {250, "i860", "i860"},
+ {251, "i960", "i960"},
+
+ {260, "SH-3", "SH-3"},
+ {261, "SH-4", "SH-4"},
+ {280, "ARM", "ARM"},
+ {281, "StrongARM", "StrongARM"},
+ {300, "6x86", "6x86"},
+ {301, "MediaGX", "MediaGX"},
+ {302, "MII", "MII"},
+ {320, "WinChip", "WinChip"},
+ {350, "DSP", "DSP"},
+ {500, "Video Processor", "Video Processor"},
+
+ /*
+ {254, "Reserved (SMBIOS Extension)", ""},
+ {255, "Reserved (Un-initialized Flash Content - Lo)", ""},
+
+ {65534, "Reserved (For Future Special Purpose Assignment)", ""},
+ {65535, "Reserved (Un-initialized Flash Content - Hi)", ""},
+ */
+ };
+
+ size_t i, fm_length = sizeof(fm) / sizeof(fm[0]);
+
+ for (i = 0; i < fm_length; i++) {
+ if (strcmp(dmi_family, fm[i].search) == 0) {
+ return fm[i].value_map;
+ }
+ }
+
+ return 1; /* Other */
+}
+
+KONKRET_REGISTRATION(
+ "root/cimv2",
+ "LMI_Processor",
+ "LMI_Processor",
+ "instance method")
diff --git a/src/hardware/cpuinfo.c b/src/hardware/cpuinfo.c
new file mode 100644
index 0000000..d80e1cb
--- /dev/null
+++ b/src/hardware/cpuinfo.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include "cpuinfo.h"
+
+
+/*
+ * Initialize CpuinfoProcessor attributes.
+ * @param cpu
+ */
+void init_cpuinfoprocessor_struct(CpuinfoProcessor *cpu)
+{
+ cpu->flags_nb = 0;
+ cpu->flags = NULL;
+ cpu->address_size = 0;
+ cpu->model_name = NULL;
+}
+
+/*
+ * Check attributes of cpu structure and fill in defaults if needed.
+ * @param cpu
+ * @return 0 if success, negative value otherwise
+ */
+short check_cpuinfoprocessor_attributes(CpuinfoProcessor *cpu)
+{
+ short ret = -1;
+
+ if (!cpu->model_name) {
+ if (!(cpu->model_name = strdup(""))) {
+ ret = -2;
+ goto done;
+ }
+ }
+
+ ret = 0;
+
+done:
+ if (ret != 0) {
+ warn("Failed to allocate memory.");
+ }
+
+ return ret;
+}
+
+short cpuinfo_get_processor(CpuinfoProcessor *cpu)
+{
+ short ret = -1;
+ unsigned i, buffer_size = 0;
+ char **buffer = NULL, *buf;
+
+ /* read /proc/cpuinfo file */
+ if (read_file("/proc/cpuinfo", &buffer, &buffer_size) != 0) {
+ ret = -2;
+ goto done;
+ }
+
+ init_cpuinfoprocessor_struct(cpu);
+
+ /* parse information about processor */
+ for (i = 0; i < buffer_size; i++) {
+ /* CPU Flags */
+ buf = copy_string_part_after_delim(buffer[i], "flags\t\t: ");
+ if (buf) {
+ if (explode(buf, NULL, &cpu->flags, &cpu->flags_nb) != 0) {
+ ret = -3;
+ goto done;
+ }
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Address Size */
+ buf = copy_string_part_after_delim(buffer[i], " bits physical, ");
+ if (buf) {
+ sscanf(buf, "%u", &cpu->address_size);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Model Name */
+ buf = copy_string_part_after_delim(buffer[i], "model name\t: ");
+ if (buf) {
+ cpu->model_name = buf;
+ buf = NULL;
+ continue;
+ }
+ }
+
+ if (check_cpuinfoprocessor_attributes(cpu) != 0) {
+ ret = -4;
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ free_2d_buffer(&buffer, &buffer_size);
+
+ if (ret != 0) {
+ cpuinfo_free_processor(cpu);
+ }
+
+ return ret;
+}
+
+void cpuinfo_free_processor(CpuinfoProcessor *cpu)
+{
+ if (cpu) {
+ if (cpu->flags_nb > 0) {
+ unsigned i;
+ for (i = 0; i < cpu->flags_nb; i++) {
+ if (cpu->flags[i]) {
+ free(cpu->flags[i]);
+ }
+ cpu->flags[i] = NULL;
+ }
+ free(cpu->flags);
+ }
+ cpu->flags_nb = 0;
+ cpu->flags = NULL;
+ if (cpu->model_name) {
+ free(cpu->model_name);
+ }
+ cpu->model_name = NULL;
+ }
+
+ return;
+}
diff --git a/src/hardware/cpuinfo.h b/src/hardware/cpuinfo.h
new file mode 100644
index 0000000..5ec5dd5
--- /dev/null
+++ b/src/hardware/cpuinfo.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#ifndef CPUINFO_H_
+#define CPUINFO_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "globals.h"
+#include "utils.h"
+
+
+/* Processor from /proc/cpuinfo file. */
+typedef struct _CpuinfoProcessor {
+ unsigned flags_nb; /* Number of CPU Flags */
+ char **flags; /* CPU Flags */
+ unsigned address_size; /* Address Size / Address Width */
+ char *model_name; /* Model Name */
+} CpuinfoProcessor;
+
+
+/*
+ * Get processor structure according to the /proc/cpuinfo file.
+ * @param cpu
+ * @return 0 if success, negative value otherwise
+ */
+short cpuinfo_get_processor(CpuinfoProcessor *cpu);
+
+/*
+ * Free attributes in the cpuinfo structure.
+ * @param cpu structure
+ */
+void cpuinfo_free_processor(CpuinfoProcessor *cpu);
+
+
+#endif /* CPUINFO_H_ */
diff --git a/src/hardware/dmidecode.c b/src/hardware/dmidecode.c
new file mode 100644
index 0000000..6a038fb
--- /dev/null
+++ b/src/hardware/dmidecode.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include "dmidecode.h"
+
+
+/*
+ * Initialize DmiProcessor attributes.
+ * @param cpu
+ */
+void init_dmiprocessor_struct(DmiProcessor *cpu)
+{
+ cpu->id = NULL;
+ cpu->family = NULL;
+ cpu->status = NULL;
+ cpu->current_speed = 0;
+ cpu->max_speed = 0;
+ cpu->external_clock = 0;
+ cpu->name = NULL;
+ cpu->enabled_cores = 1;
+ cpu->type = NULL;
+ cpu->stepping = NULL;
+ cpu->upgrade = NULL;
+ cpu->charact_nb = 0;
+ cpu->characteristics = NULL;
+}
+
+/*
+ * Check attributes of cpu structure and fill in defaults if needed.
+ * @param cpu
+ * @return 0 if success, negative value otherwise
+ */
+short check_dmiprocessor_attributes(DmiProcessor *cpu)
+{
+ short ret = -1;
+
+ if (!cpu->id) {
+ if (!(cpu->id = strdup(""))) {
+ ret = -2;
+ goto done;
+ }
+ }
+ if (!cpu->family) {
+ if (!(cpu->family = strdup("Unknown"))) {
+ ret = -3;
+ goto done;
+ }
+ }
+ if (!cpu->status) {
+ if (!(cpu->status = strdup("Unknown"))) {
+ ret = -4;
+ goto done;
+ }
+ }
+ if (!cpu->name) {
+ if (!(cpu->name = strdup(""))) {
+ ret = -5;
+ goto done;
+ }
+ }
+ if (!cpu->type) {
+ if (!(cpu->type = strdup(""))) {
+ ret = -6;
+ goto done;
+ }
+ }
+ if (!cpu->stepping) {
+ if (!(cpu->stepping = strdup(""))) {
+ ret = -7;
+ goto done;
+ }
+ }
+ if (!cpu->upgrade) {
+ if (!(cpu->upgrade = strdup("Unknown"))) {
+ ret = -8;
+ goto done;
+ }
+ }
+
+ ret = 0;
+
+done:
+ if (ret != 0) {
+ warn("Failed to allocate memory.");
+ }
+
+ return ret;
+}
+
+short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
+{
+ short ret = -1;
+ int curr_cpu = -1;
+ unsigned i, buffer_size = 0;
+ char **buffer = NULL, *buf;
+
+ *cpus_nb = 0;
+
+ /* get dmidecode output */
+ if (run_command("dmidecode -t 4", &buffer, &buffer_size) != 0) {
+ ret = -2;
+ goto done;
+ }
+
+ /* count processors */
+ for (i = 0; i < buffer_size; i++) {
+ if (strncmp(buffer[i], "Handle 0x", 9) == 0) {
+ (*cpus_nb)++;
+ }
+ }
+
+ /* if no processor was found */
+ if (*cpus_nb < 1) {
+ warn("Dmidecode didn't recognize any processor.");
+ ret = -3;
+ goto done;
+ }
+
+ /* allocate memory for processors */
+ *cpus = (DmiProcessor *)calloc(*cpus_nb, sizeof(DmiProcessor));
+ if (!(*cpus)) {
+ warn("Failed to allocate memory.");
+ ret = -4;
+ goto done;
+ }
+
+ /* parse information about processors */
+ for (i = 0; i < buffer_size; i++) {
+ if (strncmp(buffer[i], "Handle 0x", 9) == 0) {
+ curr_cpu++;
+ init_dmiprocessor_struct(cpus[curr_cpu]);
+ continue;
+ }
+ /* ignore first useless lines */
+ if (curr_cpu < 0) {
+ continue;
+ }
+ /* ID */
+ buf = copy_string_part_after_delim(buffer[i], "ID: ");
+ if (buf) {
+ cpus[curr_cpu]->id = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Family */
+ buf = copy_string_part_after_delim(buffer[i], "Family: ");
+ if (buf) {
+ cpus[curr_cpu]->family = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Status */
+ buf = copy_string_part_after_delim(buffer[i], "Status: Populated, ");
+ if (buf) {
+ cpus[curr_cpu]->status = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Current Speed */
+ buf = copy_string_part_after_delim(buffer[i], "Current Speed: ");
+ if (buf && strcmp(buf, "Unknown") != 0) {
+ sscanf(buf, "%u", &cpus[curr_cpu]->current_speed);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Max Speed */
+ buf = copy_string_part_after_delim(buffer[i], "Max Speed: ");
+ if (buf && strcmp(buf, "Unknown") != 0) {
+ sscanf(buf, "%u", &cpus[curr_cpu]->max_speed);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* External Clock Speed */
+ buf = copy_string_part_after_delim(buffer[i], "External Clock: ");
+ if (buf && strcmp(buf, "Unknown") != 0) {
+ sscanf(buf, "%u", &cpus[curr_cpu]->external_clock);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* CPU Name */
+ buf = copy_string_part_after_delim(buffer[i], "Version: ");
+ if (buf) {
+ cpus[curr_cpu]->name = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Enabled Cores */
+ buf = copy_string_part_after_delim(buffer[i], "Core Enabled: ");
+ if (buf) {
+ sscanf(buf, "%u", &cpus[curr_cpu]->enabled_cores);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* CPU Type/Role */
+ buf = copy_string_part_after_delim(buffer[i], "Type: ");
+ if (buf) {
+ cpus[curr_cpu]->type = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Stepping */
+ buf = copy_string_part_after_delim(buffer[i], ", Stepping ");
+ if (buf) {
+ cpus[curr_cpu]->stepping = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Upgrade */
+ buf = copy_string_part_after_delim(buffer[i], "Upgrade: ");
+ if (buf) {
+ cpus[curr_cpu]->upgrade = buf;
+ buf = NULL;
+ continue;
+ }
+ /* CPU Characteristics */
+ if (strstr(buffer[i], "Characteristics:")
+ && !strstr(buffer[i], "Characteristics: ")) {
+ /* count characteristics */
+ cpus[curr_cpu]->charact_nb = 0;
+ while (strlen(buffer[i + cpus[curr_cpu]->charact_nb + 1])) {
+ cpus[curr_cpu]->charact_nb += 1;
+ }
+ /* allocate memory */
+ cpus[curr_cpu]->characteristics =
+ (char **)calloc(cpus[curr_cpu]->charact_nb, sizeof(char *));
+ if (!cpus[curr_cpu]->characteristics) {
+ warn("Failed to allocate memory.");
+ ret = -5;
+ goto done;
+ }
+ unsigned j;
+ char *tmp_line;
+ for (j = 0; j < cpus[curr_cpu]->charact_nb; j++) {
+ tmp_line = trim(buffer[i + j + 1], NULL);
+ if (tmp_line) {
+ cpus[curr_cpu]->characteristics[j] = tmp_line;
+ } else {
+ cpus[curr_cpu]->characteristics[j] = strdup("");
+ if (!cpus[curr_cpu]->characteristics[j]) {
+ warn("Failed to allocate memory.");
+ ret = -6;
+ goto done;
+ }
+ }
+ }
+ /* skip characteristics and newline after them */
+ i += cpus[curr_cpu]->charact_nb + 1;
+ }
+ }
+
+ /* fill in default attributes if needed */
+ for (i = 0; i < *cpus_nb; i++) {
+ if (check_dmiprocessor_attributes(cpus[i]) != 0) {
+ ret = -7;
+ goto done;
+ }
+ }
+
+ ret = 0;
+
+done:
+ free_2d_buffer(&buffer, &buffer_size);
+
+ if (ret != 0) {
+ dmi_free_processors(cpus, cpus_nb);
+ }
+
+ return ret;
+}
+
+void dmi_free_processors(DmiProcessor **cpus, unsigned *cpus_nb)
+{
+ unsigned i, j;
+
+ if (*cpus_nb > 0) {
+ for (i = 0; i < *cpus_nb; i++) {
+ if (cpus[i]->id) {
+ free(cpus[i]->id);
+ }
+ cpus[i]->id = NULL;
+ if (cpus[i]->family) {
+ free(cpus[i]->family);
+ }
+ cpus[i]->family = NULL;
+ if (cpus[i]->status) {
+ free(cpus[i]->status);
+ }
+ cpus[i]->status = NULL;
+ if (cpus[i]->name) {
+ free(cpus[i]->name);
+ }
+ cpus[i]->name = NULL;
+ if (cpus[i]->type) {
+ free(cpus[i]->type);
+ }
+ cpus[i]->type = NULL;
+ if (cpus[i]->stepping) {
+ free(cpus[i]->stepping);
+ }
+ cpus[i]->stepping = NULL;
+ if (cpus[i]->upgrade) {
+ free(cpus[i]->upgrade);
+ }
+ cpus[i]->upgrade = NULL;
+ if (cpus[i]->charact_nb > 0) {
+ for (j = 0; j < cpus[i]->charact_nb; j++) {
+ if (cpus[i]->characteristics[j]) {
+ free(cpus[i]->characteristics[j]);
+ }
+ cpus[i]->characteristics[j] = NULL;
+ }
+ free(cpus[i]->characteristics);
+ }
+ cpus[i]->charact_nb = 0;
+ cpus[i]->characteristics = NULL;
+ }
+ free (*cpus);
+ }
+
+ *cpus_nb = 0;
+ *cpus = NULL;
+}
diff --git a/src/hardware/dmidecode.h b/src/hardware/dmidecode.h
new file mode 100644
index 0000000..f7e76a9
--- /dev/null
+++ b/src/hardware/dmidecode.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#ifndef DMIDECODE_H_
+#define DMIDECODE_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "globals.h"
+#include "utils.h"
+
+
+/* Processor from dmidecode. */
+typedef struct _DmiProcessor {
+ char *id; /* ID */
+ char *family; /* Family */
+ char *status; /* CPU Status */
+ unsigned current_speed; /* Current Speed in MHz */
+ unsigned max_speed; /* Max Speed in MHz */
+ unsigned external_clock; /* External Clock Speed in MHz */
+ char *name; /* CPU name, version in dmidecode */
+ unsigned enabled_cores; /* Number of enabled cores */
+ char *type; /* CPU Type/Role */
+ char *stepping; /* Stepping (revision level within family) */
+ char *upgrade; /* CPU upgrade method - socket */
+ unsigned charact_nb; /* Number of CPU Characteristics */
+ char **characteristics; /* CPU Characteristics */
+} DmiProcessor;
+
+
+/*
+ * Get array of processors according to the dmidecode program.
+ * @param cpu array of cpus, this function will allocate necessary memory,
+ * but caller is responsible for freeing it
+ * @param cpus_nb number of processors in cpus
+ * @return 0 if success, negative value otherwise
+ */
+short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb);
+
+/*
+ * Free array of processor structures.
+ * @param cpus array of cpus
+ * @param cpus_nb number of cpus
+ */
+void dmi_free_processors(DmiProcessor **cpus, unsigned *cpus_nb);
+
+
+#endif /* DMIDECODE_H_ */
diff --git a/src/hardware/lscpu.c b/src/hardware/lscpu.c
new file mode 100644
index 0000000..124ed7b
--- /dev/null
+++ b/src/hardware/lscpu.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include "lscpu.h"
+
+
+/*
+ * Initialize LscpuProcessor attributes.
+ * @param cpu
+ */
+void init_lscpuprocessor_struct(LscpuProcessor *cpu)
+{
+ cpu->data_width = 0;
+ cpu->processors = 0;
+ cpu->cores = 0;
+ cpu->stepping = NULL;
+ cpu->current_speed = 0;
+}
+
+/*
+ * Check attributes of cpu structure and fill in defaults if needed.
+ * @param cpu
+ * @return 0 if success, negative value otherwise
+ */
+short check_lscpuprocessor_attributes(LscpuProcessor *cpu)
+{
+ short ret = -1;
+
+ if (!cpu->stepping) {
+ if (!(cpu->stepping = strdup(""))) {
+ ret = -2;
+ goto done;
+ }
+ }
+
+ ret = 0;
+
+done:
+ if (ret != 0) {
+ warn("Failed to allocate memory.");
+ }
+
+ return ret;
+}
+
+short lscpu_get_processor(LscpuProcessor *cpu)
+{
+ short ret = -1;
+ unsigned i, buffer_size = 0;
+ char **buffer = NULL, *buf;
+
+ /* get lscpu output */
+ if (run_command("lscpu", &buffer, &buffer_size) != 0) {
+ ret = -2;
+ goto done;
+ }
+
+ init_lscpuprocessor_struct(cpu);
+
+ /* parse information about processor */
+ for (i = 0; i < buffer_size; i++) {
+ /* Data Width */
+ buf = copy_string_part_after_delim(buffer[i], "CPU op-mode(s):");
+ if (buf) {
+ if (strstr(buf, "64")) {
+ cpu->data_width = 64;
+ } else if (strstr(buf, "32")) {
+ cpu->data_width = 32;
+ }
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Cores per processor */
+ buf = copy_string_part_after_delim(buffer[i], "Core(s) per socket:");
+ if (buf) {
+ sscanf(buf, "%u", &cpu->cores);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Number of processors */
+ buf = copy_string_part_after_delim(buffer[i], "Socket(s):");
+ if (buf) {
+ sscanf(buf, "%u", &cpu->processors);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Stepping */
+ buf = copy_string_part_after_delim(buffer[i], "Stepping:");
+ if (buf) {
+ cpu->stepping = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Current speed in MHz */
+ buf = copy_string_part_after_delim(buffer[i], "CPU MHz:");
+ if (buf) {
+ sscanf(buf, "%u", &cpu->current_speed);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ }
+
+ if (check_lscpuprocessor_attributes(cpu) != 0) {
+ ret = -3;
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ free_2d_buffer(&buffer, &buffer_size);
+
+ if (ret != 0) {
+ lscpu_free_processor(cpu);
+ }
+
+ return ret;
+}
+
+void lscpu_free_processor(LscpuProcessor *cpus)
+{
+ if (cpus) {
+ if (cpus->stepping) {
+ free(cpus->stepping);
+ }
+ cpus->stepping = NULL;
+ }
+
+ return;
+}
diff --git a/src/hardware/lscpu.h b/src/hardware/lscpu.h
new file mode 100644
index 0000000..892141e
--- /dev/null
+++ b/src/hardware/lscpu.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#ifndef LSCPU_H_
+#define LSCPU_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "globals.h"
+#include "utils.h"
+
+
+/* Processor from lscpu program. */
+typedef struct _LscpuProcessor {
+ unsigned data_width; /* Data width */
+ unsigned processors; /* Number of processors */
+ unsigned cores; /* Cores per processor */
+ char *stepping; /* Stepping */
+ unsigned current_speed; /* Current speed in MHz */
+} LscpuProcessor;
+
+
+/*
+ * Get processor structure according to the lscpu program.
+ * @param cpu
+ * @return 0 if success, negative value otherwise
+ */
+short lscpu_get_processor(LscpuProcessor *cpu);
+
+/*
+ * Free attributes in the lscpu structure.
+ * @param cpu
+ */
+void lscpu_free_processor(LscpuProcessor *cpu);
+
+
+#endif /* LSCPU_H_ */
diff --git a/src/hardware/utils.c b/src/hardware/utils.c
new file mode 100644
index 0000000..da7bbfa
--- /dev/null
+++ b/src/hardware/utils.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include "utils.h"
+
+
+short read_fp_to_2d_buffer(FILE *fp, char ***buffer, unsigned *buffer_size)
+{
+ short ret = -1;
+ ssize_t read;
+ size_t line_len = 0;
+ unsigned tmp_buffer_lines, lines_read = 0;
+ char **tmp_buffer, *line = NULL;
+
+ free_2d_buffer(buffer, buffer_size);
+
+ if (!fp) {
+ warn("Given file pointer is NULL.");
+ ret = -2;
+ goto done;
+ }
+
+ /* allocate buffer */
+ tmp_buffer_lines = 128;
+ tmp_buffer = (char **)calloc(tmp_buffer_lines, sizeof(char *));
+ if (!tmp_buffer) {
+ warn("Failed to allocate memory.");
+ ret = -3;
+ goto done;
+ }
+
+ while ((read = getline(&line, &line_len, fp)) != -1) {
+ /* filter comment lines */
+ if (read > 0 && line[0] == '#') {
+ continue;
+ }
+
+ /* reallocate if needed */
+ if (lines_read >= tmp_buffer_lines) {
+ tmp_buffer_lines *= 2;
+ char **newtmp = (char **)realloc(tmp_buffer,
+ tmp_buffer_lines * sizeof(char *));
+ if (!newtmp) {
+ warn("Failed to allocate memory.");
+ ret = -4;
+ goto done;
+ }
+ tmp_buffer = newtmp;
+ }
+
+ /* copy trimmed line to buffer */
+ tmp_buffer[lines_read] = trim(line, NULL);
+ if (!tmp_buffer[lines_read]) {
+ tmp_buffer[lines_read] = strdup("");
+ if (!tmp_buffer[lines_read]) {
+ warn("Failed to allocate memory.");
+ ret = -5;
+ goto done;
+ }
+ }
+ lines_read++;
+ }
+
+ if (lines_read < 1) {
+ warn("No data read from given source.");
+ ret = -6;
+ goto done;
+ }
+
+ /* reallocate buffer to free unused space */
+ if (tmp_buffer_lines > lines_read) {
+ tmp_buffer_lines = lines_read;
+ char **newtmp = (char **)realloc(tmp_buffer,
+ tmp_buffer_lines * sizeof(char *));
+ if (!newtmp) {
+ warn("Failed to allocate memory.");
+ ret = -7;
+ goto done;
+ }
+ tmp_buffer = newtmp;
+ }
+
+ *buffer_size = tmp_buffer_lines;
+ *buffer = tmp_buffer;
+
+ ret = 0;
+
+done:
+ if (line) {
+ free(line);
+ }
+ line = NULL;
+
+ if (ret != 0) {
+ free_2d_buffer(&tmp_buffer, &tmp_buffer_lines);
+ }
+
+ return ret;
+}
+
+void free_2d_buffer(char ***buffer, unsigned *buffer_size)
+{
+ unsigned i, tmp_buffer_lines = *buffer_size;
+ char **tmp_buffer = *buffer;
+
+ if (tmp_buffer_lines > 0) {
+ for (i = 0; i < tmp_buffer_lines; i++) {
+ if (tmp_buffer[i]) {
+ free(tmp_buffer[i]);
+ }
+ tmp_buffer[i] = NULL;
+ }
+ free(tmp_buffer);
+ }
+
+ tmp_buffer = NULL;
+ *buffer_size = 0;
+ *buffer = NULL;
+}
+
+short run_command(const char *command, char ***buffer, unsigned *buffer_size)
+{
+ FILE *fp;
+ short ret = -1;
+
+ /* if command is empty */
+ if (!command || strlen(command) < 1) {
+ warn("Given command is empty.");
+ ret = -2;
+ goto done;
+ }
+
+ /* execute command */
+ debug("Running command: \"%s\"", command);
+ fp = popen(command, "r");
+ if (!fp) {
+ warn("Failed to run command: \"%s\"; Error: %s",
+ command, strerror(errno));
+ ret = -3;
+ goto done;
+ }
+
+ if (read_fp_to_2d_buffer(fp, buffer, buffer_size) != 0) {
+ ret = -4;
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (fp) {
+ int ret_code = pclose(fp);
+ if (ret_code == -1) {
+ warn("Failed to run command: \"%s\"; Error: %s",
+ command, strerror(errno));
+ if (ret == 0) {
+ ret = -5;
+ }
+ } else if (ret_code != 0) {
+ warn("Command \"%s\" exited unexpectedly.", command);
+ if (ret == 0) {
+ ret = -6;
+ }
+ }
+ }
+
+ if (ret != 0) {
+ free_2d_buffer(buffer, buffer_size);
+ }
+
+ return ret;
+}
+
+short read_file(const char *filename, char ***buffer, unsigned *buffer_size)
+{
+ FILE *fp;
+ short ret = -1;
+
+ /* open file */
+ debug("Reading \"%s\" file.", filename);
+ fp = fopen(filename, "r");
+ if (!fp) {
+ warn("Failed to open \"%s\" file.", filename);
+ ret = -2;
+ goto done;
+ }
+
+ if (read_fp_to_2d_buffer(fp, buffer, buffer_size) != 0) {
+ ret = -3;
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (fp) {
+ fclose(fp);
+ }
+
+ if (ret != 0) {
+ free_2d_buffer(buffer, buffer_size);
+ }
+
+ return ret;
+}
+
+char *copy_string_part_after_delim(const char *str, const char *delim)
+{
+ if (!str || strlen(str) < 1 || !delim || strlen(delim) < 1) {
+ return NULL;
+ }
+
+ char *p, *out = NULL;
+ size_t delim_len = strlen(delim);
+
+ /* if str contains delim and there is something after it */
+ if ((p = strstr(str, delim)) && strlen(p + delim_len) > 0) {
+ out = trim(p + delim_len, NULL);
+ }
+
+ return out;
+}
+
+char *trim(const char *str, const char *delims)
+{
+ char *out;
+ const char *default_delims = WHITESPACES;
+ size_t l;
+
+ /* if string is empty */
+ if (!str || strlen(str) < 1) {
+ return NULL;
+ }
+
+ if (!delims) {
+ delims = default_delims;
+ }
+
+ /* trim start of the string */
+ while (strchr(delims, str[0]) && str[0] != '\0') {
+ str++;
+ }
+
+ l = strlen(str);
+
+ /* if string was only white spaces */
+ if (l < 1) {
+ return NULL;
+ }
+
+ /* shorten length of string if there are trailing white spaces */
+ while (strchr(delims, str[l - 1]) && l != 0) {
+ l--;
+ }
+
+ /* sanity check */
+ if (l < 1) {
+ return NULL;
+ }
+
+ /* copy string */
+ out = strndup(str, l);
+ if (!out) {
+ warn("Failed to allocate memory.");
+ }
+
+ return out;
+}
+
+short explode(const char *str, const char *delims, char ***buffer, unsigned *buffer_size)
+{
+ size_t l;
+ short ret = -1;
+ unsigned item = 0, tmp_buffer_size;
+ char *default_delims = WHITESPACES, *trimmed_str = NULL, *ts, **tmp_buffer;
+
+ free_2d_buffer(buffer, buffer_size);
+
+ if (!str || strlen(str) < 1) {
+ ret = 0;
+ goto done;
+ }
+
+ if (!delims) {
+ delims = default_delims;
+ }
+
+ trimmed_str = trim(str, delims);
+ if (!trimmed_str || strlen(trimmed_str) < 1) {
+ ret = 0;
+ goto done;
+ }
+
+ tmp_buffer_size = 128;
+ tmp_buffer = (char **)calloc(tmp_buffer_size, sizeof(char *));
+ if (!tmp_buffer) {
+ warn("Failed to allocate memory.");
+ ret = -2;
+ goto done;
+ }
+
+ ts = trimmed_str;
+ while (ts[0] != '\0') {
+ /* skip leading delimiters of substring */
+ while (strchr(delims, ts[0]) && ts[0] != '\0') {
+ ts++;
+ }
+ /* find length of valid substring */
+ l = 0;
+ while (!strchr(delims, ts[l]) && ts[l] != '\0') {
+ l++;
+ }
+ /* reallocate if needed */
+ if (item >= tmp_buffer_size) {
+ tmp_buffer_size *= 2;
+ char **new_temp = (char **)realloc(tmp_buffer,
+ tmp_buffer_size * sizeof(char *));
+ if (!new_temp) {
+ warn("Failed to allocate memory.");
+ ret = -3;
+ goto done;
+ }
+ tmp_buffer = new_temp;
+ }
+ /* copy the substring */
+ tmp_buffer[item] = strndup(ts, l);
+ if (!tmp_buffer[item]) {
+ warn("Failed to allocate memory.");
+ ret = -4;
+ goto done;
+ }
+ item++;
+ ts += l;
+ }
+
+ /* reallocate to save unused space */
+ if (tmp_buffer_size > item) {
+ tmp_buffer_size = item;
+ char **new_temp = (char **)realloc(tmp_buffer,
+ tmp_buffer_size * sizeof(char *));
+ if (!new_temp) {
+ warn("Failed to allocate memory.");
+ ret = -5;
+ goto done;
+ }
+ tmp_buffer = new_temp;
+ }
+
+ *buffer_size = tmp_buffer_size;
+ *buffer = tmp_buffer;
+
+ ret = 0;
+
+done:
+ if (trimmed_str) {
+ free(trimmed_str);
+ }
+ trimmed_str = NULL;
+
+ if (ret != 0) {
+ free_2d_buffer(&tmp_buffer, &tmp_buffer_size);
+ }
+
+ return ret;
+}
diff --git a/src/hardware/utils.h b/src/hardware/utils.h
new file mode 100644
index 0000000..9f5686f
--- /dev/null
+++ b/src/hardware/utils.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "globals.h"
+
+#define WHITESPACES " \f\n\r\t\v"
+
+
+/*
+ * Read given file pointer and save it's output in buffer. Number of lines read
+ * is stored in buffer_size. Function skips lines starting with '#'.
+ * Every line from output is trimmed.
+ * Buffer has to be NULL, and buffer_size 0. Function will allocate
+ * necessary memory, buffer can be freed with free_2d_buffer() function.
+ * @param fp file pointer to be read
+ * @param buffer which will be filled in
+ * @param buffer_size number of lines in buffer
+ * @return 0 if success, negative value otherwise
+ */
+short read_fp_to_2d_buffer(FILE *fp, char ***buffer, unsigned *buffer_size);
+
+/*
+ * Free 2D buffer.
+ * @param buffer
+ * @param buffer_size number of lines in buffer
+ */
+void free_2d_buffer(char ***buffer, unsigned *buffer_size);
+
+/*
+ * Run given command and store its output in buffer. Number of lines in buffer
+ * is stored in buffer_size. Function skips lines starting with '#'.
+ * Buffer has to be NULL, and buffer_size 0. Function will allocate necessary
+ * memory, buffer can be freed with free_2d_buffer() function.
+ * @param command to be run
+ * @param buffer
+ * @param buffer_size number of lines in buffer
+ * @return 0 if success, negative value otherwise
+ */
+short run_command(const char *command, char ***buffer, unsigned *buffer_size);
+
+/*
+ * Run given file and store its output in buffer. Number of lines in buffer
+ * is stored in buffer_size. Function skips lines starting with '#'.
+ * Buffer has to be NULL, and buffer_size 0. Function will allocate necessary
+ * memory, buffer can be freed with free_2d_buffer() function.
+ * @param filename
+ * @param buffer
+ * @param buffer_size number of lines in buffer
+ * @return 0 if success, negative value otherwise
+ */
+short read_file(const char *filename, char ***buffer, unsigned *buffer_size);
+
+/*
+ * Copy trimmed part of the given string after delimiter and returns pointer
+ * to the newly created string, allocated with malloc.
+ * If delimiter is not part of the string, or the string ends right after
+ * delimiter, NULL is returned.
+ * @param str string to be searched
+ * @param delim delimiter
+ * @return newly created string or NULL
+ */
+char *copy_string_part_after_delim(const char *str, const char *delim);
+
+/*
+ * Create trimmed copy of given string. Trimmed will be any characters
+ * found in delims parameter, or, if delims is NULL, any white space characters.
+ * @param str
+ * @param delims string containing delimiters. If NULL, white space characters
+ * are used.
+ * @return trimmed string allocated with malloc or NULL if allocation failed
+ * or given string was empty or contained only delimiters
+ */
+char *trim(const char *str, const char *delims);
+
+/*
+ * Explode given string to substrings delimited by delims.
+ * @param str input string
+ * @param delims string consisted of delimiters
+ * @param buffer output 2D buffer. Can be NULL if input string is NULL, empty,
+ * or only delimiters.
+ * @param buffer_size number of substrings
+ * @return 0 if success, negative value otherwise.
+ */
+short explode(const char *str, const char *delims, char ***buffer, unsigned *buffer_size);
+
+
+#endif /* UTILS_H_ */