From 82e26e0d6883673bdedbcdb0ddd4bc967ce6ce70 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:16 -0600 Subject: spl: Use CONFIG_SPL... instead of CONFIG_..._SPL_... We like to put the SPL first so it is clear that it relates to SPL. Rename various malloc-related options which have crept in, to stick to this convention. Signed-off-by: Simon Glass Reviewed-by: Marcel Ziswiler Reviewed-by: Martyn Welch Reviewed-by: Svyatoslav Ryhel --- include/configs/socfpga_common.h | 2 +- include/configs/socfpga_soc64_common.h | 2 +- include/system-constants.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h index 0c96c9c24fe..4838bfd4f13 100644 --- a/include/configs/socfpga_common.h +++ b/include/configs/socfpga_common.h @@ -18,7 +18,7 @@ #define CFG_SYS_INIT_RAM_ADDR 0xFFE00000 /* SPL memory allocation configuration, this is for FAT implementation */ #define CFG_SYS_INIT_RAM_SIZE (SOCFPGA_PHYS_OCRAM_SIZE - \ - CONFIG_SYS_SPL_MALLOC_SIZE) + CONFIG_SPL_SYS_MALLOC_SIZE) #endif /* diff --git a/include/configs/socfpga_soc64_common.h b/include/configs/socfpga_soc64_common.h index 66ecb168a0a..820372c28b3 100644 --- a/include/configs/socfpga_soc64_common.h +++ b/include/configs/socfpga_soc64_common.h @@ -112,7 +112,7 @@ unsigned int cm_get_l4_sys_free_clk_hz(void); * SDRAM * 0x0000_0000 ...... Start of SDRAM_1 * unused / empty space for image loading - * Size 64MB ...... MALLOC (size CONFIG_SYS_SPL_MALLOC_SIZE) + * Size 64MB ...... MALLOC (size CONFIG_SPL_SYS_MALLOC_SIZE) * Size 1MB ...... BSS (size CONFIG_SPL_BSS_MAX_SIZE) * 0x8000_0000 ...... End of SDRAM_1 (assume 2GB) * diff --git a/include/system-constants.h b/include/system-constants.h index 0d6b71b35a0..f0a191be590 100644 --- a/include/system-constants.h +++ b/include/system-constants.h @@ -22,10 +22,10 @@ /* * Typically, we have the SPL malloc pool at the end of the BSS area. */ -#ifdef CONFIG_HAS_CUSTOM_SPL_MALLOC_START -#define SYS_SPL_MALLOC_START CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR +#ifdef CONFIG_SPL_HAS_CUSTOM_MALLOC_START +#define SPL_SYS_MALLOC_START CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR #else -#define SYS_SPL_MALLOC_START (CONFIG_SPL_BSS_START_ADDR + \ +#define SPL_SYS_MALLOC_START (CONFIG_SPL_BSS_START_ADDR + \ CONFIG_SPL_BSS_MAX_SIZE) #endif -- cgit v1.3.1 From 52779874dac3f096f9f7893f0b3603aeff4c646b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:18 -0600 Subject: spl: Avoid #ifdef with CONFIG_SPL_SYS_MALLOC Use IF_ENABLED_INT() to avoid needing to use the preprocessor. Signed-off-by: Simon Glass --- common/spl/spl.c | 8 ++++---- include/system-constants.h | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/common/spl/spl.c b/common/spl/spl.c index 0f453365516..a58b070d17e 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -750,10 +750,10 @@ void board_init_r(gd_t *dummy1, ulong dummy2) spl_set_bd(); -#if defined(CONFIG_SPL_SYS_MALLOC) - mem_malloc_init(SPL_SYS_MALLOC_START, CONFIG_SPL_SYS_MALLOC_SIZE); - gd->flags |= GD_FLG_FULL_MALLOC_INIT; -#endif + if (IS_ENABLED(CONFIG_SPL_SYS_MALLOC)) { + mem_malloc_init(SPL_SYS_MALLOC_START, SPL_SYS_MALLOC_SIZE); + gd->flags |= GD_FLG_FULL_MALLOC_INIT; + } if (!(gd->flags & GD_FLG_SPL_INIT)) { if (spl_init()) hang(); diff --git a/include/system-constants.h b/include/system-constants.h index f0a191be590..dca6a86b01f 100644 --- a/include/system-constants.h +++ b/include/system-constants.h @@ -24,9 +24,14 @@ */ #ifdef CONFIG_SPL_HAS_CUSTOM_MALLOC_START #define SPL_SYS_MALLOC_START CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR -#else +#elif defined(CONFIG_SPL_BSS_START_ADDR) #define SPL_SYS_MALLOC_START (CONFIG_SPL_BSS_START_ADDR + \ CONFIG_SPL_BSS_MAX_SIZE) +#else +/* feature not enabled: this value avoids compiler errors but is not used */ +#define SPL_SYS_MALLOC_START 0 #endif +#define SPL_SYS_MALLOC_SIZE \ + IF_ENABLED_INT(CONFIG_SPL_SYS_MALLOC, CONFIG_SPL_SYS_MALLOC_SIZE) #endif -- cgit v1.3.1 From 6371c47999ea78d00cf98028ced210bea8337711 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:20 -0600 Subject: spl: Drop #ifdefs for BOARD_INIT and watchdog Avoid using the preprocessor for these checks. Signed-off-by: Simon Glass --- common/spl/spl.c | 10 ++++------ include/spl.h | 8 ++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/common/spl/spl.c b/common/spl/spl.c index d930d2083de..530ade556ee 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -778,13 +778,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } } -#if CONFIG_IS_ENABLED(BOARD_INIT) - spl_board_init(); -#endif + if (CONFIG_IS_ENABLED(BOARD_INIT)) + spl_board_init(); -#if defined(CONFIG_SPL_WATCHDOG) && CONFIG_IS_ENABLED(WDT) - initr_watchdog(); -#endif + if (IS_ENABLED(CONFIG_SPL_WATCHDOG) && CONFIG_IS_ENABLED(WDT)) + initr_watchdog(); if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) || IS_ENABLED(CONFIG_SPL_ATF)) diff --git a/include/spl.h b/include/spl.h index 0fedddd00ef..ab06e32ebd9 100644 --- a/include/spl.h +++ b/include/spl.h @@ -707,9 +707,13 @@ int spl_early_init(void); */ int spl_init(void); -#ifdef CONFIG_SPL_BOARD_INIT +/* + * spl_board_init() - Do board-specific init in SPL + * + * If xPL_BOARD_INIT is enabled, this is called from board_init_r() before + * jumping to the next phase. + */ void spl_board_init(void); -#endif /** * spl_was_boot_source() - check if U-Boot booted from SPL -- cgit v1.3.1 From e0be6eaf581d06af788509e588129c4dbae967d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:21 -0600 Subject: spl: Avoid #ifdef with CONFIG_SPL_PAYLOAD_ARGS_ADDR Move the condition to the header file to improve readability. Signed-off-by: Simon Glass --- common/spl/spl.c | 10 ++++------ include/system-constants.h | 7 +++++++ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/common/spl/spl.c b/common/spl/spl.c index 530ade556ee..8ed2eeb5930 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -806,9 +806,8 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } memset(&spl_image, '\0', sizeof(spl_image)); -#ifdef CONFIG_SPL_PAYLOAD_ARGS_ADDR - spl_image.arg = (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR; -#endif + if (IS_ENABLED(CONFIG_SPL_OS_BOOT)) + spl_image.arg = (void *)SPL_PAYLOAD_ARGS_ADDR; spl_image.boot_device = BOOT_DEVICE_NONE; board_boot_order(spl_boot_list); @@ -865,9 +864,8 @@ void board_init_r(gd_t *dummy1, ulong dummy2) #if CONFIG_IS_ENABLED(OS_BOOT) case IH_OS_LINUX: debug("Jumping to Linux\n"); -#if defined(CONFIG_SPL_PAYLOAD_ARGS_ADDR) - spl_fixup_fdt((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR); -#endif + if (IS_ENABLED(CONFIG_SPL_OS_BOOT)) + spl_fixup_fdt((void *)SPL_PAYLOAD_ARGS_ADDR); spl_board_prepare_for_linux(); jump_to_image_linux(&spl_image); #endif diff --git a/include/system-constants.h b/include/system-constants.h index dca6a86b01f..59371568d1e 100644 --- a/include/system-constants.h +++ b/include/system-constants.h @@ -34,4 +34,11 @@ #define SPL_SYS_MALLOC_SIZE \ IF_ENABLED_INT(CONFIG_SPL_SYS_MALLOC, CONFIG_SPL_SYS_MALLOC_SIZE) +/* deal with an optional value */ +#ifdef CONFIG_SPL_OS_BOOT +#define SPL_PAYLOAD_ARGS_ADDR CONFIG_SPL_PAYLOAD_ARGS_ADDR +#else +#define SPL_PAYLOAD_ARGS_ADDR 0 +#endif + #endif -- cgit v1.3.1 From f817e08ff290c51f6471345d7bc11507cde8ffbc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:22 -0600 Subject: spl: Drop the switch() statement for OS selection This code is pretty ugly, with many #ifdefs There are quite a lot of IH_OS_U_BOOT values so the compiler struggles to create a jump table here. Also, most of the options are normally disabled. Change it to an else...if construct instead. Add an accessor for the spl_image field behind an #ifdef to avoid needing #ifdef in the C code. Signed-off-by: Simon Glass --- common/spl/spl.c | 32 ++++++++++---------------------- include/spl.h | 9 +++++++++ 2 files changed, 19 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/common/spl/spl.c b/common/spl/spl.c index 8ed2eeb5930..898ddfe0c78 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -744,7 +744,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) BOOT_DEVICE_NONE, }; struct spl_image_info spl_image; - int ret; + int ret, os; debug(">>" SPL_TPL_PROMPT "board_init_r()\n"); @@ -837,39 +837,27 @@ void board_init_r(gd_t *dummy1, ulong dummy2) ret); } - switch (spl_image.os) { - case IH_OS_U_BOOT: + os = spl_image.os; + if (os == IH_OS_U_BOOT) { debug("Jumping to %s...\n", spl_phase_name(spl_next_phase())); - break; -#if CONFIG_IS_ENABLED(ATF) - case IH_OS_ARM_TRUSTED_FIRMWARE: + } else if (CONFIG_IS_ENABLED(ATF) && os == IH_OS_ARM_TRUSTED_FIRMWARE) { debug("Jumping to U-Boot via ARM Trusted Firmware\n"); - spl_fixup_fdt(spl_image.fdt_addr); + spl_fixup_fdt(spl_image_fdt_addr(&spl_image)); spl_invoke_atf(&spl_image); - break; -#endif -#if CONFIG_IS_ENABLED(OPTEE_IMAGE) - case IH_OS_TEE: + } else if (CONFIG_IS_ENABLED(OPTEE_IMAGE) && os == IH_OS_TEE) { debug("Jumping to U-Boot via OP-TEE\n"); - spl_board_prepare_for_optee(spl_image.fdt_addr); + spl_board_prepare_for_optee(spl_image_fdt_addr(&spl_image)); jump_to_image_optee(&spl_image); - break; -#endif -#if CONFIG_IS_ENABLED(OPENSBI) - case IH_OS_OPENSBI: + } else if (CONFIG_IS_ENABLED(OPENSBI) && os == IH_OS_OPENSBI) { debug("Jumping to U-Boot via RISC-V OpenSBI\n"); spl_invoke_opensbi(&spl_image); - break; -#endif -#if CONFIG_IS_ENABLED(OS_BOOT) - case IH_OS_LINUX: + } else if (CONFIG_IS_ENABLED(OS_BOOT) && os == IH_OS_LINUX) { debug("Jumping to Linux\n"); if (IS_ENABLED(CONFIG_SPL_OS_BOOT)) spl_fixup_fdt((void *)SPL_PAYLOAD_ARGS_ADDR); spl_board_prepare_for_linux(); jump_to_image_linux(&spl_image); -#endif - default: + } else { debug("Unsupported OS image.. Jumping nevertheless..\n"); } #if CONFIG_VAL(SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_SYS_MALLOC_SIZE) diff --git a/include/spl.h b/include/spl.h index ab06e32ebd9..6c6ca07dbcc 100644 --- a/include/spl.h +++ b/include/spl.h @@ -263,6 +263,15 @@ struct spl_image_info { #endif }; +static inline void *spl_image_fdt_addr(struct spl_image_info *info) +{ +#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL) + return info->fdt_addr; +#else + return 0; +#endif +} + /** * Information required to load data from a device * -- cgit v1.3.1 From 3d6d50751469fbadec3e34fbb6d06f21746619dd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:27 -0600 Subject: spl: Use SYS_MALLOC_F instead of SYS_MALLOC_F_LEN Use the new SPL/TPL/VPL_SYS_MALLOC_F symbols to determine whether the malloc pool exists. Signed-off-by: Simon Glass Reviewed-by: Sean Anderson --- Kconfig | 9 ++++----- arch/arm/lib/bdinfo.c | 2 +- arch/mips/cpu/start.S | 4 ++-- arch/mips/mach-mtmips/mt7621/spl/start.S | 4 ++-- arch/powerpc/cpu/mpc83xx/start.S | 2 +- arch/powerpc/cpu/mpc85xx/start.S | 4 ++-- arch/sandbox/cpu/start.c | 2 +- arch/sh/lib/start.S | 4 ++-- common/Makefile | 6 +----- common/board_f.c | 2 +- common/board_r.c | 2 +- common/dlmalloc.c | 12 ++++++------ common/init/board_init.c | 4 ++-- common/spl/spl.c | 6 +++--- include/asm-generic/global_data.h | 2 +- lib/asm-offsets.c | 2 +- 16 files changed, 31 insertions(+), 36 deletions(-) (limited to 'include') diff --git a/Kconfig b/Kconfig index 927e2def085..068da61d845 100644 --- a/Kconfig +++ b/Kconfig @@ -307,8 +307,7 @@ config SPL_SYS_MALLOC_F config SPL_SYS_MALLOC_F_LEN hex "Size of malloc() pool in SPL" - depends on SYS_MALLOC_F && SPL - default 0x0 if !SPL_FRAMEWORK + depends on SPL_SYS_MALLOC_F default 0x2800 if RCAR_GEN3 default 0x2000 if IMX8MQ default SYS_MALLOC_F_LEN @@ -332,7 +331,7 @@ config TPL_SYS_MALLOC_F config TPL_SYS_MALLOC_F_LEN hex "Size of malloc() pool in TPL" - depends on SYS_MALLOC_F && TPL + depends on TPL_SYS_MALLOC_F default SPL_SYS_MALLOC_F_LEN help Sets the size of the malloc() pool in TPL. This is used for @@ -366,8 +365,8 @@ config VPL_SYS_MALLOC_F config VPL_SYS_MALLOC_F_LEN hex "Size of malloc() pool in VPL before relocation" - depends on SYS_MALLOC_F && VPL - default SYS_MALLOC_F_LEN + depends on VPL_SYS_MALLOC_F + default SPL_SYS_MALLOC_F_LEN help Sets the size of the malloc() pool in VPL. This is used for driver model and other features, which must allocate memory for diff --git a/arch/arm/lib/bdinfo.c b/arch/arm/lib/bdinfo.c index 5e6eaad968d..b88b01eefdc 100644 --- a/arch/arm/lib/bdinfo.c +++ b/arch/arm/lib/bdinfo.c @@ -57,7 +57,7 @@ void arch_print_bdinfo(void) #ifdef CONFIG_BOARD_TYPES printf("Board Type = %ld\n", gd->board_type); #endif -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) printf("Early malloc usage: %lx / %x\n", gd->malloc_ptr, CONFIG_VAL(SYS_MALLOC_F_LEN)); #endif diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 2acc21d5871..a95c95bc783 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -46,7 +46,7 @@ sp, sp, GD_SIZE # reserve space for gd and sp, sp, t0 # force 16 byte alignment move k0, sp # save gd pointer -#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) li t2, CONFIG_VAL(SYS_MALLOC_F_LEN) PTR_SUBU \ @@ -63,7 +63,7 @@ blt t0, t1, 1b nop -#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset #endif diff --git a/arch/mips/mach-mtmips/mt7621/spl/start.S b/arch/mips/mach-mtmips/mt7621/spl/start.S index d2f9c031cba..d56e624f313 100644 --- a/arch/mips/mach-mtmips/mt7621/spl/start.S +++ b/arch/mips/mach-mtmips/mt7621/spl/start.S @@ -37,7 +37,7 @@ sp, sp, GD_SIZE # reserve space for gd and sp, sp, t0 # force 16 byte alignment move k0, sp # save gd pointer -#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) li t2, CONFIG_VAL(SYS_MALLOC_F_LEN) PTR_SUBU \ @@ -54,7 +54,7 @@ blt t0, t1, 1b nop -#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset #endif diff --git a/arch/powerpc/cpu/mpc83xx/start.S b/arch/powerpc/cpu/mpc83xx/start.S index 6749263da8a..d72d3147f63 100644 --- a/arch/powerpc/cpu/mpc83xx/start.S +++ b/arch/powerpc/cpu/mpc83xx/start.S @@ -244,7 +244,7 @@ in_flash: cmplw r3, r4 bne 1b -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) #if CONFIG_VAL(SYS_MALLOC_F_LEN) + GENERATED_GBL_DATA_SIZE > CFG_SYS_INIT_RAM_SIZE #error "SYS_MALLOC_F_LEN too large to fit into initial RAM." diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S index 562b6993b9d..e9c30427734 100644 --- a/arch/powerpc/cpu/mpc85xx/start.S +++ b/arch/powerpc/cpu/mpc85xx/start.S @@ -1233,7 +1233,7 @@ _start_cont: lis r3,(CFG_SYS_INIT_RAM_ADDR)@h ori r3,r3,((CFG_SYS_INIT_SP_OFFSET-16)&~0xf)@l /* Align to 16 */ -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) #if CONFIG_VAL(SYS_MALLOC_F_LEN) + GENERATED_GBL_DATA_SIZE > CFG_SYS_INIT_RAM_SIZE #error "SYS_MALLOC_F_LEN too large to fit into initial RAM." #endif @@ -1253,7 +1253,7 @@ _start_cont: cmplw r4,r3 bne 1b -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) lis r4,SYS_INIT_SP_ADDR@h ori r4,r4,SYS_INIT_SP_ADDR@l diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 1026898727f..bbd9e77afed 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -529,7 +529,7 @@ int sandbox_main(int argc, char *argv[]) goto err; } -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) gd->malloc_base = CFG_MALLOC_F_ADDR; #endif #if CONFIG_IS_ENABLED(LOG) diff --git a/arch/sh/lib/start.S b/arch/sh/lib/start.S index ddb9aa9f87b..f0e1c805b01 100644 --- a/arch/sh/lib/start.S +++ b/arch/sh/lib/start.S @@ -53,7 +53,7 @@ _start: mov.l ._gd_init, r13 /* global data */ mov.l ._stack_init, r15 /* stack */ -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) mov.l ._gd_malloc_base, r14 mov.l r15, @r14 #endif @@ -73,7 +73,7 @@ loop: ._bss_start: .long bss_start ._bss_end: .long bss_end ._gd_init: .long (_start - GENERATED_GBL_DATA_SIZE) -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) ._gd_malloc_base: .long (_start - GENERATED_GBL_DATA_SIZE + GD_MALLOC_BASE) #endif ._stack_init: .long (_start - GENERATED_GBL_DATA_SIZE - CONFIG_SYS_MALLOC_LEN - 16) diff --git a/common/Makefile b/common/Makefile index 5c1617206f0..cdeadf72026 100644 --- a/common/Makefile +++ b/common/Makefile @@ -74,11 +74,7 @@ endif # CONFIG_SPL_BUILD obj-$(CONFIG_CROS_EC) += cros_ec.o obj-y += dlmalloc.o -ifdef CONFIG_SYS_MALLOC_F -ifneq ($(CONFIG_$(SPL_TPL_)SYS_MALLOC_F_LEN),0x0) -obj-y += malloc_simple.o -endif -endif +obj-$(CONFIG_$(SPL_TPL_)SYS_MALLOC_F) += malloc_simple.o obj-$(CONFIG_CYCLIC) += cyclic.o obj-$(CONFIG_$(SPL_TPL_)EVENT) += event.o diff --git a/common/board_f.c b/common/board_f.c index aef395b1354..99c2a43c196 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -794,7 +794,7 @@ static int initf_bootstage(void) static int initf_dm(void) { -#if defined(CONFIG_DM) && CONFIG_VAL(SYS_MALLOC_F_LEN) +#if defined(CONFIG_DM) && CONFIG_IS_ENABLED(SYS_MALLOC_F) int ret; bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f"); diff --git a/common/board_r.c b/common/board_r.c index e30963339cf..52786901be5 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -191,7 +191,7 @@ static int initr_malloc(void) { ulong start; -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) debug("Pre-reloc malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif diff --git a/common/dlmalloc.c b/common/dlmalloc.c index aa933bdf577..87a09d38fb3 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1291,7 +1291,7 @@ Void_t* mALLOc(bytes) size_t bytes; INTERNAL_SIZE_T nb; -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) return malloc_simple(bytes); #endif @@ -1572,7 +1572,7 @@ void fREe(mem) Void_t* mem; mchunkptr fwd; /* misc temp for linking */ int islr; /* track whether merging with last_remainder */ -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) /* free() is a no-op - all the memory will be freed on relocation */ if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) { VALGRIND_FREELIKE_BLOCK(mem, SIZE_SZ); @@ -1735,7 +1735,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; /* realloc of null is supposed to be same as malloc */ if (oldmem == NULL) return mALLOc(bytes); -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) { /* This is harder to support and should not be needed */ panic("pre-reloc realloc() is not supported"); @@ -1957,7 +1957,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; if ((long)bytes < 0) return NULL; -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) { return memalign_simple(alignment, bytes); } @@ -2153,7 +2153,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; return NULL; else { -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) { memset(mem, 0, sz); return mem; @@ -2455,7 +2455,7 @@ int mALLOPt(param_number, value) int param_number; int value; int initf_malloc(void) { -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) assert(gd->malloc_base); /* Set up by crt0.S */ gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN); gd->malloc_ptr = 0; diff --git a/common/init/board_init.c b/common/init/board_init.c index ab8c508ad83..ed2365daa35 100644 --- a/common/init/board_init.c +++ b/common/init/board_init.c @@ -79,7 +79,7 @@ ulong board_init_f_alloc_reserve(ulong top) { /* Reserve early malloc arena */ #ifndef CFG_MALLOC_F_ADDR -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) top -= CONFIG_VAL(SYS_MALLOC_F_LEN); #endif #endif @@ -159,7 +159,7 @@ void board_init_f_init_reserve(ulong base) * Use gd as it is now properly set for all architectures. */ -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) /* go down one 'early malloc arena' */ gd->malloc_base = base; #if CONFIG_IS_ENABLED(ZERO_MEM_BEFORE_USE) diff --git a/common/spl/spl.c b/common/spl/spl.c index 898ddfe0c78..9b0276cbdb5 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -523,7 +523,7 @@ static int spl_common_init(bool setup_malloc) { int ret; -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) if (setup_malloc) { #ifdef CFG_MALLOC_F_ADDR gd->malloc_base = CFG_MALLOC_F_ADDR; @@ -860,7 +860,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } else { debug("Unsupported OS image.. Jumping nevertheless..\n"); } -#if CONFIG_VAL(SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_SYS_MALLOC_SIZE) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && !defined(CONFIG_SPL_SYS_MALLOC_SIZE) debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif @@ -961,7 +961,7 @@ ulong spl_relocate_stack_gd(void) if (CONFIG_IS_ENABLED(SYS_REPORT_STACK_F_USAGE)) spl_relocate_stack_check(); -#if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_VAL(SYS_MALLOC_F_LEN) +#if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_IS_ENABLED(SYS_MALLOC_F) if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) { debug("SPL malloc() before relocation used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index c6d63b3657c..f8fc87f1e46 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -307,7 +307,7 @@ struct global_data { #if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA) unsigned long malloc_start; #endif -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) /** * @malloc_base: base address of early malloc() */ diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index 0808cd4b0c1..216d9716d0d 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -32,7 +32,7 @@ int main(void) DEFINE(GD_FLAGS, offsetof(struct global_data, flags)); -#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#if CONFIG_IS_ENABLED(SYS_MALLOC_F) DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base)); #endif -- cgit v1.3.1 From 2003a83cc8b3937cda09e712c75f50f579eed3fa Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:31 -0600 Subject: spl: Avoid an #ifdef when printing gd->malloc_ptr Use an accessor in the header file to avoid this. Signed-off-by: Simon Glass --- common/spl/spl.c | 9 +++++---- include/asm-generic/global_data.h | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/common/spl/spl.c b/common/spl/spl.c index 9b0276cbdb5..d676a0312af 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -860,10 +860,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } else { debug("Unsupported OS image.. Jumping nevertheless..\n"); } -#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && !defined(CONFIG_SPL_SYS_MALLOC_SIZE) - debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, - gd->malloc_ptr / 1024); -#endif + if (CONFIG_IS_ENABLED(SYS_MALLOC_F) && + !IS_ENABLED(CONFIG_SPL_SYS_MALLOC_SIZE)) + debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", + gd_malloc_ptr(), gd_malloc_ptr() / 1024); + bootstage_mark_name(get_bootstage_id(false), "end phase"); #ifdef CONFIG_BOOTSTAGE_STASH ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index f8fc87f1e46..937fb12516c 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -588,6 +588,12 @@ static_assert(sizeof(struct global_data) == GD_SIZE); #define gd_set_pci_ram_top(val) #endif +#if CONFIG_VAL(SYS_MALLOC_F_LEN) +#define gd_malloc_ptr() gd->malloc_ptr +#else +#define gd_malloc_ptr() 0L +#endif + /** * enum gd_flags - global data flags * -- cgit v1.3.1 From 17ba50106efe04ca5249ce33a8ef8374b584ee8d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:32 -0600 Subject: spl: Remove #ifdefs with BOOTSTAGE This feature has some helpers in its header file so that its functions resolve to nothing when the feature is disabled. Add a few more and use these to simplify the code. With this there are no more #ifdefs in board_init_r() Signed-off-by: Simon Glass --- common/bootstage.c | 14 ++++++++++++++ common/spl/spl.c | 15 +++------------ include/bootstage.h | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/common/bootstage.c b/common/bootstage.c index 326c40f1561..a68d883c684 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -502,6 +502,20 @@ int bootstage_unstash(const void *base, int size) return 0; } +int _bootstage_stash_default(void) +{ + return bootstage_stash(map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR, 0), + CONFIG_BOOTSTAGE_STASH_SIZE); +} + +int _bootstage_unstash_default(void) +{ + const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR, + CONFIG_BOOTSTAGE_STASH_SIZE); + + return bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE); +} + int bootstage_get_size(void) { struct bootstage_data *data = gd->bootstage; diff --git a/common/spl/spl.c b/common/spl/spl.c index d676a0312af..2239ee933b8 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -538,17 +538,11 @@ static int spl_common_init(bool setup_malloc) ret); return ret; } -#ifdef CONFIG_BOOTSTAGE_STASH if (!u_boot_first_phase()) { - const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR, - CONFIG_BOOTSTAGE_STASH_SIZE); - - ret = bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE); + ret = bootstage_unstash_default(); if (ret) - debug("%s: Failed to unstash bootstage: ret=%d\n", - __func__, ret); + log_debug("Failed to unstash bootstage: ret=%d\n", ret); } -#endif /* CONFIG_BOOTSTAGE_STASH */ bootstage_mark_name(get_bootstage_id(true), spl_phase_name(spl_phase())); #if CONFIG_IS_ENABLED(LOG) @@ -866,12 +860,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) gd_malloc_ptr(), gd_malloc_ptr() / 1024); bootstage_mark_name(get_bootstage_id(false), "end phase"); -#ifdef CONFIG_BOOTSTAGE_STASH - ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, - CONFIG_BOOTSTAGE_STASH_SIZE); + ret = bootstage_stash_default(); if (ret) debug("Failed to stash bootstage: err=%d\n", ret); -#endif if (IS_ENABLED(CONFIG_SPL_VIDEO_REMOVE)) { struct udevice *dev; diff --git a/include/bootstage.h b/include/bootstage.h index 685939ccffc..f9376c320c9 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -244,6 +244,8 @@ void show_boot_progress(int val); #ifdef ENABLE_BOOTSTAGE +#include + /* This is the full bootstage implementation */ /** @@ -452,6 +454,26 @@ static inline int bootstage_init(bool first) #endif /* ENABLE_BOOTSTAGE */ +/* helpers for SPL */ +int _bootstage_stash_default(void); +int _bootstage_unstash_default(void); + +static inline int bootstage_stash_default(void) +{ + if (CONFIG_IS_ENABLED(BOOTSTAGE) && IS_ENABLED(CONFIG_BOOTSTAGE_STASH)) + return _bootstage_stash_default(); + + return 0; +} + +static inline int bootstage_unstash_default(void) +{ + if (CONFIG_IS_ENABLED(BOOTSTAGE) && IS_ENABLED(CONFIG_BOOTSTAGE_STASH)) + return _bootstage_unstash_default(); + + return 0; +} + /* Helper macro for adding a bootstage to a line of code */ #define BOOTSTAGE_MARKER() \ bootstage_mark_code(__FILE__, __func__, __LINE__) -- cgit v1.3.1 From 035ab46e3930c8142cae881e08923043632faa51 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:34 -0600 Subject: spl: Move the full FIT code to spl_fit.c For some reason this code was put in the main spl.c file. Move it out to the FIT implementation where it belongs. Signed-off-by: Simon Glass --- common/spl/spl.c | 108 ++++----------------------------------------------- common/spl/spl_fit.c | 93 ++++++++++++++++++++++++++++++++++++++++++++ include/spl.h | 11 ++++++ 3 files changed, 111 insertions(+), 101 deletions(-) (limited to 'include') diff --git a/common/spl/spl.c b/common/spl/spl.c index 2239ee933b8..9f605b32407 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -256,102 +256,6 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) } #endif -#if CONFIG_IS_ENABLED(LOAD_FIT_FULL) -/* Parse and load full fitImage in SPL */ -static int spl_load_fit_image(struct spl_image_info *spl_image, - const struct legacy_img_hdr *header) -{ - struct bootm_headers images; - const char *fit_uname_config = NULL; - uintptr_t fdt_hack; - const char *uname; - ulong fw_data = 0, dt_data = 0, img_data = 0; - ulong fw_len = 0, dt_len = 0, img_len = 0; - int idx, conf_noffset; - int ret; - -#ifdef CONFIG_SPL_FIT_SIGNATURE - images.verify = 1; -#endif - ret = fit_image_load(&images, (ulong)header, - NULL, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, - FIT_LOAD_OPTIONAL, &fw_data, &fw_len); - if (ret >= 0) { - printf("DEPRECATED: 'standalone = ' property."); - printf("Please use either 'firmware =' or 'kernel ='\n"); - } else { - ret = fit_image_load(&images, (ulong)header, NULL, - &fit_uname_config, IH_ARCH_DEFAULT, - IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL, - &fw_data, &fw_len); - } - - if (ret < 0) { - ret = fit_image_load(&images, (ulong)header, NULL, - &fit_uname_config, IH_ARCH_DEFAULT, - IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL, - &fw_data, &fw_len); - } - - if (ret < 0) - return ret; - - spl_image->size = fw_len; - spl_image->entry_point = fw_data; - spl_image->load_addr = fw_data; - if (fit_image_get_os(header, ret, &spl_image->os)) - spl_image->os = IH_OS_INVALID; - spl_image->name = genimg_get_os_name(spl_image->os); - - debug(SPL_TPL_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n", - spl_image->name, spl_image->load_addr, spl_image->size); - -#ifdef CONFIG_SPL_FIT_SIGNATURE - images.verify = 1; -#endif - ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, - FIT_LOAD_OPTIONAL, &dt_data, &dt_len); - if (ret >= 0) { - spl_image->fdt_addr = (void *)dt_data; - - if (spl_image->os == IH_OS_U_BOOT) { - /* HACK: U-Boot expects FDT at a specific address */ - fdt_hack = spl_image->load_addr + spl_image->size; - fdt_hack = (fdt_hack + 3) & ~3; - debug("Relocating FDT to %p\n", spl_image->fdt_addr); - memcpy((void *)fdt_hack, spl_image->fdt_addr, dt_len); - } - } - - conf_noffset = fit_conf_get_node((const void *)header, - fit_uname_config); - if (conf_noffset < 0) - return 0; - - for (idx = 0; - uname = fdt_stringlist_get((const void *)header, conf_noffset, - FIT_LOADABLE_PROP, idx, - NULL), uname; - idx++) - { -#ifdef CONFIG_SPL_FIT_SIGNATURE - images.verify = 1; -#endif - ret = fit_image_load(&images, (ulong)header, - &uname, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1, - FIT_LOAD_OPTIONAL_NON_ZERO, - &img_data, &img_len); - if (ret < 0) - return ret; - } - - return 0; -} -#endif - __weak int spl_parse_board_header(struct spl_image_info *spl_image, const struct spl_boot_device *bootdev, const void *image_header, size_t size) @@ -371,12 +275,14 @@ int spl_parse_image_header(struct spl_image_info *spl_image, const struct spl_boot_device *bootdev, const struct legacy_img_hdr *header) { -#if CONFIG_IS_ENABLED(LOAD_FIT_FULL) - int ret = spl_load_fit_image(spl_image, header); + int ret; - if (!ret) - return ret; -#endif + if (CONFIG_IS_ENABLED(LOAD_FIT_FULL)) { + ret = spl_load_fit_image(spl_image, header); + + if (!ret) + return ret; + } if (image_get_magic(header) == IH_MAGIC) { int ret; diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 822d0ce0e44..9373a562b26 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -827,3 +827,96 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, return 0; } + +/* Parse and load full fitImage in SPL */ +int spl_load_fit_image(struct spl_image_info *spl_image, + const struct legacy_img_hdr *header) +{ + struct bootm_headers images; + const char *fit_uname_config = NULL; + uintptr_t fdt_hack; + const char *uname; + ulong fw_data = 0, dt_data = 0, img_data = 0; + ulong fw_len = 0, dt_len = 0, img_len = 0; + int idx, conf_noffset; + int ret; + +#ifdef CONFIG_SPL_FIT_SIGNATURE + images.verify = 1; +#endif + ret = fit_image_load(&images, (ulong)header, + NULL, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, + FIT_LOAD_OPTIONAL, &fw_data, &fw_len); + if (ret >= 0) { + printf("DEPRECATED: 'standalone = ' property."); + printf("Please use either 'firmware =' or 'kernel ='\n"); + } else { + ret = fit_image_load(&images, (ulong)header, NULL, + &fit_uname_config, IH_ARCH_DEFAULT, + IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL, + &fw_data, &fw_len); + } + + if (ret < 0) { + ret = fit_image_load(&images, (ulong)header, NULL, + &fit_uname_config, IH_ARCH_DEFAULT, + IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL, + &fw_data, &fw_len); + } + + if (ret < 0) + return ret; + + spl_image->size = fw_len; + spl_image->entry_point = fw_data; + spl_image->load_addr = fw_data; + if (fit_image_get_os(header, ret, &spl_image->os)) + spl_image->os = IH_OS_INVALID; + spl_image->name = genimg_get_os_name(spl_image->os); + + debug(SPL_TPL_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n", + spl_image->name, spl_image->load_addr, spl_image->size); + +#ifdef CONFIG_SPL_FIT_SIGNATURE + images.verify = 1; +#endif + ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, + FIT_LOAD_OPTIONAL, &dt_data, &dt_len); + if (ret >= 0) { + spl_image->fdt_addr = (void *)dt_data; + + if (spl_image->os == IH_OS_U_BOOT) { + /* HACK: U-Boot expects FDT at a specific address */ + fdt_hack = spl_image->load_addr + spl_image->size; + fdt_hack = (fdt_hack + 3) & ~3; + debug("Relocating FDT to %p\n", spl_image->fdt_addr); + memcpy((void *)fdt_hack, spl_image->fdt_addr, dt_len); + } + } + + conf_noffset = fit_conf_get_node((const void *)header, + fit_uname_config); + if (conf_noffset < 0) + return 0; + + for (idx = 0; + uname = fdt_stringlist_get((const void *)header, conf_noffset, + FIT_LOADABLE_PROP, idx, + NULL), uname; + idx++) { +#ifdef CONFIG_SPL_FIT_SIGNATURE + images.verify = 1; +#endif + ret = fit_image_load(&images, (ulong)header, + &uname, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1, + FIT_LOAD_OPTIONAL_NON_ZERO, + &img_data, &img_len); + if (ret < 0) + return ret; + } + + return 0; +} diff --git a/include/spl.h b/include/spl.h index 6c6ca07dbcc..59c508280bc 100644 --- a/include/spl.h +++ b/include/spl.h @@ -910,4 +910,15 @@ struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size); void board_boot_order(u32 *spl_boot_list); void spl_save_restore_data(void); + +/** + * spl_load_fit_image() - Fully parse and a FIT image in SPL + * + * @spl_image: SPL Image data to fill in + * @header: Pointer to FIT image + * Return 0 if OK, -ve on error + */ +int spl_load_fit_image(struct spl_image_info *spl_image, + const struct legacy_img_hdr *header); + #endif -- cgit v1.3.1 From 247970978d3de3e46537550e83137df586d9dee9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:37 -0600 Subject: dm: core: Reverse the argument order in ofnode_copy_props() Follow the order used by memcpy() as it may be less confusing. Signed-off-by: Simon Glass --- boot/vbe_request.c | 2 +- boot/vbe_simple_os.c | 2 +- drivers/core/ofnode.c | 2 +- include/dm/ofnode.h | 6 +++--- test/dm/ofnode.c | 9 ++++----- 5 files changed, 10 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/boot/vbe_request.c b/boot/vbe_request.c index 2f218d4bf97..917251afa1c 100644 --- a/boot/vbe_request.c +++ b/boot/vbe_request.c @@ -187,7 +187,7 @@ static int bootmeth_vbe_ft_fixup(void *ctx, struct event *event) ret = ofnode_add_subnode(dest_parent, name, &dest); if (ret && ret != -EEXIST) return log_msg_ret("add", ret); - ret = ofnode_copy_props(node, dest); + ret = ofnode_copy_props(dest, node); if (ret) return log_msg_ret("cp", ret); diff --git a/boot/vbe_simple_os.c b/boot/vbe_simple_os.c index 3285e438a56..84626cdeaf2 100644 --- a/boot/vbe_simple_os.c +++ b/boot/vbe_simple_os.c @@ -94,7 +94,7 @@ static int bootmeth_vbe_simple_ft_fixup(void *ctx, struct event *event) /* Copy over the vbe properties for fwupd */ log_debug("Fixing up: %s\n", dev->name); - ret = ofnode_copy_props(dev_ofnode(dev), subnode); + ret = ofnode_copy_props(subnode, dev_ofnode(dev)); if (ret) return log_msg_ret("cp", ret); diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 2cafa7bca5b..515396c62f4 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1731,7 +1731,7 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) return ret; /* 0 or -EEXIST */ } -int ofnode_copy_props(ofnode src, ofnode dst) +int ofnode_copy_props(ofnode dst, ofnode src) { struct ofprop prop; diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 06c969c61fe..32917f66155 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1598,7 +1598,7 @@ int ofnode_add_subnode(ofnode parent, const char *name, ofnode *nodep); /** * ofnode_copy_props() - copy all properties from one node to another * - * Makes a copy of all properties from the source note in the destination node. + * Makes a copy of all properties from the source node to the destination node. * Existing properties in the destination node remain unchanged, except that * any with the same name are overwritten, including changing the size of the * property. @@ -1606,9 +1606,9 @@ int ofnode_add_subnode(ofnode parent, const char *name, ofnode *nodep); * For livetree, properties are copied / allocated, so the source tree does not * need to be present afterwards. * + * @dst: Destination node to write properties to * @src: Source node to read properties from - * @dst: Destination node to write properties too */ -int ofnode_copy_props(ofnode src, ofnode dst); +int ofnode_copy_props(ofnode dst, ofnode src); #endif diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index d71faac0ee4..dee71ee5e54 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1209,12 +1209,11 @@ static int dm_test_ofnode_too_many(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_too_many, UT_TESTF_SCAN_FDT); -static int check_copy_props(struct unit_test_state *uts, ofnode src, - ofnode dst) +static int check_copy_props(struct unit_test_state *uts, ofnode dst, ofnode src) { u32 reg[2], val; - ut_assertok(ofnode_copy_props(src, dst)); + ut_assertok(ofnode_copy_props(dst, src)); ut_assertok(ofnode_read_u32(dst, "ping-expect", &val)); ut_asserteq(3, val); @@ -1246,7 +1245,7 @@ static int dm_test_ofnode_copy_props(struct unit_test_state *uts) src = ofnode_path("/b-test"); dst = ofnode_path("/some-bus"); - ut_assertok(check_copy_props(uts, src, dst)); + ut_assertok(check_copy_props(uts, dst, src)); /* check a property that is in the destination already */ ut_asserteq_str("mux0", ofnode_read_string(dst, "mux-control-names")); @@ -1262,7 +1261,7 @@ static int dm_test_ofnode_copy_props_ot(struct unit_test_state *uts) src = ofnode_path("/b-test"); dst = oftree_path(otree, "/node/subnode2"); - ut_assertok(check_copy_props(uts, src, dst)); + ut_assertok(check_copy_props(uts, dst, src)); return 0; } -- cgit v1.3.1 From e0c3c21d8ba1a0abbb7effee6c5a952f3e65a03d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:40 -0600 Subject: dm: core: Add a function to create an empty tree Provide a function to create a new, empty tree. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++---- include/dm/ofnode.h | 9 +++++++++ include/of_live.h | 8 ++++++++ lib/of_live.c | 19 +++++++++++++++++ test/dm/ofnode.c | 16 +++++++++++++++ 5 files changed, 104 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 515396c62f4..d2bdb8b9af1 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -47,6 +47,17 @@ static int oftree_find(const void *fdt) return -1; } +static int check_tree_count(void) +{ + if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) { + log_warning("Too many registered device trees (max %d)\n", + CONFIG_OFNODE_MULTI_TREE_MAX); + return -E2BIG; + } + + return 0; +} + static oftree oftree_ensure(void *fdt) { oftree tree; @@ -69,11 +80,8 @@ static oftree oftree_ensure(void *fdt) if (gd->flags & GD_FLG_RELOC) { i = oftree_find(fdt); if (i == -1) { - if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) { - log_warning("Too many registered device trees (max %d)\n", - CONFIG_OFNODE_MULTI_TREE_MAX); + if (check_tree_count()) return oftree_null(); - } /* register the new tree */ i = oftree_count++; @@ -92,6 +100,41 @@ static oftree oftree_ensure(void *fdt) return tree; } +int oftree_new(oftree *treep) +{ + oftree tree = oftree_null(); + int ret; + + if (of_live_active()) { + struct device_node *root; + + ret = of_live_create_empty(&root); + if (ret) + return log_msg_ret("liv", ret); + tree = oftree_from_np(root); + } else { + const int size = 1024; + void *fdt; + + ret = check_tree_count(); + if (ret) + return log_msg_ret("fla", ret); + + /* register the new tree with a small size */ + fdt = malloc(size); + if (!fdt) + return log_msg_ret("fla", -ENOMEM); + ret = fdt_create_empty_tree(fdt, size); + if (ret) + return log_msg_ret("fla", -EINVAL); + oftree_list[oftree_count++] = fdt; + tree.fdt = fdt; + } + *treep = tree; + + return 0; +} + void oftree_dispose(oftree tree) { if (of_live_active()) @@ -193,6 +236,11 @@ static inline int oftree_find(const void *fdt) return 0; } +int oftree_new(oftree *treep) +{ + return -ENOSYS; +} + #endif /* OFNODE_MULTI_TREE */ /** diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 32917f66155..0b96ab34ede 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -127,6 +127,15 @@ static inline ofnode noffset_to_ofnode(ofnode other_node, int of_offset) #endif /* OFNODE_MULTI_TREE */ +/** + * oftree_new() - Create a new, empty tree + * + * @treep: Returns a pointer to the tree, on success + * Returns: 0 on success, -ENOMEM if out of memory, -E2BIG if !OF_LIVE and + * there are too many (flattrees) already + */ +int oftree_new(oftree *treep); + /** * ofnode_to_np() - convert an ofnode to a live DT node pointer * diff --git a/include/of_live.h b/include/of_live.h index 05e86ac06b1..81cb9bd13e2 100644 --- a/include/of_live.h +++ b/include/of_live.h @@ -46,4 +46,12 @@ int unflatten_device_tree(const void *blob, struct device_node **mynodes); */ void of_live_free(struct device_node *root); +/** + * of_live_create_empty() - Create a new, empty tree + * + * @rootp: Returns the root node of the created tree + * Return: 0 if OK, -ENOMEM if out of memory + */ +int of_live_create_empty(struct device_node **rootp); + #endif diff --git a/lib/of_live.c b/lib/of_live.c index 25f7af61061..e4eee385547 100644 --- a/lib/of_live.c +++ b/lib/of_live.c @@ -336,3 +336,22 @@ void of_live_free(struct device_node *root) /* the tree is stored as a contiguous block of memory */ free(root); } + +int of_live_create_empty(struct device_node **rootp) +{ + struct device_node *root; + + root = calloc(1, sizeof(struct device_node)); + if (!root) + return -ENOMEM; + root->name = strdup(""); + if (!root->name) { + free(root); + return -ENOMEM; + } + root->type = ""; + root->full_name = ""; + *rootp = root; + + return 0; +} diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 3bf97761d1e..594116e3c04 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1346,3 +1346,19 @@ static int dm_test_livetree_ensure(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_livetree_ensure, UT_TESTF_SCAN_FDT); + +static int dm_test_oftree_new(struct unit_test_state *uts) +{ + ofnode node, subnode, check; + oftree tree; + + ut_assertok(oftree_new(&tree)); + node = oftree_root(tree); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_add_subnode(node, "edmund", &subnode)); + check = ofnode_find_subnode(node, "edmund"); + ut_asserteq(check.of_offset, subnode.of_offset); + + return 0; +} +DM_TEST(dm_test_oftree_new, UT_TESTF_SCAN_FDT); -- cgit v1.3.1 From c15862ffdd5f7797338808cf7645786109bcddc3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:41 -0600 Subject: dm: core: Add a way to copy a node Add a function to copy a node to another place under a new name. This is useful at least for testing, since copying a test node with existing properties is easier than writing the code to generate it all afresh. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 20 ++++++++++++++++ include/dm/ofnode.h | 15 ++++++++++++ test/dm/ofnode.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) (limited to 'include') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index d2bdb8b9af1..403ee06ad94 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1802,3 +1802,23 @@ int ofnode_copy_props(ofnode dst, ofnode src) return 0; } + +int ofnode_copy_node(ofnode dst_parent, const char *name, ofnode src, + ofnode *nodep) +{ + ofnode node; + int ret; + + ret = ofnode_add_subnode(dst_parent, name, &node); + if (ret) { + if (ret == -EEXIST) + *nodep = node; + return log_msg_ret("add", ret); + } + ret = ofnode_copy_props(node, src); + if (ret) + return log_msg_ret("cpy", ret); + *nodep = node; + + return 0; +} diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 0b96ab34ede..7eb04accd62 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1620,4 +1620,19 @@ int ofnode_add_subnode(ofnode parent, const char *name, ofnode *nodep); */ int ofnode_copy_props(ofnode dst, ofnode src); +/** + * ofnode_copy_node() - Copy a node to another place + * + * If a node with this name already exists in dst_parent, this returns an + * .error + * + * @dst_parent: Parent of the newly copied node + * @name: Name to give the new node + * @src: Source node to copy + * @nodep: Returns the new node, or the existing node if there is one + * Return: 0 if OK, -EEXIST if dst_parent already has a node with this parent + */ +int ofnode_copy_node(ofnode dst_parent, const char *name, ofnode src, + ofnode *nodep); + #endif diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 594116e3c04..5459a9afbb9 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1362,3 +1362,66 @@ static int dm_test_oftree_new(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_oftree_new, UT_TESTF_SCAN_FDT); + +static int check_copy_node(struct unit_test_state *uts, ofnode dst, ofnode src, + ofnode *nodep) +{ + u32 reg[2], val; + ofnode node; + + ut_assertok(ofnode_copy_node(dst, "copy-test", src, &node)); + + ut_assertok(ofnode_read_u32(node, "ping-expect", &val)); + ut_asserteq(3, val); + + ut_asserteq_str("denx,u-boot-fdt-test", + ofnode_read_string(node, "compatible")); + + /* check that a property with the same name is overwritten */ + ut_assertok(ofnode_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg))); + ut_asserteq(3, reg[0]); + ut_asserteq(1, reg[1]); + + /* reset the compatible so the live tree does not change */ + ut_assertok(ofnode_write_string(node, "compatible", "nothing")); + *nodep = node; + + return 0; +} + +static int dm_test_ofnode_copy_node(struct unit_test_state *uts) +{ + ofnode src, dst, node, try; + + /* + * These nodes are chosen so that the src node is before the destination + * node in the tree. This doesn't matter with livetree, but with + * flattree any attempt to insert a property earlier in the tree will + * mess up the offsets after it. + */ + src = ofnode_path("/b-test"); + dst = ofnode_path("/some-bus"); + + ut_assertok(check_copy_node(uts, dst, src, &node)); + + /* check trying to copy over an existing node */ + ut_asserteq(-EEXIST, ofnode_copy_node(dst, "copy-test", src, &try)); + ut_asserteq(try.of_offset, node.of_offset); + + return 0; +} +DM_TEST(dm_test_ofnode_copy_node, UT_TESTF_SCAN_FDT); + +/* test ofnode_copy_node() with the 'other' tree */ +static int dm_test_ofnode_copy_node_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + ofnode src, dst, node; + + src = ofnode_path("/b-test"); + dst = oftree_path(otree, "/node/subnode2"); + ut_assertok(check_copy_node(uts, dst, src, &node)); + + return 0; +} +DM_TEST(dm_test_ofnode_copy_node_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT); -- cgit v1.3.1 From 67fb2159fb3438359fa0fc3f8cb491ffe8d57c0f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:42 -0600 Subject: dm: core: Add a way to delete a node Add a function to delete a node in an existing tree. Signed-off-by: Simon Glass --- drivers/core/of_access.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/core/ofnode.c | 23 +++++++++++++++++ include/dm/of_access.h | 18 ++++++++++++++ include/dm/ofnode.h | 13 ++++++++++ test/dm/ofnode.c | 31 +++++++++++++++++++++++ 5 files changed, 150 insertions(+) (limited to 'include') diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index 1bb4d8eab70..c8db743f529 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -1040,3 +1040,68 @@ int of_add_subnode(struct device_node *parent, const char *name, int len, return 0; } + +int __of_remove_property(struct device_node *np, struct property *prop) +{ + struct property **next; + + for (next = &np->properties; *next; next = &(*next)->next) { + if (*next == prop) + break; + } + if (!*next) + return -ENODEV; + + /* found the node */ + *next = prop->next; + + return 0; +} + +int of_remove_property(struct device_node *np, struct property *prop) +{ + int rc; + + mutex_lock(&of_mutex); + + rc = __of_remove_property(np, prop); + + mutex_unlock(&of_mutex); + + return rc; +} + +int of_remove_node(struct device_node *to_remove) +{ + struct device_node *parent = to_remove->parent; + struct device_node *np, *prev; + + if (!parent) + return -EPERM; + prev = NULL; + __for_each_child_of_node(parent, np) { + if (np == to_remove) + break; + prev = np; + } + if (!np) + return -EFAULT; + + /* if there is a previous node, link it to this one's sibling */ + if (prev) + prev->sibling = np->sibling; + else + parent->child = np->sibling; + + /* + * don't free it, since if this is an unflattened tree, all the memory + * was alloced in one block; this pointer will be somewhere in the + * middle of that + * + * TODO(sjg@chromium.org): Consider marking nodes as 'allocated'? + * + * free(np); + */ + + return 0; +} diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 403ee06ad94..a5efedf6af3 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1779,6 +1779,29 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) return ret; /* 0 or -EEXIST */ } +int ofnode_delete(ofnode *nodep) +{ + ofnode node = *nodep; + int ret; + + assert(ofnode_valid(node)); + if (ofnode_is_np(node)) { + ret = of_remove_node(ofnode_to_np(node)); + } else { + void *fdt = ofnode_to_fdt(node); + int offset = ofnode_to_offset(node); + + ret = fdt_del_node(fdt, offset); + if (ret) + ret = -EFAULT; + } + if (ret) + return ret; + *nodep = ofnode_null(); + + return 0; +} + int ofnode_copy_props(ofnode dst, ofnode src) { struct ofprop prop; diff --git a/include/dm/of_access.h b/include/dm/of_access.h index 9361d0a87bf..de740d44674 100644 --- a/include/dm/of_access.h +++ b/include/dm/of_access.h @@ -597,4 +597,22 @@ int of_write_prop(struct device_node *np, const char *propname, int len, int of_add_subnode(struct device_node *node, const char *name, int len, struct device_node **subnodep); +/** + * of_remove_property() - Remove a property from a node + * + * @np: Node to remove from + * @prop: Pointer to property to remove + * Return 0 if OK, -ENODEV if the property could not be found in the node + */ +int of_remove_property(struct device_node *np, struct property *prop); + +/** + * of_remove_node() - Remove a node from the tree + * + * @to_remove: Node to remove + * Return: 0 if OK, -EPERM if it is the root node (wWhich cannot be removed), + * -ENOENT if the tree is broken (to_remove is not a child of its parent) + */ +int of_remove_node(struct device_node *to_remove); + #endif diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 7eb04accd62..f1ee02cd837 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1635,4 +1635,17 @@ int ofnode_copy_props(ofnode dst, ofnode src); int ofnode_copy_node(ofnode dst_parent, const char *name, ofnode src, ofnode *nodep); +/** + * ofnode_delete() - Delete a node + * + * Delete a node from the tree + * + * @nodep: Pointer to node to delete (set to ofnode_null() on success) + * Return: 0 if OK, -ENOENT if the node does not exist, -EPERM if it is the root + * node (wWhich cannot be removed), -EFAULT if the tree is broken (to_remove is + * not a child of its parent), + * + */ +int ofnode_delete(ofnode *nodep); + #endif diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 5459a9afbb9..845cded449a 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1425,3 +1425,34 @@ static int dm_test_ofnode_copy_node_ot(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_ofnode_copy_node_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT); + +static int dm_test_ofnode_delete(struct unit_test_state *uts) +{ + ofnode node; + + /* + * At present the livetree is not restored after changes made in tests. + * See test_pre_run() for how this is done with the other FDT and + * dm_test_pre_run() where it sets up the root-tree pointer. So use + * nodes which don't matter to other tests. + * + * We could fix this by detecting livetree changes and regenerating it + * before the next test if needed. + */ + node = ofnode_path("/leds/iracibble"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_delete(&node)); + ut_assert(!ofnode_valid(node)); + ut_assert(!ofnode_valid(ofnode_path("/leds/iracibble"))); + + node = ofnode_path("/leds/default_on"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_delete(&node)); + ut_assert(!ofnode_valid(node)); + ut_assert(!ofnode_valid(ofnode_path("/leds/default_on"))); + + ut_asserteq(2, ofnode_get_child_count(ofnode_path("/leds"))); + + return 0; +} +DM_TEST(dm_test_ofnode_delete, UT_TESTF_SCAN_FDT); -- cgit v1.3.1 From 62b1db33778611a3023d1e3a98e869b495edc9ca Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:43 -0600 Subject: dm: core: Add a way to convert a devicetree to a dtb Add a way to flatten a devicetree into binary form. For livetree this involves generating the devicetree using fdt_property() and other calls. For flattree it simply involves providing the buffer containing the tree. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 18 ++++++++ include/dm/ofnode.h | 13 ++++++ include/of_live.h | 10 +++++ lib/of_live.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/dm/ofnode.c | 24 ++++++++++ 5 files changed, 187 insertions(+) (limited to 'include') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index a5efedf6af3..39ba480c8f8 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -243,6 +243,24 @@ int oftree_new(oftree *treep) #endif /* OFNODE_MULTI_TREE */ +int oftree_to_fdt(oftree tree, struct abuf *buf) +{ + int ret; + + if (of_live_active()) { + ret = of_live_flatten(ofnode_to_np(oftree_root(tree)), buf); + if (ret) + return log_msg_ret("flt", ret); + } else { + void *fdt = oftree_lookup_fdt(tree); + + abuf_init(buf); + abuf_set(buf, fdt, fdt_totalsize(fdt)); + } + + return 0; +} + /** * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree) * diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index f1ee02cd837..a8605fb718b 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -17,6 +17,7 @@ /* Enable checks to protect against invalid calls */ #undef OF_CHECKS +struct abuf; struct resource; #include @@ -136,6 +137,18 @@ static inline ofnode noffset_to_ofnode(ofnode other_node, int of_offset) */ int oftree_new(oftree *treep); +/** + * oftree_to_fdt() - Convert an oftree to a flat FDT + * + * @tree: tree to flatten (if livetree) or copy (if not) + * @buf: Returns inited buffer containing the newly created flat tree. Note + * that for flat tree the buffer is not allocated. In either case the caller + * must call abut_uninit() to free any memory used by @buf + * Return: 0 on success, -ENOMEM if out of memory, other -ve value for any other + * error + */ +int oftree_to_fdt(oftree tree, struct abuf *buf); + /** * ofnode_to_np() - convert an ofnode to a live DT node pointer * diff --git a/include/of_live.h b/include/of_live.h index 81cb9bd13e2..67bd5f02c74 100644 --- a/include/of_live.h +++ b/include/of_live.h @@ -9,6 +9,7 @@ #ifndef _OF_LIVE_H #define _OF_LIVE_H +struct abuf; struct device_node; /** @@ -54,4 +55,13 @@ void of_live_free(struct device_node *root); */ int of_live_create_empty(struct device_node **rootp); +/** + * of_live_flatten() - Create an FDT from a hierarchical tree + * + * @root: Root node of tree to convert + * @buf: Buffer to return the tree (inited by this function) + * Return: 0 if OK, -ENOMEM if out of memory + */ +int of_live_flatten(const struct device_node *root, struct abuf *buf); + #endif diff --git a/lib/of_live.c b/lib/of_live.c index e4eee385547..812c488f606 100644 --- a/lib/of_live.c +++ b/lib/of_live.c @@ -8,13 +8,21 @@ * Copyright (c) 2017 Google, Inc */ +#define LOG_CATEGORY LOGC_DT + #include +#include #include #include #include #include #include #include +#include + +enum { + BUF_STEP = SZ_64K, +}; static void *unflatten_dt_alloc(void **mem, unsigned long size, unsigned long align) @@ -355,3 +363,117 @@ int of_live_create_empty(struct device_node **rootp) return 0; } + +static int check_space(int ret, struct abuf *buf) +{ + if (ret == -FDT_ERR_NOSPACE) { + if (!abuf_realloc_inc(buf, BUF_STEP)) + return log_msg_ret("spc", -ENOMEM); + ret = fdt_resize(abuf_data(buf), abuf_data(buf), + abuf_size(buf)); + if (ret) + return log_msg_ret("res", -EFAULT); + + return -EAGAIN; + } + + return 0; +} + +/** + * flatten_node() - Write out the node and its properties into a flat tree + */ +static int flatten_node(struct abuf *buf, const struct device_node *node) +{ + const struct device_node *np; + const struct property *pp; + int ret; + + ret = fdt_begin_node(abuf_data(buf), node->name); + ret = check_space(ret, buf); + if (ret == -EAGAIN) { + ret = fdt_begin_node(abuf_data(buf), node->name); + if (ret) { + log_debug("Internal error a %d\n", ret); + return -EFAULT; + } + } + if (ret) + return log_msg_ret("beg", ret); + + /* First write out the properties */ + for (pp = node->properties; !ret && pp; pp = pp->next) { + ret = fdt_property(abuf_data(buf), pp->name, pp->value, + pp->length); + ret = check_space(ret, buf); + if (ret == -EAGAIN) { + ret = fdt_property(abuf_data(buf), pp->name, pp->value, + pp->length); + } + } + + /* Next write out the subnodes */ + for (np = node->child; np; np = np->sibling) { + ret = flatten_node(buf, np); + if (ret) + return log_msg_ret("sub", ret); + } + + ret = fdt_end_node(abuf_data(buf)); + ret = check_space(ret, buf); + if (ret == -EAGAIN) { + ret = fdt_end_node(abuf_data(buf)); + if (ret) { + log_debug("Internal error b %d\n", ret); + return -EFAULT; + } + } + if (ret) + return log_msg_ret("end", ret); + + return 0; +} + +int of_live_flatten(const struct device_node *root, struct abuf *buf) +{ + int ret; + + abuf_init(buf); + if (!abuf_realloc(buf, BUF_STEP)) + return log_msg_ret("ini", -ENOMEM); + + ret = fdt_create(abuf_data(buf), abuf_size(buf)); + if (!ret) + ret = fdt_finish_reservemap(abuf_data(buf)); + if (ret) { + log_debug("Failed to start FDT (err=%d)\n", ret); + return log_msg_ret("sta", -EINVAL); + } + + ret = flatten_node(buf, root); + if (ret) + return log_msg_ret("flt", ret); + + ret = fdt_finish(abuf_data(buf)); + ret = check_space(ret, buf); + if (ret == -EAGAIN) { + ret = fdt_finish(abuf_data(buf)); + if (ret) { + log_debug("Internal error c %d\n", ret); + return -EFAULT; + } + } + if (ret) + return log_msg_ret("fin", ret); + + ret = fdt_pack(abuf_data(buf)); + if (ret) { + log_debug("Failed to pack (err=%d)\n", ret); + return log_msg_ret("pac", -EFAULT); + } + + if (!abuf_realloc(buf, fdt_totalsize(abuf_data(buf)))) + return log_msg_ret("abu", -EFAULT); + + return 0; +} diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 845cded449a..ceeb8e57791 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include @@ -1456,3 +1458,25 @@ static int dm_test_ofnode_delete(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_ofnode_delete, UT_TESTF_SCAN_FDT); + +static int dm_test_oftree_to_fdt(struct unit_test_state *uts) +{ + oftree tree, check; + struct abuf buf, buf2; + + tree = oftree_default(); + ut_assertok(oftree_to_fdt(tree, &buf)); + ut_assert(abuf_size(&buf) > SZ_16K); + + /* convert it back to a tree and see if it looks OK */ + check = oftree_from_fdt(abuf_data(&buf)); + ut_assert(oftree_valid(check)); + + ut_assertok(oftree_to_fdt(check, &buf2)); + ut_assert(abuf_size(&buf2) > SZ_16K); + ut_asserteq(abuf_size(&buf), abuf_size(&buf2)); + ut_asserteq_mem(abuf_data(&buf), abuf_data(&buf2), abuf_size(&buf)); + + return 0; +} +DM_TEST(dm_test_oftree_to_fdt, UT_TESTF_SCAN_FDT); -- cgit v1.3.1 From d9216c8683fced4cbf6d437b4357c9368bf1bf86 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:44 -0600 Subject: dm: core: Support writing a boolean Add functions to write a boolean property. This involves deleting it if the value is false. Add a new ofnode_has_property() as well. Add a comment about the behaviour of of_read_property() when the property value is empty. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 36 ++++++++++++++++++++++++++++++++++-- include/dm/ofnode.h | 32 +++++++++++++++++++++++++++++++- test/dm/ofnode.c | 25 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 39ba480c8f8..4dcb3dd1c03 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -491,12 +491,12 @@ u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def) bool ofnode_read_bool(ofnode node, const char *propname) { - const void *prop; + bool prop; assert(ofnode_valid(node)); debug("%s: %s: ", __func__, propname); - prop = ofnode_get_property(node, propname, NULL); + prop = ofnode_has_property(node, propname); debug("%s\n", prop ? "true" : "false"); @@ -1168,6 +1168,14 @@ const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) propname, lenp); } +bool ofnode_has_property(ofnode node, const char *propname) +{ + if (ofnode_is_np(node)) + return of_find_property(ofnode_to_np(node), propname, NULL); + else + return ofnode_get_property(node, propname, NULL); +} + int ofnode_first_property(ofnode node, struct ofprop *prop) { prop->node = node; @@ -1616,6 +1624,30 @@ int ofnode_write_u32(ofnode node, const char *propname, u32 value) return ofnode_write_prop(node, propname, val, sizeof(value), false); } +int ofnode_write_bool(ofnode node, const char *propname, bool value) +{ + if (value) + return ofnode_write_prop(node, propname, NULL, 0, false); + else + return ofnode_delete_prop(node, propname); +} + +int ofnode_delete_prop(ofnode node, const char *propname) +{ + if (ofnode_is_np(node)) { + struct property *prop; + int len; + + prop = of_find_property(ofnode_to_np(node), propname, &len); + if (prop) + return of_remove_property(ofnode_to_np(node), prop); + return 0; + } else { + return fdt_delprop(ofnode_to_fdt(node), ofnode_to_offset(node), + propname); + } +} + int ofnode_set_enabled(ofnode node, bool value) { assert(ofnode_valid(node)); diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index a8605fb718b..ebea29d32af 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1037,10 +1037,19 @@ int ofnode_decode_panel_timing(ofnode node, * @node: node to read * @propname: property to read * @lenp: place to put length on success - * Return: pointer to property, or NULL if not found + * Return: pointer to property value, or NULL if not found or empty */ const void *ofnode_get_property(ofnode node, const char *propname, int *lenp); +/** + * ofnode_has_property() - check if a node has a named property + * + * @node: node to read + * @propname: property to read + * Return: true if the property exists in the node, false if not + */ +bool ofnode_has_property(ofnode node, const char *propname); + /** * ofnode_first_property()- get the reference of the first property * @@ -1452,6 +1461,27 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value); */ int ofnode_write_u32(ofnode node, const char *propname, u32 value); +/** + * ofnode_write_bool() - Set a boolean property of an ofnode + * + * This either adds or deleted a property with a zero-length value + * + * @node: The node for whose string property should be set + * @propname: The name of the string property to set + * @value: The new value of the boolean property + * Return: 0 if successful, -ve on error + */ +int ofnode_write_bool(ofnode node, const char *propname, bool value); + +/** + * ofnode_delete_prop() - Delete a property + * + * @node: Node containing the property to delete + * @propname: Name of property to delete + * Return: 0 if successful, -ve on error + */ +int ofnode_delete_prop(ofnode node, const char *propname); + /** * ofnode_set_enabled() - Enable or disable a device tree node given by its * ofnode diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index ceeb8e57791..9477f791d64 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1480,3 +1480,28 @@ static int dm_test_oftree_to_fdt(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_oftree_to_fdt, UT_TESTF_SCAN_FDT); + +/* test ofnode_read_bool() and ofnode_write_bool() */ +static int dm_test_bool(struct unit_test_state *uts) +{ + const char *propname = "missing-bool-value"; + ofnode node; + + node = ofnode_path("/a-test"); + ut_assert(ofnode_read_bool(node, "bool-value")); + ut_assert(!ofnode_read_bool(node, propname)); + ut_assert(!ofnode_has_property(node, propname)); + + ut_assertok(ofnode_write_bool(node, propname, true)); + ut_assert(ofnode_read_bool(node, propname)); + ut_assert(ofnode_has_property(node, propname)); + ut_assert(ofnode_read_bool(node, "bool-value")); + + ut_assertok(ofnode_write_bool(node, propname, false)); + ut_assert(!ofnode_read_bool(node, propname)); + ut_assert(!ofnode_has_property(node, propname)); + ut_assert(ofnode_read_bool(node, "bool-value")); + + return 0; +} +DM_TEST(dm_test_bool, UT_TESTF_SCAN_FDT); -- cgit v1.3.1 From 7071c82bdc55ed5d7955d8e1682b7c80af5659b5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:45 -0600 Subject: dm: core: Support writing a 64-bit value Add support for writing a single 64-bit value into a property. Repurpose the existing tests to handle this case too. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 17 ++++++++++++++++- include/dm/ofnode.h | 10 ++++++++++ test/dm/ofnode.c | 15 +++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 4dcb3dd1c03..18d2eb0f118 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1621,7 +1621,22 @@ int ofnode_write_u32(ofnode node, const char *propname, u32 value) return -ENOMEM; *val = cpu_to_fdt32(value); - return ofnode_write_prop(node, propname, val, sizeof(value), false); + return ofnode_write_prop(node, propname, val, sizeof(value), true); +} + +int ofnode_write_u64(ofnode node, const char *propname, u64 value) +{ + fdt64_t *val; + + assert(ofnode_valid(node)); + + log_debug("%s = %llx", propname, (unsigned long long)value); + val = malloc(sizeof(*val)); + if (!val) + return -ENOMEM; + *val = cpu_to_fdt64(value); + + return ofnode_write_prop(node, propname, val, sizeof(value), true); } int ofnode_write_bool(ofnode node, const char *propname, bool value) diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index ebea29d32af..ef1437cc556 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1461,6 +1461,16 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value); */ int ofnode_write_u32(ofnode node, const char *propname, u32 value); +/** + * ofnode_write_u64() - Set an integer property of an ofnode + * + * @node: The node for whose string property should be set + * @propname: The name of the string property to set + * @value: The new value of the 64-bit integer property + * Return: 0 if successful, -ve on error + */ +int ofnode_write_u64(ofnode node, const char *propname, u64 value); + /** * ofnode_write_bool() - Set a boolean property of an ofnode * diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 9477f791d64..e078a9755a8 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1009,7 +1009,8 @@ static int dm_test_ofnode_u32_array(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_u32_array, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); -static int dm_test_ofnode_read_u64(struct unit_test_state *uts) +/* test ofnode_read_u64() and ofnode_write_u64() */ +static int dm_test_ofnode_u64(struct unit_test_state *uts) { ofnode node; u64 val; @@ -1018,6 +1019,10 @@ static int dm_test_ofnode_read_u64(struct unit_test_state *uts) ut_assert(ofnode_valid(node)); ut_assertok(ofnode_read_u64(node, "int64-value", &val)); ut_asserteq_64(0x1111222233334444, val); + ut_assertok(ofnode_write_u64(node, "new-int64-value", 0x9876543210)); + ut_assertok(ofnode_read_u64(node, "new-int64-value", &val)); + ut_asserteq_64(0x9876543210, val); + ut_asserteq(-EINVAL, ofnode_read_u64(node, "missing", &val)); ut_assertok(ofnode_read_u64_index(node, "int64-array", 0, &val)); @@ -1028,9 +1033,15 @@ static int dm_test_ofnode_read_u64(struct unit_test_state *uts) ofnode_read_u64_index(node, "int64-array", 2, &val)); ut_asserteq(-EINVAL, ofnode_read_u64_index(node, "missing", 0, &val)); + ut_assertok(ofnode_write_u64(node, "int64-array", 0x9876543210)); + ut_assertok(ofnode_read_u64_index(node, "int64-array", 0, &val)); + ut_asserteq_64(0x9876543210, val); + ut_asserteq(-EOVERFLOW, + ofnode_read_u64_index(node, "int64-array", 1, &val)); + return 0; } -DM_TEST(dm_test_ofnode_read_u64, UT_TESTF_SCAN_FDT); +DM_TEST(dm_test_ofnode_u64, UT_TESTF_SCAN_FDT); static int dm_test_ofnode_add_subnode(struct unit_test_state *uts) { -- cgit v1.3.1 From 3d6531803e1cdc4c6976dae3c92220daba57f148 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:51 -0600 Subject: bloblist: Support initing from multiple places Typically the bloblist is set up after the devicetree is present. This makes sense because bloblist may use malloc() to allocate the space it needs. However sometimes the devicetree itself may be present in the bloblist. In that case it is at a known location in memory so we can init the bloblist very early, before devicetree. Add a flag to indicate whether the bloblist has been inited. Add a function to init it only if needed. Use that in the init sequence. Signed-off-by: Simon Glass --- common/bloblist.c | 13 ++++++++++++- common/board_f.c | 4 +--- include/asm-generic/global_data.h | 4 ++++ include/bloblist.h | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/common/bloblist.c b/common/bloblist.c index 2144b10e1d0..6f2a4577708 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -476,6 +476,17 @@ int bloblist_init(void) log_debug("Found existing bloblist size %lx at %lx\n", size, addr); } + if (ret) + return log_msg_ret("ini", ret); + gd->flags |= GD_FLG_BLOBLIST_READY; + + return 0; +} - return ret; +int bloblist_maybe_init(void) +{ + if (CONFIG_IS_ENABLED(BLOBLIST) && !(gd->flags & GD_FLG_BLOBLIST_READY)) + return bloblist_init(); + + return 0; } diff --git a/common/board_f.c b/common/board_f.c index 99c2a43c196..d4d7d01f8f6 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -841,9 +841,7 @@ static const init_fnc_t init_sequence_f[] = { log_init, initf_bootstage, /* uses its own timer, so does not need DM */ event_init, -#ifdef CONFIG_BLOBLIST - bloblist_init, -#endif + bloblist_maybe_init, setup_spl_handoff, #if defined(CONFIG_CONSOLE_RECORD_INIT_F) console_record_init, diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 937fb12516c..e8c6412e3f8 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -693,6 +693,10 @@ enum gd_flags { * the memory used to holds its tables has been mapped out. */ GD_FLG_DM_DEAD = 0x400000, + /** + * @GD_FLG_BLOBLIST_READY: bloblist is ready for use + */ + GD_FLG_BLOBLIST_READY = 0x800000, }; #endif /* __ASSEMBLY__ */ diff --git a/include/bloblist.h b/include/bloblist.h index 7ea72c6bd46..080cc46a126 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -413,8 +413,26 @@ void bloblist_reloc(void *to, uint to_size, void *from, uint from_size); * standard passage. The size is detected automatically so CONFIG_BLOBLIST_SIZE * can be 0. * + * Sets GD_FLG_BLOBLIST_READY in global_data flags on success + * * Return: 0 if OK, -ve on error */ int bloblist_init(void); +#if CONFIG_IS_ENABLED(BLOBLIST) +/** + * bloblist_maybe_init() - Init the bloblist system if not already done + * + * Calls bloblist_init() if the GD_FLG_BLOBLIST_READY flag is not et + * + * Return: 0 if OK, -ve on error + */ +int bloblist_maybe_init(void); +#else +static inline int bloblist_maybe_init(void) +{ + return 0; +} +#endif /* BLOBLIST */ + #endif /* __BLOBLIST_H */ -- cgit v1.3.1 From be5951461c23111b343348401defd1d05227a75e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 27 Sep 2023 08:22:37 -0600 Subject: command: Include a required header in command.h This uses ARRAY_SIZE() but does not include the header file which declares it. Fix this, so that command.h can be included without common.h Signed-off-by: Simon Glass Reviewed-by: Mattijs Korpershoek --- boot/bootm.c | 2 +- include/command.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/boot/bootm.c b/boot/bootm.c index b1c3afe0a3a..8f96a80d425 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include "mkimage.h" #endif -#include #include #include diff --git a/include/command.h b/include/command.h index ae7bb4a30b0..34ea989b39b 100644 --- a/include/command.h +++ b/include/command.h @@ -25,6 +25,10 @@ #endif #ifndef __ASSEMBLY__ + +/* For ARRAY_SIZE() */ +#include + /* * Monitor Command Table */ -- cgit v1.3.1 From 9031ba824209166444d5abea2064c23015883705 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:55 -0600 Subject: spl: Add C-based runtime detection of SPL The spl_phase() function indicates whether U-Boot is in SPL and before or after relocation. But sometimes it is useful to check for SPL with zero code-size impact. Since spl_phase() checks the global_data flags, it does add a few bytes. Add a new spl_in_proper() function to check if U-Boot proper is running, regardless of the relocation status. Signed-off-by: Simon Glass --- include/spl.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include') diff --git a/include/spl.h b/include/spl.h index 59c508280bc..a222db9c559 100644 --- a/include/spl.h +++ b/include/spl.h @@ -132,6 +132,16 @@ static inline enum u_boot_phase spl_phase(void) #endif } +/* returns true if in U-Boot proper, false if in SPL */ +static inline bool spl_in_proper(void) +{ +#ifdef CONFIG_SPL_BUILD + return false; +#endif + + return true; +} + /** * spl_prev_phase() - Figure out the previous U-Boot phase * -- cgit v1.3.1 From 61fc132051740e0378a5e71f3db6cb1581e970fe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:57 -0600 Subject: dm: core: Tweak device_is_on_pci_bus() for code size This function cannot return true if PCI is not enabled, since no PCI devices will have been bound. Add a check for this to reduce code size where it is used. Signed-off-by: Simon Glass --- include/dm/device.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/dm/device.h b/include/dm/device.h index e54cb6bca41..add67f9ec06 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -1005,7 +1005,8 @@ int dev_enable_by_path(const char *path); */ static inline bool device_is_on_pci_bus(const struct udevice *dev) { - return dev->parent && device_get_uclass_id(dev->parent) == UCLASS_PCI; + return CONFIG_IS_ENABLED(PCI) && dev->parent && + device_get_uclass_id(dev->parent) == UCLASS_PCI; } /** -- cgit v1.3.1 From f69d3d6d10b15872a279aeb10b7c522627aff6c2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:58 -0600 Subject: pci: serial: Support reading PCI-register size with base The PCI helpers read only the base address for a PCI region. In some cases the size is needed as well, e.g. to pass along to a driver which needs to know the size of its register area. Update the functions to allow the size to be returned. For serial, record the information and provided it with the serial_info() call. A limitation still exists in that the size is not available when OF_LIVE is enabled, so take account of that in the tests. Signed-off-by: Simon Glass --- arch/sandbox/dts/test.dts | 6 +++--- drivers/core/fdtaddr.c | 6 +++--- drivers/core/ofnode.c | 11 ++++++++--- drivers/core/read.c | 6 ++++-- drivers/core/util.c | 2 +- drivers/pci/pci-uclass.c | 2 +- drivers/pci/pci_mvebu.c | 3 ++- drivers/pci/pci_tegra.c | 2 +- drivers/pci/pcie_mediatek.c | 4 ++-- drivers/serial/ns16550.c | 16 +++++++++++----- include/dm/fdtaddr.h | 3 ++- include/dm/ofnode.h | 4 +++- include/dm/read.h | 8 +++++--- include/ns16550.h | 4 +++- include/serial.h | 2 ++ test/dm/pci.c | 14 ++++++++++---- 16 files changed, 61 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 962b9ebcbf6..6abce9e3963 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1123,8 +1123,8 @@ pci@1,0 { compatible = "pci-generic"; /* reg 0 is at 0x14, using FDT_PCI_SPACE_MEM32 */ - reg = <0x02000814 0 0 0 0 - 0x01000810 0 0 0 0>; + reg = <0x02000814 0 0 0x80 0 + 0x01000810 0 0 0xc0 0>; sandbox,emul = <&swap_case_emul0_1>; }; p2sb-pci@2,0 { @@ -1151,7 +1151,7 @@ pci@1f,0 { compatible = "pci-generic"; /* reg 0 is at 0x10, using FDT_PCI_SPACE_IO */ - reg = <0x0100f810 0 0 0 0>; + reg = <0x0100f810 0 0 0x100 0>; sandbox,emul = <&swap_case_emul0_1f>; }; }; diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index 546db675aaf..b79d138c419 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -215,7 +215,7 @@ void *devfdt_map_physmem(const struct udevice *dev, unsigned long size) return map_physmem(addr, size, MAP_NOCACHE); } -fdt_addr_t devfdt_get_addr_pci(const struct udevice *dev) +fdt_addr_t devfdt_get_addr_pci(const struct udevice *dev, fdt_size_t *sizep) { ulong addr; @@ -226,12 +226,12 @@ fdt_addr_t devfdt_get_addr_pci(const struct udevice *dev) int ret; ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_MEM32, - "reg", &pci_addr); + "reg", &pci_addr, sizep); if (ret) { /* try if there is any i/o-mapped register */ ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_IO, "reg", - &pci_addr); + &pci_addr, sizep); if (ret) return FDT_ADDR_T_NONE; } diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 18d2eb0f118..29a42945102 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1270,7 +1270,8 @@ const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, } int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, - const char *propname, struct fdt_pci_addr *addr) + const char *propname, struct fdt_pci_addr *addr, + fdt_size_t *size) { const fdt32_t *cell; int len; @@ -1298,14 +1299,18 @@ int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, (ulong)fdt32_to_cpu(cell[1]), (ulong)fdt32_to_cpu(cell[2])); if ((fdt32_to_cpu(*cell) & type) == type) { + const unaligned_fdt64_t *ptr; + addr->phys_hi = fdt32_to_cpu(cell[0]); addr->phys_mid = fdt32_to_cpu(cell[1]); addr->phys_lo = fdt32_to_cpu(cell[2]); + ptr = (const unaligned_fdt64_t *)(cell + 3); + if (size) + *size = fdt64_to_cpu(*ptr); break; } - cell += (FDT_PCI_ADDR_CELLS + - FDT_PCI_SIZE_CELLS); + cell += FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS; } if (i == num) { diff --git a/drivers/core/read.c b/drivers/core/read.c index 49066b59cda..419013451f0 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -405,13 +405,15 @@ int dev_read_alias_highest_id(const char *stem) return fdtdec_get_alias_highest_id(gd->fdt_blob, stem); } -fdt_addr_t dev_read_addr_pci(const struct udevice *dev) +fdt_addr_t dev_read_addr_pci(const struct udevice *dev, fdt_size_t *sizep) { ulong addr; addr = dev_read_addr(dev); + if (sizep) + *sizep = 0; if (addr == FDT_ADDR_T_NONE && !of_live_active()) - addr = devfdt_get_addr_pci(dev); + addr = devfdt_get_addr_pci(dev, sizep); return addr; } diff --git a/drivers/core/util.c b/drivers/core/util.c index aa60fdd15bc..81497df85ff 100644 --- a/drivers/core/util.c +++ b/drivers/core/util.c @@ -30,7 +30,7 @@ int pci_get_devfn(struct udevice *dev) /* Extract the devfn from fdt_pci_addr */ ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_CONFIG, - "reg", &addr); + "reg", &addr, NULL); if (ret) { if (ret != -ENOENT) return -EINVAL; diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index ae7350aaff9..e0d01f6a85d 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -123,7 +123,7 @@ static void pci_dev_find_ofnode(struct udevice *bus, phys_addr_t bdf, dev_for_each_subnode(node, bus) { ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg", - &addr); + &addr, NULL); if (ret) continue; diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index 3697cd8d652..83559550e6f 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -641,7 +641,8 @@ static int mvebu_pcie_port_parse_dt(ofnode node, ofnode parent, struct mvebu_pci pcie->is_x4 = true; /* devfn is in bits [15:8], see PCI_DEV usage */ - ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg", &pci_addr); + ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg", &pci_addr, + NULL); if (ret < 0) { printf("%s: property \"reg\" is invalid\n", pcie->name); goto err; diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 131c21b7684..d6374a58e33 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -462,7 +462,7 @@ static int tegra_pcie_parse_port_info(ofnode node, uint *index, uint *lanes) *lanes = err; - err = ofnode_read_pci_addr(node, 0, "reg", &addr); + err = ofnode_read_pci_addr(node, 0, "reg", &addr, NULL); if (err < 0) { pr_err("failed to parse \"reg\" property\n"); return err; diff --git a/drivers/pci/pcie_mediatek.c b/drivers/pci/pcie_mediatek.c index ed25a10bcf0..f0f34b5d119 100644 --- a/drivers/pci/pcie_mediatek.c +++ b/drivers/pci/pcie_mediatek.c @@ -661,7 +661,7 @@ static int mtk_pcie_probe(struct udevice *dev) if (!ofnode_is_enabled(subnode)) continue; - err = ofnode_read_pci_addr(subnode, 0, "reg", &addr); + err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); if (err) return err; @@ -700,7 +700,7 @@ static int mtk_pcie_probe_v2(struct udevice *dev) if (!ofnode_is_enabled(subnode)) continue; - err = ofnode_read_pci_addr(subnode, 0, "reg", &addr); + err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); if (err) return err; diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 5ca2828ae85..6deb1d8ddc5 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -484,6 +484,7 @@ static int ns16550_serial_getinfo(struct udevice *dev, info->addr_space = SERIAL_ADDRESS_SPACE_MEMORY; #endif info->addr = plat->base; + info->size = plat->size; info->reg_width = plat->reg_width; info->reg_shift = plat->reg_shift; info->reg_offset = plat->reg_offset; @@ -492,7 +493,8 @@ static int ns16550_serial_getinfo(struct udevice *dev, return 0; } -static int ns16550_serial_assign_base(struct ns16550_plat *plat, fdt_addr_t base) +static int ns16550_serial_assign_base(struct ns16550_plat *plat, + fdt_addr_t base, fdt_size_t size) { if (base == FDT_ADDR_T_NONE) return -EINVAL; @@ -502,6 +504,7 @@ static int ns16550_serial_assign_base(struct ns16550_plat *plat, fdt_addr_t base #else plat->base = (unsigned long)map_physmem(base, 0, MAP_NOCACHE); #endif + plat->size = size; return 0; } @@ -512,6 +515,7 @@ int ns16550_serial_probe(struct udevice *dev) struct ns16550 *const com_port = dev_get_priv(dev); struct reset_ctl_bulk reset_bulk; fdt_addr_t addr; + fdt_addr_t size; int ret; /* @@ -519,8 +523,8 @@ int ns16550_serial_probe(struct udevice *dev) * or via a PCI bridge, assign plat->base before probing hardware. */ if (device_is_on_pci_bus(dev)) { - addr = devfdt_get_addr_pci(dev); - ret = ns16550_serial_assign_base(plat, addr); + addr = devfdt_get_addr_pci(dev, &size); + ret = ns16550_serial_assign_base(plat, addr, size); if (ret) return ret; } @@ -547,12 +551,14 @@ int ns16550_serial_of_to_plat(struct udevice *dev) { struct ns16550_plat *plat = dev_get_plat(dev); const u32 port_type = dev_get_driver_data(dev); + fdt_size_t size = 0; fdt_addr_t addr; struct clk clk; int err; - addr = dev_read_addr(dev); - err = ns16550_serial_assign_base(plat, addr); + addr = spl_in_proper() ? dev_read_addr_size(dev, &size) : + dev_read_addr(dev); + err = ns16550_serial_assign_base(plat, addr, size); if (err && !device_is_on_pci_bus(dev)) return err; diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h index dcdc19137cc..6d2fa8f1044 100644 --- a/include/dm/fdtaddr.h +++ b/include/dm/fdtaddr.h @@ -168,8 +168,9 @@ fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev, * devfdt_get_addr_pci() - Read an address and handle PCI address translation * * @dev: Device to read from + * @sizep: If non-NULL, returns size of address space * Return: address or FDT_ADDR_T_NONE if not found */ -fdt_addr_t devfdt_get_addr_pci(const struct udevice *dev); +fdt_addr_t devfdt_get_addr_pci(const struct udevice *dev, fdt_size_t *sizep); #endif diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index ef1437cc556..19e97a90327 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1153,13 +1153,15 @@ const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, * @type: pci address type (FDT_PCI_SPACE_xxx) * @propname: name of property to find * @addr: returns pci address in the form of fdt_pci_addr + * @size: if non-null, returns register-space size * Return: * 0 if ok, -ENOENT if the property did not exist, -EINVAL if the * format of the property was invalid, -ENXIO if the requested * address type was not found */ int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, - const char *propname, struct fdt_pci_addr *addr); + const char *propname, struct fdt_pci_addr *addr, + fdt_size_t *size); /** * ofnode_read_pci_vendev() - look up PCI vendor and device id diff --git a/include/dm/read.h b/include/dm/read.h index c2615f72f40..3c2eea6f0c4 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -346,9 +346,10 @@ void *dev_read_addr_ptr(const struct udevice *dev); * fdtdec_get_addr() and friends. * * @dev: Device to read from + * @sizep: If non-NULL, returns size of address space found * Return: address or FDT_ADDR_T_NONE if not found */ -fdt_addr_t dev_read_addr_pci(const struct udevice *dev); +fdt_addr_t dev_read_addr_pci(const struct udevice *dev, fdt_size_t *sizep); /** * dev_remap_addr() - Get the reg property of a device as a @@ -996,9 +997,10 @@ static inline void *dev_read_addr_ptr(const struct udevice *dev) return devfdt_get_addr_ptr(dev); } -static inline fdt_addr_t dev_read_addr_pci(const struct udevice *dev) +static inline fdt_addr_t dev_read_addr_pci(const struct udevice *dev, + fdt_size_t *sizep) { - return devfdt_get_addr_pci(dev); + return devfdt_get_addr_pci(dev, sizep); } static inline void *dev_remap_addr(const struct udevice *dev) diff --git a/include/ns16550.h b/include/ns16550.h index e7e68663d03..7f481300083 100644 --- a/include/ns16550.h +++ b/include/ns16550.h @@ -58,6 +58,7 @@ enum ns16550_flags { * struct ns16550_plat - information about a NS16550 port * * @base: Base register address + * @size: Size of register area in bytes * @reg_width: IO accesses size of registers (in bytes, 1 or 4) * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...) * @reg_offset: Offset to start of registers (normally 0) @@ -67,7 +68,8 @@ enum ns16550_flags { * @bdf: PCI slot/function (pci_dev_t) */ struct ns16550_plat { - unsigned long base; + ulong base; + ulong size; int reg_width; int reg_shift; int reg_offset; diff --git a/include/serial.h b/include/serial.h index 42bdf3759c0..205889d28be 100644 --- a/include/serial.h +++ b/include/serial.h @@ -137,6 +137,7 @@ enum adr_space_type { * @type: type of the UART chip * @addr_space: address space to access the registers * @addr: physical address of the registers + * @size: size of the register area in bytes * @reg_width: size (in bytes) of the IO accesses to the registers * @reg_offset: offset to apply to the @addr from the start of the registers * @reg_shift: quantity to shift the register offsets by @@ -147,6 +148,7 @@ struct serial_device_info { enum serial_chip_type type; enum adr_space_type addr_space; ulong addr; + ulong size; u8 reg_width; u8 reg_offset; u8 reg_shift; diff --git a/test/dm/pci.c b/test/dm/pci.c index 70a736cfdb8..8c5e7da9e62 100644 --- a/test/dm/pci.c +++ b/test/dm/pci.c @@ -301,10 +301,12 @@ static int dm_test_pci_addr_flat(struct unit_test_state *uts) { struct udevice *swap1f, *swap1; ulong io_addr, mem_addr; + fdt_addr_t size; ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); io_addr = dm_pci_read_bar32(swap1f, 0); - ut_asserteq(io_addr, dev_read_addr_pci(swap1f)); + ut_asserteq(io_addr, dev_read_addr_pci(swap1f, &size)); + ut_asserteq(0, size); /* * This device has both I/O and MEM spaces but the MEM space appears @@ -312,7 +314,8 @@ static int dm_test_pci_addr_flat(struct unit_test_state *uts) */ ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); mem_addr = dm_pci_read_bar32(swap1, 1); - ut_asserteq(mem_addr, dev_read_addr_pci(swap1)); + ut_asserteq(mem_addr, dev_read_addr_pci(swap1, &size)); + ut_asserteq(0, size); return 0; } @@ -329,12 +332,15 @@ DM_TEST(dm_test_pci_addr_flat, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | static int dm_test_pci_addr_live(struct unit_test_state *uts) { struct udevice *swap1f, *swap1; + fdt_size_t size; ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); - ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f, &size)); + ut_asserteq(0, size); ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); - ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1, &size)); + ut_asserteq(0, size); return 0; } -- cgit v1.3.1