On 7/1/26 2:50 AM, Paresh Bhagat wrote:
Fix phandle corruption in fdt_fixup_reserved_memory()

The original implementation used a delete/recreate approach:
- Find existing reserved memory node (e.g. tfa@80000000)
- Delete the entire node with fdt_del_node()
- Create new node with fdtdec_add_reserved_memory()

This worked fine for ATF and OPTEE nodes because no other device tree
nodes reference them via phandles but other nodes example DM are
referenced by R5 nodes.

If these nodes are deleted and recreated, it will not have any phandle
property but the nodes referencing it will still contain the old
phandle, causing initialization to fail.

Update nodes in-place instead of delete/recreate to update only the
"reg" property using fdt_setprop().

Fixes: 8b0fc29de0e3 ("arm: mach-k3: am62: Fixup TF-A/OP-TEE reserved-memory node in 
FDT")

Signed-off-by: Paresh Bhagat <[email protected]>
---
  arch/arm/mach-k3/common_fdt.c | 31 +++++++------------------------
  1 file changed, 7 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-k3/common_fdt.c b/arch/arm/mach-k3/common_fdt.c
index 39cb00c3f43..4b833f5fabe 100644
--- a/arch/arm/mach-k3/common_fdt.c
+++ b/arch/arm/mach-k3/common_fdt.c
@@ -119,7 +119,6 @@ static int fdt_fixup_reserved_memory(void *blob, const char 
*name,
                                     unsigned int new_size)
  {
        int nodeoffset, subnode;
-       int ret;
        struct fdt_memory carveout = {
                .start = new_address,
        };
@@ -129,43 +128,27 @@ static int fdt_fixup_reserved_memory(void *blob, const 
char *name,
        if (nodeoffset < 0)
                goto add_carveout;
- /* Find existing matching subnode and remove it */
+       /* Find existing matching subnode and update it in place */
        fdt_for_each_subnode(subnode, blob, nodeoffset) {
                const char *node_name;
-               fdt_addr_t addr;
-               fdt_size_t size;
+               u64 reg[2];
/* Name matching */
                node_name = fdt_get_name(blob, subnode, NULL);
                if (!name)
                        return -EINVAL;
                if (!strncmp(node_name, name, strlen(name))) {
-                       /* Read out old size first */
-                       addr = fdtdec_get_addr_size_auto_parent(
-                               blob, nodeoffset, subnode, "reg", 0, &size,
-                               false);
-                       if (addr == FDT_ADDR_T_NONE)
-                               return -EINVAL;
-                       new_size = size;
-
-                       /* Delete node */
-                       ret = fdt_del_node(blob, subnode);
-                       if (ret < 0)
-                               return ret;
-
-                       /* Only one matching node */
-                       break;
+                       /* Update the reg property in place */
+                       reg[0] = cpu_to_fdt64(new_address);
+                       reg[1] = cpu_to_fdt64(new_size);
+                       return fdt_setprop(blob, subnode, "reg", reg, 
sizeof(reg));

Note that this only updates the `reg` property, not the node name itself
which will still include the old @address. Not that it really matters though,
I'm just trying to remember why I used a delete/recreate approach here in
the first place.

This also assumes address and size cells are always 64bit (which should
always be the case, but might be good to check).

Acked-by: Andrew Davis <[email protected]>

                }
        }
add_carveout:
        carveout.end = new_address + new_size - 1;
-       ret = fdtdec_add_reserved_memory(blob, name, &carveout, NULL, 0, NULL,
+       return fdtdec_add_reserved_memory(blob, name, &carveout, NULL, 0, NULL,
                                         FDTDEC_RESERVED_MEMORY_NO_MAP);
-       if (ret < 0)
-               return ret;
-
-       return 0;
  }
int fdt_fixup_reserved(void *blob)

Reply via email to