Add an option to perform DRAM region validation before using it. The framework allows individual boards to set up a memory validaion hook that would be called prior to Barebox using that region of memory. Signed-off-by: Andrey Smirnov <andrew.smirnov@xxxxxxxxx> --- arch/arm/cpu/start.c | 14 +----------- arch/arm/cpu/uncompress.c | 32 ++++++++++++++++++++++++--- arch/arm/include/asm/barebox-arm.h | 28 ++++++++++++++++++++++++ common/Kconfig | 8 +++++++ common/Makefile | 2 +- include/common.h | 1 + include/memtest.h | 19 ++++++++++++++++ lib/Makefile | 6 ++++++ pbl/misc.c | 44 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 137 insertions(+), 17 deletions(-) diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index 304ed0c..ee7eb00 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -105,19 +105,7 @@ static noinline __noreturn void __start(unsigned long membase, else malloc_end = (unsigned long)_text; - /* - * Maximum malloc space is the Kconfig value if given - * or 1GB. - */ - if (MALLOC_SIZE > 0) { - malloc_start = malloc_end - MALLOC_SIZE; - if (malloc_start < membase) - malloc_start = membase; - } else { - malloc_start = malloc_end - (malloc_end - membase) / 2; - if (malloc_end - malloc_start > SZ_1G) - malloc_start = malloc_end - SZ_1G; - } + malloc_start = arm_get_malloc_start(membase, malloc_end); pr_debug("initializing malloc pool at 0x%08lx (size 0x%08lx)\n", malloc_start, malloc_end - malloc_start); diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c index b0b7c6d..853d2a3 100644 --- a/arch/arm/cpu/uncompress.c +++ b/arch/arm/cpu/uncompress.c @@ -20,6 +20,7 @@ #define pr_fmt(fmt) "uncompress.c: " fmt #include <common.h> +#include <memtest.h> #include <init.h> #include <linux/sizes.h> #include <pbl.h> @@ -47,6 +48,7 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase, uint32_t pg_len; void __noreturn (*barebox)(unsigned long, unsigned long, void *); uint32_t endmem = membase + memsize; + unsigned long malloc_start, malloc_end; unsigned long barebox_base; uint32_t *image_end; void *pg_start; @@ -64,10 +66,14 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase, * to the current address. Otherwise it may be a readonly location. * Copy and relocate to the start of the memory in this case. */ - if (pc > membase && pc < membase + memsize) + if (pc > membase && pc < membase + memsize) { relocate_to_current_adr(); - else + } else { + validate_memory_range("validating pbl relocation area", + membase, + membase + arm_barebox_image_size() - 1); relocate_to_adr(membase); + } } if (IS_ENABLED(CONFIG_RELOCATABLE)) @@ -77,6 +83,21 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase, setup_c(); + validate_memory_range("validating barebox decompression area", + barebox_base, endmem - 1); + + /* + We know that when we give control to __start function of + uncompressed image _text would be within the boundaries of + (membase, membase + memsize) so the malloc_end variable + would be set to _text + */ + malloc_end = barebox_base; + malloc_start = arm_get_malloc_start(membase, malloc_end); + + validate_memory_range("validating malloc area", + malloc_start, malloc_end - 1); + pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); if (IS_ENABLED(CONFIG_MMU_EARLY)) { @@ -122,7 +143,12 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase, void __naked __noreturn barebox_arm_entry(unsigned long membase, unsigned long memsize, void *boarddata) { - arm_setup_stack(membase + memsize - 16); + unsigned long stack_end = membase + memsize - 16; + + validate_memory_range("validating stack area", + membase + memsize - STACK_SIZE, stack_end); + + arm_setup_stack(stack_end); uncompress_start_payload(membase, memsize, boarddata); } diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h index dbc8aaa..f577df7 100644 --- a/arch/arm/include/asm/barebox-arm.h +++ b/arch/arm/include/asm/barebox-arm.h @@ -83,6 +83,34 @@ static inline unsigned long arm_barebox_image_place(unsigned long endmem) return endmem; } +static inline unsigned long arm_barebox_image_size(void) +{ + /* We assume that 1G is significantly more that Barebox will + * ever try to reserve */ + return SZ_1G - arm_barebox_image_place(SZ_1G); +} + +static inline unsigned long arm_get_malloc_start(unsigned long membase, + unsigned long malloc_end) +{ + unsigned long malloc_start; + /* + * Maximum malloc space is the Kconfig value if given + * or 1GB. + */ + if (MALLOC_SIZE > 0) { + malloc_start = malloc_end - MALLOC_SIZE; + if (malloc_start < membase) + malloc_start = membase; + } else { + malloc_start = malloc_end - (malloc_end - membase) / 2; + if (malloc_end - malloc_start > SZ_1G) + malloc_start = malloc_end - SZ_1G; + } + + return malloc_start; +} + #define ENTRY_FUNCTION(name, arg0, arg1, arg2) \ static void __##name(uint32_t, uint32_t, uint32_t); \ \ diff --git a/common/Kconfig b/common/Kconfig index 4032dcd..5d40dee 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -246,6 +246,14 @@ config MALLOC_SIZE prompt "malloc area size" endmenu +config MEMORY_VALIDATION + bool "Validate regions of memory prior to using them" + select PBL_CONSOLE + help + select this option if you want Barebox to perform memory test + on regions of DRAM memory that it is about to use for the + first time + config BROKEN bool diff --git a/common/Makefile b/common/Makefile index 2738238..a634f0d 100644 --- a/common/Makefile +++ b/common/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_BLSPEC) += blspec.o obj-$(CONFIG_BOOTM) += bootm.o obj-$(CONFIG_CMD_LOADS) += s_record.o obj-$(CONFIG_CMD_MEMTEST) += memtest.o +pbl-$(CONFIG_MEMORY_VALIDATION) += memtest.o obj-$(CONFIG_COMMAND_SUPPORT) += command.o obj-$(CONFIG_CONSOLE_FULL) += console.o obj-$(CONFIG_CONSOLE_SIMPLE) += console_simple.o @@ -90,4 +91,3 @@ include/generated/compile.h: FORCE @$($(quiet)chk_compile.h) $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \ "$(UTS_MACHINE)" "$(CC) $(KBUILD_CFLAGS)" - diff --git a/include/common.h b/include/common.h index 86e755d..021637a 100644 --- a/include/common.h +++ b/include/common.h @@ -209,6 +209,7 @@ static inline void *get_true_address(const void *ptr) return (void *)address; } #else + static inline void *get_true_address(const void *ptr) { return (void *)ptr; diff --git a/include/memtest.h b/include/memtest.h index a337be8..4a426c3 100644 --- a/include/memtest.h +++ b/include/memtest.h @@ -8,7 +8,26 @@ struct mem_test_resource { struct list_head list; }; +typedef int (*mem_test_handler_t)(resource_size_t _start, resource_size_t _end); + int mem_test(resource_size_t _start, resource_size_t _end, int bus_only); +#ifdef CONFIG_MEMORY_VALIDATION +void validate_memory_range(const char *message, + resource_size_t start, + resource_size_t end); +void set_memory_validation_handler(mem_test_handler_t handler); +#else +static inline void validate_memory_range(const char *message, + resource_size_t start, + resource_size_t end) +{ +} + +static inline void set_memory_validation_handler(mem_test_handler_t handler) +{ +} +#endif + #endif /* __MEMTEST_H */ diff --git a/lib/Makefile b/lib/Makefile index 6a3e9fd..3da2c27 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,6 +35,12 @@ obj-y += random.o obj-y += lzo/ obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/ obj-y += show_progress.o +pbl-$(CONFIG_MEMORY_VALIDATION) += show_progress.o +# The code is going to be used before MMU is set up and unaligned +# access will cause an exception(there is an unaligned access to the +# contenst of 'spinchr' in show_progress()) +CFLAGS_pbl-show_progress.o = -mno-unaligned-access + obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o obj-$(CONFIG_LZ4_DECOMPRESS) += decompress_unlz4.o obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o diff --git a/pbl/misc.c b/pbl/misc.c index 3d5a881..2b446f5 100644 --- a/pbl/misc.c +++ b/pbl/misc.c @@ -1,8 +1,10 @@ #include <common.h> #include <init.h> +#include <memtest.h> #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> +#include <debug_ll.h> void __noreturn __hang(void) { @@ -26,6 +28,48 @@ void set_hang_handler(hang_handler_t handler) *__hang_handler_p = handler; } +#ifdef CONFIG_MEMORY_VALIDATION + +static mem_test_handler_t mem_test_handler = NULL; + +void validate_memory_range(const char *message, + resource_size_t start, + resource_size_t end) +{ + int ret; + mem_test_handler_t *__mem_test_handler_p = get_true_address(&mem_test_handler); + mem_test_handler_t __mem_test_handler = get_true_address(*__mem_test_handler_p); + + if (__mem_test_handler) { + message = get_true_address(message); + + puts_ll(message); + putc_ll(' '); + putc_ll('['); + puthex_ll(start); + putc_ll(' '); + putc_ll('-'); + putc_ll(' '); + puthex_ll(end); + putc_ll(']'); + putc_ll('\r'); + putc_ll('\n'); + + ret = __mem_test_handler(start, end); + + if (ret < 0) + hang(); + } +} + +void set_memory_validation_handler(mem_test_handler_t handler) +{ + mem_test_handler_t *__mem_test_handler_p = get_true_address(&mem_test_handler); + + *__mem_test_handler_p = handler; +} +#endif + void __noreturn panic(const char *fmt, ...) { while(1); -- 2.1.4 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox