Currently some ARM-based platforms reserve TF-A memory in their own ways:
- Mediatek gets BL31 region via SMC call in ft_system_setup()
- K3 uses CONFIG_K3_ATF_LOAD_ADDR, effectively in ft_system_setup()

And others like Allwinner simply forget to do it, which results in Linux
overwriting TF-A and crashing.

Unfortunately seems that the things are not much better on TF-A side and
there is no universal way to get the reserved memory region across
platforms. But there is at least a most common way in TF-A, namely
reserving  memory range in the FDT, in particular:
- Allwinner     ("tf-a@40000000" node)
- ARM FPGA      ("tf-a@80000000" node)
- Xilinx        ("tf-a" node)

While this patch aims to improve the situation for Allwinner platforms,
it's deliberately adding more generic code to pave the potential way of
unification for other platforms.

Note that fdtdec_add_reserved_memory() has a check for an already existing
carveout with exactly matching boundaries and will not create a duplicate
even if the name doesn't match. It would not however detect an already
existing bigger carveout fully containing the one requested.

Signed-off-by: Alexander Sverdlin <[email protected]>
---
The patch has been developed to faciliate Allwinner A133 SoC support, where
most of the work currently happens on TF-A [1] and Linux [2] sides, but
I wanted to send this patch upfront to get the first feedback and because
already supported H616 SoC would already benefit from the patch.

[1] https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/49754
[2] 
https://lore.kernel.org/all/[email protected]/
[3] 
https://lore.kernel.org/all/[email protected]/

 arch/arm/lib/bootm-fdt.c | 55 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c
index 2671f9a0ebf..19d917943c1 100644
--- a/arch/arm/lib/bootm-fdt.c
+++ b/arch/arm/lib/bootm-fdt.c
@@ -14,7 +14,9 @@
  * Copyright (C) 2001  Erik Mouw ([email protected])
  */
 
+#include <dm/ofnode.h>
 #include <fdt_support.h>
+#include <linux/ioport.h>
 #ifdef CONFIG_ARMV7_NONSEC
 #include <asm/armv7.h>
 #endif
@@ -24,6 +26,52 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static int tfa_copy_reserved_memory(void *new_blob)
+{
+#ifdef CONFIG_OF_CONTROL
+       ofnode node, subnode;
+
+       /*
+        * TF-A for several platforms inserts its memory region as
+        * reserved-memory node
+        */
+       node = ofnode_path("/reserved-memory");
+       if (!ofnode_valid(node))
+               return 0;
+
+       ofnode_for_each_subnode(subnode, node) {
+               struct fdt_memory carveout;
+               struct resource res;
+               const char *name;
+               int ret;
+
+               name = ofnode_get_name(subnode);
+               if (!name)
+                       return -FDT_ERR_BADSTRUCTURE;
+
+               /* only handle TF-A reservations */
+               if (strncmp(name, "tf-a", 4))
+                       continue;
+
+               /* check if this subnode has a reg property */
+               ret = ofnode_read_resource(subnode, 0, &res);
+               if (ret)
+                       continue;
+
+               carveout.start = res.start,
+               carveout.end = res.end,
+
+               ret = fdtdec_add_reserved_memory(new_blob, "tf-a", &carveout,
+                                                NULL, 0, NULL,
+                                                FDTDEC_RESERVED_MEMORY_NO_MAP);
+               if (ret < 0)
+                       return ret;
+       }
+#endif
+
+       return 0;
+}
+
 #ifdef CONFIG_FMAN_ENET
 __weak int fdt_update_ethernet_dt(void *blob)
 {
@@ -56,6 +104,13 @@ int arch_fixup_fdt(void *blob)
                return ret;
 #endif
 
+       ret = tfa_copy_reserved_memory(blob);
+       if (ret) {
+               printf("ERROR: transfer of TF-A nodes to new fdt failed: %s\n",
+                      fdt_strerror(ret));
+               return ret;
+       }
+
 #ifdef CONFIG_ARMV8_SPIN_TABLE
        ret = spin_table_update_dt(blob);
        if (ret)
-- 
2.54.0

Reply via email to