6.6 KiB
Log API
Introduction
The logging API is one of the most important of the entire kernel: it allow it to output informations with various level of importance and various sources.
Output methods
The logging API can log informations with two differents methods:
- serial output: use the serial API to output in real time all the provided informations. Can be disabled by setting it to true using the
sh_log_load_serial_setting(sh_bool is_disabled)function. The serial API being disabled, this method can also be disabled by that. - ring buffer output: use the ring buffer API to store all the provided informations into a ring buffer, mapped by the bootloader. Can be disabled by setting the
logging_ring_sizeboot configuration key to 0
The following functions provide way to set and get those settings:
void sh_log_load_serial_setting(sh_bool is_disabled): specify if serial log outputting should be disabledsh_bool sh_log_get_serial_setting()return the activation status of serial log outputting (SH_TRUEmean disabled)void sh_log_load_logging_ring_size(sh_uint16 pages_count): set logging ring sizesh_uint32 sh_log_get_logging_ring_size(): return logging ring sizesh_uint64 sh_log_get_total_bytes_written(): return total amount of bytes written inside logging ring
Output primitives
The following functions doesn't care about log level or log source and are specialized into specific data type:
void sh_log_byte(sh_uint8 byte): log a byte, basic entry point of the entire logging systemSH_STATUS sh_log_string(const char* str): log a table of characters Here are the numbers logging functions under their naming scheme:
sh_log_(u)int[8/16/32/64](_hex)
Basically, there is 12 functions that can output numbers, in various sizes (8 to 64 bits), signed or unsigned, in decimal or hexadecimal. The hexadecimal variant doesn't exist for signed integers. Examples: sh_log_uint8, sh_log_int16, sh_log_uint64_hex...
There are two mores functions:
SH_STATUS sh_log_uint64_hex_fixed(sh_uint64 n): log ash_uint64in hexadecimal without removing useless zeros, useful for logging pointers and addressSH_STATUS sh_log_double(double value): log a double encoded in decimal
Output channels and log level
The Shelter logging API provide higher level functions to output on specific log channels. Here are all the log channels:
SH_LOG_DEBUG: log level 0SH_LOG_LOG: log level 1SH_LOG_WARNING: log level 2SH_LOG_ERROR: log level 3SH_LOG_CRITICAL: log level 4SH_LOG_FATAL: log level 5SH_LOG_TEST: log level 6
Each log channel has a log level. The log level is set by the log_level boot configuration key. The log API will only output log messages with log level equal or higher to current log level. This restriction doesn't apply to log channel SH_LOG_TEST.
The sh_log_OUTPUT_TYPE type is used to store output type by log level. It's a wrapper of sh_uint8. The sh_log_output_type_valid(sh_log_OUTPUT_TYPE t) can be used to check if a log level is valid.
Two functions allow to set and get the current log level:
SH_STATUS sh_log_load_log_level(sh_uint8 log_level)sh_uint8 sh_log_get_log_level()
Output sources
The Shelter logging API also require a source in order to log informations. Here are all the possible sources:
SH_LOG_SOURCE_MAINSH_LOG_SOURCE_CONFSH_LOG_SOURCE_PAGESH_LOG_SOURCE_SLABSH_LOG_SOURCE_TESTSH_LOG_SOURCE_PEZSH_LOG_SOURCE_PBASH_LOG_SOURCE_HEAPSH_LOG_SOURCE_STD
The sh_log_OUTPUT_SOURCE type is used to store log source. It's a wrapper of sh_uint16. The sh_log_output_source_valid(sh_log_OUTPUT_SOURCE s) can be used to check if a log level is valid.
Output payloads
In order to compile all of those informations into one payload, the logging API provide this structure :
typedef struct {
sh_log_OUTPUT_TYPE output_type;
sh_log_OUTPUT_SOURCE output_source;
sh_tsc_TSC_VALUE tsc_value;
const char* message_pointer;
} sh_log_OUTPUT_PAYLOAD;
This allow to contain the message content, the output channel, the output source and the TSC value of any log message.
There is two functions that can manipulate output payloads:
SH_STATUS sh_log_payload(sh_log_OUTPUT_PAYLOAD *payload): output a payloadSH_STATUS sh_log_payload_format(sh_log_OUTPUT_PAYLOAD *payload,va_list args): format then output a payload, not directly callable, see below for more informations
Higher levels logging functions
The following functions will automatically create the payload depending on the parameters they receive.
Logging with automatic line break
These functions are named like this:
sh_log_[test/debug/log/warning/error/critical/fatal]
They all need two arguments in the following order (except sh_log_test which only need the first one):
const char* str: the text to logsh_log_OUTPUT_SOURCE source: the source of the log message
These functions will automatically add the \n characters at the end of each log message.
Logging without automatic line break
These functions are named like this:
sh_log_l[test/debug/log/warning/error/critical/fatal]
They all need two arguments in the following order (except sh_log_ltest which only need the first one):
const char* str: the text to logsh_log_OUTPUT_SOURCE source: the source of the log message
Logging with formating
In order to allow for formatting log messages, the log API provide functions named like this:
sh_log_f[test/debug/log/warning/error/critical/fatal]
They all need at least two arguments in the following order (except sh_log_ltest which only need the second one):
sh_log_OUTPUT_SOURCE source: the source of the log messageconst char* format: the format text- all the others argument after that are used as content for formatting the log message
All of these functions use sh_log_payload_format() under the hood which itself use SH_STATUS sh_log_format(const char* format,va_list args) to format log messages.
The format syntax is as follow:
%s: insert a string made ofchar, passed aschar*%d: insert a double%x: insert a integer that need to be provided as ash_uint64, format it as hexadecimal without removing useless zeros. Used to log addresses%c: insert achar%%: insert a%
There is also a specific syntax for formatting integers. It's start with the % symbol, then need a amount of bytes (can be 1, 2, 4 or 8) and a output format: u for unsigned decimal, s for signed decimal, U for unsigned decimal. Example: %1s output a sh_int8 in decimal, %2u output a sh_uint16 in decimal, %4U output a unsigned sh_uint32 in hexadecimal.