aboutsummaryrefslogtreecommitdiff
path: root/modules/devices/devicetree.c
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2017-07-17 19:55:59 -0500
committerLeandro Pereira <leandro@hardinfo.org>2017-07-19 07:20:40 -0700
commitc68dc575e1ec0f537da9a03d4e65d3bde792842f (patch)
treee1ca3ab5c1e058d374a0776247c49c5b420bc389 /modules/devices/devicetree.c
parente9411970e677034a7ebdc4798b737dc0be1b1dd1 (diff)
device tree: attempt to group tuples when shown as hex values
Based on information from http://elinux.org/Device_Tree_Mysteries#.23xxx-cells_property_name which is incomplete, try and group tuples using the relevant inherited #(.*)-cells properies. Just reg, clocks, and gpios so far. More possible. See dt_tup_len(). Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'modules/devices/devicetree.c')
-rw-r--r--modules/devices/devicetree.c124
1 files changed, 104 insertions, 20 deletions
diff --git a/modules/devices/devicetree.c b/modules/devices/devicetree.c
index 5430bf28..142721c9 100644
--- a/modules/devices/devicetree.c
+++ b/modules/devices/devicetree.c
@@ -39,6 +39,7 @@ enum {
typedef struct {
char *path;
+ char *name;
int type;
unsigned long length;
void *data;
@@ -51,6 +52,8 @@ static struct {
{ "compatible", DTP_STR },
{ "model", DTP_STR },
{ "reg", DTP_HEX },
+ { "clocks", DTP_HEX },
+ { "gpios", DTP_HEX },
{ "phandle", DTP_HEX },
{ "interrupts", DTP_HEX },
{ "regulator-min-microvolt", DTP_UINT },
@@ -59,6 +62,9 @@ static struct {
{ NULL, 0 },
};
+static dt_raw *get_dt_raw(char *);
+static void dt_raw_free(dt_raw *);
+
/* Hardinfo labels that have # are truncated and/or hidden.
* Labels can't have $ because that is the delimiter in
* moreinfo. */
@@ -115,21 +121,16 @@ gchar *hardinfo_clean_value(const gchar *v, int replacing) {
return clean;
}
+#define DT_CHECK_NAME(prop, nm) (strcmp(prop->name, nm) == 0)
+
/*cstd*/
static int dt_guess_type(dt_raw *prop) {
- char *tmp, *slash, *dash;
+ char *tmp, *dash;
int i = 0, anc = 0, might_be_str = 1;
- /* find name after last slash, or start */
- slash = strrchr(prop->path, '/');
- if (slash != NULL)
- slash++;
- else
- slash = prop->path;
-
/* special #(.*)-cells names are UINT */
- if (*slash == '#') {
- dash = strrchr(slash, '-');
+ if (*prop->name == '#') {
+ dash = strrchr(prop->name, '-');
if (dash != NULL) {
if (strcmp(dash, "-cells") == 0)
return DTP_UINT;
@@ -138,7 +139,7 @@ static int dt_guess_type(dt_raw *prop) {
/* lookup known type */
while (prop_types[i].name != NULL) {
- if (strcmp(slash, prop_types[i].name) == 0)
+ if (strcmp(prop->name, prop_types[i].name) == 0)
return prop_types[i].type;
i++;
}
@@ -164,22 +165,93 @@ static int dt_guess_type(dt_raw *prop) {
}
/*cstd*/
-static char* dt_hex_list(uint32_t *list, int count) {
- char *ret, *dest, buff[11] = "";
- int i, l;
- l = count * 11 + 1;
- ret = malloc(l);
+static char* dt_hex_list(uint32_t *list, int count, int tup_len) {
+ char *ret, *dest;
+ char buff[15] = ""; /* max element: ">, <0x00000000\0" */
+ int i, l, tc;
+ l = count * 15 + 1;
+ dest = ret = malloc(l);
memset(ret, 0, l);
- dest = ret;
+ if (tup_len) {
+ strcpy(dest, "<");
+ dest = ret + 1;
+ }
+ tc = 0;
for (i = 0; i < count; i++) {
- sprintf(buff, "0x%x ", be32toh(list[i]));
+ if (tup_len) {
+ if (tc == tup_len) {
+ sprintf(buff, ">, <0x%x", be32toh(list[i]));
+ tc = 1;
+ } else {
+ sprintf(buff, "%s0x%x", (i) ? " " : "", be32toh(list[i]));
+ tc++;
+ }
+ } else
+ sprintf(buff, "%s0x%x", (i) ? " " : "", be32toh(list[i]));
l = strlen(buff);
strncpy(dest, buff, l);
dest += l;
}
+ if (tup_len)
+ strcpy(dest, ">");
+ return ret;
+}
+
+/* find an inherited property by climbing the path */
+/*cstd*/
+static int dt_inh_find(dt_raw *prop, char *inh_prop) {
+ char *slash, *tmp, *parent;
+ char buff[1024] = "";
+ dt_raw *tprop;
+ uint32_t ret = 0;
+
+ if (prop == NULL)
+ return 0;
+
+ parent = strdup(prop->path);
+ while ( slash = strrchr(parent, '/') ) {
+ *slash = 0;
+ sprintf(buff, "%s/%s", parent, inh_prop);
+ tprop = get_dt_raw(buff);
+ if (tprop != NULL) {
+ ret = be32toh(*(uint32_t*)tprop->data);
+ dt_raw_free(tprop);
+ break;
+ }
+ }
+
+ free(parent);
return ret;
}
+/*cstd*/
+static int dt_tup_len(dt_raw *prop) {
+ int address_cells, size_cells,
+ clock_cells, gpio_cells;
+
+ if (prop == NULL)
+ return 0;
+
+ if DT_CHECK_NAME(prop, "reg") {
+ address_cells = dt_inh_find(prop, "#address-cells");
+ size_cells = dt_inh_find(prop, "#size-cells");
+ return address_cells + size_cells;
+ }
+
+ if DT_CHECK_NAME(prop, "gpios") {
+ gpio_cells = dt_inh_find(prop, "#gpio-cells");
+ if (gpio_cells == 0) gpio_cells = 1;
+ return gpio_cells;
+ }
+
+ if DT_CHECK_NAME(prop, "clocks") {
+ clock_cells = dt_inh_find(prop, "#clock-cells");
+ return 1 + clock_cells;
+ }
+
+ return 0;
+}
+
/*cstd, except for g_strescape()*/
static char* dt_str(dt_raw *prop) {
char *tmp, *esc, *next_str;
@@ -219,7 +291,7 @@ static char* dt_str(dt_raw *prop) {
sprintf(ret, "%u", be32toh(*(uint32_t*)prop->data) );
} else if (i == DTP_HEX && !(prop->length % 4)) {
l = prop->length / 4;
- tmp = dt_hex_list((uint32_t*)prop->data, l);
+ tmp = dt_hex_list((uint32_t*)prop->data, l, dt_tup_len(prop));
strcpy(ret, tmp);
free(tmp);
} else {
@@ -242,8 +314,19 @@ static dt_raw *get_dt_raw(char *p) {
prop->type = DT_NODE;
} else {
prop->type = DT_PROPERTY;
- g_file_get_contents(full_path, (gchar**)&prop->data, (gsize*)&prop->length, NULL);
+ if (!g_file_get_contents(full_path, (gchar**)&prop->data, (gsize*)&prop->length, NULL)) {
+ dt_raw_free(prop);
+ return NULL;
+ }
}
+
+ /* find name after last slash, or start */
+ char *slash = strrchr(prop->path, '/');
+ if (slash != NULL)
+ prop->name = strdup(slash + 1);
+ else
+ prop->name = strdup(prop->path);
+
return prop;
}
return NULL;
@@ -253,6 +336,7 @@ static dt_raw *get_dt_raw(char *p) {
void dt_raw_free(dt_raw *s) {
if (s != NULL) {
free(s->path);
+ free(s->name);
free(s->data);
}
free(s);