diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 9 | ||||
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/board_f.c | 27 | ||||
-rw-r--r-- | common/log_syslog.c | 117 |
4 files changed, 144 insertions, 10 deletions
diff --git a/common/Kconfig b/common/Kconfig index 3072651082..ee4f748c32 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -775,9 +775,16 @@ config TPL_LOG_CONSOLE log message is shown - other details like level, category, file and line number are omitted. +config LOG_SYSLOG + bool "Log output to syslog server" + depends on LOG && NET + help + Enables a log driver which broadcasts log records via UDP port 514 + to syslog servers. + config LOG_TEST bool "Provide a test for logging" - depends on LOG + depends on LOG && UNIT_TEST default y if SANDBOX help This enables a 'log test' command to test logging. It is normally diff --git a/common/Makefile b/common/Makefile index 702f2396cf..d84e10ba99 100644 --- a/common/Makefile +++ b/common/Makefile @@ -132,6 +132,7 @@ obj-$(CONFIG_DFU_OVER_USB) += dfu.o obj-y += command.o obj-$(CONFIG_$(SPL_TPL_)LOG) += log.o obj-$(CONFIG_$(SPL_TPL_)LOG_CONSOLE) += log_console.o +obj-$(CONFIG_$(SPL_TPL_)LOG_SYSLOG) += log_syslog.o obj-y += s_record.o obj-$(CONFIG_CMD_LOADB) += xyzModem.o obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o diff --git a/common/board_f.c b/common/board_f.c index 82a164752a..2ec5dbaa68 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -472,6 +472,17 @@ static int reserve_uboot(void) return 0; } +/* + * reserve after start_addr_sp the requested size and make the stack pointer + * 16-byte aligned, this alignment is needed for cast on the reserved memory + * ref = x86_64 ABI: https://reviews.llvm.org/D30049: 16 bytes + * = ARMv8 Instruction Set Overview: quad word, 16 bytes + */ +static unsigned long reserve_stack_aligned(size_t size) +{ + return ALIGN_DOWN(gd->start_addr_sp - size, 16); +} + #ifdef CONFIG_SYS_NONCACHED_MEMORY static int reserve_noncached(void) { @@ -497,7 +508,7 @@ static int reserve_noncached(void) /* reserve memory for malloc() area */ static int reserve_malloc(void) { - gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN; + gd->start_addr_sp = reserve_stack_aligned(TOTAL_MALLOC_LEN); debug("Reserving %dk for malloc() at: %08lx\n", TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp); #ifdef CONFIG_SYS_NONCACHED_MEMORY @@ -511,7 +522,7 @@ static int reserve_malloc(void) static int reserve_board(void) { if (!gd->bd) { - gd->start_addr_sp -= sizeof(bd_t); + gd->start_addr_sp = reserve_stack_aligned(sizeof(bd_t)); gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t)); memset(gd->bd, '\0', sizeof(bd_t)); debug("Reserving %zu Bytes for Board Info at: %08lx\n", @@ -530,7 +541,7 @@ static int setup_machine(void) static int reserve_global_data(void) { - gd->start_addr_sp -= sizeof(gd_t); + gd->start_addr_sp = reserve_stack_aligned(sizeof(gd_t)); gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t)); debug("Reserving %zu Bytes for Global Data at: %08lx\n", sizeof(gd_t), gd->start_addr_sp); @@ -548,7 +559,7 @@ static int reserve_fdt(void) if (gd->fdt_blob) { gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); - gd->start_addr_sp -= gd->fdt_size; + gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size); gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size); debug("Reserving %lu Bytes for FDT at: %08lx\n", gd->fdt_size, gd->start_addr_sp); @@ -563,7 +574,7 @@ static int reserve_bootstage(void) #ifdef CONFIG_BOOTSTAGE int size = bootstage_get_size(); - gd->start_addr_sp -= size; + gd->start_addr_sp = reserve_stack_aligned(size); gd->new_bootstage = map_sysmem(gd->start_addr_sp, size); debug("Reserving %#x Bytes for bootstage at: %08lx\n", size, gd->start_addr_sp); @@ -580,8 +591,7 @@ __weak int arch_reserve_stacks(void) static int reserve_stacks(void) { /* make stack pointer 16-byte aligned */ - gd->start_addr_sp -= 16; - gd->start_addr_sp &= ~0xf; + gd->start_addr_sp = reserve_stack_aligned(16); /* * let the architecture-specific code tailor gd->start_addr_sp and @@ -593,8 +603,7 @@ static int reserve_stacks(void) static int reserve_bloblist(void) { #ifdef CONFIG_BLOBLIST - gd->start_addr_sp &= ~0xf; - gd->start_addr_sp -= CONFIG_BLOBLIST_SIZE; + gd->start_addr_sp = reserve_stack_aligned(CONFIG_BLOBLIST_SIZE); gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE); #endif diff --git a/common/log_syslog.c b/common/log_syslog.c new file mode 100644 index 0000000000..5e3e20e8a4 --- /dev/null +++ b/common/log_syslog.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Log to syslog. + * + * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> + */ + +#include <common.h> +#include <log.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define BUFFER_SIZE 480 + +static void append(char **buf, char *buf_end, const char *fmt, ...) +{ + va_list args; + size_t size = buf_end - *buf; + + va_start(args, fmt); + vsnprintf(*buf, size, fmt, args); + va_end(args); + *buf += strlen(*buf); +} + +static int log_syslog_emit(struct log_device *ldev, struct log_rec *rec) +{ + int ret; + int fmt = gd->log_fmt; + char msg[BUFFER_SIZE]; + char *msg_end = msg + BUFFER_SIZE; + char *ptr = msg; + char *iphdr; + char *log_msg; + int eth_hdr_size; + struct in_addr bcast_ip; + static int processing_msg; + unsigned int log_level; + char *log_hostname; + + /* Fend off messages from the network stack while writing a message */ + if (processing_msg) + return 0; + + processing_msg = 1; + + /* Setup packet buffers */ + net_init(); + /* Disable hardware and put it into the reset state */ + eth_halt(); + /* Set current device according to environment variables */ + eth_set_current(); + /* Get hardware ready for send and receive operations */ + ret = eth_init(); + if (ret < 0) { + eth_halt(); + goto out; + } + + memset(msg, 0, BUFFER_SIZE); + + /* Set ethernet header */ + eth_hdr_size = net_set_ether((uchar *)ptr, net_bcast_ethaddr, PROT_IP); + ptr += eth_hdr_size; + iphdr = ptr; + ptr += IP_UDP_HDR_SIZE; + log_msg = ptr; + + /* + * The syslog log levels defined in RFC 5424 match the U-Boot ones up to + * level 7 (debug). + */ + log_level = rec->level; + if (log_level > 7) + log_level = 7; + /* Leave high bits as 0 to write a 'kernel message' */ + + /* Write log message to buffer */ + append(&ptr, msg_end, "<%u>", log_level); + log_hostname = env_get("log_hostname"); + if (log_hostname) + append(&ptr, msg_end, "%s ", log_hostname); + append(&ptr, msg_end, "uboot: "); + if (fmt & (1 << LOGF_LEVEL)) + append(&ptr, msg_end, "%s.", + log_get_level_name(rec->level)); + if (fmt & (1 << LOGF_CAT)) + append(&ptr, msg_end, "%s,", + log_get_cat_name(rec->cat)); + if (fmt & (1 << LOGF_FILE)) + append(&ptr, msg_end, "%s:", rec->file); + if (fmt & (1 << LOGF_LINE)) + append(&ptr, msg_end, "%d-", rec->line); + if (fmt & (1 << LOGF_FUNC)) + append(&ptr, msg_end, "%s()", rec->func); + if (fmt & (1 << LOGF_MSG)) + append(&ptr, msg_end, "%s%s", + fmt != (1 << LOGF_MSG) ? " " : "", rec->msg); + /* Consider trailing 0x00 */ + ptr++; + + debug("log message: '%s'\n", log_msg); + + /* Broadcast message */ + bcast_ip.s_addr = 0xFFFFFFFFL; + net_set_udp_header((uchar *)iphdr, bcast_ip, 514, 514, ptr - log_msg); + net_send_packet((uchar *)msg, ptr - msg); + +out: + processing_msg = 0; + return ret; +} + +LOG_DRIVER(syslog) = { + .name = "syslog", + .emit = log_syslog_emit, +}; |