diff options
Diffstat (limited to 'modules/devices/devicetree.c')
-rw-r--r-- | modules/devices/devicetree.c | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/modules/devices/devicetree.c b/modules/devices/devicetree.c index d9700854..528a3d65 100644 --- a/modules/devices/devicetree.c +++ b/modules/devices/devicetree.c @@ -20,6 +20,7 @@ */ #include <unistd.h> #include <sys/types.h> +#include <stdint.h> #include <endian.h> #include "devices.h" @@ -29,9 +30,10 @@ enum { }; enum { DTP_UNK, - DTP_STR, + DTP_STR, /* null-delimited list of strings */ DTP_INT, - DTP_HEX, + DTP_UINT, + DTP_HEX, /* list of 32-bit values displayed in hex */ }; typedef struct { @@ -47,13 +49,12 @@ static struct { { "name", DTP_STR }, { "compatible", DTP_STR }, { "model", DTP_STR }, - { "phandle", DTP_UNK }, - { "reg", DTP_UNK }, - { "#address-cells", DTP_UNK }, - { "#size-cells", DTP_UNK }, - { "regulator-min-microvolt", DTP_INT }, - { "regulator-max-microvolt", DTP_INT }, - { "clock-frequency", DTP_INT }, + { "reg", DTP_HEX }, + { "phandle", DTP_HEX }, + { "interrupts", DTP_HEX }, + { "regulator-min-microvolt", DTP_UINT }, + { "regulator-max-microvolt", DTP_UINT }, + { "clock-frequency", DTP_UINT }, { NULL, 0 }, }; @@ -91,16 +92,27 @@ gchar *hardinfo_clean_value(const gchar *v, int replacing) { } static int dt_guess_type(dt_raw *prop) { - char *tmp, *slash; + char *tmp, *slash, *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 (dash != NULL) { + if (strcmp(dash, "-cells") == 0) + return DTP_UINT; + } + } + /* lookup known type */ while (prop_types[i].name != NULL) { - slash = strrchr(prop->path, '/'); - if (slash != NULL) - slash++; - else - slash = prop->path; if (strcmp(slash, prop_types[i].name) == 0) return prop_types[i].type; i++; @@ -120,12 +132,28 @@ static int dt_guess_type(dt_raw *prop) { || anc >= 5 ) /*arbitrary*/) return DTP_STR; - if (prop->length == 4) /* maybe an int */ - return DTP_INT; + if (!(prop->length % 4)) /* multiple of 4 bytes, try list of hex values */ + return DTP_HEX; return DTP_UNK; } +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); + memset(ret, 0, l); + dest = ret; + for (i = 0; i < count; i++) { + sprintf(buff, "0x%x ", be32toh(list[i])); + l = strlen(buff); + strncpy(dest, buff, l); + dest += l; + } + return ret; +} + static char* dt_str(dt_raw *prop) { char *tmp, *esc, *next_str, *ret = NULL; int i, l, tl; @@ -157,7 +185,13 @@ static char* dt_str(dt_raw *prop) { if (tl >= prop->length) break; } } else if (i == DTP_INT && prop->length == 4) { - ret = g_strdup_printf("%d", be32toh(*(int*)prop->data) ); + /* still use uint32_t for the byte-order conversion */ + ret = g_strdup_printf("%d", be32toh(*(uint32_t*)prop->data) ); + } else if (i == DTP_UINT && prop->length == 4) { + ret = g_strdup_printf("%u", be32toh(*(uint32_t*)prop->data) ); + } else if (i == DTP_HEX && !(prop->length % 4)) { + l = prop->length / 4; + ret = dt_hex_list((uint32_t*)prop->data, l); } else { ret = g_strdup_printf("{data} (%lu bytes)", prop->length); } |