From: Fabien Parent <fpar...@baylibre.com>

Add the ability to check if a property has the correct type. Right now dtc only
handles the two trivial types: integer array, string array. Since at the end
everything is an array of byte which may or may not be terminated by a null
byte this was enough.

A nice thing to add for the future would be to be able to specify the types
more precisely.

Add as well two test files for this feature.

/ {
    compatible = "abc";

    abc = <0xa 0xb 0xc>;
    def = "def", gef;
};

To check that the property abc is an integer array and that the property def
is a string array for the dts above one can use the following schema:

/ {
    compatible = "abc";

    abc {
        type = "integer";
    };

    def {
        type = "string";
    };
};

Signed-off-by: Fabien Parent <fpar...@baylibre.com>
Signed-off-by: Benoit Cousson <bcous...@baylibre.com>
---
 scripts/dtc/data.c                       | 22 ++++++++++++----
 scripts/dtc/dtc.h                        |  9 +++++++
 scripts/dtc/schema-test.c                |  5 ++++
 scripts/dtc/schema.c                     | 44 ++++++++++++++++++++++++++++++++
 scripts/dtc/tests/schemas/types-1.schema | 12 +++++++++
 scripts/dtc/tests/schemas/types-2.schema |  7 +++++
 scripts/dtc/tests/test1.dts              | 10 ++++++++
 7 files changed, 104 insertions(+), 5 deletions(-)
 create mode 100644 scripts/dtc/tests/schemas/types-1.schema
 create mode 100644 scripts/dtc/tests/schemas/types-2.schema
 create mode 100644 scripts/dtc/tests/test1.dts

diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index 4a40c5b..9e03718 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -75,6 +75,7 @@ struct data data_copy_escape_string(const char *s, int len)
        char *q;
 
        d = data_grow_for(empty_data, strlen(s)+1);
