summaryrefslogtreecommitdiffstats
path: root/src/hardware/dmidecode.c
diff options
context:
space:
mode:
authorPeter Schiffer <pschiffe@redhat.com>2013-04-04 19:02:29 +0200
committerPeter Schiffer <pschiffe@redhat.com>2013-04-04 19:02:29 +0200
commit381f0c0a5cd98a48dc6d5a5e0b98443707d8ea81 (patch)
treebdad2e739aac00eb02e71dfe7d4074268c6f69a4 /src/hardware/dmidecode.c
parentc47c5c19c5857439db30e40d4a691f5b700adf5f (diff)
downloadopenlmi-providers-381f0c0a5cd98a48dc6d5a5e0b98443707d8ea81.tar.gz
openlmi-providers-381f0c0a5cd98a48dc6d5a5e0b98443707d8ea81.tar.xz
openlmi-providers-381f0c0a5cd98a48dc6d5a5e0b98443707d8ea81.zip
Hardware: Added Processor Cache Memory Provider
New Providers: * LMI_ProcessorCacheMemoryProvider * LMI_AssociatedProcessorCacheMemoryProvider Other Changes: * Optimized usage of string constats * Fixed wrong usage of pointers in dmidecode.c * Filled unknown mandatory fields in providers with "Unknown" value * Replaced hard coded numbers with LMI constants * Minor optimization - don't gather data which won't be used
Diffstat (limited to 'src/hardware/dmidecode.c')
-rw-r--r--src/hardware/dmidecode.c427
1 files changed, 372 insertions, 55 deletions
diff --git a/src/hardware/dmidecode.c b/src/hardware/dmidecode.c
index 14e4ac9..a50aa8a 100644
--- a/src/hardware/dmidecode.c
+++ b/src/hardware/dmidecode.c
@@ -21,6 +21,10 @@
#include "dmidecode.h"
+/******************************************************************************
+ * DmiProcessor
+ */
+
/*
* Initialize DmiProcessor attributes.
* @param cpu
@@ -42,6 +46,9 @@ void init_dmiprocessor_struct(DmiProcessor *cpu)
cpu->upgrade = NULL;
cpu->charact_nb = 0;
cpu->characteristics = NULL;
+ cpu->l1_cache_handle = NULL;
+ cpu->l2_cache_handle = NULL;
+ cpu->l3_cache_handle = NULL;
}
/*
@@ -95,6 +102,24 @@ short check_dmiprocessor_attributes(DmiProcessor *cpu)
goto done;
}
}
+ if (!cpu->l1_cache_handle) {
+ if (!(cpu->l1_cache_handle = strdup(""))) {
+ ret = -9;
+ goto done;
+ }
+ }
+ if (!cpu->l2_cache_handle) {
+ if (!(cpu->l2_cache_handle = strdup(""))) {
+ ret = -10;
+ goto done;
+ }
+ }
+ if (!cpu->l3_cache_handle) {
+ if (!(cpu->l3_cache_handle = strdup(""))) {
+ ret = -11;
+ goto done;
+ }
+ }
ret = 0;
@@ -147,7 +172,7 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
for (i = 0; i < buffer_size; i++) {
if (strncmp(buffer[i], "Handle 0x", 9) == 0) {
curr_cpu++;
- init_dmiprocessor_struct(cpus[curr_cpu]);
+ init_dmiprocessor_struct(&(*cpus)[curr_cpu]);
continue;
}
/* ignore first useless lines */
@@ -157,28 +182,28 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* ID */
buf = copy_string_part_after_delim(buffer[i], "ID: ");
if (buf) {
- cpus[curr_cpu]->id = 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;
+ (*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;
+ (*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);
+ sscanf(buf, "%u", &(*cpus)[curr_cpu].current_speed);
free(buf);
buf = NULL;
continue;
@@ -186,7 +211,7 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* 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);
+ sscanf(buf, "%u", &(*cpus)[curr_cpu].max_speed);
free(buf);
buf = NULL;
continue;
@@ -194,7 +219,7 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* 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);
+ sscanf(buf, "%u", &(*cpus)[curr_cpu].external_clock);
free(buf);
buf = NULL;
continue;
@@ -202,14 +227,14 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* CPU Name */
buf = copy_string_part_after_delim(buffer[i], "Version: ");
if (buf) {
- cpus[curr_cpu]->name = buf;
+ (*cpus)[curr_cpu].name = buf;
buf = NULL;
continue;
}
/* Cores */
buf = copy_string_part_after_delim(buffer[i], "Core Count: ");
if (buf) {
- sscanf(buf, "%u", &cpus[curr_cpu]->cores);
+ sscanf(buf, "%u", &(*cpus)[curr_cpu].cores);
free(buf);
buf = NULL;
continue;
@@ -217,7 +242,7 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* Enabled Cores */
buf = copy_string_part_after_delim(buffer[i], "Core Enabled: ");
if (buf) {
- sscanf(buf, "%u", &cpus[curr_cpu]->enabled_cores);
+ sscanf(buf, "%u", &(*cpus)[curr_cpu].enabled_cores);
free(buf);
buf = NULL;
continue;
@@ -225,7 +250,7 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* Threads */
buf = copy_string_part_after_delim(buffer[i], "Thread Count: ");
if (buf) {
- sscanf(buf, "%u", &cpus[curr_cpu]->threads);
+ sscanf(buf, "%u", &(*cpus)[curr_cpu].threads);
free(buf);
buf = NULL;
continue;
@@ -233,21 +258,42 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
/* CPU Type/Role */
buf = copy_string_part_after_delim(buffer[i], "Type: ");
if (buf) {
- cpus[curr_cpu]->type = 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;
+ (*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;
+ (*cpus)[curr_cpu].upgrade = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Level 1 Cache Handle */
+ buf = copy_string_part_after_delim(buffer[i], "L1 Cache Handle: ");
+ if (buf) {
+ (*cpus)[curr_cpu].l1_cache_handle = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Level 2 Cache Handle */
+ buf = copy_string_part_after_delim(buffer[i], "L2 Cache Handle: ");
+ if (buf) {
+ (*cpus)[curr_cpu].l2_cache_handle = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Level 3 Cache Handle */
+ buf = copy_string_part_after_delim(buffer[i], "L3 Cache Handle: ");
+ if (buf) {
+ (*cpus)[curr_cpu].l3_cache_handle = buf;
buf = NULL;
continue;
}
@@ -255,27 +301,27 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
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;
+ (*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) {
+ (*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++) {
+ 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;
+ (*cpus)[curr_cpu].characteristics[j] = tmp_line;
} else {
- cpus[curr_cpu]->characteristics[j] = strdup("");
- if (!cpus[curr_cpu]->characteristics[j]) {
+ (*cpus)[curr_cpu].characteristics[j] = strdup("");
+ if (!(*cpus)[curr_cpu].characteristics[j]) {
warn("Failed to allocate memory.");
ret = -6;
goto done;
@@ -283,13 +329,13 @@ short dmi_get_processors(DmiProcessor **cpus, unsigned *cpus_nb)
}
}
/* skip characteristics and newline after them */
- i += cpus[curr_cpu]->charact_nb + 1;
+ 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) {
+ if (check_dmiprocessor_attributes(&(*cpus)[i]) != 0) {
ret = -7;
goto done;
}
@@ -313,45 +359,57 @@ void dmi_free_processors(DmiProcessor **cpus, unsigned *cpus_nb)
if (*cpus_nb > 0) {
for (i = 0; i < *cpus_nb; i++) {
- if (cpus[i]->id) {
- free(cpus[i]->id);
+ if ((*cpus)[i].id) {
+ free((*cpus)[i].id);
}
- cpus[i]->id = NULL;
- if (cpus[i]->family) {
- free(cpus[i]->family);
+ (*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].family = NULL;
+ if ((*cpus)[i].status) {
+ free((*cpus)[i].status);
}
- cpus[i]->status = NULL;
- if (cpus[i]->name) {
- free(cpus[i]->name);
+ (*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].name = NULL;
+ if ((*cpus)[i].type) {
+ free((*cpus)[i].type);
}
- cpus[i]->type = NULL;
- if (cpus[i]->stepping) {
- free(cpus[i]->stepping);
+ (*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].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].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;
+ (*cpus)[i].characteristics[j] = NULL;
}
- free(cpus[i]->characteristics);
+ free((*cpus)[i].characteristics);
+ }
+ (*cpus)[i].charact_nb = 0;
+ (*cpus)[i].characteristics = NULL;
+ if ((*cpus)[i].l1_cache_handle) {
+ free((*cpus)[i].l1_cache_handle);
+ }
+ (*cpus)[i].l1_cache_handle = NULL;
+ if ((*cpus)[i].l2_cache_handle) {
+ free((*cpus)[i].l2_cache_handle);
}
- cpus[i]->charact_nb = 0;
- cpus[i]->characteristics = NULL;
+ (*cpus)[i].l2_cache_handle = NULL;
+ if ((*cpus)[i].l3_cache_handle) {
+ free((*cpus)[i].l3_cache_handle);
+ }
+ (*cpus)[i].l3_cache_handle = NULL;
}
free (*cpus);
}
@@ -359,3 +417,262 @@ void dmi_free_processors(DmiProcessor **cpus, unsigned *cpus_nb)
*cpus_nb = 0;
*cpus = NULL;
}
+
+
+/******************************************************************************
+ * DmiCpuCache
+ */
+
+/*
+ * Initialize DmiCpuCache attributes.
+ * @param cache
+ */
+void init_dmi_cpu_cache_struct(DmiCpuCache *cache)
+{
+ cache->id = NULL;
+ cache->size = 0;
+ cache->name = NULL;
+ cache->status = NULL;
+ cache->level = 0;
+ cache->op_mode = NULL;
+ cache->type = NULL;
+ cache->associativity = NULL;
+}
+
+/*
+ * Check attributes of cache structure and fill in defaults if needed.
+ * @param cache
+ * @return 0 if success, negative value otherwise
+ */
+short check_dmi_cpu_cache_attributes(DmiCpuCache *cache)
+{
+ short ret = -1;
+
+ if (!cache->id) {
+ if (!(cache->id = strdup(""))) {
+ ret = -2;
+ goto done;
+ }
+ }
+ if (!cache->name) {
+ if (!(cache->name = strdup(""))) {
+ ret = -3;
+ goto done;
+ }
+ }
+ if (!cache->status) {
+ if (!(cache->status = strdup(""))) {
+ ret = -4;
+ goto done;
+ }
+ }
+ if (!cache->op_mode) {
+ if (!(cache->op_mode = strdup("Unknown"))) {
+ ret = -5;
+ goto done;
+ }
+ }
+ if (!cache->type) {
+ if (!(cache->type = strdup("Unknown"))) {
+ ret = -6;
+ goto done;
+ }
+ }
+ if (!cache->associativity) {
+ if (!(cache->associativity = strdup("Unknown"))) {
+ ret = -7;
+ goto done;
+ }
+ }
+
+ ret = 0;
+
+done:
+ if (ret != 0) {
+ warn("Failed to allocate memory.");
+ }
+
+ return ret;
+}
+
+short dmi_get_cpu_caches(DmiCpuCache **caches, unsigned *caches_nb)
+{
+ short ret = -1;
+ int curr_cache = -1;
+ unsigned i, buffer_size = 0;
+ char **buffer = NULL, *buf;
+
+ *caches_nb = 0;
+
+ /* get dmidecode output */
+ if (run_command("dmidecode -t 7", &buffer, &buffer_size) != 0) {
+ ret = -2;
+ goto done;
+ }
+
+ /* count caches */
+ for (i = 0; i < buffer_size; i++) {
+ if (strncmp(buffer[i], "Handle 0x", 9) == 0) {
+ (*caches_nb)++;
+ }
+ }
+
+ /* if no cache was found */
+ if (*caches_nb < 1) {
+ warn("Dmidecode didn't recognize any processor cache memory.");
+ ret = -3;
+ goto done;
+ }
+
+ /* allocate memory for caches */
+ *caches = (DmiCpuCache *)calloc(*caches_nb, sizeof(DmiCpuCache));
+ if (!(*caches)) {
+ warn("Failed to allocate memory.");
+ ret = -4;
+ goto done;
+ }
+
+ /* parse information about cache */
+ for (i = 0; i < buffer_size; i++) {
+ if (strncmp(buffer[i], "Handle 0x", 9) == 0) {
+ curr_cache++;
+ init_dmi_cpu_cache_struct(&(*caches)[curr_cache]);
+
+ /* Cache ID is it's handle */
+ char *id_start = buffer[i] + 7;
+ char *id_end = strchr(buffer[i], ',');
+ if (!id_end) {
+ warn("Unrecognized output from dmidecode program.");
+ ret = -5;
+ goto done;
+ }
+ (*caches)[curr_cache].id = strndup(id_start, id_end - id_start);
+ if (!(*caches)[curr_cache].id) {
+ warn("Failed to allocate memory.");
+ ret = -6;
+ goto done;
+ }
+
+ continue;
+ }
+ /* ignore first useless lines */
+ if (curr_cache < 0) {
+ continue;
+ }
+ /* Cache Name */
+ buf = copy_string_part_after_delim(buffer[i], "Socket Designation: ");
+ if (buf) {
+ (*caches)[curr_cache].name = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Cache Status and Level */
+ buf = copy_string_part_after_delim(buffer[i], "Configuration: ");
+ if (buf) {
+ char **confs = NULL;
+ unsigned confs_len = 0;
+ if (explode(buf, ",", &confs, &confs_len) != 0 ||
+ confs_len < 3) {
+ free_2d_buffer(&confs, &confs_len);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+
+ (*caches)[curr_cache].status = trim(confs[0], NULL);
+ sscanf(confs[2], "%*s %u", &(*caches)[curr_cache].level);
+
+ free_2d_buffer(&confs, &confs_len);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Cache Operational Mode */
+ buf = copy_string_part_after_delim(buffer[i], "Operational Mode: ");
+ if (buf) {
+ (*caches)[curr_cache].op_mode = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Cache Size */
+ buf = copy_string_part_after_delim(buffer[i], "Installed Size: ");
+ if (buf) {
+ sscanf(buf, "%u", &(*caches)[curr_cache].size);
+ (*caches)[curr_cache].size *= 1024; /* It's in kB, we want B */
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Cache Type */
+ buf = copy_string_part_after_delim(buffer[i], "System Type: ");
+ if (buf) {
+ (*caches)[curr_cache].type = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Cache Associativity */
+ buf = copy_string_part_after_delim(buffer[i], "Associativity: ");
+ if (buf) {
+ (*caches)[curr_cache].associativity = buf;
+ buf = NULL;
+ continue;
+ }
+ }
+
+ /* fill in default attributes if needed */
+ for (i = 0; i < *caches_nb; i++) {
+ if (check_dmi_cpu_cache_attributes(&(*caches)[i]) != 0) {
+ ret = -7;
+ goto done;
+ }
+ }
+
+ ret = 0;
+
+done:
+ free_2d_buffer(&buffer, &buffer_size);
+
+ if (ret != 0) {
+ dmi_free_cpu_caches(caches, caches_nb);
+ }
+
+ return ret;
+}
+
+void dmi_free_cpu_caches(DmiCpuCache **caches, unsigned *caches_nb)
+{
+ unsigned i;
+
+ if (*caches_nb > 0) {
+ for (i = 0; i < *caches_nb; i++) {
+ if ((*caches)[i].id) {
+ free((*caches)[i].id);
+ }
+ (*caches)[i].id = NULL;
+ if ((*caches)[i].name) {
+ free((*caches)[i].name);
+ }
+ (*caches)[i].name = NULL;
+ if ((*caches)[i].status) {
+ free((*caches)[i].status);
+ }
+ (*caches)[i].status = NULL;
+ if ((*caches)[i].op_mode) {
+ free((*caches)[i].op_mode);
+ }
+ (*caches)[i].op_mode = NULL;
+ if ((*caches)[i].type) {
+ free((*caches)[i].type);
+ }
+ (*caches)[i].type = NULL;
+ if ((*caches)[i].associativity) {
+ free((*caches)[i].associativity);
+ }
+ (*caches)[i].associativity = NULL;
+ }
+ free (*caches);
+ }
+
+ *caches_nb = 0;
+ *caches = NULL;
+}