aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--includes/devices.h1
-rw-r--r--modules/devices.c24
-rw-r--r--modules/devices/dmi_memory.c351
-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;
}