dgibson / dtc

Device Tree Compiler
218 stars 130 forks source link

String lists in files converted from DTB to DTS #47

Closed gaislerarvid closed 3 years ago

gaislerarvid commented 3 years ago

Converting a DTB file to DTS, that contains a list of strings seems to be broken. The null-character that is separating the strings gets interpreted as a literal null-character.

For example using this simple DTS as source:

$ cat stringlist.dts
/dts-v1/;

/ {
        stringlist1 = "foobar";
        stringlist2 = "hello,world", "foobar";
        stringlist3 = "hello", "world";
        nulllist1= "hello\0world", "foobar";
        nulllist2 = "hello,world", "\0";
        nulllist3 = "hello\0world", "\0";
};

Converting to DTB and back to DTS using v1.6.0 (i.e. latest commit) I get:

$ ./dtc -I dts -O dtb stringlist.dts | ./dtc -I dtb -O dts /dev/stdin
/dts-v1/;

/ {
        stringlist1 = "foobar";
        stringlist2 = "hello,world\0foobar";
        stringlist3 = "hello\0world";
        nulllist1 = "hello\0world\0foobar";
        nulllist2 = "hello,world\0\0";
        nulllist3 = "hello\0world\0\0";
};

Using v1.4.6 I get what I believe is the correct result:

$ ./dtc -I dts -O dtb stringlist.dts | ./dtc -I dtb -O dts /dev/stdin
/dts-v1/;

/ {
        stringlist1 = "foobar";
        stringlist2 = "hello,world", "foobar";
        stringlist3 = "hello", "world";
        nulllist1 = "hello", "world", "foobar";
        nulllist2 = "hello,world", "", "";
        nulllist3 = "hello", "world", "", "";
};

The commit that introduces this is 32b9c61307629ac76c6ac0bead6f926d579b3d2c . I'm new to device trees in general, and to the DTC source code, so I'm uncertain how this is supposed to work, if it's the parsing of the DTB or writing the DTS that is wrong.

This commit also includes a test, but that test only converts DTS to DTS, which doesn't trigger this issue. I.e. using v.1.6.0 (latest commit):

$ ./dtc -I dts -O dts stringlist.dts
/dts-v1/;

/ {
        stringlist1 = "foobar";
        stringlist2 = "hello,world", "foobar";
        stringlist3 = "hello", "world";
        nulllist1 = "hello\0world", "foobar";
        nulllist2 = "hello,world", "\0";
        nulllist3 = "hello\0world", "\0";
};
dgibson commented 3 years ago

So, the thing to understand here is that in a dtb, all properties are just bytestrings. At the dtb level they have no internal structure, you have to know the binding for the node/properties in question to parse them correctly.

The various ways of data in different types in the dts is just a convenience so, foo = "abc";, foo = <0x61626300>; and foo = [61626300]; will all result in byte-for-byte identical output in the dtb.

Conversion from .dtb to .dts, is based on some rough heuristics to guess which form to express the data in. So, the two forms of output you show are both correct, just making different guesses about formatting.

It used to be the case that using -I dts -O dts would also reformat things according to those heuristics. People didn't like that, so https://github.com/dgibson/dtc/commit/32b9c61307629ac76c6ac0bead6f926d579b3d2c changed things so that dtc remembers the input format and uses that to format things the same way on output. That type information doesn't make it into the .dtb though, so we still fall back to heurstics in that case. The heuristics also changed a bit in the same commit, hence the change in output you saw.

I'm honestly not that convinced that preserving the formatting for -I dts -O dts was a great idea, precisely because it can give the misleading impression that the "types" are part of the device tree structure, which they're not. Nonetheless this behaviour has been established for a while now, and people argued pretty hard for it, so I'm not planning on changing it.