diff options
Diffstat (limited to 'src/hardware/dmidecode.c')
-rw-r--r-- | src/hardware/dmidecode.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/hardware/dmidecode.c b/src/hardware/dmidecode.c index 348c7a2..367a08c 100644 --- a/src/hardware/dmidecode.c +++ b/src/hardware/dmidecode.c @@ -692,3 +692,153 @@ void dmi_free_cpu_caches(DmiCpuCache **caches, unsigned *caches_nb) *caches_nb = 0; *caches = NULL; } + + +/****************************************************************************** + * DmiMemory + */ + +/* + * Initialize DmiMemory attributes. + * @param memory + */ +void init_dmi_memory_struct(DmiMemory *memory) +{ + memory->physical_size = 0; + memory->available_size = 0; + memory->start_addr = 0; + memory->end_addr = 0; + memory->modules = NULL; + memory->modules_nb = 0; +} + +/* + * Initialize DmiMemoryModule attributes. + * @param mem + */ +void init_dmi_memory_module_struct(DmiMemoryModule *mem) +{ + mem->size = 0; +} + +short dmi_get_memory(DmiMemory *memory) +{ + short ret = -1; + int curr_mem = -1; + unsigned i, buffer_size = 0; + char **buffer = NULL, *buf; + + init_dmi_memory_struct(memory); + + /* get dmidecode output for memory modules */ + if (run_command("dmidecode -t 17", &buffer, &buffer_size) != 0) { + ret = -2; + goto done; + } + + /* count modules */ + for (i = 0; i < buffer_size; i++) { + if (strstr(buffer[i], "Size: ") && + !strstr(buffer[i], "Size: No Module Installed")) { + memory->modules_nb++; + } + } + + /* if no module was found */ + if (memory->modules_nb < 1) { + warn("Dmidecode didn't recognize any memory module."); + ret = -3; + goto done; + } + + /* allocate memory for modules */ + memory->modules = (DmiMemoryModule *)calloc(memory->modules_nb, sizeof(DmiMemoryModule)); + if (!memory->modules) { + warn("Failed to allocate memory."); + ret = -4; + goto done; + } + + /* parse information about modules */ + for (i = 0; i < buffer_size; i++) { + if (strstr(buffer[i], "Size: ") && + !strstr(buffer[i], "Size: No Module Installed")) { + curr_mem++; + init_dmi_memory_module_struct(&memory->modules[curr_mem]); + + /* Module Size */ + buf = copy_string_part_after_delim(buffer[i], "Size: "); + if (buf) { + sscanf(buf, "%lu", &memory->modules[curr_mem].size); + memory->modules[curr_mem].size *= 1048576; /* It's in MB, we want B */ + memory->physical_size += memory->modules[curr_mem].size; + free(buf); + buf = NULL; + } + + continue; + } + /* ignore first useless lines */ + if (curr_mem < 0) { + continue; + } + } + + free_2d_buffer(&buffer, &buffer_size); + + /* get dmidecode output for memory array */ + if (run_command("dmidecode -t 19", &buffer, &buffer_size) != 0) { + ret = -5; + goto done; + } + + /* parse information about memory array */ + short first_array = 1; + unsigned long start_addr, end_addr; + for (i = 0; i < buffer_size; i++) { + /* Starting Address */ + buf = copy_string_part_after_delim(buffer[i], "Starting Address: "); + if (buf) { + sscanf(buf, "%lx", &start_addr); + if (first_array || start_addr < memory->start_addr) { + memory->start_addr = start_addr / 1024; /* in Bytes, we want KB */ + first_array = 0; + } + free(buf); + buf = NULL; + continue; + } + /* Ending Address */ + buf = copy_string_part_after_delim(buffer[i], "Ending Address: "); + if (buf) { + sscanf(buf, "%lx", &end_addr); + if (end_addr > memory->end_addr) { + memory->end_addr = end_addr / 1024; /* in Bytes, we want KB */ + } + memory->available_size += end_addr - start_addr; + free(buf); + buf = NULL; + continue; + } + } + + ret = 0; + +done: + free_2d_buffer(&buffer, &buffer_size); + + if (ret != 0) { + dmi_free_memory(memory); + } + + return ret; +} + +void dmi_free_memory(DmiMemory *memory) +{ + if (memory->modules_nb > 0) { + free (memory->modules); + } + memory->modules_nb = 0; + memory->modules = NULL; +} |