diff options
author | Burt P <pburt0@gmail.com> | 2019-06-26 22:58:57 -0500 |
---|---|---|
committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2019-06-28 07:04:04 -0700 |
commit | 91af75547e7d494a82f8af8d17b4b9acb0af938d (patch) | |
tree | 79937af68b1b37d88bf26dc5865c3aaf15e1c11b | |
parent | 495481a4f2c9b21acb7bcecd793b4b6e9078399a (diff) |
Combine Memory DMI and Memory SPD into "Memory Devices"
Combines the information from DMI and SPD into a single
Memory Devices section.
Signed-off-by: Burt P <pburt0@gmail.com>
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | includes/devices.h | 1 | ||||
-rw-r--r-- | modules/devices.c | 24 | ||||
-rw-r--r-- | modules/devices/dmi_memory.c | 351 | ||||
-rw-r--r-- | modules/devices/spd-decode2.c (renamed from modules/devices/spd-decode.c) | 418 |
5 files changed, 429 insertions, 370 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 67cb03c7..39acca1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,7 +155,7 @@ set(MODULE_devices_SOURCES modules/devices/printers.c modules/devices/resources.c modules/devices/sensors.c - modules/devices/spd-decode.c +# modules/devices/spd-decode2.c modules/devices/storage.c modules/devices/usb.c ) @@ -201,8 +201,9 @@ set_source_files_properties( set_source_files_properties( modules/devices/dmi_memory.c +# modules/devices/spd-decode2.c PROPERTIES - COMPILE_FLAGS "-std=c99" + COMPILE_FLAGS "-std=c99 -Wno-deprecated-declarations" ) foreach (_module ${HARDINFO_MODULES}) diff --git a/includes/devices.h b/includes/devices.h index 71d125fe..ee47283e 100644 --- a/includes/devices.h +++ b/includes/devices.h @@ -86,7 +86,6 @@ extern GHashTable *sensor_compute; extern GHashTable *sensor_labels; extern GModule *cups; -extern gchar *spd_info; extern gchar *dmi_info; extern gchar *dtree_info; diff --git a/modules/devices.c b/modules/devices.c index f3c5addf..3780ac3d 100644 --- a/modules/devices.c +++ b/modules/devices.c @@ -51,7 +51,6 @@ gchar *callback_input(); gchar *callback_usb(); gchar *callback_dmi(); gchar *callback_dmi_mem(); -gchar *callback_spd(); gchar *callback_dtree(); gchar *callback_device_resources(); @@ -66,7 +65,6 @@ void scan_input(gboolean reload); void scan_usb(gboolean reload); void scan_dmi(gboolean reload); void scan_dmi_mem(gboolean reload); -void scan_spd(gboolean reload); void scan_dtree(gboolean reload); void scan_device_resources(gboolean reload); @@ -80,7 +78,6 @@ enum { ENTRY_DMI, ENTRY_PROCESSOR, ENTRY_GPU, - ENTRY_SPD, ENTRY_DMI_MEM, ENTRY_PCI, ENTRY_USB, @@ -103,8 +100,7 @@ static ModuleEntry entries[] = { [ENTRY_INPUT] = {N_("Input Devices"), "inputdevices.png", callback_input, scan_input, MODULE_FLAG_NONE}, [ENTRY_STORAGE] = {N_("Storage"), "hdd.png", callback_storage, scan_storage, MODULE_FLAG_NONE}, [ENTRY_DMI] = {N_("System DMI"), "computer.png", callback_dmi, scan_dmi, MODULE_FLAG_NONE}, - [ENTRY_SPD] = {N_("Memory SPD"), "memory.png", callback_spd, scan_spd, MODULE_FLAG_NONE}, - [ENTRY_DMI_MEM] = {N_("Memory DMI"), "memory.png", callback_dmi_mem, scan_dmi_mem, MODULE_FLAG_NONE}, + [ENTRY_DMI_MEM] = {N_("Memory Devices"), "memory.png", callback_dmi_mem, scan_dmi_mem, MODULE_FLAG_NONE}, #if defined(ARCH_x86) || defined(ARCH_x86_64) [ENTRY_DTREE] = {"#"}, #else @@ -546,13 +542,6 @@ void scan_dmi_mem(gboolean reload) SCAN_END(); } -void scan_spd(gboolean reload) -{ - SCAN_START(); - scan_spd_do(); - SCAN_END(); -} - void scan_dtree(gboolean reload) { SCAN_START(); @@ -646,11 +635,6 @@ gchar *callback_dmi_mem() return g_strdup(dmi_mem_info); } -gchar *callback_spd() -{ - return g_strdup(spd_info); -} - gchar *callback_dtree() { return g_strdup_printf("%s" @@ -817,12 +801,6 @@ const gchar *hi_note_func(gint entry) "<b><i>udisksd</i></b> is required for NVMe devices.")); } } - else if (entry == ENTRY_SPD){ - const char *msg; - if (spd_decode_show_hinote(&msg)) { - return msg; - } - } else if (entry == ENTRY_DMI_MEM){ const char *msg; if (dmi_mem_show_hinote(&msg)) { diff --git a/modules/devices/dmi_memory.c b/modules/devices/dmi_memory.c index 565982f4..937b5e80 100644 --- a/modules/devices/dmi_memory.c +++ b/modules/devices/dmi_memory.c @@ -22,6 +22,10 @@ #include "vendor.h" #include <inttypes.h> +#include "dt_util.h" /* for appf() */ + +#include "spd-decode2.c" + gboolean no_handles = FALSE; gboolean sketchy_info = FALSE; @@ -34,6 +38,7 @@ static const unsigned long dta = 16; /* array */ static const unsigned long dtm = 17; /* socket */ #define UNKIFNULL2(f) ((f) ? f : _("(Unknown)")) +#define UNKIFEMPTY2(f) ((*f) ? f : _("(Unknown)")) #define SEQ(s,m) (g_strcmp0(s, m) == 0) const char *problem_marker() { @@ -118,14 +123,29 @@ typedef struct { gchar *mfgr; const Vendor *vendor; + spd_data *spd; } dmi_mem_socket; typedef struct { gboolean empty; GSList *arrays; GSList *sockets; + GSList *spd; } dmi_mem; +gboolean null_if_empty(gchar **str) { + if (str && *str) { + gchar *p = *str; + while(p && *p) { + if (isalnum(*p)) + return FALSE; + p++; + } + *str = NULL; + } + return TRUE; +} + dmi_mem_socket *dmi_mem_socket_new(unsigned long h) { dmi_mem_socket *s = g_new0(dmi_mem_socket, 1); s->handle = h; @@ -164,16 +184,26 @@ dmi_mem_socket *dmi_mem_socket_new(unsigned long h) { if (!g_str_has_prefix(s->size_str, empty_mem_str)) { s->populated = 1; +#define STR_IGNORE(str, ignore) if (SEQ(str, ignore)) { *str = 0; null_if_empty(&str); } + s->form_factor = dmidecode_match("Form Factor", &dtm, &h); s->type = dmidecode_match("Type", &dtm, &h); + STR_IGNORE(s->type, "Unknown"); s->type_detail = dmidecode_match("Type Detail", &dtm, &h); + STR_IGNORE(s->type_detail, "None"); + s->speed_str = dmidecode_match("Speed", &dtm, &h); s->configured_clock_str = dmidecode_match("Configured Clock Speed", &dtm, &h); if (!s->configured_clock_str) s->configured_clock_str = dmidecode_match("Configured Memory Speed", &dtm, &h); + s->voltage_min_str = dmidecode_match("Minimum Voltage", &dtm, &h); s->voltage_max_str = dmidecode_match("Maximum Voltage", &dtm, &h); s->voltage_conf_str = dmidecode_match("Configured Voltage", &dtm, &h); + STR_IGNORE(s->voltage_min_str, "Unknown"); + STR_IGNORE(s->voltage_max_str, "Unknown"); + STR_IGNORE(s->voltage_conf_str, "Unknown"); + s->partno = dmidecode_match("Part Number", &dtm, &h); s->data_width = dmidecode_match("Data Width", &dtm, &h); @@ -185,6 +215,8 @@ dmi_mem_socket *dmi_mem_socket_new(unsigned long h) { g_free(s->mfgr); s->mfgr = NULL; } + null_if_empty(&s->mfgr); + null_if_empty(&s->partno); s->vendor = vendor_match(s->mfgr, NULL); } @@ -248,21 +280,65 @@ dmi_mem *dmi_mem_new() { dmi_handle_list_free(hlm); } - if (!m->sockets && !m->arrays) { + m->spd = spd_scan(); + + if (!m->sockets && !m->arrays && !m->spd) { m->empty = 1; return m; } - /* update array present devices/size */ - GSList *l = NULL; + GSList *l = NULL, *l2 = NULL; for(l = m->sockets; l; l = l->next) { dmi_mem_socket *s = (dmi_mem_socket*)l->data; + + /* update array present devices/size */ dmi_mem_array *a = dmi_mem_find_array(m, s->array_handle); if (a) { a->size_MiB_present += s->size_MiB; if (s->populated) a->devs_populated++; } + + if (!s->populated) continue; + if (!m->spd) continue; + + /* match SPD */ + spd_data *best = NULL; + int best_score = 0; + for(l2 = m->spd; l2; l2 = l2->next) { + spd_data *e = (spd_data*)l2->data; + int score = 0; + if (!e->claimed_by_dmi) { + if (SEQ(s->partno, e->partno)) + score += 20; + if (s->size_MiB == e->size_MiB) + score += 10; + if (s->vendor == e->vendor) + score += 5; + + if (score > best_score) + best = e; + } + } + if (best) { + s->spd = best; + best->claimed_by_dmi = 1; + + /* fill in missing from SPD */ + if (!s->mfgr && s->spd->vendor_str) { + s->mfgr = g_strdup(s->spd->vendor_str); + s->vendor = s->spd->vendor; + } + + if (!s->partno && s->spd->partno) + s->partno = g_strdup(s->spd->partno); + + if (!s->form_factor && s->spd->form_factor) + s->form_factor = g_strdup(s->spd->form_factor); + + if (!s->type_detail && s->spd->type_detail) + s->type_detail = g_strdup(s->spd->type_detail); + } } return m; @@ -272,144 +348,87 @@ void dmi_mem_free(dmi_mem* s) { if (s) { g_slist_free_full(s->arrays, (GDestroyNotify)dmi_mem_array_free); g_slist_free_full(s->sockets, (GDestroyNotify)dmi_mem_socket_free); + g_slist_free_full(s->spd, (GDestroyNotify)spd_data_free); g_free(s); } } -gchar *dmi_mem_socket_info_view0() { - gchar *ret = g_strdup("[$ShellParam$]\nViewType=0\n"); - GSList *l = NULL; - sketchy_info = FALSE; - - dmi_mem *mem = dmi_mem_new(); - - /* Arrays */ - for(l = mem->arrays; l; l = l->next) { - dmi_mem_array *a = (dmi_mem_array*)l->data; +gchar *make_spd_section(spd_data *spd) { + gchar *ret = NULL; + if (spd) { + gchar *full_spd = NULL; + switch(spd->type) { + case SDR_SDRAM: + full_spd = decode_sdr_sdram_extra(spd->bytes); + break; + case DDR_SDRAM: + full_spd = decode_ddr_sdram_extra(spd->bytes); + break; + case DDR2_SDRAM: + full_spd = decode_ddr2_sdram_extra(spd->bytes); + break; + case DDR3_SDRAM: + full_spd = decode_ddr3_sdram_extra(spd->bytes); + break; + case DDR4_SDRAM: + full_spd = decode_ddr4_sdram_extra(spd->bytes, spd->spd_size); + break; + default: + DEBUG("blug for type: %d %s\n", spd->type, ram_types[spd->type]); + } + gchar *vendor_str = NULL; + if (spd->vendor) { + if (spd->vendor->url) + vendor_str = g_strdup_printf(" (%s, %s)", + spd->vendor->name, spd->vendor->url ); + } gchar *size_str = NULL; - - if (a->size_MiB_max > 1024 && (a->size_MiB_max % 1024 == 0) - && a->size_MiB_present > 1024 && (a->size_MiB_present % 1024 == 0) ) - size_str = g_strdup_printf("%"PRId64" / %"PRId64" %s", a->size_MiB_present / 1024, a->size_MiB_max / 1024, _("GiB")); + if (!spd->size_MiB) + size_str = g_strdup(_("(Unknown)")); else - size_str = g_strdup_printf("%"PRId64" / %"PRId64" %s", a->size_MiB_present, a->size_MiB_max, _("MiB")); - - if (a->size_MiB_max < a->size_MiB_present) { - sketchy_info = TRUE; - size_str = h_strdup_cprintf(" %s", size_str, problem_marker()); - } - - ret = h_strdup_cprintf("[%s %s]\n" - "%s=0x%x\n" - "%s=%s\n" - "%s=%s\n" - "%s=%s\n" - "%s=%d / %d\n", - ret, - _("Memory Array"), a->locator ? a->locator : ".", - _("Array DMI Handle"), a->array_handle, - _("Use"), UNKIFNULL2(a->use), - _("Error Correction Type"), UNKIFNULL2(a->ecc), - _("Size (Present / Max)"), size_str, - _("Devices (Populated / Sockets)"), a->devs_populated, a->devs - ); + size_str = g_strdup_printf("%d %s", spd->size_MiB, _("MiB") ); + + ret = g_strdup_printf("[%s]\n" + "%s=%s (%s)%s\n" + "%s=%d.%d\n" + "%s=%s\n" + "%s=%s\n" + "%s=%s%s\n" /* vendor */ + "%s=%s\n" /* part */ + "%s=%s\n" /* size */ + "%s", + _("Serial Presence Detect (SPD)"), + _("Source"), spd->dev, spd->spd_driver ? "ee1004" : "eeprom", + (spd->type == DDR4_SDRAM && !spd->spd_driver) ? problem_marker() : "", + _("SPD Revision"), spd->spd_rev_major, spd->spd_rev_minor, + _("Form Factor"), UNKIFNULL2(spd->form_factor), + _("Type"), UNKIFEMPTY2(spd->type_detail), + _("Vendor"), UNKIFNULL2(spd->vendor_str), vendor_str ? vendor_str : "", + _("Part Number"), UNKIFEMPTY2(spd->partno), + _("Size"), size_str, + full_spd ? full_spd : "" + ); + g_free(full_spd); + g_free(vendor_str); g_free(size_str); } - - /* Sockets */ - for(l = mem->sockets; l; l = l->next) { - dmi_mem_socket *s = (dmi_mem_socket*)l->data; - - if (s->populated) { - gchar *vendor_str = NULL; - if (s->vendor) { - if (s->vendor->url) - vendor_str = g_strdup_printf(" (%s, %s)", - s->vendor->name, s->vendor->url ); - } - gchar *size_str = NULL; - if (!s->size_str) - size_str = g_strdup(_("(Unknown)")); - else if (!s->size_MiB) - size_str = g_strdup(s->size_str); - else - size_str = g_strdup_printf("%ld %s", s->size_MiB, _("MiB") ); - - ret = h_strdup_cprintf("[%s %s]\n" - "%s=0x%lx, 0x%lx\n" - "%s=%s\n" - "%s=%s\n" - "%s=%s%s\n" - "%s=%s\n" - "%s=%s / %s\n" - "%s=%s\n" - "%s=%s\n" - "%s=%s\n" - "%s=%s / %s\n" - "%s=%s\n" - "%s=%s\n" - "%s=%s\n", - ret, - _("Memory Socket"), s->full_locator, - _("DMI Handles (Array, Socket)"), s->array_handle, s->handle, - _("Bank Locator"), UNKIFNULL2(s->bank_locator), - _("Form Factor"), UNKIFNULL2(s->form_factor), - _("Manufacturer"), UNKIFNULL2(s->mfgr), vendor_str ? vendor_str : "", - _("Part Number"), UNKIFNULL2(s->partno), - _("Type"), UNKIFNULL2(s->type), UNKIFNULL2(s->type_detail), - _("Size"), size_str, - _("Rated Speed"), UNKIFNULL2(s->speed_str), - _("Configured Speed"), UNKIFNULL2(s->configured_clock_str), - _("Data Width/Total Width"), UNKIFNULL2(s->data_width), UNKIFNULL2(s->total_width), - _("Minimum Voltage"), UNKIFNULL2(s->voltage_min_str), - _("Maximum Voltage"), UNKIFNULL2(s->voltage_max_str), - _("Configured Voltage"), UNKIFNULL2(s->voltage_conf_str) - ); - - g_free(vendor_str); - g_free(size_str); - } else { - ret = h_strdup_cprintf("[%s %s]\n" - "%s=0x%x, 0x%x\n" - "%s=%s\n" - "%s=%s\n", - ret, - _("Memory Socket"), s->full_locator, - _("DMI Handles (Array, Socket)"), s->array_handle, s->handle, - _("Bank Locator"), UNKIFNULL2(s->bank_locator), - _("Size"), _("(Empty)") - ); - } - } - - no_handles = FALSE; - if(mem->empty) { - no_handles = TRUE; - ret = g_strdup_printf("[%s]\n%s=%s\n" "[$ShellParam$]\nViewType=0\n", - _("Socket Information"), _("Result"), - (getuid() == 0) - ? _("(Not available)") - : _("(Not available; Perhaps try running HardInfo as root.)") ); - } - - dmi_mem_free(mem); return ret; } -gchar *dmi_mem_socket_info_view1() { +gchar *dmi_mem_socket_info() { gchar *ret = g_strdup_printf( "[$ShellParam$]\nViewType=1\n" "ColumnTitle$TextValue=%s\n" /* Locator */ "ColumnTitle$Extra1=%s\n" /* Size */ - "ColumnTitle$Extra2=%s\n" /* Manufacturer */ + "ColumnTitle$Extra2=%s\n" /* Vendor */ "ColumnTitle$Value=%s\n" /* Part */ "ShowColumnHeaders=true\n" "[%s]\n", _("Locator"), _("Size"), - _("Manufacturer"), + _("Vendor"), _("Part"), - _("Memory DMI") + _("Memory Device List") ); GSList *l = NULL; sketchy_info = FALSE; @@ -478,37 +497,42 @@ gchar *dmi_mem_socket_info_view1() { else size_str = g_strdup_printf("%ld %s", s->size_MiB, _("MiB") ); + gchar *spd = s->spd ? make_spd_section(s->spd) : NULL; + gchar *details = g_strdup_printf("[%s]\n" "%s=0x%lx, 0x%lx\n" "%s=%s\n" "%s=%s\n" "%s=%s\n" + "%s=%s / %s\n" "%s=%s%s\n" "%s=%s\n" - "%s=%s / %s\n" "%s=%s\n" "%s=%s\n" "%s=%s\n" "%s=%s / %s\n" "%s=%s\n" "%s=%s\n" - "%s=%s\n", + "%s=%s\n" + "%s", /* spd */ _("Memory Socket"), _("DMI Handles (Array, Socket)"), s->array_handle, s->handle, _("Locator"), s->full_locator, _("Bank Locator"), UNKIFNULL2(s->bank_locator), _("Form Factor"), UNKIFNULL2(s->form_factor), - _("Manufacturer"), UNKIFNULL2(s->mfgr), vendor_str ? vendor_str : "", - _("Part Number"), UNKIFNULL2(s->partno), _("Type"), UNKIFNULL2(s->type), UNKIFNULL2(s->type_detail), + _("Vendor"), UNKIFNULL2(s->mfgr), vendor_str ? vendor_str : "", + _("Part Number"), UNKIFNULL2(s->partno), _("Size"), size_str, _("Rated Speed"), UNKIFNULL2(s->speed_str), _("Configured Speed"), UNKIFNULL2(s->configured_clock_str), _("Data Width/Total Width"), UNKIFNULL2(s->data_width), UNKIFNULL2(s->total_width), _("Minimum Voltage"), UNKIFNULL2(s->voltage_min_str), _("Maximum Voltage"), UNKIFNULL2(s->voltage_max_str), - _("Configured Voltage"), UNKIFNULL2(s->voltage_conf_str) + _("Configured Voltage"), UNKIFNULL2(s->voltage_conf_str), + spd ? spd : "" ); + g_free(spd); moreinfo_add_with_prefix(key_prefix, key, details); /* moreinfo now owns *details */ const gchar *mfgr = s->mfgr ? vendor_get_shortest_name(s->mfgr) : NULL; ret = h_strdup_cprintf("$!%s$%s=%s|%s|%s\n", @@ -538,6 +562,36 @@ gchar *dmi_mem_socket_info_view1() { g_free(key); } + /* Unmatched SPD */ + for(l = mem->spd; l; l = l->next) { + spd_data *s = (spd_data*)l->data; + if (s->claimed_by_dmi) continue; + gchar *key = g_strdup_printf("SPD:%s", s->dev); + gchar *vendor_str = NULL; + if (s->vendor) { + if (s->vendor->url) + vendor_str = g_strdup_printf(" (%s, %s)", + s->vendor->name, s->vendor->url ); + } + gchar *size_str = NULL; + if (!s->size_MiB) + size_str = g_strdup(_("(Unknown)")); + else + size_str = g_strdup_printf("%d %s", s->size_MiB, _("MiB") ); + + gchar *details = make_spd_section(s); + + moreinfo_add_with_prefix(key_prefix, key, details); /* moreinfo now owns *details */ + const gchar *mfgr = s->vendor_str ? vendor_get_shortest_name(s->vendor_str) : NULL; + ret = h_strdup_cprintf("$!%s$%s%s=%s|%s|%s\n", + ret, + key, key, problem_marker(), UNKIFNULL2(s->partno), size_str, UNKIFNULL2(mfgr) + ); + g_free(vendor_str); + g_free(size_str); + g_free(key); + } + no_handles = FALSE; if(mem->empty) { no_handles = TRUE; @@ -552,30 +606,47 @@ gchar *dmi_mem_socket_info_view1() { return ret; } -gchar *dmi_mem_socket_info() { - // alternative shell view types - //return dmi_mem_socket_info_view0(); - return dmi_mem_socket_info_view1(); -} +static gchar *note_state = NULL; gboolean dmi_mem_show_hinote(const char **msg) { - if (no_handles) { - if (getuid() == 0) { - *msg = g_strdup( - _("To view DMI memory information the <b><i>dmidecode</i></b> utility must be\n" - "available.")); - } else { - *msg = g_strdup( - _("To view DMI memory information the <b><i>dmidecode</i></b> utility must be\n" - "available, and HardInfo must be run with superuser privileges.")); - } + + gchar *want_dmi = _(" <b><i>dmidecode</i></b> utility available\n"); + gchar *want_root = _(" ... <i>and</i> HardInfo running with superuser privileges\n"); + gchar *want_eeprom = _(" <b><i>eeprom</i></b> module loaded (for SDR, DDR, DDR2, DDR3)\n"); + gchar *want_ee1004 = _(" ... <i>or</i> <b><i>ee1004</i></b> module loaded <b>and configured!</b> (for DDR4)"); + + gboolean has_root = (getuid() == 0); + gboolean has_dmi = !no_handles; + gboolean has_eeprom = g_file_test("/sys/bus/i2c/drivers/eeprom", G_FILE_TEST_IS_DIR); + gboolean has_ee1004 = g_file_test("/sys/bus/i2c/drivers/ee1004", G_FILE_TEST_IS_DIR); + + char *bullet_yes = "<big><b>\u2713</b></big>"; + char *bullet_no = "<big><b>\u2022<tt> </tt></b></big>"; + + g_free(note_state); + note_state = g_strdup(_("Memory information requires <b>one or both</b> of the following:\n")); + note_state = appf(note_state, "<tt>1. </tt>%s%s", has_dmi ? bullet_yes : bullet_no, want_dmi); + note_state = appf(note_state, "<tt> </tt>%s%s", has_root ? bullet_yes : bullet_no, want_root); + note_state = appf(note_state, "<tt>2. </tt>%s%s", has_eeprom ? bullet_yes : bullet_no, want_eeprom); + note_state = appf(note_state, "<tt> </tt>%s%s", has_ee1004 ? bullet_yes : bullet_no, want_ee1004); + + gboolean best_state = FALSE; + if (has_dmi && has_root && + ((has_eeprom && !spd_ddr4_partial_data) + || has_ee1004) ) + best_state = TRUE; + + if (!best_state) { + *msg = note_state; return TRUE; } + if (sketchy_info) { *msg = g_strdup( _("\"More often than not, information contained in the DMI tables is inaccurate,\n" "incomplete or simply wrong.\" -<i><b>dmidecode</b></i> manual page")); return TRUE; } + return FALSE; } diff --git a/modules/devices/spd-decode.c b/modules/devices/spd-decode2.c index 887ec749..57ceeb9a 100644 --- a/modules/devices/spd-decode.c +++ b/modules/devices/spd-decode2.c @@ -31,6 +31,10 @@ #include "devices.h" #include "hardinfo.h" +gboolean spd_no_driver = FALSE; +gboolean spd_no_support = FALSE; +gboolean spd_ddr4_partial_data = FALSE; + typedef enum { UNKNOWN, DIRECT_RAMBUS, @@ -47,8 +51,6 @@ typedef enum { DDR4_SDRAM } RamType; -char *spd_info = NULL; - static const char *ram_types[] = {"Unknown", "Direct Rambus", "Rambus", "FPM DRAM", "EDO", "Pipelined Nibble", "SDR SDRAM", "Multiplexed ROM", "DDR SGRAM", "DDR SDRAM", "DDR2 SDRAM", "DDR3 SDRAM", @@ -640,7 +642,7 @@ static const char *vendors5[] = {"T-RAM Incorporated", "Excel Semiconductor", "A-DATA Technology", "VirtualDigm", - "G Skill Intl", + "G.Skill Intl", "Quanta Computer", "Yield Microelectronics", "Afa Technologies", @@ -854,9 +856,42 @@ static const char *vendors7[] = {"MOVEKING", static const char **vendors[VENDORS_BANKS] = {vendors1, vendors2, vendors3, vendors4, vendors5, vendors6, vendors7}; -gboolean no_driver = FALSE; -gboolean no_support = FALSE; -gboolean ddr4_partial_data = FALSE; +typedef struct { + unsigned char bytes[512]; + unsigned char dev[32]; /* %1d-%04d\0 */ + int spd_driver; /* 0 = eeprom, 1 = ee1004 */ + int spd_size; + + RamType type; + + int vendor_bank; + int vendor_index; + const char *vendor_str; + const Vendor *vendor; + + char partno[32]; + const char *form_factor; + char type_detail[256]; + + int size_MiB; + + int spd_rev_major; // bytes[1] >> 4 + int spd_rev_minor; // bytes[1] & 0xf + + gboolean ddr4_no_ee1004; + gboolean claimed_by_dmi; +} spd_data; + +spd_data *spd_data_new() { + spd_data *s = g_new0(spd_data, 1); + return s; +} + +void spd_data_free(spd_data *s) { + if (s) { + g_free(s); + } +} /* * We consider that no data was written to this area of the SPD EEPROM if @@ -919,7 +954,7 @@ static void decode_sdr_module_row_address_bits(unsigned char *bytes, char **bits case 3: temp = "3/18"; break; default: /* printf("%d\n", bytes[3]); */ - temp = "Unknown"; + temp = NULL; } if (bits) { *bits = temp; } @@ -935,7 +970,7 @@ static void decode_sdr_module_col_address_bits(unsigned char *bytes, char **bits case 3: temp = "3/18"; break; default: /*printf("%d\n", bytes[4]); */ - temp = "Unknown"; + temp = NULL; } if (bits) { *bits = temp; } @@ -965,7 +1000,7 @@ static void decode_sdr_module_interface_signal_levels(unsigned char *bytes, char case 3: temp = "SSTL 3.3"; break; case 4: temp = "SSTL 2.5"; break; case 255: temp = "New Table"; break; - default: temp = "Undefined"; + default: temp = NULL; } if (signal_levels) { *signal_levels = temp; } @@ -978,7 +1013,7 @@ static void decode_sdr_module_configuration_type(unsigned char *bytes, char **mo case 0: temp = "No parity"; break; case 1: temp = "Parity"; break; case 2: temp = "ECC"; break; - default: temp = "Undefined"; + default: temp = NULL; } if (module_config_type) { *module_config_type = temp; } @@ -1006,19 +1041,24 @@ static void decode_sdr_module_refresh_rate(unsigned char *bytes, char **refresh_ case 3: temp = "Extended (31.3us)"; break; case 4: temp = "Extended (62.5us)"; break; case 5: temp = "Extended (125us)"; break; - default: temp = "Undefined"; + default: temp = NULL; } if (refresh_rate) { *refresh_rate = temp; } } -static gchar *decode_sdr_sdram(unsigned char *bytes, int *size) { +static void decode_sdr_module_detail(unsigned char *bytes, char *type_detail) { + if (type_detail) { + snprintf(type_detail, 255, "SDR"); + } +} + +static gchar *decode_sdr_sdram_extra(unsigned char *bytes) { int rows, data_width; float tcl, trcd, trp, tras; char *row_address_bits, *col_address_bits, *signal_level; char *module_config_type, *refresh_type, *refresh_rate; - decode_sdr_module_size(bytes, size); decode_sdr_module_timings(bytes, &tcl, &trcd, &trp, &tras); decode_sdr_module_row_address_bits(bytes, &row_address_bits); decode_sdr_module_col_address_bits(bytes, &col_address_bits); @@ -1041,24 +1081,27 @@ static gchar *decode_sdr_sdram(unsigned char *bytes, int *size) { - Other misc stuff */ - return g_strdup_printf("[Module Information]\n" - "Module type=SDR\n" - "SPD revision=%d\n" - "Row address bits=%s\n" - "Column address bits=%s\n" - "Number of rows=%d\n" - "Data width=%d bits\n" - "Interface signal levels=%s\n" - "Configuration type=%s\n" - "Refresh=%s (%s)\n" - "[Timings]\n" + /* expected to continue an [SPD] section */ + return g_strdup_printf("%s=%s\n" + "%s=%s\n" + "%s=%d\n" + "%s=%d bits\n" + "%s=%s\n" + "%s=%s\n" + "%s=%s (%s)\n" + "[%s]\n" "tCL=%.2f\n" "tRCD=%.2f\n" "tRP=%.2f\n" "tRAS=%.2f\n", - bytes[62], row_address_bits, col_address_bits, rows, data_width, - signal_level, module_config_type, refresh_type, refresh_rate, tcl, trcd, - trp, tras); + _("Row address bits"), row_address_bits ? row_address_bits : _("(Unknown)"), + _("Column address bits"), col_address_bits ? col_address_bits : _("(Unknown)"), + _("Number of rows"), rows, + _("Data width"), data_width, + _("Interface signal levels"), signal_level ? signal_level : _("(Unknown)"), + _("Configuration type"), module_config_type ? module_config_type : _("(Unknown)"), + _("Refresh"), refresh_type, refresh_rate ? refresh_rate : _("Unknown"), + _("Timings"), tcl, trcd, trp, tras); } static void decode_ddr_module_speed(unsigned char *bytes, float *ddrclk, int *pcclk) { @@ -1123,25 +1166,26 @@ static void decode_ddr_module_timings(unsigned char *bytes, float *tcl, float *t if (tcl) { *tcl = highest_cas; } } -static gchar *decode_ddr_sdram(unsigned char *bytes, int *size) { +static void decode_ddr_module_detail(unsigned char *bytes, char *type_detail) { float ddr_clock; - float tcl, trcd, trp, tras; int pc_speed; + if (type_detail) { + decode_ddr_module_speed(bytes, &ddr_clock, &pc_speed); + snprintf(type_detail, 255, "DDR-%.0f (PC-%d)", ddr_clock, pc_speed); + } +} + +static gchar *decode_ddr_sdram_extra(unsigned char *bytes) { + float tcl, trcd, trp, tras; - decode_ddr_module_speed(bytes, &ddr_clock, &pc_speed); - decode_ddr_module_size(bytes, size); decode_ddr_module_timings(bytes, &tcl, &trcd, &trp, &tras); - return g_strdup_printf("[Module Information]\n" - "Module type=DDR %.2fMHz (PC%d)\n" - "SPD revision=%d.%d\n" - "[Timings]\n" + return g_strdup_printf("[%s]\n" "tCL=%.2f\n" "tRCD=%.2f\n" "tRP=%.2f\n" "tRAS=%.2f\n", - ddr_clock, pc_speed, bytes[62] >> 4, bytes[62] & 0xf, tcl, trcd, trp, - tras); + _("Timings"), tcl, trcd, trp, tras); } static float decode_ddr2_module_ctime(unsigned char byte) { @@ -1217,25 +1261,26 @@ static void decode_ddr2_module_timings(unsigned char *bytes, float *trcd, float if (tcl) { *tcl = highest_cas; } } -static gchar *decode_ddr2_sdram(unsigned char *bytes, int *size) { +static void decode_ddr2_module_detail(unsigned char *bytes, char *type_detail) { float ddr_clock; - float trcd, trp, tras, tcl; int pc2_speed; + if (type_detail) { + decode_ddr2_module_speed(bytes, &ddr_clock, &pc2_speed); + snprintf(type_detail, 255, "DDR2-%.0f (PC2-%d)", ddr_clock, pc2_speed); + } +} + +static gchar *decode_ddr2_sdram_extra(unsigned char *bytes) { + float trcd, trp, tras, tcl; - decode_ddr2_module_speed(bytes, &ddr_clock, &pc2_speed); - decode_ddr2_module_size(bytes, size); decode_ddr2_module_timings(bytes, &trcd, &trp, &tras, &tcl); - return g_strdup_printf("[Module Information]\n" - "Module type=DDR2 %.2f MHz (PC2-%d)\n" - "SPD revision=%d.%d\n" - "[Timings]\n" + return g_strdup_printf("[%s]\n" "tCL=%.2f\n" "tRCD=%.2f\n" "tRP=%.2f\n" "tRAS=%.2f\n", - ddr_clock, pc2_speed, bytes[62] >> 4, bytes[62] & 0xf, tcl, trcd, trp, - tras); + _("Timings"), tcl, trcd, trp, tras); } static void decode_ddr3_module_speed(unsigned char *bytes, float *ddr_clock, int *pc3_speed) { @@ -1296,36 +1341,34 @@ static void decode_ddr3_module_timings(unsigned char *bytes, float *trcd, float static void decode_ddr3_module_type(unsigned char *bytes, const char **type) { switch (bytes[3]) { - case 0x00: *type = "Undefined"; break; case 0x01: *type = "RDIMM (Registered Long DIMM)"; break; case 0x02: *type = "UDIMM (Unbuffered Long DIMM)"; break; case 0x03: *type = "SODIMM (Small Outline DIMM)"; break; - default: *type = "Unknown"; + default: *type = NULL; } } -static gchar *decode_ddr3_sdram(unsigned char *bytes, int *size) { +static void decode_ddr3_module_detail(unsigned char *bytes, char *type_detail) { float ddr_clock; - float trcd, trp, tras, tcl; int pc3_speed; - const char *type; + if (type_detail) { + decode_ddr3_module_speed(bytes, &ddr_clock, &pc3_speed); + snprintf(type_detail, 255, "DDR3-%.0f (PC3-%d)", ddr_clock, pc3_speed); + } +} + +static gchar *decode_ddr3_sdram_extra(unsigned char *bytes) { + float trcd, trp, tras, tcl; - decode_ddr3_module_speed(bytes, &ddr_clock, &pc3_speed); - decode_ddr3_module_size(bytes, size); decode_ddr3_module_timings(bytes, &trcd, &trp, &tras, &tcl); - decode_ddr3_module_type(bytes, &type); - return g_strdup_printf("[Module Information]\n" - "Module type=DDR3 %.2f MHz (PC3-%d)\n" - "SPD revision=%d.%d\n" - "Type=%s\n" - "[Timings]\n" + return g_strdup_printf("[%s]\n" "tCL=%.2f\n" "tRCD=%.3fns\n" "tRP=%.3fns\n" "tRAS=%.3fns\n", - ddr_clock, pc3_speed, bytes[1] >> 4, bytes[1] & 0xf, type, tcl, trcd, - trp, tras); + _("Timings"), tcl, trcd, trp, tras + ); } static void decode_ddr3_part_number(unsigned char *bytes, char *part_number) { @@ -1422,7 +1465,7 @@ static void decode_ddr4_module_type(unsigned char *bytes, const char **type) { case 0x09: *type = "72b-SO-UDIMM (Small Outline Unbuffered DIMM, 72-bit data bus)"; break; case 0x0c: *type = "16b-SO-UDIMM (Small Outline Unbuffered DIMM, 16-bit data bus)"; break; case 0x0d: *type = "32b-SO-UDIMM (Small Outline Unbuffered DIMM, 32-bit data bus)"; break; - default: *type = _("Unknown"); + default: *type = NULL; } } @@ -1502,13 +1545,13 @@ static void decode_ddr4_module_size(unsigned char *bytes, int *size) { static void decode_ddr4_module_date(unsigned char *bytes, int spd_size, char **str) { if (spd_size < 324) { - *str = g_strdup(_("Unknown (Missing data)")); + *str = NULL; return; } if (bytes[323] == 0x0 || bytes[323] == 0xffff || bytes[324] == 0x0 || bytes[324] == 0xffff) { - *str = g_strdup(_("Unknown")); + *str = NULL; return; } @@ -1519,7 +1562,7 @@ static void decode_ddr4_module_date(unsigned char *bytes, int spd_size, char **s static void decode_ddr4_dram_manufacturer(unsigned char *bytes, int spd_size, const char **manufacturer) { if (spd_size < 351) { - *manufacturer = _("Unknown (Missing data)"); + *manufacturer = NULL; return; } @@ -1567,50 +1610,53 @@ static void decode_ddr4_xmp(unsigned char *bytes, int spd_size, char **str) { print_spd_timings((int) ddrclk, ceil(taa/ctime - 0.025), trcd, trp, tras, ctime)); } +static void decode_ddr4_module_detail(unsigned char *bytes, char *type_detail) { + float ddr_clock; + int pc4_speed; + if (type_detail) { + decode_ddr4_module_speed(bytes, &ddr_clock, &pc4_speed); + snprintf(type_detail, 255, "DDR4-%.0f (PC4-%d)", ddr_clock, pc4_speed); + } +} -static gchar *decode_ddr4_sdram(unsigned char *bytes, int spd_size, int *size) { +static gchar *decode_ddr4_sdram_extra(unsigned char *bytes, int spd_size) { float ddr_clock; int pc4_speed, xmp_majv = -1, xmp_minv = -1; - const char *type, *dram_manf; + const char *dram_manf; char *speed_timings = NULL, *xmp_profile = NULL, *xmp = NULL, *manf_date = NULL; static gchar *out; decode_ddr4_module_speed(bytes, &ddr_clock, &pc4_speed); - decode_ddr4_module_size(bytes, size); - decode_ddr4_module_type(bytes, &type); decode_ddr4_module_spd_timings(bytes, ddr_clock, &speed_timings); decode_ddr4_module_date(bytes, spd_size, &manf_date); - decode_ddr4_dram_manufacturer(bytes, spd_size, &dram_manf); detect_ddr4_xmp(bytes, spd_size, &xmp_majv, &xmp_minv); + decode_ddr4_dram_manufacturer(bytes, spd_size, &dram_manf); if (xmp_majv == -1 && xmp_minv == -1) { - xmp = g_strdup(_("unknown")); + xmp = NULL; } else if (xmp_majv <= 0 && xmp_minv <= 0) { - xmp = g_strdup(_("no")); + xmp = g_strdup(_("No")); } else { - xmp = g_strdup_printf("%s (revision %d.%d)", _("yes"), xmp_majv, xmp_minv); + xmp = g_strdup_printf("%s (revision %d.%d)", _("Yes"), xmp_majv, xmp_minv); if (xmp_majv == 2 && xmp_minv == 0) decode_ddr4_xmp(bytes, spd_size, &xmp_profile); } - out = g_strdup_printf("[%s]\n" - "%s=DDR4 %.0f MHz (PC4-%d)\n" - "%s=%d.%d\n" - "%s=%s\n" - "%s=%s\n" + /* expected to continue an [SPD] section */ + out = g_strdup_printf("%s=%s\n" "%s=%s\n" "%s=%s\n" "%s=%s\n" "[%s]\n" "%s\n" "%s", - _("Module Information"), _("Module type"), ddr_clock, pc4_speed, - _("SPD revision"), bytes[1] >> 4, bytes[1] & 0xf, _("Type"), type, - _("Voltage"), bytes[11] & 0x01 ? "1.2 V": _("Unknown"), - _("Manufacturing Date"), manf_date, _("DRAM Manufacturer"), dram_manf, - _("XMP"), xmp, _("JEDEC Timings"), speed_timings, + _("Voltage"), bytes[11] & 0x01 ? "1.2 V": _("(Unknown)"), + _("Manufacturing Date"), manf_date ? manf_date : _("(Unknown)"), + _("DRAM Manufacturer"), dram_manf ? dram_manf : _("(Unknown)"), + _("XMP"), xmp ? xmp : _("(Unknown)"), + _("JEDEC Timings"), speed_timings, xmp_profile ? xmp_profile: ""); g_free(speed_timings); @@ -1626,21 +1672,19 @@ static void decode_ddr4_part_number(unsigned char *bytes, int spd_size, char *pa if (!part_number) return; if (spd_size < 348) { - *part_number++ = '?'; - *part_number++ = '?'; - *part_number++ = '?'; *part_number++ = '\0'; return; } - for (i = 329; i <= 348; i++) *part_number++ = bytes[i]; + for (i = 329; i <= 348; i++) + *part_number++ = bytes[i]; *part_number = '\0'; } static void decode_ddr4_module_manufacturer(unsigned char *bytes, int spd_size, char **manufacturer) { if (spd_size < 321) { - *manufacturer = _("Unknown (Missing data)"); + *manufacturer = NULL; return; } @@ -1706,82 +1750,92 @@ static int read_spd(char *spd_path, int offset, size_t size, int use_sysfs, return data_size; } -static gchar *decode_dimms(GSList *dimm_list, gboolean use_sysfs, int max_size) { - GSList *dimm; - GString *output = NULL; - gint count = 0; +static GSList *decode_dimms2(GSList *eeprom_list, gboolean use_sysfs, int max_size) { + GSList *eeprom, *dimm_list = NULL; + int count = 0; int spd_size = 0; - guchar *bytes; + unsigned char bytes[512] = {0}; + spd_data *s = NULL; - bytes = malloc(sizeof(guchar) * max_size); + for (eeprom = eeprom_list; eeprom; eeprom = eeprom->next, count++) { + gchar *spd_path = (gchar*)eeprom->data; + s = NULL; - for (dimm = dimm_list; dimm; dimm = dimm->next, count++) { - gchar *spd_path = (gchar *)dimm->data; - gchar *manufacturer; - gchar *detailed_info; - gchar *moreinfo_key; - gchar part_number[32]; - int module_size; RamType ram_type; - shell_status_pulse(); - + memset(bytes, 0, 512); spd_size = read_spd(spd_path, 0, max_size, use_sysfs, bytes); ram_type = decode_ram_type(bytes); switch (ram_type) { + case SDR_SDRAM: + s = spd_data_new(); + memcpy(s->bytes, bytes, 512); + decode_module_part_number(bytes, s->partno); + decode_module_manufacturer(bytes + 64, (char**)&s->vendor_str); + decode_sdr_module_size(bytes, &s->size_MiB); + decode_sdr_module_detail(bytes, s->type_detail); + break; + case DDR_SDRAM: + s = spd_data_new(); + memcpy(s->bytes, bytes, 512); + decode_module_part_number(bytes, s->partno); + decode_module_manufacturer(bytes + 64, (char**)&s->vendor_str); + decode_ddr_module_size(bytes, &s->size_MiB); + decode_ddr_module_detail(bytes, s->type_detail); + break; case DDR2_SDRAM: - detailed_info = decode_ddr2_sdram(bytes, &module_size); - decode_module_part_number(bytes, part_number); - decode_module_manufacturer(bytes + 64, &manufacturer); + s = spd_data_new(); + memcpy(s->bytes, bytes, 512); + decode_module_part_number(bytes, s->partno); + decode_module_manufacturer(bytes + 64, (char**)&s->vendor_str); + decode_ddr2_module_size(bytes, &s->size_MiB); + decode_ddr2_module_detail(bytes, s->type_detail); break; case DDR3_SDRAM: - detailed_info = decode_ddr3_sdram(bytes, &module_size); - decode_ddr3_part_number(bytes, part_number); - decode_ddr3_manufacturer(bytes, &manufacturer); + s = spd_data_new(); + memcpy(s->bytes, bytes, 512); + decode_ddr3_part_number(bytes, s->partno); + decode_ddr3_manufacturer(bytes, (char**)&s->vendor_str); + decode_ddr3_module_size(bytes, &s->size_MiB); + decode_ddr3_module_type(bytes, &s->form_factor); + decode_ddr3_module_detail(bytes, s->type_detail); break; case DDR4_SDRAM: - detailed_info = decode_ddr4_sdram(bytes, spd_size, &module_size); - decode_ddr4_part_number(bytes, spd_size, part_number); - decode_ddr4_module_manufacturer(bytes, spd_size, &manufacturer); - ddr4_partial_data = ddr4_partial_data || (spd_size < 512); - break; - case DDR_SDRAM: - detailed_info = decode_ddr_sdram(bytes, &module_size); - decode_module_part_number(bytes, part_number); - decode_module_manufacturer(bytes + 64, &manufacturer); + s = spd_data_new(); + memcpy(s->bytes, bytes, 512); + decode_ddr4_part_number(bytes, spd_size, s->partno); + decode_ddr4_module_manufacturer(bytes, spd_size, (char**)&s->vendor_str); + decode_ddr4_module_size(bytes, &s->size_MiB); + decode_ddr4_module_type(bytes, &s->form_factor); + decode_ddr4_module_detail(bytes, s->type_detail); + s->ddr4_no_ee1004 = s->ddr4_no_ee1004 || (spd_size < 512); + spd_ddr4_partial_data = spd_ddr4_partial_data || s->ddr4_no_ee1004; break; - case SDR_SDRAM: - detailed_info = decode_sdr_sdram(bytes, &module_size); - decode_module_part_number(bytes, part_number); - decode_module_manufacturer(bytes + 64, &manufacturer); - break; - default: DEBUG("Unsupported EEPROM type: %s\n", ram_types[ram_type]); continue; + default: DEBUG("Unsupported EEPROM type: %s for %s\n", ram_types[ram_type], spd_path); continue; } - if (detailed_info) { - gchar *more_detailed_info = g_strdup_printf("%s[%s]\n%s=%s\n", - detailed_info, _("Source"), _("Path"), spd_path); - gchar *key = g_strdup_printf("MEM%d", count); - moreinfo_add_with_prefix("DEV", key, more_detailed_info); /* moreinfo now owns *more_detailed_info */ - g_free(key); + if (s) { + strncpy(s->dev, g_basename(spd_path), 31); + if (strstr(spd_path, "ee1004")) + s->spd_driver = 1; + s->spd_size = spd_size; + s->type = ram_type; + if (ram_type == SDR_SDRAM) { + /* SDR */ + s->spd_rev_major = 0; + s->spd_rev_minor = bytes[62]; + } else { + /* DDR, DDR2, DDR3, DDR4 */ + s->spd_rev_major = bytes[1] >> 4; + s->spd_rev_minor = bytes[1] & 0xf; + } + dimm_list = g_slist_append(dimm_list, s); + s->vendor = vendor_match(s->vendor_str, NULL); } - - if (!output) - output = g_string_new(""); - - g_string_append_printf(output, "$!MEM%d$%d=%s|%d MB|%s\n", count, count, part_number, - module_size, manufacturer); - - g_free(spd_path); - g_free(detailed_info); } - g_free(bytes); - if (!output) - return NULL; - - return g_string_free(output, FALSE); + return dimm_list; } struct SpdDriver { @@ -1797,17 +1851,16 @@ static const struct SpdDriver spd_drivers[] = { { NULL } }; -void scan_spd_do(void) { +GSList *spd_scan() { GDir *dir = NULL; - GSList *dimm_list = NULL; - void *dimm_list_entry; - gchar *dir_entry, *list = NULL; + GSList *eeprom_list = NULL, *dimm_list = NULL; + gchar *dimm_list_entry, *dir_entry, *list = NULL; const struct SpdDriver *driver; gboolean driver_found = FALSE; - ddr4_partial_data = FALSE; - no_driver = FALSE; - no_support = FALSE; + spd_ddr4_partial_data = FALSE; + spd_no_driver = FALSE; + spd_no_support = FALSE; for (driver = spd_drivers; driver->dir_path; driver++) { if (g_file_test(driver->dir_path, G_FILE_TEST_EXISTS)) { @@ -1820,71 +1873,28 @@ void scan_spd_do(void) { g_str_has_prefix(dir_entry, "eeprom-")) { dimm_list_entry = g_strdup_printf("%s/%s", driver->dir_path, dir_entry); - dimm_list = g_slist_prepend(dimm_list, dimm_list_entry); + eeprom_list = g_slist_prepend(eeprom_list, dimm_list_entry); } } g_dir_close(dir); - if (dimm_list) { - list = decode_dimms(dimm_list, driver->use_sysfs, driver->max_size); - g_slist_free(dimm_list); - dimm_list = NULL; + if (eeprom_list) { + dimm_list = decode_dimms2(eeprom_list, driver->use_sysfs, driver->max_size); + g_slist_free(eeprom_list); + eeprom_list = NULL; } - if (list) break; + if (dimm_list) break; } } if (!driver_found) { - g_free(spd_info); if (!g_file_test("/sys/module/eeprom", G_FILE_TEST_EXISTS)) { - no_driver = TRUE; /* trigger hinote for no eeprom driver */ - spd_info = - g_strdup("[$ShellParam$]\n" - "ViewType=0\n" - "ReloadInterval=500\n"); + spd_no_driver = TRUE; /* trigger hinote for no eeprom driver */ } else { - no_support = TRUE; /* trigger hinote for unsupported system */ - spd_info = - g_strdup("[$ShellParam$]\n" - "ViewType=0\n" - "ReloadInterval=500\n"); + spd_no_support = TRUE; /* trigger hinote for unsupported system */ } - - return; - } - - g_free(spd_info); - spd_info = g_strdup_printf("[%s]\n" - "%s\n" - "[$ShellParam$]\n" - "ViewType=1\n" - "ColumnTitle$TextValue=%s\n" /* Bank */ - "ColumnTitle$Extra1=%s\n" /* Size */ - "ColumnTitle$Extra2=%s\n" /* Manufacturer */ - "ColumnTitle$Value=%s\n" /* Model */ - "ShowColumnHeaders=true\n", - _("SPD"), list, _("Bank"), _("Size"), _("Manufacturer"), _("Model")); - g_free(list); -} - -gboolean spd_decode_show_hinote(const char **msg) { - if (ddr4_partial_data) { - *msg = g_strdup( - _("A current driver has provided only partial DDR4 SPD data. Please load and\n" - "configure ee1004 driver to obtain additional information about DDR4 SPD.")); - return TRUE; - } - if (no_driver) { - *msg = g_strdup( - _("Please load the eeprom module to obtain information about memory SPD.")); - return TRUE; - } - if (no_support) { - *msg = g_strdup( - _("Reading memory SPD not supported on this system.")); - return TRUE; } - return FALSE; + return dimm_list; } |