aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2024-04-22 00:35:53 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2024-04-22 00:35:53 -0300
commit5f01c706267c595de92406a32e7f31ef5056c2d0 (patch)
treed1e74ef54efc41ada622900fe3e2a50dee44a237 /modules
parent09fcc751ef158898c315ebc9299a0fa3a722d914 (diff)
New upstream version 2.0.3preupstream/2.0.3pre
Diffstat (limited to 'modules')
-rw-r--r--modules/benchmark.c938
-rw-r--r--modules/benchmark/bench_results.c637
-rw-r--r--modules/benchmark/bench_util.c58
-rw-r--r--modules/benchmark/benches.c220
-rw-r--r--modules/benchmark/blowfish.c45
-rw-r--r--modules/benchmark/blowfish2.c83
-rw-r--r--modules/benchmark/cryptohash.c49
-rw-r--r--modules/benchmark/drawing.c4
-rw-r--r--modules/benchmark/fbench.c26
-rw-r--r--modules/benchmark/fft.c41
-rw-r--r--modules/benchmark/fftbench.c6
-rw-r--r--modules/benchmark/fib.c35
-rw-r--r--modules/benchmark/guibench.c6
-rw-r--r--modules/benchmark/nqueens.c41
-rw-r--r--modules/benchmark/raytrace.c28
-rw-r--r--modules/benchmark/sha1.c2
-rw-r--r--modules/benchmark/sysbench.c270
-rw-r--r--modules/benchmark/zlib.c63
-rw-r--r--modules/computer.c490
-rw-r--r--modules/computer/alsa.c4
-rw-r--r--modules/computer/boots.c8
-rw-r--r--modules/computer/display.c169
-rw-r--r--modules/computer/environment.c4
-rw-r--r--modules/computer/filesystem.c13
-rw-r--r--modules/computer/groups.c4
-rw-r--r--modules/computer/languages.c262
-rw-r--r--modules/computer/loadavg.c4
-rw-r--r--modules/computer/memory.c4
-rw-r--r--modules/computer/memory_usage.c (renamed from modules/devices/devmemory.c)11
-rw-r--r--modules/computer/modules.c471
-rw-r--r--modules/computer/os.c249
-rw-r--r--modules/computer/ubuntu_flavors.c90
-rw-r--r--modules/computer/uptime.c4
-rw-r--r--modules/computer/users.c4
-rw-r--r--modules/devices.c567
-rw-r--r--modules/devices/alpha/processor.c4
-rw-r--r--modules/devices/arm/arm_data.c112
-rw-r--r--modules/devices/arm/arm_data.h5
-rw-r--r--modules/devices/arm/processor.c52
-rw-r--r--modules/devices/battery.c23
-rw-r--r--modules/devices/devicetree.c43
-rw-r--r--modules/devices/devicetree/pmac_data.c4
-rw-r--r--modules/devices/devicetree/rpi_data.c89
-rw-r--r--modules/devices/dmi.c156
-rw-r--r--modules/devices/dmi_memory.c1050
-rw-r--r--modules/devices/e2k/processor.c420
-rw-r--r--modules/devices/firmware.c261
-rw-r--r--modules/devices/gpu.c291
-rw-r--r--modules/devices/ia64/processor.c4
-rw-r--r--modules/devices/inputdevices.c199
-rw-r--r--modules/devices/loongarch64/processor.c90
-rw-r--r--modules/devices/m68k/processor.c4
-rw-r--r--modules/devices/mips/processor.c4
-rw-r--r--modules/devices/monitors.c515
-rw-r--r--modules/devices/parisc/processor.c4
-rw-r--r--modules/devices/pci.c384
-rw-r--r--modules/devices/ppc/processor.c4
-rw-r--r--modules/devices/printers.c70
-rw-r--r--modules/devices/resources.c30
-rw-r--r--modules/devices/riscv/processor.c4
-rw-r--r--modules/devices/riscv/riscv_data.c2
-rw-r--r--modules/devices/s390/processor.c4
-rw-r--r--modules/devices/sensors.c503
-rw-r--r--modules/devices/sh/processor.c4
-rw-r--r--modules/devices/sparc/processor.c4
-rw-r--r--modules/devices/spd-decode.c2064
-rw-r--r--modules/devices/spd-vendors.c292
-rw-r--r--modules/devices/storage.c509
-rw-r--r--modules/devices/usb.c542
-rw-r--r--modules/devices/x86/processor.c108
-rw-r--r--modules/devices/x86/x86_data.c88
-rw-r--r--modules/network.c32
-rw-r--r--modules/network/net.c6
-rw-r--r--modules/network/nfs.c4
-rw-r--r--modules/network/samba.c11
75 files changed, 9130 insertions, 3775 deletions
diff --git a/modules/benchmark.c b/modules/benchmark.c
index 26de9557..018e30fe 100644
--- a/modules/benchmark.c
+++ b/modules/benchmark.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2009 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2009 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,48 +16,84 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _GNU_SOURCE
+#include <config.h>
#include <hardinfo.h>
#include <iconcache.h>
#include <shell.h>
-#include <config.h>
#include <syncmanager.h>
-#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/time.h>
-#include <sys/types.h>
#include <signal.h>
+#include <sys/types.h>
+#include "appf.h"
#include "benchmark.h"
+#include "cpu_util.h"
#include "benchmark/bench_results.c"
bench_value bench_results[BENCHMARK_N_ENTRIES];
static void do_benchmark(void (*benchmark_function)(void), int entry);
-static gchar *benchmark_include_results_reverse(bench_value result, const gchar * benchmark);
-static gchar *benchmark_include_results(bench_value result, const gchar * benchmark);
+static gchar *benchmark_include_results_reverse(bench_value result,
+ const gchar *benchmark);
+static gchar *benchmark_include_results(bench_value result,
+ const gchar *benchmark);
/* ModuleEntry entries, scan_*(), callback_*(), etc. */
#include "benchmark/benches.c"
-static gboolean sending_benchmark_results = FALSE;
-
-char *bench_value_to_str(bench_value r) {
- return g_strdup_printf("%lf; %lf; %d", r.result, r.elapsed_time, r.threads_used);
+char *bench_value_to_str(bench_value r)
+{
+ gboolean has_rev = r.revision >= 0;
+ gboolean has_extra = r.extra && *r.extra != 0;
+ gboolean has_user_note = r.user_note && *r.user_note != 0;
+ char *ret = g_strdup_printf("%lf; %lf; %d", r.result, r.elapsed_time,
+ r.threads_used);
+ if (has_rev || has_extra || has_user_note)
+ ret = appf(ret, "; ", "%d", r.revision);
+ if (has_extra || has_user_note)
+ ret = appf(ret, "; ", "%s", r.extra);
+ if (has_user_note)
+ ret = appf(ret, "; ", "%s", r.user_note);
+ return ret;
}
-bench_value bench_value_from_str(const char* str) {
+bench_value bench_value_from_str(const char *str)
+{
bench_value ret = EMPTY_BENCH_VALUE;
- double r, e;
- int t, c;
+ char rstr[32] = "", estr[32] = "", *p;
+ int t, c, v;
+ char extra[256], user_note[256];
if (str) {
- c = sscanf(str, "%lf; %lf; %d", &r, &e, &t);
+ /* try to handle floats from locales that use ',' or '.' as decimal sep
+ */
+ c = sscanf(
+ str, "%[-+0-9.,]; %[-+0-9.,]; %d; %d; %255[^\r\n;|]; %255[^\r\n;|]",
+ rstr, estr, &t, &v, extra, user_note);
if (c >= 3) {
- ret.result = r;
- ret.elapsed_time = e;
+ if ((p = strchr(rstr, ','))) {
+ *p = '.';
+ }
+ if ((p = strchr(estr, ','))) {
+ *p = '.';
+ }
+ ret.result = g_ascii_strtod(rstr, NULL);
+ ret.elapsed_time = g_ascii_strtod(estr, NULL);
ret.threads_used = t;
}
+ if (c >= 4) {
+ ret.revision = v;
+ }
+ if (c >= 5) {
+ strcpy(ret.extra, extra);
+ }
+ if (c >= 6) {
+ strcpy(ret.user_note, user_note);
+ }
}
return ret;
}
@@ -65,46 +101,51 @@ bench_value bench_value_from_str(const char* str) {
typedef struct _ParallelBenchTask ParallelBenchTask;
struct _ParallelBenchTask {
- gint thread_number;
- guint start, end;
- gpointer data, callback;
+ gint thread_number;
+ guint start, end;
+ gpointer data, callback;
int *stop;
};
static gpointer benchmark_crunch_for_dispatcher(gpointer data)
{
- ParallelBenchTask *pbt = (ParallelBenchTask *)data;
+ ParallelBenchTask *pbt = (ParallelBenchTask *)data;
gpointer (*callback)(void *data, gint thread_number);
- gpointer return_value = g_malloc(sizeof(int));
+ gpointer return_value = g_malloc(sizeof(double));
int count = 0;
if ((callback = pbt->callback)) {
- while(!*pbt->stop) {
+ while (!*pbt->stop) {
callback(pbt->data, pbt->thread_number);
/* don't count if didn't finish in time */
if (!*pbt->stop)
count++;
}
} else {
- DEBUG("this is thread %p; callback is NULL and it should't be!", g_thread_self());
+ DEBUG("this is thread %p; callback is NULL and it should't be!",
+ g_thread_self());
}
g_free(pbt);
- *(double*)return_value = (double)count;
+ *(double *)return_value = (double)count;
return return_value;
}
-bench_value benchmark_crunch_for(float seconds, gint n_threads,
- gpointer callback, gpointer callback_data) {
- int cpu_procs, cpu_cores, cpu_threads, thread_number, stop = 0;
+bench_value benchmark_crunch_for(float seconds,
+ gint n_threads,
+ gpointer callback,
+ gpointer callback_data)
+{
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+ int thread_number, stop = 0;
GSList *threads = NULL, *t;
GTimer *timer;
bench_value ret = EMPTY_BENCH_VALUE;
timer = g_timer_new();
- cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads);
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
if (n_threads > 0)
ret.threads_used = n_threads;
else if (n_threads < 0)
@@ -120,19 +161,22 @@ bench_value benchmark_crunch_for(float seconds, gint n_threads,
DEBUG("launching thread %d", thread_number);
pbt->thread_number = thread_number;
- pbt->data = callback_data;
+ pbt->data = callback_data;
pbt->callback = callback;
pbt->stop = &stop;
- thread = g_thread_new("dispatcher",
- (GThreadFunc)benchmark_crunch_for_dispatcher, pbt);
+#if GLIB_CHECK_VERSION(2,32,0)
+ thread = g_thread_new("dispatcher", (GThreadFunc)benchmark_crunch_for_dispatcher, pbt);
+#else
+ thread = g_thread_create((GThreadFunc)benchmark_crunch_for_dispatcher, pbt,TRUE,NULL);
+#endif
threads = g_slist_prepend(threads, thread);
DEBUG("thread %d launched as context %p", thread_number, thread);
}
/* wait for time */
- //while ( g_timer_elapsed(timer, NULL) < seconds ) { }
+ // while ( g_timer_elapsed(timer, NULL) < seconds ) { }
g_usleep(seconds * 1000000);
/* signal all threads to stop */
@@ -144,7 +188,7 @@ bench_value benchmark_crunch_for(float seconds, gint n_threads,
for (t = threads; t; t = t->next) {
DEBUG("waiting for thread with context %p", t->data);
gpointer *rv = g_thread_join((GThread *)t->data);
- ret.result += *(double*)rv;
+ ret.result += *(double *)rv;
g_free(rv);
}
@@ -158,17 +202,21 @@ bench_value benchmark_crunch_for(float seconds, gint n_threads,
static gpointer benchmark_parallel_for_dispatcher(gpointer data)
{
- ParallelBenchTask *pbt = (ParallelBenchTask *)data;
- gpointer (*callback)(unsigned int start, unsigned int end, void *data, gint thread_number);
- gpointer return_value = NULL;
+ ParallelBenchTask *pbt = (ParallelBenchTask *)data;
+ gpointer (*callback)(unsigned int start, unsigned int end, void *data,
+ gint thread_number);
+ gpointer return_value = NULL;
if ((callback = pbt->callback)) {
DEBUG("this is thread %p; items %d -> %d, data %p", g_thread_self(),
pbt->start, pbt->end, pbt->data);
- return_value = callback(pbt->start, pbt->end, pbt->data, pbt->thread_number);
- DEBUG("this is thread %p; return value is %p", g_thread_self(), return_value);
+ return_value =
+ callback(pbt->start, pbt->end, pbt->data, pbt->thread_number);
+ DEBUG("this is thread %p; return value is %p", g_thread_self(),
+ return_value);
} else {
- DEBUG("this is thread %p; callback is NULL and it should't be!", g_thread_self());
+ DEBUG("this is thread %p; callback is NULL and it should't be!",
+ g_thread_self());
}
g_free(pbt);
@@ -177,31 +225,43 @@ static gpointer benchmark_parallel_for_dispatcher(gpointer data)
}
/* one call for each thread to be used */
-bench_value benchmark_parallel(gint n_threads, gpointer callback, gpointer callback_data) {
- int cpu_procs, cpu_cores, cpu_threads;
- cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads);
- if (n_threads == 0) n_threads = cpu_threads;
- else if (n_threads == -1) n_threads = cpu_cores;
- return benchmark_parallel_for(n_threads, 0, n_threads, callback, callback_data);
+bench_value
+benchmark_parallel(gint n_threads, gpointer callback, gpointer callback_data)
+{
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
+
+ if (n_threads == 0)
+ n_threads = cpu_threads;
+ else if (n_threads == -1)
+ n_threads = cpu_cores;
+
+ return benchmark_parallel_for(n_threads, 0, n_threads, callback,
+ callback_data);
}
/* Note:
* benchmark_parallel_for(): element [start] included, but [end] is excluded.
- * callback(): expected to processes elements [start] through [end] inclusive.
+ * callback(): expected to processes elements [start] through [end]
+ * inclusive.
*/
-bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
- gpointer callback, gpointer callback_data) {
- gchar *temp;
- int cpu_procs, cpu_cores, cpu_threads;
- guint iter_per_thread, iter, thread_number = 0;
- GSList *threads = NULL, *t;
- GTimer *timer;
+bench_value benchmark_parallel_for(gint n_threads,
+ guint start,
+ guint end,
+ gpointer callback,
+ gpointer callback_data)
+{
+ gchar *temp;
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+ guint iter_per_thread, iter, thread_number = 0;
+ GSList *threads = NULL, *t;
+ GTimer *timer;
bench_value ret = EMPTY_BENCH_VALUE;
timer = g_timer_new();
- cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads);
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
if (n_threads > 0)
ret.threads_used = n_threads;
@@ -214,18 +274,19 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
iter_per_thread = (end - start) / ret.threads_used;
if (iter_per_thread == 0) {
- DEBUG("not enough items per thread; disabling one thread");
- ret.threads_used--;
+ DEBUG("not enough items per thread; disabling one thread");
+ ret.threads_used--;
} else {
- break;
+ break;
}
}
- DEBUG("Using %d threads across %d logical processors; processing %d elements (%d per thread)",
+ DEBUG("Using %d threads across %d logical processors; processing %d "
+ "elements (%d per thread)",
ret.threads_used, cpu_threads, (end - start), iter_per_thread);
g_timer_start(timer);
- for (iter = start; iter < end; ) {
+ for (iter = start; iter < end;) {
ParallelBenchTask *pbt = g_new0(ParallelBenchTask, 1);
GThread *thread;
@@ -238,13 +299,17 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
DEBUG("launching thread %d", 1 + thread_number);
pbt->thread_number = thread_number++;
- pbt->start = ts;
- pbt->end = te - 1;
- pbt->data = callback_data;
+ pbt->start = ts;
+ pbt->end = te - 1;
+ pbt->data = callback_data;
pbt->callback = callback;
- thread = g_thread_new("dispatcher",
- (GThreadFunc)benchmark_parallel_for_dispatcher, pbt);
+#if GLIB_CHECK_VERSION(2,32,0)
+ thread = g_thread_new("dispatcher", (GThreadFunc)benchmark_parallel_for_dispatcher, pbt);
+#else
+ thread = g_thread_create((GThreadFunc)benchmark_parallel_for_dispatcher, pbt,TRUE,NULL);
+#endif
+
threads = g_slist_prepend(threads, thread);
DEBUG("thread %d launched as context %p", thread_number, thread);
@@ -255,8 +320,9 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
DEBUG("waiting for thread with context %p", t->data);
gpointer *rv = g_thread_join((GThread *)t->data);
if (rv) {
- if (ret.result == -1.0) ret.result = 0;
- ret.result += *(double*)rv;
+ if (ret.result == -1.0)
+ ret.result = 0;
+ ret.result += *(double *)rv;
}
g_free(rv);
}
@@ -272,140 +338,256 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
return ret;
}
-static gchar *clean_cpuname(gchar *cpuname)
+gchar *hi_more_info(gchar *entry)
{
- gchar *ret = NULL, *tmp;
- gchar *remove[] = {
- "(R)", "(r)", "(TM)", "(tm)", "Processor",
- "Technology", "processor", "CPU",
- "cpu", "Genuine", "Authentic", NULL
- };
- gint i;
+ const gchar *info = moreinfo_lookup_with_prefix("BENCH", entry);
+ return g_strdup(info ? info : "?");
+}
+
+gchar *hi_get_field(gchar *field)
+{
+ const gchar *info = moreinfo_lookup_with_prefix("BENCH", field);
+ return g_strdup(info ? info : field);
+}
- ret = g_strdup(cpuname);
- for (i = 0; remove[i]; i++) {
- tmp = strreplace(ret, remove[i], "");
- g_free(ret);
- ret = tmp;
+static void br_mi_add(char **results_list, bench_result *b, gboolean select)
+{
+ static unsigned int ri = 0; /* to ensure key is unique */
+ gchar *rkey, *lbl, *elbl, *this_marker;
+
+ if (select) {
+ this_marker = format_with_ansi_color(_("This Machine"), "0;30;43",
+ params.fmt_opts);
+ } else {
+ this_marker = "";
}
- ret = strend(ret, '@');
- ret = g_strstrip(ret);
+ rkey = g_strdup_printf("%s__%d", b->machine->mid, ri++);
- tmp = g_strdup(ret);
- g_free(ret);
+ lbl = g_strdup_printf("%s%s%s%s", this_marker, select ? " " : "",
+ b->machine->cpu_name,
+ b->legacy ? problem_marker() : "");
+ elbl = key_label_escape(lbl);
- return tmp;
-}
+ *results_list = h_strdup_cprintf("$@%s%s$%s=%.2f|%s\n", *results_list,
+ select ? "*" : "", rkey, elbl,
+ b->bvalue.result, b->machine->cpu_config);
-gchar *hi_more_info(gchar * entry)
+ moreinfo_add_with_prefix("BENCH", rkey, bench_result_more_info(b));
+
+ g_free(lbl);
+ g_free(elbl);
+ g_free(rkey);
+ if (*this_marker)
+ g_free(this_marker);
+}
+gint bench_result_sort(gconstpointer a, gconstpointer b)
{
- gchar *info = moreinfo_lookup_with_prefix("BENCH", entry);
- if (info)
- return g_strdup(info);
- return g_strdup("?");
+ bench_result *A = (bench_result *)a, *B = (bench_result *)b;
+ if (A->bvalue.result < B->bvalue.result)
+ return -1;
+ if (A->bvalue.result > B->bvalue.result)
+ return 1;
+ return 0;
}
-gchar *hi_get_field(gchar * field)
+struct append_machine_result_json_data {
+ GSList **result_list;
+ const gchar *benchmark_name;
+};
+
+static void append_machine_result_json(JsonArray *array,
+ guint index,
+ JsonNode *element_node,
+ gpointer user_data)
{
- gchar *info = moreinfo_lookup_with_prefix("BENCH", field);
- if (info)
- return g_strdup(info);
- return g_strdup(field);
+ struct append_machine_result_json_data *data = user_data;
+ bench_result *result;
+
+ result = bench_result_benchmarkjson(data->benchmark_name, element_node);
+ *data->result_list = g_slist_append(*data->result_list, result);
}
-static void br_mi_add(char **results_list, bench_result *b, gboolean select) {
- gchar *ckey, *rkey;
+static GSList *benchmark_include_results_json(const gchar *path,
+ bench_value r,
+ const gchar *benchmark)
+{
+ JsonParser *parser;
+ JsonNode *root;
+ bench_result *this_machine = NULL;
+ GSList *result_list = NULL;
+ GError *error=NULL;
+
+ DEBUG("Loading benchmark results from JSON file %s", path);
+
+ parser = json_parser_new();
+ json_parser_load_from_file(parser, path, &error);
+ if(error){
+ DEBUG ("Unable to parse JSON %s %s", path, error->message);
+ g_error_free(error);
+ g_object_unref(parser);
+ return result_list;
+ }
- ckey = hardinfo_clean_label(b->machine->cpu_name, 0);
- rkey = strdup(b->machine->mid);
+ root = json_parser_get_root(parser);
+ if (json_node_get_node_type(root) != JSON_NODE_OBJECT) goto out;
- *results_list = h_strdup_cprintf("$%s%s$%s=%.2f|%s\n", *results_list,
- select ? "*" : "", rkey, ckey,
- b->bvalue.result, b->machine->cpu_config);
+ JsonObject *results = json_node_get_object(root);
+ if (results) {
+ JsonArray *machines = json_object_get_array_member(results, benchmark);
- moreinfo_add_with_prefix("BENCH", rkey, bench_result_more_info(b) );
+ if (machines) {
+ struct append_machine_result_json_data data = {
+ .result_list = &result_list,
+ .benchmark_name = benchmark,
+ };
+ json_array_foreach_element(machines, append_machine_result_json,
+ &data);
+ }
+ }
- g_free(ckey);
- g_free(rkey);
+out:
+ g_object_unref(parser);
+
+ return result_list;
}
-static gchar *__benchmark_include_results(bench_value r,
- const gchar * benchmark,
- ShellOrderType order_type)
+static gchar *find_benchmark_conf(void)
{
- bench_result *b = NULL;
- GKeyFile *conf;
- gchar **machines, *temp = NULL;;
- gchar *path, *results = g_strdup(""), *return_value, *processor_frequency, *processor_name;
- int i, n_threads;
+ const gchar *config_dir = g_get_user_config_dir();
+ gchar *path;
- moreinfo_del_with_prefix("BENCH");
+ path = g_build_filename(config_dir, "hardinfo2", "benchmark.json", NULL);
+ if (g_file_test(path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free(path);
- if (r.result > 0.0) {
- b = bench_result_this_machine(benchmark, r);
- br_mi_add(&results, b, 1);
+ path = g_build_filename(params.path_data, "benchmark.json", NULL);
+ if (g_file_test(path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free(path);
+
+ return NULL;
+}
- temp = bench_result_benchmarkconf_line(b);
- printf("[%s]\n%s", benchmark, temp);
- g_free(temp); temp = NULL;
+struct bench_window {
+ int min, max;
+};
+
+static struct bench_window get_bench_window(GSList *result_list,
+ const bench_result *this_machine)
+{
+ struct bench_window window = {};
+ int size = params.max_bench_results;
+ int len = g_slist_length(result_list);
+
+ if (size == 0)
+ size = 1;
+ else if (size < 0)
+ size = len;
+
+ int loc = g_slist_index(result_list, this_machine); /* -1 if not found */
+ if (loc >= 0) {
+ window.min = loc - size / 2;
+ window.max = window.min + size;
+ if (window.min < 0) {
+ window.min = 0;
+ window.max = MIN(size, len);
+ } else if (window.max > len) {
+ window.max = len;
+ window.min = MAX(len - size, 0);
+ }
+ } else {
+ window.min = 0;
+ window.max = len;
}
- conf = g_key_file_new();
+ DEBUG("...len: %d, loc: %d, win_size: %d, win: [%d..%d]\n", len, loc, size,
+ window.min, window.max - 1);
+
+ return window;
+}
+
+static gboolean is_in_bench_window(const struct bench_window *window, int i)
+{
+ return i >= window->min && i < window->max;
+}
- path = g_build_filename(g_get_home_dir(), ".hardinfo", "benchmark.conf", NULL);
- if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
- DEBUG("local benchmark.conf not found, trying system-wide");
- g_free(path);
- path = g_build_filename(params.path_data, "benchmark.conf", NULL);
+static gchar *benchmark_include_results_internal(bench_value this_machine_value,
+ const gchar *benchmark,
+ ShellOrderType order_type)
+{
+ bench_result *this_machine;
+ GSList *result_list, *li;
+ gchar *results = g_strdup("");
+ gchar *output;
+ gchar *path;
+ gint i;
+
+ path = find_benchmark_conf();
+ if (path) {
+ result_list = benchmark_include_results_json(
+ path, this_machine_value, benchmark);
}
- g_key_file_load_from_file(conf, path, 0, NULL);
- g_key_file_set_list_separator(conf, '|');
+ /* this result */
+ if (this_machine_value.result > 0.0) {
+ this_machine = bench_result_this_machine(benchmark, this_machine_value);
+ result_list = g_slist_prepend(result_list, this_machine);
+ } else {
+ this_machine = NULL;
+ }
- machines = g_key_file_get_keys(conf, benchmark, NULL, NULL);
- for (i = 0; machines && machines[i]; i++) {
- gchar **values;
- bench_result *sbr;
+ /* sort */
+ result_list = g_slist_sort(result_list, bench_result_sort);
+ if (order_type == SHELL_ORDER_DESCENDING)
+ result_list = g_slist_reverse(result_list);
- values = g_key_file_get_string_list(conf, benchmark, machines[i], NULL, NULL);
+ /* prepare for shell */
+ moreinfo_del_with_prefix("BENCH");
+
+ const struct bench_window window =
+ get_bench_window(result_list, this_machine);
+ for (i = 0, li = result_list; li; li = g_slist_next(li), i++) {
+ bench_result *br = li->data;
- sbr = bench_result_benchmarkconf(benchmark, machines[i], values);
- br_mi_add(&results, sbr, 0);
+ if (is_in_bench_window(&window, i))
+ br_mi_add(&results, br, br == this_machine);
- bench_result_free(sbr);
- g_strfreev(values);
+ bench_result_free(br); /* no longer needed */
}
+ g_slist_free(result_list);
+
+ output = g_strdup_printf("[$ShellParam$]\n"
+ "Zebra=1\n"
+ "OrderType=%d\n"
+ "ViewType=4\n"
+ "ColumnTitle$Extra1=%s\n" /* CPU Clock */
+ "ColumnTitle$Progress=%s\n" /* Results */
+ "ColumnTitle$TextValue=%s\n" /* CPU */
+ "ShowColumnHeaders=true\n"
+ "[%s]\n%s",
+ order_type, _("CPU Config"), _("Results"),
+ _("CPU"), benchmark, results);
- g_strfreev(machines);
g_free(path);
- g_key_file_free(conf);
-
- return_value = g_strdup_printf("[$ShellParam$]\n"
- "Zebra=1\n"
- "OrderType=%d\n"
- "ViewType=4\n"
- "ColumnTitle$Extra1=%s\n" /* CPU Clock */
- "ColumnTitle$Progress=%s\n" /* Results */
- "ColumnTitle$TextValue=%s\n" /* CPU */
- "ShowColumnHeaders=true\n"
- "[%s]\n%s",
- order_type,
- _("CPU Config"), _("Results"), _("CPU"),
- benchmark, results);
-
- bench_result_free(b);
- return return_value;
+ g_free(results);
+
+ return output;
}
-static gchar *benchmark_include_results_reverse(bench_value result, const gchar * benchmark)
+static gchar *benchmark_include_results_reverse(bench_value result,
+ const gchar *benchmark)
{
- return __benchmark_include_results(result, benchmark, SHELL_ORDER_DESCENDING);
+ return benchmark_include_results_internal(result, benchmark,
+ SHELL_ORDER_DESCENDING);
}
-static gchar *benchmark_include_results(bench_value result, const gchar * benchmark)
+static gchar *benchmark_include_results(bench_value result,
+ const gchar *benchmark)
{
- return __benchmark_include_results(result, benchmark, SHELL_ORDER_ASCENDING);
+ return benchmark_include_results_internal(result, benchmark,
+ SHELL_ORDER_ASCENDING);
}
typedef struct _BenchmarkDialog BenchmarkDialog;
@@ -414,11 +596,10 @@ struct _BenchmarkDialog {
bench_value r;
};
-static gboolean do_benchmark_handler(GIOChannel *source,
- GIOCondition condition,
- gpointer data)
+static gboolean
+do_benchmark_handler(GIOChannel *source, GIOCondition condition, gpointer data)
{
- BenchmarkDialog *bench_dialog = (BenchmarkDialog*)data;
+ BenchmarkDialog *bench_dialog = (BenchmarkDialog *)data;
GIOStatus status;
gchar *result;
bench_value r = EMPTY_BENCH_VALUE;
@@ -433,6 +614,9 @@ static gboolean do_benchmark_handler(GIOChannel *source,
}
r = bench_value_from_str(result);
+ /* attach a user note */
+ if (params.bench_user_note)
+ strncpy(r.user_note, params.bench_user_note, 255);
bench_dialog->r = r;
gtk_widget_destroy(bench_dialog->dialog);
@@ -445,118 +629,127 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
{
int old_priority = 0;
- if (params.gui_running && !sending_benchmark_results) {
- gchar *argv[] = { params.argv0, "-b", entries[entry].name,
- "-m", "benchmark.so", "-a", NULL };
- GPid bench_pid;
- gint bench_stdout;
- GtkWidget *bench_dialog;
- GtkWidget *bench_image;
- BenchmarkDialog *benchmark_dialog;
- GSpawnFlags spawn_flags = G_SPAWN_STDERR_TO_DEV_NULL;
- gchar *bench_status;
-
- bench_value r = EMPTY_BENCH_VALUE;
- bench_results[entry] = r;
-
- bench_status = g_strdup_printf(_("Benchmarking: <b>%s</b>."), entries[entry].name);
-
- shell_view_set_enabled(FALSE);
- shell_status_update(bench_status);
-
- g_free(bench_status);
-
- bench_image = icon_cache_get_image("benchmark.png");
- gtk_widget_show(bench_image);
-
-#if GTK_CHECK_VERSION(3, 0, 0)
- GtkWidget *button;
- GtkWidget *content_area;
- GtkWidget *hbox;
- GtkWidget *label;
-
- bench_dialog = gtk_dialog_new_with_buttons("",
- NULL,
- GTK_DIALOG_MODAL,
- _("Cancel"),
- GTK_RESPONSE_ACCEPT,
- NULL);
- content_area = gtk_dialog_get_content_area(GTK_DIALOG(bench_dialog));
- label = gtk_label_new(_("Benchmarking. Please do not move your mouse " \
- "or press any keys."));
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
- gtk_box_pack_start(GTK_BOX(hbox), bench_image, TRUE, TRUE, 5);
- gtk_box_pack_end(GTK_BOX(hbox), label, TRUE, TRUE, 5);
- gtk_container_add(GTK_CONTAINER (content_area), hbox);
- gtk_widget_show_all(bench_dialog);
+ if (params.skip_benchmarks)
+ return;
+
+ if (params.gui_running) {
+ gchar *argv[] = {params.argv0, "-b", entries[entry].name,
+ "-m", "benchmark.so", "-a",
+ NULL};
+ GPid bench_pid;
+ gint bench_stdout;
+ GtkWidget *bench_dialog;
+ GtkWidget *bench_image;
+ BenchmarkDialog *benchmark_dialog;
+ GSpawnFlags spawn_flags = G_SPAWN_STDERR_TO_DEV_NULL;
+ gchar *bench_status;
+ GtkWidget *content_area, *box, *label;
+ bench_value r = EMPTY_BENCH_VALUE;
+ bench_results[entry] = r;
+
+ bench_status =
+ g_strdup_printf(_("Benchmarking: <b>%s</b>."), entries[entry].name);
+
+ shell_view_set_enabled(FALSE);
+ shell_status_update(bench_status);
+
+ g_free(bench_status);
+
+ bench_image = icon_cache_get_image("benchmark.png");
+
+ bench_dialog = gtk_dialog_new_with_buttons ("Benchmarking...",
+ GTK_WINDOW(shell_get_main_shell()->transient_dialog),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
+ "Stop",
+ GTK_BUTTONS_CLOSE,
+ NULL);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(shell_get_main_shell()->transient_dialog), FALSE);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG(bench_dialog));
+
+#if GTK_CHECK_VERSION(3,0,0)
+ box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1);
#else
- bench_dialog = gtk_message_dialog_new(GTK_WINDOW(shell_get_main_shell()->window),
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_NONE,
- _("Benchmarking. Please do not move your mouse " \
- "or press any keys."));
- gtk_dialog_add_buttons(GTK_DIALOG(bench_dialog),
- _("Cancel"), GTK_RESPONSE_ACCEPT, NULL);
- gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(bench_dialog), bench_image);
+ box = gtk_hbox_new(FALSE, 1);
#endif
+ label = gtk_label_new ("Please do not move your mouse\n"
+ "or press any keys.");
- while (gtk_events_pending()) {
- gtk_main_iteration();
- }
+ gtk_widget_show (bench_image);
- benchmark_dialog = g_new0(BenchmarkDialog, 1);
- benchmark_dialog->dialog = bench_dialog;
- benchmark_dialog->r = r;
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign (bench_image, GTK_ALIGN_START);
+#else
+ gtk_misc_set_alignment(GTK_MISC(bench_image), 0.0, 0.0);
+#endif
+
+ g_signal_connect_swapped (bench_dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ bench_dialog);
- if (!g_path_is_absolute(params.argv0)) {
- spawn_flags |= G_SPAWN_SEARCH_PATH;
- }
+ gtk_box_pack_start (GTK_BOX(box), bench_image, TRUE, TRUE, 10);
+ gtk_box_pack_start (GTK_BOX(box), label, TRUE, TRUE, 10);
+ gtk_container_add (GTK_CONTAINER(content_area), box);
- if (g_spawn_async_with_pipes(NULL,
- argv, NULL,
- spawn_flags,
- NULL, NULL,
- &bench_pid,
- NULL, &bench_stdout, NULL,
- NULL)) {
- GIOChannel *channel;
- guint watch_id;
+ gtk_window_set_deletable(GTK_WINDOW(bench_dialog), FALSE);
+ gtk_widget_show_all (bench_dialog);
- DEBUG("spawning benchmark; pid=%d", bench_pid);
+ while (gtk_events_pending()) {
+ gtk_main_iteration();
+ }
- channel = g_io_channel_unix_new(bench_stdout);
- watch_id = g_io_add_watch(channel, G_IO_IN, do_benchmark_handler,
- benchmark_dialog);
+ benchmark_dialog = g_new0(BenchmarkDialog, 1);
+ benchmark_dialog->dialog = bench_dialog;
+ benchmark_dialog->r = r;
- switch (gtk_dialog_run(GTK_DIALOG(bench_dialog))) {
+ if (!g_path_is_absolute(params.argv0)) {
+ spawn_flags |= G_SPAWN_SEARCH_PATH;
+ }
+
+ if (g_spawn_async_with_pipes(NULL, argv, NULL, spawn_flags, NULL, NULL,
+ &bench_pid, NULL, &bench_stdout, NULL,
+ NULL)) {
+ GIOChannel *channel;
+ guint watch_id;
+
+ DEBUG("spawning benchmark; pid=%d", bench_pid);
+
+ channel = g_io_channel_unix_new(bench_stdout);
+ watch_id = g_io_add_watch(channel, G_IO_IN, do_benchmark_handler,
+ benchmark_dialog);
+
+ switch (gtk_dialog_run(GTK_DIALOG(bench_dialog))) {
case GTK_RESPONSE_NONE:
- DEBUG("benchmark finished");
- break;
+ DEBUG("benchmark finished");
+ break;
case GTK_RESPONSE_ACCEPT:
- DEBUG("cancelling benchmark");
+ DEBUG("cancelling benchmark");
- gtk_widget_destroy(bench_dialog);
- g_source_remove(watch_id);
- kill(bench_pid, SIGINT);
- }
+ gtk_widget_destroy(bench_dialog);
+ g_source_remove(watch_id);
+ kill(bench_pid, SIGINT);
+ }
- bench_results[entry] = benchmark_dialog->r;
+ bench_results[entry] = benchmark_dialog->r;
- g_io_channel_unref(channel);
- shell_view_set_enabled(TRUE);
- shell_status_set_enabled(TRUE);
- g_free(benchmark_dialog);
+ g_io_channel_unref(channel);
+ shell_view_set_enabled(TRUE);
+ shell_status_set_enabled(TRUE);
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(shell_get_main_shell()->transient_dialog), TRUE);
+ g_free(benchmark_dialog);
- shell_status_update(_("Done."));
+ shell_status_update(_("Done."));
- return;
- }
+ return;
+ }
- gtk_widget_destroy(bench_dialog);
- g_free(benchmark_dialog);
- shell_status_set_enabled(TRUE);
- shell_status_update(_("Done."));
+ gtk_widget_destroy(bench_dialog);
+ g_free(benchmark_dialog);
+ shell_status_set_enabled(TRUE);
+ shell_status_update(_("Done."));
}
setpriority(PRIO_PROCESS, 0, -20);
@@ -564,79 +757,113 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
setpriority(PRIO_PROCESS, 0, old_priority);
}
-gchar *hi_module_get_name(void)
-{
- return g_strdup(_("Benchmarks"));
-}
+gchar *hi_module_get_name(void) { return g_strdup(_("Benchmarks")); }
-guchar hi_module_get_weight(void)
-{
- return 240;
-}
+guchar hi_module_get_weight(void) { return 240; }
-ModuleEntry *hi_module_get_entries(void)
-{
- return entries;
-}
+ModuleEntry *hi_module_get_entries(void) { return entries; }
-ModuleAbout *hi_module_get_about(void)
+const ModuleAbout *hi_module_get_about(void)
{
- static ModuleAbout ma[] = {
- {
- .author = "Leandro A. F. Pereira",
- .description = N_("Perform tasks and compare with other systems"),
- .version = VERSION,
- .license = "GNU GPL version 2"}
+ static const ModuleAbout ma = {
+ .author = "L. A. F. Pereira",
+ .description = N_("Perform tasks and compare with other systems"),
+ .version = VERSION,
+ .license = "GNU GPL version 2 or later.",
};
- return ma;
+ return &ma;
}
-static gchar *get_benchmark_results()
+static gchar *get_benchmark_results(gsize *len)
{
- gint i;
- void (*scan_callback) (gboolean rescan);
-
- sending_benchmark_results = TRUE;
-
- gchar *machine = module_call_method("devices::getProcessorName");
- gchar *machineclock = module_call_method("devices::getProcessorFrequency");
- gchar *machineram = module_call_method("devices::getMemoryTotal");
- gchar *result = g_strdup_printf("[param]\n"
- "machine=%s\n"
- "machineclock=%s\n"
- "machineram=%s\n"
- "nbenchmarks=%zu\n",
- machine,
- machineclock,
- machineram,
- G_N_ELEMENTS(entries) - 1);
+ void (*scan_callback)(gboolean);
+ JsonBuilder *builder;
+ JsonGenerator *generator;
+ JsonNode *root;
+ bench_machine *this_machine;
+ gchar *out;
+ guint i;
+
for (i = 0; i < G_N_ELEMENTS(entries); i++) {
- scan_callback = entries[i].scan_callback;
- if (!scan_callback)
+ if (!entries[i].name || !entries[i].scan_callback)
+ continue;
+ if (entries[i].flags & MODULE_FLAG_HIDE)
continue;
+ scan_callback = entries[i].scan_callback;
+ if (scan_callback)
+ scan_callback(bench_results[i].result < 0.0);
+ }
+
+ this_machine = bench_machine_this();
+ builder = json_builder_new();
+ json_builder_begin_object(builder);
+ for (i = 0; i < G_N_ELEMENTS(entries); i++) {
+ if (!entries[i].name || entries[i].flags & MODULE_FLAG_HIDE)
+ continue;
if (bench_results[i].result < 0.0) {
- /* benchmark was cancelled */
- scan_callback(TRUE);
- } else {
- scan_callback(FALSE);
+ /* Benchmark failed? */
+ continue;
}
- result = h_strdup_cprintf("[bench%d]\n"
- "name=%s\n"
- "value=%f\n",
- result,
- i, entries[i].name, bench_results[i]);
+ json_builder_set_member_name(builder, entries[i].name);
+
+ json_builder_begin_object(builder);
+
+#define ADD_JSON_VALUE(type, name, value) \
+ do { \
+ json_builder_set_member_name(builder, (name)); \
+ json_builder_add_##type##_value(builder, (value)); \
+ } while (0)
+
+ ADD_JSON_VALUE(string, "Board", this_machine->board);
+ ADD_JSON_VALUE(int, "MemoryInKiB", this_machine->memory_kiB);
+ ADD_JSON_VALUE(string, "CpuName", this_machine->cpu_name);
+ ADD_JSON_VALUE(string, "CpuDesc", this_machine->cpu_desc);
+ ADD_JSON_VALUE(string, "CpuConfig", this_machine->cpu_config);
+ ADD_JSON_VALUE(string, "CpuConfig", this_machine->cpu_config);
+ ADD_JSON_VALUE(string, "OpenGlRenderer", this_machine->ogl_renderer);
+ ADD_JSON_VALUE(string, "GpuDesc", this_machine->gpu_desc);
+ ADD_JSON_VALUE(int, "NumCpus", this_machine->processors);
+ ADD_JSON_VALUE(int, "NumCores", this_machine->cores);
+ ADD_JSON_VALUE(int, "NumNodes", this_machine->nodes);
+ ADD_JSON_VALUE(int, "NumThreads", this_machine->threads);
+ ADD_JSON_VALUE(string, "MachineId", this_machine->mid);
+ ADD_JSON_VALUE(int, "PointerBits", this_machine->ptr_bits);
+ ADD_JSON_VALUE(boolean, "DataFromSuperUser", this_machine->is_su_data);
+ ADD_JSON_VALUE(int, "PhysicalMemoryInMiB",
+ this_machine->memory_phys_MiB);
+ ADD_JSON_VALUE(string, "MemoryTypes", this_machine->ram_types);
+ ADD_JSON_VALUE(int, "MachineDataVersion",
+ this_machine->machine_data_version);
+ ADD_JSON_VALUE(string, "MachineType", this_machine->machine_type);
+
+ ADD_JSON_VALUE(boolean, "Legacy", FALSE);
+ ADD_JSON_VALUE(string, "ExtraInfo", bench_results[i].extra);
+ ADD_JSON_VALUE(string, "UserNote", bench_results[i].user_note);
+ ADD_JSON_VALUE(double, "BenchmarkResult", bench_results[i].result);
+ ADD_JSON_VALUE(double, "ElapsedTime", bench_results[i].elapsed_time);
+ ADD_JSON_VALUE(int, "UsedThreads", bench_results[i].threads_used);
+ ADD_JSON_VALUE(int, "BenchmarkVersion", bench_results[i].revision);
+
+#undef ADD_JSON_VALUE
+
+ json_builder_end_object(builder);
}
+ json_builder_end_object(builder);
+
+ generator = json_generator_new();
+ json_generator_set_root(generator, json_builder_get_root(builder));
+ json_generator_set_pretty(generator, TRUE);
- g_free(machine);
- g_free(machineclock);
- g_free(machineram);
+ out = json_generator_to_data(generator, len);
- sending_benchmark_results = FALSE;
+ g_object_unref(generator);
+ g_object_unref(builder);
+ bench_machine_free(this_machine);
- return result;
+ return out;
}
static gchar *run_benchmark(gchar *name)
@@ -646,42 +873,44 @@ static gchar *run_benchmark(gchar *name)
DEBUG("name = %s", name);
for (i = 0; entries[i].name; i++) {
- if (g_str_equal(entries[i].name, name)) {
- void (*scan_callback)(gboolean rescan);
-
- if ((scan_callback = entries[i].scan_callback)) {
- scan_callback(FALSE);
-
-#define CHK_RESULT_FORMAT(F) (params.result_format && strcmp(params.result_format, F) == 0)
-
- if (params.run_benchmark) {
- if (CHK_RESULT_FORMAT("conf") ) {
- bench_result *b = bench_result_this_machine(name, bench_results[i]);
- char *temp = bench_result_benchmarkconf_line(b);
- bench_result_free(b);
- return temp;
- } else if (CHK_RESULT_FORMAT("shell") ) {
- bench_result *b = bench_result_this_machine(name, bench_results[i]);
- char *temp = bench_result_more_info_complete(b);
- bench_result_free(b);
- return temp;
+ if (g_str_equal(entries[i].name, name)) {
+ void (*scan_callback)(gboolean rescan);
+
+ if ((scan_callback = entries[i].scan_callback)) {
+ scan_callback(FALSE);
+
+#define CHK_RESULT_FORMAT(F) \
+ (params.result_format && strcmp(params.result_format, F) == 0)
+
+ if (params.run_benchmark) {
+ /* attach the user note */
+ if (params.bench_user_note)
+ strncpy(bench_results[i].user_note,
+ params.bench_user_note, 255);
+
+ if (CHK_RESULT_FORMAT("shell")) {
+ bench_result *b =
+ bench_result_this_machine(name, bench_results[i]);
+ char *temp = bench_result_more_info_complete(b);
+ bench_result_free(b);
+ return temp;
+ }
+ /* defaults to "short" which is below */
+ }
+
+ return bench_value_to_str(bench_results[i]);
}
- /* defaults to "short" which is below*/
- }
-
- return bench_value_to_str(bench_results[i]);
}
- }
}
return NULL;
}
-ShellModuleMethod *hi_exported_methods(void)
+const ShellModuleMethod *hi_exported_methods(void)
{
- static ShellModuleMethod m[] = {
+ static const ShellModuleMethod m[] = {
{"runBenchmark", run_benchmark},
- {NULL}
+ {NULL},
};
return m;
@@ -690,31 +919,28 @@ ShellModuleMethod *hi_exported_methods(void)
void hi_module_init(void)
{
static SyncEntry se[] = {
- {
- .fancy_name = N_("Send benchmark results"),
- .name = "SendBenchmarkResults",
- .save_to = NULL,
- .get_data = get_benchmark_results},
- {
- .fancy_name = N_("Receive benchmark results"),
- .name = "RecvBenchmarkResults",
- .save_to = "benchmark.conf",
- .get_data = NULL}
+ {
+ .name = N_("Send benchmark results"),
+ .file_name = "benchmark.json",
+ .generate_contents_for_upload = get_benchmark_results,
+ },
+ {
+ .name = N_("Receive benchmark results"),
+ .file_name = "benchmark.json",
+ },
};
sync_manager_add_entry(&se[0]);
sync_manager_add_entry(&se[1]);
- bench_value er = EMPTY_BENCH_VALUE;
- int i;
- for (i = 0; i < G_N_ELEMENTS(entries) - 1; i++) {
- bench_results[i] = er;
- }
+ guint i;
+ for (i = 0; i < G_N_ELEMENTS(entries) - 1 /* account for NULL */; i++)
+ bench_results[i] = (bench_value)EMPTY_BENCH_VALUE;
}
gchar **hi_module_get_dependencies(void)
{
- static gchar *deps[] = { "devices.so", NULL };
+ static gchar *deps[] = {"devices.so", NULL};
return deps;
}
diff --git a/modules/benchmark/bench_results.c b/modules/benchmark/bench_results.c
index 27a33a65..18ed0739 100644
--- a/modules/benchmark/bench_results.c
+++ b/modules/benchmark/bench_results.c
@@ -1,12 +1,12 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2017 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2020 L. A. F. Pereira <l@tia.mat.br>
* This file:
* Copyright (C) 2017 Burt P. <pburt0@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,20 +18,39 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/*/ Used for an unknown value. Having it in only one place cleans up the .po line references */
+#include <stdlib.h>
+#include <locale.h>
+#include <inttypes.h>
+#include <json-glib/json-glib.h>
+#include "nice_name.h"
+
+/* in dmi_memory.c */
+uint64_t memory_devices_get_system_memory_MiB();
+gchar *memory_devices_get_system_memory_types_str();
+
+/*/ Used for an unknown value. Having it in only one place cleans up the .po
+ * line references */
static const char *unk = N_("(Unknown)");
typedef struct {
char *board;
- int memory_kiB;
+ uint64_t memory_kiB; /* from /proc/meminfo -> MemTotal */
char *cpu_name;
char *cpu_desc;
char *cpu_config;
char *ogl_renderer;
+ char *gpu_desc;
int processors;
int cores;
int threads;
+ int nodes;
char *mid;
+ int ptr_bits; /* 32, 64... BENCH_PTR_BITS; 0 for unspecified */
+ int is_su_data; /* 1 = data collected as root */
+ uint64_t memory_phys_MiB; /* from DMI/SPD/DTree/Table/Blocks, etc. */
+ char *ram_types;
+ int machine_data_version;
+ char *machine_type;
} bench_machine;
typedef struct {
@@ -41,7 +60,8 @@ typedef struct {
int legacy; /* an old benchmark.conf result */
} bench_result;
-static char *cpu_config_retranslate(char *str, int force_en, int replacing) {
+static char *cpu_config_retranslate(char *str, int force_en, int replacing)
+{
char *new_str = NULL;
char *mhz = (force_en) ? "MHz" : _("MHz");
char *c = str, *tmp;
@@ -51,19 +71,19 @@ static char *cpu_config_retranslate(char *str, int force_en, int replacing) {
if (str != NULL) {
new_str = strdup("");
if (strchr(str, 'x')) {
- while (c != NULL && sscanf(c, "%dx %f", &t, &f) ) {
- tmp = g_strdup_printf("%s%s%dx %.2f %s",
- new_str, strlen(new_str) ? " + " : "",
- t, f, mhz );
+ while (c != NULL && (sscanf(c, "%dx %f", &t, &f)==2)) {
+ tmp = g_strdup_printf("%s%s%dx %.2f %s", new_str,
+ strlen(new_str) ? " + " : "", t, f, mhz);
free(new_str);
new_str = tmp;
- c = strchr(c+1, '+');
+ c = strchr(c + 1, '+');
+ if (c)
+ c++; /* move past the + */
}
} else {
sscanf(c, "%f", &f);
- tmp = g_strdup_printf("%s%s%dx %.2f %s",
- new_str, strlen(new_str) ? " + " : "",
- 1, f, mhz );
+ tmp = g_strdup_printf("%s%s%dx %.2f %s", new_str,
+ strlen(new_str) ? " + " : "", 1, f, mhz);
free(new_str);
new_str = tmp;
}
@@ -71,19 +91,23 @@ static char *cpu_config_retranslate(char *str, int force_en, int replacing) {
if (replacing)
free(str);
}
+
return new_str;
}
/* "2x 1400.00 MHz + 2x 800.00 MHz" -> 4400.0 */
-static float cpu_config_val(char *str) {
+static float cpu_config_val(char *str)
+{
char *c = str;
int t;
float f, r = 0.0;
if (str != NULL) {
if (strchr(str, 'x')) {
- while (c != NULL && sscanf(c, "%dx %f", &t, &f) ) {
+ while (c != NULL && (sscanf(c, "%dx %f", &t, &f)==2)) {
r += f * t;
- c = strchr(c+1, '+');
+ c = strchr(c + 1, '+');
+ if (c)
+ c++; /* move past the + */
}
} else {
sscanf(c, "%f", &r);
@@ -92,16 +116,20 @@ static float cpu_config_val(char *str) {
return r;
}
-static int cpu_config_cmp(char *str0, char *str1) {
+static int cpu_config_cmp(char *str0, char *str1)
+{
float r0, r1;
r0 = cpu_config_val(str0);
r1 = cpu_config_val(str1);
- if (r0 == r1) return 0;
- if (r0 < r1) return -1;
+ if (r0 == r1)
+ return 0;
+ if (r0 < r1)
+ return -1;
return 1;
}
-static int cpu_config_is_close(char *str0, char *str1) {
+static int cpu_config_is_close(char *str0, char *str1)
+{
float r0, r1, r1n;
r0 = cpu_config_val(str0);
r1 = cpu_config_val(str1);
@@ -111,76 +139,85 @@ static int cpu_config_is_close(char *str0, char *str1) {
return 0;
}
-static gen_machine_id(bench_machine *m) {
+static void gen_machine_id(bench_machine *m)
+{
char *s;
+
if (m) {
if (m->mid != NULL)
free(m->mid);
- /* Don't try and translate unknown. The mid string needs to be made of all
- * untranslated elements.*/
+
+ /* Don't try and translate unknown. The mid string needs to be made of
+ * all untranslated elements.*/
m->mid = g_strdup_printf("%s;%s;%.2f",
- (m->board != NULL) ? m->board : "(Unknown)", m->cpu_name, cpu_config_val(m->cpu_config) );
- s = m->mid;
- while (*s != 0) {
- if (!isalnum(*s)) {
- if (*s != ';'
- && *s != '('
- && *s != '('
- && *s != ')')
+ (m->board != NULL) ? m->board : "(Unknown)",
+ m->cpu_name, cpu_config_val(m->cpu_config));
+ for (s = m->mid; *s; s++) {
+ if (!isalnum(*s) && *s != '(' && *s != ')' && *s != ';')
*s = '_';
- }
- s++;
}
}
}
-bench_machine *bench_machine_new() {
- bench_machine *m = NULL;
- m = malloc(sizeof(bench_machine));
- if (m)
- memset(m, 0, sizeof(bench_machine));
- return m;
+bench_machine *bench_machine_new()
+{
+ return calloc(1, sizeof(bench_machine));
}
-bench_machine *bench_machine_this() {
+bench_machine *bench_machine_this()
+{
bench_machine *m = NULL;
char *tmp;
m = bench_machine_new();
if (m) {
+ m->ptr_bits = BENCH_PTR_BITS;
+ m->is_su_data = (getuid() == 0);
m->board = module_call_method("devices::getMotherboard");
m->cpu_name = module_call_method("devices::getProcessorName");
m->cpu_desc = module_call_method("devices::getProcessorDesc");
- m->cpu_config = module_call_method("devices::getProcessorFrequencyDesc");
+ m->cpu_config =
+ module_call_method("devices::getProcessorFrequencyDesc");
+ m->gpu_desc = module_call_method("devices::getGPUList");
m->ogl_renderer = module_call_method("computer::getOGLRenderer");
- tmp = module_call_method("devices::getMemoryTotal");
- m->memory_kiB = atoi(tmp);
+ tmp = module_call_method("computer::getMemoryTotal");
+ m->memory_kiB = strtoull(tmp, NULL, 10);
+ m->memory_phys_MiB = memory_devices_get_system_memory_MiB();
+ m->ram_types = memory_devices_get_system_memory_types_str();
+ m->machine_type = module_call_method("computer::getMachineType");
free(tmp);
- cpu_procs_cores_threads(&m->processors, &m->cores, &m->threads);
+ cpu_procs_cores_threads_nodes(&m->processors, &m->cores, &m->threads, &m->nodes);
gen_machine_id(m);
}
return m;
}
-void bench_machine_free(bench_machine *s) {
+void bench_machine_free(bench_machine *s)
+{
if (s) {
free(s->board);
free(s->cpu_name);
free(s->cpu_desc);
free(s->cpu_config);
free(s->mid);
+ free(s->ram_types);
+ free(s->machine_type);
+ free(s);
}
}
-void bench_result_free(bench_result *s) {
+void bench_result_free(bench_result *s)
+{
if (s) {
free(s->name);
bench_machine_free(s->machine);
+ g_free(s);
}
}
-bench_result *bench_result_this_machine(const char *bench_name, bench_value r) {
+bench_result *bench_result_this_machine(const char *bench_name, bench_value r)
+{
bench_result *b = NULL;
b = malloc(sizeof(bench_result));
@@ -195,13 +232,14 @@ bench_result *bench_result_this_machine(const char *bench_name, bench_value r) {
}
/* -1 for none */
-static int nx_prefix(const char *str) {
+static int nx_prefix(const char *str)
+{
char *s, *x;
if (str != NULL) {
- s = (char*)str;
+ s = (char *)str;
x = strchr(str, 'x');
- if (x && x-s >= 1) {
- while(s != x) {
+ if (x && x - s >= 1) {
+ while (s != x) {
if (!isdigit(*s))
return -1;
s++;
@@ -214,11 +252,13 @@ static int nx_prefix(const char *str) {
}
/* old results didn't store the actual number of threads used */
-static int guess_threads_old_result(const char *bench_name, int threads_available) {
+static int guess_threads_old_result(const char *bench_name,
+ int threads_available)
+{
#define CHKBNAME(BN) (strcmp(bench_name, BN) == 0)
- if (CHKBNAME("CPU Fibonacci") )
+ if (CHKBNAME("CPU Fibonacci"))
return 1;
- if (CHKBNAME("FPU FFT") ) {
+ if (CHKBNAME("FPU FFT")) {
if (threads_available >= 4)
return 4;
else if (threads_available >= 2)
@@ -226,7 +266,7 @@ static int guess_threads_old_result(const char *bench_name, int threads_availabl
else
return 1;
}
- if (CHKBNAME("CPU N-Queens") ) {
+ if (CHKBNAME("CPU N-Queens")) {
if (threads_available >= 10)
return 10;
else if (threads_available >= 5)
@@ -239,204 +279,327 @@ static int guess_threads_old_result(const char *bench_name, int threads_availabl
return threads_available;
}
-bench_result *bench_result_benchmarkconf(const char *section, const char *key, char **values) {
- bench_result *b = NULL;
- char *s0, *s1, *s2;
- int nx = 0, vl = 0;
- float n, m;
+static gboolean cpu_name_needs_cleanup(const char *cpu_name)
+{
+ return strstr(cpu_name, "Intel") || strstr(cpu_name, "AMD") ||
+ strstr(cpu_name, "VIA") || strstr(cpu_name, "Cyrix");
+}
- vl = g_strv_length(values);
+static void filter_invalid_chars(gchar *str)
+{
+ gchar *p;
- b = malloc(sizeof(bench_result));
- if (b) {
- memset(b, 0, sizeof(bench_result));
- b->machine = bench_machine_new();
- b->name = strdup(section);
-
- if (vl >= 10) { /* the 11th could be empty */
- b->machine->mid = strdup(key);
- /* first try as bench_value, then try as double 'result' only */
- b->bvalue = bench_value_from_str(values[0]);
- if (b->bvalue.result == -1)
- b->bvalue.result = atoi(values[0]);
- b->bvalue.threads_used = atoi(values[1]);
- b->machine->board = strdup(values[2]);
- b->machine->cpu_name = strdup(values[3]);
- b->machine->cpu_desc = strdup(values[4]);
- b->machine->cpu_config = strdup(values[5]);
- b->machine->memory_kiB = atoi(values[6]);
- b->machine->processors = atoi(values[7]);
- b->machine->cores = atoi(values[8]);
- b->machine->threads = atoi(values[9]);
- if (vl >= 11)
- b->machine->ogl_renderer = strdup(values[10]);
- b->legacy = 0;
- } else if (vl >= 2) {
- b->bvalue.result = atof(values[0]);
- b->legacy = 1;
-
- /* old old format has prefix before cpu name (ex: 4x Pentium...) */
- nx = nx_prefix(key);
- if (nx > 0) {
- b->machine->cpu_name = strdup(strchr(key, 'x') + 1);
- b->machine->threads = nx;
- } else {
- b->machine->cpu_name = strdup(key);
- b->machine->threads = 1;
- }
+ for (p = str; *p; p++) {
+ if (*p == '\n' || *p == ';' || *p == '|')
+ *p = '_';
+ }
+}
- b->machine->cpu_config = strdup(values[1]);
- /* new old format has cpu_config string with nx prefix */
- nx = nx_prefix(values[1]);
- if (nx > 0) {
- b->machine->threads = nx;
- }
+static gboolean json_get_boolean(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return FALSE;
+ return json_object_get_boolean_member(obj, key);
+}
- b->bvalue.threads_used = guess_threads_old_result(section, b->machine->threads);
-
- /* If the clock rate in the id string is more than the
- * config string, use that. Older hardinfo used current cpu freq
- * instead of max freq.
- * "...@ 2.00GHz" -> 2000.0 */
- s0 = b->machine->cpu_name;
- s2 = strstr(s0, "Hz");
- if (s2 && s2 > s0 + 2) {
- m = 1; /* assume M */
- if (*(s2-1) == 'G')
- m = 1000;
- s1 = s2 - 2;
- while (s1 > s0) {
- if (!( isdigit(*s1) || *s1 == '.' || *s1 == ' '))
- break;
- s1--;
- }
-
- if (s1 > s0) {
- n = atof(s1+1);
- n *= m;
-
- s1 = g_strdup_printf("%dx %.2f %s", b->bvalue.threads_used, n, _("MHz"));
- if ( cpu_config_cmp(b->machine->cpu_config, s1) == -1
- && !cpu_config_is_close(b->machine->cpu_config, s1) ) {
- free(b->machine->cpu_config);
- b->machine->cpu_config = s1;
- } else {
- free(s1);
- }
- }
- }
+static double json_get_double(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return 0;
+ return json_object_get_double_member(obj, key);
+}
- /* old results only give threads */
- b->machine->processors = -1;
- b->machine->cores = -1;
- }
+static int json_get_int(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return 0;
+ return json_object_get_int_member(obj, key);
+}
- b->machine->cpu_config = cpu_config_retranslate(b->machine->cpu_config, 0, 1);
- if (b->machine->board != NULL && strlen(b->machine->board) == 0) {
- free(b->machine->board);
- b->machine->board = NULL;
- }
- if (b->machine->cpu_desc != NULL && strlen(b->machine->cpu_desc) == 0) {
- free(b->machine->cpu_desc);
- b->machine->cpu_desc = NULL;
- }
- gen_machine_id(b->machine);
- }
- return b;
+static const gchar *json_get_string(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return "";
+ return json_object_get_string_member(obj, key);
+}
+
+static gchar *json_get_string_dup(JsonObject *obj, const gchar *key)
+{
+ return g_strdup(json_get_string(obj, key));
+}
+
+static double parse_frequency(const char *freq)
+{
+ static locale_t locale;
+
+ if (!locale)
+ locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
+
+ return strtod_l(freq, NULL, locale);
+}
+
+static void append_cpu_config(JsonObject *object,
+ const gchar *member_name,
+ JsonNode *member_node,
+ gpointer user_data)
+{
+ GString *output = user_data;
+
+ if (output->len)
+ g_string_append(output, ", ");
+
+ g_string_append_printf(output, "%ldx %.2f %s", (long int)json_node_get_int(member_node),
+ parse_frequency(member_name), _("MHz"));
}
-char *bench_result_benchmarkconf_line(bench_result *b) {
- char *cpu_config = cpu_config_retranslate(b->machine->cpu_config, 1, 0);
- char *bv = bench_value_to_str(b->bvalue);
- char *ret = g_strdup_printf("%s=%s|%d|%s|%s|%s|%s|%d|%d|%d|%d|%s\n",
- b->machine->mid, bv, b->bvalue.threads_used,
- (b->machine->board != NULL) ? b->machine->board : "",
- b->machine->cpu_name,
- (b->machine->cpu_desc != NULL) ? b->machine->cpu_desc : "",
- cpu_config,
- b->machine->memory_kiB,
- b->machine->processors, b->machine->cores, b->machine->threads,
- (b->machine->ogl_renderer != NULL) ? b->machine->ogl_renderer : ""
- );
- free(cpu_config);
- free(bv);
+static gchar *get_cpu_config(JsonObject *machine)
+{
+ JsonObject *cpu_config_map =
+ json_object_get_object_member(machine, "CpuConfigMap");
+
+ if (!cpu_config_map)
+ return json_get_string_dup(machine, "CpuConfig");
+
+ GString *output = g_string_new(NULL);
+ json_object_foreach_member(cpu_config_map, append_cpu_config, output);
+ return g_string_free(output, FALSE);
+}
+
+static gchar *get_cpu_desc(JsonObject *machine)
+{
+ int num_cpus = json_get_int(machine, "NumCpus");
+
+ if (!num_cpus)
+ return json_get_string_dup(machine, "CpuDesc");
+
+ /* FIXME: This is adapted from processor_describe_default() in
+ * devices.c! */
+
+ int num_cores = json_get_int(machine, "NumCores");
+ int num_threads = json_get_int(machine, "NumThreads");
+ int num_nodes = json_get_int(machine, "NumNodes");
+ const char *packs_fmt =
+ ngettext("%d physical processor", "%d physical processors", num_cpus);
+ const char *cores_fmt = ngettext("%d core", "%d cores", num_cores);
+ const char *threads_fmt = ngettext("%d thread", "%d threads", num_threads);
+ char *full_fmt, *ret;
+
+ if (num_nodes > 1) {
+ const char *nodes_fmt =
+ ngettext("%d NUMA node", "%d NUMA nodes", num_nodes);
+
+ full_fmt = g_strdup_printf(
+ _(/*/NP procs; NC cores across NN nodes; NT threads*/
+ "%s; %s across %s; %s"),
+ packs_fmt, cores_fmt, nodes_fmt, threads_fmt);
+ ret = g_strdup_printf(full_fmt, num_cpus, num_cores * num_nodes, num_nodes, num_threads);
+ } else {
+ full_fmt =
+ g_strdup_printf(_(/*/NP procs; NC cores; NT threads*/ "%s; %s; %s"),
+ packs_fmt, cores_fmt, threads_fmt);
+ ret = g_strdup_printf(full_fmt, num_cpus, num_cores, num_threads);
+ }
+
+ free(full_fmt);
return ret;
}
-static char *bench_result_more_info_less(bench_result *b) {
- char *memory =
- (b->machine->memory_kiB > 0)
- ? g_strdup_printf("%d %s", b->machine->memory_kiB, _("kiB") )
- : g_strdup(_(unk) );
-
- char *ret = g_strdup_printf("[%s]\n"
- /* threads */ "%s=%d\n"
- /* legacy */ "%s=%s\n"
- "[%s]\n"
- /* board */ "%s=%s\n"
- /* cpu */ "%s=%s\n"
- /* cpudesc */ "%s=%s\n"
- /* cpucfg */ "%s=%s\n"
- /* threads */ "%s=%d\n"
- /* ogl rend */ "%s=%s\n"
- /* mem */ "%s=%s\n",
- _("Benchmark Result"),
- _("Threads"), b->bvalue.threads_used,
- b->legacy ? _("Note") : "#Note",
- b->legacy ? _("This result is from an old version of HardInfo. Results might not be comparable to current version. Some details are missing.") : "",
- _("Machine"),
- _("Board"), (b->machine->board != NULL) ? b->machine->board : _(unk),
- _("CPU Name"), b->machine->cpu_name,
- _("CPU Description"), (b->machine->cpu_desc != NULL) ? b->machine->cpu_desc : _(unk),
- _("CPU Config"), b->machine->cpu_config,
- _("Threads Available"), b->machine->threads,
- _("OpenGL Renderer"), (b->machine->ogl_renderer != NULL) ? b->machine->ogl_renderer : _(unk),
- _("Memory"), memory
- );
+bench_result *bench_result_benchmarkjson(const gchar *bench_name,
+ JsonNode *node)
+{
+ JsonObject *machine;
+ bench_result *b;
+ gchar *p;
+
+ if (json_node_get_node_type(node) != JSON_NODE_OBJECT)
+ return NULL;
+
+ machine = json_node_get_object(node);
+
+ b = g_new0(bench_result, 1);
+ b->name = g_strdup(bench_name);
+ b->legacy = json_get_boolean(machine, "Legacy");
+
+ b->bvalue = (bench_value){
+ .result = json_get_double(machine, "BenchmarkResult"),
+ .elapsed_time = json_get_double(machine, "ElapsedTime"),
+ .threads_used = json_get_int(machine, "UsedThreads"),
+ .revision = json_get_int(machine, "BenchmarkRevision"),
+ };
+
+ snprintf(b->bvalue.extra, sizeof(b->bvalue.extra), "%s",
+ json_get_string(machine, "ExtraInfo"));
+ filter_invalid_chars(b->bvalue.extra);
+
+ snprintf(b->bvalue.user_note, sizeof(b->bvalue.user_note), "%s",
+ json_get_string(machine, "UserNote"));
+ filter_invalid_chars(b->bvalue.user_note);
+
+ int nodes = json_get_int(machine, "NumNodes");
+
+ if (nodes == 0)
+ nodes = 1;
+
+ b->machine = bench_machine_new();
+ *b->machine = (bench_machine){
+ .board = json_get_string_dup(machine, "Board"),
+ .memory_kiB = json_get_int(machine, "MemoryInKiB"),
+ .cpu_name = json_get_string_dup(machine, "CpuName"),
+ .cpu_desc = get_cpu_desc(machine),
+ .cpu_config = get_cpu_config(machine),
+ .ogl_renderer = json_get_string_dup(machine, "OpenGlRenderer"),
+ .gpu_desc = json_get_string_dup(machine, "GpuDesc"),
+ .processors = json_get_int(machine, "NumCpus"),
+ .cores = json_get_int(machine, "NumCores"),
+ .threads = json_get_int(machine, "NumThreads"),
+ .nodes = nodes,
+ .mid = json_get_string_dup(machine, "MachineId"),
+ .ptr_bits = json_get_int(machine, "PointerBits"),
+ .is_su_data = json_get_boolean(machine, "DataFromSuperUser"),
+ .memory_phys_MiB = json_get_int(machine, "PhysicalMemoryInMiB"),
+ .ram_types = json_get_string_dup(machine, "MemoryTypes"),
+ .machine_data_version = json_get_int(machine, "MachineDataVersion"),
+ .machine_type = json_get_string_dup(machine, "MachineType"),
+ };
+
+ return b;
+}
+
+static char *bench_result_more_info_less(bench_result *b)
+{
+ char *memory = NULL;
+ if (b->machine->memory_phys_MiB) {
+ memory =
+ g_strdup_printf("%" PRId64 " %s %s", b->machine->memory_phys_MiB,
+ _("MiB"), b->machine->ram_types);
+ } else {
+ memory =
+ (b->machine->memory_kiB > 0)
+ ? g_strdup_printf("%" PRId64 " %s %s", b->machine->memory_kiB,
+ _("kiB"), problem_marker())
+ : g_strdup(_(unk));
+ }
+ char bench_str[256] = "";
+ if (b->bvalue.revision >= 0)
+ snprintf(bench_str, 127, "%d", b->bvalue.revision);
+ char bits[24] = "";
+ if (b->machine->ptr_bits)
+ snprintf(bits, 23, _("%d-bit"), b->machine->ptr_bits);
+
+ char *ret = g_strdup_printf(
+ "[%s]\n"
+ /* threads */ "%s=%d\n"
+ /* elapsed */ "%s=%0.4f %s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ /* legacy */ "%s%s=%s\n"
+ "[%s]\n"
+ /* board */ "%s=%s\n"
+ /* machine_type */ "%s=%s\n"
+ /* cpu */ "%s=%s\n"
+ /* cpudesc */ "%s=%s\n"
+ /* cpucfg */ "%s=%s\n"
+ /* threads */ "%s=%d\n"
+ /* gpu desc */ "%s=%s\n"
+ /* ogl rend */ "%s=%s\n"
+ /* mem */ "%s=%s\n"
+ /* bits */ "%s=%s\n",
+ _("Benchmark Result"), _("Threads"), b->bvalue.threads_used,
+ _("Elapsed Time"), b->bvalue.elapsed_time, _("seconds"),
+ *bench_str ? _("Revision") : "#Revision", bench_str,
+ *b->bvalue.extra ? _("Extra Information") : "#Extra", b->bvalue.extra,
+ *b->bvalue.user_note ? _("User Note") : "#User Note",
+ b->bvalue.user_note, b->legacy ? problem_marker() : "",
+ b->legacy ? _("Note") : "#Note",
+ b->legacy ? _("This result is from an old version of HardInfo. Results "
+ "might not be comparable to current version. Some "
+ "details are missing.")
+ : "",
+ _("Machine"),
+ _("Board"), (b->machine->board != NULL) ? b->machine->board : _(unk),
+ _("Machine Type"), (b->machine->machine_type != NULL) ? b->machine->machine_type : _(unk),
+ _("CPU Name"), b->machine->cpu_name,
+ _("CPU Description"), (b->machine->cpu_desc != NULL) ? b->machine->cpu_desc : _(unk),
+ _("CPU Config"), b->machine->cpu_config,
+ _("Threads Available"), b->machine->threads,
+ _("GPU"), (b->machine->gpu_desc != NULL) ? b->machine->gpu_desc : _(unk),
+ _("OpenGL Renderer"), (b->machine->ogl_renderer != NULL) ? b->machine->ogl_renderer : _(unk),
+ _("Memory"), memory,
+ b->machine->ptr_bits ? _("Pointer Size") : "#AddySize", bits);
free(memory);
return ret;
}
-static char *bench_result_more_info_complete(bench_result *b) {
- return g_strdup_printf("[%s]\n"
- /* bench name */"%s=%s\n"
- /* threads */ "%s=%d\n"
- /* result */ "%s=%0.2f\n"
- /* elapsed */ "%s=%0.2f\n"
- /* legacy */ "%s=%s\n"
- "[%s]\n"
- /* board */ "%s=%s\n"
- /* cpu */ "%s=%s\n"
- /* cpudesc */ "%s=%s\n"
- /* cpucfg */ "%s=%s\n"
- /* threads */ "%s=%d\n"
- /* ogl rend */ "%s=%s\n"
- /* mem */ "%s=%d %s\n"
- "[%s]\n"
- /* mid */ "%s=%s\n"
- /* cfg_val */ "%s=%.2f\n",
- _("Benchmark Result"),
- _("Benchmark"), b->name,
- _("Threads"), b->bvalue.threads_used,
- _("Result"), b->bvalue.result,
- _("Elapsed Time"), b->bvalue.elapsed_time,
- b->legacy ? _("Note") : "#Note",
- b->legacy ? _("This result is from an old version of HardInfo. Results might not be comparable to current version. Some details are missing.") : "",
- _("Machine"),
- _("Board"), (b->machine->board != NULL) ? b->machine->board : _(unk),
- _("CPU Name"), b->machine->cpu_name,
- _("CPU Description"), (b->machine->cpu_desc != NULL) ? b->machine->cpu_desc : _(unk),
- _("CPU Config"), b->machine->cpu_config,
- _("Threads Available"), b->machine->threads,
- _("OpenGL Renderer"), (b->machine->ogl_renderer != NULL) ? b->machine->ogl_renderer : _(unk),
- _("Memory"), b->machine->memory_kiB, _("kiB"),
- _("Handles"),
- _("mid"), b->machine->mid,
- _("cfg_val"), cpu_config_val(b->machine->cpu_config)
- );
+static char *bench_result_more_info_complete(bench_result *b)
+{
+ char bench_str[256] = "";
+ strncpy(bench_str, b->name, 127);
+ if (b->bvalue.revision >= 0)
+ snprintf(bench_str + strlen(bench_str), 127, " (r%d)",
+ b->bvalue.revision);
+ char bits[24] = "";
+ if (b->machine->ptr_bits)
+ snprintf(bits, 23, _("%d-bit"), b->machine->ptr_bits);
+
+ return g_strdup_printf(
+ "[%s]\n"
+ /* bench name */ "%s=%s\n"
+ /* threads */ "%s=%d\n"
+ /* result */ "%s=%0.2f\n"
+ /* elapsed */ "%s=%0.4f %s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ /* legacy */ "%s%s=%s\n"
+ "[%s]\n"
+ /* board */ "%s=%s\n"
+ /* machine_type */ "%s=%s\n"
+ /* cpu */ "%s=%s\n"
+ /* cpudesc */ "%s=%s\n"
+ /* cpucfg */ "%s=%s\n"
+ /* threads */ "%s=%d\n"
+ /* gpu desc */ "%s=%s\n"
+ /* ogl rend */ "%s=%s\n"
+ /* mem */ "%s=%" PRId64 " %s\n"
+ /* mem phys */ "%s=%" PRId64 " %s %s\n"
+ /* bits */ "%s=%s\n"
+ "%s=%d\n"
+ "%s=%d\n"
+ "[%s]\n"
+ /* mid */ "%s=%s\n"
+ /* cfg_val */ "%s=%.2f\n",
+ _("Benchmark Result"), _("Benchmark"), bench_str, _("Threads"),
+ b->bvalue.threads_used, _("Result"), b->bvalue.result,
+ _("Elapsed Time"), b->bvalue.elapsed_time, _("seconds"),
+ *b->bvalue.extra ? _("Extra Information") : "#Extra", b->bvalue.extra,
+ *b->bvalue.user_note ? _("User Note") : "#User Note",
+ b->bvalue.user_note, b->legacy ? problem_marker() : "",
+ b->legacy ? _("Note") : "#Note",
+ b->legacy ? _("This result is from an old version of HardInfo. Results "
+ "might not be comparable to current version. Some "
+ "details are missing.")
+ : "",
+ _("Machine"), _("Board"),
+ (b->machine->board != NULL) ? b->machine->board : _(unk),
+ _("Machine Type"), (b->machine->machine_type != NULL) ? b->machine->machine_type : _(unk),
+ _("CPU Name"),
+ b->machine->cpu_name, _("CPU Description"),
+ (b->machine->cpu_desc != NULL) ? b->machine->cpu_desc : _(unk),
+ _("CPU Config"), b->machine->cpu_config, _("Threads Available"),
+ b->machine->threads, _("GPU"),
+ (b->machine->gpu_desc != NULL) ? b->machine->gpu_desc : _(unk),
+ _("OpenGL Renderer"),
+ (b->machine->ogl_renderer != NULL) ? b->machine->ogl_renderer : _(unk),
+ _("Memory"), b->machine->memory_kiB, _("kiB"), _("Physical Memory"),
+ b->machine->memory_phys_MiB, _("MiB"), b->machine->ram_types,
+ b->machine->ptr_bits ? _("Pointer Size") : "#AddySize", bits,
+ ".machine_data_version", b->machine->machine_data_version,
+ ".is_su_data", b->machine->is_su_data, _("Handles"), _("mid"),
+ b->machine->mid, _("cfg_val"), cpu_config_val(b->machine->cpu_config));
}
-char *bench_result_more_info(bench_result *b) {
- //return bench_result_more_info_complete(b);
+char *bench_result_more_info(bench_result *b)
+{
+ // return bench_result_more_info_complete(b);
return bench_result_more_info_less(b);
}
diff --git a/modules/benchmark/bench_util.c b/modules/benchmark/bench_util.c
new file mode 100644
index 00000000..d9e5bc55
--- /dev/null
+++ b/modules/benchmark/bench_util.c
@@ -0,0 +1,58 @@
+
+#include "benchmark.h"
+#include "md5.h"
+
+gchar *get_test_data(gsize min_size) {
+ gchar *bdata_path, *data;
+ gsize data_size;
+
+ gchar *exp_data, *p;
+ gsize sz;
+
+ bdata_path = g_build_filename(params.path_data, "benchmark.data", NULL);
+ if (!g_file_get_contents(bdata_path, &data, &data_size, NULL)) {
+ g_free(bdata_path);
+ return NULL;
+ }
+
+ if (data_size < min_size) {
+ DEBUG("expanding %lu bytes of test data to %lu bytes", data_size, min_size);
+ exp_data = g_malloc(min_size + 1);
+ memcpy(exp_data, data, data_size);
+ p = exp_data + data_size;
+ sz = data_size;
+ while (sz < (min_size - data_size) ) {
+ memcpy(p, data, data_size);
+ p += data_size;
+ sz += data_size;
+ }
+ strncpy(p, data, min_size - sz);
+ g_free(data);
+ data = exp_data;
+ }
+ g_free(bdata_path);
+
+ return data;
+}
+
+char *digest_to_str(const char *digest, int len) {
+ int max = len * 2;
+ char *ret = malloc(max+1);
+ char *p = ret;
+ memset(ret, 0, max+1);
+ int i = 0;
+ for(; i < len; i++) {
+ unsigned char byte = digest[i];
+ p += sprintf(p, "%02x", byte);
+ }
+ return ret;
+}
+
+char *md5_digest_str(const char *data, unsigned int len) {
+ struct MD5Context ctx;
+ guchar digest[16];
+ MD5Init(&ctx);
+ MD5Update(&ctx, (guchar *)data, len);
+ MD5Final(digest, &ctx);
+ return digest_to_str(digest, 16);
+}
diff --git a/modules/benchmark/benches.c b/modules/benchmark/benches.c
index e09dedcc..c621d695 100644
--- a/modules/benchmark/benches.c
+++ b/modules/benchmark/benches.c
@@ -1,10 +1,10 @@
/*
- * HardInfo - Displays System Information
- * Copyright (C) 2003-2017 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * HardInfo - System Information and Benchmark
+ * Copyright (C) 2003-2017 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -26,15 +26,6 @@ gchar *CN() { \
return benchmark_include_results(bench_results[BID], BN); \
}
-BENCH_CALLBACK(callback_gui, "GPU Drawing", BENCHMARK_GUI, 1);
-BENCH_CALLBACK(callback_fft, "FPU FFT", BENCHMARK_FFT, 0);
-BENCH_CALLBACK(callback_nqueens, "CPU N-Queens", BENCHMARK_NQUEENS, 0);
-BENCH_CALLBACK(callback_raytr, "FPU Raytracing", BENCHMARK_RAYTRACE, 0);
-BENCH_CALLBACK(callback_bfsh, "CPU Blowfish", BENCHMARK_BLOWFISH, 0);
-BENCH_CALLBACK(callback_cryptohash, "CPU CryptoHash", BENCHMARK_CRYPTOHASH, 1);
-BENCH_CALLBACK(callback_fib, "CPU Fibonacci", BENCHMARK_FIB, 0);
-BENCH_CALLBACK(callback_zlib, "CPU Zlib", BENCHMARK_ZLIB, 0);
-
#define BENCH_SCAN_SIMPLE(SN, BF, BID) \
void SN(gboolean reload) { \
SCAN_START(); \
@@ -42,14 +33,30 @@ void SN(gboolean reload) { \
SCAN_END(); \
}
-BENCH_SCAN_SIMPLE(scan_fft, benchmark_fft, BENCHMARK_FFT);
-BENCH_SCAN_SIMPLE(scan_nqueens, benchmark_nqueens, BENCHMARK_NQUEENS);
-BENCH_SCAN_SIMPLE(scan_raytr, benchmark_raytrace, BENCHMARK_RAYTRACE);
-BENCH_SCAN_SIMPLE(scan_bfsh, benchmark_fish, BENCHMARK_BLOWFISH);
-BENCH_SCAN_SIMPLE(scan_cryptohash, benchmark_cryptohash, BENCHMARK_CRYPTOHASH);
-BENCH_SCAN_SIMPLE(scan_fib, benchmark_fib, BENCHMARK_FIB);
-BENCH_SCAN_SIMPLE(scan_zlib, benchmark_zlib, BENCHMARK_ZLIB);
+#define BENCH_SIMPLE(BID, BN, BF, R) \
+ BENCH_CALLBACK(callback_##BF, BN, BID, R); \
+ BENCH_SCAN_SIMPLE(scan_##BF, BF, BID);
+// ID, NAME, FUNCTION, R (0 = lower is better, 1 = higher is better)
+BENCH_SIMPLE(BENCHMARK_FIB, "CPU Fibonacci", benchmark_fib, 1);
+BENCH_SIMPLE(BENCHMARK_NQUEENS, "CPU N-Queens", benchmark_nqueens, 1);
+BENCH_SIMPLE(BENCHMARK_FFT, "FPU FFT", benchmark_fft, 1);
+BENCH_SIMPLE(BENCHMARK_RAYTRACE, "FPU Raytracing (Single-thread)", benchmark_raytrace, 1);
+BENCH_SIMPLE(BENCHMARK_BLOWFISH_SINGLE, "CPU Blowfish (Single-thread)", benchmark_bfish_single, 1);
+BENCH_SIMPLE(BENCHMARK_BLOWFISH_THREADS, "CPU Blowfish (Multi-thread)", benchmark_bfish_threads, 1);
+BENCH_SIMPLE(BENCHMARK_BLOWFISH_CORES, "CPU Blowfish (Multi-core)", benchmark_bfish_cores, 1);
+BENCH_SIMPLE(BENCHMARK_ZLIB, "CPU Zlib", benchmark_zlib, 1);
+BENCH_SIMPLE(BENCHMARK_CRYPTOHASH, "CPU CryptoHash", benchmark_cryptohash, 1);
+BENCH_SIMPLE(BENCHMARK_SBCPU_SINGLE, "SysBench CPU (Single-thread)", benchmark_sbcpu_single, 1);
+BENCH_SIMPLE(BENCHMARK_SBCPU_ALL, "SysBench CPU (Multi-thread)", benchmark_sbcpu_all, 1);
+BENCH_SIMPLE(BENCHMARK_SBCPU_QUAD, "SysBench CPU (Four threads)", benchmark_sbcpu_quad, 1);
+BENCH_SIMPLE(BENCHMARK_MEMORY_SINGLE, "SysBench Memory (Single-thread)", benchmark_memory_single, 1);
+BENCH_SIMPLE(BENCHMARK_MEMORY_DUAL, "SysBench Memory (Two threads)", benchmark_memory_dual, 1);
+BENCH_SIMPLE(BENCHMARK_MEMORY_QUAD, "SysBench Memory (Quad threads)", benchmark_memory_quad, 1);
+BENCH_SIMPLE(BENCHMARK_MEMORY_ALL, "SysBench Memory (Multi-thread)", benchmark_memory_all, 1);
+
+#if !GTK_CHECK_VERSION(3,0,0)
+BENCH_CALLBACK(callback_gui, "GPU Drawing", BENCHMARK_GUI, 1);
void scan_gui(gboolean reload)
{
SCAN_START();
@@ -69,37 +76,178 @@ void scan_gui(gboolean reload)
}
SCAN_END();
}
+#endif
static ModuleEntry entries[] = {
- {N_("CPU Blowfish"), "blowfish.png", callback_bfsh, scan_bfsh, MODULE_FLAG_NONE},
- {N_("CPU CryptoHash"), "cryptohash.png", callback_cryptohash, scan_cryptohash, MODULE_FLAG_NONE},
- {N_("CPU Fibonacci"), "nautilus.png", callback_fib, scan_fib, MODULE_FLAG_NONE},
- {N_("CPU N-Queens"), "nqueens.png", callback_nqueens, scan_nqueens, MODULE_FLAG_NONE},
- {N_("CPU Zlib"), "file-roller.png", callback_zlib, scan_zlib, MODULE_FLAG_NONE},
- {N_("FPU FFT"), "fft.png", callback_fft, scan_fft, MODULE_FLAG_NONE},
- {N_("FPU Raytracing"), "raytrace.png", callback_raytr, scan_raytr, MODULE_FLAG_NONE},
-#if !GTK_CHECK_VERSION(3,0,0)
- {N_("GPU Drawing"), "module.png", callback_gui, scan_gui, MODULE_FLAG_NO_REMOTE},
+ [BENCHMARK_BLOWFISH_SINGLE] =
+ {
+ N_("CPU Blowfish (Single-thread)"),
+ "blowfish.png",
+ callback_benchmark_bfish_single,
+ scan_benchmark_bfish_single,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_BLOWFISH_THREADS] =
+ {
+ N_("CPU Blowfish (Multi-thread)"),
+ "blowfish.png",
+ callback_benchmark_bfish_threads,
+ scan_benchmark_bfish_threads,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_BLOWFISH_CORES] =
+ {
+ N_("CPU Blowfish (Multi-core)"),
+ "blowfish.png",
+ callback_benchmark_bfish_cores,
+ scan_benchmark_bfish_cores,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_ZLIB] =
+ {
+ N_("CPU Zlib"),
+ "file-roller.png",
+ callback_benchmark_zlib,
+ scan_benchmark_zlib,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_CRYPTOHASH] =
+ {
+ N_("CPU CryptoHash"),
+ "cryptohash.png",
+ callback_benchmark_cryptohash,
+ scan_benchmark_cryptohash,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_FIB] =
+ {
+ N_("CPU Fibonacci"),
+ "nautilus.png",
+ callback_benchmark_fib,
+ scan_benchmark_fib,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_NQUEENS] =
+ {
+ N_("CPU N-Queens"),
+ "nqueens.png",
+ callback_benchmark_nqueens,
+ scan_benchmark_nqueens,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_FFT] =
+ {
+ N_("FPU FFT"),
+ "fft.png",
+ callback_benchmark_fft,
+ scan_benchmark_fft,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_RAYTRACE] =
+ {
+ N_("FPU Raytracing (Single-thread)"),
+ "raytrace.png",
+ callback_benchmark_raytrace,
+ scan_benchmark_raytrace,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_SBCPU_SINGLE] =
+ {
+ N_("SysBench CPU (Single-thread)"),
+ "processor.png",
+ callback_benchmark_sbcpu_single,
+ scan_benchmark_sbcpu_single,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_SBCPU_ALL] =
+ {
+ N_("SysBench CPU (Multi-thread)"),
+ "processor.png",
+ callback_benchmark_sbcpu_all,
+ scan_benchmark_sbcpu_all,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_SBCPU_QUAD] =
+ {
+ N_("SysBench CPU (Four threads)"),
+ "processor.png",
+ callback_benchmark_sbcpu_quad,
+ scan_benchmark_sbcpu_quad,
+ MODULE_FLAG_HIDE,
+ },
+ [BENCHMARK_MEMORY_SINGLE] =
+ {
+ N_("SysBench Memory (Single-thread)"),
+ "memory.png",
+ callback_benchmark_memory_single,
+ scan_benchmark_memory_single,
+ MODULE_FLAG_NONE,
+ },
+ [BENCHMARK_MEMORY_DUAL] =
+ {
+ N_("SysBench Memory (Two threads)"),
+ "memory.png",
+ callback_benchmark_memory_dual,
+ scan_benchmark_memory_dual,
+ MODULE_FLAG_HIDE,
+ },
+ [BENCHMARK_MEMORY_QUAD] =
+ {
+ N_("SysBench Memory (Quad threads)"),
+ "memory.png",
+ callback_benchmark_memory_quad,
+ scan_benchmark_memory_quad,
+ MODULE_FLAG_HIDE,
+ },
+ [BENCHMARK_MEMORY_ALL] =
+ {
+ N_("SysBench Memory (Multi-thread)"),
+ "memory.png",
+ callback_benchmark_memory_all,
+ scan_benchmark_memory_all,
+ MODULE_FLAG_NONE,
+ },
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ [BENCHMARK_GUI] =
+ {
+ N_("GPU Drawing"),
+ "module.png",
+ callback_gui,
+ scan_gui,
+ MODULE_FLAG_NO_REMOTE | MODULE_FLAG_HIDE,
+ },
+#else
+ [BENCHMARK_GUI] = {"#"},
#endif
- {NULL}
-};
+ {NULL}};
const gchar *hi_note_func(gint entry)
{
switch (entry) {
- case BENCHMARK_CRYPTOHASH:
- return _("Results in MiB/second. Higher is better.");
+ case BENCHMARK_SBCPU_SINGLE:
+ case BENCHMARK_SBCPU_QUAD:
+ case BENCHMARK_SBCPU_ALL:
+ return _("Alexey Kopytov's <i><b>sysbench</b></i> is required.\n"
+ "Results in events/second. Higher is better.");
+
+ case BENCHMARK_MEMORY_SINGLE:
+ case BENCHMARK_MEMORY_DUAL:
+ case BENCHMARK_MEMORY_QUAD:
+ case BENCHMARK_MEMORY_ALL:
+ return _("Alexey Kopytov's <i><b>sysbench</b></i> is required.\n"
+ "Results in MiB/second. Higher is better.");
+ case BENCHMARK_CRYPTOHASH:
+ case BENCHMARK_BLOWFISH_SINGLE:
+ case BENCHMARK_BLOWFISH_THREADS:
+ case BENCHMARK_BLOWFISH_CORES:
case BENCHMARK_ZLIB:
case BENCHMARK_GUI:
- return _("Results in HIMarks. Higher is better.");
-
case BENCHMARK_FFT:
case BENCHMARK_RAYTRACE:
- case BENCHMARK_BLOWFISH:
case BENCHMARK_FIB:
case BENCHMARK_NQUEENS:
- return _("Results in seconds. Lower is better.");
+ return _("Results in HIMarks. Higher is better.");
}
return NULL;
diff --git a/modules/benchmark/blowfish.c b/modules/benchmark/blowfish.c
index 2aa11a2a..f8d2e14a 100644
--- a/modules/benchmark/blowfish.c
+++ b/modules/benchmark/blowfish.c
@@ -491,48 +491,3 @@ void Blowfish_Init(BLOWFISH_CTX * ctx, unsigned char *key, int keyLen)
}
}
}
-
-static gpointer
-parallel_blowfish(unsigned int start, unsigned int end, void *data, gint thread_number)
-{
- BLOWFISH_CTX ctx;
- unsigned int i;
- unsigned long L, R;
-
- L = 0xBEBACAFE;
- R = 0xDEADBEEF;
-
- for (i = start; i <= end; i++) {
- Blowfish_Init(&ctx, (unsigned char*)data, 65536);
- Blowfish_Encrypt(&ctx, &L, &R);
- Blowfish_Decrypt(&ctx, &L, &R);
- }
-
- return NULL;
-}
-
-void
-benchmark_fish(void)
-{
- bench_value r = EMPTY_BENCH_VALUE;
-
- gchar *tmpsrc;
- gchar *bdata_path;
-
- bdata_path = g_build_filename(params.path_data, "benchmark.data", NULL);
- if (!g_file_get_contents(bdata_path, &tmpsrc, NULL, NULL)) {
- bench_results[BENCHMARK_BLOWFISH] = r;
- g_free(bdata_path);
- return;
- }
-
- shell_view_set_enabled(FALSE);
- shell_status_update("Performing Blowfish benchmark...");
-
- r = benchmark_parallel_for(0, 0, 50000, parallel_blowfish, tmpsrc);
- r.result = r.elapsed_time;
-
- bench_results[BENCHMARK_BLOWFISH] = r;
- g_free(bdata_path);
- g_free(tmpsrc);
-}
diff --git a/modules/benchmark/blowfish2.c b/modules/benchmark/blowfish2.c
new file mode 100644
index 00000000..7426bef9
--- /dev/null
+++ b/modules/benchmark/blowfish2.c
@@ -0,0 +1,83 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2017 L. A. F. Pereira <l@tia.mat.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hardinfo.h"
+#include "benchmark.h"
+#include "blowfish.h"
+
+/* if anything changes in this block, increment revision */
+#define BENCH_REVISION 1
+#define CRUNCH_TIME 7
+#define BENCH_DATA_SIZE 65536
+#define BENCH_DATA_MD5 "c25cf5c889f7bead2ff39788eedae37b"
+#define BLOW_KEY "Has my shampoo arrived?"
+#define BLOW_KEY_MD5 "6eac709cca51a228bfa70150c9c5a7c4"
+
+static gpointer bfish_exec(const void *in_data, gint thread_number)
+{
+ unsigned char key[] = BLOW_KEY;
+ unsigned char *data = NULL;
+ unsigned long data_len = BENCH_DATA_SIZE, i = 0;
+ BLOWFISH_CTX ctx;
+
+ data = malloc(BENCH_DATA_SIZE);
+ memcpy(data, in_data, BENCH_DATA_SIZE);
+
+ Blowfish_Init(&ctx, key, strlen(key));
+ for(i = 0; i < data_len; i += 8) {
+ Blowfish_Encrypt(&ctx, (unsigned long*)&data[i], (unsigned long*)&data[i+4]);
+ }
+ for(i = 0; i < data_len; i += 8) {
+ Blowfish_Decrypt(&ctx, (unsigned long*)&data[i], (unsigned long*)&data[i+4]);
+ }
+
+ free(data);
+ return NULL;
+}
+
+void benchmark_bfish_do(int threads, int entry, const char *status)
+{
+ bench_value r = EMPTY_BENCH_VALUE;
+ gchar *test_data = get_test_data(BENCH_DATA_SIZE);
+ if (!test_data) return;
+
+ shell_view_set_enabled(FALSE);
+ shell_status_update(status);
+
+ gchar *k = md5_digest_str(BLOW_KEY, strlen(BLOW_KEY));
+ if (!SEQ(k, BLOW_KEY_MD5))
+ bench_msg("test key has different md5sum: expected %s, actual %s", BLOW_KEY_MD5, k);
+ gchar *d = md5_digest_str(test_data, BENCH_DATA_SIZE);
+ if (!SEQ(d, BENCH_DATA_MD5))
+ bench_msg("test data has different md5sum: expected %s, actual %s", BENCH_DATA_MD5, d);
+
+ r = benchmark_crunch_for(CRUNCH_TIME, threads, bfish_exec, test_data);
+ r.result /= 100;
+ r.revision = BENCH_REVISION;
+ snprintf(r.extra, 255, "%0.1fs, k:%s, d:%s", (double)CRUNCH_TIME, k, d);
+
+ g_free(test_data);
+ g_free(k);
+ g_free(d);
+
+ bench_results[entry] = r;
+}
+
+void benchmark_bfish_threads(void) { benchmark_bfish_do(0, BENCHMARK_BLOWFISH_THREADS, "Performing Blowfish benchmark (multi-thread)..."); }
+void benchmark_bfish_single(void) { benchmark_bfish_do(1, BENCHMARK_BLOWFISH_SINGLE, "Performing Blowfish benchmark (single-thread)..."); }
+void benchmark_bfish_cores(void) { benchmark_bfish_do(-1, BENCHMARK_BLOWFISH_CORES, "Performing Blowfish benchmark (multi-core)..."); }
diff --git a/modules/benchmark/cryptohash.c b/modules/benchmark/cryptohash.c
index 6150f3ef..6daef545 100644
--- a/modules/benchmark/cryptohash.c
+++ b/modules/benchmark/cryptohash.c
@@ -1,10 +1,10 @@
/*
- * HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * HardInfo - System Information and Benchmark
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,7 +20,14 @@
#include "sha1.h"
#include "benchmark.h"
-void inline md5_step(char *data, glong srclen)
+/* if anything changes in this block, increment revision */
+#define BENCH_REVISION 2
+#define BENCH_DATA_SIZE 65536
+#define CRUNCH_TIME 5
+#define BENCH_DATA_MD5 "c25cf5c889f7bead2ff39788eedae37b"
+#define STEPS 250
+
+inline void md5_step(char *data, glong srclen)
{
struct MD5Context ctx;
guchar checksum[16];
@@ -30,7 +37,7 @@ void inline md5_step(char *data, glong srclen)
MD5Final(checksum, &ctx);
}
-void inline sha1_step(char *data, glong srclen)
+inline void sha1_step(char *data, glong srclen)
{
SHA1_CTX ctx;
guchar checksum[20];
@@ -40,15 +47,15 @@ void inline sha1_step(char *data, glong srclen)
SHA1Final(checksum, &ctx);
}
-static gpointer cryptohash_for(unsigned int start, unsigned int end, void *data, gint thread_number)
+static gpointer cryptohash_for(void *in_data, gint thread_number)
{
unsigned int i;
- for (i = start; i <= end; i++) {
+ for (i = 0;i <= STEPS; i++) {
if (i & 1) {
- md5_step(data, 65536);
+ md5_step(in_data, BENCH_DATA_SIZE);
} else {
- sha1_step(data, 65536);
+ sha1_step(in_data, BENCH_DATA_SIZE);
}
}
@@ -59,22 +66,24 @@ void
benchmark_cryptohash(void)
{
bench_value r = EMPTY_BENCH_VALUE;
- gchar *tmpsrc, *bdata_path;
-
- bdata_path = g_build_filename(params.path_data, "benchmark.data", NULL);
- if (!g_file_get_contents(bdata_path, &tmpsrc, NULL, NULL)) {
- g_free(bdata_path);
- return;
- }
+ gchar *test_data = get_test_data(BENCH_DATA_SIZE);
+ if (!test_data) return;
shell_view_set_enabled(FALSE);
shell_status_update("Running CryptoHash benchmark...");
- r = benchmark_parallel_for(0, 0, 5000, cryptohash_for, tmpsrc);
+ gchar *d = md5_digest_str(test_data, BENCH_DATA_SIZE);
+ if (!SEQ(d, BENCH_DATA_MD5))
+ bench_msg("test data has different md5sum: expected %s, actual %s", BENCH_DATA_MD5, d);
+
+ r = benchmark_crunch_for(CRUNCH_TIME, 0, cryptohash_for, test_data);
+ r.revision = BENCH_REVISION;
+ snprintf(r.extra, 255, "r:%d, d:%s", STEPS, d);
+
+ g_free(test_data);
+ g_free(d);
- g_free(bdata_path);
- g_free(tmpsrc);
+ r.result /= 10;
- r.result = 312.0 / r.elapsed_time; //TODO: explain in code comments
bench_results[BENCHMARK_CRYPTOHASH] = r;
}
diff --git a/modules/benchmark/drawing.c b/modules/benchmark/drawing.c
index d0905954..e92b9d62 100644
--- a/modules/benchmark/drawing.c
+++ b/modules/benchmark/drawing.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/benchmark/fbench.c b/modules/benchmark/fbench.c
index b5afc1bc..cf1ff934 100644
--- a/modules/benchmark/fbench.c
+++ b/modules/benchmark/fbench.c
@@ -277,9 +277,7 @@ static int itercount; /* The iteration counter for the main loop
optimise out the loop over the ray
tracing code. */
-#ifndef ITERATIONS
-#define ITERATIONS 1000
-#endif
+#define ITERATIONS 300
static int niter = ITERATIONS; /* Iteration counter */
#if 0
@@ -690,8 +688,6 @@ void fbench()
spectral_line[7] = 4340.477; /* G' */
spectral_line[8] = 3968.494; /* H */
- niter = 3000;
-
/* Load test case into working array */
clear_aperture = 4.0;
@@ -701,15 +697,21 @@ void fbench()
s[i + 1][j + 1] = testcase[i][j];
for (itercount = 0; itercount < niter; itercount++) {
- for (paraxial = 0; paraxial <= 1; paraxial++) {
+ /* Do main trace in D light */
- /* Do main trace in D light */
+ paraxial = FALSE;
- trace_line(4, clear_aperture / 2.0);
- od_sa[paraxial][0] = object_distance;
- od_sa[paraxial][1] = axis_slope_angle;
- }
- paraxial = FALSE;
+ trace_line(4, clear_aperture / 2.0);
+ od_sa[0][0] = object_distance;
+ od_sa[0][1] = axis_slope_angle;
+
+ paraxial = TRUE;
+
+ trace_line(4, clear_aperture / 2.0);
+ od_sa[1][0] = object_distance;
+ od_sa[1][1] = axis_slope_angle;
+
+ paraxial = FALSE;
/* Trace marginal ray in C */
diff --git a/modules/benchmark/fft.c b/modules/benchmark/fft.c
index caa52d3d..503a7aaf 100644
--- a/modules/benchmark/fft.c
+++ b/modules/benchmark/fft.c
@@ -1,10 +1,10 @@
/*
- * HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * HardInfo - System Information and Benchmark
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,48 +20,51 @@
#include "benchmark.h"
#include "fftbench.h"
-static gpointer fft_for(unsigned int start, unsigned int end, void *data, gint thread_number)
+/* if anything changes in this block, increment revision */
+#define BENCH_REVISION 2
+#define CRUNCH_TIME 5
+
+static gpointer fft_for(void *in_data, gint thread_number)
{
unsigned int i;
- FFTBench **benches = (FFTBench **)data;
+ FFTBench **benches = (FFTBench **)in_data;
FFTBench *fftbench = (FFTBench *)(benches[thread_number]);
- for (i = start; i <= end; i++) {
- fft_bench_run(fftbench);
- }
+ fft_bench_run(benches[thread_number]);
return NULL;
}
-#define FFT_MAXT 4
-
void
benchmark_fft(void)
{
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
bench_value r = EMPTY_BENCH_VALUE;
int n_cores, i;
gchar *temp;
- FFTBench **benches;
+ FFTBench **benches=NULL;
shell_view_set_enabled(FALSE);
shell_status_update("Running FFT benchmark...");
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
+
/* Pre-allocate all benchmarks */
- benches = g_new0(FFTBench *, FFT_MAXT);
- for (i = 0; i < FFT_MAXT; i++) {
- benches[i] = fft_bench_new();
- }
+ benches = g_new0(FFTBench *, cpu_threads);
+ for (i = 0; i < cpu_threads; i++) {benches[i] = fft_bench_new();}
/* Run the benchmark */
- r = benchmark_parallel_for(FFT_MAXT, 0, FFT_MAXT, fft_for, benches);
+ r = benchmark_crunch_for(CRUNCH_TIME, 0, fft_for, benches);
/* Free up the memory */
- for (i = 0; i < FFT_MAXT; i++) {
- fft_bench_free(benches[i]);
+ for (i = 0; i < cpu_threads; i++) {
+ fft_bench_free(benches[i]);
}
g_free(benches);
- r.result = r.elapsed_time;
+ r.result /= 100;
+
+ r.revision = BENCH_REVISION;
bench_results[BENCHMARK_FFT] = r;
}
diff --git a/modules/benchmark/fftbench.c b/modules/benchmark/fftbench.c
index 89fd5a73..9449cffd 100644
--- a/modules/benchmark/fftbench.c
+++ b/modules/benchmark/fftbench.c
@@ -59,9 +59,9 @@ static double random_double()
return result;
}
-static const int N = 800;
-static const int NM1 = 799; // N - 1
-static const int NP1 = 801; // N + 1
+static const int N = 100;
+static const int NM1 = 99; // N - 1
+static const int NP1 = 101; // N + 1
static void lup_decompose(FFTBench *fftbench)
{
diff --git a/modules/benchmark/fib.c b/modules/benchmark/fib.c
index d75ac367..2bec8bed 100644
--- a/modules/benchmark/fib.c
+++ b/modules/benchmark/fib.c
@@ -1,10 +1,10 @@
/*
- * HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * HardInfo - System Information and Benchmark
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,6 +18,11 @@
#include "benchmark.h"
+/* if anything changes in this block, increment revision */
+#define BENCH_REVISION 2
+#define ANSWER 25
+#define CRUNCH_TIME 5
+
gulong fib(gulong n)
{
if (n == 0)
@@ -27,6 +32,14 @@ gulong fib(gulong n)
return fib(n - 1) + fib(n - 2);
}
+static gpointer fib_for(void *in_data, gint thread_number)
+{
+ fib(ANSWER);
+
+ return NULL;
+}
+
+
void
benchmark_fib(void)
{
@@ -34,19 +47,15 @@ benchmark_fib(void)
bench_value r = EMPTY_BENCH_VALUE;
shell_view_set_enabled(FALSE);
- shell_status_update("Calculating the 42nd Fibonacci number...");
-
- g_timer_reset(timer);
- g_timer_start(timer);
+ shell_status_update("Calculating Fibonacci number...");
- fib(42);
+ r = benchmark_crunch_for(CRUNCH_TIME, 0, fib_for, NULL);
+ //r.threads_used = 1;
- g_timer_stop(timer);
- r.elapsed_time = g_timer_elapsed(timer, NULL);
- g_timer_destroy(timer);
+ r.result /= 100;
- r.threads_used = 1;
- r.result = r.elapsed_time;
+ r.revision = BENCH_REVISION;
+ snprintf(r.extra, 255, "a:%d", ANSWER);
bench_results[BENCHMARK_FIB] = r;
}
diff --git a/modules/benchmark/guibench.c b/modules/benchmark/guibench.c
index b9573278..0faf6b69 100644
--- a/modules/benchmark/guibench.c
+++ b/modules/benchmark/guibench.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2009 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2009 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -108,7 +108,7 @@ static double test_icons(GtkWindow *window)
gc = gdk_gc_new(GDK_DRAWABLE(gdk_window));
timer = g_timer_new();
- pixbufs[0] = icon_cache_get_pixbuf("logo.png");
+ pixbufs[0] = icon_cache_get_pixbuf("hardinfo2.png");
pixbufs[1] = icon_cache_get_pixbuf("syncmanager.png");
pixbufs[2] = icon_cache_get_pixbuf("report-large.png");
diff --git a/modules/benchmark/nqueens.c b/modules/benchmark/nqueens.c
index 78293abb..6aad7638 100644
--- a/modules/benchmark/nqueens.c
+++ b/modules/benchmark/nqueens.c
@@ -9,29 +9,30 @@
#include "hardinfo.h"
#include "benchmark.h"
-#define QUEENS 11
+/* if anything changes in this block, increment revision */
+#define BENCH_REVISION 2
+#define QUEENS 6
+#define CRUNCH_TIME 5
int row[QUEENS];
-bool safe(int x, int y)
-{
+bool safe(int x, int y) {
int i;
for (i = 1; i <= y; i++)
- if (row[y - i] == x || row[y - i] == x - i || row[y - i] == x + i)
- return false;
+ if (row[y - i] == x || row[y - i] == x - i || row[y - i] == x + i)
+ return false;
return true;
}
-int nqueens(int y)
-{
+int nqueens(int y) {
int x;
for (x = 0; x < QUEENS; x++) {
- if (safe((row[y - 1] = x), y - 1)) {
- if (y < QUEENS) {
- nqueens(y + 1);
- } else {
- break;
+ if (safe((row[y - 1] = x), y - 1)) {
+ if (y < QUEENS) {
+ nqueens(y + 1);
+ } else {
+ break;
}
}
}
@@ -39,13 +40,9 @@ int nqueens(int y)
return 0;
}
-static gpointer nqueens_for(unsigned int start, unsigned int end, void *data, gint thread_number)
+static gpointer nqueens_for(void *data, gint thread_number)
{
- unsigned int i;
-
- for (i = start; i <= end; i++) {
- nqueens(0);
- }
+ nqueens(0);
return NULL;
}
@@ -58,9 +55,13 @@ benchmark_nqueens(void)
shell_view_set_enabled(FALSE);
shell_status_update("Running N-Queens benchmark...");
- r = benchmark_parallel_for(0, 0, 10, nqueens_for, NULL);
- r.result = r.elapsed_time;
+ r = benchmark_crunch_for(CRUNCH_TIME, 0, nqueens_for, NULL);
+
+ r.revision = BENCH_REVISION;
+ snprintf(r.extra, 255, "q:%d", QUEENS);
+ r.result /= 25;
+
bench_results[BENCHMARK_NQUEENS] = r;
}
diff --git a/modules/benchmark/raytrace.c b/modules/benchmark/raytrace.c
index c7963583..bddc3232 100644
--- a/modules/benchmark/raytrace.c
+++ b/modules/benchmark/raytrace.c
@@ -1,10 +1,10 @@
/*
- * HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * HardInfo - System Information and Benchmark
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,16 +18,17 @@
#include "benchmark.h"
+/* if anything changes in this block, increment revision */
+#define BENCH_REVISION 2
+#define CRUNCH_TIME 5
+
void fbench(); /* fbench.c */
-static gpointer
-parallel_raytrace(unsigned int start, unsigned int end, gpointer data, gint thread_number)
+static gpointer parallel_raytrace(void *in_data, gint thread_number)
{
unsigned int i;
- for (i = start; i <= end; i++) {
- fbench();
- }
+ fbench();
return NULL;
}
@@ -36,13 +37,20 @@ void
benchmark_raytrace(void)
{
bench_value r = EMPTY_BENCH_VALUE;
+ gchar *test_data = get_test_data(1000);
shell_view_set_enabled(FALSE);
shell_status_update("Performing John Walker's FBENCH...");
- r = benchmark_parallel_for(0, 0, 1000, parallel_raytrace, NULL);
- r.result = r.elapsed_time;
+ r = benchmark_crunch_for(CRUNCH_TIME, 1, parallel_raytrace, test_data);
+
+ r.revision = BENCH_REVISION;
+ snprintf(r.extra, 255, "r:%d", 500);//niter from fbench
+
+ g_free(test_data);
+ r.result /= 10;
+
bench_results[BENCHMARK_RAYTRACE] = r;
}
diff --git a/modules/benchmark/sha1.c b/modules/benchmark/sha1.c
index b94ce254..3b213218 100644
--- a/modules/benchmark/sha1.c
+++ b/modules/benchmark/sha1.c
@@ -47,7 +47,7 @@ A million repetitions of "a"
/* Hash a single 512-bit block. This is the core of the algorithm. */
-void SHA1Transform(guint32 state[5], guchar buffer[64])
+void SHA1Transform(guint32 state[20], guchar buffer[64])
{
guint32 a, b, c, d, e;
typedef union {
diff --git a/modules/benchmark/sysbench.c b/modules/benchmark/sysbench.c
new file mode 100644
index 00000000..5c45831d
--- /dev/null
+++ b/modules/benchmark/sysbench.c
@@ -0,0 +1,270 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2017 L. A. F. Pereira <l@tia.mat.br>
+ * Copyright (C) 2019 Burt P. <pburt0@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hardinfo.h"
+#include "benchmark.h"
+#include "cpu_util.h"
+
+#define STATMSG "Performing Alexey Kopytov's sysbench memory benchmark"
+
+/* known to work with:
+ * sysbench 0.4.12 --> r:4012
+ * sysbench 1.0.11 --> r:1000011
+ * sysbench 1.0.15 --> r:1000015
+ */
+
+struct sysbench_ctx {
+ char *test;
+ int threads;
+ int max_time;
+ char *parms_test;
+ bench_value r;
+};
+
+int sysbench_version() {
+ int ret = -1;
+ int v1 = 0, v2 = 0, v3 = 0, mc = 0;
+ gboolean spawned;
+ gchar *out, *err, *p, *next_nl;
+
+ spawned = g_spawn_command_line_sync("sysbench --version",
+ &out, &err, NULL, NULL);
+ if (spawned) {
+ ret = 0;
+ p = out;
+ while(next_nl = strchr(p, '\n')) {
+ *next_nl = 0;
+ /* version */
+ mc = sscanf(p, "sysbench %d.%d.%d", &v1, &v2, &v3);
+ if (mc >= 1) {
+ ret += v1 * 1000000;
+ ret += v2 * 1000;
+ ret += v3;
+ break;
+ }
+ p = next_nl + 1;
+ }
+ g_free(out);
+ g_free(err);
+ }
+ return ret;
+}
+
+static gboolean sysbench_run(struct sysbench_ctx *ctx, int expecting_version) {
+ gboolean spawned;
+ gchar *out, *err, *p, *next_nl;
+
+ int v1 = 0, v2 = 0, v3 = 0, mc = 0;
+ char *pp = NULL;
+
+ if (!ctx) return FALSE;
+ if (!ctx->test) return FALSE;
+ if (!ctx->parms_test) return FALSE;
+ if (!ctx->threads) ctx->threads = 1;
+ ctx->r.threads_used = ctx->threads;
+ if (!ctx->max_time) ctx->max_time = 7;
+
+ gchar *cmd_line = NULL;
+ snprintf(ctx->r.extra, 255, "--time=%d %s", ctx->max_time, ctx->parms_test);
+ util_compress_space(ctx->r.extra);
+
+ if (!expecting_version)
+ expecting_version = sysbench_version();
+ if (expecting_version < 1000000) {
+ /* v0.x.x: sysbench [general-options]... --test=<test-name> [test-options]... command */
+ cmd_line = g_strdup_printf("sysbench --num-threads=%d --max-time=%d --test=%s %s run", ctx->threads, ctx->max_time, ctx->test, ctx->parms_test);
+ } else {
+ /* v1.x.x: sysbench [options]... [testname] [command] */
+ cmd_line = g_strdup_printf("sysbench --threads=%d --time=%d %s %s run", ctx->threads, ctx->max_time, ctx->parms_test, ctx->test);
+ }
+ //bench_msg("\ncmd_line: %s", cmd_line);
+
+ spawned = g_spawn_command_line_sync(cmd_line,
+ &out, &err, NULL, NULL);
+ g_free(cmd_line);
+ if (spawned) {
+ p = out;
+ while(next_nl = strchr(p, '\n')) {
+ *next_nl = 0;
+
+ if (strstr(p, "Usage:")) {
+ /* We're hosed */
+ goto sysbench_failed;
+ }
+
+ /* version */
+ mc = sscanf(p, "sysbench %d.%d.%d", &v1, &v2, &v3);
+ if (mc >= 1) {
+ ctx->r.revision = 0;
+ ctx->r.revision += v1 * 1000000;
+ ctx->r.revision += v2 * 1000;
+ ctx->r.revision += v3;
+ }
+
+ /* total_time */
+ if (pp = strstr(p, "total time:")) {
+ pp = strchr(pp, ':') + 1;
+ ctx->r.elapsed_time = strtof(pp, NULL);
+ }
+
+ /* result */
+ if (SEQ(ctx->test, "memory") ) {
+ // 57894.30 MiB transferred (5787.59 MiB/sec)
+ if (pp = strstr(p, " transferred (")) {
+ pp = strchr(pp, '(') + 1;
+ ctx->r.result = strtof(pp, NULL);
+ }
+ }
+ if (SEQ(ctx->test, "cpu") ) {
+ if (ctx->r.revision < 1000000) {
+ // there is not a nice result line
+ // to grab in version 0.x...
+ // total time: 7.0016s
+ // total number of events: 873
+
+ /* should already have "total time:" */
+ if (pp = strstr(p, " total number of events:")) {
+ pp = strchr(pp, ':') + 1;
+ ctx->r.result = strtof(pp, NULL);
+ ctx->r.result /= ctx->r.elapsed_time;
+ }
+ }
+ if (ctx->r.revision >= 1000000) {
+ // events per second: 1674.97
+ if (pp = strstr(p, " events per second:")) {
+ pp = strchr(pp, ':') + 1;
+ ctx->r.result = strtof(pp, NULL);
+ }
+ }
+ }
+
+ p = next_nl + 1;
+ }
+ g_free(out);
+ g_free(err);
+ } else {
+ bench_msg("\nfailed to spawn sysbench");
+ sleep(5);
+ }
+
+ if (ctx->r.result == -1)
+ goto sysbench_failed;
+
+ return spawned;
+
+sysbench_failed:
+ bench_msg("\nfailed to configure sysbench");
+ g_free(out);
+ g_free(err);
+ return 0;
+}
+
+void benchmark_memory_run(int threads, int result_index) {
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
+
+ struct sysbench_ctx ctx = {
+ .test = "memory",
+ .threads = threads>0 ? threads : cpu_threads,
+ .parms_test = "",
+ .r = EMPTY_BENCH_VALUE};
+
+ int sbv = sysbench_version();
+ if (BENCH_PTR_BITS > 32 && sbv >= 1000011) {
+ ctx.parms_test =
+ " --memory-block-size=1K"
+ " --memory-total-size=100G"
+ " --memory-scope=global"
+ " --memory-hugetlb=off"
+ " --memory-oper=write"
+ " --memory-access-mode=seq";
+ } else {
+ /* safer set */
+ ctx.parms_test =
+ " --memory-block-size=1K"
+ " --memory-total-size=3056M"
+ " --memory-scope=global"
+ " --memory-hugetlb=off"
+ " --memory-oper=write"
+ " --memory-access-mode=seq";
+ }
+
+ shell_view_set_enabled(FALSE);
+ char msg[128] = "";
+ snprintf(msg, 128, "%s (threads: %d)", STATMSG, threads);
+ shell_status_update(msg);
+
+ sysbench_run(&ctx, sbv);
+ bench_results[result_index] = ctx.r;
+}
+
+void benchmark_memory_single(void) { benchmark_memory_run(1, BENCHMARK_MEMORY_SINGLE); }
+void benchmark_memory_dual(void) { benchmark_memory_run(2, BENCHMARK_MEMORY_DUAL); }
+void benchmark_memory_quad(void) { benchmark_memory_run(4, BENCHMARK_MEMORY_QUAD); }
+void benchmark_memory_all(void) { benchmark_memory_run(0, BENCHMARK_MEMORY_ALL); }
+
+void benchmark_sbcpu_single(void) {
+ struct sysbench_ctx ctx = {
+ .test = "cpu",
+ .threads = 1,
+ .parms_test =
+ "--cpu-max-prime=10000",
+ .r = EMPTY_BENCH_VALUE};
+
+ shell_view_set_enabled(FALSE);
+ shell_status_update(STATMSG " (single thread)...");
+
+ sysbench_run(&ctx, 0);
+ bench_results[BENCHMARK_SBCPU_SINGLE] = ctx.r;
+}
+
+void benchmark_sbcpu_all(void) {
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
+
+ struct sysbench_ctx ctx = {
+ .test = "cpu",
+ .threads = cpu_threads,
+ .parms_test =
+ "--cpu-max-prime=10000",
+ .r = EMPTY_BENCH_VALUE};
+
+ shell_view_set_enabled(FALSE);
+ shell_status_update(STATMSG " (Multi-thread)...");
+
+ sysbench_run(&ctx, 0);
+ bench_results[BENCHMARK_SBCPU_ALL] = ctx.r;
+}
+
+void benchmark_sbcpu_quad(void) {
+ struct sysbench_ctx ctx = {
+ .test = "cpu",
+ .threads = 4,
+ .parms_test =
+ "--cpu-max-prime=10000",
+ .r = EMPTY_BENCH_VALUE};
+
+ shell_view_set_enabled(FALSE);
+ shell_status_update(STATMSG " (Four thread)...");
+
+ sysbench_run(&ctx, 0);
+ bench_results[BENCHMARK_SBCPU_QUAD] = ctx.r;
+}
diff --git a/modules/benchmark/zlib.c b/modules/benchmark/zlib.c
index 2ded59a4..2045969f 100644
--- a/modules/benchmark/zlib.c
+++ b/modules/benchmark/zlib.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2017 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2017 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,23 +22,39 @@
#include "benchmark.h"
-static gpointer zlib_for(unsigned int start, unsigned int end, void *data, gint thread_number)
-{
+/* zip/unzip 256KB blocks for 7 seconds
+ * result is number of full completions / 100 */
+
+/* if anything changes in this block, increment revision */
+#define BENCH_REVISION 3
+#define BENCH_DATA_SIZE 262144
+#define BENCH_DATA_MD5 "3753b649c4fa9ea4576fc8f89a773de2"
+#define CRUNCH_TIME 7
+#define VERIFY_RESULT 1
+
+static unsigned int zlib_errors = 0;
+
+static gpointer zlib_for(void *in_data, gint thread_number) {
char *compressed;
- uLong bound = compressBound(bound);
+ uLong bound = compressBound(BENCH_DATA_SIZE);
unsigned int i;
compressed = malloc(bound);
if (!compressed)
return NULL;
- for (i = start; i <= end; i++) {
- char uncompressed[65536];
- uLong compressedBound = bound;
- uLong destBound = sizeof(uncompressed);
+ char uncompressed[BENCH_DATA_SIZE];
+ uLong compressedBound = bound;
+ uLong destBound = sizeof(uncompressed);
- compress(compressed, &compressedBound, data, 65536);
- uncompress(uncompressed, &destBound, compressed, compressedBound);
+ compress(compressed, &compressedBound, in_data, BENCH_DATA_SIZE);
+ uncompress(uncompressed, &destBound, compressed, compressedBound);
+ if (VERIFY_RESULT) {
+ int cr = memcmp(in_data, uncompressed, BENCH_DATA_SIZE);
+ if (!!cr) {
+ zlib_errors++;
+ bench_msg("zlib error: uncompressed != original");
+ }
}
free(compressed);
@@ -50,24 +66,23 @@ void
benchmark_zlib(void)
{
bench_value r = EMPTY_BENCH_VALUE;
- gchar *tmpsrc, *bdata_path;
-
- bdata_path = g_build_filename(params.path_data, "benchmark.data", NULL);
- if (!g_file_get_contents(bdata_path, &tmpsrc, NULL, NULL)) {
- g_free(bdata_path);
+ gchar *test_data = get_test_data(BENCH_DATA_SIZE);
+ if (!test_data)
return;
- }
shell_view_set_enabled(FALSE);
shell_status_update("Running Zlib benchmark...");
- r = benchmark_parallel_for(0, 0, 50000, zlib_for, tmpsrc);
+ gchar *d = md5_digest_str(test_data, BENCH_DATA_SIZE);
+ if (!SEQ(d, BENCH_DATA_MD5))
+ bench_msg("test data has different md5sum: expected %s, actual %s", BENCH_DATA_MD5, d);
- g_free(bdata_path);
- g_free(tmpsrc);
-
- //TODO: explain in code comments
- gdouble marks = (50000. * 65536.) / (r.elapsed_time * 840205128.);
- r.result = marks;
+ r = benchmark_crunch_for(CRUNCH_TIME, 0, zlib_for, test_data);
+ r.result /= 100;
+ r.revision = BENCH_REVISION;
+ snprintf(r.extra, 255, "zlib %s (built against: %s), d:%s, e:%d", zlib_version, ZLIB_VERSION, d, zlib_errors);
bench_results[BENCHMARK_ZLIB] = r;
+
+ g_free(test_data);
+ g_free(d);
}
diff --git a/modules/computer.c b/modules/computer.c
index ea6762a7..fff8ba36 100644
--- a/modules/computer.c
+++ b/modules/computer.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2008 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2008 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -38,12 +38,16 @@
#include "info.h"
+#define THISORUNK(t) ( (t) ? t : _("(Unknown)") )
+
/* Callbacks */
gchar *callback_summary(void);
gchar *callback_os(void);
+gchar *callback_security(void);
gchar *callback_modules(void);
gchar *callback_boots(void);
gchar *callback_locales(void);
+gchar *callback_memory_usage();
gchar *callback_fs(void);
gchar *callback_display(void);
gchar *callback_network(void);
@@ -57,10 +61,12 @@ gchar *callback_dev(void);
/* Scan callbacks */
void scan_summary(gboolean reload);
void scan_os(gboolean reload);
+void scan_security(gboolean reload);
void scan_modules(gboolean reload);
void scan_boots(gboolean reload);
void scan_locales(gboolean reload);
void scan_fs(gboolean reload);
+void scan_memory_usage(gboolean reload);
void scan_display(gboolean reload);
void scan_network(gboolean reload);
void scan_users(gboolean reload);
@@ -70,26 +76,46 @@ void scan_env_var(gboolean reload);
void scan_dev(gboolean reload);
#endif /* GLIB_CHECK_VERSION(2,14,0) */
+enum {
+ ENTRY_SUMMARY,
+ ENTRY_OS,
+ ENTRY_SECURITY,
+ ENTRY_KMOD,
+ ENTRY_BOOTS,
+ ENTRY_LANGUAGES,
+ ENTRY_MEMORY_USAGE,
+ ENTRY_FS,
+ ENTRY_DISPLAY,
+ ENTRY_ENV,
+ ENTRY_DEVEL,
+ ENTRY_USERS,
+ ENTRY_GROUPS
+};
+
static ModuleEntry entries[] = {
- {N_("Summary"), "summary.png", callback_summary, scan_summary, MODULE_FLAG_NONE},
- {N_("Operating System"), "os.png", callback_os, scan_os, MODULE_FLAG_NONE},
- {N_("Kernel Modules"), "module.png", callback_modules, scan_modules, MODULE_FLAG_NONE},
- {N_("Boots"), "boot.png", callback_boots, scan_boots, MODULE_FLAG_NONE},
- {N_("Languages"), "language.png", callback_locales, scan_locales, MODULE_FLAG_NONE},
- {N_("Filesystems"), "dev_removable.png", callback_fs, scan_fs, MODULE_FLAG_NONE},
- {N_("Display"), "monitor.png", callback_display, scan_display, MODULE_FLAG_NONE},
- {N_("Environment Variables"), "environment.png", callback_env_var, scan_env_var, MODULE_FLAG_NONE},
+ [ENTRY_SUMMARY] = {N_("Summary"), "summary.png", callback_summary, scan_summary, MODULE_FLAG_NONE},
+ [ENTRY_OS] = {N_("Operating System"), "os.png", callback_os, scan_os, MODULE_FLAG_NONE},
+ [ENTRY_SECURITY] = {N_("Security"), "security.png", callback_security, scan_security, MODULE_FLAG_NONE},
+ [ENTRY_KMOD] = {N_("Kernel Modules"), "module.png", callback_modules, scan_modules, MODULE_FLAG_NONE},
+ [ENTRY_BOOTS] = {N_("Boots"), "boot.png", callback_boots, scan_boots, MODULE_FLAG_NONE},
+ [ENTRY_LANGUAGES] = {N_("Languages"), "language.png", callback_locales, scan_locales, MODULE_FLAG_NONE},
+ [ENTRY_MEMORY_USAGE] = {N_("Memory Usage"), "memory.png", callback_memory_usage, scan_memory_usage, MODULE_FLAG_NONE},
+ [ENTRY_FS] = {N_("Filesystems"), "dev_removable.png", callback_fs, scan_fs, MODULE_FLAG_NONE},
+ [ENTRY_DISPLAY] = {N_("Display"), "monitor.png", callback_display, scan_display, MODULE_FLAG_NONE},
+ [ENTRY_ENV] = {N_("Environment Variables"), "environment.png", callback_env_var, scan_env_var, MODULE_FLAG_NONE},
#if GLIB_CHECK_VERSION(2,14,0)
- {N_("Development"), "devel.png", callback_dev, scan_dev, MODULE_FLAG_NONE},
+ [ENTRY_DEVEL] = {N_("Development"), "devel.png", callback_dev, scan_dev, MODULE_FLAG_NONE},
+#else
+ [ENTRY_DEVEL] = {N_("Development"), "devel.png", callback_dev, scan_dev, MODULE_FLAG_HIDE},
#endif /* GLIB_CHECK_VERSION(2,14,0) */
- {N_("Users"), "users.png", callback_users, scan_users, MODULE_FLAG_NONE},
- {N_("Groups"), "users.png", callback_groups, scan_groups, MODULE_FLAG_NONE},
+ [ENTRY_USERS] = {N_("Users"), "users.png", callback_users, scan_users, MODULE_FLAG_NONE},
+ [ENTRY_GROUPS] = {N_("Groups"), "users.png", callback_groups, scan_groups, MODULE_FLAG_NONE},
{NULL},
};
-
gchar *module_list = NULL;
Computer *computer = NULL;
+gchar *meminfo = NULL;
gchar *hi_more_info(gchar * entry)
{
@@ -101,27 +127,42 @@ gchar *hi_more_info(gchar * entry)
return g_strdup_printf("[%s]", entry);
}
+/* a g_str_equal() where either may be null */
+#define g_str_equal0(a,b) (g_strcmp0(a,b) == 0)
+
gchar *hi_get_field(gchar * field)
{
+ gchar *tag, *label;
+ key_get_components(field, NULL, &tag, NULL, &label, NULL, TRUE);
+
gchar *tmp;
- if (g_str_equal(field, _("Memory"))) {
+ if (g_str_equal0(label, _("Memory"))) {
MemoryInfo *mi = computer_get_memory();
tmp = g_strdup_printf(_("%dMB (%dMB used)"), mi->total, mi->used);
g_free(mi);
- } else if (g_str_equal(field, _("Uptime"))) {
+ } else if (g_str_equal0(label, _("Uptime"))) {
tmp = computer_get_formatted_uptime();
- } else if (g_str_equal(field, _("Date/Time"))) {
+ } else if (g_str_equal0(label, _("Date/Time"))) {
time_t t = time(NULL);
tmp = g_new0(gchar, 64);
strftime(tmp, 64, "%c", localtime(&t));
- } else if (g_str_equal(field, _("Load Average"))) {
+ } else if (g_str_equal0(label, _("Load Average"))) {
tmp = computer_get_formatted_loadavg();
- } else if (g_str_equal(field, _("Available entropy in /dev/random"))) {
+ } else if (g_str_equal0(tag, "entropy")) {
tmp = computer_get_entropy_avail();
} else {
- tmp = g_strdup_printf("Unknown field: %s", field);
+ gchar *info = NULL;
+ if (tag)
+ info = moreinfo_lookup_with_prefix("DEV", tag);
+ else if (label)
+ info = moreinfo_lookup_with_prefix("DEV", label);
+
+ if (info)
+ tmp = g_strdup(info);
+ else
+ tmp = g_strdup_printf("Unknown field: [tag: %s] label: %s", tag ? tag : "(none)", label ? label : "(empty)");
}
return tmp;
}
@@ -141,6 +182,13 @@ void scan_os(gboolean reload)
SCAN_END();
}
+void scan_security(gboolean reload)
+{
+ SCAN_START();
+ //nothing to do here yet
+ SCAN_END();
+}
+
void scan_modules(gboolean reload)
{
SCAN_START();
@@ -170,9 +218,18 @@ void scan_fs(gboolean reload)
SCAN_END();
}
+void scan_memory_usage(gboolean reload)
+{
+ SCAN_START();
+ scan_memory_do();
+ SCAN_END();
+}
+
void scan_display(gboolean reload)
{
SCAN_START();
+ if (computer->display)
+ computer_free_display(computer->display);
computer->display = computer_get_display();
SCAN_END();
}
@@ -197,16 +254,16 @@ void scan_dev(gboolean reload)
{
SCAN_START();
- int i;
+ guint i;
struct {
gchar *compiler_name;
gchar *version_command;
gchar *regex;
- gboolean stdout;
+ gboolean read_stdout;
} detect_lang[] = {
{ N_("Scripting Languages"), NULL, FALSE },
{ N_("Gambas3 (gbr3)"), "gbr3 --version", "\\d+\\.\\d+\\.\\d+", TRUE },
- { N_("Python"), "python -V", "\\d+\\.\\d+\\.\\d+", FALSE },
+ { N_("Python (default)"), "python -V", "\\d+\\.\\d+\\.\\d+", FALSE },
{ N_("Python2"), "python2 -V", "\\d+\\.\\d+\\.\\d+", FALSE },
{ N_("Python3"), "python3 -V", "\\d+\\.\\d+\\.\\d+", TRUE },
{ N_("Perl"), "perl -v", "\\d+\\.\\d+\\.\\d+", TRUE },
@@ -215,26 +272,33 @@ void scan_dev(gboolean reload)
{ N_("PHP"), "php --version", "\\d+\\.\\d+\\.\\S+", TRUE},
{ N_("Ruby"), "ruby --version", "\\d+\\.\\d+\\.\\d+", TRUE },
{ N_("Bash"), "bash --version", "\\d+\\.\\d+\\.\\S+", TRUE},
+ { N_("JavaScript (Node.js)"), "node --version", "(?<=v)(\\d\\.?)+", TRUE },
+ { N_("awk"), "awk --version", "GNU Awk \\d+\\.\\d+\\.\\d+", TRUE },
{ N_("Compilers"), NULL, FALSE },
{ N_("C (GCC)"), "gcc -v", "\\d+\\.\\d+\\.\\d+", FALSE },
{ N_("C (Clang)"), "clang -v", "\\d+\\.\\d+", FALSE },
{ N_("D (dmd)"), "dmd --help", "\\d+\\.\\d+", TRUE },
{ N_("Gambas3 (gbc3)"), "gbc3 --version", "\\d+\\.\\d+\\.\\d+", TRUE },
{ N_("Java"), "javac -version", "\\d+\\.\\d+\\.\\d+", FALSE },
- { N_("CSharp (Mono, old)"), "mcs --version", "\\d+\\.\\d+\\.\\d+\\.\\d+", TRUE },
- { N_("CSharp (Mono)"), "gmcs --version", "\\d+\\.\\d+\\.\\d+\\.\\d+", TRUE },
+ { N_("C♯ (mcs)"), "mcs --version", "\\d+\\.\\d+\\.\\d+\\.\\d+", TRUE },
{ N_("Vala"), "valac --version", "\\d+\\.\\d+\\.\\d+", TRUE },
{ N_("Haskell (GHC)"), "ghc -v", "\\d+\\.\\d+\\.\\d+", FALSE },
{ N_("FreePascal"), "fpc -iV", "\\d+\\.\\d+\\.?\\d*", TRUE },
{ N_("Go"), "go version", "\\d+\\.\\d+\\.?\\d* ", TRUE },
+ { N_("Rust"), "rustc --version", "(?<=rustc )(\\d\\.?)+", TRUE },
{ N_("Tools"), NULL, FALSE },
{ N_("make"), "make --version", "\\d+\\.\\d+", TRUE },
+ { N_("ninja"), "ninja --version", "\\d+\\.\\d+\\.\\d+", TRUE },
{ N_("GDB"), "gdb --version", "(?<=^GNU gdb ).*", TRUE },
+ { N_("LLDB"), "lldb --version", "(?<=lldb version )(\\d\\.?)+", TRUE },
{ N_("strace"), "strace -V", "\\d+\\.\\d+\\.?\\d*", TRUE },
{ N_("valgrind"), "valgrind --version", "\\d+\\.\\d+\\.\\S+", TRUE },
{ N_("QMake"), "qmake --version", "\\d+\\.\\S+", TRUE},
{ N_("CMake"), "cmake --version", "\\d+\\.\\d+\\.?\\d*", TRUE},
{ N_("Gambas3 IDE"), "gambas3 --version", "\\d+\\.\\d+\\.\\d+", TRUE },
+ { N_("Radare2"), "radare2 -v", "(?<=radare2 )(\\d+\\.?)+(-git)?", TRUE },
+ { N_("ltrace"), "ltrace --version", "(?<=ltrace version )\\d+\\.\\d+\\.\\d+", TRUE },
+ { N_("Powershell"), "pwsh --version", "\\d+\\.\\d+\\.\\d+", TRUE },
};
g_free(dev_list);
@@ -254,10 +318,10 @@ void scan_dev(gboolean reload)
continue;
}
- if (detect_lang[i].stdout) {
- found = g_spawn_command_line_sync(detect_lang[i].version_command, &output, &ignored, NULL, NULL);
+ if (detect_lang[i].read_stdout) {
+ found = hardinfo_spawn_command_line_sync(detect_lang[i].version_command, &output, &ignored, NULL, NULL);
} else {
- found = g_spawn_command_line_sync(detect_lang[i].version_command, &ignored, &output, NULL, NULL);
+ found = hardinfo_spawn_command_line_sync(detect_lang[i].version_command, &ignored, &output, NULL, NULL);
}
g_free(ignored);
@@ -293,6 +357,7 @@ gchar *callback_dev(void)
{
return g_strdup_printf(
"[$ShellParam$]\n"
+ "ViewType=5\n"
"ColumnTitle$TextValue=%s\n" /* Program */
"ColumnTitle$Value=%s\n" /* Version */
"ShowColumnHeaders=true\n"
@@ -302,6 +367,24 @@ gchar *callback_dev(void)
}
#endif /* GLIB_CHECK_VERSION(2,14,0) */
+gchar *callback_memory_usage()
+{
+ extern gchar *lginterval;
+ return g_strdup_printf("[Memory]\n"
+ "%s\n"
+ "[$ShellParam$]\n"
+ "ViewType=2\n"
+ "LoadGraphSuffix= kB\n"
+ "RescanInterval=2000\n"
+ "ColumnTitle$TextValue=%s\n"
+ "ColumnTitle$Extra1=%s\n"
+ "ColumnTitle$Value=%s\n"
+ "ShowColumnHeaders=true\n"
+ "%s\n", meminfo,
+ _("Field"), _("Description"), _("Value"), /* column labels */
+ lginterval);
+}
+
static gchar *detect_machine_type(void)
{
GDir *dir;
@@ -315,6 +398,7 @@ static gchar *detect_machine_type(void)
if (chassis) {
if (strstr(chassis, "Raspberry Pi") != NULL
|| strstr(chassis, "ODROID") != NULL
+ || strstr(chassis, "Firefly ROC") != NULL
/* FIXME: consider making a table when adding more models */ ) {
g_free(chassis);
return g_strdup(_("Single-board computer"));
@@ -381,7 +465,7 @@ gchar *computer_get_virtualization(void)
"/var/log/dmesg",
NULL
};
- const static struct {
+ static const struct {
gchar *str;
gchar *vmtype;
} vm_types[] = {
@@ -458,9 +542,11 @@ gchar *callback_summary(void)
{
struct Info *info = info_new();
+ info_set_view_type(info, SHELL_VIEW_DETAIL);
+
info_add_group(info, _("Computer"),
- info_field_printf(_("Processor"), "%s",
- module_call_method("devices::getProcessorName")),
+ info_field(_("Processor"),
+ idle_free(module_call_method("devices::getProcessorNameAndDesc"))),
info_field_update(_("Memory"), 1000),
info_field_printf(_("Machine Type"), "%s",
computer_get_virtualization()),
@@ -472,17 +558,19 @@ gchar *callback_summary(void)
info_add_group(info, _("Display"),
info_field_printf(_("Resolution"), _(/* label for resolution */ "%dx%d pixels"),
computer->display->width, computer->display->height),
- info_field(_("OpenGL Renderer"), computer->display->ogl_renderer),
- info_field(_("X11 Vendor"), computer->display->vendor),
+ info_field(_("Display Adapter"),
+ idle_free(module_call_method("devices::getGPUList"))),
+ info_field(_("OpenGL Renderer"), THISORUNK(computer->display->xi->glx->ogl_renderer)),
+ info_field(_("Session Display Server"), THISORUNK(computer->display->display_server)),
info_field_last());
info_add_computed_group(info, _("Audio Devices"),
idle_free(computer_get_alsacards(computer)));
- info_add_computed_group(info, _("Input Devices"),
+ info_add_computed_group_wo_extra(info, _("Input Devices"),
idle_free(module_call_method("devices::getInputDevices")));
info_add_computed_group(info, NULL, /* getPrinters provides group headers */
idle_free(module_call_method("devices::getPrinters")));
- info_add_computed_group(info, NULL, /* getStorageDevices provides group headers */
+ info_add_computed_group_wo_extra(info, NULL, /* getStorageDevices provides group headers */
idle_free(module_call_method("devices::getStorageDevices")));
return info_flatten(info);
@@ -491,27 +579,116 @@ gchar *callback_summary(void)
gchar *callback_os(void)
{
struct Info *info = info_new();
-
- info_add_group(info, _("Version"),
- info_field(_("Kernel"), computer->os->kernel),
+ gchar *distro_icon;
+ gchar *distro;
+
+ info_set_view_type(info, SHELL_VIEW_DETAIL);
+
+ distro_icon = computer->os->distroid
+ ? idle_free(g_strdup_printf("distros/%s.svg",
+ computer->os->distroid))
+ : NULL;
+ distro = computer->os->distrocode
+ ? idle_free(g_strdup_printf("%s (%s)",
+ computer->os->distro, computer->os->distrocode))
+ : computer->os->distro;
+
+ struct InfoGroup *version_group =
+ info_add_group(
+ info, _("Version"), info_field(_("Kernel"), computer->os->kernel),
+ info_field(_("Command Line"), computer->os->kcmdline ?: _("Unknown")),
info_field(_("Version"), computer->os->kernel_version),
info_field(_("C Library"), computer->os->libc),
- info_field(_("Distribution"), computer->os->distro),
+ info_field(_("Distribution"), distro,
+ .value_has_vendor = TRUE,
+ .icon = distro_icon),
info_field_last());
+ if (computer->os->distro_flavor) {
+ info_group_add_field(version_group,
+ info_field(_("Spin/Flavor"), computer->os->distro_flavor->name,
+ .value_has_vendor = TRUE,
+ .icon = computer->os->distro_flavor->icon) );
+ }
+
info_add_group(info, _("Current Session"),
info_field(_("Computer Name"), computer->os->hostname),
info_field(_("User Name"), computer->os->username),
info_field(_("Language"), computer->os->language),
info_field(_("Home Directory"), computer->os->homedir),
+ info_field(_("Desktop Environment"), computer->os->desktop),
info_field_last());
- info_add_group(info, _("Misc"),
- info_field_update(_("Uptime"), 1000),
- info_field_update(_("Load Average"), 10000),
- info_field_update(_("Available entropy in /dev/random"), 1000),
+ info_add_group(info, _("Misc"), info_field_update(_("Uptime"), 1000),
+ info_field_update(_("Load Average"), 10000),
+ info_field_last());
+
+ return info_flatten(info);
+}
+
+gchar *callback_security(void)
+{
+ struct Info *info = info_new();
+
+ info_set_view_type(info, SHELL_VIEW_DETAIL);
+
+ info_add_group(info, _("HardInfo"),
+ info_field(_("HardInfo running as"),
+ (getuid() == 0) ? _("Superuser") : _("User")),
+ info_field_last());
+
+ info_add_group(
+ info, _("Health"),
+ info_field_update(_("Available entropy in /dev/random"), 1000, .tag = g_strdup("entropy") ),
info_field_last());
+ info_add_group(
+ info, _("Hardening Features"),
+ info_field(_("ASLR"), idle_free(computer_get_aslr())),
+ info_field(_("dmesg"), idle_free(computer_get_dmesg_status())),
+ info_field_last());
+
+ info_add_group(
+ info, _("Linux Security Modules"),
+ info_field(_("Modules available"), idle_free(computer_get_lsm())),
+ info_field(_("SELinux status"), computer_get_selinux()),
+ info_field_last());
+
+ GDir *dir = g_dir_open("/sys/devices/system/cpu/vulnerabilities", 0, NULL);
+ if (dir) {
+ struct InfoGroup *vulns =
+ info_add_group(info, _("CPU Vulnerabilities"), info_field_last());
+ vulns->sort = INFO_GROUP_SORT_NAME_ASCENDING;
+ const gchar *vuln;
+
+ while ((vuln = g_dir_read_name(dir))) {
+ gchar *contents = h_sysfs_read_string(
+ "/sys/devices/system/cpu/vulnerabilities", vuln);
+ if (!contents)
+ continue;
+
+ const gchar *icon = NULL;
+ if (g_strstr_len(contents, -1, "Not affected") )
+ icon = "circle_green_check.svg";
+
+ if (g_str_has_prefix(contents, "Mitigation:") ||
+ g_str_has_prefix(contents, "mitigation:"))
+ icon = "circle_yellow_exclaim.svg";
+
+ if (g_strstr_len(contents, -1, "Vulnerable") ||
+ g_strstr_len(contents, -1, "vulnerable"))
+ icon = "circle_red_x.svg";
+
+ info_group_add_fields(vulns,
+ info_field(g_strdup(vuln),
+ idle_free(contents), .icon = icon,
+ .free_name_on_flatten = TRUE),
+ info_field_last());
+ }
+
+ g_dir_close(dir);
+ }
+
return info_flatten(info);
}
@@ -575,27 +752,80 @@ gchar *callback_fs(void)
gchar *callback_display(void)
{
+ int n = 0;
+ gchar *screens_str = strdup(""), *outputs_str = strdup("");
+ xinfo *xi = computer->display->xi;
+ xrr_info *xrr = xi->xrr;
+ glx_info *glx = xi->glx;
+ wl_info *wl = computer->display->wl;
+
struct Info *info = info_new();
- info_add_group(info, _("Display"),
- info_field_printf(_("Resolution"), _(/* resolution WxH unit */ "%dx%d pixels"),
- computer->display->width, computer->display->height),
- info_field(_("Vendor"), computer->display->vendor),
- info_field(_("Version"), computer->display->version),
- info_field(_("Current Display Name"), computer->display->display_name),
+ info_set_view_type(info, SHELL_VIEW_DETAIL);
+
+ info_add_group(info, _("Session"),
+ info_field(_("Type"), THISORUNK(computer->display->session_type)),
info_field_last());
- info_add_computed_group(info, _("Monitors"), computer->display->monitors);
+ info_add_group(info, _("Wayland"),
+ info_field(_("Current Display Name"),
+ (wl->display_name) ? (wl->display_name) : _("(Not Available)")),
+ info_field_last());
- info_add_group(info, _("OpenGL"),
- info_field(_("Vendor"), computer->display->ogl_vendor),
- info_field(_("Renderer"), computer->display->ogl_renderer),
- info_field(_("Version"), computer->display->ogl_version),
- info_field(_("Direct Rendering"),
- computer->display->dri ? _("Yes") : _("No")),
+ info_add_group(info, _("X Server"),
+ info_field(_("Current Display Name"), THISORUNK(xi->display_name) ),
+ info_field(_("Vendor"), THISORUNK(xi->vendor), .value_has_vendor = TRUE ),
+ info_field(_("Version"), THISORUNK(xi->version) ),
+ info_field(_("Release Number"), THISORUNK(xi->release_number) ),
info_field_last());
- info_add_computed_group(info, _("Extensions"), computer->display->extensions);
+ for (n = 0; n < xrr->screen_count; n++) {
+ gchar *dims = g_strdup_printf(_(/* resolution WxH unit */ "%dx%d pixels"), xrr->screens[n].px_width, xrr->screens[n].px_height);
+ screens_str = h_strdup_cprintf("Screen %d=%s\n", screens_str, xrr->screens[n].number, dims);
+ g_free(dims);
+ }
+ info_add_computed_group(info, _("Screens"), screens_str);
+
+ for (n = 0; n < xrr->output_count; n++) {
+ gchar *connection = NULL;
+ switch (xrr->outputs[n].connected) {
+ case 0:
+ connection = _("Disconnected");
+ break;
+ case 1:
+ connection = _("Connected");
+ break;
+ case -1:
+ default:
+ connection = _("Unknown");
+ break;
+ }
+ gchar *dims = (xrr->outputs[n].screen == -1)
+ ? g_strdup(_("Unused"))
+ : g_strdup_printf(_("%dx%d pixels, offset (%d, %d)"),
+ xrr->outputs[n].px_width, xrr->outputs[n].px_height,
+ xrr->outputs[n].px_offset_x, xrr->outputs[n].px_offset_y);
+
+ outputs_str = h_strdup_cprintf("%s=%s; %s\n", outputs_str,
+ xrr->outputs[n].name, connection, dims);
+
+ g_free(dims);
+ }
+ info_add_computed_group(info, _("Outputs (XRandR)"), outputs_str);
+
+ info_add_group(info, _("OpenGL (GLX)"),
+ info_field(_("Vendor"), THISORUNK(glx->ogl_vendor), .value_has_vendor = TRUE ),
+ info_field(_("Renderer"), THISORUNK(glx->ogl_renderer) ),
+ info_field(_("Direct Rendering"),
+ glx->direct_rendering ? _("Yes") : _("No")),
+ info_field(_("Version (Compatibility)"), THISORUNK(glx->ogl_version) ),
+ info_field(_("Shading Language Version (Compatibility)"), THISORUNK(glx->ogl_sl_version) ),
+ info_field(_("Version (Core)"), THISORUNK(glx->ogl_core_version) ),
+ info_field(_("Shading Language Version (Core)"), THISORUNK(glx->ogl_core_sl_version) ),
+ info_field(_("Version (ES)"), THISORUNK(glx->ogles_version) ),
+ info_field(_("Shading Language Version (ES)"), THISORUNK(glx->ogles_sl_version) ),
+ info_field(_("GLX Version"), THISORUNK(glx->glx_version) ),
+ info_field_last());
return info_flatten(info);
}
@@ -641,20 +871,28 @@ gchar *get_ogl_renderer(void)
{
scan_display(FALSE);
- return g_strdup(computer->display->ogl_renderer);
+ return g_strdup(computer->display->xi->glx->ogl_renderer);
}
gchar *get_display_summary(void)
{
scan_display(FALSE);
- return g_strdup_printf("%dx%d\n"
+ gchar *gpu_list = module_call_method("devices::getGPUList");
+
+ gchar *ret = g_strdup_printf(
+ "%s\n"
+ "%dx%d\n"
"%s\n"
"%s",
- computer->display->width,
- computer->display->height,
- computer->display->ogl_renderer,
- computer->display->vendor);
+ gpu_list,
+ computer->display->width, computer->display->height,
+ computer->display->display_server,
+ (computer->display->xi->glx->ogl_renderer)
+ ? computer->display->xi->glx->ogl_renderer
+ : "" );
+ g_free(gpu_list);
+ return ret;
}
gchar *get_kernel_module_description(gchar *module)
@@ -682,16 +920,65 @@ gchar *get_audio_cards(void)
return computer_get_alsacards(computer);
}
-ShellModuleMethod *hi_exported_methods(void)
+/* the returned string must stay in kB as it is used
+ * elsewhere with that expectation */
+gchar *get_memory_total(void)
+{
+ scan_memory_usage(FALSE);
+ return moreinfo_lookup ("DEV:MemTotal");
+}
+
+gchar *memory_devices_get_system_memory_str(); /* in dmi_memory.c */
+gchar *memory_devices_get_system_memory_types_str();
+/* Note 1: moreinfo_lookup() results should not be freed because
+ * they are pointers into a GHash.
+ * module_call_method() g_strdup()s it's return value. */
+const gchar *get_memory_desc(void) // [1] const (as to say "don't free")
+{
+ scan_memory_usage(FALSE);
+ gchar *avail = g_strdup(moreinfo_lookup("DEV:MemTotal")); // [1] g_strdup()
+ double k = avail ? (double)strtol(avail, NULL, 10) : 0;
+ if (k) {
+ g_free(avail);
+ avail = NULL;
+ const char *fmt = _(/*/ <value> <unit> "usable memory" */ "%0.1f %s available to Linux");
+ if (k > (2048 * 1024))
+ avail = g_strdup_printf(fmt, k / (1024*1024), _("GiB") );
+ else if (k > 2048)
+ avail = g_strdup_printf(fmt, k / 1024, _("MiB") );
+ else
+ avail = g_strdup_printf(fmt, k, _("KiB") );
+ }
+ gchar *mem = memory_devices_get_system_memory_str();
+ if (mem) {
+ gchar *types = memory_devices_get_system_memory_types_str();
+ gchar *ret = g_strdup_printf("%s %s\n%s", mem, types, avail ? avail : "");
+ g_free(avail);
+ g_free(mem);
+ g_free(types);
+ return (gchar*)idle_free(ret); // [1] idle_free()
+ }
+ return (gchar*)idle_free(avail); // [1] idle_free()
+}
+
+static gchar *get_machine_type(void)
{
- static ShellModuleMethod m[] = {
+ return computer_get_virtualization();
+}
+
+const ShellModuleMethod *hi_exported_methods(void)
+{
+ static const ShellModuleMethod m[] = {
{"getOSKernel", get_os_kernel},
{"getOS", get_os},
{"getDisplaySummary", get_display_summary},
{"getOGLRenderer", get_ogl_renderer},
{"getAudioCards", get_audio_cards},
{"getKernelModuleDescription", get_kernel_module_description},
- {NULL}
+ {"getMemoryTotal", get_memory_total},
+ {"getMemoryDesc", get_memory_desc},
+ {"getMachineType", get_machine_type},
+ {NULL},
};
return m;
@@ -721,6 +1008,11 @@ gchar **hi_module_get_dependencies(void)
gchar *hi_module_get_summary(void)
{
+ gchar *virt = computer_get_virtualization();
+ gchar *machine_type = g_strdup_printf("%s (%s)",
+ _("Motherboard"),
+ (char*)idle_free(virt));
+
return g_strdup_printf("[%s]\n"
"Icon=os.png\n"
"Method=computer::getOS\n"
@@ -729,7 +1021,7 @@ gchar *hi_module_get_summary(void)
"Method=devices::getProcessorNameAndDesc\n"
"[%s]\n"
"Icon=memory.png\n"
- "Method=devices::getMemoryTotal\n"
+ "Method=computer::getMemoryDesc\n"
"[%s]\n"
"Icon=module.png\n"
"Method=devices::getMotherboard\n"
@@ -738,7 +1030,7 @@ gchar *hi_module_get_summary(void)
"Method=computer::getDisplaySummary\n"
"[%s]\n"
"Icon=hdd.png\n"
- "Method=devices::getStorageDevices\n"
+ "Method=devices::getStorageDevicesSimple\n"
"[%s]\n"
"Icon=printer.png\n"
"Method=devices::getPrinters\n"
@@ -746,15 +1038,18 @@ gchar *hi_module_get_summary(void)
"Icon=audio.png\n"
"Method=computer::getAudioCards\n",
_("Operating System"),
- _("CPU"), _("RAM"), _("Motherboard"), _("Graphics"),
+ _("Processor"), _("Memory"), (char*)idle_free(machine_type), _("Graphics"),
_("Storage"), _("Printers"), _("Audio")
);
}
void hi_module_deinit(void)
{
+ g_hash_table_destroy(memlabels);
+
if (computer->os) {
g_free(computer->os->kernel);
+ g_free(computer->os->kcmdline);
g_free(computer->os->libc);
g_free(computer->os->distrocode);
g_free(computer->os->distro);
@@ -769,17 +1064,7 @@ void hi_module_deinit(void)
g_free(computer->os);
}
- if (computer->display) {
- g_free(computer->display->ogl_vendor);
- g_free(computer->display->ogl_renderer);
- g_free(computer->display->ogl_version);
- g_free(computer->display->display_name);
- g_free(computer->display->vendor);
- g_free(computer->display->version);
- g_free(computer->display->extensions);
- g_free(computer->display->monitors);
- g_free(computer->display);
- }
+ computer_free_display(computer->display);
if (computer->alsa) {
g_slist_free(computer->alsa->cards);
@@ -795,18 +1080,45 @@ void hi_module_deinit(void)
void hi_module_init(void)
{
computer = g_new0(Computer, 1);
+ init_memory_labels();
+ kernel_module_icon_init();
}
-ModuleAbout *hi_module_get_about(void)
+const ModuleAbout *hi_module_get_about(void)
{
- static ModuleAbout ma[] = {
- {
- .author = "Leandro A. F. Pereira",
- .description = N_("Gathers high-level computer information"),
- .version = VERSION,
- .license = "GNU GPL version 2"}
- };
+ static const ModuleAbout ma = {
+ .author = "L. A. F. Pereira",
+ .description = N_("Gathers high-level computer information"),
+ .version = VERSION,
+ .license = "GNU GPL version 2 or later.",};
+
+ return &ma;
+}
+
+static const gchar *hinote_kmod() {
+ static gchar note[note_max_len] = "";
+ gboolean ok = TRUE;
+ *note = 0; /* clear */
+ ok &= note_require_tool("lsmod", note, _("<i><b>lsmod</b></i> is required."));
+ return ok ? NULL : g_strstrip(note); /* remove last \n */
+}
- return ma;
+static const gchar *hinote_display() {
+ static gchar note[note_max_len] = "";
+ gboolean ok = TRUE;
+ *note = 0; /* clear */
+ ok &= note_require_tool("xrandr", note, _("X.org's <i><b>xrandr</b></i> utility provides additional details when available."));
+ ok &= note_require_tool("glxinfo", note, _("Mesa's <i><b>glxinfo</b></i> utility is required for OpenGL information."));
+ return ok ? NULL : g_strstrip(note); /* remove last \n */
}
+const gchar *hi_note_func(gint entry)
+{
+ if (entry == ENTRY_KMOD) {
+ return hinote_kmod();
+ }
+ else if (entry == ENTRY_DISPLAY) {
+ return hinote_display();
+ }
+ return NULL;
+}
diff --git a/modules/computer/alsa.c b/modules/computer/alsa.c
index 00c1fceb..f74d2752 100644
--- a/modules/computer/alsa.c
+++ b/modules/computer/alsa.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/computer/boots.c b/modules/computer/boots.c
index ba458242..52c122e4 100644
--- a/modules/computer/boots.c
+++ b/modules/computer/boots.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,6 +21,8 @@
#include "hardinfo.h"
#include "computer.h"
+extern void scan_os(gboolean reload);
+
void
scan_boots_real(void)
{
@@ -35,7 +37,7 @@ scan_boots_real(void)
else
return;
- spawned = g_spawn_command_line_sync("last",
+ spawned = hardinfo_spawn_command_line_sync("last",
&out, &err, NULL, NULL);
if (spawned && out != NULL) {
p = out;
diff --git a/modules/computer/display.c b/modules/computer/display.c
index 61eac4eb..98cb7bf7 100644
--- a/modules/computer/display.c
+++ b/modules/computer/display.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,131 +21,54 @@
#include "hardinfo.h"
#include "computer.h"
-static void
-get_glx_info(DisplayInfo *di)
-{
- gchar *output;
- if (g_spawn_command_line_sync("glxinfo", &output, NULL, NULL, NULL)) {
- gchar **output_lines;
- gint i = 0;
-
- for (output_lines = g_strsplit(output, "\n", 0);
- output_lines && output_lines[i];
- i++) {
- if (strstr(output_lines[i], "OpenGL")) {
- gchar **tmp = g_strsplit(output_lines[i], ":", 0);
-
- tmp[1] = g_strchug(tmp[1]);
-
- get_str("OpenGL vendor str", di->ogl_vendor);
- get_str("OpenGL renderer str", di->ogl_renderer);
- get_str("OpenGL version str", di->ogl_version);
-
- g_strfreev(tmp);
- } else if (strstr(output_lines[i], "direct rendering: Yes")) {
- di->dri = TRUE;
- }
- }
-
- g_free(output);
- g_strfreev(output_lines);
-
- if (!di->ogl_vendor)
- di->ogl_vendor = _("(Unknown)");
- if (!di->ogl_renderer)
- di->ogl_renderer = _("(Unknown)");
- if (!di->ogl_version)
- di->ogl_version = _("(Unknown)");
-
- } else {
- di->ogl_vendor = di->ogl_renderer = di->ogl_version = _("(Unknown)");
+DisplayInfo *computer_get_display(void) {
+ DisplayInfo *di = g_new0(DisplayInfo, 1);
+ wl_info *wl = get_walyand_info();
+ xinfo *xi = xinfo_get_info();
+ xrr_info *xrr = xi->xrr;
+ glx_info *glx = xi->glx;
+
+ di->width = di->height = 0;
+ if (xrr->screen_count > 0) {
+ di->width = xrr->screens[0].px_width;
+ di->height = xrr->screens[0].px_height;
}
-
-}
-
-static void
-get_x11_info(DisplayInfo *di)
-{
- gchar *output;
-
- if (g_spawn_command_line_sync("xdpyinfo", &output, NULL, NULL, NULL)) {
- gchar **output_lines, **old;
-
- output_lines = g_strsplit(output, "\n", 0);
- g_free(output);
-
- old = output_lines;
- while (*output_lines) {
- gchar **tmp = g_strsplit(*output_lines, ":", 2);
- output_lines++;
-
- if (tmp[1] && tmp[0]) {
- tmp[1] = g_strchug(tmp[1]);
-
- get_str("vendor string", di->vendor);
- get_str("X.Org version", di->version);
- get_str("XFree86 version", di->version);
- get_str("name of display", di->display_name);
-
- if (g_str_has_prefix(tmp[0], "number of extensions")) {
- int n;
-
- di->extensions = g_strdup("");
-
- for (n = atoi(tmp[1]); n; n--) {
- di->extensions = h_strconcat(di->extensions,
- g_strstrip(*(++output_lines)),
- "=\n",
- NULL);
- }
- g_strfreev(tmp);
-
- break;
- }
- }
-
- g_strfreev(tmp);
- }
-
- g_strfreev(old);
+ di->vendor = xi->vendor;
+ di->session_type = wl->xdg_session_type;
+
+ if (strcmp(di->session_type, "x11") == 0 ) {
+ if (xi->nox) {
+ di->display_server = g_strdup(_("(Unknown)"));
+ /* assumed x11 previously, because it wasn't set */
+ free(wl->xdg_session_type);
+ di->session_type = wl->xdg_session_type = NULL;
+ } else if (xi->vendor && xi->version)
+ di->display_server = g_strdup_printf("%s %s", xi->vendor, xi->version );
+ else if (xi->vendor && xi->release_number)
+ di->display_server = g_strdup_printf("[X11] %s %s", xi->vendor, xi->release_number );
+ else
+ di->display_server = g_strdup("X11");
+ } else
+ if (strcmp(di->session_type, "wayland") == 0 ) {
+ di->display_server = g_strdup("Wayland");
+ } else
+ if (strcmp(di->session_type, "mir") == 0 ) {
+ di->display_server = g_strdup("Mir");
+ } else {
+ di->display_server = g_strdup(_("(Unknown)"));
}
- GdkScreen *screen = gdk_screen_get_default();
-
- if (screen && GDK_IS_SCREEN(screen)) {
- gint n_monitors = gdk_screen_get_n_monitors(screen);
- gint i;
-
- di->monitors = NULL;
- for (i = 0; i < n_monitors; i++) {
- GdkRectangle rect;
-
- gdk_screen_get_monitor_geometry(screen, i, &rect);
-
- di->monitors = h_strdup_cprintf(_("Monitor %d=%dx%d pixels\n"),
- di->monitors, i, rect.width, rect.height);
- }
- } else {
- di->monitors = "";
- }
+ di->xi = xi;
+ di->wl = wl;
+ return di;
}
-DisplayInfo *
-computer_get_display(void)
-{
- DisplayInfo *di = g_new0(DisplayInfo, 1);
-
- GdkScreen *screen = gdk_screen_get_default();
-
- if (screen && GDK_IS_SCREEN(screen)) {
- di->width = gdk_screen_get_width(screen);
- di->height = gdk_screen_get_height(screen);
- } else {
- di->width = di->height = 0;
+void computer_free_display(DisplayInfo *di) {
+ /* fyi: DisplayInfo is in computer.h */
+ if (di) {
+ free(di->display_server);
+ xinfo_free(di->xi);
+ wl_free(di->wl);
+ free(di);
}
-
- get_glx_info(di);
- get_x11_info(di);
-
- return di;
}
diff --git a/modules/computer/environment.c b/modules/computer/environment.c
index dc0fb6f3..2f29c861 100644
--- a/modules/computer/environment.c
+++ b/modules/computer/environment.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2008 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2008 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/computer/filesystem.c b/modules/computer/filesystem.c
index 397dc636..e9c84811 100644
--- a/modules/computer/filesystem.c
+++ b/modules/computer/filesystem.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -71,6 +71,8 @@ scan_filesystems(void)
gchar *strhash;
+ gboolean rw = strstr(tmp[3], "rw") != NULL;
+
strreplacechr(tmp[0], "#", '_');
strhash = g_strdup_printf("[%s]\n"
"%s=%s\n"
@@ -81,7 +83,7 @@ scan_filesystems(void)
"%s=%s\n",
tmp[0], /* path */
_("Filesystem"), tmp[2],
- _("Mounted As"), ( strstr(tmp[3], "rw") != NULL) ? _("Read-Write") : _("Read-Only"),
+ _("Mounted As"), rw ? _("Read-Write") : _("Read-Only"),
_("Mount Point"), tmp[1],
_("Size"), strsize,
_("Used"), strused,
@@ -90,9 +92,10 @@ scan_filesystems(void)
moreinfo_add_with_prefix("COMP", key, strhash);
g_free(key);
- fs_list = h_strdup_cprintf("$FS%d$%s=%.2f %% (%s of %s)|%s\n",
+ fs_list = h_strdup_cprintf("$FS%d$%s%s=%.2f %% (%s of %s)|%s\n",
fs_list,
- count, tmp[0], use_ratio, stravail, strsize, tmp[1]);
+ count, tmp[0], rw ? "" : "🔒",
+ use_ratio, stravail, strsize, tmp[1]);
g_free(strsize);
g_free(stravail);
diff --git a/modules/computer/groups.c b/modules/computer/groups.c
index 244b8000..9371e211 100644
--- a/modules/computer/groups.c
+++ b/modules/computer/groups.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2012 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2012 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/computer/languages.c b/modules/computer/languages.c
index d4681839..b2d4910f 100644
--- a/modules/computer/languages.c
+++ b/modules/computer/languages.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,113 +22,161 @@
#include "computer.h"
#include "cpu_util.h" /* for UNKIFNULL() */
-void
-scan_languages(OperatingSystem * os)
-{
- FILE *locale;
- gchar buf[512], *retval = NULL;
-
- locale = popen("locale -va && echo", "r");
- if (!locale)
- return;
-
+typedef struct {
gchar name[32];
- gchar *title = NULL,
- *source = NULL,
- *address = NULL,
- *email = NULL,
- *language = NULL,
- *territory = NULL,
- *revision = NULL,
- *date = NULL,
- *codeset = NULL;
-
- while (fgets(buf, 512, locale)) {
- if (!strncmp(buf, "locale:", 7)) {
- sscanf(buf, "locale: %s", name);
- (void)fgets(buf, 128, locale);
- } else if (strchr(buf, '|')) {
- gchar **tmp = g_strsplit(buf, "|", 2);
-
- tmp[0] = g_strstrip(tmp[0]);
-
- if (tmp[1]) {
- tmp[1] = g_strstrip(tmp[1]);
-
- get_str("title", title);
- get_str("source", source);
- get_str("address", address);
- get_str("email", email);
- get_str("language", language);
- get_str("territory", territory);
- get_str("revision", revision);
- get_str("date", date);
- get_str("codeset", codeset);
- }
-
- g_strfreev(tmp);
- } else {
- gchar *currlocale;
-
- retval = h_strdup_cprintf("$%s$%s=%s\n", retval, name, name, title);
-
- UNKIFNULL(title);
- UNKIFNULL(source);
- UNKIFNULL(address);
- UNKIFNULL(email);
- UNKIFNULL(language);
- UNKIFNULL(territory);
- UNKIFNULL(revision);
- UNKIFNULL(date);
- UNKIFNULL(codeset);
-
- /* values may have & */
- title = hardinfo_clean_value(title, 1);
- source = hardinfo_clean_value(source, 1);
- address = hardinfo_clean_value(address, 1);
- email = hardinfo_clean_value(email, 1);
- language = hardinfo_clean_value(language, 1);
- territory = hardinfo_clean_value(territory, 1);
-
- currlocale = g_strdup_printf("[%s]\n"
- /* Name */ "%s=%s (%s)\n"
- /* Source */ "%s=%s\n"
- /* Address */ "%s=%s\n"
- /* Email */ "%s=%s\n"
- /* Language */ "%s=%s\n"
- /* Territory */"%s=%s\n"
- /* Revision */ "%s=%s\n"
- /* Date */ "%s=%s\n"
- /* Codeset */ "%s=%s\n",
- _("Locale Information"),
- _("Name"), name, title,
- _("Source"), source,
- _("Address"), address,
- _("E-mail"), email,
- _("Language"), language,
- _("Territory"), territory,
- _("Revision"), revision,
- _("Date"), date,
- _("Codeset"), codeset );
-
- moreinfo_add_with_prefix("COMP", name, currlocale);
-
- g_free(title);
- g_free(source);
- g_free(address);
- g_free(email);
- g_free(language);
- g_free(territory);
- g_free(revision);
- g_free(date);
- g_free(codeset);
-
- title = source = address = email = language = territory = \
- revision = date = codeset = NULL;
- }
+ gchar *title,
+ *source,
+ *address,
+ *email,
+ *language,
+ *territory,
+ *revision,
+ *date,
+ *codeset;
+} locale_info;
+
+void locale_info_free(locale_info *s) {
+ if (s) {
+ g_free(s->title);
+ g_free(s->source);
+ g_free(s->address);
+ g_free(s->email);
+ g_free(s->language);
+ g_free(s->territory);
+ g_free(s->revision);
+ g_free(s->date);
+ g_free(s->codeset);
+ free(s);
}
+}
- fclose(locale);
+/* TODO: use info_* */
+gchar *locale_info_section(locale_info *s) {
+ gchar *name = g_strdup(s->name);
+ gchar *title = g_strdup(s->title),
+ *source = g_strdup(s->source),
+ *address = g_strdup(s->address),
+ *email = g_strdup(s->email),
+ *language = g_strdup(s->language),
+ *territory = g_strdup(s->territory),
+ *revision = g_strdup(s->revision),
+ *date = g_strdup(s->date),
+ *codeset = g_strdup(s->codeset);
+
+ UNKIFNULL(title);
+ UNKIFNULL(source);
+ UNKIFNULL(address);
+ UNKIFNULL(email);
+ UNKIFNULL(language);
+ UNKIFNULL(territory);
+ UNKIFNULL(revision);
+ UNKIFNULL(date);
+ UNKIFNULL(codeset);
+
+ /* values may have & */
+ title = hardinfo_clean_value(title, 1);
+ source = hardinfo_clean_value(source, 1);
+ address = hardinfo_clean_value(address, 1);
+ email = hardinfo_clean_value(email, 1);
+ language = hardinfo_clean_value(language, 1);
+ territory = hardinfo_clean_value(territory, 1);
+
+ gchar *ret = g_strdup_printf("[%s]\n"
+ /* Name */ "%s=%s (%s)\n"
+ /* Source */ "%s=%s\n"
+ /* Address */ "%s=%s\n"
+ /* Email */ "%s=%s\n"
+ /* Language */ "%s=%s\n"
+ /* Territory */"%s=%s\n"
+ /* Revision */ "%s=%s\n"
+ /* Date */ "%s=%s\n"
+ /* Codeset */ "%s=%s\n",
+ _("Locale Information"),
+ _("Name"), name, title,
+ _("Source"), source,
+ _("Address"), address,
+ _("E-mail"), email,
+ _("Language"), language,
+ _("Territory"), territory,
+ _("Revision"), revision,
+ _("Date"), date,
+ _("Codeset"), codeset );
+ g_free(name);
+ g_free(title);
+ g_free(source);
+ g_free(address);
+ g_free(email);
+ g_free(language);
+ g_free(territory);
+ g_free(revision);
+ g_free(date);
+ g_free(codeset);
+ return ret;
+}
- os->languages = retval;
+void
+scan_languages(OperatingSystem * os)
+{
+ gboolean spawned;
+ gchar *out, *err, *p, *next_nl;
+
+ gchar *ret = NULL;
+ locale_info *curr = NULL;
+ int last = 0;
+
+ spawned = hardinfo_spawn_command_line_sync("locale -va",
+ &out, &err, NULL, NULL);
+ if (spawned) {
+ ret = g_strdup("");
+ p = out;
+ while(1) {
+ /* `locale -va` doesn't end the last locale block
+ * with an \n, which makes this more complicated */
+ next_nl = strchr(p, '\n');
+ if (next_nl == NULL)
+ next_nl = strchr(p, 0);
+ last = (*next_nl == 0) ? 1 : 0;
+ strend(p, '\n');
+ if (strncmp(p, "locale:", 7) == 0) {
+ curr = g_new0(locale_info, 1);
+ sscanf(p, "locale: %s", curr->name);
+ /* TODO: 'directory:' and 'archive:' */
+ } else if (strchr(p, '|')) {
+ do {/* get_str() has a continue in it,
+ * how fn frustrating that was to figure out */
+ gchar **tmp = g_strsplit(p, "|", 2);
+ tmp[0] = g_strstrip(tmp[0]);
+ if (tmp[1]) {
+ tmp[1] = g_strstrip(tmp[1]);
+ get_str("title", curr->title);
+ get_str("source", curr->source);
+ get_str("address", curr->address);
+ get_str("email", curr->email);
+ get_str("language", curr->language);
+ get_str("territory", curr->territory);
+ get_str("revision", curr->revision);
+ get_str("date", curr->date);
+ get_str("codeset", curr->codeset);
+ }
+ g_strfreev(tmp);
+ } while (0);
+ } else if (strstr(p, "------")) {
+ /* do nothing */
+ } else if (curr) {
+ /* a blank line is the end of a locale */
+ gchar *li_str = locale_info_section(curr);
+ gchar *clean_title = hardinfo_clean_value(curr->title, 0); /* may contain & */
+ ret = h_strdup_cprintf("$%s$%s=%s\n", ret, curr->name, curr->name, clean_title);
+ moreinfo_add_with_prefix("COMP", g_strdup(curr->name), li_str); /* becomes owned by moreinfo */
+ locale_info_free(curr);
+ curr = NULL;
+ g_free(clean_title);
+ }
+ if (last) break;
+ p = next_nl + 1;
+ }
+ g_free(out);
+ g_free(err);
+ }
+ os->languages = ret;
}
diff --git a/modules/computer/loadavg.c b/modules/computer/loadavg.c
index 7311dbf0..802ae2aa 100644
--- a/modules/computer/loadavg.c
+++ b/modules/computer/loadavg.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/computer/memory.c b/modules/computer/memory.c
index dc8599c2..994e4040 100644
--- a/modules/computer/memory.c
+++ b/modules/computer/memory.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/devmemory.c b/modules/computer/memory_usage.c
index 29094dd8..12c62fe7 100644
--- a/modules/devices/devmemory.c
+++ b/modules/computer/memory_usage.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,7 +29,12 @@ void scan_memory_do(void)
if (offset == -1) {
/* gah. linux 2.4 adds three lines of data we don't need in
- /proc/meminfo */
+ * /proc/meminfo.
+ * The lines look something like this:
+ * total: used: free: shared: buffers: cached:
+ * Mem: 3301101568 1523159040 1777942528 0 3514368 1450356736
+ * Swap: 0 0 0
+ */
gchar *os_kernel = module_call_method("computer::getOSKernel");
if (os_kernel) {
offset = strstr(os_kernel, "Linux 2.4") ? 3 : 0;
diff --git a/modules/computer/modules.c b/modules/computer/modules.c
index df876e3a..14028362 100644
--- a/modules/computer/modules.c
+++ b/modules/computer/modules.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,161 +17,384 @@
*/
#include <string.h>
+#include <sys/utsname.h>
+#include <json-glib/json-glib.h>
-#include "hardinfo.h"
+#include "syncmanager.h"
#include "computer.h"
#include "cpu_util.h" /* for STRIFNULL() */
+#include "hardinfo.h"
-#define GET_STR(field_name,ptr) \
- if (!ptr && strstr(tmp[0], field_name)) { \
- ptr = g_markup_escape_text(g_strstrip(tmp[1]), strlen(tmp[1])); \
- g_strfreev(tmp); \
- continue; \
- }
+#define GET_STR(field_name, ptr) \
+ if (!ptr && strstr(tmp[0], field_name)) { \
+ ptr = g_markup_escape_text(g_strstrip(tmp[1]), strlen(tmp[1])); \
+ g_strfreev(tmp); \
+ continue; \
+ }
GHashTable *_module_hash_table = NULL;
+static gchar *kernel_modules_dir = NULL;
+
+enum icons {
+ ICON_INVALID = 0,
+
+ ICON_AUDIO,
+ ICON_BLUETOOTH,
+ ICON_CAMERA_WEB,
+ ICON_CDROM,
+ ICON_CRYPTOHASH,
+ ICON_DEVICES,
+ ICON_HDD,
+ ICON_INPUTDEVICES,
+ ICON_JOYSTICK,
+ ICON_KEYBOARD,
+ ICON_MEDIA_FLOPPY,
+ ICON_MEDIA_REMOVABLE,
+ ICON_MEMORY,
+ ICON_MONITOR,
+ ICON_MOUSE,
+ ICON_NETWORK,
+ ICON_NETWORK_CONNECTIONS,
+ ICON_NETWORK_INTERFACE,
+ ICON_THERM,
+ ICON_USB,
+ ICON_WIRELESS,
+
+ ICON_MAX,
+};
+
+static const char *icon_table[ICON_MAX] = {
+ [ICON_AUDIO] = "audio",
+ [ICON_BLUETOOTH] = "bluetooth",
+ [ICON_CAMERA_WEB] = "camera-web",
+ [ICON_CDROM] = "cdrom",
+ [ICON_CRYPTOHASH] = "cryptohash",
+ [ICON_DEVICES] = "devices",
+ [ICON_HDD] = "hdd",
+ [ICON_INPUTDEVICES] = "inputdevices",
+ [ICON_JOYSTICK] = "joystick",
+ [ICON_KEYBOARD] = "keyboard",
+ [ICON_MEDIA_FLOPPY] = "media-floppy",
+ [ICON_MEDIA_REMOVABLE] = "media-removable",
+ [ICON_MEMORY] = "memory",
+ [ICON_MONITOR] = "monitor",
+ [ICON_MOUSE] = "mouse",
+ [ICON_NETWORK] = "network",
+ [ICON_NETWORK_CONNECTIONS] = "network-connections",
+ [ICON_NETWORK_INTERFACE] = "network-interface",
+ [ICON_THERM] = "therm",
+ [ICON_USB] = "usb",
+ [ICON_WIRELESS] = "wireless",
+};
+
+/* Keep this sorted by reverse strlen(dir)! */
+static const struct {
+ const gchar *dir;
+ enum icons icon;
+} modules_icons[] = {
+ {"drivers/input/joystick/", ICON_JOYSTICK},
+ {"drivers/input/keyboard/", ICON_KEYBOARD},
+ {"drivers/media/usb/uvc/", ICON_CAMERA_WEB},
+ {"drivers/net/wireless/", ICON_WIRELESS},
+ {"drivers/net/ethernet/", ICON_NETWORK_INTERFACE},
+ {"drivers/input/mouse/", ICON_MOUSE},
+ {"drivers/bluetooth/", ICON_BLUETOOTH},
+ {"drivers/media/v4l", ICON_CAMERA_WEB},
+ {"arch/x86/crypto/", ICON_CRYPTOHASH},
+ {"drivers/crypto/", ICON_CRYPTOHASH},
+ {"net/bluetooth/", ICON_BLUETOOTH},
+ {"drivers/input/", ICON_INPUTDEVICES},
+ {"drivers/cdrom/", ICON_CDROM},
+ {"drivers/hwmon/", ICON_THERM},
+ {"drivers/iommu/", ICON_MEMORY},
+ {"net/wireless/", ICON_WIRELESS},
+ {"drivers/nvme/", ICON_HDD},
+ {"net/ethernet/", ICON_NETWORK_INTERFACE},
+ {"drivers/scsi/", ICON_HDD},
+ {"drivers/edac/", ICON_MEMORY},
+ {"drivers/hid/", ICON_INPUTDEVICES},
+ {"drivers/gpu/", ICON_MONITOR},
+ {"drivers/i2c/", ICON_MEMORY},
+ {"drivers/ata/", ICON_HDD},
+ {"drivers/usb/", ICON_USB},
+ {"drivers/pci/", ICON_DEVICES},
+ {"drivers/net/", ICON_NETWORK},
+ {"drivers/mmc/", ICON_MEDIA_REMOVABLE},
+ {"crypto/", ICON_CRYPTOHASH},
+ {"sound/", ICON_AUDIO},
+ {"net/", ICON_NETWORK_CONNECTIONS},
+ {"fs/", ICON_MEDIA_FLOPPY},
+ {},
+};
+
+static GHashTable *module_icons;
-void
-scan_modules_do(void)
+static void build_icon_table_iter(JsonObject *object,
+ const gchar *key,
+ JsonNode *value,
+ gpointer user_data)
{
+ char *key_copy = g_strdup(key);
+ char *p;
+
+ for (p = key_copy; *p; p++) {
+ if (*p == '_')
+ *p = '-';
+ }
+
+ enum icons icon;
+ const gchar *value_str = json_node_get_string(value);
+ for (icon = ICON_INVALID; icon < ICON_MAX; icon++) {
+ const char *icon_name = icon_table[icon];
+
+ if (!icon_name)
+ continue;
+
+ if (g_str_equal(value_str, icon_name)) {
+ g_hash_table_insert(module_icons,
+ key_copy, GINT_TO_POINTER(icon));
+ return;
+ }
+ }
+
+ g_free(key_copy);
+}
+
+void kernel_module_icon_init(void)
+{
+ gchar *icon_json;
+
+ static SyncEntry sync_entry = {
+ .name = N_("Update kernel module icon table"),
+ .file_name = "kernel-module-icons.json",
+ };
+ sync_manager_add_entry(&sync_entry);
+
+ icon_json = g_build_filename(g_get_user_config_dir(),
+ "hardinfo", "kernel-module-icons.json",
+ NULL);
+
+ module_icons = g_hash_table_new(g_str_hash, g_str_equal);
+
+ if (!g_file_test(icon_json, G_FILE_TEST_EXISTS))
+ goto out;
+
+ JsonParser *parser = json_parser_new();
+ if (!json_parser_load_from_file(parser, icon_json, NULL))
+ goto out_destroy_parser;
+
+ JsonNode *root = json_parser_get_root(parser);
+ if (json_node_get_node_type(root) != JSON_NODE_OBJECT)
+ goto out_destroy_parser;
+
+ JsonObject *icons = json_node_get_object(root);
+ if (!icons)
+ goto out_destroy_parser;
+
+ json_object_foreach_member(icons, build_icon_table_iter, NULL);
+
+out_destroy_parser:
+ g_object_unref(parser);
+
+out:
+ g_free(icon_json);
+}
+
+static const gchar* get_module_icon(const char *modname, const char *path)
+{
+ char *modname_temp = g_strdup(modname);
+ char *p;
+ for (p = modname_temp; *p; p++) {
+ if (*p == '_')
+ *p = '-';
+ }
+ gpointer icon = g_hash_table_lookup(module_icons, modname_temp);
+ g_free(modname_temp);
+ if (icon)
+ return icon_table[GPOINTER_TO_INT(icon)];
+
+ if (path == NULL) /* modinfo couldn't find module path */
+ return NULL;
+
+ if (kernel_modules_dir == NULL) {
+ struct utsname utsbuf;
+ uname(&utsbuf);
+ kernel_modules_dir = g_strdup_printf("/lib/modules/%s/kernel/", utsbuf.release);
+ }
+
+ if (!g_str_has_prefix(path, kernel_modules_dir))
+ return NULL;
+
+ const gchar *path_no_prefix = path + strlen(kernel_modules_dir);
+ const size_t path_no_prefix_len = strlen(path_no_prefix);
+ int i;
+
+ for (i = 0; modules_icons[i].dir; i++) {
+ if (g_str_has_prefix(path_no_prefix, modules_icons[i].dir))
+ return icon_table[modules_icons[i].icon];
+ }
+
+ return NULL;
+}
+
+void scan_modules_do(void) {
FILE *lsmod;
gchar buffer[1024];
gchar *lsmod_path;
+ gchar *module_icons;
+ const gchar *icon;
- if (!_module_hash_table) {
- _module_hash_table = g_hash_table_new(g_str_hash, g_str_equal);
- }
+ if (!_module_hash_table) { _module_hash_table = g_hash_table_new(g_str_hash, g_str_equal); }
g_free(module_list);
+ kernel_modules_dir = NULL;
module_list = NULL;
+ module_icons = NULL;
moreinfo_del_with_prefix("COMP:MOD");
lsmod_path = find_program("lsmod");
- if (!lsmod_path)
- return;
+ if (!lsmod_path) return;
lsmod = popen(lsmod_path, "r");
if (!lsmod) {
g_free(lsmod_path);
- return;
+ return;
}
- (void)fgets(buffer, 1024, lsmod); /* Discards the first line */
+ (void)fgets(buffer, 1024, lsmod); /* Discards the first line */
while (fgets(buffer, 1024, lsmod)) {
- gchar *buf, *strmodule, *hashkey;
- gchar *author = NULL,
- *description = NULL,
- *license = NULL,
- *deps = NULL, *vermagic = NULL, *filename = NULL, modname[64];
- FILE *modi;
- glong memory;
-
- shell_status_pulse();
-
- buf = buffer;
-
- sscanf(buf, "%s %ld", modname, &memory);
-
- hashkey = g_strdup_printf("MOD%s", modname);
- buf = g_strdup_printf("/sbin/modinfo %s 2>/dev/null", modname);
-
- modi = popen(buf, "r");
- while (fgets(buffer, 1024, modi)) {
- gchar **tmp = g_strsplit(buffer, ":", 2);
-
- GET_STR("author", author);
- GET_STR("description", description);
- GET_STR("license", license);
- GET_STR("depends", deps);
- GET_STR("vermagic", vermagic);
- GET_STR("filename", filename);
-
- g_strfreev(tmp);
- }
- pclose(modi);
- g_free(buf);
-
- /* old modutils includes quotes in some strings; strip them */
- /*remove_quotes(modname);
- remove_quotes(description);
- remove_quotes(vermagic);
- remove_quotes(author);
- remove_quotes(license); */
-
- /* old modutils displays <none> when there's no value for a
- given field; this is not desirable in the module name
- display, so change it to an empty string */
- if (description && g_str_equal(description, "&lt;none&gt;")) {
- g_free(description);
- description = g_strdup("");
-
- g_hash_table_insert(_module_hash_table,
- g_strdup(modname),
+ gchar *buf, *strmodule, *hashkey;
+ gchar *author = NULL, *description = NULL, *license = NULL, *deps = NULL, *vermagic = NULL,
+ *filename = NULL, *srcversion = NULL, *version = NULL, *retpoline = NULL,
+ *intree = NULL, modname[64];
+ FILE *modi;
+ glong memory;
+
+ shell_status_pulse();
+
+ buf = buffer;
+
+ sscanf(buf, "%s %ld", modname, &memory);
+
+ hashkey = g_strdup_printf("MOD%s", modname);
+ buf = g_strdup_printf("/sbin/modinfo %s 2>/dev/null", modname);
+
+ modi = popen(buf, "r");
+ while (fgets(buffer, 1024, modi)) {
+ gchar **tmp = g_strsplit(buffer, ":", 2);
+
+ GET_STR("author", author);
+ GET_STR("description", description);
+ GET_STR("license", license);
+ GET_STR("depends", deps);
+ GET_STR("vermagic", vermagic);
+ GET_STR("filename", filename);
+ GET_STR("srcversion", srcversion); /* so "version" doesn't catch */
+ GET_STR("version", version);
+ GET_STR("retpoline", retpoline);
+ GET_STR("intree", intree);
+
+ g_strfreev(tmp);
+ }
+ pclose(modi);
+ g_free(buf);
+
+ /* old modutils includes quotes in some strings; strip them */
+ /*remove_quotes(modname);
+ remove_quotes(description);
+ remove_quotes(vermagic);
+ remove_quotes(author);
+ remove_quotes(license); */
+
+ /* old modutils displays <none> when there's no value for a
+ given field; this is not desirable in the module name
+ display, so change it to an empty string */
+ if (description && g_str_equal(description, "&lt;none&gt;")) {
+ g_free(description);
+ description = g_strdup("");
+
+ g_hash_table_insert(_module_hash_table, g_strdup(modname),
g_strdup_printf("Kernel module (%s)", modname));
- } else {
- g_hash_table_insert(_module_hash_table,
- g_strdup(modname),
- g_strdup(description));
+ } else {
+ g_hash_table_insert(_module_hash_table, g_strdup(modname), g_strdup(description));
}
- /* append this module to the list of modules */
- module_list = h_strdup_cprintf("$%s$%s=%s\n",
- module_list,
- hashkey,
- modname,
- description ? description : "");
-
- STRIFNULL(filename, _("(Not available)") );
- STRIFNULL(description, _("(Not available)") );
- STRIFNULL(vermagic, _("(Not available)") );
- STRIFNULL(author, _("(Not available)") );
- STRIFNULL(license, _("(Not available)") );
-
- /* create the module information string */
- strmodule = g_strdup_printf("[%s]\n"
- "%s=%s\n"
- "%s=%.2f %s\n"
- "[%s]\n"
- "%s=%s\n"
- "%s=%s\n"
- "%s=%s\n"
- "[%s]\n"
- "%s=%s\n"
- "%s=%s\n",
- _("Module Information"),
- _("Path"), filename,
- _("Used Memory"), memory / 1024.0, _("KiB"),
- _("Description"),
- _("Name"), modname,
- _("Description"), description,
- _("Version Magic"), vermagic,
- _("Copyright"),
- _("Author"), author,
- _("License"), license );
-
- /* if there are dependencies, append them to that string */
- if (deps && strlen(deps)) {
- gchar **tmp = g_strsplit(deps, ",", 0);
-
- strmodule = h_strconcat(strmodule,
- "\n[", _("Dependencies"), "]\n",
- g_strjoinv("=\n", tmp),
- "=\n", NULL);
- g_strfreev(tmp);
- g_free(deps);
- }
+ /* append this module to the list of modules */
+ module_list = h_strdup_cprintf("$%s$%s=%s\n", module_list, hashkey, modname,
+ description ? description : "");
+ icon = get_module_icon(modname, filename);
+ module_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", module_icons, hashkey,
+ modname, icon ? icon: "module");
+
+ STRIFNULL(filename, _("(Not available)"));
+ STRIFNULL(description, _("(Not available)"));
+ STRIFNULL(vermagic, _("(Not available)"));
+ STRIFNULL(author, _("(Not available)"));
+ STRIFNULL(license, _("(Not available)"));
+ STRIFNULL(version, _("(Not available)"));
+
+ gboolean ry = FALSE, ity = FALSE;
+ if (retpoline && *retpoline == 'Y') ry = TRUE;
+ if (intree && *intree == 'Y') ity = TRUE;
- moreinfo_add_with_prefix("COMP", hashkey, strmodule);
- g_free(hashkey);
+ g_free(retpoline);
+ g_free(intree);
- g_free(license);
- g_free(description);
- g_free(author);
- g_free(vermagic);
- g_free(filename);
+ retpoline = g_strdup(ry ? _("Yes") : _("No"));
+ intree = g_strdup(ity ? _("Yes") : _("No"));
+
+ /* create the module information string */
+ strmodule = g_strdup_printf("[%s]\n"
+ "%s=%s\n"
+ "%s=%.2f %s\n"
+ "[%s]\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "[%s]\n"
+ "%s=%s\n"
+ "%s=%s\n",
+ _("Module Information"), _("Path"), filename, _("Used Memory"),
+ memory / 1024.0, _("KiB"), _("Description"), _("Name"), modname,
+ _("Description"), description, _("Version Magic"), vermagic,
+ _("Version"), version, _("In Linus' Tree"), intree,
+ _("Retpoline Enabled"), retpoline, _("Copyright"), _("Author"),
+ author, _("License"), license);
+
+ /* if there are dependencies, append them to that string */
+ if (deps && strlen(deps)) {
+ gchar **tmp = g_strsplit(deps, ",", 0);
+
+ strmodule = h_strconcat(strmodule, "\n[", _("Dependencies"), "]\n",
+ g_strjoinv("=\n", tmp), "=\n", NULL);
+ g_strfreev(tmp);
+ g_free(deps);
+ }
+
+ moreinfo_add_with_prefix("COMP", hashkey, strmodule);
+ g_free(hashkey);
+
+ g_free(license);
+ g_free(description);
+ g_free(author);
+ g_free(vermagic);
+ g_free(filename);
+ g_free(srcversion);
+ g_free(version);
+ g_free(retpoline);
+ g_free(intree);
}
pclose(lsmod);
g_free(lsmod_path);
+ g_free(kernel_modules_dir);
+
+ if (module_list != NULL && module_icons != NULL) {
+ module_list = h_strdup_cprintf("[$ShellParam$]\n%s", module_list, module_icons);
+ }
+ g_free(module_icons);
}
diff --git a/modules/computer/os.c b/modules/computer/os.c
index a8886f64..7648eef3 100644
--- a/modules/computer/os.c
+++ b/modules/computer/os.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,6 +21,7 @@
#include <sys/utsname.h>
#include "hardinfo.h"
#include "computer.h"
+#include "distro_flavors.h"
static gchar *
get_libc_version(void)
@@ -46,7 +47,7 @@ get_libc_version(void)
gboolean spawned;
gchar *out, *err, *p;
- spawned = g_spawn_command_line_sync(libs[i].test_cmd,
+ spawned = hardinfo_spawn_command_line_sync(libs[i].test_cmd,
&out, &err, NULL, NULL);
if (!spawned)
continue;
@@ -91,7 +92,7 @@ static gchar *detect_kde_version(void)
cmd = "kcontrol --version";
}
- spawned = g_spawn_command_line_sync(cmd, &out, NULL, NULL, NULL);
+ spawned = hardinfo_spawn_command_line_sync(cmd, &out, NULL, NULL, NULL);
if (!spawned)
return NULL;
@@ -106,7 +107,7 @@ detect_gnome_version(void)
gchar *out;
gboolean spawned;
- spawned = g_spawn_command_line_sync(
+ spawned = hardinfo_spawn_command_line_sync(
"gnome-shell --version", &out, NULL, NULL, NULL);
if (spawned) {
tmp = strstr(idle_free(out), _("GNOME Shell "));
@@ -117,7 +118,7 @@ detect_gnome_version(void)
}
}
- spawned = g_spawn_command_line_sync(
+ spawned = hardinfo_spawn_command_line_sync(
"gnome-about --gnome-version", &out, NULL, NULL, NULL);
if (spawned) {
tmp = strstr(idle_free(out), _("Version: "));
@@ -131,17 +132,42 @@ detect_gnome_version(void)
return NULL;
}
+
static gchar *
-detect_window_manager(void)
+detect_mate_version(void)
{
- GdkScreen *screen = gdk_screen_get_default();
- const gchar *windowman;
- const gchar *curdesktop;
+ gchar *tmp;
+ gchar *out;
+ gboolean spawned;
- if (!screen || !GDK_IS_SCREEN(screen))
- return NULL;
+ spawned = hardinfo_spawn_command_line_sync(
+ "mate-about --version", &out, NULL, NULL, NULL);
+ if (spawned) {
+ tmp = strstr(idle_free(out), _("MATE Desktop Environment "));
- windowman = gdk_x11_screen_get_window_manager_name(screen);
+ if (tmp) {
+ tmp += strlen(_("MATE Desktop Environment "));
+ return g_strdup_printf("MATE %s", strend(tmp, '\n'));
+ }
+ }
+
+ return NULL;
+}
+
+static gchar *
+detect_window_manager(void)
+{
+ const gchar *curdesktop;
+ const gchar* windowman;
+ GdkScreen *screen = gdk_screen_get_default();
+
+#if GTK_CHECK_VERSION(3,0,0)
+ if (GDK_IS_X11_SCREEN(screen)) {
+#else
+ if (screen && GDK_IS_SCREEN(screen)) {
+#endif
+ windowman = gdk_x11_screen_get_window_manager_name(screen);
+ } else return g_strdup("Not X11");
if (g_str_equal(windowman, "Xfwm4"))
return g_strdup("XFCE 4");
@@ -192,6 +218,12 @@ detect_xdg_environment(const gchar *env_var)
if (maybe_kde)
return maybe_kde;
}
+ if (g_str_equal(tmp, "MATE") || g_str_equal(tmp, "mate")) {
+ gchar *maybe_mate = detect_mate_version();
+
+ if (maybe_mate)
+ return maybe_mate;
+ }
return g_strdup(tmp);
}
@@ -235,6 +267,44 @@ detect_desktop_environment(void)
}
gchar *
+computer_get_dmesg_status(void)
+{
+ gchar *out = NULL, *err = NULL;
+ int ex = 1, result = 0;
+ hardinfo_spawn_command_line_sync("dmesg", &out, &err, &ex, NULL);
+ g_free(out);
+ g_free(err);
+ result += (getuid() == 0) ? 2 : 0;
+ result += ex ? 1 : 0;
+ switch(result) {
+ case 0: /* readable, user */
+ return g_strdup(_("User access allowed"));
+ case 1: /* unreadable, user */
+ return g_strdup(_("User access forbidden"));
+ case 2: /* readable, root */
+ return g_strdup(_("Access allowed (running as superuser)"));
+ case 3: /* unreadable, root */
+ return g_strdup(_("Access forbidden? (running as superuser)"));
+ }
+ return g_strdup(_("(Unknown)"));
+}
+
+gchar *
+computer_get_aslr(void)
+{
+ switch (h_sysfs_read_int("/proc/sys/kernel", "randomize_va_space")) {
+ case 0:
+ return g_strdup(_("Disabled"));
+ case 1:
+ return g_strdup(_("Partially enabled (mmap base+stack+VDSO base)"));
+ case 2:
+ return g_strdup(_("Fully enabled (mmap base+stack+VDSO base+heap)"));
+ default:
+ return g_strdup(_("Unknown"));
+ }
+}
+
+gchar *
computer_get_entropy_avail(void)
{
gchar tab_entropy_fstr[][32] = {
@@ -281,7 +351,77 @@ computer_get_language(void)
return ret;
}
-static gchar *
+static Distro
+parse_os_release(void)
+{
+ gchar *pretty_name = NULL;
+ gchar *id = NULL;
+ gchar *codename = NULL;
+ gchar **split, *contents, **line;
+
+ if (!g_file_get_contents("/usr/lib/os-release", &contents, NULL, NULL))
+ return (Distro) {};
+
+ split = g_strsplit(idle_free(contents), "\n", 0);
+ if (!split)
+ return (Distro) {};
+
+ for (line = split; *line; line++) {
+ if (!strncmp(*line, "ID=", sizeof("ID=") - 1)) {
+ id = g_strdup(*line + strlen("ID="));
+ } else if (!strncmp(*line, "CODENAME=", sizeof("CODENAME=") - 1)) {
+ codename = g_strdup(*line + strlen("CODENAME="));
+ } else if (!strncmp(*line, "PRETTY_NAME=", sizeof("PRETTY_NAME=") - 1)) {
+ pretty_name = g_strdup(*line +
+ strlen("PRETTY_NAME=\""));
+ strend(pretty_name, '"');
+ }
+ }
+
+ g_strfreev(split);
+
+ if (pretty_name)
+ return (Distro) { .distro = pretty_name, .codename = codename, .id = id };
+
+ g_free(id);
+ return (Distro) {};
+}
+
+static Distro
+parse_lsb_release(void)
+{
+ gchar *pretty_name = NULL;
+ gchar *id = NULL;
+ gchar *codename = NULL;
+ gchar **split, *contents, **line;
+
+ if (!hardinfo_spawn_command_line_sync("/usr/bin/lsb_release -di", &contents, NULL, NULL, NULL))
+ return (Distro) {};
+
+ split = g_strsplit(idle_free(contents), "\n", 0);
+ if (!split)
+ return (Distro) {};
+
+ for (line = split; *line; line++) {
+ if (!strncmp(*line, "Distributor ID:\t", sizeof("Distributor ID:\t") - 1)) {
+ id = g_utf8_strdown(*line + strlen("Distributor ID:\t"), -1);
+ } else if (!strncmp(*line, "Codename:\t", sizeof("Codename:\t") - 1)) {
+ codename = g_utf8_strdown(*line + strlen("Codename:\t"), -1);
+ } else if (!strncmp(*line, "Description:\t", sizeof("Description:\t") - 1)) {
+ pretty_name = g_strdup(*line + strlen("Description:\t"));
+ }
+ }
+
+ g_strfreev(split);
+
+ if (pretty_name)
+ return (Distro) { .distro = pretty_name, .codename = codename, .id = id };
+
+ g_free(id);
+ return (Distro) {};
+}
+
+static Distro
detect_distro(void)
{
static const struct {
@@ -292,11 +432,11 @@ detect_distro(void)
#define DB_PREFIX "/etc/"
{ DB_PREFIX "arch-release", "arch", "Arch Linux" },
{ DB_PREFIX "fatdog-version", "fatdog" },
- { DB_PREFIX "debian_version", "deb" },
+ { DB_PREFIX "debian_version", "debian" },
{ DB_PREFIX "slackware-version", "slk" },
{ DB_PREFIX "mandrake-release", "mdk" },
{ DB_PREFIX "mandriva-release", "mdv" },
- { DB_PREFIX "fedora-release", "fdra" },
+ { DB_PREFIX "fedora-release", "fedora" },
{ DB_PREFIX "coas", "coas" },
{ DB_PREFIX "environment.corel", "corel"},
{ DB_PREFIX "gentoo-release", "gnt" },
@@ -305,7 +445,6 @@ detect_distro(void)
{ DB_PREFIX "turbolinux-release", "tl" },
{ DB_PREFIX "yellowdog-release", "yd" },
{ DB_PREFIX "sabayon-release", "sbn" },
- { DB_PREFIX "arch-release", "arch" },
{ DB_PREFIX "enlisy-release", "enlsy" },
{ DB_PREFIX "SuSE-release", "suse" },
{ DB_PREFIX "sun-release", "sun" },
@@ -324,15 +463,17 @@ detect_distro(void)
#undef DB_PREFIX
{ NULL, NULL }
};
+ Distro distro;
gchar *contents;
int i;
- if (g_spawn_command_line_sync("lsb_release -d", &contents, NULL, NULL, NULL)) {
- gchar *tmp = strstr(idle_free(contents), "Description:\t");
+ distro = parse_os_release();
+ if (distro.distro)
+ return distro;
- if (tmp)
- return g_strdup(tmp + strlen("Description:\t"));
- }
+ distro = parse_lsb_release();
+ if (distro.distro)
+ return distro;
for (i = 0; distro_db[i].file; i++) {
if (!g_file_get_contents(distro_db[i].file, &contents, NULL, NULL))
@@ -340,23 +481,31 @@ detect_distro(void)
if (distro_db[i].override) {
g_free(contents);
- return g_strdup(distro_db[i].override);
+ return (Distro) { .distro = g_strdup(distro_db[i].override),
+ .codename = g_strdup(distro_db[i].codename) };
}
- if (g_str_equal(distro_db[i].codename, "deb")) {
+ if (g_str_equal(distro_db[i].codename, "debian")) {
/* HACK: Some Debian systems doesn't include the distribuition
* name in /etc/debian_release, so add them here. */
if (isdigit(contents[0]) || contents[0] != 'D')
- return g_strdup_printf("Debian GNU/Linux %s", (char*)idle_free(contents));
+ return (Distro) {
+ .distro = g_strdup_printf("Debian GNU/Linux %s", (char*)idle_free(contents)),
+ .codename = g_strdup(distro_db[i].codename)
+ };
}
- if (g_str_equal(distro_db[i].codename, "fatdog"))
- return g_strdup_printf("Fatdog64 [%.10s]", (char*)idle_free(contents));
+ if (g_str_equal(distro_db[i].codename, "fatdog")) {
+ return (Distro) {
+ .distro = g_strdup_printf("Fatdog64 [%.10s]", (char*)idle_free(contents)),
+ .codename = g_strdup(distro_db[i].codename)
+ };
+ }
- return contents;
+ return (Distro) { .distro = contents, .codename = g_strdup(distro_db[i].codename) };
}
- return g_strdup(_("Unknown"));
+ return (Distro) { .distro = g_strdup(_("Unknown")) };
}
OperatingSystem *
@@ -368,13 +517,17 @@ computer_get_os(void)
os = g_new0(OperatingSystem, 1);
- os->distro = g_strstrip(detect_distro());
+ Distro distro = detect_distro();
+ os->distro = g_strstrip(distro.distro);
+ os->distroid = distro.id;
+ os->distrocode = distro.codename;
/* Kernel and hostname info */
uname(&utsbuf);
os->kernel_version = g_strdup(utsbuf.version);
os->kernel = g_strdup_printf("%s %s (%s)", utsbuf.sysname,
utsbuf.release, utsbuf.machine);
+ os->kcmdline = h_sysfs_read_string("/proc", "cmdline");
os->hostname = g_strdup(utsbuf.nodename);
os->language = computer_get_language();
os->homedir = g_strdup(g_get_home_dir());
@@ -389,5 +542,41 @@ computer_get_os(void)
os->entropy_avail = computer_get_entropy_avail();
+ if (g_strcmp0(os->distrocode, "ubuntu") == 0) {
+ GSList *flavs = ubuntu_flavors_scan();
+ if (flavs) {
+ /* just use the first one */
+ os->distro_flavor = (DistroFlavor*)flavs->data;
+ }
+ g_slist_free(flavs);
+ }
+
return os;
}
+
+const gchar *
+computer_get_selinux(void)
+{
+ int r;
+ gboolean spawned = hardinfo_spawn_command_line_sync("selinuxenabled",
+ NULL, NULL, &r, NULL);
+
+ if (!spawned)
+ return _("Not installed");
+
+ if (r == 0)
+ return _("Enabled");
+
+ return _("Disabled");
+}
+
+gchar *
+computer_get_lsm(void)
+{
+ gchar *contents;
+
+ if (!g_file_get_contents("/sys/kernel/security/lsm", &contents, NULL, NULL))
+ return g_strdup(_("Unknown"));
+
+ return contents;
+}
diff --git a/modules/computer/ubuntu_flavors.c b/modules/computer/ubuntu_flavors.c
new file mode 100644
index 00000000..ac67d665
--- /dev/null
+++ b/modules/computer/ubuntu_flavors.c
@@ -0,0 +1,90 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2019 L. A. F. Pereira <l@tia.mat.br>
+ * This file Burt P. <pburt0@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <hardinfo.h>
+#include "distro_flavors.h"
+#include "util_sysobj.h" /* for appfsp() */
+
+static const UbuntuFlavor ubuntu_flavors[] = {
+ { "Vanilla Server", "distros/ubuntu.svg", "https://ubuntu.org", "ubuntu-server" },
+ { "Vanilla Desktop", "distros/ubuntu.svg", "https://ubuntu.org", "ubuntu-desktop" },
+ { "Xubuntu", "distros/xubuntu.svg", "https://xubuntu.org", "xubuntu-desktop" },
+ { "Kubuntu", "distros/kubuntu.png", "https://kubuntu.org", "kubuntu-desktop" },
+ { "Lubuntu", "distros/lubuntu.png", "https://lubuntu.me", "lubuntu-desktop" }, /* formerly or also lubuntu.net? */
+ { "Ubuntu MATE", "distros/ubuntu-mate.png", "https://ubuntu-mate.org", "ubuntu-mate-desktop" },
+ { "Ubuntu Budgie", "distros/ubuntu-budgie.png", "https://ubuntubudgie.org", "ubuntu-budgie-desktop" },
+ { "UbuntuKylin (做最有中国味的操作系统)", "distros/ubuntu-kylin.png", "https://www.ubuntukylin.com", "ubuntukylin-desktop" },
+ { "UbuntuStudio", "distros/ubuntu-studio.png", "https://ubuntustudio.org", "ubuntustudio-desktop" },
+ /* Deprecated flavors */
+ { "Ubuntu GNOME", "distros/ubuntu-gnome.png", "https://ubuntugnome.org", "ubuntu-gnome-desktop" },
+ // Edubuntu
+ // Mythbuntu
+ { NULL }
+};
+
+static const UbuntuFlavor *_find_flavor(const gchar *pkg) {
+ int i = 0;
+ for(; ubuntu_flavors[i].base.name; i++) {
+ if (SEQ(ubuntu_flavors[i].package, pkg))
+ return &ubuntu_flavors[i];
+ }
+ return NULL;
+}
+
+/* items are const; free with g_slist_free() */
+GSList *ubuntu_flavors_scan(void) {
+ GSList *ret = NULL;
+ gboolean spawned;
+ gchar *out, *err, *p, *next_nl;
+ gint exit_status;
+ const UbuntuFlavor *f = NULL;
+ gchar *cmd_line = g_strdup("apt-cache policy");
+ int i;
+ for(i = 0; ubuntu_flavors[i].base.name; i++) {
+ cmd_line = appfsp(cmd_line, "%s", ubuntu_flavors[i].package);
+ }
+ if (!i)
+ return NULL;
+
+ spawned = hardinfo_spawn_command_line_sync(cmd_line,
+ &out, &err, &exit_status, NULL);
+ if (spawned) {
+ p = out;
+ while(next_nl = strchr(p, '\n')) {
+ strend(p, '\n');
+ int mc = 0;
+ char pkg[32] = "";
+ if (*p != ' ' && *p != '\t')
+ mc = sscanf(p, "%31s", pkg);
+ if (mc == 1) {
+ strend(pkg, ':');
+ f = _find_flavor(pkg);
+ } else if
+ (g_strstr_len(p, -1, "Installed:")
+ && !g_strstr_len(p, -1, "(none)") ) {
+ ret = g_slist_append(ret, (void*)f);
+ }
+ p = next_nl + 1;
+ }
+ g_free(out);
+ g_free(err);
+ }
+ g_free(cmd_line);
+ return ret;
+}
diff --git a/modules/computer/uptime.c b/modules/computer/uptime.c
index 6ef3d250..8aef1530 100644
--- a/modules/computer/uptime.c
+++ b/modules/computer/uptime.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/computer/users.c b/modules/computer/users.c
index f47320bb..75e24f26 100644
--- a/modules/computer/users.c
+++ b/modules/computer/users.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2009 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2009 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices.c b/modules/devices.c
index 152b6831..574896ee 100644
--- a/modules/devices.c
+++ b/modules/devices.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,10 +20,6 @@
#define __USE_XOPEN
#endif /* __USE_XOPEN */
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE
-#endif /* _XOPEN_SOURCE */
-
#include <gtk/gtk.h>
#include <config.h>
#include <string.h>
@@ -38,9 +34,13 @@
#include "devices.h"
#include "dt_util.h"
+#include "udisks2_util.h"
+#include "storage_util.h"
+#include "pci_util.h"
gchar *callback_processors();
-gchar *callback_memory();
+gchar *callback_gpu();
+gchar *callback_monitors();
gchar *callback_battery();
gchar *callback_pci();
gchar *callback_sensors();
@@ -48,15 +48,15 @@ gchar *callback_printers();
gchar *callback_storage();
gchar *callback_input();
gchar *callback_usb();
-#if defined(ARCH_x86) || defined(ARCH_x86_64)
gchar *callback_dmi();
-gchar *callback_spd();
-#endif
+gchar *callback_dmi_mem();
+gchar *callback_firmware();
gchar *callback_dtree();
gchar *callback_device_resources();
void scan_processors(gboolean reload);
-void scan_memory(gboolean reload);
+void scan_gpu(gboolean reload);
+void scan_monitors(gboolean reload);
void scan_battery(gboolean reload);
void scan_pci(gboolean reload);
void scan_sensors(gboolean reload);
@@ -64,50 +64,52 @@ void scan_printers(gboolean reload);
void scan_storage(gboolean reload);
void scan_input(gboolean reload);
void scan_usb(gboolean reload);
-#if defined(ARCH_x86) || defined(ARCH_x86_64)
void scan_dmi(gboolean reload);
-void scan_spd(gboolean reload);
-#endif
+void scan_dmi_mem(gboolean reload);
+void scan_firmware(gboolean reload);
void scan_dtree(gboolean reload);
void scan_device_resources(gboolean reload);
gboolean root_required_for_resources(void);
+gboolean spd_decode_show_hinote(const char**);
gchar *hi_more_info(gchar *entry);
enum {
ENTRY_DTREE,
+ ENTRY_DMI,
ENTRY_PROCESSOR,
- ENTRY_MEMORY,
+ ENTRY_GPU,
+ ENTRY_MONITORS,
+ ENTRY_DMI_MEM,
ENTRY_PCI,
ENTRY_USB,
+ ENTRY_FW,
ENTRY_PRINTERS,
ENTRY_BATTERY,
ENTRY_SENSORS,
ENTRY_INPUT,
ENTRY_STORAGE,
- ENTRY_DMI,
- ENTRY_SPD,
ENTRY_RESOURCES
};
static ModuleEntry entries[] = {
[ENTRY_PROCESSOR] = {N_("Processor"), "processor.png", callback_processors, scan_processors, MODULE_FLAG_NONE},
- [ENTRY_MEMORY] = {N_("Memory"), "memory.png", callback_memory, scan_memory, MODULE_FLAG_NONE},
+ [ENTRY_GPU] = {N_("Graphics Processors"), "devices.png", callback_gpu, scan_gpu, MODULE_FLAG_NONE},
+ [ENTRY_MONITORS] = {N_("Monitors"), "monitor.png", callback_monitors, scan_monitors, MODULE_FLAG_NONE},
[ENTRY_PCI] = {N_("PCI Devices"), "devices.png", callback_pci, scan_pci, MODULE_FLAG_NONE},
[ENTRY_USB] = {N_("USB Devices"), "usb.png", callback_usb, scan_usb, MODULE_FLAG_NONE},
+ [ENTRY_FW] = {N_("Firmware"), "processor.png", callback_firmware, scan_firmware, MODULE_FLAG_NONE},
[ENTRY_PRINTERS] = {N_("Printers"), "printer.png", callback_printers, scan_printers, MODULE_FLAG_NONE},
[ENTRY_BATTERY] = {N_("Battery"), "battery.png", callback_battery, scan_battery, MODULE_FLAG_NONE},
[ENTRY_SENSORS] = {N_("Sensors"), "therm.png", callback_sensors, scan_sensors, MODULE_FLAG_NONE},
[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_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_DMI] = {N_("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_DTREE] = {"#"},
+ [ENTRY_DTREE] = {N_("Device Tree"), "devices.png", callback_dtree, scan_dtree, MODULE_FLAG_HIDE},
#else
- [ENTRY_DMI] = {"#"},
- [ENTRY_SPD] = {"#"},
[ENTRY_DTREE] = {N_("Device Tree"), "devices.png", callback_dtree, scan_dtree, MODULE_FLAG_NONE},
#endif /* x86 or x86_64 */
[ENTRY_RESOURCES] = {N_("Resources"), "resources.png", callback_device_resources, scan_device_resources, MODULE_FLAG_NONE},
@@ -119,13 +121,34 @@ gchar *printer_list = NULL;
gchar *printer_icons = NULL;
gchar *pci_list = NULL;
gchar *input_list = NULL;
+gboolean storage_no_nvme = FALSE;
gchar *storage_list = NULL;
gchar *battery_list = NULL;
-gchar *meminfo = NULL;
-gchar *lginterval = NULL;
+
+/* in dmi_memory.c */
+gchar *memory_devices_get_info();
+gboolean memory_devices_hinote(const char **msg);
+gchar *memory_devices_info = NULL;
+
+/* in firmware.c */
+gchar *firmware_get_info();
+gboolean firmware_hinote(const char **msg);
+gchar *firmware_info = NULL;
+
+/* in monitors.c */
+gchar *monitors_get_info();
+gboolean monitors_hinote(const char **msg);
+gchar *monitors_info = NULL;
#include <vendor.h>
+extern gchar *gpu_summary;
+const gchar *get_gpu_summary() {
+ if (gpu_summary == NULL)
+ scan_gpu(FALSE);
+ return gpu_summary;
+}
+
static gint proc_cmp_model_name(Processor *a, Processor *b) {
return g_strcmp0(a->model_name, b->model_name);
}
@@ -140,19 +163,27 @@ static gint proc_cmp_max_freq(Processor *a, Processor *b) {
gchar *processor_describe_default(GSList * processors)
{
- int packs, cores, threads;
- const gchar *packs_fmt, *cores_fmt, *threads_fmt;
+ int packs, cores, threads, nodes;
+ const gchar *packs_fmt, *cores_fmt, *threads_fmt, *nodes_fmt;
gchar *ret, *full_fmt;
- cpu_procs_cores_threads(&packs, &cores, &threads);
+ cpu_procs_cores_threads_nodes(&packs, &cores, &threads, &nodes);
+
+ /* NOTE: If this is changed, look at get_cpu_desc() in bench_results.c! */
/* if topology info was available, else fallback to old method */
if (cores > 0) {
packs_fmt = ngettext("%d physical processor", "%d physical processors", packs);
cores_fmt = ngettext("%d core", "%d cores", cores);
threads_fmt = ngettext("%d thread", "%d threads", threads);
- full_fmt = g_strdup_printf(_(/*/NP procs; NC cores; NT threads*/ "%s; %s; %s"), packs_fmt, cores_fmt, threads_fmt);
- ret = g_strdup_printf(full_fmt, packs, cores, threads);
+ if (nodes > 1) {
+ nodes_fmt = ngettext("%d NUMA node", "%d NUMA nodes", nodes);
+ full_fmt = g_strdup_printf(_(/*/NP procs; NC cores across NN nodes; NT threads*/ "%s; %s across %s; %s"), packs_fmt, cores_fmt, nodes_fmt, threads_fmt);
+ ret = g_strdup_printf(full_fmt, packs, cores * nodes, nodes, threads);
+ } else {
+ full_fmt = g_strdup_printf(_(/*/NP procs; NC cores; NT threads*/ "%s; %s; %s"), packs_fmt, cores_fmt, threads_fmt);
+ ret = g_strdup_printf(full_fmt, packs, cores, threads);
+ }
g_free(full_fmt);
return ret;
} else {
@@ -246,6 +277,44 @@ gchar *get_processor_name_and_desc(void)
return nd;
}
+gchar *get_storage_devices_simple(void)
+{
+ scan_storage(FALSE);
+
+ struct Info *info = info_unflatten(storage_list);
+ if (!info) {
+ return "";
+ }
+
+ guint i, fi;
+ struct InfoGroup *group;
+ struct InfoField *field;
+ gchar *storage_devs = NULL, *tmp;
+ const gchar *dev_label, *model_wo_tags;
+
+ GRegex *regex;
+ regex = g_regex_new ("<.*>", 0, 0, NULL);
+
+ for (i = 0; i < info->groups->len; i++) {
+ group = &g_array_index(info->groups, struct InfoGroup, info->groups->len - 1);
+ if (!group)
+ continue;
+
+ info_group_strip_extra(group);
+ for (fi = 0; fi < group->fields->len; fi++) {
+ field = &g_array_index(group->fields, struct InfoField, fi);
+ if (!field->value)
+ continue;
+
+ tmp = g_regex_replace(regex, field->value, -1, 0, "", 0, NULL); // remove html tags
+ storage_devs = h_strdup_cprintf("%s\n", storage_devs, g_strchug(tmp));
+ g_free(tmp);
+ }
+ }
+ g_free(info);
+
+ return storage_devs;
+}
gchar *get_storage_devices(void)
{
@@ -336,59 +405,138 @@ gchar *get_processor_max_frequency(void)
}
}
-gchar *get_pci_device_description(gchar *pci_id)
+gchar *get_motherboard(void)
{
- gchar *description;
+ gchar *board_name, *board_vendor, *board_version;
+ gchar *product_name, *product_vendor, *product_version;
+ gchar *board_part = NULL, *product_part = NULL;
+ const gchar *tmp;
+ int b = 0, p = 0;
- if (!_pci_devices) {
- scan_pci(FALSE);
+ gchar *ret;
+
+#if defined(ARCH_x86) || defined(ARCH_x86_64)
+ scan_dmi(FALSE);
+
+ board_name = dmi_get_str("baseboard-product-name");
+ board_version = dmi_get_str("baseboard-version");
+ board_vendor = dmi_get_str("baseboard-manufacturer");
+ if (board_vendor) {
+ /* attempt to shorten */
+ tmp = vendor_get_shortest_name(board_vendor);
+ if (tmp && tmp != board_vendor) {
+ g_free(board_vendor);
+ board_vendor = g_strdup(tmp);
+ }
}
- if ((description = g_hash_table_lookup(_pci_devices, pci_id))) {
- return g_strdup(description);
+ product_name = dmi_get_str("system-product-name");
+ product_version = dmi_get_str("system-version");
+ product_vendor = dmi_get_str("system-manufacturer");
+ if (product_vendor) {
+ /* attempt to shorten */
+ tmp = vendor_get_shortest_name(product_vendor);
+ if (tmp && tmp != product_vendor) {
+ g_free(product_vendor);
+ product_vendor = g_strdup(tmp);
+ }
}
- return NULL;
-}
+ if (board_vendor && product_vendor &&
+ strcmp(board_vendor, product_vendor) == 0) {
+ /* ignore duplicate vendor */
+ g_free(product_vendor);
+ product_vendor = NULL;
+ }
-gchar *get_memory_total(void)
-{
- scan_memory(FALSE);
- return moreinfo_lookup ("DEV:MemTotal");
-}
+ if (board_name && product_name &&
+ strcmp(board_name, product_name) == 0) {
+ /* ignore duplicate name */
+ g_free(product_name);
+ product_name = NULL;
+ }
-gchar *get_motherboard(void)
-{
- char *board_name, *board_vendor, *system_version;
- char *ret;
+ if (board_version && product_version &&
+ strcmp(board_version, product_version) == 0) {
+ /* ignore duplicate version */
+ g_free(product_version);
+ product_version = NULL;
+ }
-#if defined(ARCH_x86) || defined(ARCH_x86_64)
- scan_dmi(FALSE);
+ if (board_name) b += 1;
+ if (board_vendor) b += 2;
+ if (board_version) b += 4;
+
+ switch(b) {
+ case 1: /* only name */
+ board_part = g_strdup(board_name);
+ break;
+ case 2: /* only vendor */
+ board_part = g_strdup(board_vendor);
+ break;
+ case 3: /* only name and vendor */
+ board_part = g_strdup_printf("%s %s", board_vendor, board_name);
+ break;
+ case 4: /* only version? Seems unlikely */
+ board_part = g_strdup(board_version);
+ break;
+ case 5: /* only name and version? */
+ board_part = g_strdup_printf("%s %s", board_name, board_version);
+ break;
+ case 6: /* only vendor and version (like lpereira's Thinkpad) */
+ board_part = g_strdup_printf("%s %s", board_vendor, board_version);
+ break;
+ case 7: /* all */
+ board_part = g_strdup_printf("%s %s %s", board_vendor, board_name, board_version);
+ break;
+ }
- board_name = dmi_get_str("baseboard-product-name");
- if (board_name == NULL)
- board_name = dmi_get_str("system-product-name");
+ if (product_name) p += 1;
+ if (product_vendor) p += 2;
+ if (product_version) p += 4;
+
+ switch(p) {
+ case 1: /* only name */
+ product_part = g_strdup(product_name);
+ break;
+ case 2: /* only vendor */
+ product_part = g_strdup(product_vendor);
+ break;
+ case 3: /* only name and vendor */
+ product_part = g_strdup_printf("%s %s", product_vendor, product_name);
+ break;
+ case 4: /* only version? Seems unlikely */
+ product_part = g_strdup(product_version);
+ break;
+ case 5: /* only name and version? */
+ product_part = g_strdup_printf("%s %s", product_name, product_version);
+ break;
+ case 6: /* only vendor and version? */
+ product_part = g_strdup_printf("%s %s", product_vendor, product_version);
+ break;
+ case 7: /* all */
+ product_part = g_strdup_printf("%s %s %s", product_vendor, product_name, product_version);
+ break;
+ }
- board_vendor = dmi_get_str("baseboard-manufacturer");
- if (board_vendor == NULL)
- board_vendor = dmi_get_str("system-manufacturer");
-
- system_version = dmi_get_str("system-version");
-
- if (board_name && board_vendor && system_version)
- ret = g_strdup_printf("%s / %s (%s)", system_version, board_name, board_vendor);
- else if (board_name && board_vendor)
- ret = g_strconcat(board_vendor, " ", board_name, NULL);
- else if (board_name)
- ret = g_strdup(board_name);
- else if (board_vendor)
- ret = g_strdup(board_vendor);
+ if (board_part && product_part) {
+ ret = g_strdup_printf("%s (%s)", board_part, product_part);
+ g_free(board_part);
+ g_free(product_part);
+ } else if (board_part)
+ ret = board_part;
+ else if (product_part)
+ ret = product_part;
else
ret = g_strdup(_("(Unknown)"));
- free(board_name);
- free(board_vendor);
- free(system_version);
+ g_free(board_name);
+ g_free(board_vendor);
+ g_free(board_version);
+ g_free(product_name);
+ g_free(product_vendor);
+ g_free(product_version);
+
return ret;
#endif
@@ -400,22 +548,22 @@ gchar *get_motherboard(void)
return g_strdup(_("Unknown"));
}
-ShellModuleMethod *hi_exported_methods(void)
-{
- static ShellModuleMethod m[] = {
- {"getProcessorCount", get_processor_count},
- {"getProcessorName", get_processor_name},
- {"getProcessorDesc", get_processor_desc},
- {"getProcessorNameAndDesc", get_processor_name_and_desc},
- {"getProcessorFrequency", get_processor_max_frequency},
- {"getProcessorFrequencyDesc", get_processor_frequency_desc},
- {"getMemoryTotal", get_memory_total},
- {"getStorageDevices", get_storage_devices},
- {"getPrinters", get_printers},
- {"getInputDevices", get_input_devices},
- {"getPCIDeviceDescription", get_pci_device_description},
- {"getMotherboard", get_motherboard},
- {NULL}
+const ShellModuleMethod *hi_exported_methods(void)
+{
+ static const ShellModuleMethod m[] = {
+ {"getProcessorCount", get_processor_count},
+ {"getProcessorName", get_processor_name},
+ {"getProcessorDesc", get_processor_desc},
+ {"getProcessorNameAndDesc", get_processor_name_and_desc},
+ {"getProcessorFrequency", get_processor_max_frequency},
+ {"getProcessorFrequencyDesc", get_processor_frequency_desc},
+ {"getStorageDevices", get_storage_devices},
+ {"getStorageDevicesSimple", get_storage_devices_simple},
+ {"getPrinters", get_printers},
+ {"getInputDevices", get_input_devices},
+ {"getMotherboard", get_motherboard},
+ {"getGPUList", get_gpu_summary},
+ {NULL},
};
return m;
@@ -434,14 +582,12 @@ gchar *hi_more_info(gchar * entry)
gchar *hi_get_field(gchar * field)
{
gchar *info = moreinfo_lookup_with_prefix("DEV", field);
-
if (info)
- return g_strdup(info);
+ return g_strdup(info);
return g_strdup(field);
}
-#if defined(ARCH_x86) || defined(ARCH_x86_64)
void scan_dmi(gboolean reload)
{
SCAN_START();
@@ -449,13 +595,32 @@ void scan_dmi(gboolean reload)
SCAN_END();
}
-void scan_spd(gboolean reload)
+void scan_dmi_mem(gboolean reload)
{
SCAN_START();
- scan_spd_do();
+ if (memory_devices_info)
+ g_free(memory_devices_info);
+ memory_devices_info = memory_devices_get_info();
+ SCAN_END();
+}
+
+void scan_monitors(gboolean reload)
+{
+ SCAN_START();
+ if (monitors_info)
+ g_free(monitors_info);
+ monitors_info = monitors_get_info();
+ SCAN_END();
+}
+
+void scan_firmware(gboolean reload)
+{
+ SCAN_START();
+ if (firmware_info)
+ g_free(firmware_info);
+ firmware_info = firmware_get_info();
SCAN_END();
}
-#endif
void scan_dtree(gboolean reload)
{
@@ -472,17 +637,17 @@ void scan_processors(gboolean reload)
SCAN_END();
}
-void scan_memory(gboolean reload)
+void scan_battery(gboolean reload)
{
SCAN_START();
- scan_memory_do();
+ scan_battery_do();
SCAN_END();
}
-void scan_battery(gboolean reload)
+void scan_gpu(gboolean reload)
{
SCAN_START();
- scan_battery_do();
+ scan_gpu_do();
SCAN_END();
}
@@ -512,9 +677,12 @@ void scan_storage(gboolean reload)
SCAN_START();
g_free(storage_list);
storage_list = g_strdup("");
-
- __scan_ide_devices();
- __scan_scsi_devices();
+ storage_no_nvme = FALSE;
+ if (!__scan_udisks2_devices()) {
+ storage_no_nvme = TRUE;
+ __scan_ide_devices();
+ __scan_scsi_devices();
+ }
SCAN_END();
}
@@ -537,17 +705,28 @@ gchar *callback_processors()
return processor_get_info(processors);
}
-#if defined(ARCH_x86) || defined(ARCH_x86_64)
gchar *callback_dmi()
{
- return g_strdup(dmi_info);
+ return g_strdup_printf("%s"
+ "[$ShellParam$]\n"
+ "ViewType=5\n",
+ dmi_info);
}
-gchar *callback_spd()
+gchar *callback_dmi_mem()
{
- return g_strdup(spd_info);
+ return g_strdup(memory_devices_info);
+}
+
+gchar *callback_monitors()
+{
+ return g_strdup(monitors_info);
+}
+
+gchar *callback_firmware()
+{
+ return g_strdup(firmware_info);
}
-#endif
gchar *callback_dtree()
{
@@ -556,41 +735,27 @@ gchar *callback_dtree()
"ViewType=1\n", dtree_info);
}
-gchar *callback_memory()
-{
- return g_strdup_printf("[Memory]\n"
- "%s\n"
- "[$ShellParam$]\n"
- "ViewType=2\n"
- "LoadGraphSuffix= kB\n"
- "RescanInterval=2000\n"
- "ColumnTitle$TextValue=%s\n"
- "ColumnTitle$Extra1=%s\n"
- "ColumnTitle$Value=%s\n"
- "ShowColumnHeaders=true\n"
- "%s\n", meminfo,
- _("Field"), _("Description"), _("Value"), /* column labels */
- lginterval);
-}
-
gchar *callback_battery()
{
return g_strdup_printf("%s\n"
"[$ShellParam$]\n"
+ "ViewType=5\n"
"ReloadInterval=4000\n", battery_list);
}
gchar *callback_pci()
{
- return g_strdup_printf("[PCI Devices]\n"
- "%s"
- "[$ShellParam$]\n" "ViewType=1\n", pci_list);
+ return g_strdup(pci_list);
+}
+
+gchar *callback_gpu()
+{
+ return g_strdup(gpu_list);
}
gchar *callback_sensors()
{
- return g_strdup_printf("[Sensors]\n"
- "%s\n"
+ return g_strdup_printf("%s\n"
"[$ShellParam$]\n"
"ViewType=2\n"
"LoadGraphSuffix=\n"
@@ -599,10 +764,13 @@ gchar *callback_sensors()
"ColumnTitle$Extra1=%s\n"
"ShowColumnHeaders=true\n"
"RescanInterval=5000\n"
+ "%s\n"
"%s",
sensors,
- _("Sensor"), _("Value"), _("Type"), /* column labels */
- lginterval);
+ _("Sensor"), _("Value"),
+ SENSORS_GROUP_BY_TYPE ? _("Driver"): _("Type"),
+ lginterval,
+ sensor_icons);
}
gchar *callback_printers()
@@ -617,27 +785,37 @@ gchar *callback_printers()
gchar *callback_storage()
{
return g_strdup_printf("%s\n"
- "[$ShellParam$]\n"
- "ReloadInterval=5000\n"
- "ViewType=1\n%s", storage_list, storage_icons);
+ "[$ShellParam$]\n"
+ "ReloadInterval=5000\n"
+ "ColumnTitle$TextValue=%s\n"
+ "ColumnTitle$Value=%s\n"
+ "ColumnTitle$Extra1=%s\n"
+ "ShowColumnHeaders=true\n"
+ "ViewType=1\n%s", storage_list, _("Device"), _("Size"), _("Model"), storage_icons);
}
gchar *callback_input()
{
return g_strdup_printf("[Input Devices]\n"
- "%s"
- "[$ShellParam$]\n"
- "ViewType=1\n"
- "ReloadInterval=5000\n%s", input_list,
- input_icons);
+ "%s"
+ "[$ShellParam$]\n"
+ "ViewType=1\n"
+ "ColumnTitle$TextValue=%s\n"
+ "ColumnTitle$Value=%s\n"
+ "ColumnTitle$Extra1=%s\n"
+ "ShowColumnHeaders=true\n"
+ "ReloadInterval=5000\n%s",
+ input_list, _("Device"), _("Vendor"), _("Type"),
+ input_icons);
}
gchar *callback_usb()
{
return g_strdup_printf("%s"
- "[$ShellParam$]\n"
- "ViewType=1\n"
- "ReloadInterval=5000\n", usb_list);
+ "[$ShellParam$]\n"
+ "ViewType=1\n"
+ "ReloadInterval=5000\n%s", usb_list, usb_icons);
+
}
ModuleEntry *hi_module_get_entries(void)
@@ -657,54 +835,68 @@ guchar hi_module_get_weight(void)
void hi_module_init(void)
{
- if (!g_file_test("/usr/share/misc/pci.ids", G_FILE_TEST_EXISTS)) {
- static SyncEntry se = {
- .fancy_name = N_("Update PCI ID listing"),
- .name = "GetPCIIds",
- .save_to = "pci.ids",
- .get_data = NULL
- };
-
- sync_manager_add_entry(&se);
- }
+ static SyncEntry entries[] = {
+ {
+ .name = N_("Update PCI ID listing"),
+ .file_name = "pci.ids",
+ },
+ {
+ .name = N_("Update USB ID listing"),
+ .file_name = "usb.ids",
+ },
+ {
+ .name = N_("Update EDID vendor codes"),
+ .file_name = "edid.ids",
+ },
+ {
+ .name = N_("Update IEEE OUI vendor codes"),
+ .file_name = "ieee_oui.ids",
+ },
+ {
+ .name = N_("Update SD card manufacturer information"),
+ .file_name = "sdcard.ids",
+ },
+#ifdef ARCH_x86
+ {
+ .name = N_("Update CPU flags database"),
+ .file_name = "cpuflags.json",
+ },
+#endif
+ };
+ guint i;
-#if defined(ARCH_x86) || defined(ARCH_x86_64)
- {
- static SyncEntry se = {
- .fancy_name = N_("Update CPU feature database"),
- .name = "RecvCPUFlags",
- .save_to = "cpuflags.conf",
- .get_data = NULL
- };
-
- sync_manager_add_entry(&se);
- }
-#endif /* defined(ARCH_x86) */
+ for (i = 0; i < G_N_ELEMENTS(entries); i++)
+ sync_manager_add_entry(&entries[i]);
- init_memory_labels();
init_cups();
- sensors_init();
+ sensor_init();
+ udisks2_init();
+
+#ifdef ARCH_x86
+ void cpuflags_x86_init(void);
+ cpuflags_x86_init();
+#endif
}
void hi_module_deinit(void)
{
moreinfo_del_with_prefix("DEV");
- sensors_shutdown();
- g_hash_table_destroy(memlabels);
- g_module_close(cups);
+ sensor_shutdown();
+ storage_shutdown();
+ udisks2_shutdown();
+ if(cups) g_module_close(cups);
}
-ModuleAbout *hi_module_get_about(void)
+const ModuleAbout *hi_module_get_about(void)
{
- static ModuleAbout ma[] = {
- {
- .author = "Leandro A. F. Pereira",
- .description = N_("Gathers information about hardware devices"),
- .version = VERSION,
- .license = "GNU GPL version 2"}
+ static const ModuleAbout ma = {
+ .author = "L. A. F. Pereira",
+ .description = N_("Gathers information about hardware devices"),
+ .version = VERSION,
+ .license = "GNU GPL version 2 or later.",
};
- return ma;
+ return &ma;
}
gchar **hi_module_get_dependencies(void)
@@ -716,10 +908,39 @@ gchar **hi_module_get_dependencies(void)
const gchar *hi_note_func(gint entry)
{
+ if (entry == ENTRY_PCI
+ || entry == ENTRY_GPU) {
+ const gchar *ids = find_pci_ids_file();
+ if (!ids) {
+ return g_strdup(_("A copy of <i><b>pci.ids</b></i> is not available on the system."));
+ }
+ if (ids && strstr(ids, ".min")) {
+ return g_strdup(_("A full <i><b>pci.ids</b></i> is not available on the system."));
+ }
+ }
if (entry == ENTRY_RESOURCES) {
if (root_required_for_resources()) {
return g_strdup(_("Resource information requires superuser privileges"));
}
}
+ else if (entry == ENTRY_STORAGE){
+ if (storage_no_nvme) {
+ return g_strdup(
+ _("Any NVMe storage devices present are not listed.\n"
+ "<b><i>udisksd</i></b> is required for NVMe devices."));
+ }
+ }
+ else if (entry == ENTRY_DMI_MEM){
+ const char *msg;
+ if (memory_devices_hinote(&msg)) {
+ return msg;
+ }
+ }
+ else if (entry == ENTRY_FW) {
+ const char *msg;
+ if (firmware_hinote(&msg)) {
+ return msg;
+ }
+ }
return NULL;
}
diff --git a/modules/devices/alpha/processor.c b/modules/devices/alpha/processor.c
index c7862232..0e625316 100644
--- a/modules/devices/alpha/processor.c
+++ b/modules/devices/alpha/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/arm/arm_data.c b/modules/devices/arm/arm_data.c
index 60e8ea34..aece272f 100644
--- a/modules/devices/arm/arm_data.c
+++ b/modules/devices/arm/arm_data.c
@@ -82,47 +82,6 @@ static struct {
};
static struct {
- int code; char *name;
-} tab_arm_implementer[] = {
- { 0x41, "ARM" },
- { 0x44, "Intel (formerly DEC) StrongARM" },
- { 0x4e, "nVidia" },
- { 0x54, "Texas Instruments" },
- { 0x56, "Marvell" },
- { 0x69, "Intel XScale" },
- { 0, NULL},
-};
-
-static struct {
- /* source: t = tested, d = official docs, f = web */
- int code; char *part_desc;
-} tab_arm_arm_part[] = { /* only valid for implementer 0x41 ARM */
- /*d */ { 0x920, "ARM920" },
- /*d */ { 0x926, "ARM926" },
- /*d */ { 0x946, "ARM946" },
- /*d */ { 0x966, "ARM966" },
- /*d */ { 0xb02, "ARM11 MPCore" },
- /*d */ { 0xb36, "ARM1136" },
- /*d */ { 0xb56, "ARM1156" },
- /*dt*/ { 0xb76, "ARM1176" },
- /*dt*/ { 0xc05, "Cortex-A5" },
- /*d */ { 0xc07, "Cortex-A7 MPCore" },
- /*dt*/ { 0xc08, "Cortex-A8" },
- /*dt*/ { 0xc09, "Cortex-A9" },
- /*d */ { 0xc0e, "Cortex-A17 MPCore" },
- /*d */ { 0xc0f, "Cortex-A15" },
- /*d */ { 0xd01, "Cortex-A32" },
- /*dt*/ { 0xd03, "Cortex-A53" },
- /*d */ { 0xd04, "Cortex-A35" },
- /*d */ { 0xd05, "Cortex-A55" },
- /*d */ { 0xd07, "Cortex-A57 MPCore" },
- /*d */ { 0xd08, "Cortex-A72" },
- /*d */ { 0xd09, "Cortex-A73" },
- /*d */ { 0xd0a, "Cortex-A75" },
- { 0, NULL},
-};
-
-static struct {
char *code; char *name; char *more;
} tab_arm_arch[] = {
{ "7", "AArch32", "AArch32 (ARMv7)" },
@@ -161,37 +120,47 @@ const char *arm_flag_meaning(const char *flag) {
return NULL;
}
-static int code_match(int c0, const char* code1) {
- int c1;
- if (code1 == NULL) return 0;
- c1 = strtol(code1, NULL, 0);
- return (c0 == c1) ? 1 : 0;
-}
-
-const char *arm_implementer(const char *code) {
- int i = 0;
- if (code)
- while(tab_arm_implementer[i].code) {
- if (code_match(tab_arm_implementer[i].code, code))
- return tab_arm_implementer[i].name;
- i++;
+#include "util_ids.h"
+
+gchar *arm_ids_file = NULL;
+
+void find_arm_ids_file() {
+ if (arm_ids_file) return;
+ char *file_search_order[] = {
+ g_build_filename(g_get_user_config_dir(), "hardinfo2", "arm.ids", NULL),
+ g_build_filename(params.path_data, "arm.ids", NULL),
+ NULL
+ };
+ int n;
+ for(n = 0; file_search_order[n]; n++) {
+ if (!arm_ids_file && !access(file_search_order[n], R_OK))
+ arm_ids_file = (gchar*) auto_free_on_exit( file_search_order[n] );
+ else
+ g_free(file_search_order[n]);
}
- return NULL;
}
-const char *arm_part(const char *imp_code, const char *part_code) {
- int i = 0;
- if (imp_code && part_code) {
- if (code_match(0x41, imp_code)) {
- /* 0x41=ARM parts */
- while(tab_arm_arm_part[i].code) {
- if (code_match(tab_arm_arm_part[i].code, part_code))
- return tab_arm_arm_part[i].part_desc;
- i++;
- }
- }
- }
- return NULL;
+void arm_part(const char *imp_code, const char *part_code, char **imp, char **part) {
+ gchar *qpath = NULL;
+ ids_query_result result = {};
+ unsigned int i,p;
+
+ if (!arm_ids_file)
+ find_arm_ids_file();
+
+ i = strtol(imp_code, NULL, 0);
+ p = strtol(part_code, NULL, 0);
+ qpath = g_strdup_printf("%02x/%03x", i, p);
+ scan_ids_file(arm_ids_file, qpath, &result, -1);
+ g_free(qpath);
+ if (imp)
+ *imp = result.results[0]
+ ? g_strdup(result.results[0])
+ : NULL;
+ if (part)
+ *part = result.results[1]
+ ? g_strdup(result.results[1])
+ : NULL;
}
const char *arm_arch(const char *cpuinfo_arch_str) {
@@ -229,8 +198,7 @@ char *arm_decoded_name(const char *imp, const char *part, const char *var, const
* variant and revision can be rendered r{variant}p{revision} */
r = strtol(var, NULL, 0);
p = strtol(rev, NULL, 0);
- imp_name = (char*) arm_implementer(imp);
- part_desc = (char*) arm_part(imp, part);
+ arm_part(imp, part, &imp_name, &part_desc);
arch_name = (char*) arm_arch(arch);
if (imp_name || part_desc) {
if (arch_name != arch)
@@ -251,6 +219,8 @@ char *arm_decoded_name(const char *imp, const char *part, const char *var, const
(part_desc) ? part_desc : part,
r, p, arch);
}
+ g_free(imp_name);
+ g_free(part_desc);
} else {
/* prolly not ARM arch at all */
if (model_name)
diff --git a/modules/devices/arm/arm_data.h b/modules/devices/arm/arm_data.h
index 63b3c906..0e93d323 100644
--- a/modules/devices/arm/arm_data.h
+++ b/modules/devices/arm/arm_data.h
@@ -22,13 +22,12 @@
#define _ARMDATA_H_
/* table lookups */
-const char *arm_implementer(const char *code);
-const char *arm_part(const char *imp_code, const char *part_code);
+void arm_part(const char *imp_code, const char *part_code, char **imp, char **part);
const char *arm_arch(const char *cpuinfo_arch_str);
const char *arm_arch_more(const char *cpuinfo_arch_str);
/* cpu_implementer, cpu_part, cpu_variant, cpu_revision, cpu_architecture from /proc/cpuinfo
- * model_name is returned as a fallback if not enough data is known */
+ * strdup(model_name) is returned as a fallback if not enough data is known */
char *arm_decoded_name(
const char *imp, const char *part, const char *var, const char *rev,
const char *arch, const char *model_name);
diff --git a/modules/devices/arm/processor.c b/modules/devices/arm/processor.c
index 3bee39f8..9446108d 100644
--- a/modules/devices/arm/processor.c
+++ b/modules/devices/arm/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -45,6 +45,7 @@ processor_scan(void)
gchar buffer[128];
gchar *rep_pname = NULL;
GSList *pi = NULL;
+ dtr *dt = dtr_new(NULL);
cpuinfo = fopen(PROC_CPUINFO, "r");
if (!cpuinfo)
@@ -162,6 +163,18 @@ processor_scan(void)
else
processor->cpu_mhz = 0.0f;
+ /* Try OPP, although if it exists, it should have been available
+ * via cpufreq. */
+ if (dt && processor->cpu_mhz == 0.0f) {
+ gchar *dt_cpu_path = g_strdup_printf("/cpus/cpu@%d", processor->id);
+ dt_opp_range *opp = dtr_get_opp_range(dt, dt_cpu_path);
+ if (opp) {
+ processor->cpu_mhz = (double)opp->khz_max / 1000;
+ g_free(opp);
+ }
+ g_free(dt_cpu_path);
+ }
+
/* mode */
processor->mode = ARM_A32;
if ( processor_has_flag(processor->flags, "pmull")
@@ -173,6 +186,7 @@ processor_scan(void)
#endif
}
}
+ dtr_free(dt);
return procs;
}
@@ -233,7 +247,7 @@ gchar *clocks_summary(GSList * processors)
/* create list of all clock references */
for (l = processors; l; l = l->next) {
p = (Processor*)l->data;
- if (p->cpufreq) {
+ if (p->cpufreq && p->cpufreq->cpukhz_max > 0) {
all_clocks = g_slist_prepend(all_clocks, p->cpufreq);
}
}
@@ -297,10 +311,10 @@ gchar *clocks_summary(GSList * processors)
gchar *
processor_get_detailed_info(Processor *processor)
{
- gchar *tmp_flags, *tmp_imp, *tmp_part, *tmp_arch, *tmp_cpufreq, *tmp_topology, *ret;
+ gchar *tmp_flags, *tmp_imp = NULL, *tmp_part = NULL,
+ *tmp_arch, *tmp_cpufreq, *tmp_topology, *ret;
tmp_flags = processor_get_capabilities_from_flags(processor->flags);
- tmp_imp = (char*)arm_implementer(processor->cpu_implementer);
- tmp_part = (char*)arm_part(processor->cpu_implementer, processor->cpu_part);
+ arm_part(processor->cpu_implementer, processor->cpu_part, &tmp_imp, &tmp_part);
tmp_arch = (char*)arm_arch_more(processor->cpu_architecture);
tmp_topology = cputopo_section_str(processor->cputopo);
@@ -361,9 +375,15 @@ gchar *processor_name(GSList *processors) {
char *vendor;
char *soc;
} dt_compat_searches[] = {
- { "brcm,bcm2837", "Broadcom", "BCM2837" },
- { "brcm,bcm2836", "Broadcom", "BCM2836" },
- { "brcm,bcm2835", "Broadcom", "BCM2835" },
+ { "brcm,bcm2838", "Broadcom", "BCM2838" }, // RPi 4
+ { "brcm,bcm2837", "Broadcom", "BCM2837" }, // RPi 3
+ { "brcm,bcm2836", "Broadcom", "BCM2836" }, // RPi 2
+ { "brcm,bcm2835", "Broadcom", "BCM2835" }, // RPi 1
+ { "rockchip,rk3288", "Rockchip", "RK3288" }, // Asus Tinkerboard
+ { "rockchip,rk3328", "Rockchip", "RK3328" }, // Firefly Renegade
+ { "rockchip,rk3399", "Rockchip", "RK3399" }, // Firefly Renegade Elite
+ { "rockchip,rk32", "Rockchip", "RK32xx-family" },
+ { "rockchip,rk33", "Rockchip", "RK33xx-family" },
{ "ti,omap5432", "Texas Instruments", "OMAP5432" },
{ "ti,omap5430", "Texas Instruments", "OMAP5430" },
{ "ti,omap4470", "Texas Instruments", "OMAP4470" },
@@ -395,13 +415,15 @@ gchar *processor_name(GSList *processors) {
{ "mediatek,mt6732", "MediaTek", "MT6732" },
{ "qcom,msm8939", "Qualcomm", "Snapdragon 615"},
{ "qcom,msm", "Qualcomm", "Snapdragon-family"},
- { "nvidia,tegra" "nVidia", "Tegra-family" },
- { "bcm,", "Broadcom", UNKSOC },
- { "nvidia," "nVidia", UNKSOC },
- { "rockchip," "Rockchip", UNKSOC },
+ { "nvidia,tegra", "nVidia", "Tegra-family" },
+ { "brcm,", "Broadcom", UNKSOC },
+ { "nvidia,", "nVidia", UNKSOC },
+ { "rockchip,", "Rockchip", UNKSOC },
{ "ti,", "Texas Instruments", UNKSOC },
{ "qcom,", "Qualcom", UNKSOC },
- { "mediatek," "MediaTek", UNKSOC },
+ { "mediatek,", "MediaTek", UNKSOC },
+ { "amlogic,", "Amlogic", UNKSOC },
+ { "allwinner,", "Allwinner", UNKSOC },
{ NULL, NULL }
};
gchar *ret = NULL;
@@ -464,7 +486,7 @@ gchar *processor_get_info(GSList * processors)
gchar *meta; /* becomes owned by more_info? no need to free? */
GSList *l;
- tmp = g_strdup_printf("$CPU_META$%s=\n", _("SOC/Package Information") );
+ tmp = g_strdup_printf("$!CPU_META$%s=\n", _("SOC/Package Information") );
meta = processor_meta(processors);
moreinfo_add_with_prefix("DEV", "CPU_META", meta);
diff --git a/modules/devices/battery.c b/modules/devices/battery.c
index cbcebb12..e356c14a 100644
--- a/modules/devices/battery.c
+++ b/modules/devices/battery.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -57,7 +57,7 @@ __scan_battery_apcupsd(void)
GHashTable *ups_data;
FILE *apcaccess;
char buffer[512], *apcaccess_path;
- int i;
+ guint i;
apcaccess_path = find_program("apcaccess");
if (apcaccess_path && (apcaccess = popen(apcaccess_path, "r"))) {
@@ -82,9 +82,9 @@ __scan_battery_apcupsd(void)
battery_list = h_strdup_cprintf("[%s]\n", battery_list, ups_fields[i].key);
} else {
/* there's a name: adds a line */
+ const gchar *name = g_hash_table_lookup(ups_data, ups_fields[i].key);
battery_list = h_strdup_cprintf("%s=%s\n", battery_list,
- ups_fields[i].name,
- g_hash_table_lookup(ups_data, ups_fields[i].key));
+ ups_fields[i].name, name);
}
}
@@ -165,12 +165,9 @@ __scan_battery_acpi(void)
fclose(f);
- const gchar *url = vendor_get_url(manufacturer);
- if (url) {
- char *tmp = g_strdup_printf("%s (%s)", vendor_get_name(manufacturer), url);
- g_free(manufacturer);
- manufacturer = tmp;
- }
+ gchar *tmp = vendor_get_link(manufacturer);
+ g_free(manufacturer);
+ manufacturer = tmp;
if (g_str_equal(present, "yes")) {
if (remaining && capacity)
@@ -229,11 +226,11 @@ read_contents(const gchar *base, const gchar *key)
return NULL;
if (!g_file_get_contents(path, &value, NULL, NULL)) {
- free(path);
+ g_free(path);
return NULL;
}
- free(path);
+ g_free(path);
return g_strchomp(value);
}
diff --git a/modules/devices/devicetree.c b/modules/devices/devicetree.c
index 4f3c85a2..7c798670 100644
--- a/modules/devices/devicetree.c
+++ b/modules/devices/devicetree.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,6 +28,10 @@
#include "devices.h"
#include "cpu_util.h"
#include "dt_util.h"
+#include "appf.h"
+
+gchar *dtree_info = NULL;
+const char *dtree_mem_str = NULL; /* used by memory devices when nothing else is available */
/* These should really go into CMakeLists.txt */
#if defined(__arm__)
@@ -36,8 +40,6 @@
#include "devicetree/pmac_data.c"
#endif
-gchar *dtree_info = NULL;
-
static gchar *get_node(dtr *dt, char *np) {
gchar *nodes = NULL, *props = NULL, *ret = NULL;
gchar *tmp = NULL, *pstr = NULL, *lstr = NULL;
@@ -216,13 +218,14 @@ static gchar *get_summary(dtr *dt) {
return ret;
}
-static void mi_add(const char *key, const char *value) {
+static void mi_add(const char *key, const char *value, int report_details) {
gchar *ckey, *rkey;
ckey = hardinfo_clean_label(key, 0);
rkey = g_strdup_printf("%s:%s", "DTREE", ckey);
- dtree_info = h_strdup_cprintf("$%s$%s=\n", dtree_info, rkey, ckey);
+ dtree_info = h_strdup_cprintf("$%s%s$%s=\n", dtree_info,
+ (report_details) ? "!" : "", rkey, ckey);
moreinfo_add_with_prefix("DEV", rkey, g_strdup(value));
g_free(ckey);
@@ -237,15 +240,14 @@ static void add_keys(dtr *dt, char *np) {
GDir *dir;
dtr_obj *obj;
- /* add self */
- obj = dtr_obj_read(dt, np);
- dt_path = dtr_obj_path(obj);
- n_info = get_node(dt, dt_path);
- mi_add(dt_path, n_info);
-
dir_path = g_strdup_printf("%s/%s", dtr_base_path(dt), np);
dir = g_dir_open(dir_path, 0 , NULL);
- if (dir) {
+ if(!dir){ /* add self */
+ obj = dtr_obj_read(dt, np);
+ dt_path = dtr_obj_path(obj);
+ n_info = get_node(dt, dt_path);
+ mi_add(dt_path, n_info, 0);
+ }else { //dir
while((fn = g_dir_read_name(dir)) != NULL) {
ftmp = g_strdup_printf("%s/%s", dir_path, fn);
if ( g_file_test(ftmp, G_FILE_TEST_IS_DIR) ) {
@@ -253,24 +255,25 @@ static void add_keys(dtr *dt, char *np) {
ntmp = g_strdup_printf("/%s", fn);
else
ntmp = g_strdup_printf("%s/%s", np, fn);
- add_keys(dt, ntmp);
+ if(strlen(ntmp)>0) add_keys(dt, ntmp);
g_free(ntmp);
}
g_free(ftmp);
}
+ g_dir_close(dir);
}
- g_dir_close(dir);
+ g_free(dir_path);
}
static char *msg_section(dtr *dt, int dump) {
gchar *aslbl = NULL;
gchar *messages = dtr_messages(dt);
- gchar *ret = g_strdup_printf("[%s]\n", _("Messages"));
+ gchar *ret = g_strdup_printf("[%s]", _("Messages"));
gchar **lines = g_strsplit(messages, "\n", 0);
int i = 0;
while(lines[i] != NULL) {
aslbl = hardinfo_clean_label(lines[i], 0);
- ret = appf(ret, "%s=\n", aslbl);
+ ret = appfnl(ret, "%s=", aslbl);
g_free(aslbl);
i++;
}
@@ -289,13 +292,13 @@ void __scan_dtree()
gchar *messages = NULL;
dtree_info = g_strdup("[Device Tree]\n");
- mi_add("Summary", summary);
- mi_add("Maps", maps);
+ mi_add("Summary", summary, 1);
+ mi_add("Maps", maps, 0);
if(dtr_was_found(dt))
add_keys(dt, "/");
messages = msg_section(dt, 0);
- mi_add("Messages", messages);
+ mi_add("Messages", messages, 0);
g_free(summary);
g_free(maps);
diff --git a/modules/devices/devicetree/pmac_data.c b/modules/devices/devicetree/pmac_data.c
index b236aef1..8c5471f0 100644
--- a/modules/devices/devicetree/pmac_data.c
+++ b/modules/devices/devicetree/pmac_data.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/devicetree/rpi_data.c b/modules/devices/devicetree/rpi_data.c
index d0132e3a..63daa7f3 100644
--- a/modules/devices/devicetree/rpi_data.c
+++ b/modules/devices/devicetree/rpi_data.c
@@ -1,12 +1,12 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
* This file from: rpiz - https://github.com/bp0/rpiz
* Copyright (C) 2017 Burt P. <pburt0@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,48 +21,57 @@
static char unk[] = "(Unknown)";
/* information table from: http://elinux.org/RPi_HardwareHistory */
-static struct {
+typedef struct {
char *value, *intro, *model, *pcb, *mem, *mfg, *soc;
-} rpi_boardinfo[] = {
+} RaspberryPiBoard;
+
+static const RaspberryPiBoard rpi_boardinfo[] = {
/* Value Introduction Model Name PCB rev. Memory(spec) Manufacturer SOC(spec) *
* Raspberry Pi %s */
{ unk, unk, unk, unk, unk, unk, NULL },
- { "Beta", "Q1 2012", "B (Beta)", unk, "256MB", "(Beta board)", NULL },
- { "0002", "Q1 2012", "B", "1.0", "256MB", unk, "BCM2835" },
- { "0003", "Q3 2012", "B (ECN0001)", "1.0", "256MB", "(Fuses mod and D14 removed)", NULL },
- { "0004", "Q3 2012", "B", "2.0", "256MB", "Sony", NULL },
- { "0005", "Q4 2012", "B", "2.0", "256MB", "Qisda", NULL },
- { "0006", "Q4 2012", "B", "2.0", "256MB", "Egoman", NULL },
- { "0007", "Q1 2013", "A", "2.0", "256MB", "Egoman", NULL },
- { "0008", "Q1 2013", "A", "2.0", "256MB", "Sony", NULL },
- { "0009", "Q1 2013", "A", "2.0", "256MB", "Qisda", NULL },
- { "000d", "Q4 2012", "B", "2.0", "512MB", "Egoman", NULL },
- { "000e", "Q4 2012", "B", "2.0", "512MB", "Sony", NULL },
- { "000f", "Q4 2012", "B", "2.0", "512MB", "Qisda", NULL },
- { "0010", "Q3 2014", "B+", "1.0", "512MB", "Sony", NULL },
- { "0011", "Q2 2014", "Compute Module 1", "1.0", "512MB", "Sony", NULL },
- { "0012", "Q4 2014", "A+", "1.1", "256MB", "Sony", NULL },
- { "0013", "Q1 2015", "B+", "1.2", "512MB", unk, NULL },
- { "0014", "Q2 2014", "Compute Module 1", "1.0", "512MB", "Embest", NULL },
- { "0015", unk, "A+", "1.1", "256MB/512MB", "Embest", NULL },
- { "a01040", unk, "2 Model B", "1.0", "1GB", "Sony", "BCM2836" },
- { "a01041", "Q1 2015", "2 Model B", "1.1", "1GB", "Sony", "BCM2836" },
- { "a21041", "Q1 2015", "2 Model B", "1.1", "1GB", "Embest", "BCM2836" },
- { "a22042", "Q3 2016", "2 Model B", "1.2", "1GB", "Embest", "BCM2837" }, /* (with BCM2837) */
- { "900021", "Q3 2016", "A+", "1.1", "512MB", "Sony", NULL },
- { "900032", "Q2 2016?", "B+", "1.2", "512MB", "Sony", NULL },
- { "900092", "Q4 2015", "Zero", "1.2", "512MB", "Sony", NULL },
- { "900093", "Q2 2016", "Zero", "1.3", "512MB", "Sony", NULL },
- { "920093", "Q4 2016?", "Zero", "1.3", "512MB", "Embest", NULL },
- { "9000c1", "Q1 2017", "Zero W", "1.1", "512MB", "Sony", NULL },
- { "a02082", "Q1 2016", "3 Model B", "1.2", "1GB", "Sony", "BCM2837" },
- { "a020a0", "Q1 2017", "Compute Module 3 or CM3 Lite", "1.0", "1GB", "Sony", NULL },
- { "a22082", "Q1 2016", "3 Model B", "1.2", "1GB", "Embest", "BCM2837" },
- { "a32082", "Q4 2016", "3 Model B", "1.2", "1GB", "Sony Japan", NULL },
+ { "Beta", "Q1 2012", "B (Beta)", unk, "256 MB", "(Beta board)", NULL },
+ { "0002", "Q1 2012", "B", "1.0", "256 MB", unk, "BCM2835" },
+ { "0003", "Q3 2012", "B (ECN0001)", "1.0", "256 MB", "(Fuses mod and D14 removed)", NULL },
+ { "0004", "Q3 2012", "B", "2.0", "256 MB", "Sony", NULL },
+ { "0005", "Q4 2012", "B", "2.0", "256 MB", "Qisda", NULL },
+ { "0006", "Q4 2012", "B", "2.0", "256 MB", "Egoman", NULL },
+ { "0007", "Q1 2013", "A", "2.0", "256 MB", "Egoman", NULL },
+ { "0008", "Q1 2013", "A", "2.0", "256 MB", "Sony", NULL },
+ { "0009", "Q1 2013", "A", "2.0", "256 MB", "Qisda", NULL },
+ { "000d", "Q4 2012", "B", "2.0", "512 MB", "Egoman", NULL },
+ { "000e", "Q4 2012", "B", "2.0", "512 MB", "Sony", NULL },
+ { "000f", "Q4 2012", "B", "2.0", "512 MB", "Qisda", NULL },
+ { "0010", "Q3 2014", "B+", "1.0", "512 MB", "Sony", NULL },
+ { "0011", "Q2 2014", "Compute Module 1", "1.0", "512 MB", "Sony", NULL },
+ { "0012", "Q4 2014", "A+", "1.1", "256 MB", "Sony", NULL },
+ { "0013", "Q1 2015", "B+", "1.2", "512 MB", unk, NULL },
+ { "0014", "Q2 2014", "Compute Module 1", "1.0", "512 MB", "Embest", NULL },
+ { "0015", unk, "A+", "1.1", "256 MB/512 MB", "Embest", NULL },
+ { "a01040", unk, "2 Model B", "1.0", "1024 MB DDR2", "Sony", "BCM2836" },
+ { "a01041", "Q1 2015", "2 Model B", "1.1", "1024 MB DDR2", "Sony", "BCM2836" },
+ { "a21041", "Q1 2015", "2 Model B", "1.1", "1024 MB DDR2", "Embest", "BCM2836" },
+ { "a22042", "Q3 2016", "2 Model B", "1.2", "1024 MB DDR2", "Embest", "BCM2837" }, /* (with BCM2837) */
+ { "900021", "Q3 2016", "A+", "1.1", "512 MB", "Sony", NULL },
+ { "900032", "Q2 2016?", "B+", "1.2", "512 MB", "Sony", NULL },
+ { "900092", "Q4 2015", "Zero", "1.2", "512 MB", "Sony", NULL },
+ { "900093", "Q2 2016", "Zero", "1.3", "512 MB", "Sony", NULL },
+ { "920093", "Q4 2016?", "Zero", "1.3", "512 MB", "Embest", NULL },
+ { "9000c1", "Q1 2017", "Zero W", "1.1", "512 MB", "Sony", NULL },
+ { "a02082", "Q1 2016", "3 Model B", "1.2", "1024 MB DDR2", "Sony", "BCM2837" },
+ { "a020a0", "Q1 2017", "Compute Module 3 or CM3 Lite", "1.0", "1024 MB DDR2", "Sony", NULL },
+ { "a22082", "Q1 2016", "3 Model B", "1.2", "1024 MB DDR2", "Embest", "BCM2837" },
+ { "a32082", "Q4 2016", "3 Model B", "1.2", "1024 MB DDR2", "Sony Japan", NULL },
+ { "a020d3", "Q1 2018", "3 Model B+", "1.3", "1024 MB DDR2", "Sony", "BCM2837" },
+ { "9020e0", "Q4 2018", "3 Model A+", "1.0", "512 MB DDR2", "Sony", "BCM2837" },
+
+ { "a03111", "Q2 2019", "4 Model B", "1.0", "1024 MB DDR4", "Sony", "BCM2838" },
+ { "b03111", "Q2 2019", "4 Model B", "1.0", "2048 MB DDR4", "Sony", "BCM2838" },
+ { "c03111", "Q2 2019", "4 Model B", "1.1", "4096 MB DDR4", "Sony", "BCM2838" },
+ { "c03114", "Q2 2020", "4 Model B", "1.4", "8192 MB DDR4", "Sony", "BCM2838" },
+
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
-
/* return number of chars to skip */
static int rpi_ov_check(const char *r_code) {
/* sources differ. prefix is either 1000... or just 1... */
@@ -154,7 +163,7 @@ static gchar *rpi_board_details(void) {
_("PCB Revision"), rpi_boardinfo[i].pcb,
_("Introduction"), rpi_boardinfo[i].intro,
_("Manufacturer"), rpi_boardinfo[i].mfg,
- _("RCode"), rpi_boardinfo[i].value,
+ _("RCode"), (rpi_boardinfo[i].value != unk) ? rpi_boardinfo[i].value : revision,
_("SOC (spec)"), rpi_boardinfo[i].soc,
_("Memory (spec)"), rpi_boardinfo[i].mem,
_("Serial Number"), serial,
@@ -162,5 +171,9 @@ static gchar *rpi_board_details(void) {
g_free(soc);
g_free(revision);
+
+ if (rpi_boardinfo[i].mem)
+ dtree_mem_str = rpi_boardinfo[i].mem;
+
return ret;
}
diff --git a/modules/devices/dmi.c b/modules/devices/dmi.c
index b25cfe21..34374fbe 100644
--- a/modules/devices/dmi.c
+++ b/modules/devices/dmi.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -30,26 +30,29 @@ struct _DMIInfo {
const gchar *name;
const gchar *id_str;
int group;
+ gboolean maybe_vendor;
};
DMIInfo dmi_info_table[] = {
{ N_("Product"), NULL, 1 },
{ N_("Name"), "system-product-name", 0 },
{ N_("Family"), "system-product-family", 0 },
- { N_("Vendor"), "system-manufacturer", 0 },
+ { N_("Vendor"), "system-manufacturer", 0, TRUE },
{ N_("Version"), "system-version", 0 },
+ { N_("Serial Number"), "system-serial-number", 0 },
+ { N_("SKU"), "system-sku", 0 },
{ N_("BIOS"), NULL, 1 },
{ N_("Date"), "bios-release-date", 0 },
- { N_("Vendor"), "bios-vendor", 0 },
+ { N_("Vendor"), "bios-vendor", 0, TRUE },
{ N_("Version"), "bios-version", 0 },
{ N_("Board"), NULL, 1 },
{ N_("Name"), "baseboard-product-name", 0 },
- { N_("Vendor"), "baseboard-manufacturer", 0 },
+ { N_("Vendor"), "baseboard-manufacturer", 0, TRUE },
{ N_("Version"), "baseboard-version", 0 },
{ N_("Serial Number"), "baseboard-serial-number", 0 },
{ N_("Asset Tag"), "baseboard-asset-tag", 0 },
{ N_("Chassis"), NULL, 1 },
- { N_("Vendor"), "chassis-manufacturer", 0 },
+ { N_("Vendor"), "chassis-manufacturer", 0, TRUE },
{ N_("Type"), "chassis-type", 0 },
{ N_("Version"), "chassis-version", 0 },
{ N_("Serial Number"), "chassis-serial-number", 0 },
@@ -64,77 +67,102 @@ static void add_to_moreinfo(const char *group, const char *key, char *value)
moreinfo_add_with_prefix("DEV", new_key, g_strdup(g_strstrip(value)));
}
-gboolean dmi_get_info()
+gboolean dmi_get_info(void)
{
- const gchar *group = NULL;
- DMIInfo *info;
- gboolean dmi_succeeded = FALSE;
- gint i;
- gchar *value;
-
- if (dmi_info) {
- g_free(dmi_info);
- dmi_info = NULL;
- }
+ const gchar *group = NULL;
+ DMIInfo *info;
+ gboolean dmi_succeeded = FALSE;
+ guint i;
+ gchar *value;
+ const gchar *vendor;
+
+ if (dmi_info) {
+ g_free(dmi_info);
+ dmi_info = NULL;
+ }
- for (i = 0; i < G_N_ELEMENTS(dmi_info_table); i++) {
- info = &dmi_info_table[i];
-
- if (info->group) {
- group = info->name;
- dmi_info = h_strdup_cprintf("[%s]\n", dmi_info, _(info->name) );
- } else if (group && info->id_str) {
- if (strcmp(info->id_str, "chassis-type") == 0)
- value = dmi_chassis_type_str(-1, 1);
- else
- value = dmi_get_str(info->id_str);
-
- if (value != NULL) {
- add_to_moreinfo(group, info->name, value);
-
- const gchar *url = vendor_get_url(value);
- if (url) {
- const gchar *vendor = vendor_get_name(value);
- dmi_info = h_strdup_cprintf("%s=%s (%s, %s)\n",
- dmi_info,
- _(info->name),
- value,
- vendor, url);
- } else {
- dmi_info = h_strdup_cprintf("%s=%s\n",
- dmi_info,
- _(info->name),
- value);
+ for (i = 0; i < G_N_ELEMENTS(dmi_info_table); i++) {
+ info = &dmi_info_table[i];
+
+ if (info->group) {
+ group = info->name;
+ dmi_info = h_strdup_cprintf("[%s]\n", dmi_info, _(info->name));
+ } else if (group && info->id_str) {
+ int state = 3;
+
+ if (strcmp(info->id_str, "chassis-type") == 0) {
+ value = dmi_chassis_type_str(-1, 1);
+ if (value == NULL)
+ state = (getuid() == 0) ? 0 : 1;
+ }
+ else {
+ switch (dmi_str_status(info->id_str)) {
+ case 0:
+ value = NULL;
+ state = (getuid() == 0) ? 0 : 1;
+ break;
+ case -1:
+ state = 2;
+ value = dmi_get_str_abs(info->id_str);
+ break;
+ case 1:
+ value = dmi_get_str_abs(info->id_str);
+ break;
+ }
+ }
+
+ switch (state) {
+ case 0: /* no value, root */
+ dmi_info = h_strdup_cprintf("%s=%s\n", dmi_info, _(info->name),
+ _("(Not available)"));
+ break;
+ case 1: /* no value, no root */
+ dmi_info = h_strdup_cprintf("%s=%s\n", dmi_info, _(info->name),
+ _("(Not available; Perhaps try "
+ "running HardInfo as root.)"));
+ break;
+ case 2: /* ignored value */
+ if (params.markup_ok)
+ dmi_info = h_strdup_cprintf("%s=<s>%s</s>\n", dmi_info,
+ _(info->name), value);
+ else
+ dmi_info = h_strdup_cprintf("%s=[X]\"%s\"\n", dmi_info,
+ _(info->name), value);
+ break;
+ case 3: /* good value */
+ {
+ dmi_info =
+ h_strdup_cprintf("%s%s=%s\n", dmi_info,
+ info->maybe_vendor ? "$^$" : "",
+ _(info->name), value);
+ add_to_moreinfo(group, info->name, value);
+ dmi_succeeded = TRUE;
+ break;
+ }
+ }
}
- dmi_succeeded = TRUE;
- } else {
- dmi_info = h_strdup_cprintf("%s=%s\n",
- dmi_info,
- _(info->name),
- (getuid() == 0)
- ? _("(Not available)")
- : _("(Not available; Perhaps try running HardInfo as root.)") );
- }
}
- }
- if (!dmi_succeeded) {
- g_free(dmi_info);
- dmi_info = NULL;
- }
+ if (!dmi_succeeded) {
+ g_free(dmi_info);
+ dmi_info = NULL;
+ }
- return dmi_succeeded;
+ return dmi_succeeded;
}
-void __scan_dmi()
+void __scan_dmi(void)
{
gboolean dmi_ok;
dmi_ok = dmi_get_info();
if (!dmi_ok) {
- dmi_info = g_strdup("[No DMI information]\n"
- "There was an error retrieving the information.=\n"
- "Please try running HardInfo as root.=\n");
+ dmi_info = g_strdup_printf("[%s]\n%s=\n",
+ _("DMI Unavailable"),
+ (getuid() == 0)
+ ? _("DMI is not avaliable. Perhaps this platform does not provide DMI.")
+ : _("DMI is not available; Perhaps try running HardInfo as root.") );
+
}
}
diff --git a/modules/devices/dmi_memory.c b/modules/devices/dmi_memory.c
new file mode 100644
index 00000000..eba26c8b
--- /dev/null
+++ b/modules/devices/dmi_memory.c
@@ -0,0 +1,1050 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2019 L. A. F. Pereira <l@tia.mat.br>
+ * Copyright (C) 2019 Burt P. <pburt0@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _GNU_SOURCE
+
+#include "hardinfo.h"
+#include "devices.h"
+#include "vendor.h"
+#include <inttypes.h>
+
+extern const char *dtree_mem_str; /* in devicetree.c */
+
+/* in monitors.c */
+gchar **get_output_lines(const char *cmd_line);
+
+#include "util_sysobj.h" /* for appfsp() */
+#define dmi_spd_msg(...) /* fprintf (stderr, __VA_ARGS__) */
+
+typedef uint64_t dmi_mem_size;
+
+#include "spd-decode.c"
+
+gboolean no_handles = FALSE;
+gboolean sketchy_info = FALSE;
+
+int dmi_ram_types = 0; /* bits using enum RamType */
+
+/* strings from dmidecode */
+static const char empty_mem_str[] = "No Module Installed";
+static const char unknown_mfgr_str[] = "<BAD INDEX>";
+static const char mobo_location[] = "System Board Or Motherboard";
+static const char mobo_shorter[] = "Mainboard";
+static const dmi_type dta = 16; /* array */
+static const dmi_type dtm = 17; /* socket */
+static const char mem_icon[] = "memory.png";
+static const char array_icon[] = "devices.png";
+static const char empty_icon[] = "module.png";
+
+#define UNKNOWN_MEM_TYPE_STRING _("RAM")
+#define UNKIFNULL2(f) ((f) ? f : _("(Unknown)"))
+#define UNKIFEMPTY2(f) ((*f) ? f : _("(Unknown)"))
+#define STR_IGNORE(str, ignore) if (SEQ(str, ignore)) { *str = 0; null_if_empty(&str); }
+
+dmi_mem_size dmi_read_memory_str_to_MiB(const char *memstr) {
+ dmi_mem_size ret = 0, v = 0;
+ char l[7] = "";
+ /* dmidecode units: "bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB" */
+ int mc = sscanf(memstr, "%"PRId64" %6s", &v, l);
+ if (mc == 2) {
+ if (SEQ(l, "ZB")) ret = v * 1024 * 1024 * 1024 * 1024 * 1024;
+ else if (SEQ(l, "EB")) ret = v * 1024 * 1024 * 1024 * 1024;
+ else if (SEQ(l, "PB")) ret = v * 1024 * 1024 * 1024;
+ else if (SEQ(l, "TB")) ret = v * 1024 * 1024;
+ else if (SEQ(l, "GB")) ret = v * 1024;
+ else if (SEQ(l, "MB")) ret = v;
+ else if (SEQ(l, "kB")) {
+ /* should never appear */
+ if (v % 1024) { dmi_spd_msg("OMG kB!"); }
+ ret = v / 1024;
+ }
+ else if (SEQ(l, "bytes")) {
+ /* should never appear */
+ if (v % 1024) { dmi_spd_msg("OMG bytes!"); }
+ ret = v / (1024 * 1024);
+ }
+ }
+ return ret;
+}
+
+typedef struct {
+ dmi_handle array_handle;
+ gboolean is_main_memory;
+ gchar *locator;
+ gchar *use;
+ gchar *ecc;
+ int devs;
+ int devs_populated;
+ dmi_mem_size size_MiB_max;
+ dmi_mem_size size_MiB_present;
+ dmi_mem_size size_MiB_rom;
+ int ram_types; /* bits using enum RamType */
+} dmi_mem_array;
+
+dmi_mem_array *dmi_mem_array_new(dmi_handle h) {
+ dmi_mem_array *s = g_new0(dmi_mem_array, 1);
+ s->array_handle = h;
+ s->use = dmidecode_match("Use", &dta, &h);
+ if (SEQ(s->use, "System Memory"))
+ s->is_main_memory = TRUE;
+ s->ecc = dmidecode_match("Error Correction Type", &dta, &h);
+ s->locator = dmidecode_match("Location", &dta, &h);
+ if (SEQ(s->locator, mobo_location)) {
+ g_free(s->locator);
+ s->locator = g_strdup(mobo_shorter);
+ s->is_main_memory = TRUE;
+ }
+
+ gchar *array_max_size = dmidecode_match("Maximum Capacity", &dta, &h);
+ if (array_max_size) {
+ s->size_MiB_max = dmi_read_memory_str_to_MiB(array_max_size);
+ g_free(array_max_size);
+ }
+ gchar *array_devs = dmidecode_match("Number Of Devices", &dta, &h);
+ if (array_devs) {
+ s->devs = strtol(array_devs, NULL, 10);
+ g_free(array_devs);
+ }
+ return s;
+}
+
+void dmi_mem_array_free(dmi_mem_array* s) {
+ if (s) {
+ g_free(s->locator);
+ g_free(s->use);
+ g_free(s->ecc);
+ g_free(s);
+ }
+}
+
+typedef struct dmi_mem_socket {
+ dmi_handle handle;
+ dmi_handle array_handle;
+ gboolean populated;
+ gchar *locator;
+ gchar *full_locator;
+ gchar *short_locator;
+ gchar *size_str;
+ dmi_mem_size size_MiB;
+
+ gboolean is_not_ram; /* maybe is_rom, maybe elsewise, but don't include in RAM total */
+ gboolean is_rom;
+
+ gchar *type;
+ gchar *type_detail;
+ int ram_type; /* using enum RamType */
+ gchar *array_locator;
+ gchar *bank_locator;
+ gchar *rank;
+ gchar *form_factor;
+ gchar *speed_str;
+ gchar *configured_clock_str;
+ gchar *voltage_min_str;
+ gchar *voltage_max_str;
+ gchar *voltage_conf_str;
+ gchar *partno;
+ gchar *data_width;
+ gchar *total_width;
+ gchar *mfgr;
+ gboolean has_jedec_mfg_id;
+ int mfgr_bank, mfgr_index;
+
+ const Vendor *vendor;
+ spd_data *spd;
+} dmi_mem_socket;
+
+typedef struct {
+ gboolean empty;
+ GSList *arrays;
+ GSList *sockets;
+ GSList *spd;
+ dmi_mem_size spd_size_MiB;
+ int spd_ram_types; /* bits using enum RamType */
+
+ dmi_mem_size system_memory_MiB;
+ int system_memory_ram_types; /* bits using enum RamType */
+
+ /* ->short_locator is unique among *sockets */
+ gboolean unique_short_locators;
+} 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(dmi_handle h) {
+ dmi_mem_socket *s = g_new0(dmi_mem_socket, 1);
+ s->handle = h;
+ s->locator = dmidecode_match("Locator", &dtm, &h);
+ s->size_str = dmidecode_match("Size", &dtm, &h);
+ if (s->size_str)
+ s->size_MiB = dmi_read_memory_str_to_MiB(s->size_str);
+
+ s->bank_locator = dmidecode_match("Bank Locator", &dtm, &h);
+ STR_IGNORE(s->bank_locator, "Unknown");
+ STR_IGNORE(s->bank_locator, "Not Specified");
+ null_if_empty(&s->bank_locator);
+
+ gchar *ah = dmidecode_match("Array Handle", &dtm, &h);
+ STR_IGNORE(ah, "Unknown");
+ if (ah) {
+ s->array_handle = strtol(ah, NULL, 16);
+ g_free(ah);
+ s->array_locator = dmidecode_match("Location", &dta, &s->array_handle);
+ if (SEQ(s->array_locator, mobo_location)) {
+ g_free(s->array_locator);
+ s->array_locator = g_strdup(mobo_shorter);
+ }
+ }
+
+ gchar *ah_str = g_strdup_printf("0x%"PRIx32, s->array_handle);
+ gchar *h_str = g_strdup_printf("0x%"PRIx32, s->handle);
+ s->short_locator = g_strdup_printf("%s \u27A4 %s",
+ s->array_locator ? s->array_locator : ah_str,
+ s->locator ? s->locator : h_str);
+
+ if (s->bank_locator)
+ s->full_locator = g_strdup_printf("%s \u27A4 %s \u27A4 %s",
+ s->array_locator ? s->array_locator : ah_str,
+ s->bank_locator,
+ s->locator ? s->locator : h_str);
+ else
+ s->full_locator = g_strdup(s->short_locator);
+
+ g_free(ah_str);
+ g_free(h_str);
+
+ if (!g_str_has_prefix(s->size_str, empty_mem_str)) {
+ s->populated = 1;
+
+ s->form_factor = dmidecode_match("Form Factor", &dtm, &h);
+ s->type = dmidecode_match("Type", &dtm, &h);
+ STR_IGNORE(s->type, "Unknown");
+ if (SEQ(s->type, "Flash") || SEQ(s->type, "ROM")) {
+ s->is_rom = TRUE;
+ s->is_not_ram = TRUE;
+ } else {
+ if (SEQ(s->type, "DDR")) s->ram_type = DDR_SDRAM;
+ if (SEQ(s->type, "DDR2")) s->ram_type = DDR2_SDRAM;
+ if (SEQ(s->type, "DDR3")) s->ram_type = DDR3_SDRAM;
+ if (SEQ(s->type, "DDR4")) s->ram_type = DDR4_SDRAM;
+ if (SEQ(s->type, "DRDRAM")) s->ram_type = DIRECT_RAMBUS;
+ if (SEQ(s->type, "RDRAM")) s->ram_type = RAMBUS;
+ if (s->ram_type)
+ dmi_ram_types |= (1 << (s->ram_type-1));
+ }
+ 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);
+ STR_IGNORE(s->partno, "PartNum0");
+ STR_IGNORE(s->partno, "PartNum1");
+ STR_IGNORE(s->partno, "PartNum2");
+ STR_IGNORE(s->partno, "PartNum3");
+ null_if_empty(&s->partno);
+
+ s->data_width = dmidecode_match("Data Width", &dtm, &h);
+ s->total_width = dmidecode_match("Total Width", &dtm, &h);
+
+ s->rank = dmidecode_match("Rank", &dtm, &h);
+
+ s->mfgr = dmidecode_match("Manufacturer", &dtm, &h);
+ STR_IGNORE(s->mfgr, unknown_mfgr_str);
+ STR_IGNORE(s->mfgr, "Manufacturer0");
+ STR_IGNORE(s->mfgr, "Manufacturer1");
+ STR_IGNORE(s->mfgr, "Manufacturer2");
+ STR_IGNORE(s->mfgr, "Manufacturer3");
+ STR_IGNORE(s->mfgr, "Unknown");
+ null_if_empty(&s->mfgr);
+
+ gchar *mfgr_id_str = dmidecode_match("Module Manufacturer ID", &dtm, &h);
+ STR_IGNORE(mfgr_id_str, "Unknown");
+ if (mfgr_id_str) {
+ static const char dmi_mfg_id_fmt[] = "Bank %d, Hex 0x%02X"; /* from dmidecode.c */
+ int mc = sscanf(strstr(mfgr_id_str, "Bank"), dmi_mfg_id_fmt, &s->mfgr_bank, &s->mfgr_index);
+ if (mc > 0 && !s->mfgr) {
+ s->has_jedec_mfg_id = TRUE;
+ s->mfgr = g_strdup(JEDEC_MFG_STR(s->mfgr_bank, s->mfgr_index));
+ }
+ }
+
+ if (s->mfgr && !s->has_jedec_mfg_id && strlen(s->mfgr) == 4) {
+ /* Some BIOS put the code bytes into the mfgr string
+ * if they don't know the manufacturer.
+ * It's not always reliable, but what is lost
+ * by trying it? */
+ if (isxdigit(s->mfgr[0])
+ && isxdigit(s->mfgr[1])
+ && isxdigit(s->mfgr[2])
+ && isxdigit(s->mfgr[3]) ) {
+ int codes = strtol(s->mfgr, NULL, 16);
+ char *mstr = NULL;
+ decode_ddr34_manufacturer(codes >> 8, codes & 0xff,
+ &mstr, &s->mfgr_bank, &s->mfgr_index);
+ s->has_jedec_mfg_id = TRUE;
+ g_free(s->mfgr);
+ s->mfgr = NULL;
+ if (mstr)
+ s->mfgr = g_strdup(mstr);
+ }
+ }
+
+ s->vendor = vendor_match(s->mfgr, NULL);
+ }
+ return s;
+}
+
+void dmi_mem_socket_free(dmi_mem_socket* s) {
+ if (s) {
+ g_free(s->locator);
+ g_free(s->full_locator);
+ g_free(s->short_locator);
+ g_free(s->size_str);
+ g_free(s->type);
+ g_free(s->type_detail);
+ g_free(s->bank_locator);
+ g_free(s->rank);
+ g_free(s->array_locator);
+ g_free(s->form_factor);
+ g_free(s->speed_str);
+ g_free(s->configured_clock_str);
+ g_free(s->voltage_min_str);
+ g_free(s->voltage_max_str);
+ g_free(s->voltage_conf_str);
+ g_free(s->partno);
+ g_free(s->data_width);
+ g_free(s->total_width);
+ g_free(s->mfgr);
+
+ g_free(s);
+ }
+}
+
+dmi_mem_array *dmi_mem_find_array(dmi_mem *s, unsigned int handle) {
+ GSList *l = NULL;
+ for(l = s->arrays; l; l = l->next) {
+ dmi_mem_array *a = (dmi_mem_array*)l->data;
+ if (a->array_handle == handle)
+ return a;
+ }
+ return NULL;
+}
+
+static int dmi_spd_match_score(dmi_mem_socket *s, spd_data *e) {
+ int score = 0;
+ if (SEQ(s->partno, e->partno))
+ score += 20;
+ if (s->size_MiB == e->size_MiB)
+ score += 10;
+ if (s->vendor == e->vendor)
+ score += 5;
+ return score;
+}
+
+/* fill in missing from SPD */
+static void dmi_fill_from_spd(dmi_mem_socket *s) {
+ if (!s->spd)
+ return;
+
+ if (!s->mfgr && s->spd->vendor_str) {
+ s->mfgr = g_strdup(s->spd->vendor_str);
+ s->vendor = s->spd->vendor;
+ }
+ if (!s->has_jedec_mfg_id) {
+ s->mfgr_bank = s->spd->vendor_bank;
+ s->mfgr_index = s->spd->vendor_index;
+ s->has_jedec_mfg_id = TRUE;
+ }
+
+ //Always true - FIXME
+ //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);
+
+ //Always true - FIXME
+ //if (!s->type_detail && s->spd->type_detail)
+ s->type_detail = g_strdup(s->spd->type_detail);
+}
+
+static dmi_mem_size size_of_online_memory_blocks() {
+ gchar *block_size_bytes_str = NULL;
+ dmi_mem_size block_size_bytes = 0;
+ dmi_mem_size ret = 0;
+
+ if (g_file_get_contents("/sys/devices/system/memory/block_size_bytes", &block_size_bytes_str, NULL, NULL) ) {
+ block_size_bytes = strtoll(block_size_bytes_str, NULL, 16);
+ }
+ if (!block_size_bytes)
+ return 0;
+
+ const gchar *f = NULL;
+ GDir *d = g_dir_open("/sys/devices/system/memory", 0, NULL);
+ if (!d) return 0;
+
+ while((f = g_dir_read_name(d))) {
+ gchar *p = g_strdup_printf("/sys/devices/system/memory/%s/online", f);
+ gchar *ol = NULL;
+ if (g_file_get_contents(p, &ol, NULL, NULL) ) {
+ if (1 == strtol(ol, NULL, 0)) {
+ ret += block_size_bytes;
+ }
+ }
+ g_free(ol);
+ g_free(p);
+ }
+ g_dir_close(d);
+ return ret;
+}
+
+dmi_mem *dmi_mem_new() {
+ dmi_mem *m = g_new0(dmi_mem, 1);
+
+ dmi_handle_list *hla = dmidecode_handles(&dta);
+ if (hla) {
+ unsigned int i = 0;
+ for(i = 0; i < hla->count; i++) {
+ dmi_handle h = hla->handles[i];
+ m->arrays = g_slist_append(m->arrays, dmi_mem_array_new(h));
+ }
+ dmi_handle_list_free(hla);
+ }
+
+ dmi_handle_list *hlm = dmidecode_handles(&dtm);
+ if (hlm) {
+ unsigned int i = 0;
+ for(i = 0; i < hlm->count; i++) {
+ dmi_handle h = hlm->handles[i];
+ m->sockets = g_slist_append(m->sockets, dmi_mem_socket_new(h));
+ }
+ dmi_handle_list_free(hlm);
+ }
+
+ m->spd = spd_scan();
+
+ if (!m->sockets && !m->arrays && !m->spd) {
+ m->empty = 1;
+ goto dmi_mem_new_last_chance;
+ }
+
+ GSList *l = NULL, *l2 = NULL;
+
+ /* totals for SPD */
+ for(l2 = m->spd; l2; l2 = l2->next) {
+ spd_data *e = (spd_data*)l2->data;
+ m->spd_size_MiB += e->size_MiB;
+ if (e->type)
+ m->spd_ram_types |= (1 << (e->type-1));
+ }
+
+ m->unique_short_locators = TRUE;
+ for(l = m->sockets; l; l = l->next) {
+ dmi_mem_socket *s = (dmi_mem_socket*)l->data;
+
+ /* check for duplicate short_locator */
+ if (m->unique_short_locators) {
+ for(l2 = l->next; l2; l2 = l2->next) {
+ dmi_mem_socket *d = (dmi_mem_socket*)l2->data;
+ if (SEQ(s->short_locator, d->short_locator)) {
+ m->unique_short_locators = FALSE;
+ break;
+ }
+ }
+ }
+
+ /* update array present devices/size */
+ dmi_mem_array *a = dmi_mem_find_array(m, s->array_handle);
+ if (a) {
+ if (s->is_not_ram) {
+ if (s->is_rom)
+ a->size_MiB_rom += s->size_MiB;
+ } else {
+ a->size_MiB_present += s->size_MiB;
+ if (s->populated)
+ a->devs_populated++;
+ if (s->ram_type)
+ a->ram_types |= (1 << (s->ram_type-1));
+ }
+ }
+ }
+
+ if (m->sockets && m->spd) {
+ /* attempt to match DMI and SPD data */
+ GSList *sock_queue = g_slist_copy(m->sockets);
+ int loops = g_slist_length(sock_queue) * 4;
+ while(sock_queue) {
+ if (loops-- <= 0) break; /* something is wrong, give up */
+ spd_data *best = NULL;
+ int best_score = 0;
+ dmi_mem_socket *s = (dmi_mem_socket*)sock_queue->data;
+ /* pop that one off */
+ sock_queue = g_slist_delete_link(sock_queue, sock_queue);
+ if (!s->populated)
+ continue;
+ for(l2 = m->spd; l2; l2 = l2->next) {
+ spd_data *e = (spd_data*)l2->data;
+ int score = dmi_spd_match_score(s, e);
+ if (score > best_score) {
+ if (score > e->match_score) {
+ best = e;
+ best_score = score;
+ }
+ }
+ }
+ if (best) {
+ if (best->dmi_socket) {
+ /* displace */
+ dmi_mem_socket *old_sock = best->dmi_socket;
+ old_sock->spd = NULL;
+ sock_queue = g_slist_append(sock_queue, old_sock);
+
+ best->dmi_socket = s;
+ best->match_score = best_score;
+ s->spd = best;
+ } else {
+ best->dmi_socket = s;
+ best->match_score = best_score;
+ s->spd = best;
+ }
+ }
+ }
+
+ /* fill any missing data in DMI that is
+ * provided by the matched SPD */
+ for(l = m->sockets; l; l = l->next) {
+ dmi_mem_socket *s = (dmi_mem_socket*)l->data;
+ dmi_fill_from_spd(s);
+ }
+
+ } /* end if (m->sockets && m->spd) */
+
+ /* Look for arrays with "System Memory" use,
+ * or Mainboard as locator */
+ for(l = m->arrays; l; l = l->next) {
+ dmi_mem_array *a = (dmi_mem_array*)l->data;
+ if (a->is_main_memory) {
+ m->system_memory_MiB += a->size_MiB_present;
+ m->system_memory_ram_types |= a->ram_types;
+ }
+ }
+
+ /* If no arrays, then try the SPD total */
+ if (!m->system_memory_MiB) {
+ m->system_memory_MiB = m->spd_size_MiB;
+ m->system_memory_ram_types |= m->spd_ram_types;
+ }
+
+dmi_mem_new_last_chance:
+ if (m->empty) {
+ /* reach */
+ if (dtree_mem_str) {
+ int rt = 0;
+ m->system_memory_MiB = dmi_read_memory_str_to_MiB(dtree_mem_str);
+ if (strstr(dtree_mem_str, "DDR4")) rt = DDR4_SDRAM;
+ else if (strstr(dtree_mem_str, "DDR3")) rt = DDR3_SDRAM;
+ else if (strstr(dtree_mem_str, "DDR2")) rt = DDR2_SDRAM;
+ else if (strstr(dtree_mem_str, "DDR")) rt = DDR_SDRAM;
+ else if (strstr(dtree_mem_str, "DRDRAM")) rt = DIRECT_RAMBUS;
+ else if (strstr(dtree_mem_str, "RDRAM")) rt = RAMBUS;
+ if (rt)
+ m->system_memory_ram_types |= (1 << (rt-1));
+ }
+ }
+
+ /* Try to sum the online blocks for a physical memory total */
+ if (!m->system_memory_MiB)
+ m->system_memory_MiB = size_of_online_memory_blocks() / 1024 / 1024;
+
+ return m;
+}
+
+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 *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 *size_str = NULL;
+ if (!spd->size_MiB)
+ size_str = g_strdup(_("(Unknown)"));
+ else
+ size_str = g_strdup_printf("%"PRId64" %s", spd->size_MiB, _("MiB") );
+
+ gchar *mfg_date_str = NULL;
+ if (spd->year)
+ mfg_date_str = g_strdup_printf("%d / %d", spd->week, spd->year);
+
+ ret = g_strdup_printf("[%s]\n"
+ "%s=%s (%s)%s\n"
+ "%s=%d.%d\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "$^$%s=[%02x%02x] %s\n" /* module vendor */
+ "$^$%s=[%02x%02x] %s\n" /* dram vendor */
+ "%s=%s\n" /* part */
+ "%s=%s\n" /* size */
+ "%s=%s\n" /* mfg date */
+ "%s",
+ _("Serial Presence Detect (SPD)"),
+ _("Source"), spd->dev, spd->spd_driver,
+ (spd->type == DDR4_SDRAM && strcmp(spd->spd_driver, "ee1004") != 0) ? problem_marker() : "",
+ _("SPD Revision"), spd->spd_rev_major, spd->spd_rev_minor,
+ _("Form Factor"), UNKIFNULL2(spd->form_factor),
+ _("Type"), UNKIFEMPTY2(spd->type_detail),
+ _("Module Vendor"), spd->vendor_bank, spd->vendor_index,
+ UNKIFNULL2(spd->vendor_str),
+ _("DRAM Vendor"), spd->dram_vendor_bank, spd->dram_vendor_index,
+ UNKIFNULL2(spd->dram_vendor_str),
+ _("Part Number"), UNKIFEMPTY2(spd->partno),
+ _("Size"), size_str,
+ _("Manufacturing Date (Week / Year)"), UNKIFNULL2(mfg_date_str),
+ full_spd ? full_spd : ""
+ );
+ g_free(full_spd);
+ g_free(size_str);
+ g_free(mfg_date_str);
+ }
+ return ret;
+}
+
+static gchar *tag_make_safe_inplace(gchar *tag) {
+ if (!tag)
+ return tag;
+ if (!g_utf8_validate(tag, -1, NULL))
+ return tag; //TODO: reconsider
+ gchar *p = tag, *pd = tag;
+ while(*p) {
+ gchar *np = g_utf8_next_char(p);
+ gunichar c = g_utf8_get_char_validated(p, -1);
+ int l = g_unichar_to_utf8(c, NULL);
+ if (l == 1 && g_unichar_isalnum(c)) {
+ g_unichar_to_utf8(c, pd);
+ } else {
+ *pd = '_';
+ }
+ p = np;
+ pd++;
+ }
+ return tag;
+}
+
+gchar *memory_devices_get_info() {
+ gchar *icons = g_strdup("");
+ gchar *ret = g_strdup_printf("[%s]\n", _("Memory Device List"));
+ GSList *l = NULL;
+ sketchy_info = FALSE;
+ gchar tag_prefix[] = "DEV";
+
+ 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 *tag = g_strdup_printf("%s", a->locator);
+ gchar *size_str = NULL, *rom_size_str = NULL;
+
+ tag_make_safe_inplace(tag);
+
+ 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"));
+ 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());
+ }
+
+ if (a->size_MiB_rom > 1024 && (a->size_MiB_rom % 1024 == 0))
+ rom_size_str = g_strdup_printf("%"PRId64" %s", a->size_MiB_rom / 1024, _("GiB"));
+ else
+ rom_size_str = g_strdup_printf("%"PRId64" %s", a->size_MiB_rom, _("MiB"));
+
+ gchar *types_str = NULL;
+ int i;
+ for(i = 1; i < N_RAM_TYPES; i++) {
+ int bit = 1 << (i-1);
+ if (a->ram_types & bit)
+ types_str = appfsp(types_str, "%s", GET_RAM_TYPE_STR(i));
+ }
+
+ gchar *details = g_strdup_printf("[%s]\n"
+ "%s=0x%"PRIx32"\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%d / %d\n"
+ "%s=[0x%x] %s\n"
+ "%s=%s\n",
+ _("Memory Array"),
+ _("DMI Handle"), a->array_handle,
+ _("Locator"), a->locator ? a->locator : ".",
+ _("Use"), UNKIFNULL2(a->use),
+ _("Error Correction Type"), UNKIFNULL2(a->ecc),
+ _("Size (Present / Max)"), size_str,
+ _("Devices (Populated / Sockets)"), a->devs_populated, a->devs,
+ _("Types Present"), a->ram_types, UNKIFNULL2(types_str),
+ _("ROM Size"), rom_size_str
+ );
+ moreinfo_add_with_prefix(tag_prefix, tag, details); /* moreinfo now owns *details */
+ ret = h_strdup_cprintf("$!%s$%s=%s|%s\n",
+ ret,
+ tag, a->locator, UNKIFNULL2(types_str), size_str
+ );
+ icons = h_strdup_cprintf("Icon$%s$=%s\n", icons, tag, array_icon);
+ g_free(tag);
+ g_free(size_str);
+ g_free(rom_size_str);
+ g_free(types_str);
+ }
+
+ /* Sockets */
+ for(l = mem->sockets; l; l = l->next) {
+ dmi_mem_socket *s = (dmi_mem_socket*)l->data;
+ gchar *tag = g_strdup_printf("%s", s->full_locator);
+ tag_make_safe_inplace(tag);
+
+ if (s->populated) {
+ 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("%"PRId64" %s", s->size_MiB, _("MiB") );
+
+ gchar *spd = s->spd ? make_spd_section(s->spd) : NULL;
+
+ gchar *details = g_strdup_printf("[%s]\n"
+ "%s=0x%"PRIx32", 0x%"PRIx32"\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s / %s\n"
+ "$^$%s=[%02x%02x] %s\n"
+ "%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),
+ _("Type"), UNKIFNULL2(s->type), UNKIFNULL2(s->type_detail),
+ _("Vendor"),
+ s->mfgr_bank, s->mfgr_index, UNKIFNULL2(s->mfgr),
+ _("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),
+ _("Rank"), UNKIFNULL2(s->rank),
+ _("Minimum Voltage"), UNKIFNULL2(s->voltage_min_str),
+ _("Maximum Voltage"), UNKIFNULL2(s->voltage_max_str),
+ _("Configured Voltage"), UNKIFNULL2(s->voltage_conf_str),
+ spd ? spd : ""
+ );
+ g_free(spd);
+ moreinfo_add_with_prefix(tag_prefix, tag, details); /* moreinfo now owns *details */
+ gchar *mfgr = s->mfgr ? vendor_match_tag(s->mfgr, params.fmt_opts) : NULL;
+ ret = h_strdup_cprintf("$!%s$%s=%s|%s|%s\n",
+ ret,
+ tag,
+ mem->unique_short_locators ? s->short_locator : s->full_locator,
+ UNKIFNULL2(s->partno), size_str, UNKIFNULL2(mfgr)
+ );
+ icons = h_strdup_cprintf("Icon$%s$=%s\n", icons, tag, mem_icon);
+ g_free(size_str);
+ g_free(mfgr);
+ } else {
+ gchar *details = g_strdup_printf("[%s]\n"
+ "%s=0x%"PRIx32", 0x%"PRIx32"\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n",
+ _("Memory Socket"),
+ _("DMI Handles (Array, Socket)"), s->array_handle, s->handle,
+ _("Locator"), s->full_locator,
+ _("Bank Locator"), UNKIFNULL2(s->bank_locator),
+ _("Size"), _("(Empty)")
+ );
+ moreinfo_add_with_prefix(tag_prefix, tag, details); /* moreinfo now owns *details */
+ ret = h_strdup_cprintf("$%s$%s=|%s\n",
+ ret,
+ tag,
+ mem->unique_short_locators ? s->short_locator : s->full_locator,
+ _("(Empty)")
+ );
+ icons = h_strdup_cprintf("Icon$%s$=%s\n", icons, tag, empty_icon);
+ }
+ g_free(tag);
+ }
+
+ /* No DMI Array, show SPD totals */
+ if (!mem->arrays && mem->spd) {
+ gchar *key = g_strdup("SPD:*");
+ gchar *tag = g_strdup(key);
+ tag_make_safe_inplace(tag);
+ gchar *types_str = NULL;
+ gchar *size_str = NULL;
+
+ if (mem->spd_size_MiB > 1024 && (mem->spd_size_MiB % 1024 == 0) )
+ size_str = g_strdup_printf("%"PRId64" %s", mem->spd_size_MiB / 1024, _("GiB"));
+ else
+ size_str = g_strdup_printf("%"PRId64" %s", mem->spd_size_MiB, _("MiB"));
+
+ int i;
+ for(i = 1; i < N_RAM_TYPES; i++) {
+ int bit = 1 << (i-1);
+ if (mem->spd_ram_types & bit)
+ types_str = appfsp(types_str, "%s", GET_RAM_TYPE_STR(i));
+ }
+
+ gchar *details = g_strdup_printf("[%s]\n"
+ "%s=%s\n"
+ "%s=%d\n"
+ "%s=[0x%x] %s\n",
+ _("Serial Presence Detect (SPD) Summary"),
+ _("Size"), size_str,
+ _("Devices"), g_slist_length(mem->spd),
+ _("Types Present"), mem->spd_ram_types, UNKIFNULL2(types_str)
+ );
+ moreinfo_add_with_prefix(tag_prefix, tag, details); /* moreinfo now owns *details */
+ ret = h_strdup_cprintf("$!%s$%s=%s|%s\n",
+ ret,
+ tag, key, UNKIFNULL2(types_str), size_str
+ );
+ icons = h_strdup_cprintf("Icon$%s$=%s\n", icons, tag, array_icon);
+ g_free(key);
+ g_free(tag);
+ g_free(size_str);
+ g_free(types_str);
+ }
+
+ /* Unmatched SPD */
+ for(l = mem->spd; l; l = l->next) {
+ spd_data *s = (spd_data*)l->data;
+ if (s->dmi_socket) continue; /* claimed by DMI */
+ gchar *key = g_strdup_printf("SPD:%s", s->dev);
+ gchar *tag = g_strdup(key);
+ tag_make_safe_inplace(tag);
+
+ gchar *vendor_str = NULL;
+ if (s->vendor) {
+ vendor_str = vendor_get_link_from_vendor(s->vendor);
+ }
+ gchar *size_str = NULL;
+ if (!s->size_MiB)
+ size_str = g_strdup(_("(Unknown)"));
+ else
+ size_str = g_strdup_printf("%"PRId64" %s", s->size_MiB, _("MiB") );
+
+ gchar *details = make_spd_section(s);
+
+ moreinfo_add_with_prefix(tag_prefix, tag, 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,
+ tag, key, problem_marker(), UNKIFEMPTY2(s->partno), size_str, UNKIFNULL2(mfgr)
+ );
+ icons = h_strdup_cprintf("Icon$%s$=%s\n", icons, tag, mem_icon);
+ g_free(vendor_str);
+ g_free(size_str);
+ g_free(key);
+ g_free(tag);
+ }
+
+ no_handles = FALSE;
+ if(mem->empty) {
+ no_handles = TRUE;
+ g_free(ret);
+ ret = g_strdup_printf("[%s]\n%s=%s\n" "[$ShellParam$]\nViewType=0\n",
+ _("Memory Device List"), _("Result"),
+ (getuid() == 0)
+ ? _("(Not available)")
+ : _("(Not available; Perhaps try running HardInfo as root.)") );
+ } else {
+ ret = h_strdup_cprintf(
+ "[$ShellParam$]\nViewType=1\n"
+ "ColumnTitle$TextValue=%s\n" /* Locator */
+ "ColumnTitle$Extra1=%s\n" /* Size */
+ "ColumnTitle$Extra2=%s\n" /* Vendor */
+ "ColumnTitle$Value=%s\n" /* Part */
+ "ShowColumnHeaders=true\n"
+ "%s",
+ ret,
+ _("Locator"),
+ _("Size"),
+ _("Vendor"),
+ _("Part"),
+ icons
+ );
+ }
+
+ g_free(icons);
+ dmi_mem_free(mem);
+ return ret;
+}
+
+gchar *memory_devices_get_system_memory_types_str() {
+ gchar *ret = NULL, *types_str = NULL;
+ int i, rtypes;
+
+ dmi_mem *lmem = dmi_mem_new();
+ rtypes = lmem->system_memory_ram_types;
+ dmi_mem_free(lmem);
+
+ for(i = 1; i < N_RAM_TYPES; i++) {
+ int bit = 1 << (i-1);
+ if (rtypes & bit)
+ types_str = appfsp(types_str, "%s", GET_RAM_TYPE_STR(i));
+ }
+
+ if (types_str)
+ ret = g_strdup(types_str);
+ else
+ ret = g_strdup(UNKNOWN_MEM_TYPE_STRING);
+ g_free(types_str);
+ return ret;
+}
+
+uint64_t memory_devices_get_system_memory_MiB() {
+ dmi_mem *mem = dmi_mem_new();
+ int ret = (int)mem->system_memory_MiB;
+ dmi_mem_free(mem);
+ return ret;
+}
+
+gchar *memory_devices_get_system_memory_str() {
+ gchar *ret = NULL;
+ dmi_mem_size m = memory_devices_get_system_memory_MiB();
+ if (m) {
+ if (m > 1024 && (m % 1024 == 0) )
+ ret = g_strdup_printf("%"PRId64" %s", m/1024, _("GiB"));
+ else
+ ret = g_strdup_printf("%"PRId64" %s", m, _("MiB"));
+ }
+ return ret;
+}
+
+static gchar note_state[note_max_len] = "";
+
+gboolean memory_devices_hinote(const char **msg) {
+ gchar *want_dmi = _(" <b><i>dmidecode</i></b> utility available");
+ gchar *want_root = _(" ... <i>and</i> HardInfo running with superuser privileges");
+ gchar *want_at24 = _(" <b><i>at24</i></b> (or eeprom) module loaded (for SDR, DDR, DDR2, DDR3)");
+ 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_at24eep = g_file_test("/sys/bus/i2c/drivers/at24", G_FILE_TEST_IS_DIR) ||
+ 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);
+
+ *note_state = 0; /* clear */
+ note_printf(note_state, "%s\n", _("Memory information requires <b>one or both</b> of the following:"));
+ note_print(note_state, "<tt>1. </tt>");
+ note_cond_bullet(has_dmi, note_state, want_dmi);
+ note_print(note_state, "<tt> </tt>");
+ note_cond_bullet(has_root, note_state, want_root);
+ note_print(note_state, "<tt>2. </tt>");
+ note_cond_bullet(has_at24eep, note_state, want_at24);
+ note_print(note_state, "<tt> </tt>");
+ note_cond_bullet(has_ee1004, note_state, want_ee1004);
+ g_strstrip(note_state); /* remove last \n */
+
+ gboolean ddr3_ee1004 = ((dmi_ram_types & (1<<(DDR3_SDRAM-1))) && has_ee1004);
+
+ gboolean best_state = FALSE;
+ if (has_dmi && has_root &&
+ ((has_at24eep && !spd_ddr4_partial_data)
+ || (has_ee1004 && !ddr3_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/e2k/processor.c b/modules/devices/e2k/processor.c
new file mode 100644
index 00000000..74476853
--- /dev/null
+++ b/modules/devices/e2k/processor.c
@@ -0,0 +1,420 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2020 EntityFX <artem.solopiy@gmail.com> and MCST Elbrus Team
+ * modified by Boris Afonot <boris.afonot@gmail.com> (2022)
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hardinfo.h"
+#include "devices.h"
+#include "cpu_util.h"
+
+static gchar *__cache_get_info_as_string(Processor *processor)
+{
+ gchar *result = g_strdup("");
+ GSList *cache_list;
+ ProcessorCache *cache;
+
+ if (!processor->cache) {
+ return g_strdup(_("Cache information not available=\n"));
+ }
+
+ for (cache_list = processor->cache; cache_list; cache_list = cache_list->next) {
+ cache = (ProcessorCache *)cache_list->data;
+
+ result = h_strdup_cprintf(_("Level %d (%s)=%d-way set-associative, %d sets, %dKB size\n"),
+ result,
+ cache->level,
+ C_("cache-type", cache->type),
+ cache->ways_of_associativity,
+ cache->number_of_sets,
+ cache->size);
+ }
+
+ return result;
+}
+
+/* This is not used directly, but creates translatable strings for
+ * the type string returned from /sys/.../cache */
+static const char* cache_types[] = {
+ NC_("cache-type", /*/cache type, as appears in: Level 1 (Data)*/ "Data"),
+ NC_("cache-type", /*/cache type, as appears in: Level 1 (Instruction)*/ "Instruction"),
+ NC_("cache-type", /*/cache type, as appears in: Level 2 (Unified)*/ "Unified")
+};
+
+static void __cache_obtain_info(Processor *processor)
+{
+ ProcessorCache *cache;
+ gchar *endpoint, *entry, *index;
+ gchar *uref = NULL;
+ gint i;
+ gint processor_number = processor->id;
+
+ endpoint = g_strdup_printf("/sys/devices/system/cpu/cpu%d/cache", processor_number);
+
+ for (i = 0; ; i++) {
+ cache = g_new0(ProcessorCache, 1);
+
+ index = g_strdup_printf("index%d/", i);
+
+ entry = g_strconcat(index, "type", NULL);
+ cache->type = h_sysfs_read_string(endpoint, entry);
+ g_free(entry);
+
+ if (!cache->type) {
+ g_free(cache);
+ g_free(index);
+ goto fail;
+ }
+
+ entry = g_strconcat(index, "level", NULL);
+ cache->level = h_sysfs_read_int(endpoint, entry);
+ g_free(entry);
+
+ entry = g_strconcat(index, "number_of_sets", NULL);
+ cache->number_of_sets = h_sysfs_read_int(endpoint, entry);
+ g_free(entry);
+
+ entry = g_strconcat(index, "physical_line_partition", NULL);
+ cache->physical_line_partition = h_sysfs_read_int(endpoint, entry);
+ g_free(entry);
+
+ entry = g_strconcat(index, "size", NULL);
+ cache->size = h_sysfs_read_int(endpoint, entry);
+ g_free(entry);
+
+ entry = g_strconcat(index, "ways_of_associativity", NULL);
+ cache->ways_of_associativity = h_sysfs_read_int(endpoint, entry);
+ g_free(entry);
+
+ /* unique cache references: id is nice, but share_cpu_list can be
+ * used if it is not available. */
+ entry = g_strconcat(index, "id", NULL);
+ uref = h_sysfs_read_string(endpoint, entry);
+ g_free(entry);
+ if (uref != NULL && *uref != 0 )
+ cache->uid = atoi(uref);
+ else
+ cache->uid = -1;
+ g_free(uref);
+ entry = g_strconcat(index, "shared_cpu_list", NULL);
+ cache->shared_cpu_list = h_sysfs_read_string(endpoint, entry);
+ g_free(entry);
+
+ /* reacharound */
+ entry = g_strconcat(index, "../../topology/physical_package_id", NULL);
+ cache->phy_sock = h_sysfs_read_int(endpoint, entry);
+ g_free(entry);
+
+ g_free(index);
+
+ processor->cache = g_slist_append(processor->cache, cache);
+ }
+
+fail:
+ g_free(endpoint);
+}
+
+#define cmp_cache_test(f) if (a->f < b->f) return -1; if (a->f > b->f) return 1;
+
+static gint cmp_cache(ProcessorCache *a, ProcessorCache *b) {
+ gint i = 0;
+ cmp_cache_test(phy_sock);
+ i = g_strcmp0(a->type, b->type); if (i!=0) return i;
+ cmp_cache_test(level);
+ cmp_cache_test(size);
+ cmp_cache_test(uid); /* uid is unique among caches with the same (type, level) */
+ if (a->uid == -1) {
+ /* if id wasn't available, use shared_cpu_list as a unique ref */
+ i = g_strcmp0(a->shared_cpu_list, b->shared_cpu_list); if (i!=0)
+ return i;
+ }
+ return 0;
+}
+
+static gint cmp_cache_ignore_id(ProcessorCache *a, ProcessorCache *b) {
+ gint i = 0;
+ cmp_cache_test(phy_sock);
+ i = g_strcmp0(a->type, b->type); if (i!=0) return i;
+ cmp_cache_test(level);
+ cmp_cache_test(size);
+ return 0;
+}
+
+gchar *caches_summary(GSList * processors)
+{
+ gchar *ret = g_strdup_printf("[%s]\n", _("Caches"));
+ GSList *all_cache = NULL, *uniq_cache = NULL;
+ GSList *tmp, *l;
+ Processor *p;
+ ProcessorCache *c, *cur = NULL;
+ gint cur_count = 0, i = 0;
+
+ /* create list of all cache references */
+ for (l = processors; l; l = l->next) {
+ p = (Processor*)l->data;
+ if (p->cache) {
+ tmp = g_slist_copy(p->cache);
+ if (all_cache) {
+ all_cache = g_slist_concat(all_cache, tmp);
+ } else {
+ all_cache = tmp;
+ }
+ }
+ }
+
+ if (g_slist_length(all_cache) == 0) {
+ ret = h_strdup_cprintf("%s=\n", ret, _("(Not Available)") );
+ g_slist_free(all_cache);
+ return ret;
+ }
+
+ /* ignore duplicate references */
+ all_cache = g_slist_sort(all_cache, (GCompareFunc)cmp_cache);
+ for (l = all_cache; l; l = l->next) {
+ c = (ProcessorCache*)l->data;
+ if (!cur) {
+ cur = c;
+ } else {
+ if (cmp_cache(cur, c) != 0) {
+ uniq_cache = g_slist_prepend(uniq_cache, cur);
+ cur = c;
+ }
+ }
+ }
+ uniq_cache = g_slist_prepend(uniq_cache, cur);
+ uniq_cache = g_slist_reverse(uniq_cache);
+ cur = 0, cur_count = 0;
+
+ /* count and list caches */
+ for (l = uniq_cache; l; l = l->next) {
+ c = (ProcessorCache*)l->data;
+ if (!cur) {
+ cur = c;
+ cur_count = 1;
+ } else {
+ if (cmp_cache_ignore_id(cur, c) != 0) {
+ ret = h_strdup_cprintf(_("Level %d (%s)#%d=%dx %dKB (%dKB), %d-way set-associative, %d sets\n"),
+ ret,
+ cur->level,
+ C_("cache-type", cur->type),
+ cur->phy_sock,
+ cur_count,
+ cur->size,
+ cur->size * cur_count,
+ cur->ways_of_associativity,
+ cur->number_of_sets);
+ cur = c;
+ cur_count = 1;
+ } else {
+ cur_count++;
+ }
+ }
+ }
+ ret = h_strdup_cprintf(_("Level %d (%s)#%d=%dx %dKB (%dKB), %d-way set-associative, %d sets\n"),
+ ret,
+ cur->level,
+ C_("cache-type", cur->type),
+ cur->phy_sock,
+ cur_count,
+ cur->size,
+ cur->size * cur_count,
+ cur->ways_of_associativity,
+ cur->number_of_sets);
+
+ g_slist_free(all_cache);
+ g_slist_free(uniq_cache);
+ return ret;
+}
+
+static gchar *processor_get_full_name(const gchar *model_name)
+{
+ if(g_strcmp0(model_name ,"E2S") == 0)
+ return "Elbrus-4C";
+ else if(g_strcmp0(model_name ,"E1C+") == 0)
+ return "Elbrus-1C+";
+ else if(g_strcmp0(model_name ,"E2C+DSP") == 0)
+ return "Elbrus-2C+";
+ else if(g_strcmp0(model_name ,"E8C") == 0)
+ return "Elbrus-8C";
+ else if(g_strcmp0(model_name ,"E8C2") == 0)
+ return "Elbrus-8CB";
+ else if(g_strcmp0(model_name ,"E12C") == 0)
+ return "Elbrus-12C";
+ else if(g_strcmp0(model_name ,"E16C") == 0)
+ return "Elbrus-16C";
+ else if(g_strcmp0(model_name ,"E2C3") == 0)
+ return "Elbrus-2C3";
+ else
+ return (gchar *)model_name;
+}
+
+GSList *processor_scan(void)
+{
+ GSList *procs = NULL, *l = NULL;
+ Processor *processor = NULL;
+ FILE *cpuinfo;
+ gchar buffer[1024];
+
+ cpuinfo = fopen(PROC_CPUINFO, "r");
+ if (!cpuinfo)
+ return NULL;
+
+ while (fgets(buffer, 1024, cpuinfo)) {
+ gchar **tmp = g_strsplit(buffer, ":", 2);
+ if (!tmp[1] || !tmp[0]) {
+ g_strfreev(tmp);
+ continue;
+ }
+
+ tmp[0] = g_strstrip(tmp[0]);
+ tmp[1] = g_strstrip(tmp[1]);
+
+ if (g_str_has_prefix(tmp[0], "processor")) {
+ /* finish previous */
+ if (processor)
+ procs = g_slist_append(procs, processor);
+
+ /* start next */
+ processor = g_new0(Processor, 1);
+ processor->id = atol(tmp[1]);
+ g_strfreev(tmp);
+ continue;
+ }
+
+ if (processor) {
+ if (g_str_has_prefix(tmp[0], "model name")) {
+ const gchar *model_name = processor_get_full_name(tmp[1]);
+ processor->model_name = g_strdup(model_name);
+ g_strfreev(tmp);
+ continue;
+ }
+
+ get_str("vendor_id", processor->vendor_id);
+ get_int("cpu family", processor->family);
+ get_int("model", processor->model);
+ get_int("revision", processor->revision);
+
+ get_float("cpu MHz", processor->cpu_mhz);
+ get_float("bogomips", processor->bogomips);
+ }
+
+ //populate processor structure
+ g_strfreev(tmp);
+ }
+
+ //appent to the list
+ if (processor)
+ procs = g_slist_append(procs, processor);
+
+ for (l = procs; l; l = l->next) {
+ processor = (Processor *) l->data;
+ __cache_obtain_info(processor);
+ }
+
+ fclose(cpuinfo);
+
+ return procs;
+}
+
+gchar *processor_name(GSList * processors) {
+ return processor_name_default(processors);
+}
+
+gchar *processor_describe(GSList * processors) {
+ return processor_describe_default(processors);
+}
+
+gchar *
+processor_get_detailed_info(Processor *processor)
+{
+ gchar *ret;
+ gchar *cache_info;
+ cache_info = __cache_get_info_as_string(processor);
+
+ ret = g_strdup_printf("[%s]\n"
+ "$^$%s=%s\n" /* name */
+ "$^$%s=%s\n" /* vendor */
+ "%s=%d\n" /* family */
+ "%s=%d\n" /* model */
+ "%s=%d\n" /* revision */
+ "%s=%.2f %s\n" /* frequency */
+ "%s=%.2f\n" /* bogomips */
+ "%s=%s\n" /* byte order */
+ "[%s]\n" /* cache */
+ "%s\n",
+ _("Processor"),
+ _("Name"), processor->model_name,
+ _("Vendor"), processor->vendor_id,
+ _("Family"), processor->family,
+ _("Model"), processor->model,
+ _("Revision"), processor->revision,
+ _("Frequency"), processor->cpu_mhz, _("MHz"),
+ _("BogoMips"), processor->bogomips,
+ _("Byte Order"), byte_order_str(),
+ _("Cache"), cache_info
+ );
+ g_free(cache_info);
+ return ret;
+}
+
+//prepare processor info for all cpus
+gchar *processor_get_info(GSList * processors)
+{
+ Processor *processor;
+
+ gchar *ret, *tmp, *hashkey;
+ GSList *l;
+
+ tmp = g_strdup("");
+
+ for (l = processors; l; l = l->next) {
+ processor = (Processor *) l->data;
+ gchar *model_name = g_strdup_printf("MCST %s", processor->model_name);
+
+ /* change vendor id of 8CB processor for correct parse from vendor.ids */
+ if (!g_strcmp0(processor->vendor_id, "E8C")) {
+ gchar *orig_vendor_id = processor->vendor_id;
+ processor->vendor_id = g_strdup_printf("%s-SWTX", orig_vendor_id);
+ free(orig_vendor_id);
+ }
+
+ const Vendor *v = vendor_match(processor->vendor_id, NULL);
+ if (v)
+ tag_vendor(&model_name, 0, v->name_short ? v->name_short : v->name, v->ansi_color, params.fmt_opts);
+
+ tmp = g_strdup_printf("%s$CPU%d$cpu%d=%.2f %s|%s\n",
+ tmp, processor->id,
+ processor->id,
+ processor->cpu_mhz, _("MHz"),
+ model_name);
+
+ hashkey = g_strdup_printf("CPU%d", processor->id);
+ moreinfo_add_with_prefix("DEV", hashkey,
+ processor_get_detailed_info(processor));
+ g_free(hashkey);
+ }
+
+ ret = g_strdup_printf("[$ShellParam$]\n"
+ "ViewType=1\n"
+ "ColumnTitle$TextValue=%s\n"
+ "ColumnTitle$Value=%s\n"
+ "ColumnTitle$Extra1=%s\n"
+ "ShowColumnHeaders=true\n"
+ "[Processors]\n"
+ "%s", _("Device"), _("Frequency"), _("Model"), tmp);
+ g_free(tmp);
+
+ return ret;
+}
diff --git a/modules/devices/firmware.c b/modules/devices/firmware.c
new file mode 100644
index 00000000..ea6ce532
--- /dev/null
+++ b/modules/devices/firmware.c
@@ -0,0 +1,261 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2019 L. A. F. Pereira <l@tia.mat.br>
+ * Copyright (C) 2019 Burt P. <pburt0@gmail.com>
+ * Copyright (C) 2020 Ondrej Čerman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hardinfo.h"
+#include "devices.h"
+#include <inttypes.h>
+#include <gio/gio.h>
+#include "util_sysobj.h" /* for SEQ() and appf() */
+
+#define fw_msg(msg, ...) fprintf (stderr, "[%s] " msg "\n", __FUNCTION__, ##__VA_ARGS__) /**/
+
+#define FWUPT_INTERFACE "org.freedesktop.fwupd"
+
+gboolean fail_no_fwupd = TRUE;
+
+char *decode_flags(guint64 flags) {
+ /* https://github.com/hughsie/fwupd/blob/master/libfwupd/fwupd-enums.{h,c} */
+ static const struct { guint64 b; char *flag, *def; } flag_defs[] = {
+ { (1u << 0), "internal", N_("Device cannot be removed easily") },
+ { (1u << 1), "updatable", N_("Device is updatable in this or any other mode") },
+ { (1u << 2), "only-offline", N_("Update can only be done from offline mode") },
+ { (1u << 3), "require-ac", N_("Requires AC power") },
+ { (1u << 4), "locked", N_("Is locked and can be unlocked") },
+ { (1u << 5), "supported", N_("Is found in current metadata") },
+ { (1u << 6), "needs-bootloader", N_("Requires a bootloader mode to be manually enabled by the user") },
+ { (1u << 7), "registered", N_("Has been registered with other plugins") },
+ { (1u << 8), "needs-reboot", N_("Requires a reboot to apply firmware or to reload hardware") },
+ { (1u << 17), "needs-shutdown", N_("Requires system shutdown to apply firmware") },
+ { (1u << 9), "reported", N_("Has been reported to a metadata server") },
+ { (1u << 10), "notified", N_("User has been notified") },
+ { (1u << 11), "use-runtime-version", N_("Always use the runtime version rather than the bootloader") },
+ { (1u << 12), "install-parent-first", N_("Install composite firmware on the parent before the child") },
+ { (1u << 13), "is-bootloader", N_("Is currently in bootloader mode") },
+ { (1u << 14), "wait-for-replug", N_("The hardware is waiting to be replugged") },
+ { (1u << 15), "ignore-validation", N_("Ignore validation safety checks when flashing this device") },
+ { (1u << 18), "another-write-required", N_("Requires the update to be retried with a new plugin") },
+ { (1u << 19), "no-auto-instance-ids", N_("Do not add instance IDs from the device baseclass") },
+ { (1u << 20), "needs-activation", N_("Device update needs to be separately activated") },
+ { (1u << 21), "ensure-semver", N_("Ensure the version is a valid semantic version, e.g. numbers separated with dots") },
+ { (1u << 16), "trusted", N_("Extra metadata can be exposed about this device") },
+ { 0, NULL }
+ };
+
+ gchar *flag_list = g_strdup("");
+
+ int i;
+ for (i = 0; flag_defs[i].flag; i++) {
+ if (flags & flag_defs[i].b)
+ flag_list = appfnl(flag_list, "[%s] %s", flag_defs[i].flag, flag_defs[i].def);
+ }
+ return flag_list;
+}
+
+const char *find_translation(const char *str) {
+ /* TODO: https://github.com/hughsie/fwupd/blob/master/src/README.md */
+ static const char *translatable[] = {
+ N_("DeviceId"), N_("Guid"), N_("Summary"), N_("Plugin"), N_("Flags"),
+ N_("Vendor"), N_("VendorId"), N_("Version"), N_("VersionBootloader"),
+ N_("Icon"), N_("InstallDuration"), N_("Created"),
+ NULL
+ };
+ int i;
+ if (!str) return NULL;
+ for (i = 0; translatable[i]; i++) {
+ if (SEQ(str, translatable[i]))
+ return _(translatable[i]);
+ }
+ return str;
+};
+
+/* map lvfs icon names to hardinfo icon names */
+const char *find_icon(const char *lvfs_name) {
+ /* icon names found by looking for fu_device_add_icon ()
+ * in the fwupd source. */
+ static const
+ struct { char *lvfs, *hi; } imap[] = {
+ { "applications-internet", "dns.png" },
+ { "audio-card", "audio.png" },
+ { "computer", "computer.png" },
+ { "drive-harddisk", "hdd.png" },
+ { "input-gaming", "joystick.png" },
+ { "input-tablet", NULL },
+ { "network-modem", "wireless.png" },
+ { "preferences-desktop-keyboard", "keyboard.png" },
+ { "thunderbolt", NULL },
+ { "touchpad-disabled", NULL },
+ /* default */
+ { NULL, "memory.png" } /* a device with firmware maybe */
+ };
+ unsigned int i = 0;
+ for(; imap[i].lvfs; i++) {
+ if (SEQ(imap[i].lvfs, lvfs_name) && imap[i].hi)
+ return imap[i].hi;
+ }
+ return imap[i].hi;
+}
+
+gchar *fwupdmgr_get_devices_info() {
+ struct Info *info = info_new();
+ struct InfoGroup *this_group = NULL;
+ gboolean has_vendor_field = FALSE;
+ gboolean updatable = FALSE;
+ const Vendor *gv = NULL;
+ int gc = 0;
+
+ GDBusConnection *conn;
+ GDBusProxy *proxy;
+ GVariant *devices, *value;
+ GVariantIter *deviter, *dictiter, *iter;
+ const gchar *key, *tmpstr;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
+ if (!conn)
+ return g_strdup("");
+
+ proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
+ FWUPT_INTERFACE, "/", FWUPT_INTERFACE,
+ NULL, NULL);
+ if (!proxy) {
+ g_object_unref(conn);
+ return g_strdup("");
+ }
+
+ fail_no_fwupd = FALSE;
+ devices = g_dbus_proxy_call_sync(proxy, "GetDevices", NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);
+
+ if (devices) {
+ g_variant_get(devices, "(aa{sv})", &deviter);
+ while(g_variant_iter_loop(deviter, "a{sv}", &dictiter)){
+
+ this_group = info_add_group(info, _("Unknown"), info_field_last());
+ this_group->sort = INFO_GROUP_SORT_NAME_DESCENDING;
+ has_vendor_field = FALSE;
+ updatable = FALSE;
+ gv = NULL;
+
+ while (g_variant_iter_loop(dictiter, "{&sv}", &key, &value)) {
+ if (SEQ(key, "Name")) {
+ tmpstr = g_variant_get_string(value, NULL);
+ this_group->name = hardinfo_clean_grpname(tmpstr, 0);
+ gv = vendor_match(tmpstr, NULL);
+ } else if (SEQ(key, "Vendor")) {
+ has_vendor_field = TRUE;
+ tmpstr = g_variant_get_string(value, NULL);
+
+ const Vendor* v = vendor_match(tmpstr, NULL);
+ if (v) {
+ info_group_add_field(this_group,
+ info_field(_("Vendor"), v->name,
+ .value_has_vendor = TRUE,
+ .free_value_on_flatten = FALSE) );
+ } else {
+ info_group_add_field(this_group,
+ info_field(_("Vendor"), g_strdup(tmpstr),
+ .free_value_on_flatten = TRUE) );
+ }
+ } else if (SEQ(key, "Icon")) {
+ g_variant_get(value, "as", &iter);
+ while (g_variant_iter_loop(iter, "s", &tmpstr)) {
+ info_group_add_field(this_group,
+ info_field(_("Icon"), g_strdup(tmpstr),
+ .free_value_on_flatten = TRUE,
+ .icon = g_strdup(find_icon(tmpstr)) ) );
+ }
+ } else if (SEQ(key, "Guid")) {
+ g_variant_get(value, "as", &iter);
+ while (g_variant_iter_loop(iter, "s", &tmpstr)) {
+ info_group_add_field(this_group,
+ info_field(_("Guid"), g_strdup(tmpstr),
+ .tag = g_strdup_printf("guid%d", gc++),
+ .free_value_on_flatten = TRUE) );
+ }
+ g_variant_iter_free(iter);
+ } else if (SEQ(key, "Created")) {
+ guint64 created = g_variant_get_uint64(value);
+ GDateTime *dt = g_date_time_new_from_unix_local(created);
+ if (dt) {
+ info_group_add_field(this_group,
+ info_field(_("Created"), g_date_time_format(dt, "%x"),
+ .free_value_on_flatten = TRUE) );
+ g_date_time_unref(dt);
+ }
+ } else if (SEQ(key, "Flags")) {
+ guint64 flags = g_variant_get_uint64(value);
+ updatable = (gboolean)(flags & (1u << 1));
+ info_group_add_field(this_group,
+ info_field(_("Flags"), decode_flags(flags),
+ .free_value_on_flatten = TRUE) );
+ } else {
+ if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
+ info_group_add_field(this_group,
+ info_field(find_translation(key),
+ g_variant_dup_string(value, NULL),
+ .free_value_on_flatten = TRUE) );
+ }
+ }
+ }
+
+ if (gv && !has_vendor_field) {
+ info_group_add_field(this_group,
+ info_field(_("Vendor"), gv->name,
+ .value_has_vendor = TRUE,
+ .free_value_on_flatten = FALSE) );
+ }
+
+ // hide devices that are not updatable
+ if (!updatable) {
+ info_remove_group(info, info->groups->len - 1);
+ }
+ }
+ g_variant_iter_free(deviter);
+ g_variant_unref(devices);
+ }
+
+ g_object_unref(proxy);
+ g_object_unref(conn);
+
+ gchar *ret = NULL;
+ if (info->groups->len) {
+ info_set_view_type(info, SHELL_VIEW_DETAIL);
+ //fw_msg("flatten...");
+ ret = info_flatten(info);
+ //fw_msg("ret: %s", ret);
+ } else {
+ ret = g_strdup_printf("[%s]\n%s=%s\n" "[$ShellParam$]\nViewType=0\n",
+ _("Firmware List"),
+ _("Result"), _("(Not available)") );
+ }
+ return ret;
+}
+
+gchar *firmware_get_info() {
+ return fwupdmgr_get_devices_info();
+}
+
+gboolean firmware_hinote(const char **msg) {
+ if (fail_no_fwupd) {
+ *msg = g_strdup(
+ _("Requires the <i><b>fwupd</b></i> daemon."));
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/modules/devices/gpu.c b/modules/devices/gpu.c
new file mode 100644
index 00000000..96520161
--- /dev/null
+++ b/modules/devices/gpu.c
@@ -0,0 +1,291 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2017 L. A. F. Pereira <l@tia.mat.br>
+ * This file
+ * Copyright (C) 2018 Burt P. <pburt0@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+
+#include "hardinfo.h"
+#include "devices.h"
+#include "gpu_util.h"
+
+gchar *gpu_list = NULL;
+gchar *gpu_summary = NULL;
+
+void gpu_summary_add(const char *gpu_name) {
+ if (strlen(gpu_summary) == 0) {
+ /* first one */
+ gpu_summary = h_strdup_cprintf("%s", gpu_summary, gpu_name);
+ } else {
+ /* additional */
+ gpu_summary = h_strdup_cprintf(" + %s", gpu_summary, gpu_name);
+ }
+}
+
+#define UNKIFNULL_AC(f) (f != NULL) ? f : _("(Unknown)");
+
+static void _gpu_pci_dev(gpud* gpu) {
+ pcid *p = gpu->pci_dev;
+ gchar *str;
+ gchar *vendor, *svendor, *product, *sproduct;
+ gchar *name, *key;
+ gchar *drm_path = NULL;
+
+ gboolean vendor_is_svendor = (p->vendor_id == p->sub_vendor_id && p->device_id == p->sub_device_id);
+
+ vendor = UNKIFNULL_AC(p->vendor_id_str);
+ svendor = UNKIFNULL_AC(p->sub_vendor_id_str);
+ product = UNKIFNULL_AC(p->device_id_str);
+ sproduct = UNKIFNULL_AC(p->sub_device_id_str);
+ if (gpu->drm_dev)
+ drm_path = g_strdup_printf("/dev/dri/%s", gpu->drm_dev);
+ else
+ drm_path = g_strdup(_("(Unknown)"));
+
+ gchar *ven_tag = vendor_match_tag(p->vendor_id_str, params.fmt_opts);
+ gchar *sven_tag = vendor_match_tag(p->sub_vendor_id_str, params.fmt_opts);
+ if (ven_tag) {
+ if (sven_tag && !vendor_is_svendor) {
+ name = g_strdup_printf("%s %s %s", sven_tag, ven_tag, product);
+ } else {
+ name = g_strdup_printf("%s %s", ven_tag, product);
+ }
+ } else {
+ name = g_strdup_printf("%s %s", vendor, product);
+ }
+ g_free(ven_tag);
+ g_free(sven_tag);
+
+ key = g_strdup_printf("GPU%s", gpu->id);
+
+ gpu_summary_add((gpu->nice_name) ? gpu->nice_name : name);
+ gpu_list = h_strdup_cprintf("$!%s$%s=%s\n", gpu_list, key, gpu->id, name);
+
+ gchar *vendor_device_str;
+ if (p->vendor_id == p->sub_vendor_id && p->device_id == p->sub_device_id) {
+ vendor_device_str = g_strdup_printf(
+ /* Vendor */ "$^$%s=[%04x] %s\n"
+ /* Device */ "%s=[%04x] %s\n",
+ _("Vendor"), p->vendor_id, vendor,
+ _("Device"), p->device_id, product);
+ } else {
+ vendor_device_str = g_strdup_printf(
+ /* Vendor */ "$^$%s=[%04x] %s\n"
+ /* Device */ "%s=[%04x] %s\n"
+ /* Sub-device vendor */ "$^$%s=[%04x] %s\n"
+ /* Sub-device */ "%s=[%04x] %s\n",
+ _("Vendor"), p->vendor_id, vendor,
+ _("Device"), p->device_id, product,
+ _("SVendor"), p->sub_vendor_id, svendor,
+ _("SDevice"), p->sub_device_id, sproduct);
+ }
+
+ gchar *pcie_str;
+ if (p->pcie_width_curr) {
+ pcie_str = g_strdup_printf("[%s]\n"
+ /* Width (max) */ "%s=x%u\n"
+ /* Speed (max) */ "%s=%0.1f %s\n",
+ _("PCI Express"),
+ _("Maximum Link Width"), p->pcie_width_max,
+ _("Maximum Link Speed"), p->pcie_speed_max, _("GT/s") );
+ } else
+ pcie_str = strdup("");
+
+ gchar *nv_str;
+ if (gpu->nv_info) {
+ nv_str = g_strdup_printf("[%s]\n"
+ /* model */ "%s=%s\n"
+ /* bios */ "%s=%s\n"
+ /* uuid */ "%s=%s\n",
+ _("NVIDIA"),
+ _("Model"), gpu->nv_info->model,
+ _("BIOS Version"), gpu->nv_info->bios_version,
+ _("UUID"), gpu->nv_info->uuid );
+ } else
+ nv_str = strdup("");
+
+ gchar *freq = g_strdup(_("(Unknown)"));
+ if (gpu->khz_max > 0) {
+ if (gpu->khz_min > 0 && gpu->khz_min != gpu->khz_max)
+ freq = g_strdup_printf("%0.2f-%0.2f %s", (double) gpu->khz_min / 1000, (double) gpu->khz_max / 1000, _("MHz"));
+ else
+ freq = g_strdup_printf("%0.2f %s", (double) gpu->khz_max / 1000, _("MHz"));
+ }
+
+ gchar *mem_freq = g_strdup(_("(Unknown)"));
+ if (gpu->mem_khz_max > 0) {
+ if (gpu->mem_khz_min > 0 && gpu->mem_khz_min != gpu->mem_khz_max)
+ mem_freq = g_strdup_printf("%0.2f-%0.2f %s", (double) gpu->mem_khz_min / 1000, (double) gpu->mem_khz_max / 1000, _("MHz"));
+ else
+ mem_freq = g_strdup_printf("%0.2f %s", (double) gpu->mem_khz_max / 1000, _("MHz"));
+ }
+
+ str = g_strdup_printf("[%s]\n"
+ /* Location */ "%s=%s\n"
+ /* DRM Dev */ "%s=%s\n"
+ /* Class */ "%s=[%04x] %s\n"
+ "%s"
+ /* Revision */ "%s=%02x\n"
+ "[%s]\n"
+ /* Core freq */ "%s=%s\n"
+ /* Mem freq */ "%s=%s\n"
+ /* NV */ "%s"
+ /* PCIe */ "%s"
+ "[%s]\n"
+ /* Driver */ "%s=%s\n"
+ /* Modules */ "%s=%s\n",
+ _("Device Information"),
+ _("Location"), gpu->location,
+ _("DRM Device"), drm_path,
+ _("Class"), p->class, p->class_str,
+ vendor_device_str,
+ _("Revision"), p->revision,
+ _("Clocks"),
+ _("Core"), freq,
+ _("Memory"), mem_freq,
+ nv_str,
+ pcie_str,
+ _("Driver"),
+ _("In Use"), (p->driver) ? p->driver : _("(Unknown)"),
+ _("Kernel Modules"), (p->driver_list) ? p->driver_list : _("(Unknown)")
+ );
+
+ moreinfo_add_with_prefix("DEV", key, str); /* str now owned by morinfo */
+
+ g_free(drm_path);
+ g_free(pcie_str);
+ g_free(nv_str);
+ g_free(vendor_device_str);
+ g_free(name);
+ g_free(key);
+}
+
+int _dt_soc_gpu(gpud *gpu) {
+ static char UNKSOC[] = "(Unknown)"; /* don't translate this */
+ gchar *vendor = gpu->vendor_str;
+ gchar *device = gpu->device_str;
+ if (vendor == NULL) vendor = UNKSOC;
+ if (device == NULL) device = UNKSOC;
+ gchar *freq = g_strdup(_("(Unknown)"));
+ if (gpu->khz_max > 0) {
+ if (gpu->khz_min > 0)
+ freq = g_strdup_printf("%0.2f-%0.2f %s", (double) gpu->khz_min / 1000, (double) gpu->khz_max / 1000, _("MHz"));
+ else
+ freq = g_strdup_printf("%0.2f %s", (double) gpu->khz_max / 1000, _("MHz"));
+ }
+ gchar *key = g_strdup(gpu->id);
+
+ gchar *name = NULL;
+ gchar *vtag = vendor_match_tag(gpu->vendor_str, params.fmt_opts);
+ if (vtag) {
+ name = g_strdup_printf("%s %s", vtag, device);
+ } else {
+ name = (vendor == UNKSOC && device == UNKSOC)
+ ? g_strdup(_("Unknown integrated GPU"))
+ : g_strdup_printf("%s %s", vendor, device);
+ }
+ g_free(vtag);
+
+ gchar *opp_str;
+ if (gpu->dt_opp) {
+ static const char *freq_src[] = {
+ N_("clock-frequency property"),
+ N_("Operating Points (OPPv1)"),
+ N_("Operating Points (OPPv2)"),
+ };
+ opp_str = g_strdup_printf("[%s]\n"
+ /* MinFreq */ "%s=%d %s\n"
+ /* MaxFreq */ "%s=%d %s\n"
+ /* Latency */ "%s=%d %s\n"
+ /* Source */ "%s=%s\n",
+ _("Frequency Scaling"),
+ _("Minimum"), gpu->dt_opp->khz_min, _("kHz"),
+ _("Maximum"), gpu->dt_opp->khz_max, _("kHz"),
+ _("Transition Latency"), gpu->dt_opp->clock_latency_ns, _("ns"),
+ _("Source"), _(freq_src[gpu->dt_opp->version]) );
+ } else
+ opp_str = strdup("");
+
+ gpu_summary_add((gpu->nice_name) ? gpu->nice_name : name);
+ gpu_list = h_strdup_cprintf("$!%s$%s=%s\n", gpu_list, key, key, name);
+ gchar *str = g_strdup_printf("[%s]\n"
+ /* Location */ "%s=%s\n"
+ /* Vendor */ "$^$%s=%s\n"
+ /* Device */ "%s=%s\n"
+ "[%s]\n"
+ /* Freq */ "%s=%s\n"
+ /* opp-v2 */ "%s"
+ "[%s]\n"
+ /* Path */ "%s=%s\n"
+ /* Compat */ "%s=%s\n"
+ /* Status */ "%s=%s\n"
+ /* Name */ "%s=%s\n",
+ _("Device Information"),
+ _("Location"), gpu->location,
+ _("Vendor"), vendor,
+ _("Device"), device,
+ _("Clocks"),
+ _("Core"), freq,
+ opp_str,
+ _("Device Tree Node"),
+ _("Path"), gpu->dt_path,
+ _("Compatible"), gpu->dt_compat,
+ _("Status"), gpu->dt_status,
+ _("Name"), gpu->dt_name
+ );
+ moreinfo_add_with_prefix("DEV", key, str); /* str now owned by morinfo */
+ g_free(freq);
+ g_free(opp_str);
+ return 1;
+}
+
+void scan_gpu_do(void) {
+ if (gpu_summary)
+ g_free(gpu_summary);
+ if (gpu_list) {
+ moreinfo_del_with_prefix("DEV:GPU");
+ g_free(gpu_list);
+ }
+ gpu_summary = strdup("");
+ gpu_list = g_strdup_printf("[%s]\n", _("GPUs"));
+
+ gpud *gpus = gpu_get_device_list();
+ gpud *curr = gpus;
+
+ int c = gpud_list_count(gpus);
+
+ if (c > 0) {
+ while(curr) {
+ if (curr->pci_dev) {
+ _gpu_pci_dev(curr);
+ }
+ if (curr->dt_compat) {
+ _dt_soc_gpu(curr);
+ }
+ curr=curr->next;
+ }
+ }
+ gpud_list_free(gpus);
+
+ if (c)
+ gpu_list = g_strconcat(gpu_list, "[$ShellParam$]\n", "ViewType=1\n", NULL);
+ else {
+ /* NO GPU? */
+ gpu_list = g_strconcat(gpu_list, _("No GPU devices found"), "=\n", NULL);
+ }
+}
diff --git a/modules/devices/ia64/processor.c b/modules/devices/ia64/processor.c
index c4d06a71..f31813bc 100644
--- a/modules/devices/ia64/processor.c
+++ b/modules/devices/ia64/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/inputdevices.c b/modules/devices/inputdevices.c
index cf1728a9..301641d4 100644
--- a/modules/devices/inputdevices.c
+++ b/modules/devices/inputdevices.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,6 +20,7 @@
#include "hardinfo.h"
#include "devices.h"
+#include "usb_util.h"
gchar *input_icons = NULL;
@@ -27,113 +28,143 @@ static struct {
char *name;
char *icon;
} input_devices[] = {
+ { NULL, "module.png" }, // UNKNOWN
{ "Keyboard", "keyboard.png" },
{ "Joystick", "joystick.png" },
{ "Mouse", "mouse.png" },
- { "Speaker", "audio.png" },
- { "Unknown", "module.png" },
+ { "Speaker", "audio.png" },
+ { "Audio", "audio.png" }
};
+// source: https://elixir.bootlin.com/linux/v5.9/source/include/uapi/linux/input.h#L251
+static const gchar *bus_types[] = {
+ NULL, "PCI", "ISA PnP", "USB", // 0x0 - 0x3
+ "HIL", "Bluetooth", "Virtual", NULL, // 0x4 - 0x7
+ NULL, NULL, NULL, NULL, // 0x8 - 0xB
+ NULL, NULL, NULL, NULL, // 0xC - 0xF
+ "ISA", "i8042", "XT Keyboard bus", "RS232", // 0x10 - 0x13
+ "Game port", "Parallel port", "Amiga bus", "ADB", // 0x14 - 0x17
+ "I²C", "HOST", "GSC", "Atari bus", // 0x18 - 0x1B
+ "SPI", "RMI", "CEC", "Intel ISHTP" // 0x1C - 0x1F
+};
+
+#define UNKWNIFNULL(f) ((f) ? f : _("(Unknown)"))
+#define EMPTYIFNULL(f) ((f) ? f : "")
+
void
__scan_input_devices(void)
{
FILE *dev;
gchar buffer[1024];
+ vendor_list vl = NULL;
gchar *tmp, *name = NULL, *phys = NULL;
+ gchar *vendor_str = NULL, *product_str = NULL, *vendor_tags = NULL;
gint bus = 0, vendor = 0, product = 0, version = 0;
+ const gchar *bus_str = NULL;
int d = 0, n = 0;
dev = fopen("/proc/bus/input/devices", "r");
if (!dev)
- return;
+ return;
if (input_list) {
moreinfo_del_with_prefix("DEV:INP");
- g_free(input_list);
- g_free(input_icons);
+ g_free(input_list);
+ g_free(input_icons);
}
input_list = g_strdup("");
input_icons = g_strdup("");
while (fgets(buffer, sizeof(buffer), dev)) {
- tmp = buffer;
-
- switch (*tmp) {
- case 'N':
- tmp = strreplacechr(tmp + strlen("N: Name="), "=", ':');
- name = g_strdup(tmp);
- remove_quotes(name);
- break;
- case 'P':
- phys = g_strdup(tmp + strlen("P: Phys="));
- break;
- case 'I':
- sscanf(tmp, "I: Bus=%x Vendor=%x Product=%x Version=%x",
- &bus, &vendor, &product, &version);
- break;
- case 'H':
- if (strstr(tmp, "kbd"))
- d = 0; //INPUT_KEYBOARD;
- else if (strstr(tmp, "js"))
- d = 1; //INPUT_JOYSTICK;
- else if (strstr(tmp, "mouse"))
- d = 2; //INPUT_MOUSE;
- else
- d = 4; //INPUT_UNKNOWN;
- break;
- case '\n':
- if (name && strstr(name, "PC Speaker")) {
- d = 3; // INPUT_PCSPKR
- }
-
- tmp = g_strdup_printf("INP%d", ++n);
- input_list = h_strdup_cprintf("$%s$%s=\n",
- input_list,
- tmp, name);
- input_icons = h_strdup_cprintf("Icon$%s$%s=%s\n",
- input_icons,
- tmp, name,
- input_devices[d].icon);
-
- const gchar *v_url = (gchar*)vendor_get_url(name);
- const gchar *v_name = (gchar*)vendor_get_name(name);
- gchar *v_str = NULL;
- if (v_url != NULL)
- v_str = g_strdup_printf("[0x%x] %s (%s)", vendor, v_name, v_url);
- else
- v_str = g_strdup_printf("0x%x", vendor);
- v_str = hardinfo_clean_value(v_str, 1);
- name = hardinfo_clean_value(name, 1);
-
- gchar *strhash = g_strdup_printf("[%s]\n"
- /* Name */ "%s=%s\n"
- /* Type */ "%s=%s\n"
- /* Bus */ "%s=0x%x\n"
- /* Vendor */ "%s=%s\n"
- /* Product */"%s=0x%x\n"
- /* Version */"%s=0x%x\n",
- _("Device Information"),
- _("Name"), name,
- _("Type"), input_devices[d].name,
- _("Bus"), bus,
- _("Vendor"), v_str,
- _("Product"), product,
- _("Version"), version );
-
- if (phys && phys[1] != 0) {
- strhash = h_strdup_cprintf("%s=%s\n", strhash, _("Connected to"), phys);
+ tmp = buffer;
+
+ switch (*tmp) {
+ case 'N':
+ tmp = strreplacechr(tmp + strlen("N: Name="), "=", ':');
+ name = g_strdup(tmp);
+ remove_quotes(name);
+ break;
+ case 'P':
+ phys = g_strdup(tmp + strlen("P: Phys="));
+ break;
+ case 'I':
+ sscanf(tmp, "I: Bus=%x Vendor=%x Product=%x Version=%x",
+ &bus, &vendor, &product, &version);
+ break;
+ case 'H':
+ if (strstr(tmp, "kbd"))
+ d = 1; //INPUT_KEYBOARD;
+ else if (strstr(tmp, "js"))
+ d = 2; //INPUT_JOYSTICK;
+ else if (strstr(tmp, "mouse"))
+ d = 3; //INPUT_MOUSE;
+ else
+ d = 0; //INPUT_UNKNOWN;
+ break;
+ case '\n':
+ if (name && strstr(name, "PC Speaker")) {
+ d = 4; // INPUT_PCSPKR
+ }
+ if (d == 0 && g_strcmp0(phys, "ALSA")) {
+ d = 5; // INPUT_AUDIO
+ }
+
+ if (vendor > 0 && product > 0 && g_str_has_prefix(phys, "usb-")) {
+ usb_lookup_ids_vendor_product_str(vendor, product, &vendor_str, &product_str);
+ }
+
+ if (bus >= 0 && (guint)bus < sizeof(bus_types) / sizeof(gchar*)) {
+ bus_str = bus_types[bus];
+ }
+
+ vl = vendor_list_remove_duplicates_deep(vendors_match(name, vendor_str, NULL));
+ vendor_tags = vendor_list_ribbon(vl, params.fmt_opts);
+
+ tmp = g_strdup_printf("INP%d", ++n);
+ input_list = h_strdup_cprintf("$%s$%s=%s|%s\n",
+ input_list,
+ tmp, name, EMPTYIFNULL(vendor_tags),
+ EMPTYIFNULL(input_devices[d].name));
+ input_icons = h_strdup_cprintf("Icon$%s$%s=%s\n",
+ input_icons,
+ tmp, name,
+ input_devices[d].icon);
+
+ gchar *strhash = g_strdup_printf("[%s]\n"
+ /* Name */ "$^$%s=%s\n"
+ /* Type */ "%s=%s\n"
+ /* Bus */ "%s=[0x%x] %s\n"
+ /* Vendor */ "$^$%s=[0x%x] %s\n"
+ /* Product */"%s=[0x%x] %s\n"
+ /* Version */"%s=0x%x\n",
+ _("Device Information"),
+ _("Name"), name,
+ _("Type"), UNKWNIFNULL(input_devices[d].name),
+ _("Bus"), bus, UNKWNIFNULL(bus_str),
+ _("Vendor"), vendor, UNKWNIFNULL(vendor_str),
+ _("Product"), product, UNKWNIFNULL(product_str),
+ _("Version"), version );
+
+ if (phys && phys[1] != 0) {
+ strhash = h_strdup_cprintf("%s=%s\n", strhash, _("Connected to"), phys);
+ }
+
+ if (phys && strstr(phys, "ir")) {
+ strhash = h_strdup_cprintf("%s=%s\n", strhash, _("InfraRed port"), _("Yes") );
+ }
+
+ moreinfo_add_with_prefix("DEV", tmp, strhash);
+ g_free(tmp);
+ g_free(phys);
+ g_free(name);
+ g_free(vendor_str);
+ g_free(vendor_tags);
+ g_free(product_str);
+ bus_str = NULL;
+ vendor_str = NULL;
+ product_str = NULL;
+ vendor_tags = NULL;
}
-
- if (phys && strstr(phys, "ir")) {
- strhash = h_strdup_cprintf("%s=%s\n", strhash, _("InfraRed port"), _("Yes") );
- }
-
- moreinfo_add_with_prefix("DEV", tmp, strhash);
- g_free(tmp);
- g_free(v_str);
- g_free(phys);
- g_free(name);
- }
}
fclose(dev);
diff --git a/modules/devices/loongarch64/processor.c b/modules/devices/loongarch64/processor.c
new file mode 100644
index 00000000..08f3645e
--- /dev/null
+++ b/modules/devices/loongarch64/processor.c
@@ -0,0 +1,90 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hardinfo.h"
+#include "devices.h"
+#include "cpu_util.h"
+
+GSList *
+processor_scan(void)
+{
+ Processor *processor;
+ FILE *cpuinfo;
+ gchar buffer[128];
+
+ cpuinfo = fopen(PROC_CPUINFO, "r");
+ if (!cpuinfo)
+ return NULL;
+
+ processor = g_new0(Processor, 1);
+ while (fgets(buffer, 128, cpuinfo)) {
+ gchar **tmp = g_strsplit(buffer, ":", 2);
+
+ if (tmp[0] && tmp[1]) {
+ tmp[0] = g_strstrip(tmp[0]);
+ tmp[1] = g_strstrip(tmp[1]);
+
+ get_str("system type", processor->vendor_id);
+ get_str("CPU Family", processor->family);
+ get_str("Model Name", processor->model_name);
+ get_int("CPU Revision", processor->revision);
+ get_float("CPU MHz", processor->cpu_mhz);
+ get_float("BogoMIPS", processor->bogomips);
+ get_str("Features", processor->features);
+ }
+ g_strfreev(tmp);
+ }
+
+ fclose(cpuinfo);
+
+ return g_slist_append(NULL, processor);
+}
+
+gchar *processor_name(GSList * processors) {
+ return processor_name_default(processors);
+}
+
+gchar *processor_describe(GSList * processors) {
+ return processor_describe_default(processors);
+}
+
+gchar *
+processor_get_info(GSList *processors)
+{
+ Processor *processor = (Processor *)processors->data;
+
+ return g_strdup_printf("[%s]\n"
+ "%s=%s\n" /* vendor */
+ "%s=%s\n" /* family */
+ "%s=%s\n" /* name */
+ "%s=%d\n" /* revision */
+ "%s=%.2f %s\n" /* frequency */
+ "%s=%.2f\n" /* bogoMIPS */
+ "%s=%s\n" /* features */
+ "%s=%s\n", /* byte order */
+ _("Processor"),
+ _("System Type"), processor->vendor_id,
+ _("Family"), processor->family,
+ _("Model"), processor->model_name,
+ _("Revision"), processor->revision,
+ _("Frequency"), processor->cpu_mhz, _("MHz"),
+ _("BogoMIPS"), processor->bogomips,
+ _("Features"), processor->features,
+ _("Byte Order"), byte_order_str()
+ );
+}
diff --git a/modules/devices/m68k/processor.c b/modules/devices/m68k/processor.c
index e030732a..a9d71835 100644
--- a/modules/devices/m68k/processor.c
+++ b/modules/devices/m68k/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/mips/processor.c b/modules/devices/mips/processor.c
index b31af7dd..112a3c3b 100644
--- a/modules/devices/mips/processor.c
+++ b/modules/devices/mips/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/monitors.c b/modules/devices/monitors.c
new file mode 100644
index 00000000..02fb1d67
--- /dev/null
+++ b/modules/devices/monitors.c
@@ -0,0 +1,515 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2019 L. A. F. Pereira <l@tia.mat.br>
+ * Copyright (C) 2019 Burt P. <pburt0@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 or later.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "devices.h"
+#include "util_sysobj.h"
+#include "util_edid.h"
+#include "util_ids.h"
+
+static const char monitor_icon[] = "monitor.png";
+
+#define UNKIFNULL2(f) ((f) ? f : _("(Unknown)"))
+#define UNKIFEMPTY2(f) ((*f) ? f : _("(Unknown)"))
+#define UNSPECIFNULL2(f) ((f) ? f : _("(Unspecified)"))
+
+gboolean no_monitors = FALSE;
+
+gchar *edid_ids_file = NULL;
+gchar *ieee_oui_ids_file = NULL;
+
+void find_edid_ids_file() {
+ if (edid_ids_file) return;
+ char *file_search_order[] = {
+ g_build_filename(g_get_user_config_dir(), "hardinfo2", "edid.ids", NULL),
+ g_build_filename(params.path_data, "edid.ids", NULL),
+ NULL
+ };
+ int n;
+ for(n = 0; file_search_order[n]; n++) {
+ if (!edid_ids_file && !access(file_search_order[n], R_OK))
+ edid_ids_file = file_search_order[n];
+ else
+ g_free(file_search_order[n]);
+ }
+ auto_free(edid_ids_file);
+}
+
+void find_ieee_oui_ids_file() {
+ if (ieee_oui_ids_file) return;
+ char *file_search_order[] = {
+ g_build_filename(g_get_user_config_dir(), "hardinfo2", "ieee_oui.ids", NULL),
+ g_build_filename(params.path_data, "ieee_oui.ids", NULL),
+ NULL
+ };
+ int n;
+ for(n = 0; file_search_order[n]; n++) {
+ if (!ieee_oui_ids_file && !access(file_search_order[n], R_OK))
+ ieee_oui_ids_file = file_search_order[n];
+ else
+ g_free(file_search_order[n]);
+ }
+ auto_free(ieee_oui_ids_file);
+}
+
+typedef struct {
+ gchar *drm_path;
+ gchar *drm_connection;
+ gchar *drm_status;
+ gchar *drm_enabled;
+ edid *e;
+ gchar *_vstr; /* use monitor_vendor_str() */
+} monitor;
+#define monitor_new() g_new0(monitor, 1)
+
+monitor *monitor_new_from_sysfs(const gchar *sysfs_edid_file) {
+ gchar *edid_bin = NULL;
+ gsize edid_len = 0;
+ if (!sysfs_edid_file || !*sysfs_edid_file) return NULL;
+ monitor *m = monitor_new();
+ m->drm_path = g_path_get_dirname(sysfs_edid_file);
+ m->drm_connection = g_path_get_basename(m->drm_path);
+ gchar *drm_enabled_file = g_strdup_printf("%s/%s", m->drm_path, "enabled");
+ gchar *drm_status_file = g_strdup_printf("%s/%s", m->drm_path, "status");
+ g_file_get_contents(drm_enabled_file, &m->drm_enabled, NULL, NULL);
+ if (m->drm_enabled) g_strstrip(m->drm_enabled);
+ g_file_get_contents(drm_status_file, &m->drm_status, NULL, NULL);
+ if (m->drm_status) g_strstrip(m->drm_status);
+ g_file_get_contents(sysfs_edid_file, &edid_bin, &edid_len, NULL);
+ if (edid_len)
+ m->e = edid_new(edid_bin, edid_len);
+ g_free(drm_enabled_file);
+ g_free(drm_status_file);
+ return m;
+}
+
+void monitor_free(monitor *m) {
+ if (m) {
+ g_free(m->_vstr);
+ g_free(m->drm_connection);
+ edid_free(m->e);
+ g_free(m);
+ }
+}
+
+gchar *monitor_vendor_str(monitor *m, gboolean include_value, gboolean link_name) {
+ if (!m || !m->e) return NULL;
+ edid_ven ven = m->e->ven;
+ gchar v[20] = "", t[4] = "";
+ ids_query_result result;// = {};
+
+ memset(&result,0,sizeof(ids_query_result));
+ if (ven.type == VEN_TYPE_PNP) {
+ strcpy(v, ven.pnp);
+ strcpy(t, "PNP");
+ } else if (ven.type == VEN_TYPE_OUI) {
+ strcpy(v, ven.oui_str);
+ strcpy(t, "OUI");
+ }
+
+ if (!m->_vstr) {
+ if (ven.type == VEN_TYPE_PNP) {
+ if (!edid_ids_file)
+ find_edid_ids_file();
+ scan_ids_file(edid_ids_file, v, &result, -1);
+ if (result.results[0])
+ m->_vstr = g_strdup(result.results[0]);
+ } else if (ven.type == VEN_TYPE_OUI) {
+ if (!ieee_oui_ids_file)
+ find_ieee_oui_ids_file();
+ scan_ids_file(ieee_oui_ids_file, v, &result, -1);
+ if (result.results[0])
+ m->_vstr = g_strdup(result.results[0]);
+ }
+ }
+
+ gchar *ret = NULL;
+ if (include_value)
+ ret = g_strdup_printf("[%s:%s]", t, v);
+ if (m->_vstr) {
+ if (link_name) {
+ gchar *lv = vendor_get_link(m->_vstr);
+ ret = appfsp(ret, "%s", lv);
+ g_free(lv);
+ } else
+ ret = appfsp(ret, "%s", m->_vstr);
+ } else if (!include_value && ven.type == VEN_TYPE_PNP) {
+ ret = appfsp(ret, "%s", ven.pnp);
+ } else
+ ret = appfsp(ret, "%s", _("(Unknown)"));
+ return ret;
+}
+
+gchar *monitor_name(monitor *m, gboolean include_vendor) {
+ if (!m) return NULL;
+ gchar *desc = NULL;
+ edid *e = m->e;
+ if (!e)
+ return g_strdup(_("(Unknown)"));
+
+ if (include_vendor) {
+ if (e->ven.type != VEN_TYPE_INVALID) {
+ gchar *vstr = monitor_vendor_str(m, FALSE, FALSE);
+ gchar *vtag = vendor_match_tag(vstr, params.fmt_opts);
+ desc = appfsp(desc, "%s", vtag ? vtag : vstr);
+ g_free(vstr);
+ g_free(vtag);
+ } else
+ desc = appfsp(desc, "%s", "Unknown");
+ }
+
+ if (e->img_max.diag_in)
+ desc = appfsp(desc, "%s", e->img_max.class_inch);
+
+ if (e->name)
+ desc = appfsp(desc, "%s", e->name);
+ else
+ desc = appfsp(desc, "%s %s", e->a_or_d ? "Digital" : "Analog", "Display");
+
+ return desc;
+}
+
+gchar **get_output_lines(const char *cmd_line) {
+ gboolean spawned;
+ gchar *out, *err;
+ gchar **ret = NULL;
+
+ spawned = g_spawn_command_line_sync(cmd_line,
+ &out, &err, NULL, NULL);
+ if (spawned) {
+ ret = g_strsplit(out, "\n", -1);
+ g_free(out);
+ g_free(err);
+ }
+ return ret;
+}
+
+static gchar *tag_make_safe_inplace(gchar *tag) {
+ if (!tag)
+ return tag;
+ if (!g_utf8_validate(tag, -1, NULL))
+ return tag; //TODO: reconsider
+ gchar *p = tag, *pd = tag;
+ while(*p) {
+ gchar *np = g_utf8_next_char(p);
+ gunichar c = g_utf8_get_char_validated(p, -1);
+ int l = g_unichar_to_utf8(c, NULL);
+ if (l == 1 && g_unichar_isalnum(c)) {
+ g_unichar_to_utf8(c, pd);
+ } else {
+ *pd = '_';
+ }
+ p = np;
+ pd++;
+ }
+ return tag;
+}
+
+static gchar *make_edid_section(monitor *m) {
+ int i;
+ edid *e = m->e;
+ if (e->len) {
+ gchar *vstr = monitor_vendor_str(m, TRUE, FALSE);
+
+ gchar *dom = NULL;
+ if (!e->dom.is_model_year && e->dom.week && e->dom.year)
+ dom = g_strdup_printf(_("Week %d of %d"), e->dom.week, e->dom.year);
+ else if (e->dom.year)
+ dom = g_strdup_printf("%d", e->dom.year);
+
+ gchar *bpcc = NULL;
+ if (e->bpc)
+ bpcc = g_strdup_printf("%d", e->bpc);
+
+ int aok = e->checksum_ok;
+ if (e->ext_blocks_fail) aok = 0;
+ gchar *csum = aok ? _("Ok") : _("Fail");
+
+ gchar *iface;
+ if (e->interface && e->di.exists) {
+ gchar *tmp = g_strdup_printf("[%x] %s\n[DI-EXT:%x] %s",
+ e->interface, _(edid_interface(e->interface)),
+ e->di.interface, _(edid_di_interface(e->di.interface)) );
+ iface = gg_key_file_parse_string_as_value(tmp, '|');
+ g_free(tmp);
+ } else if (e->di.exists) {
+ iface = g_strdup_printf("[DI-EXT:%x] %s",
+ e->di.interface, _(edid_di_interface(e->di.interface)) );
+ } else {
+ iface = g_strdup_printf("[%x] %s",
+ e->interface,
+ e->interface ? _(edid_interface(e->interface)) : _("(Unspecified)") );
+ }
+
+ gchar *d_list, *ext_list, *dtd_list, *cea_list,
+ *etb_list, *std_list, *svd_list, *sad_list,
+ *didt_list, *did_string_list;
+
+ etb_list = NULL;
+ for(i = 0; i < e->etb_count; i++) {
+ char *desc = edid_output_describe(&e->etbs[i]);
+ etb_list = appfnl(etb_list, "etb%d=%s", i, desc);
+ g_free(desc);
+ }
+ if (!etb_list) etb_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ std_list = NULL;
+ for(i = 0; i < e->std_count; i++) {
+ char *desc = edid_output_describe(&e->stds[i].out);
+ std_list = appfnl(std_list, "std%d=%s", i, desc);
+ g_free(desc);
+ }
+ if (!std_list) std_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ d_list = NULL;
+ for(i = 0; i < 4; i++) {
+ char *desc = edid_base_descriptor_describe(&e->d[i]);
+ d_list = appfnl(d_list, "descriptor%d=%s", i, desc);
+ g_free(desc);
+ }
+ if (!d_list) d_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ ext_list = NULL;
+ for(i = 0; i < e->ext_blocks; i++) {
+ int type = e->u8[(i+1)*128];
+ int version = e->u8[(i+1)*128 + 1];
+ ext_list = appfnl(ext_list, "ext%d = ([%02x:v%02x] %s) %s", i,
+ type, version, _(edid_ext_block_type(type)),
+ e->ext_ok[i] ? "ok" : "fail"
+ );
+ }
+ if (!ext_list) ext_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ dtd_list = NULL;
+ for(i = 0; i < e->dtd_count; i++) {
+ char *desc = edid_dtd_describe(&e->dtds[i], 0);
+ dtd_list = appfnl(dtd_list, "dtd%d = %s", i, desc);
+ free(desc);
+ }
+ if (!dtd_list) dtd_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ cea_list = NULL;
+ for(i = 0; i < e->cea_block_count; i++) {
+ char *desc = edid_cea_block_describe(&e->cea_blocks[i]);
+ cea_list = appfnl(cea_list, "cea_block%d = %s", i, desc);
+ }
+ if (!cea_list) cea_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ svd_list = NULL;
+ for(i = 0; i < e->svd_count; i++) {
+ char *desc = edid_output_describe(&e->svds[i].out);
+ svd_list = appfnl(svd_list, "svd%d=%s", i, desc);
+ g_free(desc);
+ }
+ if (!svd_list) svd_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ sad_list = NULL;
+ for(i = 0; i < e->sad_count; i++) {
+ char *desc = edid_cea_audio_describe(&e->sads[i]);
+ sad_list = appfnl(sad_list, "sad%d=%s", i, desc);
+ g_free(desc);
+ }
+ if (!sad_list) sad_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ didt_list = NULL;
+ for(i = 0; i < e->didt_count; i++) {
+ char *desc = edid_output_describe(&e->didts[i]);
+ didt_list = appfnl(didt_list, "didt%d=%s", i, desc);
+ g_free(desc);
+ }
+ if (!didt_list) didt_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ did_string_list = NULL;
+ for(i = 0; i < e->did_string_count; i++) {
+ did_string_list = appfnl(did_string_list, "did_string%d=%s", i, e->did_strings[i].str);
+ }
+ if (!did_string_list) did_string_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ gchar *speakers = NULL;
+ if (e->speaker_alloc_bits) {
+ gchar *spk_tmp = edid_cea_speaker_allocation_describe(e->speaker_alloc_bits, 0);
+ speakers = gg_key_file_parse_string_as_value(spk_tmp, '|');
+ g_free(spk_tmp);
+ } else
+ speakers = g_strdup(_("(Unspecified)"));
+
+ gchar *hex = edid_dump_hex(e, 0, 1);
+ gchar *hex_esc = gg_key_file_parse_string_as_value(hex, '|');
+ g_free(hex);
+ if (params.markup_ok)
+ hex = g_strdup_printf("<tt>%s</tt>", hex_esc);
+ else
+ hex = g_strdup(hex_esc);
+ g_free(hex_esc);
+
+ gchar *ret = g_strdup_printf(
+ /* extending "Connection" section */
+ "%s=%s\n" /* sig type */
+ "%s=%s\n" /* interface */
+ "%s=%s\n" /* bpcc */
+ "%s=%s\n" /* speakers */
+ "[%s]\n"
+ "%s=%s\n" /* base out */
+ "%s=%s\n" /* ext out */
+ "[%s]\n"
+ "$^$%s=%s\n" /* vendor */
+ "%s=%s\n" /* name */
+ "%s=[%04x-%08x] %u-%u\n" /* model, n_serial */
+ "%s=%s\n" /* serial */
+ "%s=%s\n" /* dom */
+ "[%s]\n"
+ "%s=%d %s\n" /* size */
+ "%s=%d.%d\n" /* version */
+ "%s=%d\n" /* ext block */
+ "%s=%s\n" /* ext to */
+ "%s=%s %s\n" /* checksum */
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s\n"
+ "[%s]\n%s=%s\n"
+ ,
+ _("Signal Type"), e->a_or_d ? _("Digital") : _("Analog"),
+ _("Interface"), iface,
+ _("Bits per Color Channel"), UNSPECIFNULL2(bpcc),
+ _("Speaker Allocation"), speakers,
+ _("Output (Max)"),
+ edid_output_src(e->img.src), edid_output_describe(&e->img),
+ edid_output_src(e->img_max.src), edid_output_describe(&e->img_max),
+ _("EDID Device"),
+ _("Vendor"), vstr,
+ _("Name"), e->name,
+ _("Model"), e->product, e->n_serial, e->product, e->n_serial,
+ _("Serial"), UNKIFNULL2(e->serial),
+ _("Manufacture Date"), UNKIFNULL2(dom),
+ _("EDID Meta"),
+ _("Data Size"), e->len, _("bytes"),
+ _("Version"), (int)e->ver_major, (int)e->ver_minor,
+ _("Extension Blocks"), e->ext_blocks,
+ _("Extended to"), e->std ? _(edid_standard(e->std)) : _("(None)"),
+ _("Checksum"), csum, aok ? "" : problem_marker(),
+ _("EDID Descriptors"), d_list,
+ _("Detailed Timing Descriptors (DTD)"), dtd_list,
+ _("Established Timings Bitmap (ETB)"), etb_list,
+ _("Standard Timings (STD)"), std_list,
+ _("E-EDID Extension Blocks"), ext_list,
+ _("EIA/CEA-861 Data Blocks"), cea_list,
+ _("EIA/CEA-861 Short Audio Descriptors"), sad_list,
+ _("EIA/CEA-861 Short Video Descriptors"), svd_list,
+ _("DisplayID Timings"), didt_list,
+ _("DisplayID Strings"), did_string_list,
+ _("Hex Dump"), _("Data"), hex
+ );
+ g_free(bpcc);
+ g_free(dom);
+
+ g_free(d_list);
+ g_free(ext_list);
+ g_free(etb_list);
+ g_free(std_list);
+ g_free(dtd_list);
+ g_free(cea_list);
+ g_free(sad_list);
+ g_free(svd_list);
+ g_free(didt_list);
+ g_free(did_string_list);
+ g_free(iface);
+ g_free(vstr);
+ g_free(hex);
+ //printf("ret: %s\n", ret);
+ return ret;
+ } else
+ return g_strdup("");
+}
+
+gchar *monitors_get_info() {
+ gchar *icons = g_strdup("");
+ gchar *ret = g_strdup_printf("[%s]\n", _("Monitors"));
+ gchar tag_prefix[] = "DEV";
+
+ gchar **edid_files = get_output_lines("find /sys/devices -name edid");
+ //gchar **edid_files = get_output_lines("find /home/pburt/github/verbose-spork/junk/testing/.testing/edid2/ -name edid.*");
+ int i, found = 0;
+ for(i = 0; edid_files[i]; i++) {
+ monitor *m = monitor_new_from_sysfs(edid_files[i]);
+ //if (m && m->e->std < STD_DISPLAYID) continue;
+ //if (m && !m->e->interface) continue;
+ //if (m && m->e->interface != 1) continue;
+ if (m && !SEQ(m->drm_status, "disconnected")) {
+ gchar *tag = g_strdup_printf("%d-%s", found, m->drm_connection);
+ tag_make_safe_inplace(tag);
+ gchar *desc = monitor_name(m, TRUE);
+ gchar *edid_section = NULL;
+ edid *e = m->e;
+ if (e && e->checksum_ok)
+ edid_section = make_edid_section(m);
+
+ gchar *details = g_strdup_printf("[%s]\n"
+ "%s=%s\n"
+ "%s=%s %s\n"
+ "%s\n",
+ _("Connection"),
+ _("DRM"), m->drm_connection,
+ _("Status"), m->drm_status, m->drm_enabled,
+ edid_section ? edid_section : ""
+ );
+ moreinfo_add_with_prefix(tag_prefix, tag, details); /* moreinfo now owns *details */
+ ret = h_strdup_cprintf("$!%s$%s=%s\n",
+ ret, tag, m->drm_connection, desc);
+ icons = h_strdup_cprintf("Icon$%s$=%s\n", icons, tag, monitor_icon);
+ g_free(desc);
+ g_free(edid_section);
+ found++;
+ }
+ monitor_free(m);
+ }
+ g_strfreev(edid_files);
+
+ no_monitors = FALSE;
+ if(!found) {
+ no_monitors = TRUE;
+ g_free(ret);
+ ret = g_strdup_printf("[%s]\n%s=%s\n" "[$ShellParam$]\nViewType=0\n",
+ _("Monitors"), _("Result"), _("(Empty)") );
+ } else {
+ ret = h_strdup_cprintf(
+ "[$ShellParam$]\nViewType=1\n"
+ "ColumnTitle$TextValue=%s\n" /* DRM connection */
+ "ColumnTitle$Value=%s\n" /* Name */
+ "ShowColumnHeaders=true\n"
+ "%s",
+ ret,
+ _("Connection"),
+ _("Name"),
+ icons
+ );
+ }
+
+ return ret;
+}
+
+gboolean monitors_hinote(const char **msg) {
+ PARAM_NOT_UNUSED(msg);
+ return FALSE;
+}
diff --git a/modules/devices/parisc/processor.c b/modules/devices/parisc/processor.c
index 9ca38d12..c749bc5a 100644
--- a/modules/devices/parisc/processor.c
+++ b/modules/devices/parisc/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/pci.c b/modules/devices/pci.c
index c1965a63..859fa339 100644
--- a/modules/devices/pci.c
+++ b/modules/devices/pci.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,239 +16,185 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/*
- * TODO: This thing must be rewritten. We really should have a struct with all the
- * PCI stuff we'll present to the user, and hash them by the PCI ID
- * (domain:bus:device.function).
- * This way we'll have ways to better organize the output, instead of relying
- * on the order the information appears on lspci's output.
- * Also, the "Resources" thing might be better implemented (and we won't need
- * copies of information scattered everywhere like we do today).
- */
-
#include <string.h>
#include "hardinfo.h"
#include "devices.h"
-
-GHashTable *_pci_devices = NULL;
-
-void
-scan_pci_do(void)
+#include "pci_util.h"
+
+#define UNKIFNULL_AC(f) (f != NULL) ? f : _("(Unknown)");
+
+static const struct {
+ const gchar *icon;
+ uint32_t class;
+} class2icon[] = {
+ { .class = 0x0200, .icon = "network-interface.png" },
+ { .class = 0x0c03, .icon = "usb.png" },
+ { .class = 0x0403, .icon = "audio.png" },
+ { .class = 0x0805, .icon = "usbfldisk.png" },
+ { .class = 0x0d11, .icon = "bluetooth.png" },
+ { .class = 0x0703, .icon = "modem.png" },
+ { .class = 0x01, .icon = "hdd.png" },
+ { .class = 0x02, .icon = "network.png" },
+ { .class = 0x03, .icon = "monitor.png" },
+ { .class = 0x05, .icon = "memory.png" },
+ { .class = 0x07, .icon = "network-connections.png" },
+ { .class = 0x09, .icon = "inputdevices.png" },
+ { .class = 0x10, .icon = "cryptohash.png" },
+};
+
+static const gchar *find_icon_for_class(uint32_t class)
{
- FILE *lspci;
- gchar buffer[256], *buf, *strhash = NULL, *strdevice = NULL;
- gchar *category = NULL, *name = NULL, *icon, *lspci_path, *command_line = NULL;
- gint n = 0, x = 0;
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS(class2icon); i++) {
+ if (class2icon[i].class <= 0xff) {
+ if ((class & 0xff00) == class2icon[i].class << 8)
+ return class2icon[i].icon;
+ } else if (class == class2icon[i].class) {
+ return class2icon[i].icon;
+ }
+ }
- if ((lspci_path = find_program("lspci")) == NULL) {
- goto pci_error;
+ return "devices.png";
+}
+
+static gchar *_pci_dev(const pcid *p, gchar *icons) {
+ gchar *str;
+ const gchar *class, *vendor, *svendor, *product, *sproduct, *lproduct;
+ gchar *name, *key;
+
+ gboolean device_is_sdevice = (p->vendor_id == p->sub_vendor_id && p->device_id == p->sub_device_id);
+
+ class = UNKIFNULL_AC(p->class_str);
+ vendor = UNKIFNULL_AC(p->vendor_id_str);
+ svendor = UNKIFNULL_AC(p->sub_vendor_id_str);
+ product = UNKIFNULL_AC(p->device_id_str);
+ sproduct = UNKIFNULL_AC(p->sub_device_id_str);
+ lproduct = p->device_id_str ? p->device_id_str : p->class_str;
+ lproduct = UNKIFNULL_AC(lproduct);
+
+ gchar *ven_tag = vendor_match_tag(p->vendor_id_str, params.fmt_opts);
+ gchar *sven_tag = vendor_match_tag(p->sub_vendor_id_str, params.fmt_opts);
+ if (ven_tag) {
+ if (sven_tag && p->vendor_id != p->sub_vendor_id) {
+ name = g_strdup_printf("%s %s %s", sven_tag, ven_tag, lproduct);
+ } else {
+ name = g_strdup_printf("%s %s", ven_tag, lproduct);
+ }
} else {
- command_line = g_strdup_printf("%s -v", lspci_path);
+ name = g_strdup_printf("%s %s", vendor, lproduct);
}
+ g_free(ven_tag);
+ g_free(sven_tag);
- if (!_pci_devices) {
- _pci_devices = g_hash_table_new(g_str_hash, g_str_equal);
- }
+ key = g_strdup_printf("PCI%04x:%02x:%02x.%01x", p->domain, p->bus, p->device, p->function);
- buf = g_build_filename(g_get_home_dir(), ".hardinfo", "pci.ids", NULL);
- if (!g_file_test(buf, G_FILE_TEST_EXISTS)) {
- DEBUG("using system-provided PCI IDs");
- g_free(buf);
- if (!(lspci = popen(command_line, "r"))) {
- goto pci_error;
- }
+ pci_list = h_strdup_cprintf("$%s$%04x:%02x:%02x.%01x=%s\n", pci_list, key, p->domain, p->bus, p->device, p->function, name);
+ icons = h_strdup_cprintf("Icon$%s$%04x:%02x:%02x.%01x=%s\n", icons, key, p->domain, p->bus, p->device, p->function, find_icon_for_class(p->class));
+
+ gchar *vendor_device_str;
+ if (device_is_sdevice) {
+ vendor_device_str = g_strdup_printf(
+ /* Vendor */ "$^$%s=[%04x] %s\n"
+ /* Device */ "%s=[%04x] %s\n",
+ _("Vendor"), p->vendor_id, vendor,
+ _("Device"), p->device_id, product);
} else {
- gchar *tmp;
-
- tmp = g_strdup_printf("%s -i '%s'", command_line, buf);
- g_free(buf);
- buf = tmp;
-
- DEBUG("using updated PCI IDs (from %s)", buf);
- if (!(lspci = popen(tmp, "r"))) {
- g_free(buf);
- goto pci_error;
- } else {
- g_free(buf);
- }
+ vendor_device_str = g_strdup_printf(
+ /* Vendor */ "$^$%s=[%04x] %s\n"
+ /* Device */ "%s=[%04x] %s\n"
+ /* Sub-device vendor */ "$^$%s=[%04x] %s\n"
+ /* Sub-device */ "%s=[%04x] %s\n",
+ _("Vendor"), p->vendor_id, vendor,
+ _("Device"), p->device_id, product,
+ _("SVendor"), p->sub_vendor_id, svendor,
+ _("SDevice"), p->sub_device_id, sproduct);
}
- while (fgets(buffer, 256, lspci)) {
- buf = g_strstrip(buffer);
-
- if (!strncmp(buf, "Flags", 5)) {
- gint irq = 0, freq = 0, latency = 0, i;
- gchar **list;
- gboolean bus_master;
-
- buf += 7;
-
- bus_master = FALSE;
-
- list = g_strsplit(buf, ", ", 10);
- for (i = 0; i <= 10; i++) {
- if (!list[i])
- break;
-
- if (!strncmp(list[i], "IRQ", 3))
- sscanf(list[i], "IRQ %d", &irq);
- else if (strstr(list[i], "Mhz"))
- sscanf(list[i], "%dMhz", &freq);
- else if (!strncmp(list[i], "bus master", 10))
- bus_master = TRUE;
- else if (!strncmp(list[i], "latency", 7))
- sscanf(list[i], "latency %d", &latency);
- }
- g_strfreev(list);
-
- if (irq)
- strdevice = h_strdup_cprintf("%s=%d\n", strdevice, _("IRQ"), irq);
- if (freq)
- strdevice = h_strdup_cprintf("%s=%d %s\n", strdevice, _("Frequency"), freq, _("MHz") );
- if (latency)
- strdevice = h_strdup_cprintf("%s=%d\n", strdevice, _("Latency"), latency);
-
- strdevice = h_strdup_cprintf("%s=%s\n", strdevice, _("Bus Master"), bus_master ? _("Yes") : _("No") );
- } else if (!strncmp(buf, "Kernel modules", 14)) {
- WALK_UNTIL(' ');
- WALK_UNTIL(':');
- buf++;
-
- strdevice = h_strdup_cprintf("%s=%s\n", strdevice, _("Kernel modules"), buf);
- } else if (!strncmp(buf, "Subsystem", 9)) {
- WALK_UNTIL(' ');
- buf++;
- const gchar *oem_vendor_url = vendor_get_url(buf);
- if (oem_vendor_url)
- strdevice = h_strdup_cprintf(_("%s=%s (%s)\n"),
- strdevice,
- _("OEM Vendor"),
- vendor_get_name(buf),
- oem_vendor_url);
- } else if (!strncmp(buf, "Capabilities", 12)
- && !strstr(buf, "only to root") &&
- !strstr(buf, "access denied")) {
- WALK_UNTIL(' ');
- WALK_UNTIL(']');
- buf++;
- strdevice = h_strdup_cprintf("Capability#%d=%s\n", strdevice, ++x, buf);
- } else if (!strncmp(buf, "Memory at", 9) && strstr(buf, "[size=")) {
- gint mem;
- gchar unit;
- gboolean prefetch;
- gboolean _32bit;
-
- prefetch = strstr(buf, "non-prefetchable") ? FALSE : TRUE;
- _32bit = strstr(buf, "32-bit") ? TRUE : FALSE;
-
- WALK_UNTIL('[');
- sscanf(buf, "[size=%d%c", &mem, &unit);
-
- strdevice = h_strdup_cprintf("%s#%d=%d%cB (%s%s)\n",
- strdevice, _("Memory"), ++x,
- mem,
- (unit == ']') ? ' ' : unit,
- _32bit ? "32-bit, " : "",
- prefetch ? _("prefetchable") :
- _("non-prefetchable") );
-
- } else if (!strncmp(buf, "I/O ports at", 12)) {
- guint io_addr, io_size;
-
- sscanf(buf, "I/O ports at %x [size=%d]", &io_addr, &io_size);
-
- strdevice =
- h_strdup_cprintf("%s#%d=0x%x - 0x%x\n",
- strdevice, _("I/O ports at"), ++x, io_addr,
- io_addr + io_size - 1);
- } else if ((buf[0] >= '0' && buf[0] <= '9') && (buf[4] == ':' || buf[2] == ':')) {
- gint bus, device, function, domain;
- gpointer start, end;
-
- if (strdevice != NULL && strhash != NULL) {
- moreinfo_add_with_prefix("DEV", strhash, strdevice);
- g_free(strhash);
- g_free(category);
- g_free(name);
- }
-
- if (buf[4] == ':') {
- sscanf(buf, "%x:%x:%x.%d", &domain, &bus, &device, &function);
- } else {
- /* lspci without domain field */
- sscanf(buf, "%x:%x.%x", &bus, &device, &function);
- domain = 0;
- }
-
- WALK_UNTIL(' ');
-
- start = buf;
-
- WALK_UNTIL(':');
- end = buf + 1;
- *buf = 0;
-
- buf = start + 1;
- category = g_strdup(buf);
-
- buf = end;
-
- if (strstr(category, "RAM memory")) icon = "mem";
- else if (strstr(category, "Multimedia")) icon = "media";
- else if (strstr(category, "USB")) icon = "usb";
- else icon = "pci";
-
- name = g_strdup(buf);
- g_hash_table_insert(_pci_devices,
- g_strdup_printf("0000:%02x:%02x.%x", bus, device, function),
- name);
-
- strhash = g_strdup_printf("PCI%d", n);
- strdevice = g_strdup_printf("[%s]\n"
- /* Name */ "%s=%s\n"
- /* Class */ "%s=%s\n"
- /* Domain */ "%s=%d\n"
- /* Bus, device, function */
- "%s=%d, %d, %d\n",
- _("Device Information"),
- _("Name"), name,
- _("Class"), category,
- _("Domain"), domain,
- _("Bus, device, function"),
- bus, device, function);
-
- const gchar *url = vendor_get_url(name);
- if (url) {
- strdevice = h_strdup_cprintf("%s=%s (%s)\n",
- strdevice,
- _("Vendor"),
- vendor_get_name(name),
- url);
- }
-
- g_hash_table_insert(_pci_devices,
- g_strdup_printf("0000:%02x:%02x.%x", bus, device, function),
- g_strdup(name));
-
- pci_list = h_strdup_cprintf("$PCI%d$%s=%s\n", pci_list, n, category, name);
-
- n++;
- }
+ gchar *pcie_str;
+ if (p->pcie_width_curr) {
+ pcie_str = g_strdup_printf("[%s]\n"
+ /* Width */ "%s=x%u\n"
+ /* Width (max) */ "%s=x%u\n"
+ /* Speed */ "%s=%0.1f %s\n"
+ /* Speed (max) */ "%s=%0.1f %s\n",
+ _("PCI Express"),
+ _("Link Width"), p->pcie_width_curr,
+ _("Maximum Link Width"), p->pcie_width_max,
+ _("Link Speed"), p->pcie_speed_curr, _("GT/s"),
+ _("Maximum Link Speed"), p->pcie_speed_max, _("GT/s") );
+ } else
+ pcie_str = strdup("");
+
+ str = g_strdup_printf("[%s]\n"
+ /* Class */ "%s=[%04x] %s\n"
+ "%s"
+ /* Revision */ "%s=%02x\n"
+ /* PCIE? */ "%s"
+ "[%s]\n"
+ /* Driver */ "%s=%s\n"
+ /* Modules */ "%s=%s\n"
+ "[%s]\n"
+ /* Domain */ "%s=%04x\n"
+ /* Bus */ "%s=%02x\n"
+ /* Device */ "%s=%02x\n"
+ /* Function */ "%s=%01x\n",
+ _("Device Information"),
+ _("Class"), p->class, class,
+ vendor_device_str,
+ _("Revision"), p->revision,
+ pcie_str,
+ _("Driver"),
+ _("In Use"), (p->driver) ? p->driver : _("(Unknown)"),
+ _("Kernel Modules"), (p->driver_list) ? p->driver_list : _("(Unknown)"),
+ _("Connection"),
+ _("Domain"), p->domain,
+ _("Bus"), p->bus,
+ _("Device"), p->device,
+ _("Function"), p->function
+ );
+
+ g_free(pcie_str);
+
+ moreinfo_add_with_prefix("DEV", key, str); /* str now owned by morinfo */
+
+ g_free(vendor_device_str);
+ g_free(name);
+ g_free(key);
+
+ return icons;
+}
+
+void scan_pci_do(void) {
+
+ if (pci_list) {
+ moreinfo_del_with_prefix("DEV:PCI");
+ g_free(pci_list);
+ }
+ pci_list = g_strdup_printf("[%s]\n", _("PCI Devices"));
+
+ gchar *pci_icons = g_strdup("");
+
+ pcid_list list = pci_get_device_list(0,0);
+ list = g_slist_sort(list, (GCompareFunc)pcid_cmp_by_addy);
+ GSList *l = list;
+
+ int c = 0;
+ while(l) {
+ pcid *curr = (pcid*)l->data;
+ pci_icons = _pci_dev(curr, pci_icons);
+ c++;
+ l=l->next;
}
+ pcid_list_free(list);
- if (pclose(lspci)) {
-pci_error:
- /* error (no pci, perhaps?) */
+ if (c) {
+ pci_list = g_strconcat(pci_list, "[$ShellParam$]\n", "ViewType=1\n", pci_icons, NULL);
+ } else {
+ /* NO PCI? */
pci_list = g_strconcat(pci_list, _("No PCI devices found"), "=\n", NULL);
- } else if (strhash) {
- /* insert the last device */
- moreinfo_add_with_prefix("DEV", strhash, strdevice);
- g_free(strhash);
- g_free(category);
- g_free(name);
}
- g_free(lspci_path);
- g_free(command_line);
+ g_free(pci_icons);
}
diff --git a/modules/devices/ppc/processor.c b/modules/devices/ppc/processor.c
index 3360a136..12c575a6 100644
--- a/modules/devices/ppc/processor.c
+++ b/modules/devices/ppc/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/printers.c b/modules/devices/printers.c
index 77b52a43..fb9389ac 100644
--- a/modules/devices/printers.c
+++ b/modules/devices/printers.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2007 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,6 +16,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -33,7 +37,7 @@ struct _CUPSDest {
char *name, *instance;
int is_default;
int num_options;
- CUPSOption *options;
+ CUPSOption *options;
};
static int (*cups_dests_get) (CUPSDest **dests) = NULL;
@@ -49,13 +53,13 @@ init_cups(void)
if (!(cups_dests_get && cups_dests_free)) {
int i;
-
+
for (i = 0; libcups[i] != NULL; i++) {
cups = g_module_open(libcups[i], G_MODULE_BIND_LAZY);
if (cups)
- break;
+ break;
}
-
+
if (!cups) {
cups_init = FALSE;
return;
@@ -63,11 +67,11 @@ init_cups(void)
if (!g_module_symbol(cups, "cupsGetDests", (gpointer) & cups_dests_get)
|| !g_module_symbol(cups, "cupsFreeDests", (gpointer) & cups_dests_free)) {
- g_module_close(cups);
+ if(cups) g_module_close(cups);
cups_init = FALSE;
}
}
-
+
cups_init = TRUE;
}
@@ -76,7 +80,7 @@ gchar *__cups_callback_ptype(gchar *strvalue)
if (strvalue) {
unsigned value = atoi(strvalue);
gchar *output = g_strdup("\n");
-
+
if (value & 0x0004)
output = h_strdup_cprintf(_("\342\232\254 Can do black and white printing=\n"), output);
if (value & 0x0008)
@@ -121,7 +125,7 @@ gchar *__cups_callback_state_change_time(gchar *value)
{
struct tm tm;
char buf[255];
-
+
if (value) {
strptime(value, "%s", &tm);
strftime(buf, sizeof(buf), "%c", &tm);
@@ -144,29 +148,30 @@ gchar *__cups_callback_boolean(gchar *value)
const struct {
char *key, *name;
gchar *(*callback)(gchar *value);
+ gboolean maybe_vendor;
} cups_fields[] = {
{ "Printer Information", NULL, NULL },
{ "printer-info", "Destination Name", NULL },
- { "printer-make-and-model", "Make and Model", NULL },
-
+ { "printer-make-and-model", "Make and Model", NULL, TRUE },
+
{ "Capabilities", NULL, NULL },
{ "printer-type", "#", __cups_callback_ptype },
-
+
{ "Printer State", NULL, NULL },
{ "printer-state", "State", __cups_callback_state },
{ "printer-state-change-time", "Change Time", __cups_callback_state_change_time },
{ "printer-state-reasons", "State Reasons" },
-
+
{ "Sharing Information", NULL, NULL },
{ "printer-is-shared", "Shared?", __cups_callback_boolean },
{ "printer-location", "Physical Location" },
{ "auth-info-required", "Authentication Required", __cups_callback_boolean },
-
+
{ "Jobs", NULL, NULL },
{ "job-hold-until", "Hold Until", NULL },
{ "job-priority", "Priority", NULL },
{ "printer-is-accepting-jobs", "Accepting Jobs", __cups_callback_boolean },
-
+
{ "Media", NULL, NULL },
{ "media", "Media", NULL },
{ "finishings", "Finishings", NULL },
@@ -176,7 +181,7 @@ const struct {
void
scan_printers_do(void)
{
- int num_dests, i, j;
+ guint num_dests, j, i;
CUPSDest *dests;
gchar *prn_id, *prn_moreinfo;
@@ -185,7 +190,7 @@ scan_printers_do(void)
if (!cups_init) {
init_cups();
-
+
printer_icons = g_strdup("");
printer_list = g_strdup(_("[Printers]\n"
"No suitable CUPS library found="));
@@ -201,22 +206,22 @@ scan_printers_do(void)
printer_icons = g_strdup("");
for (i = 0; i < num_dests; i++) {
GHashTable *options;
-
+
options = g_hash_table_new(g_str_hash, g_str_equal);
-
- for (j = 0; j < dests[i].num_options; j++) {
+
+ for (j = 0; (int)j < dests[i].num_options; j++) {
g_hash_table_insert(options,
g_strdup(dests[i].options[j].name),
g_strdup(dests[i].options[j].value));
}
-
+
prn_id = g_strdup_printf("PRN%d", i);
-
+
printer_list = h_strdup_cprintf("\n$%s$%s=%s\n",
printer_list,
- prn_id,
+ prn_id,
dests[i].name,
- dests[i].is_default ? "<i>Default</i>" : "");
+ dests[i].is_default ? ((params.markup_ok) ? "<i>Default</i>" : "(Default)") : "");
printer_icons = h_strdup_cprintf("\nIcon$%s$%s=printer.png",
printer_icons,
prn_id,
@@ -230,9 +235,9 @@ scan_printers_do(void)
cups_fields[j].key);
} else {
gchar *temp;
-
+
temp = g_hash_table_lookup(options, cups_fields[j].key);
-
+
if (cups_fields[j].callback) {
temp = cups_fields[j].callback(temp);
} else {
@@ -243,21 +248,22 @@ scan_printers_do(void)
temp = g_strdup(_("Unknown"));
}
}
-
- prn_moreinfo = h_strdup_cprintf("%s=%s\n",
+
+ prn_moreinfo = h_strdup_cprintf("%s%s=%s\n",
prn_moreinfo,
+ cups_fields[j].maybe_vendor ? "$^$" : "",
cups_fields[j].name,
temp);
-
+
g_free(temp);
}
}
-
+
moreinfo_add_with_prefix("DEV", prn_id, prn_moreinfo);
g_free(prn_id);
g_hash_table_destroy(options);
}
-
+
cups_dests_free(num_dests, dests);
} else {
printer_list = g_strdup(_("[Printers]\n"
diff --git a/modules/devices/resources.c b/modules/devices/resources.c
index 15cb8f21..c9d1ccb5 100644
--- a/modules/devices/resources.c
+++ b/modules/devices/resources.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2008 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2008 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -37,21 +37,27 @@ static gchar *_resource_obtain_name(gchar *name)
0, 0, NULL);
_regex_module = g_regex_new("^[0-9a-zA-Z\\_\\-]+$", 0, 0, NULL);
}
-
+
name = g_strstrip(name);
-
+
if (g_regex_match(_regex_pci, name, 0, NULL)) {
temp = module_call_method_param("devices::getPCIDeviceDescription", name);
if (temp) {
+ if (params.markup_ok)
return g_strdup_printf("<b><small>PCI</small></b> %s", (gchar *)idle_free(temp));
+ else
+ return g_strdup_printf("PCI %s", (gchar *)idle_free(temp));
}
} else if (g_regex_match(_regex_module, name, 0, NULL)) {
temp = module_call_method_param("computer::getKernelModuleDescription", name);
if (temp) {
+ if (params.markup_ok)
return g_strdup_printf("<b><small>Module</small></b> %s", (gchar *)idle_free(temp));
+ else
+ return g_strdup_printf("Module %s", (gchar *)idle_free(temp));
}
}
-
+
return g_strdup(name);
}
#else
@@ -66,7 +72,7 @@ void scan_device_resources(gboolean reload)
SCAN_START();
FILE *io;
gchar buffer[256];
- gint i;
+ guint i;
gint zero_to_zero_addr = 0;
struct {
@@ -77,10 +83,10 @@ void scan_device_resources(gboolean reload)
{ "/proc/iomem", "[Memory]\n" },
{ "/proc/dma", "[DMA]\n" }
};
-
+
g_free(_resources);
_resources = g_strdup("");
-
+
for (i = 0; i < G_N_ELEMENTS(resources); i++) {
if ((io = fopen(resources[i].file, "r"))) {
_resources = h_strconcat(_resources, resources[i].description, NULL);
@@ -92,8 +98,12 @@ void scan_device_resources(gboolean reload)
if (strstr(temp[0], "0000-0000"))
zero_to_zero_addr++;
- _resources = h_strdup_cprintf("<tt>%s</tt>=%s\n", _resources,
- temp[0], name);
+ if (params.markup_ok)
+ _resources = h_strdup_cprintf("<tt>%s</tt>=%s\n", _resources,
+ temp[0], name);
+ else
+ _resources = h_strdup_cprintf(">%s=%s\n", _resources,
+ temp[0], name);
g_strfreev(temp);
g_free(name);
diff --git a/modules/devices/riscv/processor.c b/modules/devices/riscv/processor.c
index afddf89d..f2e51c91 100644
--- a/modules/devices/riscv/processor.c
+++ b/modules/devices/riscv/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/riscv/riscv_data.c b/modules/devices/riscv/riscv_data.c
index 4ae68ef4..917e8e06 100644
--- a/modules/devices/riscv/riscv_data.c
+++ b/modules/devices/riscv/riscv_data.c
@@ -93,7 +93,7 @@ const char *riscv_ext_meaning(const char *ext) {
/* see RISC-V spec 2.2: Chapter 22: ISA Subset Naming Conventions */
-/* Spec says case-insensitve, but I prefer single-letter extensions
+/* Spec says case-insensitive, but I prefer single-letter extensions
* capped and version string (like "2p1") with a lowercase p. */
#define RV_FIX_CASE(fstr,vo) \
p = fstr; while (*p != 0 && *p != ':') { if (!vo) *p = toupper(*p); p++; } \
diff --git a/modules/devices/s390/processor.c b/modules/devices/s390/processor.c
index cf45c33c..e4f2b303 100644
--- a/modules/devices/s390/processor.c
+++ b/modules/devices/s390/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/sensors.c b/modules/devices/sensors.c
index c9d78ff7..095f0bc4 100644
--- a/modules/devices/sensors.c
+++ b/modules/devices/sensors.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,12 +22,21 @@
#include "expr.h"
#include "hardinfo.h"
#include "socket.h"
+#include "udisks2_util.h"
+
+#if defined(HAS_LIBSENSORS) && HAS_LIBSENSORS
+#include <sensors/sensors.h>
+#endif
gchar *sensors = NULL;
+gchar *sensor_icons = NULL;
GHashTable *sensor_compute = NULL;
GHashTable *sensor_labels = NULL;
+gboolean hwmon_first_run = TRUE;
+
+static gchar *last_group = NULL;
-static void read_sensor_labels(gchar *driver) {
+static void read_sensor_labels(gchar *devname) {
FILE *conf;
gchar buf[256], *line, *p;
gboolean lock = FALSE;
@@ -55,14 +64,14 @@ static void read_sensor_labels(gchar *driver) {
continue;
} else if (lock && strstr(line, "label")) { /* label lines */
gchar **names = g_strsplit(strstr(line, "label") + 5, " ", 0);
- gchar *name = NULL, *value = NULL;
+ gchar *key = NULL, *value = NULL;
for (i = 0; names[i]; i++) {
if (names[i][0] == '\0')
continue;
- if (!name)
- name = g_strdup(names[i]);
+ if (!key)
+ key = g_strdup_printf("%s/%s", devname, names[i]);
else if (!value)
value = g_strdup(names[i]);
else
@@ -70,7 +79,7 @@ static void read_sensor_labels(gchar *driver) {
}
remove_quotes(value);
- g_hash_table_insert(sensor_labels, name, value);
+ g_hash_table_insert(sensor_labels, key, g_strstrip(value));
g_strfreev(names);
} else if (lock && strstr(line, "ignore")) { /* ignore lines */
@@ -80,19 +89,18 @@ static void read_sensor_labels(gchar *driver) {
while (*p == ' ')
p++;
- g_hash_table_insert(sensor_labels, g_strdup(p), "ignore");
+ g_hash_table_insert(sensor_labels, g_strdup_printf("%s/%s", devname, p), "ignore");
} else if (lock && strstr(line, "compute")) { /* compute lines */
+ strend(line, ',');
gchar **formulas = g_strsplit(strstr(line, "compute") + 7, " ", 0);
- gchar *name = NULL, *formula = NULL;
+ gchar *key = NULL, *formula = NULL;
for (i = 0; formulas[i]; i++) {
if (formulas[i][0] == '\0')
continue;
- if (formulas[i][0] == ',')
- break;
- if (!name)
- name = g_strdup(formulas[i]);
+ if (!key)
+ key = g_strdup_printf("%s/%s", devname, formulas[i]);
else if (!formula)
formula = g_strdup(formulas[i]);
else
@@ -100,7 +108,7 @@ static void read_sensor_labels(gchar *driver) {
}
g_strfreev(formulas);
- g_hash_table_insert(sensor_compute, name,
+ g_hash_table_insert(sensor_compute, key,
math_string_to_postfix(formula));
} else if (g_str_has_prefix(line,
"chip")) { /* chip lines (delimiter) */
@@ -110,7 +118,7 @@ static void read_sensor_labels(gchar *driver) {
for (i = 1; chips[i]; i++) {
strend(chips[i], '*');
- if (g_str_has_prefix(chips[i] + 1, driver)) {
+ if (g_str_has_prefix(chips[i] + 1, devname)) {
lock = TRUE;
break;
}
@@ -128,36 +136,59 @@ static void read_sensor_labels(gchar *driver) {
static void add_sensor(const char *type,
const char *sensor,
- const char *driver,
+ const char *parent,
double value,
- const char *unit) {
+ const char *unit,
+ const char *icon) {
char key[64];
- sensors = h_strdup_cprintf("%s/%s=%.2f%s|%s\n", sensors,
- driver, sensor, value, unit, type);
+ snprintf(key, sizeof(key), "%s/%s", parent, sensor);
+
+ if (SENSORS_GROUP_BY_TYPE) {
+ // group by type
+ if (g_strcmp0(last_group, type) != 0) {
+ sensors = h_strdup_cprintf("[%s]\n", sensors, type);
+ g_free(last_group);
+ last_group = g_strdup(type);
+ }
+ sensors = h_strdup_cprintf("$%s$%s=%.2f%s|%s\n", sensors,
+ key, sensor, value, unit, parent);
+ }
+ else {
+ // group by device source / driver
+ if (g_strcmp0(last_group, parent) != 0) {
+ sensors = h_strdup_cprintf("[%s]\n", sensors, parent);
+ g_free(last_group);
+ last_group = g_strdup(parent);
+ }
+ sensors = h_strdup_cprintf("$%s$%s=%.2f%s|%s\n", sensors,
+ key, sensor, value, unit, type);
+ }
+
+ if (icon != NULL) {
+ sensor_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", sensor_icons,
+ key, sensor, icon);
+ }
- snprintf(key, sizeof(key), "%s/%s", driver, sensor);
moreinfo_add_with_prefix("DEV", key, g_strdup_printf("%.2f%s", value, unit));
lginterval = h_strdup_cprintf("UpdateInterval$%s=1000\n", lginterval, key);
}
-static gchar *get_sensor_label(gchar *sensor) {
+static gchar *get_sensor_label_from_conf(gchar *key) {
gchar *ret;
+ ret = g_hash_table_lookup(sensor_labels, key);
- ret = g_hash_table_lookup(sensor_labels, sensor);
- if (!ret)
- ret = g_strdup(sensor);
- else
- ret = g_strdup(ret);
+ if (ret)
+ return g_strdup(ret);
- return ret;
+ return NULL;
}
-static float adjust_sensor(gchar *name, float value) {
+static float adjust_sensor(gchar *key, float value) {
GSList *postfix;
- postfix = g_hash_table_lookup(sensor_compute, name);
+ postfix = g_hash_table_lookup(sensor_compute, key);
if (!postfix)
return value;
@@ -168,79 +199,137 @@ static char *get_sensor_path(int number, const char *prefix) {
return g_strdup_printf("/sys/class/hwmon/hwmon%d/%s", number, prefix);
}
-static char *determine_driver_for_hwmon_path(char *path) {
- char *tmp, *driver;
+static char *determine_devname_for_hwmon_path(char *path) {
+ char *tmp, *devname = NULL;
+
+ // device name
+ tmp = g_strdup_printf("%s/name", path);
+ g_file_get_contents(tmp, &devname, NULL, NULL);
+ g_free(tmp);
+ if (devname)
+ return g_strstrip(devname);
+ // fallback: driver name (from driver link)
tmp = g_strdup_printf("%s/device/driver", path);
- driver = g_file_read_link(tmp, NULL);
+ devname = g_file_read_link(tmp, NULL);
g_free(tmp);
- if (driver) {
- tmp = g_path_get_basename(driver);
- g_free(driver);
- driver = tmp;
- } else {
+ if (!devname) {
+ // fallback: device folder name (from device link)
tmp = g_strdup_printf("%s/device", path);
- driver = g_file_read_link(tmp, NULL);
+ devname = g_file_read_link(tmp, NULL);
g_free(tmp);
}
- if (!driver) {
- tmp = g_strdup_printf("%s/name", path);
- if (!g_file_get_contents(tmp, &driver, NULL, NULL)) {
- driver = g_strdup("unknown");
- } else {
- driver = g_strstrip(driver);
- }
- g_free(tmp);
+ if (devname) {
+ tmp = g_path_get_basename(devname);
+ g_free(devname);
+ return tmp;
}
- return driver;
+ return g_strdup("unknown");
}
struct HwmonSensor {
const char *friendly_name;
- const char *path_format;
+ const char *value_file_regex;
+ const char *value_path_format;
+ const char *label_path_format;
const char *key_format;
const char *unit;
const float adjust_ratio;
- const int begin_at;
+ const char *icon;
};
static const struct HwmonSensor hwmon_sensors[] = {
{
- "Fan",
+ "Fan Speed",
+ "^fan([0-9]+)_input$",
"%s/fan%d_input",
+ "%s/fan%d_label",
"fan%d",
- "RPM",
+ " RPM",
1.0,
- 1
+ "fan"
},
{
"Temperature",
+ "^temp([0-9]+)_input$",
"%s/temp%d_input",
+ "%s/temp%d_label",
"temp%d",
"\302\260C",
1000.0,
- 1
+ "therm"
},
{
"Voltage",
+ "^in([0-9]+)_input$",
"%s/in%d_input",
+ "%s/in%d_label",
"in%d",
"V",
1000.0,
- 0
+ "bolt"
+ },
+ {
+ "Current",
+ "^curr([0-9]+)_input$",
+ "%s/curr%d_input",
+ "%s/curr%d_label",
+ "curr%d",
+ " A",
+ 1000.0,
+ "bolt"
+ },
+ {
+ "Power",
+ "^power([0-9]+)_input$",
+ "%s/power%d_input",
+ "%s/power%d_label",
+ "power%d",
+ " W",
+ 1000000.0,
+ "bolt"
+ },
+ {
+ "CPU Voltage",
+ "^cpu([0-9]+)_vid$",
+ "%s/cpu%d_vid",
+ NULL,
+ "cpu%d_vid",
+ " V",
+ 1000.0,
+ "bolt"
},
{ }
};
static const char *hwmon_prefix[] = {"device", "", NULL};
+static gboolean read_raw_hwmon_value(gchar *path_hwmon, const gchar *item_path_format, int item_id, gchar **result){
+ gchar *full_path;
+ gboolean file_result;
+
+ if (item_path_format == NULL)
+ return FALSE;
+
+ full_path = g_strdup_printf(item_path_format, path_hwmon, item_id);
+ file_result = g_file_get_contents(full_path, result, NULL, NULL);
+
+ g_free(full_path);
+
+ return file_result;
+}
+
static void read_sensors_hwmon(void) {
- int hwmon, count;
- gchar *path_hwmon, *path_sensor, *tmp, *driver, *name, *mon;
- const char **prefix;
+ int hwmon, count, min, max;
+ gchar *path_hwmon, *tmp, *devname, *name, *mon, *key;
+ const char **prefix, *entry;
+ GDir *dir;
+ GRegex *regex;
+ GMatchInfo *match_info;
+ GError *err = NULL;
for (prefix = hwmon_prefix; *prefix; prefix++) {
hwmon = 0;
@@ -248,56 +337,92 @@ static void read_sensors_hwmon(void) {
while (path_hwmon && g_file_test(path_hwmon, G_FILE_TEST_EXISTS)) {
const struct HwmonSensor *sensor;
- driver = determine_driver_for_hwmon_path(path_hwmon);
- DEBUG("hwmon%d has driver=%s", hwmon, driver);
-
- if (!sensor_labels) {
- read_sensor_labels(driver);
+ devname = determine_devname_for_hwmon_path(path_hwmon);
+ DEBUG("hwmon%d has device=%s", hwmon, devname);
+ if (hwmon_first_run) {
+ read_sensor_labels(devname);
}
+ dir = g_dir_open(path_hwmon, 0, NULL);
+ if (!dir)
+ continue;
+
for (sensor = hwmon_sensors; sensor->friendly_name; sensor++) {
DEBUG("current sensor type=%s", sensor->friendly_name);
+ regex = g_regex_new (sensor->value_file_regex, 0, 0, &err);
+ if (err != NULL){
+ g_free(err);
+ err = NULL;
+ continue;
+ }
- for (count = sensor->begin_at;; count++) {
- path_sensor =
- g_strdup_printf(sensor->path_format, path_hwmon, count);
- DEBUG("should be reading from %s", path_sensor);
- if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL)) {
- g_free(path_sensor);
- if (count < 256)
- continue; // brute-force find all
- else
- break;
+ g_dir_rewind(dir);
+ min = 999;
+ max = -1;
+
+ while ((entry = g_dir_read_name(dir))) {
+ g_regex_match(regex, entry, 0, &match_info);
+ if (g_match_info_matches(match_info)) {
+ tmp = g_match_info_fetch(match_info, 1);
+ count = atoi(tmp);
+ g_free (tmp);
+
+ if (count < min){
+ min = count;
+ }
+ if (count > max){
+ max = count;
+ }
+ }
+ g_match_info_free(match_info);
+ }
+ g_regex_unref(regex);
+
+ for (count = min; count <= max; count++) {
+ if (!read_raw_hwmon_value(path_hwmon, sensor->value_path_format, count, &tmp)) {
+ continue;
}
mon = g_strdup_printf(sensor->key_format, count);
- name = get_sensor_label(mon);
+ key = g_strdup_printf("%s/%s", devname, mon);
+ name = get_sensor_label_from_conf(key);
+ if (name == NULL){
+ if (read_raw_hwmon_value(path_hwmon, sensor->label_path_format, count, &name)){
+ name = g_strchomp(name);
+ }
+ else{
+ name = g_strdup(mon);
+ }
+ }
+
if (!g_str_equal(name, "ignore")) {
- float adjusted = adjust_sensor(mon,
+ float adjusted = adjust_sensor(key,
atof(tmp) / sensor->adjust_ratio);
add_sensor(sensor->friendly_name,
name,
- driver,
+ devname,
adjusted,
- sensor->unit);
+ sensor->unit,
+ sensor->icon);
}
g_free(tmp);
g_free(mon);
+ g_free(key);
g_free(name);
- g_free(path_sensor);
}
}
+ g_dir_close(dir);
g_free(path_hwmon);
- g_free(driver);
+ g_free(devname);
path_hwmon = get_sensor_path(++hwmon, *prefix);
}
-
g_free(path_hwmon);
}
+ hwmon_first_run = FALSE;
}
static void read_sensors_acpi(void) {
@@ -323,7 +448,8 @@ static void read_sensors_acpi(void) {
entry,
"ACPI Thermal Zone",
temperature,
- "\302\260C");
+ "\302\260C",
+ "therm");
}
}
@@ -332,6 +458,78 @@ static void read_sensors_acpi(void) {
}
}
+// Sensors for Apple PowerPC devices using Windfarm driver.
+struct WindfarmSensorType {
+ const char *type;
+ const char *icon;
+ const char *file_regex;
+ const char *unit;
+ gboolean with_decimal_p;
+};
+static const struct WindfarmSensorType windfarm_sensor_types[] = {
+ {"Fan", "fan", "^[a-z-]+-fan(-[0-9]+)?$", " RPM", FALSE},
+ {"Temperature", "therm", "^[a-z-]+-temp(-[0-9]+)?$", "\302\260C", TRUE},
+ {"Power", "bolt", "^[a-z-]+-power(-[0-9]+)?$", " W", TRUE},
+ {"Current", "bolt", "^[a-z-]+-current(-[0-9]+)?$", " A", TRUE},
+ {"Voltage", "bolt", "^[a-z-]+-voltage(-[0-9]+)?$", " V", TRUE},
+ { }
+};
+static void read_sensors_windfarm(void)
+{
+ const gchar *path_wf = "/sys/devices/platform/windfarm.0";
+ GDir *wf;
+ gchar *tmp = NULL;
+ gint v1, v2;
+ double value;
+
+ wf = g_dir_open(path_wf, 0, NULL);
+ if (wf) {
+ GRegex *regex;
+ GError *err = NULL;
+ const gchar *entry;
+ const struct WindfarmSensorType *sensor;
+
+ for (sensor = windfarm_sensor_types; sensor->type; sensor++) {
+ DEBUG("current windfarm sensor type=%s", sensor->type);
+ regex = g_regex_new(sensor->file_regex, 0, 0, &err);
+ if (err != NULL) {
+ g_free(err);
+ err = NULL;
+ continue;
+ }
+
+ g_dir_rewind(wf);
+
+ while ((entry = g_dir_read_name(wf))) {
+ if (g_regex_match(regex, entry, 0, NULL)) {
+ gchar *path = g_strdup_printf("%s/%s", path_wf, entry);
+ if (g_file_get_contents(path, &tmp, NULL, NULL)) {
+
+ if (sensor->with_decimal_p) {
+ // format source
+ // https://elixir.free-electrons.com/linux/v5.14/source/drivers/macintosh/windfarm_core.c#L301
+ sscanf(tmp, "%d.%03d", &v1, &v2);
+ value = v1 + (v2 / 1000.0);
+ } else {
+ value = (double)atoi(tmp);
+ }
+ g_free(tmp);
+
+ tmp = g_strdup(entry);
+ add_sensor(sensor->type, g_strdelimit(tmp, "-", ' '),
+ "windfarm", value, sensor->unit,
+ sensor->icon);
+ g_free(tmp);
+ }
+ g_free(path);
+ }
+ }
+ g_regex_unref(regex);
+ }
+ g_dir_close(wf);
+ }
+}
+
static void read_sensors_sys_thermal(void) {
const gchar *path_tz = "/sys/class/thermal";
@@ -355,7 +553,8 @@ static void read_sensors_sys_thermal(void) {
entry,
"thermal",
temperature / 1000.0,
- "\302\260C");
+ "\302\260C",
+ "therm");
g_free(contents);
}
@@ -379,7 +578,8 @@ static void read_sensors_omnibook(void) {
"CPU",
"omnibook",
temperature,
- "\302\260C\n");
+ "\302\260C",
+ "therm");
g_free(contents);
}
@@ -401,7 +601,7 @@ static void read_sensors_hddtemp(void) {
gchar **disks;
int i;
- disks = g_strsplit(buffer, "\n", 0);
+ disks = g_strsplit(buffer, "||", 0);
for (i = 0; disks[i]; i++) {
gchar **fields = g_strsplit(disks[i] + 1, "|", 5);
@@ -412,12 +612,13 @@ static void read_sensors_hddtemp(void) {
* 3 -> C
*/
const gchar *unit = strcmp(fields[3], "C")
- ? "\302\260C" : "\302\260F";
- add_sensor("Hard Drive",
+ ? "\302\260F" : "\302\260C";
+ add_sensor("Drive Temperature",
fields[1],
"hddtemp",
atoi(fields[2]),
- unit);
+ unit,
+ "therm");
g_strfreev(fields);
}
@@ -426,28 +627,144 @@ static void read_sensors_hddtemp(void) {
}
}
+static void read_sensors_udisks2(void) {
+ GSList *node;
+ GSList *temps;
+ udiskt *disk;
+
+ temps = get_udisks2_temps();
+ if (temps == NULL)
+ return;
+
+ for (node = temps; node != NULL; node = node->next) {
+ disk = (udiskt *)node->data;
+ add_sensor("Drive Temperature",
+ disk->drive,
+ "udisks2",
+ disk->temperature,
+ "\302\260C",
+ "therm");
+ udiskt_free(disk);
+ }
+ g_slist_free(temps);
+}
+
+#if HAS_LIBSENSORS
+static const struct libsensors_feature_type {
+ const char *type_name;
+ const char *icon;
+ const char *unit;
+ sensors_subfeature_type input;
+} libsensors_feature_types[SENSORS_FEATURE_MAX] = {
+ [SENSORS_FEATURE_FAN] = {"Fan", "fan", "RPM",
+ SENSORS_SUBFEATURE_FAN_INPUT},
+ [SENSORS_FEATURE_TEMP] = {"Temperature", "therm", "\302\260C",
+ SENSORS_SUBFEATURE_TEMP_INPUT},
+ [SENSORS_FEATURE_POWER] = {"Power", "bolt", "W",
+ SENSORS_SUBFEATURE_POWER_INPUT},
+ [SENSORS_FEATURE_CURR] = {"Current", "bolt", "A",
+ SENSORS_SUBFEATURE_CURR_INPUT},
+ [SENSORS_FEATURE_IN] = {"Voltage", "bolt", "V",
+ SENSORS_SUBFEATURE_IN_INPUT},
+ [SENSORS_FEATURE_VID] = {"CPU Voltage", "bolt", "V",
+ SENSORS_SUBFEATURE_VID},
+};
+static gboolean libsensors_initialized;
+
+static int read_sensors_libsensors(void) {
+ char chip_name_buf[512];
+ const sensors_chip_name *name;
+ int chip_nr = 0;
+ int added_sensors = 0;
+
+ if (!libsensors_initialized)
+ return 0;
+
+ while ((name = sensors_get_detected_chips(NULL, &chip_nr))) {
+ const struct sensors_feature *feat;
+ int feat_nr = 0;
+
+ sensors_snprintf_chip_name(chip_name_buf, 512, name);
+
+ while ((feat = sensors_get_features(name, &feat_nr))) {
+ const struct libsensors_feature_type *feat_descr;
+ const struct sensors_subfeature *subfeat;
+ double value;
+
+ feat_descr = &libsensors_feature_types[feat->type];
+ if (!feat_descr->type_name)
+ continue;
+
+ subfeat = sensors_get_subfeature(name, feat, feat_descr->input);
+ if (!subfeat)
+ continue;
+
+ if (!sensors_get_value(name, subfeat->number, &value)) {
+ char *label = sensors_get_label(name, feat);
+ gchar *label_with_chip = g_strdup_printf("%s (%s)", label, chip_name_buf);
+
+ add_sensor(feat_descr->type_name,
+ label_with_chip,
+ "libsensors",
+ value,
+ feat_descr->unit,
+ feat_descr->icon);
+
+ free(label_with_chip);
+ free(label);
+
+ added_sensors++;
+ }
+ }
+ }
+
+ return added_sensors;
+}
+#else
+static int read_sensors_libsensors(void)
+{
+ return 0;
+}
+#endif
+
void scan_sensors_do(void) {
g_free(sensors);
+ g_free(sensor_icons);
+ g_free(last_group);
+ last_group = NULL;
sensors = g_strdup("");
+ sensor_icons = g_strdup("");
g_free(lginterval);
lginterval = g_strdup("");
- read_sensors_hwmon();
- read_sensors_acpi();
- read_sensors_sys_thermal();
- read_sensors_omnibook();
+ if (read_sensors_libsensors() == 0) {
+ read_sensors_hwmon();
+ read_sensors_acpi();
+ read_sensors_sys_thermal();
+ read_sensors_omnibook();
+ }
+
+ read_sensors_windfarm();
read_sensors_hddtemp();
- /* FIXME: Add support for ibm acpi and more sensors */
+ read_sensors_udisks2();
}
-void sensors_init(void) {
+void sensor_init(void) {
+#if HAS_LIBSENSORS
+ libsensors_initialized = sensors_init(NULL) == 0;
+#endif
+
sensor_labels =
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
sensor_compute = g_hash_table_new(g_str_hash, g_str_equal);
}
-void sensors_shutdown(void) {
+void sensor_shutdown(void) {
+#if HAS_LIBSENSORS
+ sensors_cleanup();
+#endif
+
g_hash_table_destroy(sensor_labels);
g_hash_table_destroy(sensor_compute);
}
diff --git a/modules/devices/sh/processor.c b/modules/devices/sh/processor.c
index 9da2f9b0..a5ce3e0a 100644
--- a/modules/devices/sh/processor.c
+++ b/modules/devices/sh/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/sparc/processor.c b/modules/devices/sparc/processor.c
index 32c7aa94..76f4b0e0 100644
--- a/modules/devices/sparc/processor.c
+++ b/modules/devices/sparc/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/devices/spd-decode.c b/modules/devices/spd-decode.c
index 2db4895b..511504b2 100644
--- a/modules/devices/spd-decode.c
+++ b/modules/devices/spd-decode.c
@@ -1,6 +1,8 @@
/*
- * spd-decode.c
- * Copyright (c) 2010 Leandro A. F. Pereira
+ * spd-decode.c, spd-vendors.c
+ * Copyright (c) 2010 L. A. F. Pereira
+ * modified by Ondrej Čerman (2019)
+ * modified by Burt P. (2019)
*
* Based on decode-dimms.pl
* Copyright 1998, 1999 Philip Edelbrock <phil@netroedge.com>
@@ -27,602 +29,91 @@
#include <stdio.h>
#include <sys/stat.h>
-#include "hardinfo.h"
#include "devices.h"
+#include "hardinfo.h"
+
+gboolean spd_no_driver = FALSE;
+gboolean spd_no_support = FALSE;
+gboolean spd_ddr4_partial_data = FALSE;
+int spd_ram_types = 0; /* bits using enum RamType */
typedef enum {
- UNKNOWN,
- DIRECT_RAMBUS,
- RAMBUS,
- FPM_DRAM,
- EDO,
- PIPELINED_NIBBLE,
- SDR_SDRAM,
- MULTIPLEXED_ROM,
- DDR_SGRAM,
- DDR_SDRAM,
- DDR2_SDRAM,
- DDR3_SDRAM
+ UNKNOWN = 0,
+ DIRECT_RAMBUS = 1,
+ RAMBUS = 2,
+ FPM_DRAM = 3,
+ EDO = 4,
+ PIPELINED_NIBBLE = 5,
+ SDR_SDRAM = 6,
+ MULTIPLEXED_ROM = 7,
+ DDR_SGRAM = 8,
+ DDR_SDRAM = 9,
+ DDR2_SDRAM = 10,
+ DDR3_SDRAM = 11,
+ DDR4_SDRAM = 12,
+ N_RAM_TYPES = 13
} 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"
-};
+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",
+ "DDR4 SDRAM"};
+#define GET_RAM_TYPE_STR(rt) (ram_types[(rt < N_RAM_TYPES) ? rt : 0])
-static const char *vendors1[] = { "AMD", "AMI", "Fairchild", "Fujitsu",
- "GTE", "Harris", "Hitachi", "Inmos",
- "Intel", "I.T.T.", "Intersil",
- "Monolithic Memories",
- "Mostek",
- "Freescale (former Motorola)",
- "National", "NEC",
- "RCA", "Raytheon",
- "Conexant (Rockwell)", "Seeq",
- "NXP (former Signetics, Philips Semi.)",
- "Synertek",
- "Texas Instruments", "Toshiba",
- "Xicor", "Zilog", "Eurotechnique",
- "Mitsubishi",
- "Lucent (AT&T)", "Exel", "Atmel",
- "SGS/Thomson",
- "Lattice Semi.", "NCR",
- "Wafer Scale Integration", "IBM",
- "Tristar", "Visic",
- "Intl. CMOS Technology", "SSSI",
- "MicrochipTechnology", "Ricoh Ltd.",
- "VLSI", "Micron Technology",
- "Hyundai Electronics",
- "OKI Semiconductor", "ACTEL",
- "Sharp",
- "Catalyst", "Panasonic", "IDT",
- "Cypress",
- "DEC", "LSI Logic",
- "Zarlink (former Plessey)", "UTMC",
- "Thinking Machine", "Thomson CSF",
- "Integrated CMOS (Vertex)",
- "Honeywell",
- "Tektronix", "Sun Microsystems",
- "SST", "ProMos/Mosel Vitelic",
- "Infineon (former Siemens)",
- "Macronix", "Xerox", "Plus Logic",
- "SunDisk", "Elan Circuit Tech.",
- "European Silicon Str.",
- "Apple Computer",
- "Xilinx", "Compaq",
- "Protocol Engines", "SCI",
- "Seiko Instruments", "Samsung",
- "I3 Design System", "Klic",
- "Crosspoint Solutions",
- "Alliance Semiconductor", "Tandem",
- "Hewlett-Packard",
- "Intg. Silicon Solutions",
- "Brooktree", "New Media",
- "MHS Electronic",
- "Performance Semi.",
- "Winbond Electronic",
- "Kawasaki Steel",
- "Bright Micro",
- "TECMAR", "Exar", "PCMCIA",
- "LG Semi (former Goldstar)",
- "Northern Telecom", "Sanyo",
- "Array Microsystems",
- "Crystal Semiconductor",
- "Analog Devices", "PMC-Sierra",
- "Asparix", "Convex Computer",
- "Quality Semiconductor",
- "Nimbus Technology", "Transwitch",
- "Micronas (ITT Intermetall)",
- "Cannon", "Altera", "NEXCOM",
- "QUALCOMM",
- "Sony", "Cray Research",
- "AMS(Austria Micro)", "Vitesse",
- "Aster Electronics",
- "Bay Networks (Synoptic)",
- "Zentrum or ZMD",
- "TRW",
- "Thesys", "Solbourne Computer",
- "Allied-Signal", "Dialog",
- "Media Vision",
- "Level One Communication"
-};
+#include "spd-vendors.c"
-static const char *vendors2[] = { "Cirrus Logic",
- "National Instruments",
- "ILC Data Device",
- "Alcatel Mietec",
- "Micro Linear",
- "Univ. of NC",
- "JTAG Technologies",
- "BAE Systems",
- "Nchip",
- "Galileo Tech",
- "Bestlink Systems",
- "Graychip",
- "GENNUM",
- "VideoLogic",
- "Robert Bosch",
- "Chip Express",
- "DATARAM",
- "United Microelec Corp.",
- "TCSI",
- "Smart Modular",
- "Hughes Aircraft",
- "Lanstar Semiconductor",
- "Qlogic", "Kingston",
- "Music Semi",
- "Ericsson Components",
- "SpaSE",
- "Eon Silicon Devices",
- "Programmable Micro Corp",
- "DoD",
- "Integ. Memories Tech.",
- "Corollary Inc.",
- "Dallas Semiconductor",
- "Omnivision",
- "EIV(Switzerland)",
- "Novatel Wireless",
- "Zarlink (former Mitel)",
- "Clearpoint",
- "Cabletron",
- "STEC (former Silicon Technology)",
- "Vanguard",
- "Hagiwara Sys-Com",
- "Vantis", "Celestica",
- "Century",
- "Hal Computers",
- "Rohm Company Ltd.",
- "Juniper Networks",
- "Libit Signal Processing",
- "Mushkin Enhanced Memory",
- "Tundra Semiconductor",
- "Adaptec Inc.",
- "LightSpeed Semi.",
- "ZSP Corp.",
- "AMIC Technology",
- "Adobe Systems",
- "Dynachip",
- "PNY Electronics",
- "Newport Digital",
- "MMC Networks",
- "T Square",
- "Seiko Epson",
- "Broadcom",
- "Viking Components",
- "V3 Semiconductor",
- "Flextronics (former Orbit)",
- "Suwa Electronics",
- "Transmeta",
- "Micron CMS",
- "American Computer & Digital Components Inc",
- "Enhance 3000 Inc",
- "Tower Semiconductor",
- "CPU Design",
- "Price Point",
- "Maxim Integrated Product",
- "Tellabs",
- "Centaur Technology",
- "Unigen Corporation",
- "Transcend Information",
- "Memory Card Technology",
- "CKD Corporation Ltd.",
- "Capital Instruments, Inc.",
- "Aica Kogyo, Ltd.",
- "Linvex Technology",
- "MSC Vertriebs GmbH",
- "AKM Company, Ltd.",
- "Dynamem, Inc.",
- "NERA ASA",
- "GSI Technology",
- "Dane-Elec (C Memory)",
- "Acorn Computers",
- "Lara Technology",
- "Oak Technology, Inc.",
- "Itec Memory",
- "Tanisys Technology",
- "Truevision",
- "Wintec Industries",
- "Super PC Memory",
- "MGV Memory",
- "Galvantech",
- "Gadzoox Nteworks",
- "Multi Dimensional Cons.",
- "GateField",
- "Integrated Memory System",
- "Triscend", "XaQti",
- "Goldenram",
- "Clear Logic",
- "Cimaron Communications",
- "Nippon Steel Semi. Corp.",
- "Advantage Memory",
- "AMCC",
- "LeCroy",
- "Yamaha Corporation",
- "Digital Microwave",
- "NetLogic Microsystems",
- "MIMOS Semiconductor",
- "Advanced Fibre",
- "BF Goodrich Data.",
- "Epigram",
- "Acbel Polytech Inc.",
- "Apacer Technology",
- "Admor Memory",
- "FOXCONN",
- "Quadratics Superconductor",
- "3COM",
-};
+struct dmi_mem_socket;
+typedef struct {
+ unsigned char bytes[512];
+ char dev[32]; /* %1d-%04d\0 */
+ const char *spd_driver;
+ int spd_size;
-static const char *vendors3[] = { "Camintonn Corporation", "ISOA Incorporated",
- "Agate Semiconductor", "ADMtek Incorporated",
- "HYPERTEC", "Adhoc Technologies", "MOSAID Technologies",
- "Ardent Technologies",
- "Switchcore", "Cisco Systems, Inc.", "Allayer Technologies",
- "WorkX AG",
- "Oasis Semiconductor", "Novanet Semiconductor", "E-M Solutions",
- "Power General",
- "Advanced Hardware Arch.", "Inova Semiconductors GmbH", "Telocity",
- "Delkin Devices",
- "Symagery Microsystems", "C-Port Corporation",
- "SiberCore Technologies", "Southland Microsystems",
- "Malleable Technologies", "Kendin Communications",
- "Great Technology Microcomputer", "Sanmina Corporation",
- "HADCO Corporation", "Corsair", "Actrans System Inc.",
- "ALPHA Technologies",
- "Silicon Laboratories, Inc. (Cygnal)", "Artesyn Technologies",
- "Align Manufacturing", "Peregrine Semiconductor",
- "Chameleon Systems", "Aplus Flash Technology", "MIPS Technologies",
- "Chrysalis ITS",
- "ADTEC Corporation", "Kentron Technologies", "Win Technologies",
- "Tachyon Semiconductor (former ASIC Designs Inc.)",
- "Extreme Packet Devices", "RF Micro Devices", "Siemens AG",
- "Sarnoff Corporation",
- "Itautec Philco SA", "Radiata Inc.", "Benchmark Elect. (AVEX)",
- "Legend",
- "SpecTek Incorporated", "Hi/fn", "Enikia Incorporated",
- "SwitchOn Networks",
- "AANetcom Incorporated", "Micro Memory Bank", "ESS Technology",
- "Virata Corporation",
- "Excess Bandwidth", "West Bay Semiconductor", "DSP Group",
- "Newport Communications",
- "Chip2Chip Incorporated", "Phobos Corporation",
- "Intellitech Corporation", "Nordic VLSI ASA",
- "Ishoni Networks", "Silicon Spice", "Alchemy Semiconductor",
- "Agilent Technologies",
- "Centillium Communications", "W.L. Gore", "HanBit Electronics",
- "GlobeSpan",
- "Element 14", "Pycon", "Saifun Semiconductors", "Sibyte, Incorporated",
- "MetaLink Technologies", "Feiya Technology", "I & C Technology",
- "Shikatronics",
- "Elektrobit", "Megic", "Com-Tier", "Malaysia Micro Solutions",
- "Hyperchip", "Gemstone Communications", "Anadigm (former Anadyne)",
- "3ParData",
- "Mellanox Technologies", "Tenx Technologies", "Helix AG", "Domosys",
- "Skyup Technology", "HiNT Corporation", "Chiaro",
- "MDT Technologies GmbH (former MCI Computer GMBH)",
- "Exbit Technology A/S", "Integrated Technology Express", "AVED Memory",
- "Legerity",
- "Jasmine Networks", "Caspian Networks", "nCUBE",
- "Silicon Access Networks",
- "FDK Corporation", "High Bandwidth Access", "MultiLink Technology",
- "BRECIS",
- "World Wide Packets", "APW", "Chicory Systems", "Xstream Logic",
- "Fast-Chip", "Zucotto Wireless", "Realchip", "Galaxy Power",
- "eSilicon", "Morphics Technology", "Accelerant Networks",
- "Silicon Wave",
- "SandCraft", "Elpida"
-};
+ RamType type;
-static const char *vendors4[] = { "Solectron", "Optosys Technologies",
- "Buffalo (former Melco)",
- "TriMedia Technologies",
- "Cyan Technologies", "Global Locate",
- "Optillion",
- "Terago Communications",
- "Ikanos Communications",
- "Princeton Technology",
- "Nanya Technology",
- "Elite Flash Storage",
- "Mysticom", "LightSand Communications",
- "ATI Technologies",
- "Agere Systems",
- "NeoMagic", "AuroraNetics", "Golden Empire",
- "Mushkin",
- "Tioga Technologies", "Netlist", "TeraLogic",
- "Cicada Semiconductor",
- "Centon Electronics", "Tyco Electronics",
- "Magis Works", "Zettacom",
- "Cogency Semiconductor", "Chipcon AS",
- "Aspex Technology",
- "F5 Networks",
- "Programmable Silicon Solutions",
- "ChipWrights",
- "Acorn Networks",
- "Quicklogic",
- "Kingmax Semiconductor", "BOPS", "Flasys",
- "BitBlitz Communications",
- "eMemory Technology", "Procket Networks",
- "Purple Ray",
- "Trebia Networks",
- "Delta Electronics", "Onex Communications",
- "Ample Communications",
- "Memory Experts Intl",
- "Astute Networks", "Azanda Network Devices",
- "Dibcom", "Tekmos",
- "API NetWorks", "Bay Microsystems",
- "Firecron Ltd",
- "Resonext Communications",
- "Tachys Technologies", "Equator Technology",
- "Concept Computer",
- "SILCOM",
- "3Dlabs", "c't Magazine", "Sanera Systems",
- "Silicon Packets",
- "Viasystems Group", "Simtek",
- "Semicon Devices Singapore",
- "Satron Handelsges",
- "Improv Systems", "INDUSYS GmbH", "Corrent",
- "Infrant Technologies",
- "Ritek Corp", "empowerTel Networks",
- "Hypertec",
- "Cavium Networks",
- "PLX Technology", "Massana Design",
- "Intrinsity",
- "Valence Semiconductor",
- "Terawave Communications",
- "IceFyre Semiconductor", "Primarion",
- "Picochip Designs Ltd",
- "Silverback Systems",
- "Jade Star Technologies",
- "Pijnenburg Securealink",
- "TakeMS International AG",
- "Cambridge Silicon Radio",
- "Swissbit", "Nazomi Communications",
- "eWave System",
- "Rockwell Collins", "Picocel Co., Ltd.",
- "Alphamosaic Ltd",
- "Sandburst",
- "SiCon Video", "NanoAmp Solutions",
- "Ericsson Technology",
- "PrairieComm",
- "Mitac International", "Layer N Networks",
- "MtekVision",
- "Allegro Networks",
- "Marvell Semiconductors",
- "Netergy Microelectronic", "NVIDIA",
- "Internet Machines",
- "Peak Electronics",
- "Litchfield Communication",
- "Accton Technology",
- "Teradiant Networks",
- "Europe Technologies", "Cortina Systems",
- "RAM Components",
- "Raqia Networks",
- "ClearSpeed", "Matsushita Battery",
- "Xelerated",
- "SimpleTech",
- "Utron Technology", "Astec International",
- "AVM gmbH",
- "Redux Communications",
- "Dot Hill Systems", "TeraChip"
-};
+ int vendor_bank;
+ int vendor_index;
+ const char *vendor_str;
+ const Vendor *vendor;
-static const char *vendors5[] = { "T-RAM Incorporated",
- "Innovics Wireless", "Teknovus", "KeyEye Communications",
- "Runcom Technologies", "RedSwitch", "Dotcast",
- "Silicon Mountain Memory",
- "Signia Technologies", "Pixim", "Galazar Networks",
- "White Electronic Designs",
- "Patriot Scientific", "Neoaxiom Corporation", "3Y Power Technology",
- "Europe Technologies",
- "Potentia Power Systems", "C-guys Incorporated",
- "Digital Communications Technology Incorporated",
- "Silicon-Based Technology",
- "Fulcrum Microsystems", "Positivo Informatica Ltd",
- "XIOtech Corporation", "PortalPlayer",
- "Zhiying Software", "Direct2Data", "Phonex Broadband",
- "Skyworks Solutions",
- "Entropic Communications", "Pacific Force Technology", "Zensys A/S",
- "Legend Silicon Corp.",
- "sci-worx GmbH", "SMSC (former Oasis Silicon Systems)",
- "Renesas Technology", "Raza Microelectronics",
- "Phyworks", "MediaTek", "Non-cents Productions", "US Modular",
- "Wintegra Ltd", "Mathstar", "StarCore", "Oplus Technologies",
- "Mindspeed", "Just Young Computer", "Radia Communications", "OCZ",
- "Emuzed", "LOGIC Devices", "Inphi Corporation", "Quake Technologies",
- "Vixel", "SolusTek", "Kongsberg Maritime", "Faraday Technology",
- "Altium Ltd.", "Insyte", "ARM Ltd.", "DigiVision",
- "Vativ Technologies", "Endicott Interconnect Technologies", "Pericom",
- "Bandspeed",
- "LeWiz Communications", "CPU Technology", "Ramaxel Technology",
- "DSP Group",
- "Axis Communications", "Legacy Electronics", "Chrontel",
- "Powerchip Semiconductor",
- "MobilEye Technologies", "Excel Semiconductor", "A-DATA Technology",
- "VirtualDigm",
- "G Skill Intl", "Quanta Computer", "Yield Microelectronics",
- "Afa Technologies",
- "KINGBOX Technology Co. Ltd.", "Ceva", "iStor Networks",
- "Advance Modules",
- "Microsoft", "Open-Silicon", "Goal Semiconductor",
- "ARC International",
- "Simmtec", "Metanoia", "Key Stream", "Lowrance Electronics",
- "Adimos", "SiGe Semiconductor", "Fodus Communications",
- "Credence Systems Corp.",
- "Genesis Microchip Inc.", "Vihana, Inc.", "WIS Technologies",
- "GateChange Technologies",
- "High Density Devices AS", "Synopsys", "Gigaram",
- "Enigma Semiconductor Inc.",
- "Century Micro Inc.", "Icera Semiconductor",
- "Mediaworks Integrated Systems", "O'Neil Product Development",
- "Supreme Top Technology Ltd.", "MicroDisplay Corporation",
- "Team Group Inc.", "Sinett Corporation",
- "Toshiba Corporation", "Tensilica", "SiRF Technology", "Bacoc Inc.",
- "SMaL Camera Technologies", "Thomson SC", "Airgo Networks",
- "Wisair Ltd.",
- "SigmaTel", "Arkados", "Compete IT gmbH Co. KG",
- "Eudar Technology Inc.",
- "Focus Enhancements", "Xyratex"
-};
+ int dram_vendor_bank;
+ int dram_vendor_index;
+ const char *dram_vendor_str;
+ const Vendor *dram_vendor;
-static const char *vendors6[] = { "Specular Networks",
- "Patriot Memory",
- "U-Chip Technology Corp.",
- "Silicon Optix",
- "Greenfield Networks",
- "CompuRAM GmbH", "Stargen, Inc.",
- "NetCell Corporation",
- "Excalibrus Technologies Ltd",
- "SCM Microsystems",
- "Xsigo Systems, Inc.",
- "CHIPS & Systems Inc",
- "Tier 1 Multichip Solutions",
- "CWRL Labs", "Teradici",
- "Gigaram, Inc.",
- "g2 Microsystems",
- "PowerFlash Semiconductor",
- "P.A. Semi, Inc.",
- "NovaTech Solutions, S.A.",
- "c2 Microsystems, Inc.",
- "Level5 Networks",
- "COS Memory AG",
- "Innovasic Semiconductor",
- "02IC Co. Ltd", "Tabula, Inc.",
- "Crucial Technology",
- "Chelsio Communications",
- "Solarflare Communications",
- "Xambala Inc.", "EADS Astrium",
- "ATO Semicon Co. Ltd.",
- "Imaging Works, Inc.",
- "Astute Networks, Inc.", "Tzero",
- "Emulex",
- "Power-One", "Pulse~LINK Inc.",
- "Hon Hai Precision Industry",
- "White Rock Networks Inc.",
- "Telegent Systems USA, Inc.",
- "Atrua Technologies, Inc.",
- "Acbel Polytech Inc.",
- "eRide Inc.",
- "ULi Electronics Inc.",
- "Magnum Semiconductor Inc.",
- "neoOne Technology, Inc.",
- "Connex Technology, Inc.",
- "Stream Processors, Inc.",
- "Focus Enhancements",
- "Telecis Wireless, Inc.",
- "uNav Microelectronics",
- "Tarari, Inc.", "Ambric, Inc.",
- "Newport Media, Inc.", "VMTS",
- "Enuclia Semiconductor, Inc.",
- "Virtium Technology Inc.",
- "Solid State System Co., Ltd.",
- "Kian Tech LLC",
- "Artimi",
- "Power Quotient International",
- "Avago Technologies",
- "ADTechnology", "Sigma Designs",
- "SiCortex, Inc.",
- "Ventura Technology Group",
- "eASIC", "M.H.S. SAS",
- "Micro Star International",
- "Rapport Inc.",
- "Makway International",
- "Broad Reach Engineering Co.",
- "Semiconductor Mfg Intl Corp",
- "SiConnect", "FCI USA Inc.",
- "Validity Sensors",
- "Coney Technology Co. Ltd.",
- "Spans Logic", "Neterion Inc.",
- "Qimonda",
- "New Japan Radio Co. Ltd.",
- "Velogix", "Montalvo Systems",
- "iVivity Inc.",
- "Walton Chaintech",
- "AENEON",
- "Lorom Industrial Co. Ltd.",
- "Radiospire Networks",
- "Sensio Technologies, Inc.",
- "Nethra Imaging",
- "Hexon Technology Pte Ltd",
- "CompuStocx (CSX)",
- "Methode Electronics, Inc.",
- "Connect One Ltd.",
- "Opulan Technologies",
- "Septentrio NV",
- "Goldenmars Technology Inc.",
- "Kreton Corporation",
- "Cochlear Ltd.",
- "Altair Semiconductor",
- "NetEffect, Inc.",
- "Spansion, Inc.",
- "Taiwan Semiconductor Mfg",
- "Emphany Systems Inc.",
- "ApaceWave Technologies",
- "Mobilygen Corporation", "Tego",
- "Cswitch Corporation",
- "Haier (Beijing) IC Design Co.",
- "MetaRAM",
- "Axel Electronics Co. Ltd.",
- "Tilera Corporation",
- "Aquantia",
- "Vivace Semiconductor",
- "Redpine Signals", "Octalica",
- "InterDigital Communications",
- "Avant Technology",
- "Asrock, Inc.", "Availink",
- "Quartics, Inc.",
- "Element CXI",
- "Innovaciones Microelectronicas",
- "VeriSilicon Microelectronics",
- "W5 Networks"
-};
+ char partno[32];
+ const char *form_factor;
+ char type_detail[256];
-static const char *vendors7[] = { "MOVEKING", "Mavrix Technology, Inc.",
- "CellGuide Ltd.", "Faraday Technology",
- "Diablo Technologies, Inc.", "Jennic", "Octasic",
- "Molex Incorporated",
- "3Leaf Networks",
- "Bright Micron Technology", "Netxen", "NextWave Broadband Inc.",
- "DisplayLink", "ZMOS Technology",
- "Tec-Hill", "Multigig, Inc.", "Amimon", "Euphonic Technologies, Inc.",
- "BRN Phoenix",
- "InSilica", "Ember Corporation", "Avexir Technologies Corporation",
- "Echelon Corporation",
- "Edgewater Computer Systems", "XMOS Semiconductor Ltd.",
- "GENUSION, Inc.", "Memory Corp NV",
- "SiliconBlue Technologies", "Rambus Inc."
-};
+ dmi_mem_size size_MiB;
-static const char **vendors[7] = { vendors1, vendors2, vendors3, vendors4, vendors5, vendors6,
- vendors7
-};
+ int spd_rev_major; // bytes[1] >> 4
+ int spd_rev_minor; // bytes[1] & 0xf
+
+ int week, year;
+
+ gboolean ddr4_no_ee1004;
+
+ struct dmi_mem_socket *dmi_socket;
+ int match_score;
+} spd_data;
+
+#define spd_data_new() g_new0(spd_data, 1)
+void spd_data_free(spd_data *s) { g_free(s); }
/*
* We consider that no data was written to this area of the SPD EEPROM if
* all bytes read 0x00 or all bytes read 0xff
*/
-static int spd_written(unsigned char *bytes, int len)
-{
+static int spd_written(unsigned char *bytes, int len) {
do {
- if (*bytes == 0x00 || *bytes == 0xFF)
- return 1;
+ if (*bytes == 0x00 || *bytes == 0xFF) return 1;
} while (--len && bytes++);
return 0;
}
-static int parity(int value)
-{
+static int parity(int value) {
value ^= value >> 16;
value ^= value >> 8;
value ^= value >> 4;
@@ -631,235 +122,152 @@ static int parity(int value)
return (0x6996 >> value) & 1;
}
-static void decode_sdr_module_size(unsigned char *bytes, int *size)
-{
- int i, k = 0;
+static void decode_sdr_module_size(unsigned char *bytes, dmi_mem_size *size) {
+ unsigned short i, k = 0;
i = (bytes[3] & 0x0f) + (bytes[4] & 0x0f) - 17;
- if (bytes[5] <= 8 && bytes[17] <= 8) {
- k = bytes[5] * bytes[17];
- }
+ if (bytes[5] <= 8 && bytes[17] <= 8) { k = bytes[5] * bytes[17]; }
if (i > 0 && i <= 12 && k > 0) {
- if (size) {
- *size = (1 << i) * k;
- }
+ if (size) { *size = (dmi_mem_size)k * (unsigned short)(1 << i); }
} else {
- if (size) {
- *size = -1;
- }
+ if (size) { *size = -1; }
}
}
-static void decode_sdr_module_timings(unsigned char *bytes, float *tcl, float *trcd, float *trp, float *tras)
-{
+static void decode_sdr_module_timings(unsigned char *bytes, float *tcl, float *trcd, float *trp,
+ float *tras) {
float cas[3], ctime;
int i, j;
for (i = 0, j = 0; j < 7; j++) {
- if (bytes[18] & 1 << j) {
- cas[i++] = j + 1;
- }
+ if (bytes[18] & 1 << j) { cas[i++] = j + 1; }
}
- ctime = (bytes[9] >> 4 + bytes[9] & 0xf) * 0.1;
+ ctime = ((bytes[9] >> 4) + (bytes[9] & 0xf)) * 0.1;
- if (trcd) {
- *trcd = ceil(bytes[29] / ctime);
- }
- if (trp) {
- *trp = ceil(bytes[27] / ctime);
- }
- if (tras) {
- *tras = ceil(bytes[30] / ctime);
- }
- if (tcl) {
- *tcl = cas[i];
- }
+ if (trcd) { *trcd = ceil(bytes[29] / ctime); }
+ if (trp) { *trp = ceil(bytes[27] / ctime); }
+ if (tras) { *tras = ceil(bytes[30] / ctime); }
+ if (tcl) { *tcl = cas[i]; }
}
-static void decode_sdr_module_row_address_bits(unsigned char *bytes, char **bits)
-{
+static void decode_sdr_module_row_address_bits(unsigned char *bytes, char **bits) {
char *temp;
switch (bytes[3]) {
- case 0:
- temp = "Undefined";
- break;
- case 1:
- temp = "1/16";
- break;
- case 2:
- temp = "2/27";
- break;
- case 3:
- temp = "3/18";
- break;
+ case 0: temp = "Undefined"; break;
+ case 1: temp = "1/16"; break;
+ case 2: temp = "2/27"; break;
+ case 3: temp = "3/18"; break;
default:
- /* printf("%d\n", bytes[3]); */
- temp = "Unknown";
+ /* printf("%d\n", bytes[3]); */
+ temp = NULL;
}
- if (bits) {
- *bits = temp;
- }
+ if (bits) { *bits = temp; }
}
-static void decode_sdr_module_col_address_bits(unsigned char *bytes, char **bits)
-{
+static void decode_sdr_module_col_address_bits(unsigned char *bytes, char **bits) {
char *temp;
switch (bytes[4]) {
- case 0:
- temp = "Undefined";
- break;
- case 1:
- temp = "1/16";
- break;
- case 2:
- temp = "2/17";
- break;
- case 3:
- temp = "3/18";
- break;
+ case 0: temp = "Undefined"; break;
+ case 1: temp = "1/16"; break;
+ case 2: temp = "2/17"; break;
+ case 3: temp = "3/18"; break;
default:
- /*printf("%d\n", bytes[4]); */
- temp = "Unknown";
+ /*printf("%d\n", bytes[4]); */
+ temp = NULL;
}
- if (bits) {
- *bits = temp;
- }
+ if (bits) { *bits = temp; }
}
-static void decode_sdr_module_number_of_rows(unsigned char *bytes, int *rows)
-{
- if (rows) {
- *rows = bytes[5];
- }
+static void decode_sdr_module_number_of_rows(unsigned char *bytes, int *rows) {
+ if (rows) { *rows = bytes[5]; }
}
-static void decode_sdr_module_data_with(unsigned char *bytes, int *width)
-{
+static void decode_sdr_module_data_with(unsigned char *bytes, int *width) {
if (width) {
- if (bytes[7] > 1) {
- *width = 0;
- } else {
- *width = (bytes[7] * 0xff) + bytes[6];
- }
+ if (bytes[7] > 1) {
+ *width = 0;
+ } else {
+ *width = (bytes[7] * 0xff) + bytes[6];
+ }
}
}
-static void decode_sdr_module_interface_signal_levels(unsigned char *bytes, char **signal_levels)
-{
+static void decode_sdr_module_interface_signal_levels(unsigned char *bytes, char **signal_levels) {
char *temp;
switch (bytes[8]) {
- case 0:
- temp = "5.0 Volt/TTL";
- break;
- case 1:
- temp = "LVTTL";
- break;
- case 2:
- temp = "HSTL 1.5";
- break;
- case 3:
- temp = "SSTL 3.3";
- break;
- case 4:
- temp = "SSTL 2.5";
- break;
- case 255:
- temp = "New Table";
- break;
- default:
- temp = "Undefined";
+ case 0: temp = "5.0 Volt/TTL"; break;
+ case 1: temp = "LVTTL"; break;
+ case 2: temp = "HSTL 1.5"; break;
+ case 3: temp = "SSTL 3.3"; break;
+ case 4: temp = "SSTL 2.5"; break;
+ case 255: temp = "New Table"; break;
+ default: temp = NULL;
}
- if (signal_levels) {
- *signal_levels = temp;
- }
+ if (signal_levels) { *signal_levels = temp; }
}
-static void decode_sdr_module_configuration_type(unsigned char *bytes, char **module_config_type)
-{
+static void decode_sdr_module_configuration_type(unsigned char *bytes, char **module_config_type) {
char *temp;
switch (bytes[11]) {
- case 0:
- temp = "No parity";
- break;
- case 1:
- temp = "Parity";
- break;
- case 2:
- temp = "ECC";
- break;
- default:
- temp = "Undefined";
+ case 0: temp = "No parity"; break;
+ case 1: temp = "Parity"; break;
+ case 2: temp = "ECC"; break;
+ default: temp = NULL;
}
- if (module_config_type) {
- *module_config_type = temp;
- }
+ if (module_config_type) { *module_config_type = temp; }
}
-static void decode_sdr_module_refresh_type(unsigned char *bytes, char **refresh_type)
-{
+static void decode_sdr_module_refresh_type(unsigned char *bytes, char **refresh_type) {
char *temp;
if (bytes[12] & 0x80) {
- temp = "Self refreshing";
+ temp = "Self refreshing";
} else {
- temp = "Not self refreshing";
+ temp = "Not self refreshing";
}
- if (refresh_type) {
- *refresh_type = temp;
- }
+ if (refresh_type) { *refresh_type = temp; }
}
-static void decode_sdr_module_refresh_rate(unsigned char *bytes, char **refresh_rate)
-{
+static void decode_sdr_module_refresh_rate(unsigned char *bytes, char **refresh_rate) {
char *temp;
switch (bytes[12] & 0x7f) {
- case 0:
- temp = "Normal (15.625us)";
- break;
- case 1:
- temp = "Reduced (3.9us)";
- break;
- case 2:
- temp = "Reduced (7.8us)";
- break;
- case 3:
- temp = "Extended (31.3us)";
- break;
- case 4:
- temp = "Extended (62.5us)";
- break;
- case 5:
- temp = "Extended (125us)";
- break;
- default:
- temp = "Undefined";
+ case 0: temp = "Normal (15.625us)"; break;
+ case 1: temp = "Reduced (3.9us)"; break;
+ case 2: temp = "Reduced (7.8us)"; break;
+ case 3: temp = "Extended (31.3us)"; break;
+ case 4: temp = "Extended (62.5us)"; break;
+ case 5: temp = "Extended (125us)"; break;
+ default: temp = NULL;
}
- if (refresh_rate) {
- *refresh_rate = temp;
+ if (refresh_rate) { *refresh_rate = temp; }
+}
+
+static void decode_sdr_module_detail(unsigned char *bytes, char *type_detail) {
+ bytes = bytes; /* silence unused warning */
+ if (type_detail) {
+ snprintf(type_detail, 255, "SDR");
}
}
-static gchar *decode_sdr_sdram(unsigned char *bytes, int *size)
-{
+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);
@@ -882,29 +290,30 @@ 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"
- "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);
+ /* 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",
+ _("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)
-{
+static void decode_ddr_module_speed(unsigned char *bytes, float *ddrclk, int *pcclk) {
float temp, clk;
int tbits, pc;
@@ -912,601 +321,952 @@ static void decode_ddr_module_speed(unsigned char *bytes, float *ddrclk, int *pc
clk = 2 * (1000 / temp);
tbits = (bytes[7] * 256) + bytes[6];
- if (bytes[11] == 2 || bytes[11] == 1) {
- tbits -= 8;
- }
+ if (bytes[11] == 2 || bytes[11] == 1) { tbits -= 8; }
pc = clk * tbits / 8;
- if (pc % 100 > 50) {
- pc += 100;
- }
+ if (pc % 100 > 50) { pc += 100; }
pc -= pc % 100;
- if (ddrclk)
- *ddrclk = (int) clk;
+ if (ddrclk) *ddrclk = (int)clk;
- if (pcclk)
- *pcclk = pc;
+ if (pcclk) *pcclk = pc;
}
-static void decode_ddr_module_size(unsigned char *bytes, int *size)
-{
- int i, k;
+static void decode_ddr_module_size(unsigned char *bytes, dmi_mem_size *size) {
+ unsigned short i, k;
i = (bytes[3] & 0x0f) + (bytes[4] & 0x0f) - 17;
k = (bytes[5] <= 8 && bytes[17] <= 8) ? bytes[5] * bytes[17] : 0;
if (i > 0 && i <= 12 && k > 0) {
- if (size) {
- *size = (1 << i) * k;
- }
+ if (size) { *size = (dmi_mem_size)k * (unsigned short)(1 << i); }
} else {
- if (size) {
- *size = -1;
- }
+ if (size) { *size = -1; }
}
}
-static void *decode_ddr_module_timings(unsigned char *bytes, float *tcl, float *trcd, float *trp, float *tras)
-{
+static void decode_ddr_module_timings(unsigned char *bytes, float *tcl, float *trcd, float *trp,
+ float *tras) {
float ctime;
float highest_cas = 0;
int i;
for (i = 0; i < 7; i++) {
- if (bytes[18] & (1 << i)) {
- highest_cas = 1 + i * 0.5f;
- }
+ if (bytes[18] & (1 << i)) { highest_cas = 1 + i * 0.5f; }
}
ctime = (bytes[9] >> 4) + (bytes[9] & 0xf) * 0.1;
if (trcd) {
- *trcd = (bytes[29] >> 2) + ((bytes[29] & 3) * 0.25);
- *trcd = ceil(*trcd / ctime);
+ *trcd = (bytes[29] >> 2) + ((bytes[29] & 3) * 0.25);
+ *trcd = ceil(*trcd / ctime);
}
if (trp) {
- *trp = (bytes[27] >> 2) + ((bytes[27] & 3) * 0.25);
- *trp = ceil(*trp / ctime);
+ *trp = (bytes[27] >> 2) + ((bytes[27] & 3) * 0.25);
+ *trp = ceil(*trp / ctime);
}
if (tras) {
- *tras = bytes[30];
- *tras = ceil(*tras / ctime);
+ *tras = bytes[30];
+ *tras = ceil(*tras / ctime);
}
- if (tcl) {
- *tcl = highest_cas;
- }
+ 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"
- "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);
+ return g_strdup_printf("[%s]\n"
+ "tCL=%.2f\n"
+ "tRCD=%.2f\n"
+ "tRP=%.2f\n"
+ "tRAS=%.2f\n",
+ _("Timings"), tcl, trcd, trp, tras);
}
-static float decode_ddr2_module_ctime(unsigned char byte)
-{
+static float decode_ddr2_module_ctime(unsigned char byte) {
float ctime;
ctime = (byte >> 4);
byte &= 0xf;
if (byte <= 9) {
- ctime += byte * 0.1;
+ ctime += byte * 0.1;
} else if (byte == 10) {
- ctime += 0.25;
+ ctime += 0.25;
} else if (byte == 11) {
- ctime += 0.33;
+ ctime += 0.33;
} else if (byte == 12) {
- ctime += 0.66;
+ ctime += 0.66;
} else if (byte == 13) {
- ctime += 0.75;
+ ctime += 0.75;
}
return ctime;
}
-static void decode_ddr2_module_speed(unsigned char *bytes, float *ddr_clock, int *pc2_speed)
-{
+static void decode_ddr2_module_speed(unsigned char *bytes, float *ddr_clock, int *pc2_speed) {
float ctime;
float ddrclk;
int tbits, pcclk;
-
ctime = decode_ddr2_module_ctime(bytes[9]);
ddrclk = 2 * (1000 / ctime);
tbits = (bytes[7] * 256) + bytes[6];
- if (bytes[11] & 0x03) {
- tbits -= 8;
- }
+ if (bytes[11] & 0x03) { tbits -= 8; }
pcclk = ddrclk * tbits / 8;
pcclk -= pcclk % 100;
- if (ddr_clock) {
- *ddr_clock = (int) ddrclk;
- }
- if (pc2_speed) {
- *pc2_speed = pcclk;
- }
+ if (ddr_clock) { *ddr_clock = (int)ddrclk; }
+ if (pc2_speed) { *pc2_speed = pcclk; }
}
-static void decode_ddr2_module_size(unsigned char *bytes, int *size)
-{
- int i, k;
+static void decode_ddr2_module_size(unsigned char *bytes, dmi_mem_size *size) {
+ unsigned short i, k;
i = (bytes[3] & 0x0f) + (bytes[4] & 0x0f) - 17;
k = ((bytes[5] & 0x7) + 1) * bytes[17];
if (i > 0 && i <= 12 && k > 0) {
- if (*size) {
- *size = ((1 << i) * k);
- }
+ if (size) { *size = (dmi_mem_size)k * (unsigned short)(1 << i); }
} else {
- if (*size) {
- *size = 0;
- }
+ if (size) { *size = 0; }
}
}
-static void decode_ddr2_module_timings(unsigned char *bytes, float *trcd, float *trp, float *tras, float *tcl)
-{
- float ctime;
- float highest_cas = 0;
- int i;
-
- for (i = 0; i < 7; i++) {
- if (bytes[18] & (1 << i)) {
- highest_cas = i;
- }
+static void decode_ddr2_module_type(unsigned char *bytes, const char **type) {
+ switch (bytes[20]) {
+ case 0x01: *type = "RDIMM (Registered DIMM)"; break;
+ case 0x02: *type = "UDIMM (Unbuffered DIMM)"; break;
+ case 0x04: *type = "SO-DIMM (Small Outline DIMM)"; break;
+ case 0x06: *type = "72b-SO-CDIMM (Small Outline Clocked DIMM, 72-bit data bus)"; break;
+ case 0x07: *type = "72b-SO-RDIMM (Small Outline Registered DIMM, 72-bit data bus)"; break;
+ case 0x08: *type = "Micro-DIMM"; break;
+ case 0x10: *type = "Mini-RDIMM (Mini Registered DIMM)"; break;
+ case 0x20: *type = "Mini-UDIMM (Mini Unbuffered DIMM)"; break;
+ default: *type = NULL;
}
+}
- ctime = decode_ddr2_module_ctime(bytes[9]);
+static void decode_ddr2_module_timings(float ctime, unsigned char *bytes, float *trcd, float *trp, float *tras) {
- if (trcd) {
- *trcd = ceil(((bytes[29] >> 2) + ((bytes[29] & 3) * 0.25)) / ctime);
- }
+ if (trcd) { *trcd = ceil(((bytes[29] >> 2) + ((bytes[29] & 3) * 0.25)) / ctime); }
- if (trp) {
- *trp = ceil(((bytes[27] >> 2) + ((bytes[27] & 3) * 0.25)) / ctime);
- }
+ if (trp) { *trp = ceil(((bytes[27] >> 2) + ((bytes[27] & 3) * 0.25)) / ctime); }
- if (tras) {
- *tras = ceil(bytes[30] / ctime);
+ if (tras) { *tras = ceil(bytes[30] / ctime); }
+}
+
+static gboolean decode_ddr2_module_ctime_for_casx(int casx_minus, unsigned char *bytes, float *ctime, float *tcl){
+ int highest_cas, i, bytei;
+ float ctimev = 0;
+
+ switch (casx_minus){
+ case 0:
+ bytei = 9;
+ break;
+ case 1:
+ bytei = 23;
+ break;
+ case 2:
+ bytei = 25;
+ break;
+ default:
+ return FALSE;
}
- if (tcl) {
- *tcl = highest_cas;
+ for (i = 0; i < 7; i++) {
+ if (bytes[18] & (1 << i)) { highest_cas = i; }
}
+
+ if ((bytes[18] & (1 << (highest_cas-casx_minus))) == 0)
+ return FALSE;
+
+ ctimev = decode_ddr2_module_ctime(bytes[bytei]);
+ if (ctimev == 0)
+ return FALSE;
+
+ if (tcl) { *tcl = highest_cas-casx_minus; }
+ if (ctime) { *ctime = ctimev; }
+
+ return TRUE;
}
-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);
+ }
+}
- 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"
- "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);
+static gchar *decode_ddr2_sdram_extra(unsigned char *bytes) {
+ float trcd, trp, tras, ctime, tcl;
+ const char* voltage;
+ gchar *out;
+ int i;
+
+ switch(bytes[8]){
+ case 0x0:
+ voltage = "TTL/5 V tolerant";
+ break;
+ case 0x1:
+ voltage = "LVTTL";
+ break;
+ case 0x2:
+ voltage = "HSTL 1.5 V";
+ break;
+ case 0x3:
+ voltage = "SSTL 3.3 V";
+ break;
+ case 0x4:
+ voltage = "SSTL 2.5 V";
+ break;
+ case 0x5:
+ voltage = "SSTL 1.8 V";
+ break;
+ default:
+ voltage = _("(Unknown)");
+ }
+
+ /* expected to continue an [SPD] section */
+ out = g_strdup_printf("%s=%s\n"
+ "[%s]\n",
+ _("Voltage"), voltage,
+ _("JEDEC Timings"));
+
+ for (i = 0; i <= 2; i++) {
+ if (!decode_ddr2_module_ctime_for_casx(i, bytes, &ctime, &tcl))
+ break;
+ decode_ddr2_module_timings(ctime, bytes, &trcd, &trp, &tras);
+ out = h_strdup_cprintf("DDR2-%d=%.0f-%.0f-%.0f-%.0f\n",
+ out,
+ (int)(2 * (1000 / ctime)), tcl, trcd, trp, tras);
+ }
+
+ return out;
}
-static void decode_ddr3_module_speed(unsigned char *bytes, float *ddr_clock, int *pc3_speed)
-{
+static void decode_ddr3_module_speed(unsigned char *bytes, float *ddr_clock, int *pc3_speed) {
float ctime;
float ddrclk;
int tbits, pcclk;
float mtb = 0.125;
- if (bytes[10] == 1 && bytes[11] == 8)
- mtb = 0.125;
- if (bytes[10] == 1 && bytes[11] == 15)
- mtb = 0.0625;
+ if (bytes[10] == 1 && bytes[11] == 8) mtb = 0.125;
+ if (bytes[10] == 1 && bytes[11] == 15) mtb = 0.0625;
ctime = mtb * bytes[12];
ddrclk = 2 * (1000 / ctime);
tbits = 64;
switch (bytes[8]) {
- case 1:
- tbits = 16;
- break;
- case 4:
- tbits = 32;
- break;
+ case 1: tbits = 16; break;
+ case 4: tbits = 32; break;
case 3:
- case 0xb:
- tbits = 64;
- break;
+ case 0xb: tbits = 64; break;
}
pcclk = ddrclk * tbits / 8;
pcclk -= pcclk % 100;
- if (ddr_clock) {
- *ddr_clock = (int) ddrclk;
- }
- if (pc3_speed) {
- *pc3_speed = pcclk;
- }
+ if (ddr_clock) { *ddr_clock = (int)ddrclk; }
+ if (pc3_speed) { *pc3_speed = pcclk; }
}
-static void decode_ddr3_module_size(unsigned char *bytes, int *size)
-{
- *size = 512 << bytes[4];
+static void decode_ddr3_module_size(unsigned char *bytes, dmi_mem_size *size) {
+ unsigned int sdr_capacity = 256 << (bytes[4] & 0xF);
+ unsigned int sdr_width = 4 << (bytes[7] & 0x7);
+ unsigned int bus_width = 8 << (bytes[8] & 0x7);
+ unsigned int ranks = 1 + ((bytes[7] >> 3) & 0x7);
+
+ *size = (dmi_mem_size)sdr_capacity / 8 * bus_width / sdr_width * ranks;
}
-static void decode_ddr3_module_timings(unsigned char *bytes, float *trcd, float *trp, float *tras, float *tcl)
-{
+static void decode_ddr3_module_timings(unsigned char *bytes, float *trcd, float *trp, float *tras,
+ float *tcl) {
float ctime;
- float highest_cas = 0;
- int i;
float mtb = 0.125;
+ float taa;
- if (bytes[10] == 1 && bytes[11] == 8)
- mtb = 0.125;
- if (bytes[10] == 1 && bytes[11] == 15)
- mtb = 0.0625;
+ if (bytes[10] == 1 && bytes[11] == 8) mtb = 0.125;
+ if (bytes[10] == 1 && bytes[11] == 15) mtb = 0.0625;
ctime = mtb * bytes[12];
+ taa = bytes[16] * mtb;
- switch (bytes[14]) {
- case 6:
- highest_cas = 5;
- break;
- case 4:
- highest_cas = 6;
- break;
- case 0xc:
- highest_cas = 7;
- break;
- case 0x1e:
- highest_cas = 8;
- break;
- }
- if (trcd) {
- *trcd = bytes[18] * mtb;
- }
+ if (trcd) { *trcd = bytes[18] * mtb; }
- if (trp) {
- *trp = bytes[20] * mtb;
- }
+ if (trp) { *trp = bytes[20] * mtb; }
- if (tras) {
- *tras = (bytes[22] + bytes[21] & 0xf) * mtb;
- }
+ if (tras) { *tras = (bytes[22] + (bytes[21] & 0xf)) * mtb; }
- if (tcl) {
- *tcl = highest_cas;
- }
+ if (tcl) { *tcl = ceil(taa/ctime); }
}
-static void decode_ddr3_module_type(unsigned char *bytes, const char **type)
-{
+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";
+ 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 = 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"
- "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);
+
+ int ranks = 1 + ((bytes[7] >> 3) & 0x7);
+ int pins = 4 << (bytes[7] & 0x7);
+ int die_count = (bytes[33] >> 4) & 0x7;
+ int ts = !!(bytes[32] & 0x80);
+
+ /* expected to continue an [SPD] section */
+ return g_strdup_printf("%s=%d\n"
+ "%s=%d\n"
+ "%s=%d %s\n"
+ "%s=[%02x] %s\n"
+ "%s=%s%s%s\n"
+ "%s="
+ "%s%s%s%s%s%s%s%s"
+ "%s%s%s%s%s%s%s\n"
+ "[%s]\n"
+ "tCL=%.0f\n"
+ "tRCD=%.3fns\n"
+ "tRP=%.3fns\n"
+ "tRAS=%.3fns\n",
+ _("Ranks"), ranks,
+ _("IO Pins per Chip"), pins,
+ _("Die count"), die_count, die_count ? "" : _("(Unspecified)"),
+ _("Thermal Sensor"), bytes[32], ts ? _("Present") : _("Not present"),
+ _("Supported Voltages"),
+ (bytes[6] & 4) ? "1.25V " : "",
+ (bytes[6] & 2) ? "1.35V " : "",
+ (bytes[6] & 1) ? "" : "1.5V",
+ _("Supported CAS Latencies"),
+ (bytes[15] & 0x40) ? "18 " : "",
+ (bytes[15] & 0x20) ? "17 " : "",
+ (bytes[15] & 0x10) ? "16 " : "",
+ (bytes[15] & 0x08) ? "15 " : "",
+ (bytes[15] & 0x04) ? "14 " : "",
+ (bytes[15] & 0x02) ? "13 " : "",
+ (bytes[15] & 0x01) ? "12 " : "",
+ (bytes[14] & 0x80) ? "11 " : "",
+ (bytes[14] & 0x40) ? "10 " : "",
+ (bytes[14] & 0x20) ? "9 " : "",
+ (bytes[14] & 0x10) ? "8 " : "",
+ (bytes[14] & 0x08) ? "7 " : "",
+ (bytes[14] & 0x04) ? "6 " : "",
+ (bytes[14] & 0x02) ? "5 " : "",
+ (bytes[14] & 0x01) ? "4" : "",
+ _("Timings"), tcl, trcd, trp, tras
+ );
}
-static void decode_ddr3_part_number(unsigned char *bytes, char *part_number)
-{
+static void decode_ddr3_part_number(unsigned char *bytes, char *part_number) {
int i;
if (part_number) {
- for (i = 128; i <= 145; i++)
- *part_number++ = bytes[i];
- *part_number = '\0';
+ for (i = 128; i <= 145; i++) *part_number++ = bytes[i];
+ *part_number = '\0';
}
}
-static void decode_ddr3_manufacturer(unsigned char *bytes, char **manufacturer)
-{
- char *out = "Unknown";
+static void decode_ddr34_manufacturer(unsigned char count, unsigned char code, char **manufacturer, int *bank, int *index) {
+ if (!manufacturer) return;
+
+ if (code == 0x00 || code == 0xFF) {
+ *manufacturer = NULL;
+ return;
+ }
+
+ if (parity(count) != 1 || parity(code) != 1) {
+ *manufacturer = _("Invalid");
+ return;
+ }
- end:
- if (manufacturer) {
- *manufacturer = out;
+ *bank = count & 0x7f;
+ *index = code & 0x7f;
+ if (*bank >= VENDORS_BANKS) {
+ *manufacturer = NULL;
+ return;
}
+
+ *manufacturer = (char *)JEDEC_MFG_STR(*bank, *index - 1);
+}
+
+static void decode_ddr3_manufacturer(unsigned char *bytes, char **manufacturer, int *bank, int *index) {
+ decode_ddr34_manufacturer(bytes[117], bytes[118], (char **) manufacturer, bank, index);
}
-static void decode_module_manufacturer(unsigned char *bytes, char **manufacturer)
-{
+static void decode_module_manufacturer(unsigned char *bytes, char **manufacturer) {
char *out = "Unknown";
unsigned char first;
int ai = 0;
int len = 8;
- unsigned char *initial = bytes;
if (!spd_written(bytes, 8)) {
- out = "Undefined";
- goto end;
+ out = "Undefined";
+ goto end;
}
- do {
- ai++;
- } while ((--len && (*bytes++ == 0x7f)));
+ do { ai++; } while ((--len && (*bytes++ == 0x7f)));
first = *--bytes;
if (ai == 0) {
- out = "Invalid";
- goto end;
+ out = "Invalid";
+ goto end;
}
if (parity(first) != 1) {
- out = "Invalid";
- goto end;
+ out = "Invalid";
+ goto end;
}
- out = (char *) vendors[ai - 1][(first & 0x7f) - 1];
+ out = (char*)JEDEC_MFG_STR(ai - 1, (first & 0x7f) - 1);
- end:
- if (manufacturer) {
- *manufacturer = out;
- }
+end:
+ if (manufacturer) { *manufacturer = out; }
}
-static void decode_module_part_number(unsigned char *bytes, char *part_number)
-{
+static void decode_module_part_number(unsigned char *bytes, char *part_number) {
if (part_number) {
- bytes += 8 + 64;
+ bytes += 8 + 64;
+
+ while (*++bytes && *bytes >= 32 && *bytes < 127) { *part_number++ = *bytes; }
+ *part_number = '\0';
+ }
+}
+
+static char *print_spd_timings(int speed, float cas, float trcd, float trp, float tras,
+ float ctime) {
+ return g_strdup_printf("DDR4-%d=%.0f-%.0f-%.0f-%.0f\n", speed, cas, ceil(trcd / ctime - 0.025),
+ ceil(trp / ctime - 0.025), ceil(tras / ctime - 0.025));
+}
+
+static void decode_ddr4_module_type(unsigned char *bytes, const char **type) {
+ switch (bytes[3]) {
+ case 0x01: *type = "RDIMM (Registered DIMM)"; break;
+ case 0x02: *type = "UDIMM (Unbuffered DIMM)"; break;
+ case 0x03: *type = "SODIMM (Small Outline Unbuffered DIMM)"; break;
+ case 0x04: *type = "LRDIMM (Load-Reduced DIMM)"; break;
+ case 0x05: *type = "Mini-RDIMM (Mini Registered DIMM)"; break;
+ case 0x06: *type = "Mini-UDIMM (Mini Unbuffered DIMM)"; break;
+ case 0x08: *type = "72b-SO-RDIMM (Small Outline Registered DIMM, 72-bit data bus)"; break;
+ 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 = NULL;
+ }
+}
+
+static float ddr4_mtb_ftb_calc(unsigned char b1, signed char b2) {
+ float mtb = 0.125;
+ float ftb = 0.001;
+ return b1 * mtb + b2 * ftb;
+}
+
+static void decode_ddr4_module_speed(unsigned char *bytes, float *ddr_clock, int *pc4_speed) {
+ float ctime;
+ float ddrclk;
+ int tbits, pcclk;
+
+ ctime = ddr4_mtb_ftb_calc(bytes[18], bytes[125]);
+ ddrclk = 2 * (1000 / ctime);
+ tbits = 8 << (bytes[13] & 7);
+
+ pcclk = ddrclk * tbits / 8;
+ pcclk -= pcclk % 100;
+
+ if (ddr_clock) { *ddr_clock = (int)ddrclk; }
+ if (pc4_speed) { *pc4_speed = pcclk; }
+}
+
+static void decode_ddr4_module_spd_timings(unsigned char *bytes, float speed, char **str) {
+ float ctime, ctime_max, pctime, taa, trcd, trp, tras;
+ int pcas, best_cas, base_cas, ci, i, j;
+ unsigned char cas_support[] = {bytes[20], bytes[21], bytes[22], bytes[23] & 0x1f};
+ float possible_ctimes[] = {15 / 24.0, 15 / 22.0, 15 / 20.0, 15 / 18.0,
+ 15 / 16.0, 15 / 14.0, 15 / 12.0};
+
+ base_cas = bytes[23] & 0x80 ? 23 : 7;
+
+ ctime = ddr4_mtb_ftb_calc(bytes[18], bytes[125]);
+ ctime_max = ddr4_mtb_ftb_calc(bytes[19], bytes[124]);
+
+ taa = ddr4_mtb_ftb_calc(bytes[24], bytes[123]);
+ trcd = ddr4_mtb_ftb_calc(bytes[25], bytes[122]);
+ trp = ddr4_mtb_ftb_calc(bytes[26], bytes[121]);
+ tras = (((bytes[27] & 0x0f) << 8) + bytes[28]) * 0.125;
+
+ *str = print_spd_timings((int)speed, ceil(taa / ctime - 0.025), trcd, trp, tras, ctime);
+
+ for (ci = 0; ci < 7; ci++) {
+ best_cas = 0;
+ pctime = possible_ctimes[ci];
+
+ for (i = 3; i >= 0; i--) {
+ for (j = 7; j >= 0; j--) {
+ if ((cas_support[i] & (1 << j)) != 0) {
+ pcas = base_cas + 8 * i + j;
+ if (ceil(taa / pctime) - 0.025 <= pcas) { best_cas = pcas; }
+ }
+ }
+ }
+
+ if (best_cas > 0 && pctime <= ctime_max && pctime >= ctime) {
+ *str = h_strdup_cprintf(
+ "%s\n", *str,
+ print_spd_timings((int)(2000.0 / pctime), best_cas, trcd, trp, tras, pctime));
+ }
+ }
+}
+
+static void decode_ddr4_module_size(unsigned char *bytes, dmi_mem_size *size) {
+ int sdrcap = 256 << (bytes[4] & 15);
+ int buswidth = 8 << (bytes[13] & 7);
+ int sdrwidth = 4 << (bytes[12] & 7);
+ int signal_loading = bytes[6] & 3;
+ int lranks_per_dimm = ((bytes[12] >> 3) & 7) + 1;
+
+ if (signal_loading == 2) lranks_per_dimm *= ((bytes[6] >> 4) & 7) + 1;
+
+ *size = (dmi_mem_size)sdrcap / 8 * buswidth / sdrwidth * lranks_per_dimm;
+}
+
+
+static void decode_ddr234_module_date(unsigned char weekb, unsigned char yearb, int *week, int *year) {
+ if (yearb == 0x0 || yearb == 0xff ||
+ weekb == 0x0 || weekb == 0xff) {
+ return;
+ }
+ *week = (weekb>>4) & 0xf;
+ *week *= 10;
+ *week += weekb & 0xf;
+ *year = (yearb>>4) & 0xf;
+ *year *= 10;
+ *year += yearb & 0xf;
+ *year += 2000;
+}
+
+static void decode_ddr2_module_date(unsigned char *bytes, int *week, int *year) {
+ decode_ddr234_module_date(bytes[94], bytes[93], week, year);
+}
- while (*bytes++ && *bytes >= 32 && *bytes < 127) {
- *part_number++ = *bytes;
- }
- *part_number = '\0';
+static void decode_ddr3_module_date(unsigned char *bytes, int *week, int *year) {
+ decode_ddr234_module_date(bytes[121], bytes[120], week, year);
+}
+
+static void decode_ddr4_module_date(unsigned char *bytes, int spd_size, int *week, int *year) {
+ if (spd_size < 324)
+ return;
+ decode_ddr234_module_date(bytes[324], bytes[323], week, year);
+}
+
+static void decode_ddr3_dram_manufacturer(unsigned char *bytes,
+ char **manufacturer, int *bank, int *index) {
+ decode_ddr34_manufacturer(bytes[94], bytes[95], (char **) manufacturer, bank, index);
+}
+
+static void decode_ddr4_dram_manufacturer(unsigned char *bytes, int spd_size,
+ char **manufacturer, int *bank, int *index) {
+ if (spd_size < 351) {
+ *manufacturer = NULL;
+ return;
+ }
+
+ decode_ddr34_manufacturer(bytes[350], bytes[351], (char **) manufacturer, bank, index);
+}
+
+static void detect_ddr4_xmp(unsigned char *bytes, int spd_size, int *majv, int *minv) {
+ if (spd_size < 387)
+ return;
+
+ *majv = 0; *minv = 0;
+
+ if (bytes[384] != 0x0c || bytes[385] != 0x4a) // XMP magic number
+ return;
+
+ if (majv)
+ *majv = bytes[387] >> 4;
+ if (minv)
+ *minv = bytes[387] & 0xf;
+}
+
+static void decode_ddr4_xmp(unsigned char *bytes, int spd_size, char **str) {
+ float ctime;
+ float ddrclk, taa, trcd, trp, tras;
+
+ if (spd_size < 405)
+ return;
+
+ ctime = ddr4_mtb_ftb_calc(bytes[396], bytes[431]);
+ ddrclk = 2 * (1000 / ctime);
+ taa = ddr4_mtb_ftb_calc(bytes[401], bytes[430]);
+ trcd = ddr4_mtb_ftb_calc(bytes[402], bytes[429]);
+ trp = ddr4_mtb_ftb_calc(bytes[403], bytes[428]);
+ tras = (((bytes[404] & 0x0f) << 8) + bytes[405]) * 0.125;
+
+ *str = g_strdup_printf("[%s]\n"
+ "%s=DDR4 %d MHz\n"
+ "%s=%d.%d V\n"
+ "[%s]\n"
+ "%s",
+ _("XMP Profile"),
+ _("Speed"), (int) ddrclk,
+ _("Voltage"), bytes[393] >> 7, bytes[393] & 0x7f,
+ _("XMP Timings"),
+ 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_extra(unsigned char *bytes, int spd_size) {
+ float ddr_clock;
+ int pc4_speed, xmp_majv = -1, xmp_minv = -1;
+ 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_spd_timings(bytes, ddr_clock, &speed_timings);
+ detect_ddr4_xmp(bytes, spd_size, &xmp_majv, &xmp_minv);
+
+ if (xmp_majv == -1 && xmp_minv == -1) {
+ xmp = NULL;
+ }
+ else if (xmp_majv <= 0 && xmp_minv <= 0) {
+ xmp = g_strdup(_("No"));
+ }
+ else {
+ 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);
+ }
+
+ /* expected to continue an [SPD] section */
+ out = g_strdup_printf("%s=%s\n"
+ "%s=%s\n"
+ "[%s]\n"
+ "%s\n"
+ "%s",
+ _("Voltage"), bytes[11] & 0x01 ? "1.2 V": _("(Unknown)"),
+ _("XMP"), xmp ? xmp : _("(Unknown)"),
+ _("JEDEC Timings"), speed_timings,
+ xmp_profile ? xmp_profile: "");
+
+ g_free(speed_timings);
+ g_free(manf_date);
+ g_free(xmp);
+ g_free(xmp_profile);
+
+ return out;
+}
+
+static void decode_ddr4_part_number(unsigned char *bytes, int spd_size, char *part_number) {
+ int i;
+ if (!part_number) return;
+
+ if (spd_size < 348) {
+ *part_number++ = '\0';
+ return;
}
+
+ 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, int *bank, int *index) {
+ if (spd_size < 321) {
+ *manufacturer = NULL;
+ return;
+ }
+
+ decode_ddr34_manufacturer(bytes[320], bytes[321], manufacturer, bank, index);
}
-static int decode_ram_type(unsigned char *bytes)
-{
+static int decode_ram_type(unsigned char *bytes) {
if (bytes[0] < 4) {
- switch (bytes[2]) {
- case 1:
- return DIRECT_RAMBUS;
- case 17:
- return RAMBUS;
- }
+ switch (bytes[2]) {
+ case 1: return DIRECT_RAMBUS;
+ case 17: return RAMBUS;
+ }
} else {
- switch (bytes[2]) {
- case 1:
- return FPM_DRAM;
- case 2:
- return EDO;
- case 3:
- return PIPELINED_NIBBLE;
- case 4:
- return SDR_SDRAM;
- case 5:
- return MULTIPLEXED_ROM;
- case 6:
- return DDR_SGRAM;
- case 7:
- return DDR_SDRAM;
- case 8:
- return DDR2_SDRAM;
- case 11:
- return DDR3_SDRAM;
- }
+ switch (bytes[2]) {
+ case 1: return FPM_DRAM;
+ case 2: return EDO;
+ case 3: return PIPELINED_NIBBLE;
+ case 4: return SDR_SDRAM;
+ case 5: return MULTIPLEXED_ROM;
+ case 6: return DDR_SGRAM;
+ case 7: return DDR_SDRAM;
+ case 8: return DDR2_SDRAM;
+ case 11: return DDR3_SDRAM;
+ case 12: return DDR4_SDRAM;
+ }
}
return UNKNOWN;
}
-static void read_spd(char *spd_path, int offset, size_t size, int use_sysfs, unsigned char *bytes_out)
-{
+static int read_spd(char *spd_path, int offset, size_t size, int use_sysfs,
+ unsigned char *bytes_out) {
+ int data_size = 0;
if (use_sysfs) {
- FILE *spd;
- gchar *temp_path;
+ FILE *spd;
+ gchar *temp_path;
- temp_path = g_strdup_printf("%s/eeprom", spd_path);
- if ((spd = fopen(temp_path, "rb"))) {
- fseek(spd, offset, SEEK_SET);
- fread(bytes_out, 1, size, spd);
- fclose(spd);
- }
+ temp_path = g_strdup_printf("%s/eeprom", spd_path);
+ if ((spd = fopen(temp_path, "rb"))) {
+ fseek(spd, offset, SEEK_SET);
+ data_size = fread(bytes_out, 1, size, spd);
+ fclose(spd);
+ }
- g_free(temp_path);
+ g_free(temp_path);
} else {
- int i;
+ int i;
- for (i = 0; i <= 3; i++) {
- FILE *spd;
- char *temp_path;
+ for (i = 0; i <= 3; i++) {
+ FILE *spd;
+ char *temp_path;
- temp_path = g_strdup_printf("%s/%02x", spd_path, offset + i * 16);
- if ((spd = fopen(temp_path, "rb"))) {
- fread(bytes_out + i * 16, 1, 16, spd);
- fclose(spd);
- }
+ temp_path = g_strdup_printf("%s/%02x", spd_path, offset + i * 16);
+ if ((spd = fopen(temp_path, "rb"))) {
+ data_size += fread(bytes_out + i * 16, 1, 16, spd);
+ fclose(spd);
+ }
- g_free(temp_path);
- }
+ g_free(temp_path);
+ }
}
+
+ return data_size;
}
-static gchar *decode_dimms(GSList * dimm_list, gboolean use_sysfs)
-{
- GSList *dimm;
- GString *output;
- gint count = 0;
-
- output = g_string_new("");
-
- 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];
- unsigned char bytes[256];
- int module_size;
- RamType ram_type;
-
- shell_status_pulse();
-
- read_spd(spd_path, 0, 256, use_sysfs, bytes);
- ram_type = decode_ram_type(bytes);
-
- switch (ram_type) {
- case DDR2_SDRAM:
- detailed_info = decode_ddr2_sdram(bytes, &module_size);
- decode_module_part_number(bytes, part_number);
- decode_module_manufacturer(bytes + 64, &manufacturer);
- break;
- case DDR3_SDRAM:
- detailed_info = decode_ddr3_sdram(bytes, &module_size);
- decode_ddr3_part_number(bytes, part_number);
- decode_ddr3_manufacturer(bytes, &manufacturer);
- 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);
- 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;
- }
-
-
-
- gchar *key = g_strdup_printf("MEM%d", count);
- moreinfo_add_with_prefix("DEV", key, g_strdup(detailed_info));
- g_free(key);
- 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);
+static GSList *decode_dimms2(GSList *eeprom_list, const gchar *driver, gboolean use_sysfs, int max_size) {
+ GSList *eeprom, *dimm_list = NULL;
+ int count = 0;
+ int spd_size = 0;
+ unsigned char bytes[512] = {0};
+ spd_data *s = NULL;
+
+ for (eeprom = eeprom_list; eeprom; eeprom = eeprom->next, count++) {
+ gchar *spd_path = (gchar*)eeprom->data;
+ s = NULL;
+
+ RamType ram_type;
+
+ memset(bytes, 0, 512); /* clear */
+ 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:
+ 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);
+ decode_ddr2_module_type(bytes, &s->form_factor);
+ decode_ddr2_module_date(bytes, &s->week, &s->year);
+ break;
+ case DDR3_SDRAM:
+ s = spd_data_new();
+ memcpy(s->bytes, bytes, 512);
+ decode_ddr3_part_number(bytes, s->partno);
+ decode_ddr3_manufacturer(bytes, (char**)&s->vendor_str,
+ &s->vendor_bank, &s->vendor_index);
+ decode_ddr3_dram_manufacturer(bytes, (char**)&s->dram_vendor_str,
+ &s->dram_vendor_bank, &s->dram_vendor_index);
+ decode_ddr3_module_size(bytes, &s->size_MiB);
+ decode_ddr3_module_type(bytes, &s->form_factor);
+ decode_ddr3_module_detail(bytes, s->type_detail);
+ decode_ddr3_module_date(bytes, &s->week, &s->year);
+ break;
+ case DDR4_SDRAM:
+ 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,
+ &s->vendor_bank, &s->vendor_index);
+ decode_ddr4_dram_manufacturer(bytes, spd_size, (char**)&s->dram_vendor_str,
+ &s->dram_vendor_bank, &s->dram_vendor_index);
+ decode_ddr4_module_size(bytes, &s->size_MiB);
+ decode_ddr4_module_type(bytes, &s->form_factor);
+ decode_ddr4_module_detail(bytes, s->type_detail);
+ decode_ddr4_module_date(bytes, spd_size, &s->week, &s->year);
+ 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 UNKNOWN:
+ break;
+ default:
+ DEBUG("Unsupported EEPROM type: %s for %s\n", GET_RAM_TYPE_STR(ram_type), spd_path); continue;
+ if (ram_type) {
+ /* some kind of RAM that we can't decode, but exists */
+ s = spd_data_new();
+ memcpy(s->bytes, bytes, 512);
+ }
+ }
+
+ if (s) {
+ strncpy(s->dev, g_basename(spd_path), 31);
+ s->spd_driver = driver;
+ s->spd_size = spd_size;
+ s->type = ram_type;
+ spd_ram_types |= (1 << (ram_type-1));
+ switch (ram_type) {
+ case SDR_SDRAM:
+ case DDR_SDRAM:
+ case DDR2_SDRAM:
+ s->spd_rev_major = bytes[62] >> 4;
+ s->spd_rev_minor = bytes[62] & 0xf;
+ break;
+ case DDR3_SDRAM:
+ case DDR4_SDRAM:
+ s->spd_rev_major = bytes[1] >> 4;
+ s->spd_rev_minor = bytes[1] & 0xf;
+ break;
+ }
+ s->vendor = vendor_match(s->vendor_str, NULL);
+ s->dram_vendor = vendor_match(s->dram_vendor_str, NULL);
+ dimm_list = g_slist_append(dimm_list, s);
+ }
}
- return g_string_free(output, FALSE);
+ return dimm_list;
}
-void scan_spd_do(void)
-{
- GDir *dir = NULL;
- GSList *dimm_list = NULL;
- gboolean use_sysfs = FALSE;
- gchar *dir_entry;
- gchar *list;
-
- if (g_file_test("/sys/bus/i2c/drivers/eeprom", G_FILE_TEST_EXISTS)) {
- dir = g_dir_open("/sys/bus/i2c/drivers/eeprom", 0, NULL);
- use_sysfs = TRUE;
- } else if (g_file_test("/proc/sys/dev/sensors", G_FILE_TEST_EXISTS)) {
- dir = g_dir_open("/proc/sys/dev/sensors", 0, NULL);
- }
+struct SpdDriver {
+ const char *driver;
+ const char *dir_path;
+ const gint max_size;
+ const gboolean use_sysfs;
+ const char *spd_name;
+};
- if (!dir) {
- g_free(spd_info);
- if (!g_file_test("/sys/module/eeprom", G_FILE_TEST_EXISTS)) {
- spd_info = g_strdup(_("[SPD]\n"
- "Please load the eeprom module to obtain information about memory SPD=\n"
- "[$ShellParam$]\n"
- "ReloadInterval=500\n"));
- } else {
- spd_info = g_strdup(_("[SPD]\n" "Reading memory SPD not supported on this system=\n"));
- }
-
- return;
+static const struct SpdDriver spd_drivers[] = {
+ { "ee1004", "/sys/bus/i2c/drivers/ee1004", 512, TRUE, "ee1004"},
+ { "at24", "/sys/bus/i2c/drivers/at24" , 256, TRUE, "spd"},
+ { "eeprom", "/sys/bus/i2c/drivers/eeprom", 256, TRUE, "eeprom"},
+ { "eeprom-proc", "/proc/sys/dev/sensors" , 256, FALSE, NULL},
+ { NULL }
+};
+
+GSList *spd_scan() {
+ GDir *dir = NULL;
+ GSList *eeprom_list = NULL, *dimm_list = NULL;
+ gchar *dimm_list_entry, *dir_entry, *name_file, *name;
+ const struct SpdDriver *driver;
+ gboolean driver_found = FALSE;
+ gboolean is_spd = 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)) {
+ dir = g_dir_open(driver->dir_path, 0, NULL);
+ if (!dir) continue;
+
+ driver_found = TRUE;
+ while ((dir_entry = (char *)g_dir_read_name(dir))) {
+ is_spd = FALSE;
+
+ if (driver->use_sysfs) {
+ name_file = NULL;
+ name = NULL;
+
+ if (isdigit(dir_entry[0])) {
+ name_file = g_build_filename(driver->dir_path, dir_entry, "name", NULL);
+ g_file_get_contents(name_file, &name, NULL, NULL);
+
+ is_spd = g_strcmp0(name, driver->spd_name);
+
+ g_free(name_file);
+ g_free(name);
+ }
+ }
+ else {
+ is_spd = g_str_has_prefix(dir_entry, "eeprom-");
+ }
+
+ if (is_spd){
+ dimm_list_entry = g_strdup_printf("%s/%s", driver->dir_path, dir_entry);
+ eeprom_list = g_slist_prepend(eeprom_list, dimm_list_entry);
+ }
+ }
+
+ g_dir_close(dir);
+
+ if (eeprom_list) {
+ dimm_list = decode_dimms2(eeprom_list, driver->driver, driver->use_sysfs, driver->max_size);
+ g_slist_free(eeprom_list);
+ eeprom_list = NULL;
+ }
+ if (dimm_list) break;
+ }
}
- while ((dir_entry = (char *) g_dir_read_name(dir))) {
- if (use_sysfs && isdigit(dir_entry[0])) {
- dimm_list = g_slist_prepend(dimm_list, g_strdup_printf("/sys/bus/i2c/drivers/eeprom/%s", dir_entry));
- } else if (g_str_has_prefix(dir_entry, "eeprom-")) {
- dimm_list = g_slist_prepend(dimm_list, g_strdup_printf("/proc/sys/dev/sensors/%s", dir_entry));
- }
+ if (!driver_found) {
+ if (!g_file_test("/sys/module/eeprom", G_FILE_TEST_EXISTS) &&
+ !g_file_test("/sys/module/at24", G_FILE_TEST_EXISTS)) {
+ spd_no_driver = TRUE; /* trigger hinote for no eeprom driver */
+ } else {
+ spd_no_support = TRUE; /* trigger hinote for unsupported system */
+ }
}
- g_dir_close(dir);
-
- list = decode_dimms(dimm_list, use_sysfs);
- g_slist_free(dimm_list);
-
- 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);
+ return dimm_list;
}
diff --git a/modules/devices/spd-vendors.c b/modules/devices/spd-vendors.c
new file mode 100644
index 00000000..80b2a6a4
--- /dev/null
+++ b/modules/devices/spd-vendors.c
@@ -0,0 +1,292 @@
+/*
+ * spd-decode.c, spd-vendors.c
+ * Copyright (c) 2010 L. A. F. Pereira
+ * modified by Ondrej Čerman (2019)
+ * modified by Burt P. (2019)
+ *
+ * Based on decode-dimms.pl
+ * Copyright 1998, 1999 Philip Edelbrock <phil@netroedge.com>
+ * modified by Christian Zuckschwerdt <zany@triq.net>
+ * modified by Burkart Lingner <burkart@bollchen.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* from decode-dimms, in the i2c-tools package:
+ * https://github.com/angeloc/i2c-tools/blob/master/eeprom/decode-dimms
+ *
+ * STANDARD MANUFACTURERS IDENTIFICATION CODEs
+ * as defined in JEP106
+ *
+ * As of: 28 June 2019
+ *
+ */
+
+#define VENDORS_BANKS 8
+#define VENDORS_ITEMS 128
+#define JEDEC_MFG_STR(b,i) ( (b >= 0 && b < VENDORS_BANKS && i < VENDORS_ITEMS) ? vendors[(b)][(i)] : NULL )
+static const char* vendors[VENDORS_BANKS][VENDORS_ITEMS] =
+{
+{"AMD", "AMI", "Fairchild", "Fujitsu",
+ "GTE", "Harris", "Hitachi", "Inmos",
+ "Intel", "I.T.T.", "Intersil", "Monolithic Memories",
+ "Mostek", "Freescale (former Motorola)", "National", "NEC",
+ "RCA", "Raytheon", "Conexant (Rockwell)", "Seeq",
+ "NXP (former Signetics, Philips Semi.)", "Synertek", "Texas Instruments", "Toshiba",
+ "Xicor", "Zilog", "Eurotechnique", "Mitsubishi",
+ "Lucent (AT&T)", "Exel", "Atmel", "SGS/Thomson",
+ "Lattice Semi.", "NCR", "Wafer Scale Integration", "IBM",
+ "Tristar", "Visic", "Intl. CMOS Technology", "SSSI",
+ "MicrochipTechnology", "Ricoh Ltd.", "VLSI", "Micron Technology",
+ "SK Hynix (former Hyundai Electronics)", "OKI Semiconductor", "ACTEL", "Sharp",
+ "Catalyst", "Panasonic", "IDT", "Cypress",
+ "DEC", "LSI Logic", "Zarlink (former Plessey)", "UTMC",
+ "Thinking Machine", "Thomson CSF", "Integrated CMOS (Vertex)", "Honeywell",
+ "Tektronix", "Oracle Corporation (former Sun Microsystems)", "Silicon Storage Technology", "ProMos/Mosel Vitelic",
+ "Infineon (former Siemens)", "Macronix", "Xerox", "Plus Logic",
+ "SunDisk", "Elan Circuit Tech.", "European Silicon Str.", "Apple Computer",
+ "Xilinx", "Compaq", "Protocol Engines", "SCI",
+ "Seiko Instruments", "Samsung", "I3 Design System", "Klic",
+ "Crosspoint Solutions", "Alliance Semiconductor", "Tandem", "Hewlett-Packard",
+ "Integrated Silicon Solutions", "Brooktree", "New Media", "MHS Electronic",
+ "Performance Semi.", "Winbond Electronic", "Kawasaki Steel", "Bright Micro",
+ "TECMAR", "Exar", "PCMCIA", "LG Semi (former Goldstar)",
+ "Northern Telecom", "Sanyo", "Array Microsystems", "Crystal Semiconductor",
+ "Analog Devices", "PMC-Sierra", "Asparix", "Convex Computer",
+ "Quality Semiconductor", "Nimbus Technology", "Transwitch", "Micronas (ITT Intermetall)",
+ "Cannon", "Altera", "NEXCOM", "QUALCOMM",
+ "Sony", "Cray Research", "AMS(Austria Micro)", "Vitesse",
+ "Aster Electronics", "Bay Networks (Synoptic)", "Zentrum or ZMD", "TRW",
+ "Thesys", "Solbourne Computer", "Allied-Signal", "Dialog",
+ "Media Vision", "Numonyx Corporation (former Level One Communication)"},
+{"Cirrus Logic", "National Instruments", "ILC Data Device", "Alcatel Mietec",
+ "Micro Linear", "Univ. of NC", "JTAG Technologies", "BAE Systems",
+ "Nchip", "Galileo Tech", "Bestlink Systems", "Graychip",
+ "GENNUM", "VideoLogic", "Robert Bosch", "Chip Express",
+ "DATARAM", "United Microelec Corp.", "TCSI", "Smart Modular",
+ "Hughes Aircraft", "Lanstar Semiconductor", "Qlogic", "Kingston",
+ "Music Semi", "Ericsson Components", "SpaSE", "Eon Silicon Devices",
+ "Programmable Micro Corp", "DoD", "Integ. Memories Tech.", "Corollary Inc.",
+ "Dallas Semiconductor", "Omnivision", "EIV(Switzerland)", "Novatel Wireless",
+ "Zarlink (former Mitel)", "Clearpoint", "Cabletron", "STEC (former Silicon Technology)",
+ "Vanguard", "Hagiwara Sys-Com", "Vantis", "Celestica",
+ "Century", "Hal Computers", "Rohm Company Ltd.", "Juniper Networks",
+ "Libit Signal Processing", "Mushkin Enhanced Memory", "Tundra Semiconductor", "Adaptec Inc.",
+ "LightSpeed Semi.", "ZSP Corp.", "AMIC Technology", "Adobe Systems",
+ "Dynachip", "PNY Electronics", "Newport Digital", "MMC Networks",
+ "T Square", "Seiko Epson", "Broadcom", "Viking Components",
+ "V3 Semiconductor", "Flextronics (former Orbit)", "Suwa Electronics", "Transmeta",
+ "Micron CMS", "American Computer & Digital Components Inc", "Enhance 3000 Inc", "Tower Semiconductor",
+ "CPU Design", "Price Point", "Maxim Integrated Product", "Tellabs",
+ "Centaur Technology", "Unigen Corporation", "Transcend Information", "Memory Card Technology",
+ "CKD Corporation Ltd.", "Capital Instruments, Inc.", "Aica Kogyo, Ltd.", "Linvex Technology",
+ "MSC Vertriebs GmbH", "AKM Company, Ltd.", "Dynamem, Inc.", "NERA ASA",
+ "GSI Technology", "Dane-Elec (C Memory)", "Acorn Computers", "Lara Technology",
+ "Oak Technology, Inc.", "Itec Memory", "Tanisys Technology", "Truevision",
+ "Wintec Industries", "Super PC Memory", "MGV Memory", "Galvantech",
+ "Gadzoox Nteworks", "Multi Dimensional Cons.", "GateField", "Integrated Memory System",
+ "Triscend", "XaQti", "Goldenram", "Clear Logic",
+ "Cimaron Communications", "Nippon Steel Semi. Corp.", "Advantage Memory", "AMCC",
+ "LeCroy", "Yamaha Corporation", "Digital Microwave", "NetLogic Microsystems",
+ "MIMOS Semiconductor", "Advanced Fibre", "BF Goodrich Data.", "Epigram",
+ "Acbel Polytech Inc.", "Apacer Technology", "Admor Memory", "FOXCONN",
+ "Quadratics Superconductor", "3COM"},
+{"Camintonn Corporation", "ISOA Incorporated", "Agate Semiconductor", "ADMtek Incorporated",
+ "HYPERTEC", "Adhoc Technologies", "MOSAID Technologies", "Ardent Technologies",
+ "Switchcore", "Cisco Systems, Inc.", "Allayer Technologies", "WorkX AG (Wichman)",
+ "Oasis Semiconductor", "Novanet Semiconductor", "E-M Solutions", "Power General",
+ "Advanced Hardware Arch.", "Inova Semiconductors GmbH", "Telocity", "Delkin Devices",
+ "Symagery Microsystems", "C-Port Corporation", "SiberCore Technologies", "Southland Microsystems",
+ "Malleable Technologies", "Kendin Communications", "Great Technology Microcomputer", "Sanmina Corporation",
+ "HADCO Corporation", "Corsair", "Actrans System Inc.", "ALPHA Technologies",
+ "Silicon Laboratories, Inc. (Cygnal)", "Artesyn Technologies", "Align Manufacturing", "Peregrine Semiconductor",
+ "Chameleon Systems", "Aplus Flash Technology", "MIPS Technologies", "Chrysalis ITS",
+ "ADTEC Corporation", "Kentron Technologies", "Win Technologies", "Tachyon Semiconductor (former ASIC Designs Inc.)",
+ "Extreme Packet Devices", "RF Micro Devices", "Siemens AG", "Sarnoff Corporation",
+ "Itautec SA (former Itautec Philco SA)", "Radiata Inc.", "Benchmark Elect. (AVEX)", "Legend",
+ "SpecTek Incorporated", "Hi/fn", "Enikia Incorporated", "SwitchOn Networks",
+ "AANetcom Incorporated", "Micro Memory Bank", "ESS Technology", "Virata Corporation",
+ "Excess Bandwidth", "West Bay Semiconductor", "DSP Group", "Newport Communications",
+ "Chip2Chip Incorporated", "Phobos Corporation", "Intellitech Corporation", "Nordic VLSI ASA",
+ "Ishoni Networks", "Silicon Spice", "Alchemy Semiconductor", "Agilent Technologies",
+ "Centillium Communications", "W.L. Gore", "HanBit Electronics", "GlobeSpan",
+ "Element 14", "Pycon", "Saifun Semiconductors", "Sibyte, Incorporated",
+ "MetaLink Technologies", "Feiya Technology", "I & C Technology", "Shikatronics",
+ "Elektrobit", "Megic", "Com-Tier", "Malaysia Micro Solutions",
+ "Hyperchip", "Gemstone Communications", "Anadigm (former Anadyne)", "3ParData",
+ "Mellanox Technologies", "Tenx Technologies", "Helix AG", "Domosys",
+ "Skyup Technology", "HiNT Corporation", "Chiaro", "MDT Technologies GmbH (former MCI Computer GMBH)",
+ "Exbit Technology A/S", "Integrated Technology Express", "AVED Memory", "Legerity",
+ "Jasmine Networks", "Caspian Networks", "nCUBE", "Silicon Access Networks",
+ "FDK Corporation", "High Bandwidth Access", "MultiLink Technology", "BRECIS",
+ "World Wide Packets", "APW", "Chicory Systems", "Xstream Logic",
+ "Fast-Chip", "Zucotto Wireless", "Realchip", "Galaxy Power",
+ "eSilicon", "Morphics Technology", "Accelerant Networks", "Silicon Wave",
+ "SandCraft", "Elpida"},
+{"Solectron", "Optosys Technologies", "Buffalo (former Melco)", "TriMedia Technologies",
+ "Cyan Technologies", "Global Locate", "Optillion", "Terago Communications",
+ "Ikanos Communications", "Princeton Technology", "Nanya Technology", "Elite Flash Storage",
+ "Mysticom", "LightSand Communications", "ATI Technologies", "Agere Systems",
+ "NeoMagic", "AuroraNetics", "Golden Empire", "Mushkin",
+ "Tioga Technologies", "Netlist", "TeraLogic", "Cicada Semiconductor",
+ "Centon Electronics", "Tyco Electronics", "Magis Works", "Zettacom",
+ "Cogency Semiconductor", "Chipcon AS", "Aspex Technology", "F5 Networks",
+ "Programmable Silicon Solutions", "ChipWrights", "Acorn Networks", "Quicklogic",
+ "Kingmax Semiconductor", "BOPS", "Flasys", "BitBlitz Communications",
+ "eMemory Technology", "Procket Networks", "Purple Ray", "Trebia Networks",
+ "Delta Electronics", "Onex Communications", "Ample Communications", "Memory Experts Intl",
+ "Astute Networks", "Azanda Network Devices", "Dibcom", "Tekmos",
+ "API NetWorks", "Bay Microsystems", "Firecron Ltd", "Resonext Communications",
+ "Tachys Technologies", "Equator Technology", "Concept Computer", "SILCOM",
+ "3Dlabs", "c't Magazine", "Sanera Systems", "Silicon Packets",
+ "Viasystems Group", "Simtek", "Semicon Devices Singapore", "Satron Handelsges",
+ "Improv Systems", "INDUSYS GmbH", "Corrent", "Infrant Technologies",
+ "Ritek Corp", "empowerTel Networks", "Hypertec", "Cavium Networks",
+ "PLX Technology", "Massana Design", "Intrinsity", "Valence Semiconductor",
+ "Terawave Communications", "IceFyre Semiconductor", "Primarion", "Picochip Designs Ltd",
+ "Silverback Systems", "Jade Star Technologies", "Pijnenburg Securealink",
+ "takeMS - Ultron AG (former Memorysolution GmbH)", "Cambridge Silicon Radio",
+ "Swissbit", "Nazomi Communications", "eWave System",
+ "Rockwell Collins", "Picocel Co., Ltd.", "Alphamosaic Ltd", "Sandburst",
+ "SiCon Video", "NanoAmp Solutions", "Ericsson Technology", "PrairieComm",
+ "Mitac International", "Layer N Networks", "MtekVision", "Allegro Networks",
+ "Marvell Semiconductors", "Netergy Microelectronic", "NVIDIA", "Internet Machines",
+ "Peak Electronics", "Litchfield Communication", "Accton Technology", "Teradiant Networks",
+ "Scaleo Chip (former Europe Technologies)", "Cortina Systems", "RAM Components", "Raqia Networks",
+ "ClearSpeed", "Matsushita Battery", "Xelerated", "SimpleTech",
+ "Utron Technology", "Astec International", "AVM gmbH", "Redux Communications",
+ "Dot Hill Systems", "TeraChip"},
+{"T-RAM Incorporated", "Innovics Wireless", "Teknovus", "KeyEye Communications",
+ "Runcom Technologies", "RedSwitch", "Dotcast", "Silicon Mountain Memory",
+ "Signia Technologies", "Pixim", "Galazar Networks", "White Electronic Designs",
+ "Patriot Scientific", "Neoaxiom Corporation", "3Y Power Technology", "Scaleo Chip (former Europe Technologies)",
+ "Potentia Power Systems", "C-guys Incorporated", "Digital Communications Technology Incorporated", "Silicon-Based Technology",
+ "Fulcrum Microsystems", "Positivo Informatica Ltd", "XIOtech Corporation", "PortalPlayer",
+ "Zhiying Software", "Parker Vision, Inc. (former Direct2Data)", "Phonex Broadband", "Skyworks Solutions",
+ "Entropic Communications", "Pacific Force Technology", "Zensys A/S", "Legend Silicon Corp.",
+ "sci-worx GmbH", "SMSC (former Oasis Silicon Systems)", "Renesas Electronics (former Renesas Technology)", "Raza Microelectronics",
+ "Phyworks", "MediaTek", "Non-cents Productions", "US Modular",
+ "Wintegra Ltd", "Mathstar", "StarCore", "Oplus Technologies",
+ "Mindspeed", "Just Young Computer", "Radia Communications", "OCZ",
+ "Emuzed", "LOGIC Devices", "Inphi Corporation", "Quake Technologies",
+ "Vixel", "SolusTek", "Kongsberg Maritime", "Faraday Technology",
+ "Altium Ltd.", "Insyte", "ARM Ltd.", "DigiVision",
+ "Vativ Technologies", "Endicott Interconnect Technologies", "Pericom", "Bandspeed",
+ "LeWiz Communications", "CPU Technology", "Ramaxel Technology", "DSP Group",
+ "Axis Communications", "Legacy Electronics", "Chrontel", "Powerchip Semiconductor",
+ "MobilEye Technologies", "Excel Semiconductor", "A-DATA Technology", "VirtualDigm",
+ "G.Skill Intl", "Quanta Computer", "Yield Microelectronics", "Afa Technologies",
+ "KINGBOX Technology Co. Ltd.", "Ceva", "iStor Networks", "Advance Modules",
+ "Microsoft", "Open-Silicon", "Goal Semiconductor", "ARC International",
+ "Simmtec", "Metanoia", "Key Stream", "Lowrance Electronics",
+ "Adimos", "SiGe Semiconductor", "Fodus Communications", "Credence Systems Corp.",
+ "Genesis Microchip Inc.", "Vihana, Inc.", "WIS Technologies", "GateChange Technologies",
+ "High Density Devices AS", "Synopsys", "Gigaram", "Enigma Semiconductor Inc.",
+ "Century Micro Inc.", "Icera Semiconductor", "Mediaworks Integrated Systems", "O'Neil Product Development",
+ "Supreme Top Technology Ltd.", "MicroDisplay Corporation", "Team Group Inc.", "Sinett Corporation",
+ "Toshiba Corporation", "Tensilica", "SiRF Technology", "Bacoc Inc.",
+ "SMaL Camera Technologies", "Thomson SC", "Airgo Networks", "Wisair Ltd.",
+ "SigmaTel", "Arkados", "Compete IT gmbH Co. KG", "Eudar Technology Inc.",
+ "Focus Enhancements", "Xyratex"},
+{"Specular Networks", "Patriot Memory", "U-Chip Technology Corp.", "Silicon Optix",
+ "Greenfield Networks", "CompuRAM GmbH", "Stargen, Inc.", "NetCell Corporation",
+ "Excalibrus Technologies Ltd", "SCM Microsystems", "Xsigo Systems, Inc.", "CHIPS & Systems Inc",
+ "Tier 1 Multichip Solutions", "CWRL Labs", "Teradici", "Gigaram, Inc.",
+ "g2 Microsystems", "PowerFlash Semiconductor", "P.A. Semi, Inc.", "NovaTech Solutions, S.A.",
+ "c2 Microsystems, Inc.", "Level5 Networks", "COS Memory AG", "Innovasic Semiconductor",
+ "02IC Co. Ltd", "Tabula, Inc.", "Crucial Technology", "Chelsio Communications",
+ "Solarflare Communications", "Xambala Inc.", "EADS Astrium", "Terra Semiconductor Inc. (former ATO Semicon Co. Ltd.)",
+ "Imaging Works, Inc.", "Astute Networks, Inc.", "Tzero", "Emulex",
+ "Power-One", "Pulse~LINK Inc.", "Hon Hai Precision Industry", "White Rock Networks Inc.",
+ "Telegent Systems USA, Inc.", "Atrua Technologies, Inc.", "Acbel Polytech Inc.",
+ "eRide Inc.","ULi Electronics Inc.", "Magnum Semiconductor Inc.", "neoOne Technology, Inc.",
+ "Connex Technology, Inc.", "Stream Processors, Inc.", "Focus Enhancements", "Telecis Wireless, Inc.",
+ "uNav Microelectronics", "Tarari, Inc.", "Ambric, Inc.", "Newport Media, Inc.", "VMTS",
+ "Enuclia Semiconductor, Inc.", "Virtium Technology Inc.", "Solid State System Co., Ltd.", "Kian Tech LLC",
+ "Artimi", "Power Quotient International", "Avago Technologies", "ADTechnology", "Sigma Designs",
+ "SiCortex, Inc.", "Ventura Technology Group", "eASIC", "M.H.S. SAS", "Micro Star International",
+ "Rapport Inc.", "Makway International", "Broad Reach Engineering Co.",
+ "Semiconductor Mfg Intl Corp", "SiConnect", "FCI USA Inc.", "Validity Sensors",
+ "Coney Technology Co. Ltd.", "Spans Logic", "Neterion Inc.", "Qimonda",
+ "New Japan Radio Co. Ltd.", "Velogix", "Montalvo Systems", "iVivity Inc.", "Walton Chaintech",
+ "AENEON", "Lorom Industrial Co. Ltd.", "Radiospire Networks", "Sensio Technologies, Inc.",
+ "Nethra Imaging", "Hexon Technology Pte Ltd", "CompuStocx (CSX)", "Methode Electronics, Inc.",
+ "Connect One Ltd.", "Opulan Technologies", "Septentrio NV", "Goldenmars Technology Inc.",
+ "Kreton Corporation", "Cochlear Ltd.", "Altair Semiconductor", "NetEffect, Inc.",
+ "Spansion, Inc.", "Taiwan Semiconductor Mfg", "Emphany Systems Inc.",
+ "ApaceWave Technologies", "Mobilygen Corporation", "Tego", "Cswitch Corporation",
+ "Haier (Beijing) IC Design Co.", "MetaRAM", "Axel Electronics Co. Ltd.", "Tilera Corporation",
+ "Aquantia", "Vivace Semiconductor", "Redpine Signals", "Octalica", "InterDigital Communications",
+ "Avant Technology", "Asrock, Inc.", "Availink", "Quartics, Inc.", "Element CXI",
+ "Innovaciones Microelectronicas", "VeriSilicon Microelectronics", "W5 Networks"},
+{"MOVEKING", "Mavrix Technology, Inc.", "CellGuide Ltd.", "Faraday Technology",
+ "Diablo Technologies, Inc.", "Jennic", "Octasic", "Molex Incorporated", "3Leaf Networks",
+ "Bright Micron Technology", "Netxen", "NextWave Broadband Inc.", "DisplayLink", "ZMOS Technology",
+ "Tec-Hill", "Multigig, Inc.", "Amimon", "Euphonic Technologies, Inc.", "BRN Phoenix",
+ "InSilica", "Ember Corporation", "Avexir Technologies Corporation", "Echelon Corporation",
+ "Edgewater Computer Systems", "XMOS Semiconductor Ltd.", "GENUSION, Inc.", "Memory Corp NV",
+ "SiliconBlue Technologies", "Rambus Inc.", "Andes Technology Corporation", "Coronis Systems",
+ "Achronix Semiconductor", "Siano Mobile Silicon Ltd.", "Semtech Corporation", "Pixelworks Inc.",
+ "Gaisler Research AB", "Teranetics", "Toppan Printing Co. Ltd.", "Kingxcon",
+ "Silicon Integrated Systems", "I-O Data Device, Inc.", "NDS Americas Inc.", "Solomon Systech Limited",
+ "On Demand Microelectronics", "Amicus Wireless Inc.", "SMARDTV SNC", "Comsys Communication Ltd.",
+ "Movidia Ltd.", "Javad GNSS, Inc.", "Montage Technology Group", "Trident Microsystems", "Super Talent",
+ "Optichron, Inc.", "Future Waves UK Ltd.", "SiBEAM, Inc.", "Inicore, Inc.", "Virident Systems",
+ "M2000, Inc.", "ZeroG Wireless, Inc.", "Gingle Technology Co. Ltd.", "Space Micro Inc.", "Wilocity",
+ "Novafora, Inc.", "iKoa Corporation", "ASint Technology", "Ramtron", "Plato Networks Inc.",
+ "IPtronics AS", "Infinite-Memories", "Parade Technologies Inc.", "Dune Networks",
+ "GigaDevice Semiconductor", "Modu Ltd.", "CEITEC", "Northrop Grumman", "XRONET Corporation",
+ "Sicon Semiconductor AB", "Atla Electronics Co. Ltd.", "TOPRAM Technology", "Silego Technology Inc.",
+ "Kinglife", "Ability Industries Ltd.", "Silicon Power Computer & Communications",
+ "Augusta Technology, Inc.", "Nantronics Semiconductors", "Hilscher Gesellschaft", "Quixant Ltd.",
+ "Percello Ltd.", "NextIO Inc.", "Scanimetrics Inc.", "FS-Semi Company Ltd.", "Infinera Corporation",
+ "SandForce Inc.", "Lexar Media", "Teradyne Inc.", "Memory Exchange Corp.", "Suzhou Smartek Electronics",
+ "Avantium Corporation", "ATP Electronics Inc.", "Valens Semiconductor Ltd", "Agate Logic, Inc.",
+ "Netronome", "Zenverge, Inc.", "N-trig Ltd", "SanMax Technologies Inc.", "Contour Semiconductor Inc.",
+ "TwinMOS", "Silicon Systems, Inc.", "V-Color Technology Inc.", "Certicom Corporation", "JSC ICC Milandr",
+ "PhotoFast Global Inc.", "InnoDisk Corporation", "Muscle Power", "Energy Micro", "Innofidei",
+ "CopperGate Communications", "Holtek Semiconductor Inc.", "Myson Century, Inc.", "FIDELIX",
+ "Red Digital Cinema", "Densbits Technology", "Zempro", "MoSys", "Provigent", "Triad Semiconductor, Inc."},
+{"Siklu Communication Ltd.", "A Force Manufacturing Ltd.", "Strontium", "Abilis Systems", "Siglead, Inc.",
+ "Ubicom, Inc.", "Unifosa Corporation", "Stretch, Inc.", "Lantiq Deutschland GmbH", "Visipro",
+ "EKMemory", "Microelectronics Institute ZTE", "Cognovo Ltd.", "Carry Technology Co. Ltd.", "Nokia",
+ "King Tiger Technology", "Sierra Wireless", "HT Micron", "Albatron Technology Co. Ltd.",
+ "Leica Geosystems AG", "BroadLight", "AEXEA", "ClariPhy Communications, Inc.", "Green Plug",
+ "Design Art Networks", "Mach Xtreme Technology Ltd.", "ATO Solutions Co. Ltd.", "Ramsta",
+ "Greenliant Systems, Ltd.", "Teikon", "Antec Hadron", "NavCom Technology, Inc.",
+ "Shanghai Fudan Microelectronics", "Calxeda, Inc.", "JSC EDC Electronics", "Kandit Technology Co. Ltd.",
+ "Ramos Technology", "Goldenmars Technology", "XeL Technology Inc.", "Newzone Corporation",
+ "ShenZhen MercyPower Tech", "Nanjing Yihuo Technology", "Nethra Imaging Inc.", "SiTel Semiconductor BV",
+ "SolidGear Corporation", "Topower Computer Ind Co Ltd.", "Wilocity", "Profichip GmbH",
+ "Gerad Technologies", "Ritek Corporation", "Gomos Technology Limited", "Memoright Corporation",
+ "D-Broad, Inc.", "HiSilicon Technologies", "Syndiant Inc.", "Enverv Inc.", "Cognex",
+ "Xinnova Technology Inc.", "Ultron AG", "Concord Idea Corporation", "AIM Corporation",
+ "Lifetime Memory Products", "Ramsway", "Recore Systems BV", "Haotian Jinshibo Science Tech",
+ "Being Advanced Memory", "Adesto Technologies", "Giantec Semiconductor, Inc.", "HMD Electronics AG",
+ "Gloway International (HK)", "Kingcore", "Anucell Technology Holding",
+ "Accord Software & Systems Pvt. Ltd.", "Active-Semi Inc.", "Denso Corporation", "TLSI Inc.",
+ "Shenzhen Daling Electronic Co. Ltd.", "Mustang", "Orca Systems", "Passif Semiconductor",
+ "GigaDevice Semiconductor (Beijing) Inc.", "Memphis Electronic", "Beckhoff Automation GmbH",
+ "Harmony Semiconductor Corp (former ProPlus Design Solutions)", "Air Computers SRL", "TMT Memory",
+ "Eorex Corporation", "Xingtera", "Netsol", "Bestdon Technology Co. Ltd.", "Baysand Inc.",
+ "Uroad Technology Co. Ltd. (former Triple Grow Industrial Ltd.)", "Wilk Elektronik S.A.",
+ "AAI", "Harman", "Berg Microelectronics Inc.", "ASSIA, Inc.", "Visiontek Products LLC",
+ "OCMEMORY", "Welink Solution Inc.", "Shark Gaming", "Avalanche Technology",
+ "R&D Center ELVEES OJSC", "KingboMars Technology Co. Ltd.",
+ "High Bridge Solutions Industria Eletronica", "Transcend Technology Co. Ltd.",
+ "Everspin Technologies", "Hon-Hai Precision", "Smart Storage Systems", "Toumaz Group",
+ "Zentel Electronics Corporation", "Panram International Corporation",
+ "Silicon Space Technology"}
+};
diff --git a/modules/devices/storage.c b/modules/devices/storage.c
index 0c393682..bbf9b195 100644
--- a/modules/devices/storage.c
+++ b/modules/devices/storage.c
@@ -1,10 +1,11 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
+ * modified by Ondrej Čerman (2019-2021)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,12 +21,464 @@
#include "hardinfo.h"
#include "devices.h"
+#include "udisks2_util.h"
+#include "storage_util.h"
+
+#define UNKIFNULL_AC(f) (f != NULL) ? f : _("(Unknown)");
gchar *storage_icons = NULL;
+gchar *nvme_pci_sections(pcid *p) {
+ const gchar *vendor, *svendor, *product, *sproduct;
+
+ if (!p) return NULL;
+
+ vendor = UNKIFNULL_AC(p->vendor_id_str);
+ svendor = UNKIFNULL_AC(p->sub_vendor_id_str);
+ product = UNKIFNULL_AC(p->device_id_str);
+ sproduct = UNKIFNULL_AC(p->sub_device_id_str);
+
+ gchar *vendor_device_str;
+ if (p->vendor_id == p->sub_vendor_id && p->device_id == p->sub_device_id) {
+ vendor_device_str = g_strdup_printf("[%s]\n"
+ /* Vendor */ "$^$%s=[%04x] %s\n"
+ /* Device */ "%s=[%04x] %s\n",
+ _("NVMe Controller"),
+ _("Vendor"), p->vendor_id, vendor,
+ _("Device"), p->device_id, product);
+ } else {
+ vendor_device_str = g_strdup_printf("[%s]\n"
+ /* Vendor */ "$^$%s=[%04x] %s\n"
+ /* Device */ "%s=[%04x] %s\n"
+ /* Sub-device vendor */ "$^$%s=[%04x] %s\n"
+ /* Sub-device */ "%s=[%04x] %s\n",
+ _("NVMe Controller"),
+ _("Vendor"), p->vendor_id, vendor,
+ _("Device"), p->device_id, product,
+ _("SVendor"), p->sub_vendor_id, svendor,
+ _("SDevice"), p->sub_device_id, sproduct);
+ }
+
+ gchar *pcie_str;
+ if (p->pcie_width_curr) {
+ pcie_str = g_strdup_printf("[%s]\n"
+ /* Addy */ "%s=PCI/%s\n"
+ /* Width (max) */ "%s=x%u\n"
+ /* Speed (max) */ "%s=%0.1f %s\n",
+ _("PCI Express"),
+ _("Location"), p->slot_str,
+ _("Maximum Link Width"), p->pcie_width_max,
+ _("Maximum Link Speed"), p->pcie_speed_max, _("GT/s") );
+ } else
+ pcie_str = strdup("");
+
+ gchar *ret = g_strdup_printf("%s%s", vendor_device_str, pcie_str);
+ g_free(vendor_device_str);
+ g_free(pcie_str);
+ return ret;
+}
+
+gboolean __scan_udisks2_devices(void) {
+ GSList *node, *drives;
+ u2driveext *ext;
+ udiskd *disk;
+ udiskp *part;
+ udisksa *attrib;
+ gchar *udisks2_storage_list = NULL, *features = NULL, *moreinfo = NULL;
+ gchar *devid, *size, *tmp = NULL, *media_comp = NULL, *ven_tag = NULL;
+ const gchar *url, *media_label, *alabel, *icon, *media_curr = NULL;
+ int n = 0, i, j, m;
+
+ // http://storaged.org/doc/udisks2-api/latest/gdbus-org.freedesktop.UDisks2.Drive.html#gdbus-property-org-freedesktop-UDisks2-Drive.MediaCompatibility
+ static struct {
+ char *media;
+ char *label;
+ char *icon;
+ } media_info[] = {
+ { "thumb", "Thumb-drive", "usbfldisk" },
+ { "flash", "Flash Card", "usbfldisk" },
+ { "flash_cf", "CompactFlash", "usbfldisk" },
+ { "flash_ms", "MemoryStick", "usbfldisk" },
+ { "flash_sm", "SmartMedia", "usbfldisk" },
+ { "flash_sd", "SD", "usbfldisk" },
+ { "flash_sdhc", "SDHC", "usbfldisk" },
+ { "flash_sdxc", "SDXC", "usbfldisk" },
+ { "flash_mmc", "MMC", "usbfldisk" },
+ { "floppy", "Floppy Disk", "media-floppy" },
+ { "floppy_zip", "Zip Disk", "media-floppy" },
+ { "floppy_jaz", "Jaz Disk", "media-floppy" },
+ { "optical", "Optical Disc", "cdrom" },
+ { "optical_cd", "CD-ROM", "cdrom" },
+ { "optical_cd_r", "CD-R", "cdrom" },
+ { "optical_cd_rw", "CD-RW", "cdrom" },
+ { "optical_dvd", "DVD-ROM", "cdrom" },
+ { "optical_dvd_r", "DVD-R", "cdrom" },
+ { "optical_dvd_rw", "DVD-RW", "cdrom" },
+ { "optical_dvd_ram", "DVD-RAM", "cdrom" },
+ { "optical_dvd_plus_r", "DVD+R" , "cdrom" },
+ { "optical_dvd_plus_rw", "DVD+RW" , "cdrom" },
+ { "optical_dvd_plus_r_dl", "DVD+R DL", "cdrom" },
+ { "optical_dvd_plus_rw_dl", "DVD+RW DL", "cdrom" },
+ { "optical_bd", "BD-ROM", "cdrom" },
+ { "optical_bd_r", "BD-R", "cdrom" },
+ { "optical_bd_re", "BD-RE", "cdrom" },
+ { "optical_hddvd", "HD DVD-ROM", "cdrom" },
+ { "optical_hddvd_r", "HD DVD-R", "cdrom" },
+ { "optical_hddvd_rw", "HD DVD-RW", "cdrom" },
+ { "optical_mo", "MO Disc", "cdrom" },
+ { "optical_mrw", "MRW Media", "cdrom" },
+ { "optical_mrw_w", "MRW Media (write)", "cdrom" },
+ { NULL, NULL }
+ };
+
+ struct {
+ char *identifier;
+ char *label;
+ } smart_attrib_info[] = {
+ { "raw-read-error-rate", _("Read Error Rate" ) },
+ { "throughput-performance", _("Throughput Performance") },
+ { "spin-up-time", _("Spin-Up Time") },
+ { "start-stop-count", _("Start/Stop Count") },
+ { "reallocated-sector-count", _("Reallocated Sector Count") },
+ { "read-channel-margin", _("Read Channel Margin") },
+ { "seek-error-rate", _("Seek Error Rate") },
+ { "seek-time-performance", _("Seek Timer Performance") },
+ { "power-on-hours", _("Power-On Hours") },
+ { "spin-retry-count", _("Spin Retry Count") },
+ { "calibration-retry-count", _("Calibration Retry Count") },
+ { "power-cycle-count", _("Power Cycle Count") },
+ { "read-soft-error-rate", _("Soft Read Error Rate") },
+ { "runtime-bad-block-total", _("Runtime Bad Block") },
+ { "end-to-end-error", _("End-to-End error") },
+ { "reported-uncorrect", _("Reported Uncorrectable Errors") },
+ { "command-timeout", _("Command Timeout") },
+ { "high-fly-writes", _("High Fly Writes") },
+ { "airflow-temperature-celsius", _("Airflow Temperature") },
+ { "g-sense-error-rate", _("G-sense Error Rate") },
+ { "power-off-retract-count", _("Power-off Retract Count") },
+ { "load-cycle-count", _("Load Cycle Count") },
+ { "temperature-celsius-2", _("Temperature") },
+ { "hardware-ecc-recovered", _("Hardware ECC Recovered") },
+ { "reallocated-event-count", _("Reallocation Event Count") },
+ { "current-pending-sector", _("Current Pending Sector Count") },
+ { "offline-uncorrectable", _("Uncorrectable Sector Count") },
+ { "udma-crc-error-count", _("UltraDMA CRC Error Count") },
+ { "multi-zone-error-rate", _("Multi-Zone Error Rate") },
+ { "soft-read-error-rate", _("Soft Read Error Rate") },
+ { "run-out-cancel", _("Run Out Cancel") },
+ { "flying-height", _("Flying Height") },
+ { "spin-high-current", _("Spin High Current") },
+ { "spin-buzz", _("Spin Buzz") },
+ { "offline-seek-performance", _("Offline Seek Performance") },
+ { "disk-shift", _("Disk Shift") },
+ { "g-sense-error-rate-2", _("G-Sense Error Rate") },
+ { "loaded-hours", _("Loaded Hours") },
+ { "load-retry-count", _("Load/Unload Retry Count") },
+ { "load-friction", _("Load Friction") },
+ { "load-cycle-count-2", _("Load/Unload Cycle Count") },
+ { "load-in-time", _("Load-in time") },
+ { "torq-amp-count", _("Torque Amplification Count") },
+ { "power-off-retract-count-2", _("Power-Off Retract Count") },
+ { "head-amplitude", _("GMR Head Amplitude") },
+ { "temperature-celsius", _("Temperature") },
+ { "endurance-remaining", _("Endurance Remaining") },
+ { "power-on-seconds-2", _("Power-On Hours") },
+ { "good-block-rate", _("Good Block Rate") },
+ { "head-flying-hours", _("Head Flying Hours") },
+ { "read-error-retry-rate", _("Read Error Retry Rate") },
+ { "total-lbas-written", _("Total LBAs Written") },
+ { "total-lbas-read", _("Total LBAs Read") },
+ { "wear-leveling-count", _("Wear leveling Count") },
+ { "used-reserved-blocks-total", _("Total Used Reserved Block Count") },
+ { "program-fail-count-total", _("Total Program Fail Count") },
+ { "erase-fail-count-total", _("Total Erase Fail Count") },
+ { "available-reserved-space", _("Available Reserved Space") },
+ { "program-fail-count", _("Program Fail Count") },
+ { "erase-fail-count", _("Erase Fail Count") },
+ { "ta-increase-count", _("TA Counter Increased") },
+ { "unused-reserved-blocks", _("Total Unused Reserved Block Count") },
+ { NULL, NULL }
+ };
+
+ moreinfo_del_with_prefix("DEV:UDISKS");
+ udisks2_storage_list = g_strdup(_("\n[UDisks2]\n"));
+
+ drives = get_udisks2_drives_ext();
+ for (node = drives; node != NULL; node = node->next) {
+ ext = (u2driveext *)node->data;
+ disk = ext->d;
+ devid = g_strdup_printf("UDISKS%d", n++);
+
+ icon = NULL;
+
+ media_curr = disk->media;
+ if (disk->media){
+ for (j = 0; media_info[j].media != NULL; j++) {
+ if (g_strcmp0(disk->media, media_info[j].media) == 0) {
+ media_curr = media_info[j].label;
+ break;
+ }
+ }
+ }
+
+ if (disk->media_compatibility){
+ for (i = 0; disk->media_compatibility[i] != NULL; i++){
+ media_label = disk->media_compatibility[i];
+
+ for (j = 0; media_info[j].media != NULL; j++) {
+ if (g_strcmp0(disk->media_compatibility[i], media_info[j].media) == 0) {
+ media_label = media_info[j].label;
+ if (icon == NULL)
+ icon = media_info[j].icon;
+ break;
+ }
+ }
+
+ if (media_comp == NULL){
+ media_comp = g_strdup(media_label);
+ }
+ else{
+ media_comp = h_strdup_cprintf(", %s", media_comp, media_label);
+ }
+ }
+ }
+ if (icon == NULL && disk->ejectable && g_strcmp0(disk->connection_bus, "usb") == 0) {
+ icon = "usbfldisk";
+ }
+ if (icon == NULL){
+ icon = "hdd";
+ }
+
+ size = size_human_readable((gfloat) disk->size);
+ ven_tag = vendor_list_ribbon(ext->vendors, params.fmt_opts);
+
+ udisks2_storage_list = h_strdup_cprintf("$%s$%s=%s|%s %s\n", udisks2_storage_list, devid, disk->block_dev, size, ven_tag ? ven_tag : "", disk->model);
+ storage_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", storage_icons, devid, disk->model, icon);
+ features = h_strdup_cprintf("%s", features, disk->removable ? _("Removable"): _("Fixed"));
+
+ if (disk->ejectable) {
+ features = h_strdup_cprintf(", %s", features, _("Ejectable"));
+ }
+ if (disk->smart_supported) {
+ features = h_strdup_cprintf(", %s", features, _("Self-monitoring (S.M.A.R.T.)"));
+ }
+ if (disk->pm_supported) {
+ features = h_strdup_cprintf(", %s", features, _("Power Management"));
+ }
+ if (disk->apm_supported) {
+ features = h_strdup_cprintf(", %s", features, _("Advanced Power Management"));
+ }
+ if (disk->aam_supported) {
+ features = h_strdup_cprintf(", %s", features, _("Automatic Acoustic Management"));
+ }
+
+ moreinfo = g_strdup_printf(_("[Drive Information]\n"
+ "Model=%s\n"),
+ disk->model);
+
+ if (disk->vendor && *disk->vendor) {
+ moreinfo = h_strdup_cprintf("$^$%s=%s\n",
+ moreinfo,
+ _("Vendor"), disk->vendor);
+ }
+
+ moreinfo = h_strdup_cprintf(_("Revision=%s\n"
+ "Block Device=%s\n"
+ "Serial=%s\n"
+ "Size=%s\n"
+ "Features=%s\n"),
+ moreinfo,
+ disk->revision,
+ disk->block_dev,
+ disk->serial,
+ size,
+ features);
+ g_free(size);
+ g_free(ven_tag);
+
+ if (disk->rotation_rate > 0) {
+ moreinfo = h_strdup_cprintf(_("Rotation Rate=%d RPM\n"), moreinfo, disk->rotation_rate);
+ }
+ if (media_comp || media_curr) {
+ moreinfo = h_strdup_cprintf(_("Media=%s\n"
+ "Media compatibility=%s\n"),
+ moreinfo,
+ media_curr ? media_curr : _("(None)"),
+ media_comp ? media_comp : _("(Unknown)"));
+ }
+ if (disk->connection_bus && strlen(disk->connection_bus) > 0) {
+ moreinfo = h_strdup_cprintf(_("Connection bus=%s\n"), moreinfo, disk->connection_bus);
+ }
+
+ tmp = NULL;
+ if (disk->wwid) {
+ m = strlen(disk->wwid);
+ if (m > 2 && m % 2 == 0){
+ for (j = 4; j < m; j = j + 2) {
+ tmp = h_strdup_cprintf("%s%c%c", tmp, j > 4 ? "-": "", disk->wwid[j], disk->wwid[j+1]);
+ }
+ }
+ moreinfo = h_strdup_cprintf("%s=%s\n", moreinfo,
+ g_str_has_prefix(disk->wwid, "nna.") ? _("WWN"):
+ (g_str_has_prefix(disk->wwid, "eui.") ? _("EUI "): "Unknown ID"),
+ tmp);
+ g_free(tmp);
+ }
+ else{
+ moreinfo = h_strdup_cprintf("%s=%s\n", moreinfo, _("WWN / EUI"), _("(None)"));
+ }
+
+ if (ext->wwid_oui.oui) {
+ moreinfo = h_strdup_cprintf(_("$^$%s=[%s] %s\n"),
+ moreinfo,
+ _("IEEE OUI"), ext->wwid_oui.oui,
+ ext->wwid_oui.vendor ?
+ ext->wwid_oui.vendor : _("(Unknown)"));
+ }
+
+ if (ext->nvme_controller) {
+ gchar *nvme = nvme_pci_sections(ext->nvme_controller);
+ if (nvme)
+ moreinfo = h_strdup_cprintf("%s", moreinfo, nvme);
+ g_free(nvme);
+ }
+ if (disk->smart_enabled) {
+ moreinfo = h_strdup_cprintf(_("[Self-monitoring (S.M.A.R.T.)]\n"
+ "Status=%s\n"
+ "Bad Sectors=%" G_GINT64_FORMAT "\n"
+ "Power on time=%" G_GUINT64_FORMAT " days %" G_GUINT64_FORMAT " hours\n"
+ "Temperature=%d°C\n"),
+ moreinfo,
+ disk->smart_failing ? _("Failing"): _("OK"),
+ disk->smart_bad_sectors,
+ disk->smart_poweron/(60*60*24), (disk->smart_poweron/60/60) % 24,
+ disk->smart_temperature);
+
+ if (disk->smart_attributes != NULL) {
+ moreinfo = h_strdup_cprintf(_("[S.M.A.R.T. Attributes]\n"
+ "Attribute=<tt>Value / Normalized / Worst / Threshold</tt>\n"),
+ moreinfo);
+
+ attrib = disk->smart_attributes;
+
+ while (attrib != NULL){
+ tmp = g_strdup("");
+
+ switch (attrib->interpreted_unit){
+ case UDSK_INTPVAL_SKIP:
+ tmp = h_strdup_cprintf("-", tmp);
+ break;
+ case UDSK_INTPVAL_MILISECONDS:
+ tmp = h_strdup_cprintf("%" G_GINT64_FORMAT " ms", tmp, attrib->interpreted);
+ break;
+ case UDSK_INTPVAL_HOURS:
+ tmp = h_strdup_cprintf("%" G_GINT64_FORMAT " h", tmp, attrib->interpreted);
+ break;
+ case UDSK_INTPVAL_CELSIUS:
+ tmp = h_strdup_cprintf("%" G_GINT64_FORMAT "°C", tmp, attrib->interpreted);
+ break;
+ case UDSK_INTPVAL_SECTORS:
+ tmp = h_strdup_cprintf(ngettext("%" G_GINT64_FORMAT " sector",
+ "%" G_GINT64_FORMAT " sectors", attrib->interpreted),
+ tmp, attrib->interpreted);
+ break;
+ case UDSK_INTPVAL_DIMENSIONLESS:
+ default:
+ tmp = h_strdup_cprintf("%" G_GINT64_FORMAT, tmp, attrib->interpreted);
+ break;
+ }
+
+ // pad spaces to next col
+ j = g_utf8_strlen(tmp, -1);
+ if (j < 13) tmp = h_strdup_cprintf("%*c", tmp, 13 - j, ' ');
+
+ if (attrib->value != -1)
+ tmp = h_strdup_cprintf("%-13d", tmp, attrib->value);
+ else
+ tmp = h_strdup_cprintf("%-13s", tmp, "???");
+
+ if (attrib->worst != -1)
+ tmp = h_strdup_cprintf("%-8d", tmp, attrib->worst);
+ else
+ tmp = h_strdup_cprintf("%-8s", tmp, "???");
+
+ if (attrib->threshold != -1)
+ tmp = h_strdup_cprintf("%d", tmp, attrib->threshold);
+ else
+ tmp = h_strdup_cprintf("???", tmp);
+
+
+ alabel = attrib->identifier;
+ for (i = 0; smart_attrib_info[i].identifier != NULL; i++) {
+ if (g_strcmp0(attrib->identifier, smart_attrib_info[i].identifier) == 0) {
+ alabel = smart_attrib_info[i].label;
+ break;
+ }
+ }
+
+ moreinfo = h_strdup_cprintf(_("(%d) %s=<tt>%s</tt>\n"),
+ moreinfo,
+ attrib->id, alabel, tmp);
+ g_free(tmp);
+ attrib = attrib->next;
+ }
+ }
+ }
+ if (disk->partition_table || disk->partitions) {
+ moreinfo = h_strdup_cprintf(_("[Partition table]\n"
+ "Type=%s\n"),
+ moreinfo,
+ disk->partition_table ? disk->partition_table : _("(Unknown)"));
+
+ if (disk->partitions != NULL) {
+ part = disk->partitions;
+ while (part != NULL){
+
+ tmp = size_human_readable((gfloat) part->size);
+ if (part->label) {
+ tmp = h_strdup_cprintf(" - %s", tmp, part->label);
+ }
+ if (part->type && part->version) {
+ tmp = h_strdup_cprintf(" (%s %s)", tmp, part->type, part->version);
+ }
+ else if (part->type) {
+ tmp = h_strdup_cprintf(" (%s)", tmp, part->type);
+ }
+ moreinfo = h_strdup_cprintf(_("Partition %s=%s\n"),
+ moreinfo,
+ part->block, tmp);
+ g_free(tmp);
+ part = part->next;
+ }
+ }
+ }
+
+ moreinfo_add_with_prefix("DEV", devid, moreinfo);
+ g_free(devid);
+ g_free(features);
+ g_free(media_comp);
+ media_comp = NULL;
+
+ features = NULL;
+ moreinfo = NULL;
+ devid = NULL;
+
+ u2driveext_free(ext);
+ }
+ g_slist_free(drives);
+
+ if (n) {
+ storage_list = h_strconcat(storage_list, udisks2_storage_list, NULL);
+ g_free(udisks2_storage_list);
+ return TRUE;
+ }
+
+ g_free(udisks2_storage_list);
+ return FALSE;
+}
+
/* SCSI support by Pascal F.Martin <pascalmartin@earthlink.net> */
-void
-__scan_scsi_devices(void)
+void __scan_scsi_devices(void)
{
FILE *proc_scsi;
gchar buffer[256], *buf;
@@ -40,12 +493,16 @@ __scan_scsi_devices(void)
/* remove old devices from global device table */
moreinfo_del_with_prefix("DEV:SCSI");
- if (!g_file_test("/proc/scsi/scsi", G_FILE_TEST_EXISTS))
- return;
-
scsi_storage_list = g_strdup(_("\n[SCSI Disks]\n"));
- if ((proc_scsi = fopen("/proc/scsi/scsi", "r"))) {
+ int otype = 0;
+ if (proc_scsi = fopen("/proc/scsi/scsi", "r")) {
+ otype = 1;
+ } else if (proc_scsi = popen("lsscsi -c", "r")) {
+ otype = 2;
+ }
+
+ if (otype) {
while (fgets(buffer, 256, proc_scsi)) {
buf = g_strstrip(buffer);
if (!strncmp(buf, "Host: scsi", 10)) {
@@ -104,23 +561,15 @@ __scan_scsi_devices(void)
}
gchar *devid = g_strdup_printf("SCSI%d", n);
- scsi_storage_list = h_strdup_cprintf("$%s$%s=\n", scsi_storage_list, devid, model);
+ scsi_storage_list = h_strdup_cprintf("$%s$scsi%d=|%s\n", scsi_storage_list, devid, scsi_controller, model);
storage_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", storage_icons, devid, model, icon);
gchar *strhash = g_strdup_printf(_("[Device Information]\n"
"Model=%s\n"), model);
- const gchar *url = vendor_get_url(model);
- if (url) {
- strhash = h_strdup_cprintf(_("Vendor=%s (%s)\n"),
- strhash,
- vendor_get_name(model),
- url);
- } else {
- strhash = h_strdup_cprintf(_("Vendor=%s\n"),
- strhash,
- vendor_get_name(model));
- }
+ strhash = h_strdup_cprintf("$^$%s=%s\n",
+ strhash,
+ _("Vendor"), model);
strhash = h_strdup_cprintf(_("Type=%s\n"
"Revision=%s\n"
@@ -135,6 +584,7 @@ __scan_scsi_devices(void)
scsi_channel,
scsi_id,
scsi_lun);
+
moreinfo_add_with_prefix("DEV", devid, strhash);
g_free(devid);
@@ -145,7 +595,10 @@ __scan_scsi_devices(void)
scsi_controller = scsi_channel = scsi_id = scsi_lun = 0;
}
}
- fclose(proc_scsi);
+ if (otype == 1)
+ fclose(proc_scsi);
+ else if (otype == 2)
+ pclose(proc_scsi);
}
if (n) {
@@ -157,7 +610,8 @@ __scan_scsi_devices(void)
void __scan_ide_devices(void)
{
FILE *proc_ide;
- gchar *device, iface, *model, *media, *pgeometry = NULL, *lgeometry = NULL;
+ gchar *device, *model, *media, *pgeometry = NULL, *lgeometry = NULL;
+ gchar iface;
gint n = 0, i = 0, cache, nn = 0;
gchar *capab = NULL, *speed = NULL, *driver = NULL, *ide_storage_list;
@@ -305,7 +759,7 @@ void __scan_ide_devices(void)
gchar *devid = g_strdup_printf("IDE%d", n);
- ide_storage_list = h_strdup_cprintf("$%s$%s=\n", ide_storage_list, devid, model);
+ ide_storage_list = h_strdup_cprintf("$%s$hd%c=|%s\n", ide_storage_list, devid, iface, model);
storage_icons =
h_strdup_cprintf("Icon$%s$%s=%s.png\n", storage_icons,
devid, model, g_str_equal(media, "cdrom") ? "cdrom" : "hdd");
@@ -313,13 +767,8 @@ void __scan_ide_devices(void)
gchar *strhash = g_strdup_printf(_("[Device Information]\n" "Model=%s\n"),
model);
- const gchar *url = vendor_get_url(model);
-
- if (url) {
- strhash = h_strdup_cprintf(_("Vendor=%s (%s)\n"), strhash, vendor_get_name(model), url);
- } else {
- strhash = h_strdup_cprintf(_("Vendor=%s\n"), strhash, vendor_get_name(model));
- }
+ strhash = h_strdup_cprintf("$^$%s=%s\n",
+ strhash, _("Vendor"), model);
strhash = h_strdup_cprintf(_("Device Name=hd%c\n"
"Media=%s\n" "Cache=%dkb\n"), strhash, iface, media, cache);
diff --git a/modules/devices/usb.c b/modules/devices/usb.c
index 9366c7ce..c6a5ab39 100644
--- a/modules/devices/usb.c
+++ b/modules/devices/usb.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2008 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2008 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,422 +15,210 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/*
- * FIXME:
- * - listing with sysfs does not generate device hierarchy
- */
#include <string.h>
+#include "cpu_util.h"
#include "hardinfo.h"
#include "devices.h"
+#include "usb_util.h"
gchar *usb_list = NULL;
-
-void __scan_usb_sysfs_add_device(gchar * endpoint, int n)
-{
- gchar *manufacturer, *product, *mxpwr, *tmp, *strhash;
- gint bus, classid, vendor, prodid;
- gfloat version, speed;
-
- classid = h_sysfs_read_int(endpoint, "bDeviceClass");
- vendor = h_sysfs_read_int(endpoint, "idVendor");
- prodid = h_sysfs_read_int(endpoint, "idProduct");
- bus = h_sysfs_read_int(endpoint, "busnum");
- speed = h_sysfs_read_float(endpoint, "speed");
- version = h_sysfs_read_float(endpoint, "version");
-
- if (!(mxpwr = h_sysfs_read_string(endpoint, "bMaxPower"))) {
- mxpwr = g_strdup_printf("%d %s", 0 , _("mA") );
- }
-
- if (!(manufacturer = h_sysfs_read_string(endpoint, "manufacturer"))) {
- manufacturer = g_strdup(_("(Unknown)"));
- }
-
- if (!(product = h_sysfs_read_string(endpoint, "product"))) {
- if (classid == 9) {
- product = g_strdup_printf(_(/*/%.2f is version*/ "USB %.2f Hub"), version);
- } else {
- product = g_strdup_printf(_("Unknown USB %.2f Device (class %d)"), version, classid);
+gchar *usb_icons = NULL;
+
+#define UNKIFNULL_AC(f) (f != NULL) ? f : _("(Unknown)")
+#define IARR_END -2
+#define IARR_ANY -1
+
+static struct {
+ int class;
+ char *icon;
+} usb_class_icons[] = {
+ { 0x1, "audio"}, /* Audio */
+ { 0x2, "modem"}, /* Communications and CDC Control */
+ { 0x3, "inputdevices"}, /* HID (Human Interface Device) */
+ { 0x6, "camera-photo"}, /* Still Imaging */
+ { 0x7, "printer"}, /* Printer */
+ { 0x8, "media-removable"}, /* Mass storage */
+ { 0x9, "usb"}, /* Hub */
+ { 0xe, "camera-web"}, /* Video */
+ {IARR_END, NULL}
+};
+
+static struct {
+ int class, subclass, protocol;
+ char *icon;
+} usb_type_icons[] = {
+ { 0x2, 0x6, IARR_ANY, "network-interface"}, /* Ethernet Networking Control Model */
+ { 0x3, 0x1, 0x1, "keyboard"}, /* Keyboard */
+ { 0x3, 0x1, 0x2, "mouse"}, /* Mouse */
+ {0xe0, 0x1, 0x1, "bluetooth"}, /* Bluetooth Programming Interface */
+ {IARR_END, IARR_END, IARR_END, NULL},
+};
+
+static const char* get_class_icon(int class){
+ int i = 0;
+ while (usb_class_icons[i].class != IARR_END) {
+ if (usb_class_icons[i].class == class) {
+ return usb_class_icons[i].icon;
}
+ i++;
}
-
- const gchar *v_url = vendor_get_url(manufacturer);
- const gchar *v_name = vendor_get_name(manufacturer);
- gchar *v_str;
- if (v_url != NULL) {
- v_str = g_strdup_printf("%s (%s)", v_name, v_url);
- } else {
- v_str = g_strdup_printf("%s", manufacturer);
- }
-
- tmp = g_strdup_printf("USB%d", n);
- usb_list = h_strdup_cprintf("$%s$%s=\n", usb_list, tmp, product);
-
- strhash = g_strdup_printf("[%s]\n"
- /* Product */ "%s=%s\n"
- /* Manufacturer */ "%s=%s\n"
- /* Speed */ "%s=%.2f %s\n"
- /* Max Current */ "%s=%s\n"
- "[%s]\n"
- /* USB Version */ "%s=%.2f\n"
- /* Class */ "%s=0x%x\n"
- /* Vendor */ "%s=0x%x\n"
- /* Product ID */ "%s=0x%x\n"
- /* Bus */ "%s=%d\n",
- _("Device Information"),
- _("Product"), product,
- _("Manufacturer"), v_str,
- _("Speed"), speed, _("Mbit/s"),
- _("Max Current"), mxpwr,
- _("Misc"),
- _("USB Version"), version,
- _("Class"), classid,
- _("Vendor ID"), vendor,
- _("Product ID"), prodid,
- _("Bus"), bus);
-
- moreinfo_add_with_prefix("DEV", tmp, strhash);
- g_free(tmp);
- g_free(v_str);
- g_free(manufacturer);
- g_free(product);
- g_free(mxpwr);
+ return NULL;
}
-gboolean __scan_usb_sysfs(void)
-{
- GDir *sysfs;
- gchar *filename;
- const gchar *sysfs_path = "/sys/class/usb_endpoint";
- gint usb_device_number = 0;
-
- if (!(sysfs = g_dir_open(sysfs_path, 0, NULL))) {
- return FALSE;
- }
-
- if (usb_list) {
- moreinfo_del_with_prefix("DEV:USB");
- g_free(usb_list);
- }
- usb_list = g_strdup_printf("[%s]\n", _("USB Devices"));
-
- while ((filename = (gchar *) g_dir_read_name(sysfs))) {
- gchar *endpoint =
- g_build_filename(sysfs_path, filename, "device", NULL);
- gchar *temp;
+static const char* get_usbif_icon(const usbi *usbif) {
+ int i = 0;
+ while (usb_type_icons[i].class != IARR_END) {
+ if (usb_type_icons[i].class == usbif->if_class && usb_type_icons[i].subclass == usbif->if_subclass &&
+ (usb_type_icons[i].protocol == IARR_ANY || usb_type_icons[i].protocol == usbif->if_protocol)) {
- temp = g_build_filename(endpoint, "idVendor", NULL);
- if (g_file_test(temp, G_FILE_TEST_EXISTS)) {
- __scan_usb_sysfs_add_device(endpoint, ++usb_device_number);
- }
-
- g_free(temp);
- g_free(endpoint);
+ return usb_type_icons[i].icon;
+ }
+ i++;
}
- g_dir_close(sysfs);
-
- return usb_device_number > 0;
+ return get_class_icon(usbif->if_class);
}
-gboolean __scan_usb_procfs(void)
-{
- FILE *dev;
- gchar buffer[128];
- gchar *tmp, *manuf = NULL, *product = NULL, *mxpwr = NULL;
- gint bus = 0, level = 0, port = 0, classid = 0, trash;
- gint vendor = 0, prodid = 0;
- gfloat ver = 0.0f, rev = 0.0f, speed = 0.0f;
- int n = 0;
-
- dev = fopen("/proc/bus/usb/devices", "r");
- if (!dev)
- return 0;
+static const char* get_usbdev_icon(const usbd *u) {
+ const char * icon = NULL;
+ usbi *curr_if;
- if (usb_list) {
- moreinfo_del_with_prefix("DEV:USB");
- g_free(usb_list);
+ curr_if = u->if_list;
+ while (icon == NULL && curr_if != NULL){
+ icon = get_usbif_icon(curr_if);
+ curr_if = curr_if->next;
}
- usb_list = g_strdup_printf("[%s]\n", _("USB Devices"));
-
- while (fgets(buffer, 128, dev)) {
- tmp = buffer;
- switch (*tmp) {
- case 'T':
- sscanf(tmp,
- "T: Bus=%d Lev=%d Prnt=%d Port=%d Cnt=%d Dev#=%d Spd=%f",
- &bus, &level, &trash, &port, &trash, &trash, &speed);
- break;
- case 'D':
- sscanf(tmp, "D: Ver=%f Cls=%x", &ver, &classid);
- break;
- case 'P':
- sscanf(tmp, "P: Vendor=%x ProdID=%x Rev=%f", &vendor, &prodid, &rev);
- break;
- case 'S':
- if (strstr(tmp, "Manufacturer=")) {
- manuf = g_strdup(strchr(tmp, '=') + 1);
- remove_linefeed(manuf);
- } else if (strstr(tmp, "Product=")) {
- product = g_strdup(strchr(tmp, '=') + 1);
- remove_linefeed(product);
- }
- break;
- case 'C':
- mxpwr = strstr(buffer, "MxPwr=") + 6;
-
- tmp = g_strdup_printf("USB%d", ++n);
-
- if (product && *product == '\0') {
- g_free(product);
- if (classid == 9) {
- product = g_strdup_printf(_("USB %.2f Hub"), ver);
- } else {
- product = g_strdup_printf(_("Unknown USB %.2f Device (class %d)"), ver, classid);
- }
- }
-
- if (classid == 9) { /* hub */
- usb_list = h_strdup_cprintf("[%s#%d]\n", usb_list, product, n);
- } else { /* everything else */
- usb_list = h_strdup_cprintf("$%s$%s=\n", usb_list, tmp, product);
-
- EMPIFNULL(manuf);
- const gchar *v_url = vendor_get_url(manuf);
- const gchar *v_name = vendor_get_name(manuf);
- gchar *v_str = NULL;
- if (strlen(manuf)) {
- if (v_url != NULL)
- v_str = g_strdup_printf("%s (%s)", v_name, v_url);
- else
- v_str = g_strdup_printf("%s", manuf);
- }
- UNKIFNULL(v_str);
- UNKIFNULL(product);
-
- gchar *strhash = g_strdup_printf("[%s]\n" "%s=%s\n" "%s=%s\n",
- _("Device Information"),
- _("Product"), product,
- _("Manufacturer"), v_str);
-
- strhash = h_strdup_cprintf("[%s #%d]\n"
- /* Speed */ "%s=%.2f %s\n"
- /* Max Current */ "%s=%s\n"
- "[%s]\n"
- /* USB Version */ "%s=%.2f\n"
- /* Revision */ "%s=%.2f\n"
- /* Class */ "%s=0x%x\n"
- /* Vendor */ "%s=0x%x\n"
- /* Product ID */ "%s=0x%x\n"
- /* Bus */ "%s=%d\n"
- /* Level */ "%s=%d\n",
- strhash,
- _("Port"), port,
- _("Speed"), speed, _("Mbit/s"),
- _("Max Current"), mxpwr,
- _("Misc"),
- _("USB Version"), ver,
- _("Revision"), rev,
- _("Class"), classid,
- _("Vendor ID"), vendor,
- _("Product ID"), prodid,
- _("Bus"), bus,
- _("Level"), level);
-
- moreinfo_add_with_prefix("DEV", tmp, strhash);
- g_free(v_str);
- g_free(tmp);
- }
-
- g_free(manuf);
- g_free(product);
- manuf = NULL;
- product = NULL;
- port = classid = 0;
- }
+ if (icon == NULL){
+ icon = get_class_icon(u->dev_class);
}
- fclose(dev);
-
- return n > 0;
+ return icon;
}
-
-void __scan_usb_lsusb_add_device(char *buffer, int bufsize, FILE * lsusb, int usb_device_number)
-{
- gint bus, device, vendor_id, product_id;
- gchar *version = NULL, *product = NULL, *vendor = NULL, *dev_class = NULL, *int_class = NULL;
- gchar *max_power = NULL, *name = NULL;
- gchar *tmp, *strhash;
- long position = 0;
-
- g_strstrip(buffer);
- sscanf(buffer, "Bus %d Device %d: ID %x:%x", &bus, &device, &vendor_id, &product_id);
- name = g_strdup(buffer + 33);
-
- for (fgets(buffer, bufsize, lsusb); position >= 0 && fgets(buffer, bufsize, lsusb); position = ftell(lsusb)) {
- g_strstrip(buffer);
-
- if (g_str_has_prefix(buffer, "idVendor")) {
- g_free(vendor);
- vendor = g_strdup(buffer + 26);
- } else if (g_str_has_prefix(buffer, "idProduct")) {
- g_free(product);
- product = g_strdup(buffer + 26);
- } else if (g_str_has_prefix(buffer, "MaxPower")) {
- g_free(max_power);
- max_power = g_strdup(buffer + 9);
- } else if (g_str_has_prefix(buffer, "bcdUSB")) {
- g_free(version);
- version = g_strdup(buffer + 7);
- } else if (g_str_has_prefix(buffer, "bDeviceClass")) {
- g_free(dev_class);
- dev_class = g_strdup(buffer + 14);
- } else if (g_str_has_prefix(buffer, "bInterfaceClass")) {
- g_free(int_class);
- int_class = g_strdup(buffer + 16);
- } else if (g_str_has_prefix(buffer, "Bus ")) {
- /* device separator */
- fseek(lsusb, position, SEEK_SET);
- break;
- }
- }
-
- if (dev_class && strstr(dev_class, "0 (Defined at Interface level)")) {
- g_free(dev_class);
- if (int_class) {
- dev_class = int_class;
- } else {
- dev_class = g_strdup(_("(Unknown)"));
- }
- } else
- dev_class = g_strdup(_("(Unknown)"));
-
- tmp = g_strdup_printf("USB%d", usb_device_number);
- usb_list = h_strdup_cprintf("$%s$%s=\n", usb_list, tmp, name);
-
- const gchar *v_url = vendor_get_url(vendor);
- const gchar *v_name = vendor_get_name(vendor);
- gchar *v_str;
- if (v_url != NULL) {
- v_str = g_strdup_printf("%s (%s)", v_name, v_url);
+static void _usb_dev(const usbd *u) {
+ gchar *name, *key, *label, *str, *speed;
+ gchar *product, *vendor, *manufacturer, *device; /* don't free */
+ gchar *interfaces = strdup("");
+ usbi *i;
+ const char* icon;
+
+ vendor = UNKIFNULL_AC(u->vendor);
+ product = UNKIFNULL_AC(u->product);
+ manufacturer = UNKIFNULL_AC(u->manufacturer);
+ device = UNKIFNULL_AC(u->device);
+
+ if (u->vendors) {
+ gchar *ribbon = vendor_list_ribbon(u->vendors, params.fmt_opts);
+ name = g_strdup_printf("%s %s", ribbon, u->product? product: device);
} else {
- v_str = g_strdup_printf("%s", g_strstrip(vendor) );
+ name = g_strdup_printf("%s %s", u->vendor? vendor: manufacturer, u->product? product: device);
+ }
+ key = g_strdup_printf("USB%03d:%03d:%03d", u->bus, u->dev, 0);
+ label = g_strdup_printf("%03d:%03d", u->bus, u->dev);
+ icon = get_usbdev_icon(u);
+
+ usb_list = h_strdup_cprintf("$%s$%s=%s\n", usb_list, key, label, name);
+ usb_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", usb_icons, key, label, icon ? icon: "usb");
+
+ if (u->if_list != NULL) {
+ i = u->if_list;
+ while (i != NULL){
+ interfaces = h_strdup_cprintf("[%s %d %s]\n"
+ /* Class */ "%s=[%d] %s\n"
+ /* Sub-class */ "%s=[%d] %s\n"
+ /* Protocol */ "%s=[%d] %s\n"
+ /* Driver */ "%s=%s\n",
+ interfaces,
+ _("Interface"), i->if_number, i->if_label? i->if_label: "",
+ _("Class"), i->if_class, UNKIFNULL_AC(i->if_class_str),
+ _("Sub-class"), i->if_subclass, UNKIFNULL_AC(i->if_subclass_str),
+ _("Protocol"), i->if_protocol, UNKIFNULL_AC(i->if_protocol_str),
+ _("Driver"), UNKIFNULL_AC(i->driver)
+ );
+ i = i->next;
+ }
}
- if (max_power != NULL) {
- int mA = atoi(g_strstrip(max_power));
- gchar *trent_steel = g_strdup_printf("%d %s", mA, _("mA"));
- g_free(max_power);
- max_power = trent_steel;
+ if (u->speed_mbs > 0){
+ speed = g_strdup_printf("%d %s", u->speed_mbs, _("Mb/s"));
+ }
+ else{
+ speed = g_strdup(_("Unknown"));
}
- UNKIFNULL(product);
- UNKIFNULL(v_str);
- UNKIFNULL(max_power);
- UNKIFNULL(version);
- UNKIFNULL(dev_class);
-
- strhash = g_strdup_printf("[%s]\n"
- /* Product */ "%s=%s\n"
- /* Manufacturer */ "%s=%s\n"
- /* Max Current */ "%s=%s\n"
- "[%s]\n"
+ str = g_strdup_printf("[%s]\n"
+ /* Product */ "%s=[0x%04x] %s\n"
+ /* Vendor */ "$^$%s=[0x%04x] %s\n"
+ /* Device */ "%s=%s\n"
+ /* Manufacturer */ "$^$%s=%s\n"
+ /* Max Current */ "%s=%d %s\n"
/* USB Version */ "%s=%s\n"
- /* Class */ "%s=%s\n"
- /* Vendor ID */ "%s=0x%x\n"
- /* Product ID */ "%s=0x%x\n"
- /* Bus */ "%s=%d\n",
+ /* Speed */ "%s=%s\n"
+ /* Class */ "%s=[%d] %s\n"
+ /* Sub-class */ "%s=[%d] %s\n"
+ /* Protocol */ "%s=[%d] %s\n"
+ /* Dev Version */ "%s=%s\n"
+ /* Serial */ "%s=%s\n"
+ "[%s]\n"
+ /* Bus */ "%s=%03d\n"
+ /* Device */ "%s=%03d\n"
+ /* Interfaces */ "%s",
_("Device Information"),
- _("Product"), g_strstrip(product),
- _("Vendor"), v_str,
- _("Max Current"), g_strstrip(max_power),
- _("Misc"),
- _("USB Version"), g_strstrip(version),
- _("Class"), g_strstrip(dev_class),
- _("Vendor ID"), vendor_id,
- _("Product ID"), product_id,
- _("Bus"), bus);
-
- moreinfo_add_with_prefix("DEV", tmp, strhash);
- g_free(v_str);
- g_free(vendor);
- g_free(product);
- g_free(max_power);
- g_free(dev_class);
- g_free(version);
- g_free(tmp);
+ _("Product"), u->product_id, product,
+ _("Vendor"), u->vendor_id, vendor,
+ _("Device"), device,
+ _("Manufacturer"), manufacturer,
+ _("Max Current"), u->max_curr_ma, _("mA"),
+ _("USB Version"), u->usb_version,
+ _("Speed"), speed,
+ _("Class"), u->dev_class, UNKIFNULL_AC(u->dev_class_str),
+ _("Sub-class"), u->dev_subclass, UNKIFNULL_AC(u->dev_subclass_str),
+ _("Protocol"), u->dev_protocol, UNKIFNULL_AC(u->dev_protocol_str),
+ _("Device Version"), UNKIFNULL_AC(u->device_version),
+ _("Serial Number"), UNKIFNULL_AC(u->serial),
+ _("Connection"),
+ _("Bus"), u->bus,
+ _("Device"), u->dev,
+ interfaces
+ );
+
+ moreinfo_add_with_prefix("DEV", key, str); /* str now owned by morinfo */
+
+ g_free(speed);
g_free(name);
+ g_free(key);
+ g_free(label);
+ g_free(interfaces);
}
-gboolean __scan_usb_lsusb(void)
-{
- static gchar *lsusb_path = NULL;
- int usb_device_number = 0;
- FILE *lsusb;
- FILE *temp_lsusb;
- char buffer[512], *temp;
+void __scan_usb(void) {
+ usbd *list = usb_get_device_list();
+ usbd *curr = list;
- if (!lsusb_path) {
- if (!(lsusb_path = find_program("lsusb"))) {
- DEBUG("lsusb not found");
-
- return FALSE;
- }
- }
-
- temp = g_strdup_printf("%s -v | tr '[]' '()'", lsusb_path);
- if (!(lsusb = popen(temp, "r"))) {
- DEBUG("cannot run %s", lsusb_path);
-
- g_free(temp);
- return FALSE;
- }
-
- temp_lsusb = tmpfile();
- if (!temp_lsusb) {
- DEBUG("cannot create temporary file for lsusb");
- pclose(lsusb);
- g_free(temp);
- return FALSE;
- }
-
- while (fgets(buffer, sizeof(buffer), lsusb)) {
- fputs(buffer, temp_lsusb);
- }
-
- pclose(lsusb);
-
- // rewind file so we can read from it
- fseek(temp_lsusb, 0, SEEK_SET);
-
- g_free(temp);
+ int c = usbd_list_count(list);
if (usb_list) {
- moreinfo_del_with_prefix("DEV:USB");
+ moreinfo_del_with_prefix("DEV:USB");
g_free(usb_list);
}
+ if (usb_icons){
+ g_free(usb_icons);
+ usb_icons = NULL;
+ }
usb_list = g_strdup_printf("[%s]\n", _("USB Devices"));
- while (fgets(buffer, sizeof(buffer), temp_lsusb)) {
- if (g_str_has_prefix(buffer, "Bus ")) {
- __scan_usb_lsusb_add_device(buffer, sizeof(buffer), temp_lsusb, ++usb_device_number);
+ if (c > 0) {
+ while(curr) {
+ _usb_dev(curr);
+ curr=curr->next;
}
- }
-
- fclose(temp_lsusb);
- return usb_device_number > 0;
-}
-
-void __scan_usb(void)
-{
- if (!__scan_usb_procfs()) {
- if (!__scan_usb_sysfs()) {
- __scan_usb_lsusb();
- }
+ usbd_list_free(list);
+ } else {
+ /* No USB? */
+ usb_list = g_strconcat(usb_list, _("No USB devices found."), "=\n", NULL);
}
}
diff --git a/modules/devices/x86/processor.c b/modules/devices/x86/processor.c
index f1c2b6e9..4141f051 100644
--- a/modules/devices/x86/processor.c
+++ b/modules/devices/x86/processor.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2006 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,7 +19,7 @@
#include "hardinfo.h"
#include "devices.h"
#include "cpu_util.h"
-
+#include "nice_name.h"
#include "x86_data.h"
#include "x86_data.c"
@@ -275,7 +275,7 @@ gchar *clocks_summary(GSList * processors)
/* create list of all clock references */
for (l = processors; l; l = l->next) {
p = (Processor*)l->data;
- if (p->cpufreq) {
+ if (p->cpufreq && p->cpufreq->cpukhz_max > 0) {
all_clocks = g_slist_prepend(all_clocks, p->cpufreq);
}
}
@@ -448,14 +448,15 @@ gchar *caches_summary(GSList * processors)
return ret;
}
-#define PROC_SCAN_READ_BUFFER_SIZE 896
+#define PROC_SCAN_READ_BUFFER_SIZE 1024
GSList *processor_scan(void)
{
GSList *procs = NULL, *l = NULL;
Processor *processor = NULL;
FILE *cpuinfo;
- gchar buffer[PROC_SCAN_READ_BUFFER_SIZE];
+ gchar *buffer;
+ buffer = g_malloc(PROC_SCAN_READ_BUFFER_SIZE);
cpuinfo = fopen(PROC_CPUINFO, "r");
if (!cpuinfo)
return NULL;
@@ -513,6 +514,7 @@ GSList *processor_scan(void)
}
fclose(cpuinfo);
+ g_free(buffer);
/* finish last */
if (processor)
@@ -567,6 +569,8 @@ GSList *processor_scan(void)
if (processor->cpufreq->cpukhz_max)
processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000;
+
+ nice_name_x86_cpuid_model_string(processor->model_name);
}
return procs;
@@ -584,7 +588,7 @@ gchar *processor_get_capabilities_from_flags(gchar *strflags, gchar *lookup_pref
old = flags;
while (flags[j]) {
- if ( sscanf(flags[j], "[%d]", &i) ) {
+ if ( sscanf(flags[j], "[%d]", &i)==1 ) {
/* Some flags are indexes, like [13], and that looks like
* a new section to hardinfo shell */
tmp = h_strdup_cprintf("(%s%d)=\n", tmp,
@@ -624,7 +628,7 @@ gchar *processor_get_detailed_info(Processor * processor)
ret = g_strdup_printf("[%s]\n"
"%s=%s\n"
"%s=%d, %d, %d (%s)\n" /* family, model, stepping (decoded name) */
- "%s=%s\n" /* vendor */
+ "$^$%s=%s\n" /* vendor */
"%s=%s\n" /* microcode */
"[%s]\n" /* configuration */
"%s=%d %s\n" /* cache size (from cpuinfo) */
@@ -648,7 +652,7 @@ gchar *processor_get_detailed_info(Processor * processor)
processor->model,
processor->stepping,
processor->strmodel,
- _("Vendor"), vendor_get_name(processor->vendor_id),
+ _("Vendor"), processor->vendor_id,
_("Microcode Version"), processor->microcode,
_("Configuration"),
_("Cache Size"), processor->cache_size, _("kb"),
@@ -678,12 +682,62 @@ gchar *processor_describe(GSList * processors) {
return processor_describe_default(processors);
}
+gchar *dmi_socket_info() {
+ gchar *ret;
+ dmi_type dt = 4;
+ guint i;
+ dmi_handle_list *hl = dmidecode_handles(&dt);
+
+ if (!hl) {
+ ret = g_strdup_printf("[%s]\n%s=%s\n",
+ _("Socket Information"), _("Result"),
+ (getuid() == 0)
+ ? _("(Not available)")
+ : _("(Not available; Perhaps try running HardInfo as root.)") );
+ } else {
+ ret = g_strdup("");
+ for(i = 0; i < hl->count; i++) {
+ dmi_handle h = hl->handles[i];
+ gchar *upgrade = dmidecode_match("Upgrade", &dt, &h);
+ gchar *socket = dmidecode_match("Socket Designation", &dt, &h);
+ gchar *bus_clock_str = dmidecode_match("External Clock", &dt, &h);
+ gchar *voltage_str = dmidecode_match("Voltage", &dt, &h);
+ gchar *max_speed_str = dmidecode_match("Max Speed", &dt, &h);
+
+ ret = h_strdup_cprintf("[%s (%d) %s]\n"
+ "%s=0x%x\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n"
+ "%s=%s\n",
+ ret,
+ _("CPU Socket"), i, socket,
+ _("DMI Handle"), h,
+ _("Type"), upgrade,
+ _("Voltage"), voltage_str,
+ _("External Clock"), bus_clock_str,
+ _("Max Frequency"), max_speed_str
+ );
+ g_free(upgrade);
+ g_free(socket);
+ g_free(bus_clock_str);
+ g_free(voltage_str);
+ g_free(max_speed_str);
+ }
+
+ dmi_handle_list_free(hl);
+ }
+
+ return ret;
+}
+
gchar *processor_meta(GSList * processors) {
gchar *meta_cpu_name = processor_name(processors);
gchar *meta_cpu_desc = processor_describe(processors);
gchar *meta_freq_desc = processor_frequency_desc(processors);
gchar *meta_clocks = clocks_summary(processors);
gchar *meta_caches = caches_summary(processors);
+ gchar *meta_dmi = dmi_socket_info();
gchar *ret = NULL;
UNKIFNULL(meta_cpu_desc);
ret = g_strdup_printf("[%s]\n"
@@ -691,13 +745,15 @@ gchar *processor_meta(GSList * processors) {
"%s=%s\n"
"%s=%s\n"
"%s"
+ "%s"
"%s",
_("Package Information"),
_("Name"), meta_cpu_name,
_("Topology"), meta_cpu_desc,
_("Logical CPU Config"), meta_freq_desc,
meta_clocks,
- meta_caches);
+ meta_caches,
+ meta_dmi);
g_free(meta_cpu_desc);
g_free(meta_freq_desc);
g_free(meta_clocks);
@@ -711,8 +767,9 @@ gchar *processor_get_info(GSList * processors)
gchar *ret, *tmp, *hashkey;
gchar *meta; /* becomes owned by more_info? no need to free? */
GSList *l;
+ gchar *icons=g_strdup("");
- tmp = g_strdup_printf("$CPU_META$%s=\n", _("Package Information") );
+ tmp = g_strdup_printf("$!CPU_META$%s=|Summary\n", "all");
meta = processor_meta(processors);
moreinfo_add_with_prefix("DEV", "CPU_META", meta);
@@ -720,27 +777,46 @@ gchar *processor_get_info(GSList * processors)
for (l = processors; l; l = l->next) {
processor = (Processor *) l->data;
- tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s|%d:%d|%d\n",
+ gchar *model_name = g_strdup(processor->model_name);
+ const Vendor *v = vendor_match(processor->vendor_id, NULL);
+ if (v)
+ tag_vendor(&model_name, 0, v->name_short ? v->name_short : v->name, v->ansi_color, params.fmt_opts);
+
+ // bp: not convinced it looks good, but here's how it would be done...
+ //icons = h_strdup_cprintf("Icon$CPU%d$cpu%d=processor.png\n", icons, processor->id, processor->id);
+
+ tmp = g_strdup_printf("%s$CPU%d$cpu%d=%.2f %s|%s|%d:%d\n",
tmp, processor->id,
- processor->model_name,
+ processor->id,
processor->cpu_mhz, _("MHz"),
+ model_name,
processor->cputopo->socket_id,
- processor->cputopo->core_id,
- processor->cputopo->id );
+ processor->cputopo->core_id);
hashkey = g_strdup_printf("CPU%d", processor->id);
moreinfo_add_with_prefix("DEV", hashkey,
processor_get_detailed_info(processor));
g_free(hashkey);
+ g_free(model_name);
}
ret = g_strdup_printf("[$ShellParam$]\n"
"ViewType=1\n"
+ "ColumnTitle$TextValue=%s\n"
+ "ColumnTitle$Value=%s\n"
"ColumnTitle$Extra1=%s\n"
"ColumnTitle$Extra2=%s\n"
+ "ShowColumnHeaders=true\n"
+ "%s"
"[Processors]\n"
- "%s", _("Socket:Core"), _("Thread" /*TODO: +s*/), tmp);
+ "%s", _("Device"), _("Frequency"), _("Model"), _("Socket:Core"), icons, tmp);
g_free(tmp);
+ g_free(icons);
+
+ // now here's something fun...
+ struct Info *i = info_unflatten(ret);
+ g_free(ret);
+ ret = info_flatten(i);
return ret;
}
diff --git a/modules/devices/x86/x86_data.c b/modules/devices/x86/x86_data.c
index c052f4e1..f56e8668 100644
--- a/modules/devices/x86/x86_data.c
+++ b/modules/devices/x86/x86_data.c
@@ -18,6 +18,7 @@
*
*/
+#include <json-glib/json-glib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -35,9 +36,13 @@
* https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/arch/x86/include/asm/cpufeatures.h?id=refs/tags/v4.9
* hardinfo: modules/devices/x86/processor.c
*/
-static struct {
- char *name, *meaning;
-} tab_flag_meaning[] = {
+
+struct flag_to_meaning {
+ char *name;
+ char *meaning;
+};
+
+static const struct flag_to_meaning builtin_tab_flag_meaning[] = {
/* Intel-defined CPU features, CPUID level 0x00000001 (edx)
* See also Wikipedia and table 2-27 in Intel Advanced Vector Extensions Programming Reference */
{ "fpu", NC_("x86-flag", /*/flag:fpu*/ "Onboard FPU (floating point support)") },
@@ -282,6 +287,8 @@ static struct {
{ "bug:cpu_meltdown", NC_("x86-flag", /*/bug:cpu_insecure & bug:cpu_meltdown*/ "CPU is affected by meltdown attack and needs kernel page table isolation") },
{ "bug:spectre_v1", NC_("x86-flag", /*/bug:spectre_v1*/ "CPU is affected by Spectre variant 1 attack with conditional branches") },
{ "bug:spectre_v2", NC_("x86-flag", /*/bug:spectre_v2*/ "CPU is affected by Spectre variant 2 attack with indirect branches") },
+ { "bug:spec_store_bypass", NC_("x86-flag", /*/bug:spec_store_bypass*/ "CPU is affected by speculative store bypass attack") },
+ { "bug:l1tf", NC_("x86-flag", /*/bug:l1tf*/ "CPU is affected by L1 Terminal Fault") },
/* power management
* ... from arch/x86/kernel/cpu/powerflags.h */
{ "pm:ts", NC_("x86-flag", /*/flag:pm:ts*/ "temperature sensor") },
@@ -299,32 +306,77 @@ static struct {
{ NULL, NULL},
};
+static struct flag_to_meaning *tab_flag_meaning;
+
static char all_flags[4096] = "";
-#define APPEND_FLAG(f) strcat(all_flags, f); strcat(all_flags, " ");
-const char *x86_flag_list() {
- int i = 0, built = 0;
- built = strlen(all_flags);
- if (!built) {
- while(tab_flag_meaning[i].name != NULL) {
- APPEND_FLAG(tab_flag_meaning[i].name);
- i++;
- }
- }
- return all_flags;
+static void build_meaning_table_iter(JsonObject *object,
+ const gchar *member_name,
+ JsonNode *member_node,
+ gpointer user_data)
+{
+ int *i = user_data;
+
+ tab_flag_meaning[*i] = (struct flag_to_meaning) {
+ .name = g_strdup(member_name),
+ .meaning = g_strdup(json_node_get_string(member_node)),
+ };
+
+ (*i)++;
}
-const char *x86_flag_meaning(const char *flag) {
+void cpuflags_x86_init(void)
+{
+ gchar *flag_json = g_build_filename(g_get_user_config_dir(), "hardinfo2",
+ "cpuflags.json", NULL);
+ gboolean use_builtin_table = TRUE;
+
+ if (!g_file_test(flag_json, G_FILE_TEST_EXISTS))
+ goto use_builtin_table;
+
+ JsonParser *parser = json_parser_new();
+ if (!json_parser_load_from_file(parser, flag_json, NULL))
+ goto use_builtin_table_with_json;
+
+ JsonNode *root = json_parser_get_root(parser);
+ if (json_node_get_node_type(root) != JSON_NODE_OBJECT)
+ goto use_builtin_table_with_json;
+
+ JsonObject *x86_flags =
+ json_object_get_object_member(json_node_get_object(root), "x86");
+ if (!x86_flags)
+ goto use_builtin_table_with_json;
+
+ tab_flag_meaning =
+ g_new(struct flag_to_meaning, json_object_get_size(x86_flags) + 1);
int i = 0;
- if (flag)
- while(tab_flag_meaning[i].name != NULL) {
+ json_object_foreach_member(x86_flags, build_meaning_table_iter, &i);
+ tab_flag_meaning[i] = (struct flag_to_meaning){NULL, NULL};
+ use_builtin_table = FALSE;
+
+use_builtin_table_with_json:
+ g_object_unref(parser);
+use_builtin_table:
+ g_free(flag_json);
+
+ if (use_builtin_table)
+ tab_flag_meaning = (struct flag_to_meaning *)builtin_tab_flag_meaning;
+}
+
+const char *x86_flag_meaning(const char *flag) {
+ int i;
+
+ if (!flag)
+ return NULL;
+
+ for (i = 0; tab_flag_meaning[i].name; i++) {
if (strcmp(tab_flag_meaning[i].name, flag) == 0) {
if (tab_flag_meaning[i].meaning != NULL)
return C_("x86-flag", tab_flag_meaning[i].meaning);
else return NULL;
}
- i++;
}
+
return NULL;
}
diff --git a/modules/network.c b/modules/network.c
index f27a159a..4b65e0aa 100644
--- a/modules/network.c
+++ b/modules/network.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2008 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2008 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,6 +27,8 @@
#include <sys/stat.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netdb.h>
#include <hardinfo.h>
@@ -106,8 +108,13 @@ void scan_statistics(gboolean reload)
gchar *tmp = buffer;
while (*tmp && isspace(*tmp)) tmp++;
-
- __statistics = h_strdup_cprintf("<b> </b>#%d=%s\n",
+ /* the bolded-space/dot used here is a hardinfo shell hack */
+ if (params.markup_ok)
+ __statistics = h_strdup_cprintf("<b> </b>#%d=%s\n",
+ __statistics,
+ line++, tmp);
+ else
+ __statistics = h_strdup_cprintf(">#%d=%s\n",
__statistics,
line++, tmp);
}
@@ -154,7 +161,6 @@ void scan_dns(gboolean reload)
__nameservers = h_strdup_cprintf("%s=%s\n",
__nameservers,
ip, hbuf);
-
}
shell_status_pulse();
@@ -427,15 +433,15 @@ void hi_module_deinit(void)
g_free(__connections);
}
-ModuleAbout *hi_module_get_about(void)
+const ModuleAbout *hi_module_get_about(void)
{
- static ModuleAbout ma[] = {
- {
- .author = "Leandro A. F. Pereira",
- .description = N_("Gathers information about this computer's network connection"),
- .version = VERSION,
- .license = "GNU GPL version 2"}
+ static const ModuleAbout ma = {
+ .author = "L. A. F. Pereira",
+ .description =
+ N_("Gathers information about this computer's network connection"),
+ .version = VERSION,
+ .license = "GNU GPL version 2 or later.",
};
- return ma;
+ return &ma;
}
diff --git a/modules/network/net.c b/modules/network/net.c
index a75cf8b6..9a5cb5f1 100644
--- a/modules/network/net.c
+++ b/modules/network/net.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2008 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2008 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -146,7 +146,7 @@ void get_wireless_info(int fd, NetInfo *netinfo)
if (ioctl(fd, SIOCGIWMODE, &wi_req) < 0) {
netinfo->wi_mode = 0;
} else {
- if (wi_req.u.mode >= 0 && wi_req.u.mode < 6) {
+ if (wi_req.u.mode < 6) {
netinfo->wi_mode = wi_req.u.mode;
} else {
netinfo->wi_mode = 6;
diff --git a/modules/network/nfs.c b/modules/network/nfs.c
index 54bbfe0e..67095f92 100644
--- a/modules/network/nfs.c
+++ b/modules/network/nfs.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2009 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2009 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/modules/network/samba.c b/modules/network/samba.c
index 7e8dc46c..e14742ea 100644
--- a/modules/network/samba.c
+++ b/modules/network/samba.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2009 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2009 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -57,7 +57,7 @@ scan_samba_usershares(void)
gchar *usershare, *cmdline;
gsize length;
- spawned = g_spawn_command_line_sync("net usershare list",
+ spawned = hardinfo_spawn_command_line_sync("net usershare list",
&out, &err, &status, NULL);
if (spawned && status == 0 && out != NULL) {
@@ -66,7 +66,7 @@ scan_samba_usershares(void)
while(next_nl = strchr(p, '\n')) {
cmdline = g_strdup_printf("net usershare info '%s'",
strend(p, '\n'));
- if (g_spawn_command_line_sync(cmdline,
+ if (hardinfo_spawn_command_line_sync(cmdline,
&usershare, NULL, NULL, NULL)) {
length = strlen(usershare);
scan_samba_from_string(usershare, length);
@@ -74,7 +74,6 @@ scan_samba_usershares(void)
}
g_free(cmdline);
- shell_status_pulse();
p = next_nl + 1;
}
g_free(out);
@@ -105,8 +104,6 @@ scan_samba_from_string(gchar *str, gsize length)
groups = g_key_file_get_groups(keyfile, NULL);
while (groups[i]) {
- shell_status_pulse();
-
if (g_key_file_has_key(keyfile, groups[i], "path", NULL)) {
gchar *path = g_key_file_get_string(keyfile, groups[i], "path", NULL);
smb_shares_list = h_strdup_cprintf("%s=%s\n",