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>
diff --git a/docs/design/console-framework.rst b/docs/design/console-framework.rst
new file mode 100644
index 0000000..fcd2e68
--- /dev/null
+++ b/docs/design/console-framework.rst
@@ -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.*
\ No newline at end of file
diff --git a/docs/design/index.rst b/docs/design/index.rst
index 17ef756..f0ca540 100644
--- a/docs/design/index.rst
+++ b/docs/design/index.rst
@@ -12,9 +12,10 @@
interrupt-framework-design
psci-pd-tree
reset-design
+ console-framework
trusted-board-boot
trusted-board-boot-build
--------------
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*