seL4/include/machine/io.h
Axel Heider 4608941f38 debug: restructure kernel console handling
Remove the UART handling details from the top level I/O handling that
implements printf(). The architecture's I/O handling must define how
the debug channel is implemented and what special handling is
required. This allows separating UART and SBI debug output handling.

Signed-off-by: Axel Heider <axelheider@gmx.de>
2021-05-14 13:13:36 +10:00

128 lines
3.6 KiB
C

/*
* Copyright 2014, General Dynamics C4 Systems
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#pragma once
#include <config.h>
#ifdef CONFIG_DEBUG_BUILD
/* io for dumping capdl */
unsigned char kernel_getDebugChar(void);
#endif
#ifdef CONFIG_PRINTING
#include <arch/types.h>
#include <stdarg.h>
/* the actual output function */
void kernel_putDebugChar(unsigned char c);
/* This is the actual implementation of the kernel printing API. It must never
* be called directly from anywhere except the function defined in this file.
*/
int impl_kvprintf(const char *format, va_list ap);
int impl_ksnvprintf(char *str, word_t size, const char *format, va_list ap);
/*
*------------------------------------------------------------------------------
* Kernel printing API
*------------------------------------------------------------------------------
*/
/* Writes a character to the kernel output channel. This is used to implement
* the syscall SysDebugPutChar.
*/
static inline void kernel_putchar(
char c)
{
/* Write to target specific debug output channel. */
kernel_putDebugChar(c);
}
/* Writes a character to the active output channel. This is used by all code
* related to printf(). Contrary to the common signature of putchar(), there is
* no return value here.
*/
static inline void putchar(
char c)
{
/* Write to target specific debug output channel. Purposely, we do not call
* kernel_putchar() here, as the kernel printf() channel is semantically
* different from the syscall SysDebugPutChar channel. The unification
* of both channels happens at the lower layer eventually
*/
kernel_putDebugChar(c);
}
/* Writes the string and a trailing newline. There is no point to enforce a
* kernel_puts(), as this is just a wrapper for putchar() anyway.
*/
static inline int puts(
const char *str)
{
if (str) {
while (*str) {
putchar(*str++);
}
}
putchar('\n');
/* Standards define that a non-negative number is returned on success. */
return 0;
}
/* There should only be a kprintf() that all kernel code must use for printing,
* but for convenience we provide a printf() here.
*/
static inline __attribute__((format(printf, 1, 2))) int printf(
const char *format,
...)
{
va_list args;
va_start(args, format);
int ret = impl_kvprintf(format, args); /* will call putchar() eventually */
va_end(args);
return ret;
}
/* Provide the standard snprintf() for write formatted data into a buffer, which
* can then be printed or stored.
*/
static inline __attribute__((format(printf, 3, 4))) int snprintf(
char *buf,
word_t size,
const char *format,
...)
{
va_list args;
va_start(args, format);
int ret = impl_ksnvprintf(buf, size, format, args);
va_end(args);
return ret;
}
#else /* not CONFIG_PRINTING */
/* The verification runs on the output of the preprocessing stage of a release
* build configuration, CONFIG_PRINTING is not enabled there. We remove all
* calls to printf() completely from the code base, because neither printf() nor
* the usage of a variable argument list is supported by the verification
* toolchain. It would just reject the code if it encounters any unsupported
* things.
*/
#define printf(...) ((void)(0))
/* Seems there is no need to define out these functions, they are use by code
* that is active with CONFIG_PRINTING only.
*
* #define kernel_putchar(...) ((void)(0))
* #define putchar(...) ((void)(0))
* #define puts(...) ((void)(0))
* #define snprintf(...) ((void)(0))
*/
#endif /* [not] CONFIG_PRINTING */