Commit b4f4a2f0 authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #1093 from soby-mathew/eb/log_fw

Implement log framework
parents 756f9bb8 7f56e9a3
...@@ -162,11 +162,13 @@ include lib/compiler-rt/compiler-rt.mk ...@@ -162,11 +162,13 @@ include lib/compiler-rt/compiler-rt.mk
include lib/stdlib/stdlib.mk include lib/stdlib/stdlib.mk
BL_COMMON_SOURCES += common/bl_common.c \ BL_COMMON_SOURCES += common/bl_common.c \
common/tf_log.c \
common/tf_printf.c \ common/tf_printf.c \
common/tf_snprintf.c \ common/tf_snprintf.c \
common/${ARCH}/debug.S \ common/${ARCH}/debug.S \
lib/${ARCH}/cache_helpers.S \ lib/${ARCH}/cache_helpers.S \
lib/${ARCH}/misc_helpers.S \ lib/${ARCH}/misc_helpers.S \
plat/common/plat_log_common.c \
plat/common/${ARCH}/plat_common.c \ plat/common/${ARCH}/plat_common.c \
plat/common/${ARCH}/platform_helpers.S \ plat/common/${ARCH}/platform_helpers.S \
${COMPILER_RT_SRCS} \ ${COMPILER_RT_SRCS} \
......
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <debug.h>
#include <platform.h>
/* Set the default maximum log level to the `LOG_LEVEL` build flag */
static unsigned int max_log_level = LOG_LEVEL;
/*
* The common log function which is invoked by ARM Trusted Firmware code.
* This function should not be directly invoked and is meant to be
* only used by the log macros defined in debug.h. The function
* expects the first character in the format string to be one of the
* LOG_MARKER_* macros defined in debug.h.
*/
void tf_log(const char *fmt, ...)
{
unsigned int log_level;
va_list args;
const char *prefix_str;
/* We expect the LOG_MARKER_* macro as the first character */
log_level = fmt[0];
/* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */
assert(log_level && log_level <= LOG_LEVEL_VERBOSE);
assert(log_level % 10 == 0);
if (log_level > max_log_level)
return;
prefix_str = plat_log_get_prefix(log_level);
if (prefix_str != NULL)
tf_string_print(prefix_str);
va_start(args, fmt);
tf_vprintf(fmt+1, args);
va_end(args);
}
/*
* The helper function to set the log level dynamically by platform. The
* maximum log level is determined by `LOG_LEVEL` build flag at compile time
* and this helper can set a lower log level than the one at compile.
*/
void tf_log_set_max_level(unsigned int log_level)
{
assert(log_level <= LOG_LEVEL_VERBOSE);
assert((log_level % 10) == 0);
/* Cap log_level to the compile time maximum. */
if (log_level < LOG_LEVEL)
max_log_level = log_level;
}
...@@ -23,8 +23,10 @@ ...@@ -23,8 +23,10 @@
(((lcount) > 1) ? va_arg(args, unsigned long long int) : \ (((lcount) > 1) ? va_arg(args, unsigned long long int) : \
((lcount) ? va_arg(args, unsigned long int) : va_arg(args, unsigned int))) ((lcount) ? va_arg(args, unsigned long int) : va_arg(args, unsigned int)))
static void string_print(const char *str) void tf_string_print(const char *str)
{ {
assert(str);
while (*str) while (*str)
putchar(*str++); putchar(*str++);
} }
...@@ -64,15 +66,13 @@ static void unsigned_num_print(unsigned long long int unum, unsigned int radix) ...@@ -64,15 +66,13 @@ static void unsigned_num_print(unsigned long long int unum, unsigned int radix)
* The print exits on all other formats specifiers other than valid * The print exits on all other formats specifiers other than valid
* combinations of the above specifiers. * combinations of the above specifiers.
*******************************************************************/ *******************************************************************/
void tf_printf(const char *fmt, ...) void tf_vprintf(const char *fmt, va_list args)
{ {
va_list args;
int l_count; int l_count;
long long int num; long long int num;
unsigned long long int unum; unsigned long long int unum;
char *str; char *str;
va_start(args, fmt);
while (*fmt) { while (*fmt) {
l_count = 0; l_count = 0;
...@@ -94,12 +94,12 @@ loop: ...@@ -94,12 +94,12 @@ loop:
break; break;
case 's': case 's':
str = va_arg(args, char *); str = va_arg(args, char *);
string_print(str); tf_string_print(str);
break; break;
case 'p': case 'p':
unum = (uintptr_t)va_arg(args, void *); unum = (uintptr_t)va_arg(args, void *);
if (unum) if (unum)
string_print("0x"); tf_string_print("0x");
unsigned_num_print(unum, 16); unsigned_num_print(unum, 16);
break; break;
...@@ -123,13 +123,20 @@ loop: ...@@ -123,13 +123,20 @@ loop:
break; break;
default: default:
/* Exit on any other format specifier */ /* Exit on any other format specifier */
goto exit; return;
} }
fmt++; fmt++;
continue; continue;
} }
putchar(*fmt++); putchar(*fmt++);
} }
exit: }
va_end(args);
void tf_printf(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
tf_vprintf(fmt, va);
va_end(va);
} }
...@@ -1014,6 +1014,21 @@ This function flushes to main memory all the image params that are passed to ...@@ -1014,6 +1014,21 @@ This function flushes to main memory all the image params that are passed to
next image. This function is currently invoked in BL2 to flush this information next image. This function is currently invoked in BL2 to flush this information
to the next BL image, when LOAD\_IMAGE\_V2 is enabled. to the next BL image, when LOAD\_IMAGE\_V2 is enabled.
Function : plat\_log\_get\_prefix()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
Argument : unsigned int
Return : const char *
This function defines the prefix string corresponding to the `log_level` to be
prepended to all the log output from ARM Trusted Firmware. The `log_level`
(argument) will correspond to one of the standard log levels defined in
debug.h. The platform can override the common implementation to define a
different prefix string for the log output. The implementation should be
robust to future changes that increase the number of log levels.
Modifications specific to a Boot Loader stage Modifications specific to a Boot Loader stage
--------------------------------------------- ---------------------------------------------
......
...@@ -24,47 +24,62 @@ ...@@ -24,47 +24,62 @@
#define LOG_LEVEL_VERBOSE 50 #define LOG_LEVEL_VERBOSE 50
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
/*
* Define Log Markers corresponding to each log level which will
* be embedded in the format string and is expected by tf_log() to determine
* the log level.
*/
#define LOG_MARKER_ERROR "\xa" /* 10 */
#define LOG_MARKER_NOTICE "\x14" /* 20 */
#define LOG_MARKER_WARNING "\x1e" /* 30 */
#define LOG_MARKER_INFO "\x28" /* 40 */
#define LOG_MARKER_VERBOSE "\x32" /* 50 */
#if LOG_LEVEL >= LOG_LEVEL_NOTICE #if LOG_LEVEL >= LOG_LEVEL_NOTICE
# define NOTICE(...) tf_printf("NOTICE: " __VA_ARGS__) # define NOTICE(...) tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
#else #else
# define NOTICE(...) # define NOTICE(...)
#endif #endif
#if LOG_LEVEL >= LOG_LEVEL_ERROR #if LOG_LEVEL >= LOG_LEVEL_ERROR
# define ERROR(...) tf_printf("ERROR: " __VA_ARGS__) # define ERROR(...) tf_log(LOG_MARKER_ERROR __VA_ARGS__)
#else #else
# define ERROR(...) # define ERROR(...)
#endif #endif
#if LOG_LEVEL >= LOG_LEVEL_WARNING #if LOG_LEVEL >= LOG_LEVEL_WARNING
# define WARN(...) tf_printf("WARNING: " __VA_ARGS__) # define WARN(...) tf_log(LOG_MARKER_WARNING __VA_ARGS__)
#else #else
# define WARN(...) # define WARN(...)
#endif #endif
#if LOG_LEVEL >= LOG_LEVEL_INFO #if LOG_LEVEL >= LOG_LEVEL_INFO
# define INFO(...) tf_printf("INFO: " __VA_ARGS__) # define INFO(...) tf_log(LOG_MARKER_INFO __VA_ARGS__)
#else #else
# define INFO(...) # define INFO(...)
#endif #endif
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
# define VERBOSE(...) tf_printf("VERBOSE: " __VA_ARGS__) # define VERBOSE(...) tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
#else #else
# define VERBOSE(...) # define VERBOSE(...)
#endif #endif
void __dead2 do_panic(void); void __dead2 do_panic(void);
#define panic() do_panic() #define panic() do_panic()
/* Function called when stack protection check code detects a corrupted stack */ /* Function called when stack protection check code detects a corrupted stack */
void __dead2 __stack_chk_fail(void); void __dead2 __stack_chk_fail(void);
void tf_log(const char *fmt, ...) __printflike(1, 2);
void tf_printf(const char *fmt, ...) __printflike(1, 2); void tf_printf(const char *fmt, ...) __printflike(1, 2);
int tf_snprintf(char *s, size_t n, const char *fmt, ...) __printflike(3, 4); int tf_snprintf(char *s, size_t n, const char *fmt, ...) __printflike(3, 4);
void tf_vprintf(const char *fmt, va_list args);
void tf_string_print(const char *str);
void tf_log_set_max_level(unsigned int log_level);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __DEBUG_H__ */ #endif /* __DEBUG_H__ */
...@@ -79,6 +79,7 @@ int plat_crash_console_putc(int c); ...@@ -79,6 +79,7 @@ int plat_crash_console_putc(int c);
int plat_crash_console_flush(void); int plat_crash_console_flush(void);
void plat_error_handler(int err) __dead2; void plat_error_handler(int err) __dead2;
void plat_panic_handler(void) __dead2; void plat_panic_handler(void) __dead2;
const char *plat_log_get_prefix(unsigned int log_level);
/******************************************************************************* /*******************************************************************************
* Mandatory BL1 functions * Mandatory BL1 functions
......
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <debug.h>
#include <platform.h>
/* Allow platforms to override the log prefix string */
#pragma weak plat_log_get_prefix
static const char *prefix_str[] = {
"ERROR: ", "NOTICE: ", "WARNING: ", "INFO: ", "VERBOSE: "};
const char *plat_log_get_prefix(unsigned int log_level)
{
if (log_level < LOG_LEVEL_ERROR)
log_level = LOG_LEVEL_ERROR;
else if (log_level > LOG_LEVEL_VERBOSE)
log_level = LOG_LEVEL_VERBOSE;
return prefix_str[(log_level/10) - 1];
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment