blob: fcd2e6812bc1528c0a06520f68215267134c8201 [file] [log] [blame]
Salman Nabi31edc202024-02-01 15:28:43 +00001Console Framework
2=================
3
4The TF-A console framework is used to register consoles for different boot states
5so that user's output can be displayed on physical consoles throughout the different
6boot stages. The framework also supports debug mode for general debugging purposes.
7
8The console framework supports a number of different UARTs, it is highly likely
9that the driver of the UART that is needed is already implemented. If not, a driver
10will need to be written for the new UART in TF-A. Current supported UARTs are:
11
12* Amlogic Meson
13* Arm PL011
14* Cadence CDNS
15* Coreboot CBMEM
16* Marvell A3700
17* NXP
18 * i.MX LPUART
19 * i.MX UART
20 * Linflex
21* Nvidia SPE
22* Qualcomm UARTDM
23* Renesas RCAR
24* STMicroelectronics STM32
25* Texas Instruments 16550
26
27 .. note::
28 The supported UART list is non-exhaustive. Check if the UART driver has
29 already been written before writing a new one.
30
31::
32
33 Console scopes and flags
34
35 Scope : Flag
36 BOOT : CONSOLE_FLAG_BOOT
37 RUNTIME : CONSOLE_FLAG_RUNTIME
38 CRASH : CONSOLE_FLAG_CRASH
39
40The console framework supports multiple consoles. Multiple instances of a UART
41can be registered at any given moment. Any registered console can have a single
42scope or multiple scopes. In single scope for example, setting three different
43consoles with each having BOOT, RUNTIME, and CRASH states respectively, the boot
44console will display only boot logs, the runtime console will display only the
45runtime output, while the crash console will be used to print the crash log in the
46event of a crash. Similarly, a console with all three scopes will display any and
47all output destined for BOOT, RUNTIME, or CRASH consoles.
48
49These multiple scopes can be useful in many ways, for example:
50
51* Having different consoles for Boot and Runtime messages
52* Having a single console for both Runtime and Boot messages
53* Having no runtime console at all and just having a single Boot console.
54* Having a separate console for crash reporting when debugging.
55
56.. Registering a console:
57
58Registering a console
59---------------------
60To register a console in TF-A check if the hardware (UART) that is going to be used
61is already defined, if not we will need to define it, for example, the **PL011**
62UART driver API is defined in ``include/drivers/arm/pl011.h``.
63
64A skeleton console driver (assembly) is provided in TF-A ``drivers/console/aarch64/
65skeleton_console.S``, this skeleton sets the rules for writing a new console_driver.
66Have a look at ``drivers/arm/pl011/aarch64/pl011_console.S`` for an actual
67implementation using this skeleton.
68
69Function : console_xxx_register
70~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71
72::
73
74 Argument : console_t *, ...
75 Return : int
76
77This ASM Function is used to initialize and register a console. The caller needs
78to pass an empty ``console_t`` struct which *MUST* be allocated in persistent
79memory (e.g. a global or static local variable, *NOT* on the stack).
80
81This function takes a ``console_t`` struct placed in x0 and additional
82arguments placed in x1 - x7. It returns x0 with either a 0 on failure or 1
83on success.
84
85See ``console_pl011_register`` ASM function for an implementation of this
86function.
87
88 .. note::
89 The ``xxx`` in the function name is replaced with the console driver
90 name, for example, ``console_xxx_register`` becomes
91 ``console_pl011_register`` in the driver for pl011.
92
93Function : console_xxx_putc
94~~~~~~~~~~~~~~~~~~~~~~~~~~~
95
96::
97
98 Argument : int, console_t *
99 Return : int
100
101This ASM function is used to send a character to the UART's Transmit FIFO. It takes
102two arguments, a character as int stored in w0, and the ``console_t`` struct pointer
103stored in x1. It returns w0 with either the character on successs or a negative
104value on error. In a crash context this function must only clobber x0 - x2, x16 - x17.
105
106See ``console_pl011_putc`` ASM function for an implementation.
107
108 .. note::
109 Avoid the direct use of this function for printing to the console, instead use
110 the ``debug.h`` print macros, such as: VERBOSE(...), INFO(...), WARN(...),
111 NOTICE(...) and ERROR(...).
112
113Function : console_xxx_getc
114~~~~~~~~~~~~~~~~~~~~~~~~~~~
115
116::
117
118 Argument : console_t *
119 Return : int
120
121This ASM function is used to read a character from the receive FIFO. It takes a pointer
122to the console_struct as an argument and returns a character on success or a negative
123value below -2 on failure. This function is dependent on the ``ENABLE_CONSOLE_GETC`` flag,
124which is optional and is left to the platform because there may be security implications.
125
126See ``console_pl011_getc`` ASM function for an implementation.
127
128Function : console_xxx_flush
129~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130
131::
132
133 Argument : console_t *
134 Return : void
135
136This ASM function flushes any characters, that are still in the Transmit FIFO but
137haven't been printed yet to the console. It takes a pointer to the console_struct
138but doesn't return any value. In a crash context this function must only clobber
139x0 - x5, x16 - x17.
140
141See ``console_pl011_flush`` ASM function for an implementation.
142
143Macro : finish_console_register xxx putc=1 getc=ENABLE_CONSOLE_GETC flush=1
144~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
145
146::
147
148 Callbacks
149 xxx : name of the console driver
150 putc : 0 for off, 1 to turn on putc function
151 getc : 0 for off, ENABLE_CONSOLE_GETC to turn on the getc function
152 flush : 0 for off, 1 to turn on flush function
153
154This assembly macro function is called by the ``console_xxx_register`` to
155encapsulate the common setup that has to be done at the end of a console
156driver's register function. It takes ``putc``, ``getc`` and ``flush`` macro
157arguments. It will register all of the driver's callbacks in the ``console_t``
158struct and initialize the ``flags`` field (by default consoles are enabled for
159"boot" and "crash" states, this can be changed after registration using the
160``console_set_scope`` function). This macro ends with a tail call that will
161include return to the caller.
162
163This macro requires ``console_t`` pointer in x0 and a valid return address in x30.
164
165See ``include/arch/aarch64/console_macros.S``.
166
167Registering a console using C
168-----------------------------
169
170A console can be implemented in pure C, which is much easier than using assembly.
171Currently there is no C template for implementing a console driver in C but it can
172easily be implemented using existing examples. See ``drivers/arm/dcc/dcc_console.c``
173for an implementation of a console driver in C.
174
175The assembly functions in `Registering a console`_ section can be written in C when
176implementing a console driver using C.
177
178 .. note::
179 A crash callback needs to be able to run without a stack. If crash mode
180 support is required then the console driver will need to be written in
181 Assembly (only the putc and flush functions are needed in a crash
182 context).
183
184Multi Console API
185-----------------
186
187TF-A uses the multi-console API to manage the registered console instances and the
188characters print queue. This can be found in ``drivers/console/multi_console.c``.
189
190The multi-console API stores all registered consoles in a struct list ``console_list``.
191Consoles can be removed from the console_list if no longer needed.
192
193Consoles are registered with BOOT and CRASH scopes by default. These scopes can be
194changed after registration using ``console_set_scope`` function, as per the platform
195requirement.
196
197This API also helps print characters to the specified consoles, characters can also
198be retrieved from the receive FIFO (this implementation is disabled by default but can
199be enabled if there is a need for it). The API can also help flush the transmit FIFO
200to get rid of any lingering characters from the queue when switching from secure world
201to the non-secure world.
202
203The following functions are defined in the multi_console API.
204
205Function : console_register()
206~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207
208::
209
210 Argument : console_t*
211 Return : int
212
213This function adds a console to the ``console_list`` declared in
214``include/drivers/console.h`` and makes sure that there is only one instance
215of a specific console in this list. This function is called by the
216``finish_console_register`` asm macro function, at the end of the console
217registration process.
218
219This function always return 1. If the console is already present in the
220``console_list`` it will return immediately with a value of 1, otherwise
221it will add the console to the ``console_list`` and then return 1.
222
223 .. note::
224 The ``console_list`` is a list of type ``console_t``, it is an **extern**
225 variable declared in ``include/drivers/console.h``.
226
227Function : console_unregister()
228~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229
230::
231
232 Argument : console_t*
233 Return : console_t* or NULL
234
235This function removes a console from the ``console_list``. It will return the
236removed console on success or a ``NULL`` character upon failure.
237
238Function : console_set_scope()
239~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
240
241::
242
243 Argument : console_t*, int
244 Return : void
245
246This function is used to set the scope of the registered console. A console
247can be registered with upto three states (called the scope). These states are
248
249* BOOT - set using the flag ``CONSOLE_FLAG_BOOT``
250* RUNTIME - set using the flag ``CONSOLE_FLAG_RUNTIME``
251* CRASH - set using the flag ``CONSOLE_FLAG_CRASH``
252
253It takes a pointer to the console and an int value (which is provided as the
254FLAG value) as its arguments. This function does not return anything.
255
256Function : console_switch_state()
257~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
258
259::
260
261 Argument : int
262 Return : void
263
264This function sets the console state (scope) for printing, i.e, TF-A will
265start sending all logs (INFO, WARNING, ERROR, NOTICE, VERBOSE) to the consoles
266that are registered with this new state (scope). For example, calling
267``console_switch_state(CONSOLE_FLAG_RUNTIME)``, TF-A will start sending all log
268messages to all consoles marked with the RUNTIME flag. BOOT is the default
269console state.
270
271This function takes a console state as the function's only argument. This function
272does not return a value.
273
274Function : console_putc()
275~~~~~~~~~~~~~~~~~~~~~~~~~
276
277::
278
279 Argument : int
280 Return : int
281
282Invoking this function sends a character to the ``console->putc`` (struct
283member) function of all consoles registered for the current scope, for example,
284BOOT logs will only be printed on consoles set with a BOOT scope. In the PL011
285implementation ``console->putc`` call points to the ``console_pl011_putc()``
286function.
287
288This function takes the int value of a character as an argument and returns the
289int value of the character back on success or a negative int value on error.
290
291 .. note::
292 Do not use this function in TF-A release builds, instead use the log
293 prefixes, for example, ``INFO("Print information here.")`` to print
294 messages on the active console.
295
296Function : console_getc()
297~~~~~~~~~~~~~~~~~~~~~~~~~
298
299::
300
301 Argument : void
302 Return : int
303
304This function is used to fetch a character from the receive FIFO that has
305not been printed to the console yet. This function is disabled by default for
306security reasons but can be enabled using the ``ENABLE_CONSOLE_GETC`` macro
307if there is a need for it.
308
309This function doesn't take any argument but returns a character as an int.
310
311Function : console_flush()
312~~~~~~~~~~~~~~~~~~~~~~~~~~
313
314::
315
316 Argument : void
317 Return : void
318
319This function flushes all the characters pending in the transmit FIFO of the
320active UART thus removing them from the print queue.
321
322This function has no arguments and do not return a value.
323
324Function : putchar()
325~~~~~~~~~~~~~~~~~~~~
326
327::
328
329 Argument : int
330 Return : int
331
332This function overrides the weak implementation of the putchar library. It is
333used to send a character to the ``console_putc()`` function to be printed to
334the active console.
335
336This function will either return the character on success or an **EOF** character
337otherwise.
338
339--------------
340
341*Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.*