From 2c670b8f1d426dade00c25f47bfa01267d43cc94 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 8 Dec 2014 10:05:07 +0100 Subject: PBL: Add strnlen, needed for printf support vsprintf needs strnlen, so in oder to add console support to the PBL we need a strnlen implementation. Signed-off-by: Sascha Hauer --- pbl/string.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pbl/string.c b/pbl/string.c index b773f5cf7c..927c92dc05 100644 --- a/pbl/string.c +++ b/pbl/string.c @@ -119,3 +119,17 @@ void *memset(void *s, int c, size_t count) *xs++ = c; return s; } + +/** + * strnlen - Find the length of a length-limited string + * @s: The string to be sized + * @count: The maximum number of bytes to search + */ +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} -- cgit v1.2.3 From 8edb3a0545c0931d6bf59af9d58aa2e7f8c780ac Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 8 Dec 2014 10:11:04 +0100 Subject: printf: move panic() to common/misc.c panic() is not really a printf like function, so move it to common/misc.c. This is done because we want to have printf support in the PBL, but PBL has it's own panic() implementation. Signed-off-by: Sascha Hauer --- common/misc.c | 22 ++++++++++++++++++++++ lib/vsprintf.c | 21 --------------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/common/misc.c b/common/misc.c index 65f3306bee..6da71c7ab7 100644 --- a/common/misc.c +++ b/common/misc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include int errno; @@ -188,3 +189,24 @@ EXPORT_SYMBOL(barebox_get_hostname); BAREBOX_MAGICVAR_NAMED(global_hostname, global.hostname, "shortname of the board. Also used as hostname for DHCP requests"); + +void __noreturn panic(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + putchar('\n'); + va_end(args); + + dump_stack(); + + led_trigger(LED_TRIGGER_PANIC, TRIGGER_ENABLE); + + if (IS_ENABLED(CONFIG_PANIC_HANG)) { + hang(); + } else { + udelay(100000); /* allow messages to go out */ + reset_cpu(0); + } +} +EXPORT_SYMBOL(panic); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 512c88247f..a1f95fed26 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -680,24 +680,3 @@ char *asprintf(const char *fmt, ...) return p; } EXPORT_SYMBOL(asprintf); - -void __noreturn panic(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - putchar('\n'); - va_end(args); - - dump_stack(); - - led_trigger(LED_TRIGGER_PANIC, TRIGGER_ENABLE); - - if (IS_ENABLED(CONFIG_PANIC_HANG)) { - hang(); - } else { - udelay(100000); /* allow messages to go out */ - reset_cpu(0); - } -} -EXPORT_SYMBOL(panic); -- cgit v1.2.3 From c41691a7755fef462ef12f51cc299335f0d832f2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 8 Dec 2014 10:14:29 +0100 Subject: printf: move simple_strto*() functions to separate file These are not needed in the PBL, so move them to a separate file. Signed-off-by: Sascha Hauer --- lib/Makefile | 1 + lib/strtox.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/vsprintf.c | 66 -------------------------------------------------------- 3 files changed, 69 insertions(+), 66 deletions(-) create mode 100644 lib/strtox.c diff --git a/lib/Makefile b/lib/Makefile index a6c7dfbbbe..604d934765 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,6 +4,7 @@ obj-y += ctype.o obj-y += rbtree.o obj-y += display_options.o obj-y += string.o +obj-y += strtox.o obj-y += vsprintf.o obj-y += div64.o obj-y += misc.o diff --git a/lib/strtox.c b/lib/strtox.c new file mode 100644 index 0000000000..882865b45d --- /dev/null +++ b/lib/strtox.c @@ -0,0 +1,68 @@ +#include +#include + +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (*cp == '0') { + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + base = 16; + cp++; + } + if (!base) { + base = 8; + } + } + if (!base) { + base = 10; + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} +EXPORT_SYMBOL(simple_strtoul); + +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} +EXPORT_SYMBOL(simple_strtol); + +unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base) +{ + unsigned long long result = 0, value; + + if (*cp == '0') { + cp++; + if ((*cp == 'x') && isxdigit (cp[1])) { + base = 16; + cp++; + } + if (!base) { + base = 8; + } + } + if (!base) { + base = 10; + } + while (isxdigit (*cp) && (value = isdigit (*cp) + ? *cp - '0' + : (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) { + result = result * base + value; + cp++; + } + if (endp) + *endp = (char *) cp; + return result; +} +EXPORT_SYMBOL(simple_strtoull); + diff --git a/lib/vsprintf.c b/lib/vsprintf.c index a1f95fed26..b474202fc1 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -18,72 +18,6 @@ #include #include -#include - -unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) -{ - unsigned long result = 0,value; - - if (*cp == '0') { - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - base = 16; - cp++; - } - if (!base) { - base = 8; - } - } - if (!base) { - base = 10; - } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - if (endp) - *endp = (char *)cp; - return result; -} -EXPORT_SYMBOL(simple_strtoul); - -long simple_strtol(const char *cp,char **endp,unsigned int base) -{ - if(*cp=='-') - return -simple_strtoul(cp+1,endp,base); - return simple_strtoul(cp,endp,base); -} -EXPORT_SYMBOL(simple_strtol); - -unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base) -{ - unsigned long long result = 0, value; - - if (*cp == '0') { - cp++; - if ((*cp == 'x') && isxdigit (cp[1])) { - base = 16; - cp++; - } - if (!base) { - base = 8; - } - } - if (!base) { - base = 10; - } - while (isxdigit (*cp) && (value = isdigit (*cp) - ? *cp - '0' - : (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) { - result = result * base + value; - cp++; - } - if (endp) - *endp = (char *) cp; - return result; -} -EXPORT_SYMBOL(simple_strtoull); /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') -- cgit v1.2.3 From 5d876958860201175e6fb684c3e01b6a82410b03 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 8 Dec 2014 10:16:43 +0100 Subject: printf: use local isdigit/isalnum implementation To be independent of the _ctype array. This makes it possible to add printf support to the PBL without adding _ctype aswell. Signed-off-by: Sascha Hauer --- lib/vsprintf.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b474202fc1..7f6b161a47 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -21,6 +21,8 @@ /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') +#define is_alpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) +#define is_alnum(c) (is_digit(c) || is_alpha(c)) static int skip_atoi(const char **s) { @@ -351,7 +353,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) /* get field width */ field_width = -1; - if (isdigit(*fmt)) + if (is_digit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; @@ -367,7 +369,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) precision = -1; if (*fmt == '.') { ++fmt; - if (isdigit(*fmt)) + if (is_digit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; @@ -422,7 +424,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) va_arg(args, void *), field_width, precision, flags); /* Skip all alphanumeric pointer suffixes */ - while (isalnum(fmt[1])) + while (is_alnum(fmt[1])) fmt++; continue; -- cgit v1.2.3 From f2847088be8f94caa19d6f4a8f5d5a2d6487568c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 8 Dec 2014 10:28:59 +0100 Subject: Add PBL console support This adds simple console support to the PBL which makes it possible to print more complex messages in the PBL than just strings or hex numbers. For now puts_ll is used to print the messages, so it depends on CONFIG_DEBUG_LL which makes it more a debugging option. However, this could be extended later to get regular output from the PBL if desired. Signed-off-by: Sascha Hauer --- common/Kconfig | 11 +++++++++++ include/printk.h | 15 ++++++++++----- include/stdio.h | 20 +++++++++++--------- lib/Makefile | 2 ++ lib/vsprintf.c | 12 ++++++++++++ pbl/Makefile | 1 + pbl/console.c | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 pbl/console.c diff --git a/common/Kconfig b/common/Kconfig index 4614965899..00e4f36d62 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -882,6 +882,17 @@ config DEBUG_INITCALLS bool "Trace initcalls" help If enabled this will print initcall traces. + +config PBL_CONSOLE + depends on DEBUG_LL + bool "Enable console support in PBL" + help + This enables printf/pr_* support in the PBL to get more + informational output earlier during startup. Note that + printf/pr_* need a valid C environment, so the binary + must be running at the address it's linked at and bss must + be cleared. On ARM that would be after setup_c(). + endmenu config HAS_DEBUG_LL diff --git a/include/printk.h b/include/printk.h index 22c6c732f7..a27ad514cf 100644 --- a/include/printk.h +++ b/include/printk.h @@ -22,18 +22,23 @@ /* debugging and troubleshooting/diagnostic helpers. */ #ifndef CONFIG_CONSOLE_NONE -int pr_print(int level, const char *format, ...) - __attribute__ ((format(__printf__, 2, 3))); - int dev_printf(int level, const struct device_d *dev, const char *format, ...) __attribute__ ((format(__printf__, 3, 4))); #else -static inline int pr_print(int level, const char *format, ...) +static inline int dev_printf(int level, const struct device_d *dev, const char *format, ...) { return 0; } +#endif -static inline int dev_printf(int level, const struct device_d *dev, const char *format, ...) +#if (!defined(__PBL__) && !defined(CONFIG_CONSOLE_NONE)) || \ + (defined(__PBL__) && defined(CONFIG_PBL_CONSOLE)) +int pr_print(int level, const char *format, ...) + __attribute__ ((format(__printf__, 2, 3))); +#else +static int pr_print(int level, const char *format, ...) + __attribute__ ((format(__printf__, 2, 3))); +static inline int pr_print(int level, const char *format, ...) { return 0; } diff --git a/include/stdio.h b/include/stdio.h index 71dbae35ca..f190911762 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -29,8 +29,6 @@ int getc(void); int console_puts(unsigned int ch, const char *s); void console_flush(void); - -int printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2))); int vprintf(const char *fmt, va_list args); #else static inline int tstc(void) @@ -52,13 +50,6 @@ static inline void console_putc(unsigned int ch, char c) {} static inline void console_flush(void) {} -static int printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2))); -static inline int printf(const char *fmt, ...) -{ - return 0; -} - - static inline int vprintf(const char *fmt, va_list args) { return 0; @@ -74,6 +65,17 @@ static inline int ctrlc (void) #endif +#if (!defined(__PBL__) && !defined(CONFIG_CONSOLE_NONE)) || \ + (defined(__PBL__) && defined(CONFIG_PBL_CONSOLE)) +int printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2))); +#else +static int printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2))); +static inline int printf(const char *fmt, ...) +{ + return 0; +} +#endif + static inline int puts(const char *s) { return console_puts(CONSOLE_STDOUT, s); diff --git a/lib/Makefile b/lib/Makefile index 604d934765..226570a7e6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -6,7 +6,9 @@ obj-y += display_options.o obj-y += string.o obj-y += strtox.o obj-y += vsprintf.o +pbl-$(CONFIG_PBL_CONSOLE) += vsprintf.o obj-y += div64.o +pbl-y += div64.o obj-y += misc.o obj-$(CONFIG_PARAMETER) += parameter.o obj-y += xfuncs.o diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7f6b161a47..800ded7939 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -175,6 +175,7 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio return buf; } +#ifndef __PBL__ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags) { unsigned long value = (unsigned long) ptr; @@ -277,6 +278,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field } return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags); } +#else +static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) +{ + flags |= SMALL; + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags); +} +#endif /** * vsnprintf - Format a string and place it in a buffer diff --git a/pbl/Makefile b/pbl/Makefile index a2d7468687..c5a08c1354 100644 --- a/pbl/Makefile +++ b/pbl/Makefile @@ -4,3 +4,4 @@ pbl-y += misc.o pbl-y += string.o pbl-y += decomp.o +pbl-$(CONFIG_PBL_CONSOLE) += console.o diff --git a/pbl/console.c b/pbl/console.c new file mode 100644 index 0000000000..3875e2aafd --- /dev/null +++ b/pbl/console.c @@ -0,0 +1,32 @@ +#include +#include + +int printf(const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CFG_PBSIZE]; + + va_start(args, fmt); + i = vsprintf(printbuffer, fmt, args); + va_end(args); + + puts_ll(printbuffer); + + return i; +} + +int pr_print(int level, const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CFG_PBSIZE]; + + va_start(args, fmt); + i = vsprintf(printbuffer, fmt, args); + va_end(args); + + puts_ll(printbuffer); + + return i; +} -- cgit v1.2.3 From e847cc2f0b7025e5fb269d0bb336b811f394d46d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 9 Dec 2014 12:39:54 +0100 Subject: malloc: Add a function to detect if malloc pool is already initialized Signed-off-by: Sascha Hauer --- common/memory.c | 8 ++++++++ include/malloc.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/common/memory.c b/common/memory.c index 57c73abb22..4725f6e382 100644 --- a/common/memory.c +++ b/common/memory.c @@ -49,6 +49,13 @@ unsigned long mem_malloc_end(void) tlsf_pool tlsf_mem_pool; #endif +int mem_malloc_initialized; + +int mem_malloc_is_initialized(void) +{ + return mem_malloc_initialized; +} + void mem_malloc_init(void *start, void *end) { malloc_start = (unsigned long)start; @@ -57,6 +64,7 @@ void mem_malloc_init(void *start, void *end) #ifdef CONFIG_MALLOC_TLSF tlsf_mem_pool = tlsf_create(start, end - start + 1); #endif + mem_malloc_initialized = 1; } #if !defined __SANDBOX__ && !defined CONFIG_ARCH_EFI diff --git a/include/malloc.h b/include/malloc.h index a36f3c0de4..0d3c9e97a0 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -11,4 +11,6 @@ void *calloc(size_t, size_t); void malloc_stats(void); void *sbrk(ptrdiff_t increment); +int mem_malloc_is_initialized(void); + #endif /* __MALLOC_H */ -- cgit v1.2.3 From 61d2f7e4b60fc7d34c2b99559e8fcba5e85b4e16 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 9 Dec 2014 12:40:39 +0100 Subject: console: Make sure xzalloc is only used when it's available To make it possible to call the pr_* functions very early before malloc is initialized test if malloc is available before using it. Signed-off-by: Sascha Hauer --- common/console_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/console_common.c b/common/console_common.c index cc25f97d9d..df1b085982 100644 --- a/common/console_common.c +++ b/common/console_common.c @@ -101,7 +101,7 @@ void pr_puts(int level, const char *str) { struct log_entry *log; - if (IS_ENABLED(CONFIG_LOGBUF)) { + if (IS_ENABLED(CONFIG_LOGBUF) && mem_malloc_is_initialized()) { if (barebox_log_max_messages > 0) log_clean(barebox_log_max_messages - 1); -- cgit v1.2.3 From 81de61ab7545efee4bedd74d99d9a42f7e8b6264 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 9 Dec 2014 12:42:21 +0100 Subject: ARM: start.c: Add some debugging messages pr_debug can now be used right after setup_c(), so add some debug messages to the early startup code to make it a bit more clear what is happening there. Signed-off-by: Sascha Hauer --- arch/arm/cpu/start.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index 264420d084..e2a6b8e90f 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -16,6 +16,7 @@ * GNU General Public License for more details. * */ +#define pr_fmt(fmt) "start.c: " fmt #include #include @@ -62,6 +63,8 @@ static noinline __noreturn void __start(unsigned long membase, setup_c(); + pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); + barebox_boarddata = boarddata; arm_stack_top = endmem; endmem -= STACK_SIZE; /* Stack */ @@ -74,6 +77,7 @@ static noinline __noreturn void __start(unsigned long membase, if (IS_ENABLED(CONFIG_PBL_IMAGE)) { arm_set_cache_functions(); } else { + pr_debug("enabling MMU, ttb @ 0x%08lx\n", endmem); arm_early_mmu_cache_invalidate(); mmu_early_enable(membase, memsize, endmem); } @@ -87,6 +91,8 @@ static noinline __noreturn void __start(unsigned long membase, uint32_t totalsize = get_unaligned_be32(boarddata + 4); endmem -= ALIGN(totalsize, 64); barebox_boot_dtb = (void *)endmem; + pr_debug("found DTB in boarddata, copying to 0x%p\n", + barebox_boot_dtb); memcpy(barebox_boot_dtb, boarddata, totalsize); } @@ -115,8 +121,13 @@ static noinline __noreturn void __start(unsigned long membase, malloc_start = malloc_end - SZ_1G; } + pr_debug("initializing malloc pool at 0x%08lx (size 0x%08lx)\n", + malloc_start, malloc_end - malloc_start); + mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1); + pr_debug("starting barebox...\n"); + start_barebox(); } -- cgit v1.2.3 From 4babc41c7fef3331588c84b1fb99b4c6f6112997 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 9 Dec 2014 12:44:25 +0100 Subject: ARM: uncompress.c: Add some debugging messages Now that we have printf support in the PBL we can use it right after setup_c(). Add some debug messages to the early PBL code to make it more clear what is happening there. Signed-off-by: Sascha Hauer --- arch/arm/cpu/uncompress.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c index d64706d217..03c73d56a3 100644 --- a/arch/arm/cpu/uncompress.c +++ b/arch/arm/cpu/uncompress.c @@ -17,6 +17,7 @@ * GNU General Public License for more details. * */ +#define pr_fmt(fmt) "uncompress.c: " fmt #include #include @@ -76,9 +77,12 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase, setup_c(); + pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); + if (IS_ENABLED(CONFIG_MMU_EARLY)) { endmem &= ~0x3fff; endmem -= SZ_16K; /* ttb */ + pr_debug("enabling MMU, ttb @ 0x%08x\n", endmem); mmu_early_enable(membase, memsize, endmem); } @@ -93,6 +97,9 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase, pg_start = image_end + 1; pg_len = *(image_end); + pr_debug("uncompressing barebox binary at 0x%p (size 0x%08x) to 0x%08lx\n", + pg_start, pg_len, barebox_base); + pbl_barebox_uncompress((void*)barebox_base, pg_start, pg_len); arm_early_mmu_cache_flush(); @@ -103,6 +110,8 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase, else barebox = (void *)barebox_base; + pr_debug("jumping to uncompressed image at 0x%p\n", barebox); + barebox(membase, memsize, boarddata); } -- cgit v1.2.3