On 28/02/16(Sun) 16:58, Patrick Wildt wrote:
> Hi,
>
> unfortunately the end signature check is still not correct. Consulting
> the spec cleared the confusion of why the check does not work on my ARM
> machines.
>
> The FDT tree contains a "structure block". The FDT header contains
> information, on which offset that block starts. Since version 17 of
> the spec there's another bit of information in the header. It's the
> size of the structure block. Now the end of the structure block is
> marked by an FDT_END marker.
>
> The spec says that there shall only be one FDT_END token, and it should
> be the last _in_ the structure block. And the byte following that token
> has the offset fh_struct_size + fh_struct_off from the root header.
>
> Now essentially we have to look for that tag at:
>
> fdt + fh_struct_size + fh_struct_off - 1
>
> The following diff allows fdt_init() to succeed in my tests.
Looks good to me and does not create any regression on Thecus N1200.
I'm going to commit the rebased diff below unless I hear any objection.
Index: dev/ofw//fdt.c
===================================================================
RCS file: /cvs/src/sys/dev/ofw/fdt.c,v
retrieving revision 1.1
diff -u -p -r1.1 fdt.c
--- dev/ofw//fdt.c 3 Mar 2016 02:42:16 -0000 1.1
+++ dev/ofw//fdt.c 6 Mar 2016 14:32:02 -0000
@@ -59,7 +59,8 @@ fdt_check_head(void *fdt)
/* check for end signature on version 17 blob */
if ((betoh32(fh->fh_version) >= 17) &&
- (betoh32(*(ptr + betoh32(fh->fh_struct_size))) != FDT_END))
+ (betoh32(*(ptr + (betoh32(fh->fh_struct_off) / 4) +
+ (betoh32(fh->fh_struct_size) / 4) - 1)) != FDT_END))
return 0;
return betoh32(fh->fh_version);