+       d.type = STRING;
 
        q = d.val;
        while (i < len) {
@@ -93,6 +94,7 @@ struct data data_copy_escape_string(const char *s, int len)
 struct data data_copy_file(FILE *f, size_t maxlen)
 {
        struct data d = empty_data;
+       d.type = STRING;
 
        while (!feof(f) && (d.len < maxlen)) {
                size_t chunksize, ret;
@@ -157,6 +159,7 @@ struct data data_merge(struct data d1, struct data d2)
        struct marker *m2 = d2.markers;
 
        d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
+       d.type = d2.type ? d2.type : d1.type;
 
        /* Adjust for the length of d1 */
        for_each_marker(m2)
@@ -178,23 +181,30 @@ struct data data_append_integer(struct data d, uint64_t 
value, int bits)
        switch (bits) {
        case 8:
                value_8 = value;
-               return data_append_data(d, &value_8, 1);
+               d = data_append_data(d, &value_8, 1);
+               break;
 
        case 16:
                value_16 = cpu_to_fdt16(value);
-               return data_append_data(d, &value_16, 2);
+               d = data_append_data(d, &value_16, 2);
+               break;
 
        case 32:
                value_32 = cpu_to_fdt32(value);
-               return data_append_data(d, &value_32, 4);
+               d = data_append_data(d, &value_32, 4);
+               break;
 
        case 64:
                value_64 = cpu_to_fdt64(value);
-               return data_append_data(d, &value_64, 8);
+               d = data_append_data(d, &value_64, 8);
+               break;
 
        default:
                die("Invalid literal size (%d)\n", bits);
        }
+
+       d.type = INTEGER;
+       return d;
 }
 
 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
@@ -219,7 +229,9 @@ struct data data_append_addr(struct data d, uint64_t addr)
 
 struct data data_append_byte(struct data d, uint8_t byte)
 {
-       return data_append_data(d, &byte, 1);
+       d = data_append_data(d, &byte, 1);
+       d.type = INTEGER;
+       return d;
 }
 
 struct data data_append_zeroes(struct data d, int len)
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index e61dde7..a9b8602 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -82,10 +82,19 @@ struct  marker {
        struct marker *next;
 };
 
+enum datatype {
+       UNDEFINED,
+       BOOLEAN,
+       INTEGER,
+       STRING,
+};
+
 struct data {
        int len;
        char *val;
        struct marker *markers;
+
+       enum datatype type;
 };
 
 
diff --git a/scripts/dtc/schema-test.c b/scripts/dtc/schema-test.c
index 0eb2499..57c86d0 100644
--- a/scripts/dtc/schema-test.c
+++ b/scripts/dtc/schema-test.c
@@ -18,6 +18,11 @@ struct schema_test {
 };
 
 static struct schema_test tests[] = {
+       /* Types */
+       {"Types #1", "tests/test1.dts",
+        "tests/schemas/types-1.schema", 1},
+       {"Types #2", "tests/test1.dts",
+        "tests/schemas/types-2.schema", 0},
 };
 
 int main(void)
diff --git a/scripts/dtc/schema.c b/scripts/dtc/schema.c
index b190241..c01cdee 100644
--- a/scripts/dtc/schema.c
+++ b/scripts/dtc/schema.c
@@ -33,6 +33,7 @@ struct node_list {
 
 struct prop_constraints {
        const char *name;
+       char *type;
 };
 
 struct node_constraints {
@@ -202,9 +203,41 @@ load_property_constraints(struct node *schema)
        if (p)
                pc->name = p->val.val;
 
+       p = get_property(schema, "type");
+       if (p)
+               pc->type = p->val.val;
+
        return pc;
 }
 
+static int check_types(struct property *p, struct prop_constraints *pc)
+{
+       assert(p);
+       assert(pc);
+
+       if (!pc->type)
+               return 1;
+
+       switch (p->val.type) {
+       case BOOLEAN:
+               return !strcmp(pc->type, "bool");
+
+       case STRING:
+               return !strcmp(pc->type, "string");
+
+       case INTEGER:
+               return !strcmp(pc->type, "integer");
+
+       case UNDEFINED:
+               return 1;
+
+       default:
+               die("We shouldn't reach this point.");
+       };
+
+       return 0;
+}
+
 static int validate_properties(struct node *n,
                               struct node *schema,
                               struct node_list *path);
@@ -222,6 +255,15 @@ static int validate_property(struct node *n,
        assert(pc);
        assert(path);
 
+       if (!p)
+               goto end;
+
+       if (!check_types(p, pc)) {
+               DT_ERROR(path, p, "Bad type for property, expecting a value of "
+                                 "the following type: '%s'\n", pc->type);
+       }
+
+end:
        free_property_constraints(pc);
        return ret;
 }
@@ -319,6 +361,7 @@ static int for_each_compatible_validate(struct schema_db 
*db,
        assert(db);
        assert(node);
        assert(p);
+       assert(p->val.type == STRING);
 
        while (offset >= 0 && offset < p->val.len) {
                i = 0;
@@ -455,6 +498,7 @@ static void add_to_schema_db_from_property(struct schema_db 
*db,
        assert(db);
        assert(file);
        assert(p);
+       assert(p->val.type == STRING);
 
        while (offset >= 0 && offset < p->val.len) {
                add_compatible_to_schema_db(db, p->val.val + offset, file);
diff --git a/scripts/dtc/tests/schemas/types-1.schema 
b/scripts/dtc/tests/schemas/types-1.schema
new file mode 100644
index 0000000..71d09e7
--- /dev/null
+++ b/scripts/dtc/tests/schemas/types-1.schema
@@ -0,0 +1,12 @@
+/dts-v1/;
+/ {
+       compatible = "compat1";
+
+       mypropint {
+               type = "integer";
+       };
+
+       mypropstr {
+               type = "string";
+       };
+};
diff --git a/scripts/dtc/tests/schemas/types-2.schema 
b/scripts/dtc/tests/schemas/types-2.schema
new file mode 100644
index 0000000..f0779e1
--- /dev/null
+++ b/scripts/dtc/tests/schemas/types-2.schema
@@ -0,0 +1,7 @@
+/dts-v1/;
+/ {
+       compatible = "compat1";
+       mypropstr {
+               type = "integer";
+       };
+};
diff --git a/scripts/dtc/tests/test1.dts b/scripts/dtc/tests/test1.dts
new file mode 100644
index 0000000..9a950da
--- /dev/null
+++ b/scripts/dtc/tests/test1.dts
@@ -0,0 +1,10 @@
+/dts-v1/;
+/ {
+       compatible = "root", "node";
+
+       node1 {
+               compatible = "compat1";
+               mypropint = <0 2 4 6>;
+               mypropstr = "value0", "value1", "value2";
+       };
+};
-- 
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to