mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-24 13:55:56 +00:00
docs(console): updated console docs
Add documentation for the console framework on how to go about instantiating a new console and how to use these consoles in TF-A. This includes BOOT, RUNTIME and CRASH consoles. Change-Id: I746d38f69f1b035d2e85d2589646e7fd67cb9cc3 Signed-off-by: Salman Nabi <salman.nabi@arm.com>
This commit is contained in:
parent
0f38b9f87e
commit
31edc20dc4
3 changed files with 363 additions and 6 deletions
341
docs/design/console-framework.rst
Normal file
341
docs/design/console-framework.rst
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
Console Framework
|
||||||
|
=================
|
||||||
|
|
||||||
|
The TF-A console framework is used to register consoles for different boot states
|
||||||
|
so that user's output can be displayed on physical consoles throughout the different
|
||||||
|
boot stages. The framework also supports debug mode for general debugging purposes.
|
||||||
|
|
||||||
|
The console framework supports a number of different UARTs, it is highly likely
|
||||||
|
that the driver of the UART that is needed is already implemented. If not, a driver
|
||||||
|
will need to be written for the new UART in TF-A. Current supported UARTs are:
|
||||||
|
|
||||||
|
* Amlogic Meson
|
||||||
|
* Arm PL011
|
||||||
|
* Cadence CDNS
|
||||||
|
* Coreboot CBMEM
|
||||||
|
* Marvell A3700
|
||||||
|
* NXP
|
||||||
|
* i.MX LPUART
|
||||||
|
* i.MX UART
|
||||||
|
* Linflex
|
||||||
|
* Nvidia SPE
|
||||||
|
* Qualcomm UARTDM
|
||||||
|
* Renesas RCAR
|
||||||
|
* STMicroelectronics STM32
|
||||||
|
* Texas Instruments 16550
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The supported UART list is non-exhaustive. Check if the UART driver has
|
||||||
|
already been written before writing a new one.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Console scopes and flags
|
||||||
|
|
||||||
|
Scope : Flag
|
||||||
|
BOOT : CONSOLE_FLAG_BOOT
|
||||||
|
RUNTIME : CONSOLE_FLAG_RUNTIME
|
||||||
|
CRASH : CONSOLE_FLAG_CRASH
|
||||||
|
|
||||||
|
The console framework supports multiple consoles. Multiple instances of a UART
|
||||||
|
can be registered at any given moment. Any registered console can have a single
|
||||||
|
scope or multiple scopes. In single scope for example, setting three different
|
||||||
|
consoles with each having BOOT, RUNTIME, and CRASH states respectively, the boot
|
||||||
|
console will display only boot logs, the runtime console will display only the
|
||||||
|
runtime output, while the crash console will be used to print the crash log in the
|
||||||
|
event of a crash. Similarly, a console with all three scopes will display any and
|
||||||
|
all output destined for BOOT, RUNTIME, or CRASH consoles.
|
||||||
|
|
||||||
|
These multiple scopes can be useful in many ways, for example:
|
||||||
|
|
||||||
|
* Having different consoles for Boot and Runtime messages
|
||||||
|
* Having a single console for both Runtime and Boot messages
|
||||||
|
* Having no runtime console at all and just having a single Boot console.
|
||||||
|
* Having a separate console for crash reporting when debugging.
|
||||||
|
|
||||||
|
.. Registering a console:
|
||||||
|
|
||||||
|
Registering a console
|
||||||
|
---------------------
|
||||||
|
To register a console in TF-A check if the hardware (UART) that is going to be used
|
||||||
|
is already defined, if not we will need to define it, for example, the **PL011**
|
||||||
|
UART driver API is defined in ``include/drivers/arm/pl011.h``.
|
||||||
|
|
||||||
|
A skeleton console driver (assembly) is provided in TF-A ``drivers/console/aarch64/
|
||||||
|
skeleton_console.S``, this skeleton sets the rules for writing a new console_driver.
|
||||||
|
Have a look at ``drivers/arm/pl011/aarch64/pl011_console.S`` for an actual
|
||||||
|
implementation using this skeleton.
|
||||||
|
|
||||||
|
Function : console_xxx_register
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : console_t *, ...
|
||||||
|
Return : int
|
||||||
|
|
||||||
|
This ASM Function is used to initialize and register a console. The caller needs
|
||||||
|
to pass an empty ``console_t`` struct which *MUST* be allocated in persistent
|
||||||
|
memory (e.g. a global or static local variable, *NOT* on the stack).
|
||||||
|
|
||||||
|
This function takes a ``console_t`` struct placed in x0 and additional
|
||||||
|
arguments placed in x1 - x7. It returns x0 with either a 0 on failure or 1
|
||||||
|
on success.
|
||||||
|
|
||||||
|
See ``console_pl011_register`` ASM function for an implementation of this
|
||||||
|
function.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The ``xxx`` in the function name is replaced with the console driver
|
||||||
|
name, for example, ``console_xxx_register`` becomes
|
||||||
|
``console_pl011_register`` in the driver for pl011.
|
||||||
|
|
||||||
|
Function : console_xxx_putc
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : int, console_t *
|
||||||
|
Return : int
|
||||||
|
|
||||||
|
This ASM function is used to send a character to the UART's Transmit FIFO. It takes
|
||||||
|
two arguments, a character as int stored in w0, and the ``console_t`` struct pointer
|
||||||
|
stored in x1. It returns w0 with either the character on successs or a negative
|
||||||
|
value on error. In a crash context this function must only clobber x0 - x2, x16 - x17.
|
||||||
|
|
||||||
|
See ``console_pl011_putc`` ASM function for an implementation.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Avoid the direct use of this function for printing to the console, instead use
|
||||||
|
the ``debug.h`` print macros, such as: VERBOSE(...), INFO(...), WARN(...),
|
||||||
|
NOTICE(...) and ERROR(...).
|
||||||
|
|
||||||
|
Function : console_xxx_getc
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : console_t *
|
||||||
|
Return : int
|
||||||
|
|
||||||
|
This ASM function is used to read a character from the receive FIFO. It takes a pointer
|
||||||
|
to the console_struct as an argument and returns a character on success or a negative
|
||||||
|
value below -2 on failure. This function is dependent on the ``ENABLE_CONSOLE_GETC`` flag,
|
||||||
|
which is optional and is left to the platform because there may be security implications.
|
||||||
|
|
||||||
|
See ``console_pl011_getc`` ASM function for an implementation.
|
||||||
|
|
||||||
|
Function : console_xxx_flush
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : console_t *
|
||||||
|
Return : void
|
||||||
|
|
||||||
|
This ASM function flushes any characters, that are still in the Transmit FIFO but
|
||||||
|
haven't been printed yet to the console. It takes a pointer to the console_struct
|
||||||
|
but doesn't return any value. In a crash context this function must only clobber
|
||||||
|
x0 - x5, x16 - x17.
|
||||||
|
|
||||||
|
See ``console_pl011_flush`` ASM function for an implementation.
|
||||||
|
|
||||||
|
Macro : finish_console_register xxx putc=1 getc=ENABLE_CONSOLE_GETC flush=1
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Callbacks
|
||||||
|
xxx : name of the console driver
|
||||||
|
putc : 0 for off, 1 to turn on putc function
|
||||||
|
getc : 0 for off, ENABLE_CONSOLE_GETC to turn on the getc function
|
||||||
|
flush : 0 for off, 1 to turn on flush function
|
||||||
|
|
||||||
|
This assembly macro function is called by the ``console_xxx_register`` to
|
||||||
|
encapsulate the common setup that has to be done at the end of a console
|
||||||
|
driver's register function. It takes ``putc``, ``getc`` and ``flush`` macro
|
||||||
|
arguments. It will register all of the driver's callbacks in the ``console_t``
|
||||||
|
struct and initialize the ``flags`` field (by default consoles are enabled for
|
||||||
|
"boot" and "crash" states, this can be changed after registration using the
|
||||||
|
``console_set_scope`` function). This macro ends with a tail call that will
|
||||||
|
include return to the caller.
|
||||||
|
|
||||||
|
This macro requires ``console_t`` pointer in x0 and a valid return address in x30.
|
||||||
|
|
||||||
|
See ``include/arch/aarch64/console_macros.S``.
|
||||||
|
|
||||||
|
Registering a console using C
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
A console can be implemented in pure C, which is much easier than using assembly.
|
||||||
|
Currently there is no C template for implementing a console driver in C but it can
|
||||||
|
easily be implemented using existing examples. See ``drivers/arm/dcc/dcc_console.c``
|
||||||
|
for an implementation of a console driver in C.
|
||||||
|
|
||||||
|
The assembly functions in `Registering a console`_ section can be written in C when
|
||||||
|
implementing a console driver using C.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
A crash callback needs to be able to run without a stack. If crash mode
|
||||||
|
support is required then the console driver will need to be written in
|
||||||
|
Assembly (only the putc and flush functions are needed in a crash
|
||||||
|
context).
|
||||||
|
|
||||||
|
Multi Console API
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
TF-A uses the multi-console API to manage the registered console instances and the
|
||||||
|
characters print queue. This can be found in ``drivers/console/multi_console.c``.
|
||||||
|
|
||||||
|
The multi-console API stores all registered consoles in a struct list ``console_list``.
|
||||||
|
Consoles can be removed from the console_list if no longer needed.
|
||||||
|
|
||||||
|
Consoles are registered with BOOT and CRASH scopes by default. These scopes can be
|
||||||
|
changed after registration using ``console_set_scope`` function, as per the platform
|
||||||
|
requirement.
|
||||||
|
|
||||||
|
This API also helps print characters to the specified consoles, characters can also
|
||||||
|
be retrieved from the receive FIFO (this implementation is disabled by default but can
|
||||||
|
be enabled if there is a need for it). The API can also help flush the transmit FIFO
|
||||||
|
to get rid of any lingering characters from the queue when switching from secure world
|
||||||
|
to the non-secure world.
|
||||||
|
|
||||||
|
The following functions are defined in the multi_console API.
|
||||||
|
|
||||||
|
Function : console_register()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : console_t*
|
||||||
|
Return : int
|
||||||
|
|
||||||
|
This function adds a console to the ``console_list`` declared in
|
||||||
|
``include/drivers/console.h`` and makes sure that there is only one instance
|
||||||
|
of a specific console in this list. This function is called by the
|
||||||
|
``finish_console_register`` asm macro function, at the end of the console
|
||||||
|
registration process.
|
||||||
|
|
||||||
|
This function always return 1. If the console is already present in the
|
||||||
|
``console_list`` it will return immediately with a value of 1, otherwise
|
||||||
|
it will add the console to the ``console_list`` and then return 1.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The ``console_list`` is a list of type ``console_t``, it is an **extern**
|
||||||
|
variable declared in ``include/drivers/console.h``.
|
||||||
|
|
||||||
|
Function : console_unregister()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : console_t*
|
||||||
|
Return : console_t* or NULL
|
||||||
|
|
||||||
|
This function removes a console from the ``console_list``. It will return the
|
||||||
|
removed console on success or a ``NULL`` character upon failure.
|
||||||
|
|
||||||
|
Function : console_set_scope()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : console_t*, int
|
||||||
|
Return : void
|
||||||
|
|
||||||
|
This function is used to set the scope of the registered console. A console
|
||||||
|
can be registered with upto three states (called the scope). These states are
|
||||||
|
|
||||||
|
* BOOT - set using the flag ``CONSOLE_FLAG_BOOT``
|
||||||
|
* RUNTIME - set using the flag ``CONSOLE_FLAG_RUNTIME``
|
||||||
|
* CRASH - set using the flag ``CONSOLE_FLAG_CRASH``
|
||||||
|
|
||||||
|
It takes a pointer to the console and an int value (which is provided as the
|
||||||
|
FLAG value) as its arguments. This function does not return anything.
|
||||||
|
|
||||||
|
Function : console_switch_state()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : int
|
||||||
|
Return : void
|
||||||
|
|
||||||
|
This function sets the console state (scope) for printing, i.e, TF-A will
|
||||||
|
start sending all logs (INFO, WARNING, ERROR, NOTICE, VERBOSE) to the consoles
|
||||||
|
that are registered with this new state (scope). For example, calling
|
||||||
|
``console_switch_state(CONSOLE_FLAG_RUNTIME)``, TF-A will start sending all log
|
||||||
|
messages to all consoles marked with the RUNTIME flag. BOOT is the default
|
||||||
|
console state.
|
||||||
|
|
||||||
|
This function takes a console state as the function's only argument. This function
|
||||||
|
does not return a value.
|
||||||
|
|
||||||
|
Function : console_putc()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : int
|
||||||
|
Return : int
|
||||||
|
|
||||||
|
Invoking this function sends a character to the ``console->putc`` (struct
|
||||||
|
member) function of all consoles registered for the current scope, for example,
|
||||||
|
BOOT logs will only be printed on consoles set with a BOOT scope. In the PL011
|
||||||
|
implementation ``console->putc`` call points to the ``console_pl011_putc()``
|
||||||
|
function.
|
||||||
|
|
||||||
|
This function takes the int value of a character as an argument and returns the
|
||||||
|
int value of the character back on success or a negative int value on error.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Do not use this function in TF-A release builds, instead use the log
|
||||||
|
prefixes, for example, ``INFO("Print information here.")`` to print
|
||||||
|
messages on the active console.
|
||||||
|
|
||||||
|
Function : console_getc()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : void
|
||||||
|
Return : int
|
||||||
|
|
||||||
|
This function is used to fetch a character from the receive FIFO that has
|
||||||
|
not been printed to the console yet. This function is disabled by default for
|
||||||
|
security reasons but can be enabled using the ``ENABLE_CONSOLE_GETC`` macro
|
||||||
|
if there is a need for it.
|
||||||
|
|
||||||
|
This function doesn't take any argument but returns a character as an int.
|
||||||
|
|
||||||
|
Function : console_flush()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : void
|
||||||
|
Return : void
|
||||||
|
|
||||||
|
This function flushes all the characters pending in the transmit FIFO of the
|
||||||
|
active UART thus removing them from the print queue.
|
||||||
|
|
||||||
|
This function has no arguments and do not return a value.
|
||||||
|
|
||||||
|
Function : putchar()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : int
|
||||||
|
Return : int
|
||||||
|
|
||||||
|
This function overrides the weak implementation of the putchar library. It is
|
||||||
|
used to send a character to the ``console_putc()`` function to be printed to
|
||||||
|
the active console.
|
||||||
|
|
||||||
|
This function will either return the character on success or an **EOF** character
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
--------------
|
||||||
|
|
||||||
|
*Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.*
|
|
@ -12,9 +12,10 @@ System Design
|
||||||
interrupt-framework-design
|
interrupt-framework-design
|
||||||
psci-pd-tree
|
psci-pd-tree
|
||||||
reset-design
|
reset-design
|
||||||
|
console-framework
|
||||||
trusted-board-boot
|
trusted-board-boot
|
||||||
trusted-board-boot-build
|
trusted-board-boot-build
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
*Copyright (c) 2019, Arm Limited. All rights reserved.*
|
*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
|
||||||
|
|
|
@ -2220,10 +2220,10 @@ Function : bl31_plat_runtime_setup() [optional]
|
||||||
Argument : void
|
Argument : void
|
||||||
Return : void
|
Return : void
|
||||||
|
|
||||||
The purpose of this function is allow the platform to perform any BL31 runtime
|
The purpose of this function is to allow the platform to perform any BL31 runtime
|
||||||
setup just prior to BL31 exit during cold boot. The default weak
|
setup just prior to BL31 exit during cold boot. The default weak implementation
|
||||||
implementation of this function will invoke ``console_switch_state()`` to switch
|
of this function is empty. Any platform that needs to perform additional runtime
|
||||||
console output to consoles marked for use in the ``runtime`` state.
|
setup, before BL31 exits, will need to override this function.
|
||||||
|
|
||||||
Function : bl31_plat_get_next_image_ep_info() [mandatory]
|
Function : bl31_plat_get_next_image_ep_info() [mandatory]
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -3296,6 +3296,21 @@ Register* (``GICD_IGROUPRn``) and *Interrupt Group Modifier Register*
|
||||||
(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured
|
(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured
|
||||||
as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt.
|
as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt.
|
||||||
|
|
||||||
|
Registering a console
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Platforms will need to implement the TF-A console framework to register and use
|
||||||
|
a console for visual data output in TF-A. These can be used for data output during
|
||||||
|
the different stages of the firmware boot process and also for debugging purposes.
|
||||||
|
|
||||||
|
The console framework can be used to output data on to a console using a number of
|
||||||
|
TF-A supported UARTs. Multiple consoles can be registered at the same time with
|
||||||
|
different output scopes (BOOT, RUNTIME, CRASH) so that data can be displayed on
|
||||||
|
their respective consoles without unnecessary cluttering of a single console.
|
||||||
|
|
||||||
|
Information for registering a console can be found in the :ref:`Console Framework` section
|
||||||
|
of the :ref:`System Design` documentation.
|
||||||
|
|
||||||
Common helper functions
|
Common helper functions
|
||||||
-----------------------
|
-----------------------
|
||||||
Function : elx_panic()
|
Function : elx_panic()
|
||||||
|
@ -3700,7 +3715,7 @@ to :ref:`Measured Boot Design` for more details.
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
*Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.*
|
*Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.*
|
||||||
|
|
||||||
.. _PSCI: https://developer.arm.com/documentation/den0022/latest/
|
.. _PSCI: https://developer.arm.com/documentation/den0022/latest/
|
||||||
.. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html
|
.. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html
|
||||||
|
|
Loading…
Add table
Reference in a new issue