This commit allows running functions marked with
__attribute__((constructor))[1] automatically after the C environment is
setup in setup_c, which most likely will be early setup code shared
across SoCs/Arches in the PBL.

[1]: 
https://gcc.gnu.org/onlinedocs/gcc-16.2.0/gcc/Common-Attributes.html#index-constructor

Signed-off-by: Stefan Kerkmann <[email protected]>
---
 arch/arm/cpu/setupc_32.S       |  3 +++
 arch/arm/cpu/setupc_64.S       |  3 +++
 arch/arm/lib/pbl.lds.S         |  8 ++++++++
 arch/riscv/lib/pbl.lds.S       |  9 +++++++++
 arch/riscv/lib/setupc.S        |  3 +++
 include/asm-generic/sections.h |  2 ++
 pbl/Makefile                   |  1 +
 pbl/ctors.c                    | 13 +++++++++++++
 8 files changed, 42 insertions(+)

diff --git a/arch/arm/cpu/setupc_32.S b/arch/arm/cpu/setupc_32.S
index fadfc28ae1..f34b144556 100644
--- a/arch/arm/cpu/setupc_32.S
+++ b/arch/arm/cpu/setupc_32.S
@@ -23,6 +23,9 @@ ENTRY(setup_c)
        ldr     r0, =bss_cleared
        mov     r1, #1
        str     r1, [r0]                /* mark bss cleared */
+#ifdef __PBL__
+       bl      pbl_do_ctors
+#endif
 1:     pop     {r4, pc}
 ENDPROC(setup_c)
 
diff --git a/arch/arm/cpu/setupc_64.S b/arch/arm/cpu/setupc_64.S
index a0767c5136..e3c6149e27 100644
--- a/arch/arm/cpu/setupc_64.S
+++ b/arch/arm/cpu/setupc_64.S
@@ -22,6 +22,9 @@ ENTRY(setup_c)
        adr_l   x0, bss_cleared
        mov     w1, #1
        str     w1, [x0]                /* mark bss cleared */
+#ifdef __PBL__
+       bl      pbl_do_ctors
+#endif
        mov     x30, x15
 1:     ret
 ENDPROC(setup_c)
diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S
index 9c51f5eb3a..72aca83495 100644
--- a/arch/arm/lib/pbl.lds.S
+++ b/arch/arm/lib/pbl.lds.S
@@ -78,6 +78,14 @@ SECTIONS
        . = ALIGN(4);
        .rodata : { *(.rodata*) }
 
+       . = ALIGN(ASM_SZPTR);
+       __ctors_start = .;
+       .init_array : {
+               KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
+               KEEP(*(.init_array))
+       }
+       __ctors_end = .;
+
        .barebox_imd : { BAREBOX_IMD }
 
        . = ALIGN(PBL_SEGMENT_ALIGN);
diff --git a/arch/riscv/lib/pbl.lds.S b/arch/riscv/lib/pbl.lds.S
index 3a37d01475..17cd61ff75 100644
--- a/arch/riscv/lib/pbl.lds.S
+++ b/arch/riscv/lib/pbl.lds.S
@@ -4,6 +4,7 @@
 #include <linux/sizes.h>
 #include <asm/barebox.lds.h>
 #include <asm-generic/memory_layout.h>
+#include <asm-generic/pointer.h>
 
 OUTPUT_ARCH(BAREBOX_OUTPUT_ARCH)
 OUTPUT_FORMAT(BAREBOX_OUTPUT_FORMAT)
@@ -32,6 +33,14 @@ SECTIONS
        __start_rodata = .;
        .rodata : { *(.rodata*) }
 
+       . = ALIGN(ASM_SZPTR);
+       __ctors_start = .;
+       .init_array : {
+               KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
+               KEEP(*(.init_array))
+       }
+       __ctors_end = .;
+
        .barebox_imd : { BAREBOX_IMD }
 
        __end_rodata = .;
diff --git a/arch/riscv/lib/setupc.S b/arch/riscv/lib/setupc.S
index 5370e8a48e..938c78350c 100644
--- a/arch/riscv/lib/setupc.S
+++ b/arch/riscv/lib/setupc.S
@@ -23,6 +23,9 @@ ENTRY(setup_c)
        lla     a0, bss_cleared
        li      a1, 1
        sw      a1, 0(a0)
+#ifdef __PBL__
+       jal     pbl_do_ctors
+#endif
 zeroed:
        REG_L   ra, SZREG(sp)
        addi    sp, sp, SZREG * 2
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 816e30341d..c7c576970a 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -49,4 +49,6 @@ static inline bool in_barebox_efi_runtime(unsigned long addr)
               addr < (unsigned long)__efi_runtime_stop;
 }
 
+void pbl_do_ctors(void);
+
 #endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/pbl/Makefile b/pbl/Makefile
index 4506f192fe..7ce8cee077 100644
--- a/pbl/Makefile
+++ b/pbl/Makefile
@@ -3,6 +3,7 @@
 #
 # only unsed by the pbl
 #
+pbl-y += ctors.o
 pbl-y += misc.o
 pbl-y += string.o
 pbl-y += malloc.o
diff --git a/pbl/ctors.c b/pbl/ctors.c
new file mode 100644
index 0000000000..fcab599877
--- /dev/null
+++ b/pbl/ctors.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <asm-generic/sections.h>
+
+typedef void (*ctor_fn_t)(void);
+
+void pbl_do_ctors(void)
+{
+       ctor_fn_t *fn = (ctor_fn_t *)__ctors_start;
+
+       for (; fn < (ctor_fn_t *)__ctors_end; fn++)
+               (*fn)();
+}

-- 
2.47.3


Reply via email to