]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fdt] Identify free space (if any) at end of parsed tree
authorMichael Brown <mcb30@ipxe.org>
Tue, 1 Apr 2025 12:04:10 +0000 (13:04 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 1 Apr 2025 12:08:41 +0000 (13:08 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/fdt.c
src/include/ipxe/fdt.h

index 59692e1352827412ff4565116af46d54dd295a6a..1664ec7b2085026f147db2fec75b38f9bdd9caa9 100644 (file)
@@ -458,10 +458,11 @@ int fdt_mac ( struct fdt *fdt, unsigned int offset,
  * @ret rc             Return status code
  */
 int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ) {
-       const uint8_t *end;
+       const uint8_t *nul;
+       size_t end;
 
        /* Sanity check */
-       if ( sizeof ( fdt ) > max_len ) {
+       if ( sizeof ( *hdr ) > max_len ) {
                DBGC ( fdt, "FDT length %#zx too short for header\n",
                       max_len );
                goto err;
@@ -470,6 +471,7 @@ int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ) {
        /* Record device tree location */
        fdt->hdr = hdr;
        fdt->len = be32_to_cpu ( hdr->totalsize );
+       fdt->used = sizeof ( *hdr );
        if ( fdt->len > max_len ) {
                DBGC ( fdt, "FDT has invalid length %#zx / %#zx\n",
                       fdt->len, max_len );
@@ -507,6 +509,9 @@ int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ) {
                DBGC ( fdt, "FDT structure block is misaligned\n" );
                goto err;
        }
+       end = ( fdt->structure + fdt->structure_len );
+       if ( fdt->used < end )
+               fdt->used = end;
 
        /* Record strings block location */
        fdt->strings = be32_to_cpu ( hdr->off_dt_strings );
@@ -518,11 +523,14 @@ int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ) {
                DBGC ( fdt, "FDT strings block exceeds table\n" );
                goto err;
        }
+       end = ( fdt->strings + fdt->strings_len );
+       if ( fdt->used < end )
+               fdt->used = end;
 
        /* Shrink strings block to ensure NUL termination safety */
-       end = ( fdt->raw + fdt->strings + fdt->strings_len );
+       nul = ( fdt->raw + fdt->strings + fdt->strings_len );
        for ( ; fdt->strings_len ; fdt->strings_len-- ) {
-               if ( *(--end) == '\0' )
+               if ( *(--nul) == '\0' )
                        break;
        }
        if ( fdt->strings_len != be32_to_cpu ( hdr->size_dt_strings ) ) {
@@ -530,6 +538,21 @@ int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ) {
                       fdt->strings, ( fdt->strings + fdt->strings_len ) );
        }
 
+       /* Record memory reservation block location */
+       fdt->reservations = be32_to_cpu ( hdr->off_mem_rsvmap );
+       DBGC ( fdt, "FDT memory reservations at +[%#04x,...)\n",
+              fdt->reservations );
+       if ( fdt->used <= fdt->reservations ) {
+               /* No size field exists: assume whole table is used */
+               fdt->used = fdt->len;
+       }
+
+       /* Identify free space (if any) */
+       if ( fdt->used < fdt->len ) {
+               DBGC ( fdt, "FDT free space at +[%#04zx,%#04zx)\n",
+                      fdt->used, fdt->len );
+       }
+
        /* Print model name (for debugging) */
        DBGC ( fdt, "FDT model is \"%s\"\n", fdt_string ( fdt, 0, "model" ) );
 
index 46025f02e995c24dea481000436bb35d0447d9d0..0c2137f2bbf8d7050b80847c3ac253166bc33349 100644 (file)
@@ -84,6 +84,8 @@ struct fdt {
        };
        /** Length of tree */
        size_t len;
+       /** Used length of tree */
+       size_t used;
        /** Offset to structure block */
        unsigned int structure;
        /** Length of structure block */
@@ -92,6 +94,8 @@ struct fdt {
        unsigned int strings;
        /** Length of strings block */
        size_t strings_len;
+       /** Offset to memory reservation block */
+       unsigned int reservations;
 };
 
 extern struct image_tag fdt_image __image_tag;