mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-15 00:54:22 +00:00
Merge pull request #1193 from jwerner-chromium/JW_coreboot
New console API and coreboot support [v4]
This commit is contained in:
commit
040f1e6987
33 changed files with 1590 additions and 334 deletions
2
Makefile
2
Makefile
|
@ -488,6 +488,7 @@ $(eval $(call assert_boolean,GENERATE_COT))
|
|||
$(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
|
||||
$(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
|
||||
$(eval $(call assert_boolean,LOAD_IMAGE_V2))
|
||||
$(eval $(call assert_boolean,MULTI_CONSOLE_API))
|
||||
$(eval $(call assert_boolean,NS_TIMER_SWITCH))
|
||||
$(eval $(call assert_boolean,PL011_GENERIC_UART))
|
||||
$(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
|
||||
|
@ -530,6 +531,7 @@ $(eval $(call add_define,GICV2_G0_FOR_EL3))
|
|||
$(eval $(call add_define,HW_ASSISTED_COHERENCY))
|
||||
$(eval $(call add_define,LOAD_IMAGE_V2))
|
||||
$(eval $(call add_define,LOG_LEVEL))
|
||||
$(eval $(call add_define,MULTI_CONSOLE_API))
|
||||
$(eval $(call add_define,NS_TIMER_SWITCH))
|
||||
$(eval $(call add_define,PL011_GENERIC_UART))
|
||||
$(eval $(call add_define,PLAT_${PLAT}))
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
#include <cpu_data.h>
|
||||
#include <plat_macros.S>
|
||||
#include <platform_def.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
.globl report_unhandled_exception
|
||||
.globl report_unhandled_interrupt
|
||||
.globl el3_panic
|
||||
|
||||
#if CRASH_REPORTING
|
||||
#define REG_SIZE 0x8
|
||||
|
||||
/* ------------------------------------------------------
|
||||
* The below section deals with dumping the system state
|
||||
|
@ -92,7 +92,7 @@ test_size_list:
|
|||
mov x6, x4
|
||||
adr x4, print_spacer
|
||||
bl asm_print_str
|
||||
ldr x4, [x7], #REG_SIZE
|
||||
ldr x4, [x7], #REGSZ
|
||||
bl asm_print_hex
|
||||
bl print_newline
|
||||
b test_size_list
|
||||
|
@ -114,9 +114,9 @@ func str_in_crash_buf_print
|
|||
/* restore the crash buf address in x0 */
|
||||
mrs x0, tpidr_el3
|
||||
stp x8, x9, [x0]
|
||||
stp x10, x11, [x0, #REG_SIZE * 2]
|
||||
stp x12, x13, [x0, #REG_SIZE * 4]
|
||||
stp x14, x15, [x0, #REG_SIZE * 6]
|
||||
stp x10, x11, [x0, #REGSZ * 2]
|
||||
stp x12, x13, [x0, #REGSZ * 4]
|
||||
stp x14, x15, [x0, #REGSZ * 6]
|
||||
b size_controlled_print
|
||||
endfunc str_in_crash_buf_print
|
||||
|
||||
|
@ -136,7 +136,7 @@ endfunc str_in_crash_buf_print
|
|||
add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
|
||||
/* Store crash buffer address in tpidr_el3 */
|
||||
msr tpidr_el3, x0
|
||||
str x1, [x0, #REG_SIZE]
|
||||
str x1, [x0, #REGSZ]
|
||||
mov x1, sp
|
||||
str x1, [x0]
|
||||
.endm
|
||||
|
@ -214,9 +214,9 @@ func do_crash_reporting
|
|||
/* Retrieve the crash buf from tpidr_el3 */
|
||||
mrs x0, tpidr_el3
|
||||
/* Store x2 - x6, x30 in the crash buffer */
|
||||
stp x2, x3, [x0, #REG_SIZE * 2]
|
||||
stp x4, x5, [x0, #REG_SIZE * 4]
|
||||
stp x6, x30, [x0, #REG_SIZE * 6]
|
||||
stp x2, x3, [x0, #REGSZ * 2]
|
||||
stp x4, x5, [x0, #REGSZ * 4]
|
||||
stp x6, x30, [x0, #REGSZ * 6]
|
||||
/* Initialize the crash console */
|
||||
bl plat_crash_console_init
|
||||
/* Verify the console is initialized */
|
||||
|
@ -227,13 +227,13 @@ func do_crash_reporting
|
|||
/* load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* report x30 first from the crash buf */
|
||||
ldr x4, [x0, #REG_SIZE * 7]
|
||||
ldr x4, [x0, #REGSZ * 7]
|
||||
bl asm_print_hex
|
||||
bl print_newline
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* Now mov x7 into crash buf */
|
||||
str x7, [x0, #REG_SIZE * 7]
|
||||
str x7, [x0, #REGSZ * 7]
|
||||
|
||||
/* Report x0 - x29 values stored in crash buf*/
|
||||
/* Store the ascii list pointer in x6 */
|
||||
|
@ -246,15 +246,15 @@ func do_crash_reporting
|
|||
mrs x0, tpidr_el3
|
||||
/* Store the rest of gp regs and print */
|
||||
stp x16, x17, [x0]
|
||||
stp x18, x19, [x0, #REG_SIZE * 2]
|
||||
stp x20, x21, [x0, #REG_SIZE * 4]
|
||||
stp x22, x23, [x0, #REG_SIZE * 6]
|
||||
stp x18, x19, [x0, #REGSZ * 2]
|
||||
stp x20, x21, [x0, #REGSZ * 4]
|
||||
stp x22, x23, [x0, #REGSZ * 6]
|
||||
bl size_controlled_print
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
stp x24, x25, [x0]
|
||||
stp x26, x27, [x0, #REG_SIZE * 2]
|
||||
stp x28, x29, [x0, #REG_SIZE * 4]
|
||||
stp x26, x27, [x0, #REGSZ * 2]
|
||||
stp x28, x29, [x0, #REGSZ * 4]
|
||||
bl size_controlled_print
|
||||
|
||||
/* Print the el3 sys registers */
|
||||
|
|
|
@ -1929,12 +1929,8 @@ Function : bl31\_plat\_runtime\_setup() [optional]
|
|||
|
||||
The purpose of this function is allow the platform to perform any BL31 runtime
|
||||
setup just prior to BL31 exit during cold boot. The default weak
|
||||
implementation of this function will invoke ``console_uninit()`` which will
|
||||
suppress any BL31 runtime logs.
|
||||
|
||||
In ARM Standard platforms, this function will initialize the BL31 runtime
|
||||
console which will cause all further BL31 logs to be output to the
|
||||
runtime console.
|
||||
implementation of this function will invoke ``console_switch_state()`` to switch
|
||||
console output to consoles marked for use in the ``runtime`` state.
|
||||
|
||||
Function : bl31\_get\_next\_image\_info() [mandatory]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -2702,14 +2698,20 @@ as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt.
|
|||
Crash Reporting mechanism (in BL31)
|
||||
-----------------------------------
|
||||
|
||||
BL31 implements a crash reporting mechanism which prints the various registers
|
||||
of the CPU to enable quick crash analysis and debugging. It requires that a
|
||||
console is designated as the crash console by the platform which will be used to
|
||||
print the register dump.
|
||||
NOTE: This section assumes that your platform is enabling the MULTI_CONSOLE_API
|
||||
flag in its platform.mk. Not using this flag is deprecated for new platforms.
|
||||
|
||||
The following functions must be implemented by the platform if it wants crash
|
||||
reporting mechanism in BL31. The functions are implemented in assembly so that
|
||||
they can be invoked without a C Runtime stack.
|
||||
BL31 implements a crash reporting mechanism which prints the various registers
|
||||
of the CPU to enable quick crash analysis and debugging. By default, the
|
||||
definitions in ``plat/common/aarch64/platform\_helpers.S`` will cause the crash
|
||||
output to be routed over the normal console infrastructure and get printed on
|
||||
consoles configured to output in crash state. ``console_set_scope()`` can be
|
||||
used to control whether a console is used for crash output.
|
||||
|
||||
In some cases (such as debugging very early crashes that happen before the
|
||||
normal boot console can be set up), platforms may want to control crash output
|
||||
more explicitly. For these, the following functions can be overridden by
|
||||
platform code. They are executed outside of a C environment and without a stack.
|
||||
|
||||
Function : plat\_crash\_console\_init
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -2720,9 +2722,30 @@ Function : plat\_crash\_console\_init
|
|||
Return : int
|
||||
|
||||
This API is used by the crash reporting mechanism to initialize the crash
|
||||
console. It must only use the general purpose registers x0 to x4 to do the
|
||||
console. It must only use the general purpose registers x0 through x7 to do the
|
||||
initialization and returns 1 on success.
|
||||
|
||||
If you are trying to debug crashes before the console driver would normally get
|
||||
registered, you can use this to register a driver from assembly with hardcoded
|
||||
parameters. For example, you could register the 16550 driver like this:
|
||||
|
||||
::
|
||||
|
||||
.section .data.crash_console /* Reserve space for console structure */
|
||||
crash_console:
|
||||
.zero 6 * 8 /* console_16550_t has 6 8-byte words */
|
||||
func plat_crash_console_init
|
||||
ldr x0, =YOUR_16550_BASE_ADDR
|
||||
ldr x1, =YOUR_16550_SRCCLK_IN_HZ
|
||||
ldr x2, =YOUR_16550_TARGET_BAUD_RATE
|
||||
adrp x3, crash_console
|
||||
add x3, x3, :lo12:crash_console
|
||||
b console_16550_register /* tail call, returns 1 on success */
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
If you're trying to debug crashes in BL1, you can call the console_xxx_core_init
|
||||
function exported by some console drivers from here.
|
||||
|
||||
Function : plat\_crash\_console\_putc
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -2736,6 +2759,12 @@ designated crash console. It must only use general purpose registers x1 and
|
|||
x2 to do its work. The parameter and the return value are in general purpose
|
||||
register x0.
|
||||
|
||||
If you have registered a normal console driver in ``plat_crash_console_init``,
|
||||
you can keep the default implementation here (which calls ``console_putc()``).
|
||||
|
||||
If you're trying to debug crashes in BL1, you can call the console_xxx_core_putc
|
||||
function exported by some console drivers from here.
|
||||
|
||||
Function : plat\_crash\_console\_flush
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -2746,9 +2775,15 @@ Function : plat\_crash\_console\_flush
|
|||
|
||||
This API is used by the crash reporting mechanism to force write of all buffered
|
||||
data on the designated crash console. It should only use general purpose
|
||||
registers x0 and x1 to do its work. The return value is 0 on successful
|
||||
registers x0 through x5 to do its work. The return value is 0 on successful
|
||||
completion; otherwise the return value is -1.
|
||||
|
||||
If you have registered a normal console driver in ``plat_crash_console_init``,
|
||||
you can keep the default implementation here (which calls ``console_flush()``).
|
||||
|
||||
If you're trying to debug crashes in BL1, you can call the console_xx_core_flush
|
||||
function exported by some console drivers from here.
|
||||
|
||||
Build flags
|
||||
-----------
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <pl011.h>
|
||||
|
||||
/*
|
||||
|
@ -13,15 +14,21 @@
|
|||
*/
|
||||
#include "../../../console/aarch64/console.S"
|
||||
|
||||
/*
|
||||
* "core" functions are low-level implementations that don't require
|
||||
* writable memory and are thus safe to call in BL1 crash context.
|
||||
*/
|
||||
.globl console_pl011_core_init
|
||||
.globl console_pl011_core_putc
|
||||
.globl console_pl011_core_getc
|
||||
.globl console_pl011_core_flush
|
||||
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
|
||||
.globl console_pl011_putc
|
||||
.globl console_pl011_getc
|
||||
.globl console_pl011_flush
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_core_init(uintptr_t base_addr,
|
||||
* int console_pl011_core_init(uintptr_t base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. This
|
||||
|
@ -34,7 +41,7 @@
|
|||
* Clobber list : x1, x2, x3, x4
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_core_init
|
||||
func console_pl011_core_init
|
||||
/* Check the input base address */
|
||||
cbz x0, core_init_fail
|
||||
#if !PL011_GENERIC_UART
|
||||
|
@ -71,10 +78,54 @@ func console_core_init
|
|||
core_init_fail:
|
||||
mov w0, wzr
|
||||
ret
|
||||
endfunc console_core_init
|
||||
endfunc console_pl011_core_init
|
||||
|
||||
#if MULTI_CONSOLE_API
|
||||
.globl console_pl011_register
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_pl011_register(console_pl011_t *console,
|
||||
uintptr_t base, uint32_t clk, uint32_t baud)
|
||||
* Function to initialize and register a new PL011
|
||||
* console. Storage passed in for the console struct
|
||||
* *must* be persistent (i.e. not from the stack).
|
||||
* In: x0 - UART register base address
|
||||
* w1 - UART clock in Hz
|
||||
* w2 - Baud rate
|
||||
* x3 - pointer to empty console_pl011_t struct
|
||||
* Out: return 1 on success, 0 on error
|
||||
* Clobber list : x0, x1, x2, x6, x7, x14
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_pl011_register
|
||||
mov x7, x30
|
||||
mov x6, x3
|
||||
cbz x6, register_fail
|
||||
str x0, [x6, #CONSOLE_T_PL011_BASE]
|
||||
|
||||
bl console_pl011_core_init
|
||||
cbz x0, register_fail
|
||||
|
||||
mov x0, x6
|
||||
mov x30, x7
|
||||
finish_console_register pl011
|
||||
|
||||
register_fail:
|
||||
ret x7
|
||||
endfunc console_pl011_register
|
||||
#else
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
.equ console_core_init,console_pl011_core_init
|
||||
.equ console_core_putc,console_pl011_core_putc
|
||||
.equ console_core_getc,console_pl011_core_getc
|
||||
.equ console_core_flush,console_pl011_core_flush
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_core_putc(int c, uintptr_t base_addr)
|
||||
* int console_pl011_core_putc(int c, uintptr_t base_addr)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
|
@ -83,9 +134,12 @@ endfunc console_core_init
|
|||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_core_putc
|
||||
/* Check the input parameter */
|
||||
cbz x1, putc_error
|
||||
func console_pl011_core_putc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x1, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Prepend '\r' to '\n' */
|
||||
cmp w0, #0xA
|
||||
b.ne 2f
|
||||
|
@ -101,36 +155,75 @@ func console_core_putc
|
|||
tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
|
||||
str w0, [x1, #UARTDR]
|
||||
ret
|
||||
putc_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_putc
|
||||
endfunc console_pl011_core_putc
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_pl011_putc(int c, console_pl011_t *console)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
* x1 - pointer to console_t structure
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_pl011_putc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x1, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr x1, [x1, #CONSOLE_T_PL011_BASE]
|
||||
b console_pl011_core_putc
|
||||
endfunc console_pl011_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_getc(uintptr_t base_addr)
|
||||
* int console_pl011_core_getc(uintptr_t base_addr)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* or -1 if no character is available.
|
||||
* In : x0 - console base address
|
||||
* Out: w0 - character if available, else -1
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_getc
|
||||
cbz x0, getc_error
|
||||
1:
|
||||
func console_pl011_core_getc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Check if the receive FIFO is empty */
|
||||
ldr w1, [x0, #UARTFR]
|
||||
tbnz w1, #PL011_UARTFR_RXFE_BIT, 1b
|
||||
tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char
|
||||
ldr w1, [x0, #UARTDR]
|
||||
mov w0, w1
|
||||
ret
|
||||
getc_error:
|
||||
mov w0, #-1
|
||||
no_char:
|
||||
mov w0, #ERROR_NO_PENDING_CHAR
|
||||
ret
|
||||
endfunc console_core_getc
|
||||
endfunc console_pl011_core_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_flush(uintptr_t base_addr)
|
||||
* int console_pl011_getc(console_pl011_t *console)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 if no character is available.
|
||||
* In : x0 - pointer to console_t structure
|
||||
* Out: w0 - character if available, else -1
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_pl011_getc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr x0, [x0, #CONSOLE_T_PL011_BASE]
|
||||
b console_pl011_core_getc
|
||||
endfunc console_pl011_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_pl011_core_flush(uintptr_t base_addr)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* In : x0 - console base address
|
||||
|
@ -138,9 +231,11 @@ endfunc console_core_getc
|
|||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_flush
|
||||
cbz x0, flush_error
|
||||
|
||||
func console_pl011_core_flush
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
1:
|
||||
/* Loop until the transmit FIFO is empty */
|
||||
ldr w1, [x0, #UARTFR]
|
||||
|
@ -148,7 +243,22 @@ func console_core_flush
|
|||
|
||||
mov w0, #0
|
||||
ret
|
||||
flush_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_flush
|
||||
endfunc console_pl011_core_flush
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_pl011_flush(console_pl011_t *console)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* In : x0 - pointer to console_t structure
|
||||
* Out : return -1 on error else return 0.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_pl011_flush
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr x0, [x0, #CONSOLE_T_PL011_BASE]
|
||||
b console_pl011_core_flush
|
||||
endfunc console_pl011_flush
|
||||
|
|
|
@ -5,16 +5,22 @@
|
|||
*/
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <cadence/cdns_uart.h>
|
||||
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
/*
|
||||
* "core" functions are low-level implementations that don't require
|
||||
* writable memory and are thus safe to call in BL1 crash context.
|
||||
*/
|
||||
.globl console_cdns_core_init
|
||||
.globl console_cdns_core_putc
|
||||
.globl console_cdns_core_getc
|
||||
|
||||
.globl console_cdns_putc
|
||||
.globl console_cdns_getc
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_core_init(unsigned long base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* int console_cdns_core_init(uintptr_t base_addr)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. This
|
||||
* function will be accessed by console_init and
|
||||
|
@ -23,18 +29,13 @@
|
|||
* the HW (baud, ...) and only enable the trans-
|
||||
* mitter and receiver here.
|
||||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* Out: return 1 on success else 0 on error
|
||||
* Clobber list : x1, x2, x3
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_core_init
|
||||
func console_cdns_core_init
|
||||
/* Check the input base address */
|
||||
cbz x0, core_init_fail
|
||||
/* Check baud rate and uart clock for sanity */
|
||||
cbz w1, core_init_fail
|
||||
cbz w2, core_init_fail
|
||||
|
||||
/* RX/TX enabled & reset */
|
||||
mov w3, #(R_UART_CR_TX_EN | R_UART_CR_RX_EN | R_UART_CR_TXRST | R_UART_CR_RXRST)
|
||||
|
@ -45,10 +46,51 @@ func console_core_init
|
|||
core_init_fail:
|
||||
mov w0, wzr
|
||||
ret
|
||||
endfunc console_core_init
|
||||
endfunc console_cdns_core_init
|
||||
|
||||
#if MULTI_CONSOLE_API
|
||||
.globl console_cdns_register
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_cdns_register(console_cdns_t *console,
|
||||
uintptr_t base, uint32_t clk, uint32_t baud)
|
||||
* Function to initialize and register a new CDNS
|
||||
* console. Storage passed in for the console struct
|
||||
* *must* be persistent (i.e. not from the stack).
|
||||
* In: x0 - UART register base address
|
||||
* x1 - pointer to empty console_cdns_t struct
|
||||
* Out: return 1 on success, 0 on error
|
||||
* Clobber list : x0, x1, x2, x6, x7, x14
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_cdns_register
|
||||
mov x7, x30
|
||||
mov x6, x1
|
||||
cbz x6, register_fail
|
||||
str x0, [x6, #CONSOLE_T_CDNS_BASE]
|
||||
|
||||
bl console_cdns_core_init
|
||||
cbz x0, register_fail
|
||||
|
||||
mov x0, x6
|
||||
mov x30, v7
|
||||
finish_console_register cdns
|
||||
|
||||
register_fail:
|
||||
ret x7
|
||||
endfunc console_cdns_register
|
||||
#else
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
.equ console_core_init,console_cdns_core_init
|
||||
.equ console_core_putc,console_cdns_core_putc
|
||||
.equ console_core_getc,console_cdns_core_getc
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_core_putc(int c, unsigned long base_addr)
|
||||
* int console_cdns_core_putc(int c, uintptr_t base_addr)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
|
@ -57,9 +99,12 @@ endfunc console_core_init
|
|||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_core_putc
|
||||
/* Check the input parameter */
|
||||
cbz x1, putc_error
|
||||
func console_cdns_core_putc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x1, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Prepend '\r' to '\n' */
|
||||
cmp w0, #0xA
|
||||
b.ne 2f
|
||||
|
@ -75,36 +120,76 @@ func console_core_putc
|
|||
tbnz w2, #UART_SR_INTR_TFUL_BIT, 2b
|
||||
str w0, [x1, #R_UART_TX]
|
||||
ret
|
||||
putc_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_putc
|
||||
endfunc console_cdns_core_putc
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_cdns_putc(int c, console_cdns_t *cdns)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
* x1 - pointer to console_t structure
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_cdns_putc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x1, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr x1, [x1, #CONSOLE_T_CDNS_BASE]
|
||||
b console_cdns_core_putc
|
||||
endfunc console_cdns_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_getc(unsigned long base_addr)
|
||||
* int console_cdns_core_getc(uintptr_t base_addr)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* or -1 if no character is available.
|
||||
* In : x0 - console base address
|
||||
* Out: w0 - character if available, else -1
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_getc
|
||||
cbz x0, getc_error
|
||||
1:
|
||||
func console_cdns_core_getc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Check if the receive FIFO is empty */
|
||||
ldr w1, [x0, #R_UART_SR]
|
||||
tbnz w1, #UART_SR_INTR_REMPTY_BIT, 1b
|
||||
tbnz w1, #UART_SR_INTR_REMPTY_BIT, no_char
|
||||
ldr w1, [x0, #R_UART_RX]
|
||||
mov w0, w1
|
||||
ret
|
||||
getc_error:
|
||||
mov w0, #-1
|
||||
no_char:
|
||||
mov w0, #ERROR_NO_PENDING_CHAR
|
||||
ret
|
||||
endfunc console_core_getc
|
||||
endfunc console_cdns_core_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_cdns_getc(console_cdns_t *console)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 if no character is available.
|
||||
* In : x0 - pointer to console_t structure
|
||||
* Out: w0 - character if available, else -1
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_cdns_getc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr x0, [x0, #CONSOLE_T_CDNS_BASE]
|
||||
b console_cdns_core_getc
|
||||
endfunc console_cdns_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_flush(uintptr_t base_addr)
|
||||
* DEPRECATED: Not used with MULTI_CONSOLE_API!
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* In : x0 - console base address
|
||||
|
|
|
@ -1,105 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <asm_macros.S>
|
||||
|
||||
.globl console_init
|
||||
.globl console_uninit
|
||||
.globl console_putc
|
||||
.globl console_getc
|
||||
.globl console_flush
|
||||
|
||||
/*
|
||||
* The console base is in the data section and not in .bss
|
||||
* even though it is zero-init. In particular, this allows
|
||||
* the console functions to start using this variable before
|
||||
* the runtime memory is initialized for images which do not
|
||||
* need to copy the .data section from ROM to RAM.
|
||||
*/
|
||||
.section .data.console_base ; .align 3
|
||||
console_base: .quad 0x0
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_init(uintptr_t base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. It saves
|
||||
* the console base to the data section.
|
||||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* out: return 1 on success else 0 on error
|
||||
* Clobber list : x1 - x4
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_init
|
||||
/* Check the input base address */
|
||||
cbz x0, init_fail
|
||||
adrp x3, console_base
|
||||
str x0, [x3, :lo12:console_base]
|
||||
b console_core_init
|
||||
init_fail:
|
||||
ret
|
||||
endfunc console_init
|
||||
|
||||
/* -----------------------------------------------
|
||||
* void console_uninit(void)
|
||||
* Function to finish the use of console driver.
|
||||
* It sets the console_base as NULL so that any
|
||||
* further invocation of `console_putc` or
|
||||
* `console_getc` APIs would return error.
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_uninit
|
||||
mov x0, #0
|
||||
adrp x3, console_base
|
||||
str x0, [x3, :lo12:console_base]
|
||||
ret
|
||||
endfunc console_uninit
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_putc(int c)
|
||||
* Function to output a character over the
|
||||
* console. It returns the character printed on
|
||||
* success or -1 on error.
|
||||
* In : x0 - character to be printed
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_putc
|
||||
adrp x2, console_base
|
||||
ldr x1, [x2, :lo12:console_base]
|
||||
b console_core_putc
|
||||
endfunc console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_getc(void)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_getc
|
||||
adrp x1, console_base
|
||||
ldr x0, [x1, :lo12:console_base]
|
||||
b console_core_getc
|
||||
endfunc console_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_flush(void)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output. It returns 0
|
||||
* upon successful completion, otherwise it
|
||||
* returns -1.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_flush
|
||||
adrp x1, console_base
|
||||
ldr x0, [x1, :lo12:console_base]
|
||||
b console_core_flush
|
||||
endfunc console_flush
|
||||
#if MULTI_CONSOLE_API
|
||||
#include "multi_console.S"
|
||||
#else
|
||||
#include "deprecated_console.S"
|
||||
#endif
|
||||
|
|
110
drivers/console/aarch64/deprecated_console.S
Normal file
110
drivers/console/aarch64/deprecated_console.S
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <asm_macros.S>
|
||||
|
||||
/*
|
||||
* This is the common console core code for the deprecated single-console API.
|
||||
* New platforms should set MULTI_CONSOLE_API=1 and not use this file.
|
||||
*/
|
||||
|
||||
.globl console_init
|
||||
.globl console_uninit
|
||||
.globl console_putc
|
||||
.globl console_getc
|
||||
.globl console_flush
|
||||
|
||||
/*
|
||||
* The console base is in the data section and not in .bss
|
||||
* even though it is zero-init. In particular, this allows
|
||||
* the console functions to start using this variable before
|
||||
* the runtime memory is initialized for images which do not
|
||||
* need to copy the .data section from ROM to RAM.
|
||||
*/
|
||||
.section .data.console_base ; .align 3
|
||||
console_base: .quad 0x0
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_init(uintptr_t base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. It saves
|
||||
* the console base to the data section.
|
||||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* out: return 1 on success else 0 on error
|
||||
* Clobber list : x1 - x4
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_init
|
||||
/* Check the input base address */
|
||||
cbz x0, init_fail
|
||||
adrp x3, console_base
|
||||
str x0, [x3, :lo12:console_base]
|
||||
b console_core_init
|
||||
init_fail:
|
||||
ret
|
||||
endfunc console_init
|
||||
|
||||
/* -----------------------------------------------
|
||||
* void console_uninit(void)
|
||||
* Function to finish the use of console driver.
|
||||
* It sets the console_base as NULL so that any
|
||||
* further invocation of `console_putc` or
|
||||
* `console_getc` APIs would return error.
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_uninit
|
||||
mov x0, #0
|
||||
adrp x3, console_base
|
||||
str x0, [x3, :lo12:console_base]
|
||||
ret
|
||||
endfunc console_uninit
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_putc(int c)
|
||||
* Function to output a character over the
|
||||
* console. It returns the character printed on
|
||||
* success or -1 on error.
|
||||
* In : x0 - character to be printed
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_putc
|
||||
adrp x2, console_base
|
||||
ldr x1, [x2, :lo12:console_base]
|
||||
b console_core_putc
|
||||
endfunc console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_getc(void)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_getc
|
||||
adrp x1, console_base
|
||||
ldr x0, [x1, :lo12:console_base]
|
||||
b console_core_getc
|
||||
endfunc console_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_flush(void)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output. It returns 0
|
||||
* upon successful completion, otherwise it
|
||||
* returns -1.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_flush
|
||||
adrp x1, console_base
|
||||
ldr x0, [x1, :lo12:console_base]
|
||||
b console_core_flush
|
||||
endfunc console_flush
|
260
drivers/console/aarch64/multi_console.S
Normal file
260
drivers/console/aarch64/multi_console.S
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <console.h>
|
||||
|
||||
.globl console_register
|
||||
.globl console_unregister
|
||||
.globl console_set_scope
|
||||
.globl console_switch_state
|
||||
.globl console_putc
|
||||
.globl console_getc
|
||||
.globl console_flush
|
||||
|
||||
/*
|
||||
* The console list pointer is in the data section and not in
|
||||
* .bss even though it is zero-init. In particular, this allows
|
||||
* the console functions to start using this variable before
|
||||
* the runtime memory is initialized for images which do not
|
||||
* need to copy the .data section from ROM to RAM.
|
||||
*/
|
||||
.section .data.console_list ; .align 3
|
||||
console_list: .quad 0x0
|
||||
.section .data.console_state ; .align 0
|
||||
console_state: .byte CONSOLE_FLAG_BOOT
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_register(console_t *console)
|
||||
* Function to insert a new console structure into
|
||||
* the console list. Should usually be called by
|
||||
* console_<driver>_register implementations. The
|
||||
* data structure passed will be taken over by the
|
||||
* console framework and *MUST* be allocated in
|
||||
* persistent memory (e.g. the data section).
|
||||
* In : x0 - address of console_t structure
|
||||
* Out: x0 - Always 1 (for easier tail calling)
|
||||
* Clobber list: x0, x1, x14
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_register
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
adrp x1, __STACKS_START__
|
||||
add x1, x1, :lo12:__STACKS_START__
|
||||
cmp x0, x1
|
||||
b.lo not_on_stack
|
||||
adrp x1, __STACKS_END__
|
||||
add x1, x1, :lo12:__STACKS_END__
|
||||
cmp x0, x1
|
||||
ASM_ASSERT(hs)
|
||||
not_on_stack:
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
adrp x14, console_list
|
||||
ldr x1, [x14, :lo12:console_list] /* X1 = first struct in list */
|
||||
str x0, [x14, :lo12:console_list] /* list head = new console */
|
||||
str x1, [x0, #CONSOLE_T_NEXT] /* new console next ptr = X1 */
|
||||
mov x0, #1
|
||||
ret
|
||||
endfunc console_register
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_unregister(console_t *console)
|
||||
* Function to find a specific console in the list
|
||||
* of currently active consoles and remove it.
|
||||
* In: x0 - address of console_t struct to remove
|
||||
* Out: x0 - removed address, or NULL if not found
|
||||
* Clobber list: x0, x1, x14
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_unregister
|
||||
adrp x14, console_list
|
||||
add x14, x14, :lo12:console_list /* X14 = ptr to first struct */
|
||||
ldr x1, [x14] /* X1 = first struct */
|
||||
|
||||
unregister_loop:
|
||||
cbz x1, unregister_not_found
|
||||
cmp x0, x1
|
||||
b.eq unregister_found
|
||||
ldr x14, [x14] /* X14 = next ptr of struct */
|
||||
ldr x1, [x14] /* X1 = next struct */
|
||||
b unregister_loop
|
||||
|
||||
unregister_found:
|
||||
ldr x1, [x1] /* X1 = next struct */
|
||||
str x1, [x14] /* prev->next = cur->next */
|
||||
ret
|
||||
|
||||
unregister_not_found:
|
||||
mov x0, #0 /* return NULL if not found */
|
||||
ret
|
||||
endfunc console_unregister
|
||||
|
||||
/* -----------------------------------------------
|
||||
* void console_switch_state(unsigned int new_state)
|
||||
* Function to switch the current console state.
|
||||
* The console state determines which of the
|
||||
* registered consoles are actually used at a time.
|
||||
* In : w0 - global console state to move to
|
||||
* Clobber list: x0, x1
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_switch_state
|
||||
adrp x1, console_state
|
||||
strb w0, [x1, :lo12:console_state]
|
||||
ret
|
||||
endfunc console_switch_state
|
||||
|
||||
/* -----------------------------------------------
|
||||
* void console_set_scope(console_t *console,
|
||||
* unsigned int scope)
|
||||
* Function to update the states that a given console
|
||||
* may be active in.
|
||||
* In : x0 - pointer to console_t struct
|
||||
* : w1 - new active state mask
|
||||
* Clobber list: x0, x1, x2
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_set_scope
|
||||
#if ENABLE_ASSERTIONS
|
||||
tst w1, #~CONSOLE_FLAG_SCOPE_MASK
|
||||
ASM_ASSERT(eq)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr w2, [x0, #CONSOLE_T_FLAGS]
|
||||
and w2, w2, #~CONSOLE_FLAG_SCOPE_MASK
|
||||
orr w2, w2, w1
|
||||
str w2, [x0, #CONSOLE_T_FLAGS]
|
||||
ret
|
||||
endfunc console_set_scope
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_putc(int c)
|
||||
* Function to output a character. Calls all
|
||||
* active console's putc() handlers in succession.
|
||||
* In : x0 - character to be printed
|
||||
* Out: x0 - printed character on success, or < 0
|
||||
if at least one console had an error
|
||||
* Clobber list : x0, x1, x2, x12, x13, x14, x15
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_putc
|
||||
mov x15, x30
|
||||
mov w13, #ERROR_NO_VALID_CONSOLE /* W13 = current return value */
|
||||
mov w12, w0 /* W12 = character to print */
|
||||
adrp x14, console_list
|
||||
ldr x14, [x14, :lo12:console_list] /* X14 = first console struct */
|
||||
|
||||
putc_loop:
|
||||
cbz x14, putc_done
|
||||
adrp x1, console_state
|
||||
ldrb w1, [x1, :lo12:console_state]
|
||||
ldr x2, [x14, #CONSOLE_T_FLAGS]
|
||||
tst w1, w2
|
||||
b.eq putc_continue
|
||||
ldr x2, [x14, #CONSOLE_T_PUTC]
|
||||
cbz x2, putc_continue
|
||||
mov w0, w12
|
||||
mov x1, x14
|
||||
blr x2
|
||||
cmp w13, #ERROR_NO_VALID_CONSOLE /* update W13 if it's NOVALID */
|
||||
ccmp w0, #0, #0x8, ne /* else update it if W0 < 0 */
|
||||
csel w13, w0, w13, lt
|
||||
putc_continue:
|
||||
ldr x14, [x14] /* X14 = next struct */
|
||||
b putc_loop
|
||||
|
||||
putc_done:
|
||||
mov w0, w13
|
||||
ret x15
|
||||
endfunc console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_getc(void)
|
||||
* Function to get a character from any console.
|
||||
* Keeps looping through all consoles' getc()
|
||||
* handlers until one of them returns a
|
||||
* character, then stops iterating and returns
|
||||
* that character to the caller. Will stop looping
|
||||
* if all active consoles report real errors
|
||||
* (other than just not having a char available).
|
||||
* Out : x0 - read character, or < 0 on error
|
||||
* Clobber list : x0, x1, x13, x14, x15
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_getc
|
||||
mov x15, x30
|
||||
getc_try_again:
|
||||
mov w13, #ERROR_NO_VALID_CONSOLE /* W13 = current return value */
|
||||
adrp x14, console_list
|
||||
ldr x14, [x14, :lo12:console_list] /* X14 = first console struct */
|
||||
cbnz x14, getc_loop
|
||||
mov w0, w13 /* If no consoles registered */
|
||||
ret x15 /* return immediately. */
|
||||
|
||||
getc_loop:
|
||||
adrp x0, console_state
|
||||
ldrb w0, [x0, :lo12:console_state]
|
||||
ldr x1, [x14, #CONSOLE_T_FLAGS]
|
||||
tst w0, w1
|
||||
b.eq getc_continue
|
||||
ldr x1, [x14, #CONSOLE_T_GETC]
|
||||
cbz x1, getc_continue
|
||||
mov x0, x14
|
||||
blr x1
|
||||
cmp w0, #0 /* if X0 >= 0: return */
|
||||
b.ge getc_found
|
||||
cmp w13, #ERROR_NO_PENDING_CHAR /* may update W13 (NOCHAR has */
|
||||
csel w13, w13, w0, eq /* precedence vs real errors) */
|
||||
getc_continue:
|
||||
ldr x14, [x14] /* X14 = next struct */
|
||||
cbnz x14, getc_loop
|
||||
cmp w13, #ERROR_NO_PENDING_CHAR /* Keep scanning if at least */
|
||||
b.eq getc_try_again /* one console returns NOCHAR */
|
||||
mov w0, w13
|
||||
|
||||
getc_found:
|
||||
ret x15
|
||||
endfunc console_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_flush(void)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output. Calls all
|
||||
* console's flush() handlers in succession.
|
||||
* Out: x0 - 0 on success, < 0 if at least one error
|
||||
* Clobber list : x0, x1, x2, x3, x4, x5, x13, x14, x15
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_flush
|
||||
mov x15, x30
|
||||
mov w13, #ERROR_NO_VALID_CONSOLE /* W13 = current return value */
|
||||
adrp x14, console_list
|
||||
ldr x14, [x14, :lo12:console_list] /* X14 = first console struct */
|
||||
|
||||
flush_loop:
|
||||
cbz x14, flush_done
|
||||
adrp x1, console_state
|
||||
ldrb w1, [x1, :lo12:console_state]
|
||||
ldr x2, [x14, #CONSOLE_T_FLAGS]
|
||||
tst w1, w2
|
||||
b.eq flush_continue
|
||||
ldr x1, [x14, #CONSOLE_T_FLUSH]
|
||||
cbz x1, flush_continue
|
||||
mov x0, x14
|
||||
blr x1
|
||||
cmp w13, #ERROR_NO_VALID_CONSOLE /* update W13 if it's NOVALID */
|
||||
ccmp w0, #0, #0x8, ne /* else update it if W0 < 0 */
|
||||
csel w13, w0, w13, lt
|
||||
flush_continue:
|
||||
ldr x14, [x14] /* X14 = next struct */
|
||||
b flush_loop
|
||||
|
||||
flush_done:
|
||||
mov w0, w13
|
||||
ret x15
|
||||
endfunc console_flush
|
|
@ -4,99 +4,171 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <asm_macros.S>
|
||||
#include <console_macros.S>
|
||||
|
||||
/*
|
||||
* This file contains a skeleton console implementation that can
|
||||
* be used as basis for a real console implementation by platforms
|
||||
* that do not contain PL011 hardware.
|
||||
* This file contains a skeleton console driver that can be used as
|
||||
* basis for a real console driver. Console drivers in Trusted Firmware
|
||||
* can be instantiated multiple times. Each instance is described by a
|
||||
* separate console_t structure which must be registered with the common
|
||||
* console framework via console_register(). Console drivers should
|
||||
* define a console_xxx_register() function that initializes a new
|
||||
* console_t structure passed in from the caller and registers it after
|
||||
* initializing the console hardware. Drivers may define their own
|
||||
* structures extending console_t to store private driver information.
|
||||
* Console drivers *MUST* take care that the console callbacks they
|
||||
* implement only change registers allowed in the clobber lists defined
|
||||
* in this file. (Note that in addition to the explicit clobber lists,
|
||||
* any function may always clobber the intra-procedure-call registers
|
||||
* X16 and X17, but may never depend on them retaining their values
|
||||
* across any function call.)
|
||||
* Platforms using drivers based on this template need to enable
|
||||
* MULTI_CONSOLE_API := 1 in their platform.mk.
|
||||
*/
|
||||
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
.globl console_xxx_register
|
||||
.globl console_xxx_putc
|
||||
.globl console_xxx_getc
|
||||
.globl console_xxx_flush
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_core_init(uintptr_t base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. This
|
||||
* function will be accessed by console_init and
|
||||
* crash reporting.
|
||||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* Out: return 1 on success else 0 on error
|
||||
* Clobber list : x1, x2
|
||||
* int console_xxx_register(console_xxx_t *console,
|
||||
* ...additional parameters as desired...)
|
||||
* Function to initialize and register the console.
|
||||
* The caller needs to pass an empty console_xxx_t
|
||||
* structure in which *MUST* be allocated in
|
||||
* persistent memory (e.g. a global or static local
|
||||
* variable, *NOT* on the stack).
|
||||
* In : x0 - pointer to empty console_t structure
|
||||
* x1 through x7: additional parameters as desired
|
||||
* Out: x0 - 1 on success, 0 on error
|
||||
* Clobber list : x0 - x7
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_core_init
|
||||
/* Check the input base address */
|
||||
cbz x0, core_init_fail
|
||||
/* Check baud rate and uart clock for sanity */
|
||||
cbz w1, core_init_fail
|
||||
cbz w2, core_init_fail
|
||||
/* Insert implementation here */
|
||||
mov w0, #1
|
||||
func console_xxx_register
|
||||
/*
|
||||
* Store parameters (e.g. hardware base address) in driver-specific
|
||||
* console_xxx_t structure field if they will need to be retrieved
|
||||
* by later console callback (e.g. putc).
|
||||
* Example:
|
||||
*/
|
||||
str x1, [x0, #CONSOLE_T_XXX_BASE]
|
||||
str x2, [x0, #CONSOLE_T_XXX_SOME_OTHER_VALUE]
|
||||
|
||||
/*
|
||||
* Initialize console hardware, using x1 - x7 parameters as needed.
|
||||
* Keep console_t pointer in x0 for later.
|
||||
*/
|
||||
|
||||
/* Macro to finish up registration and return (needs valid x0 + x30). */
|
||||
finish_console_register xxx
|
||||
|
||||
/* Jump here if hardware init fails or parameters are invalid. */
|
||||
register_fail:
|
||||
mov w0, #0
|
||||
ret
|
||||
core_init_fail:
|
||||
mov w0, wzr
|
||||
ret
|
||||
endfunc console_core_init
|
||||
endfunc console_xxx_register
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_core_putc(int c, uintptr_t base_addr)
|
||||
* int console_xxx_putc(int c, console_xxx_t *console)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
* x1 - console base address
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x2
|
||||
* x1 - pointer to console_t struct
|
||||
* Out: w0 - printed character on success, < 0 on error.
|
||||
* Clobber list : x0, x1, x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_core_putc
|
||||
/* Check the input parameter */
|
||||
cbz x1, putc_error
|
||||
/* Insert implementation here */
|
||||
func console_xxx_putc
|
||||
/*
|
||||
* Retrieve values we need (e.g. hardware base address) from
|
||||
* console_xxx_t structure pointed to by x1.
|
||||
* Example:
|
||||
*/
|
||||
ldr x1, [x1, #CONSOLE_T_XXX_BASE]
|
||||
|
||||
/*
|
||||
* Write w0 to hardware.
|
||||
*/
|
||||
|
||||
ret
|
||||
|
||||
/* Jump here if output fails for any reason. */
|
||||
putc_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_putc
|
||||
endfunc console_xxx_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_getc(uintptr_t base_addr)
|
||||
* int console_xxx_getc(console_xxx_t *console)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* In : x0 - console base address
|
||||
* Even though console_getc() is blocking, this
|
||||
* callback has to be non-blocking and always
|
||||
* return immediately to allow polling multiple
|
||||
* drivers concurrently.
|
||||
* Returns the character grabbed on success,
|
||||
* ERROR_NO_PENDING_CHAR if no character was
|
||||
* available at this time, or any value
|
||||
* between -2 and -127 if there was an error.
|
||||
* In : x0 - pointer to console_t struct
|
||||
* Out: w0 - character on success,
|
||||
* ERROR_NO_PENDING_CHAR if no char,
|
||||
* < -1 on error
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_getc
|
||||
cbz x0, getc_error
|
||||
/* Insert implementation here */
|
||||
func console_xxx_getc
|
||||
/*
|
||||
* Retrieve values we need (e.g. hardware base address) from
|
||||
* console_xxx_t structure pointed to by x0.
|
||||
* Example:
|
||||
*/
|
||||
ldr x1, [x0, #CONSOLE_T_XXX_BASE]
|
||||
|
||||
/*
|
||||
* Try to read character into w0 from hardware.
|
||||
*/
|
||||
|
||||
ret
|
||||
|
||||
/* Jump here if there is no character available at this time. */
|
||||
getc_no_char:
|
||||
mov w0, #ERROR_NO_PENDING_CHAR
|
||||
ret
|
||||
|
||||
/* Jump here if there was any hardware error. */
|
||||
getc_error:
|
||||
mov w0, #-1
|
||||
mov w0, #-2 /* may pick error codes between -2 and -127 */
|
||||
ret
|
||||
endfunc console_core_getc
|
||||
endfunc console_xxx_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_flush(uintptr_t base_addr)
|
||||
* int console_xxx_flush(console_xxx_t *console)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* In : x0 - console base address
|
||||
* Out : return -1 on error else return 0.
|
||||
* Clobber list : x0, x1
|
||||
* In : x0 - pointer to console_xxx_t struct
|
||||
* Out: w0 - 0 on success, < 0 on error
|
||||
* Clobber list : x0, x1, x2, x3, x4, x5
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_flush
|
||||
cbz x0, flush_error
|
||||
/* Insert implementation here */
|
||||
func console_xxx_flush
|
||||
/*
|
||||
* Retrieve values we need (e.g. hardware base address) from
|
||||
* console_xxx_t structure pointed to by x0.
|
||||
* Example:
|
||||
*/
|
||||
ldr x1, [x0, #CONSOLE_T_XXX_BASE]
|
||||
|
||||
/*
|
||||
* Flush all remaining output from hardware FIFOs. Do not return until
|
||||
* all data has been flushed or there was an unrecoverable error.
|
||||
*/
|
||||
|
||||
mov w0, #0
|
||||
ret
|
||||
|
||||
/* Jump here if an unrecoverable error has been encountered. */
|
||||
flush_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_flush
|
||||
endfunc console_xxx_flush
|
||||
|
|
101
drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
Normal file
101
drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <cbmem_console.h>
|
||||
#include <console_macros.S>
|
||||
|
||||
/*
|
||||
* This driver implements access to coreboot's in-memory console
|
||||
* (CBMEM console). For the original implementation, see
|
||||
* <coreboot>/src/lib/cbmem_console.c.
|
||||
*/
|
||||
|
||||
.globl console_cbmc_register
|
||||
.globl console_cbmc_putc
|
||||
.globl console_cbmc_flush
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_cbmc_register(console_cbmc_t *console,
|
||||
* uintptr_t base)
|
||||
* Registers a new CBMEM console instance. Reads
|
||||
* the size field from the buffer header structure
|
||||
* and stores it in our console_cbmc_t struct, so
|
||||
* that we keep the size in secure memory where we
|
||||
* can trust it. A malicious EL1 could manipulate
|
||||
* the console buffer (including the header), so we
|
||||
* must not trust its contents after boot.
|
||||
* In: x0 - CBMEM console base address
|
||||
* x1 - pointer to empty console_cbmc_t struct
|
||||
* Out: x0 - 1 to indicate success
|
||||
* Clobber list: x0, x1, x2, x7
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_cbmc_register
|
||||
str x0, [x1, #CONSOLE_T_CBMC_BASE]
|
||||
ldr w2, [x0]
|
||||
str w2, [x1, #CONSOLE_T_CBMC_SIZE]
|
||||
mov x0, x1
|
||||
finish_console_register cbmc
|
||||
endfunc console_cbmc_register
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_cbmc_puts(int c, console_cbmc_t *console)
|
||||
* Writes a character to the CBMEM console buffer,
|
||||
* including overflow handling of the cursor field.
|
||||
* The character must be preserved in x0.
|
||||
* In: x0 - character to be stored
|
||||
* x1 - pointer to console_cbmc_t struct
|
||||
* Clobber list: x1, x2, x16, x17
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_cbmc_putc
|
||||
ldr w2, [x1, #CONSOLE_T_CBMC_SIZE]
|
||||
ldr x1, [x1, #CONSOLE_T_CBMC_BASE]
|
||||
add x1, x1, #8 /* keep address of body in x1 */
|
||||
|
||||
ldr w16, [x1, #-4] /* load cursor (one u32 before body) */
|
||||
and w17, w16, #0xf0000000 /* keep flags part in w17 */
|
||||
and w16, w16, #0x0fffffff /* keep actual cursor part in w16 */
|
||||
|
||||
cmp w16, w2 /* sanity check that cursor < size */
|
||||
b.lo putc_within_bounds
|
||||
mov w0, #-1 /* cursor >= size must be malicious */
|
||||
ret /* so return error, don't write char */
|
||||
|
||||
putc_within_bounds:
|
||||
strb w0, [x1, w16, uxtw] /* body[cursor] = character */
|
||||
add w16, w16, #1 /* cursor++ */
|
||||
cmp w16, w2 /* if cursor < size... */
|
||||
b.lo putc_write_back /* ...skip overflow handling */
|
||||
|
||||
mov w16, #0 /* on overflow, set cursor back to 0 */
|
||||
orr w17, w17, #(1 << 31) /* and set overflow flag */
|
||||
|
||||
putc_write_back:
|
||||
orr w16, w16, w17 /* merge cursor and flags back */
|
||||
str w16, [x1, #-4] /* write back cursor to memory */
|
||||
ret
|
||||
endfunc console_cbmc_putc
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_cbmc_flush(console_cbmc_t *console)
|
||||
* Flushes the CBMEM console by flushing the
|
||||
* console buffer from the CPU's data cache.
|
||||
* In: x0 - pointer to console_cbmc_t struct
|
||||
* Out: x0 - 0 for success
|
||||
* Clobber list: x0, x1, x2, x3, x5
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_cbmc_flush
|
||||
mov x5, x30
|
||||
ldr x1, [x0, #CONSOLE_T_CBMC_SIZE]
|
||||
ldr x0, [x0, #CONSOLE_T_CBMC_BASE]
|
||||
add x1, x1, #8 /* add size of console header */
|
||||
bl clean_dcache_range /* (clobbers x2 and x3) */
|
||||
mov x0, #0
|
||||
ret x5
|
||||
endfunc console_cbmc_flush
|
|
@ -6,15 +6,24 @@
|
|||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <console_macros.S>
|
||||
#include <uart_16550.h>
|
||||
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
/*
|
||||
* "core" functions are low-level implementations that don't require
|
||||
* writable memory and are thus safe to call in BL1 crash context.
|
||||
*/
|
||||
.globl console_16550_core_init
|
||||
.globl console_16550_core_putc
|
||||
.globl console_16550_core_getc
|
||||
|
||||
.globl console_16550_putc
|
||||
.globl console_16550_getc
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_core_init(unsigned long base_addr,
|
||||
* int console_16550_core_init(uintptr_t base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. This
|
||||
|
@ -23,11 +32,11 @@
|
|||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* Out: return 1 on success
|
||||
* Out: return 1 on success, 0 on error
|
||||
* Clobber list : x1, x2, x3
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_core_init
|
||||
func console_16550_core_init
|
||||
/* Check the input base address */
|
||||
cbz x0, init_fail
|
||||
/* Check baud rate and uart clock for sanity */
|
||||
|
@ -63,12 +72,57 @@ func console_core_init
|
|||
mov w3, #3
|
||||
str w3, [x0, #UARTMCR]
|
||||
mov w0, #1
|
||||
init_fail:
|
||||
ret
|
||||
endfunc console_core_init
|
||||
init_fail:
|
||||
mov w0, #0
|
||||
ret
|
||||
endfunc console_16550_core_init
|
||||
|
||||
#if MULTI_CONSOLE_API
|
||||
.globl console_16550_register
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_16550_register(console_16550_t *console,
|
||||
uintptr_t base, uint32_t clk, uint32_t baud)
|
||||
* Function to initialize and register a new 16550
|
||||
* console. Storage passed in for the console struct
|
||||
* *must* be persistent (i.e. not from the stack).
|
||||
* In: x0 - UART register base address
|
||||
* w1 - UART clock in Hz
|
||||
* w2 - Baud rate
|
||||
* x3 - pointer to empty console_16550_t struct
|
||||
* Out: return 1 on success, 0 on error
|
||||
* Clobber list : x0, x1, x2, x6, x7, x14
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_16550_register
|
||||
mov x7, x30
|
||||
mov x6, x3
|
||||
cbz x6, register_fail
|
||||
str x0, [x6, #CONSOLE_T_16550_BASE]
|
||||
|
||||
bl console_16550_core_init
|
||||
cbz x0, register_fail
|
||||
|
||||
mov x0, x6
|
||||
mov x30, x7
|
||||
finish_console_register 16550
|
||||
|
||||
register_fail:
|
||||
ret x7
|
||||
endfunc console_16550_register
|
||||
#else
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
.equ console_core_init,console_16550_core_init
|
||||
.equ console_core_putc,console_16550_core_putc
|
||||
.equ console_core_getc,console_16550_core_getc
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_core_putc(int c, unsigned int base_addr)
|
||||
* int console_16550_core_putc(int c, uintptr_t base_addr)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
|
@ -77,9 +131,11 @@ endfunc console_core_init
|
|||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_core_putc
|
||||
/* Check the input parameter */
|
||||
cbz x1, putc_error
|
||||
func console_16550_core_putc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x1, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Prepend '\r' to '\n' */
|
||||
cmp w0, #0xA
|
||||
|
@ -99,34 +155,75 @@ func console_core_putc
|
|||
b.ne 2b
|
||||
str w0, [x1, #UARTTX]
|
||||
ret
|
||||
putc_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_putc
|
||||
endfunc console_16550_core_putc
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_16550_putc(int c, console_16550_t *console)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
* x1 - pointer to console_t structure
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_16550_putc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x1, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr x1, [x1, #CONSOLE_T_16550_BASE]
|
||||
b console_16550_core_putc
|
||||
endfunc console_16550_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_getc(void)
|
||||
* int console_16550_core_getc(uintptr_t base_addr)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* In : w0 - console base address
|
||||
* Out : return -1 on error else return character.
|
||||
* or -1 on if no character is available.
|
||||
* In : x0 - console base address
|
||||
* Out : w0 - character if available, else -1
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_getc
|
||||
func console_16550_core_getc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x0, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Check if the receive FIFO is empty */
|
||||
1: ldr w1, [x0, #UARTLSR]
|
||||
tbz w1, #UARTLSR_RDR_BIT, 1b
|
||||
tbz w1, #UARTLSR_RDR_BIT, no_char
|
||||
ldr w0, [x0, #UARTRX]
|
||||
ret
|
||||
getc_error:
|
||||
mov w0, #-1
|
||||
no_char:
|
||||
mov w0, #ERROR_NO_PENDING_CHAR
|
||||
ret
|
||||
endfunc console_core_getc
|
||||
endfunc console_16550_core_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_16550_getc(console_16550_t *console)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on if no character is available.
|
||||
* In : x0 - pointer to console_t stucture
|
||||
* Out : w0 - character if available, else -1
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_16550_getc
|
||||
#if ENABLE_ASSERTIONS
|
||||
cmp x1, #0
|
||||
ASM_ASSERT(ne)
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
ldr x0, [x0, #CONSOLE_T_16550_BASE]
|
||||
b console_16550_core_getc
|
||||
endfunc console_16550_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_flush(uintptr_t base_addr)
|
||||
* DEPRECATED: Not used with MULTI_CONSOLE_API!
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* In : x0 - console base address
|
||||
|
|
43
include/common/aarch64/console_macros.S
Normal file
43
include/common/aarch64/console_macros.S
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef __CONSOLE_MACROS_S__
|
||||
#define __CONSOLE_MACROS_S__
|
||||
|
||||
#include <console.h>
|
||||
|
||||
/*
|
||||
* This macro encapsulates the common setup that has to be done at the end of
|
||||
* a console driver's register function. It will register all of the driver's
|
||||
* callbacks in the console_t structure and initialize the flags field (by
|
||||
* default consoles are enabled for the "boot" and "crash" states, this can be
|
||||
* changed after registration with the console_set_scope() function). It ends
|
||||
* with a tail call that will include return to the caller.
|
||||
* REQUIRES console_t pointer in x0 and a valid return address in x30.
|
||||
*/
|
||||
.macro finish_console_register _driver
|
||||
/*
|
||||
* Add these weak definitions so we will automatically write a 0 if the
|
||||
* function doesn't exist. I'd rather use .ifdef but that only works if
|
||||
* the function was defined (not just declared .global) above this point
|
||||
* in the file, which we can't guarantee.
|
||||
*/
|
||||
.weak console_\_driver\()_putc
|
||||
.weak console_\_driver\()_getc
|
||||
.weak console_\_driver\()_flush
|
||||
|
||||
/* Don't use adrp on weak funcs! See GNU ld bugzilla issue 22589. */
|
||||
ldr x1, =console_\_driver\()_putc
|
||||
str x1, [x0, #CONSOLE_T_PUTC]
|
||||
ldr x1, =console_\_driver\()_getc
|
||||
str x1, [x0, #CONSOLE_T_GETC]
|
||||
ldr x1, =console_\_driver\()_flush
|
||||
str x1, [x0, #CONSOLE_T_FLUSH]
|
||||
mov x1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
|
||||
str x1, [x0, #CONSOLE_T_FLAGS]
|
||||
b console_register
|
||||
.endm
|
||||
|
||||
#endif /* __CONSOLE_MACROS_S__ */
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef __PL011_H__
|
||||
#define __PL011_H__
|
||||
|
||||
#include <console.h>
|
||||
|
||||
/* PL011 Registers */
|
||||
#define UARTDR 0x000
|
||||
#define UARTRSR 0x004
|
||||
|
@ -79,4 +81,26 @@
|
|||
|
||||
#endif /* !PL011_GENERIC_UART */
|
||||
|
||||
#define CONSOLE_T_PL011_BASE CONSOLE_T_DRVDATA
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
console_t console;
|
||||
uintptr_t base;
|
||||
} console_pl011_t;
|
||||
|
||||
/*
|
||||
* Initialize a new PL011 console instance and register it with the console
|
||||
* framework. The |console| pointer must point to storage that will be valid
|
||||
* for the lifetime of the console, such as a global or static local variable.
|
||||
* Its contents will be reinitialized from scratch.
|
||||
*/
|
||||
int console_pl011_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
|
||||
console_pl011_t *console);
|
||||
|
||||
#endif /*__ASSEMBLY__*/
|
||||
|
||||
#endif /* __PL011_H__ */
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef __CADENCE_UART_H__
|
||||
#define __CADENCE_UART_H__
|
||||
|
||||
#include <console.h>
|
||||
|
||||
/* This is very minimalistic and will only work in QEMU. */
|
||||
|
||||
/* CADENCE Registers */
|
||||
|
@ -23,4 +25,26 @@
|
|||
#define R_UART_TX 0x30
|
||||
#define R_UART_RX 0x30
|
||||
|
||||
#define CONSOLE_T_CDNS_BASE CONSOLE_T_DRVDATA
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
console_t console;
|
||||
uintptr_t base;
|
||||
} console_cdns_t;
|
||||
|
||||
/*
|
||||
* Initialize a new Cadence console instance and register it with the console
|
||||
* framework. The |console| pointer must point to storage that will be valid
|
||||
* for the lifetime of the console, such as a global or static local variable.
|
||||
* Its contents will be reinitialized from scratch.
|
||||
*/
|
||||
int console_cdns_register(uint64_t baseaddr, uint32_t clock, uint32_t baud,
|
||||
console_cdns_t *console);
|
||||
|
||||
#endif /*__ASSEMBLY__*/
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,14 +7,69 @@
|
|||
#ifndef __CONSOLE_H__
|
||||
#define __CONSOLE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
int console_init(uintptr_t base_addr,
|
||||
unsigned int uart_clk, unsigned int baud_rate);
|
||||
void console_uninit(void);
|
||||
#define CONSOLE_T_NEXT (U(0) * REGSZ)
|
||||
#define CONSOLE_T_FLAGS (U(1) * REGSZ)
|
||||
#define CONSOLE_T_PUTC (U(2) * REGSZ)
|
||||
#define CONSOLE_T_GETC (U(3) * REGSZ)
|
||||
#define CONSOLE_T_FLUSH (U(4) * REGSZ)
|
||||
#define CONSOLE_T_DRVDATA (U(5) * REGSZ)
|
||||
|
||||
#define CONSOLE_FLAG_BOOT BIT(0)
|
||||
#define CONSOLE_FLAG_RUNTIME BIT(1)
|
||||
#define CONSOLE_FLAG_CRASH BIT(2)
|
||||
/* Bits 3 to 7 reserved for additional scopes in future expansion. */
|
||||
#define CONSOLE_FLAG_SCOPE_MASK ((U(1) << 8) - 1)
|
||||
/* Bits 8 to 31 reserved for non-scope use in future expansion. */
|
||||
|
||||
/* Returned by getc callbacks when receive FIFO is empty. */
|
||||
#define ERROR_NO_PENDING_CHAR (-1)
|
||||
/* Returned by console_xxx() if no registered console implements xxx. */
|
||||
#define ERROR_NO_VALID_CONSOLE (-128)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef struct console {
|
||||
struct console *next;
|
||||
u_register_t flags;
|
||||
int (*putc)(int character, struct console *console);
|
||||
int (*getc)(struct console *console);
|
||||
int (*flush)(struct console *console);
|
||||
/* Additional private driver data may follow here. */
|
||||
} console_t;
|
||||
#include <console_assertions.h> /* offset macro assertions for console_t */
|
||||
|
||||
/*
|
||||
* NOTE: There is no publicly accessible console_register() function. Consoles
|
||||
* are registered by directly calling the register function of a specific
|
||||
* implementation, e.g. console_16550_register() from <uart_16550.h>. Consoles
|
||||
* registered that way can be unregistered/reconfigured with below functions.
|
||||
*/
|
||||
/* Remove a single console_t instance from the console list. */
|
||||
int console_unregister(console_t *console);
|
||||
/* Set scope mask of a console that determines in what states it is active. */
|
||||
void console_set_scope(console_t *console, unsigned int scope);
|
||||
|
||||
/* Switch to a new global console state (CONSOLE_FLAG_BOOT/RUNTIME/CRASH). */
|
||||
void console_switch_state(unsigned int new_state);
|
||||
/* Output a character on all consoles registered for the current state. */
|
||||
int console_putc(int c);
|
||||
/* Read a character (blocking) from any console registered for current state. */
|
||||
int console_getc(void);
|
||||
/* Flush all consoles registered for the current state. */
|
||||
int console_flush(void);
|
||||
|
||||
#if !MULTI_CONSOLE_API
|
||||
/* DEPRECATED on AArch64 -- use console_<driver>_register() instead! */
|
||||
int console_init(uintptr_t base_addr,
|
||||
unsigned int uart_clk, unsigned int baud_rate) __deprecated;
|
||||
void console_uninit(void) __deprecated;
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __CONSOLE_H__ */
|
||||
|
||||
|
|
30
include/drivers/console_assertions.h
Normal file
30
include/drivers/console_assertions.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __CONSOLE_ASSERTIONS_H__
|
||||
#define __CONSOLE_ASSERTIONS_H__
|
||||
|
||||
#include <cassert.h>
|
||||
|
||||
/*
|
||||
* This file contains some separate assertions about console_t, moved here to
|
||||
* keep them out of the way. Should only be included from <console.h>.
|
||||
*/
|
||||
CASSERT(CONSOLE_T_NEXT == __builtin_offsetof(console_t, next),
|
||||
assert_console_t_next_offset_mismatch);
|
||||
CASSERT(CONSOLE_T_FLAGS == __builtin_offsetof(console_t, flags),
|
||||
assert_console_t_flags_offset_mismatch);
|
||||
CASSERT(CONSOLE_T_PUTC == __builtin_offsetof(console_t, putc),
|
||||
assert_console_t_putc_offset_mismatch);
|
||||
CASSERT(CONSOLE_T_GETC == __builtin_offsetof(console_t, getc),
|
||||
assert_console_t_getc_offset_mismatch);
|
||||
CASSERT(CONSOLE_T_FLUSH == __builtin_offsetof(console_t, flush),
|
||||
assert_console_t_flush_offset_mismatch);
|
||||
CASSERT(CONSOLE_T_DRVDATA == sizeof(console_t),
|
||||
assert_console_t_drvdata_offset_mismatch);
|
||||
|
||||
#endif /* __CONSOLE_ASSERTIONS_H__ */
|
||||
|
27
include/drivers/coreboot/cbmem_console.h
Normal file
27
include/drivers/coreboot/cbmem_console.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __CBMEM_CONSOLE_H__
|
||||
#define __CBMEM_CONSOLE_H__
|
||||
|
||||
#include <console.h>
|
||||
|
||||
#define CONSOLE_T_CBMC_BASE CONSOLE_T_DRVDATA
|
||||
#define CONSOLE_T_CBMC_SIZE (CONSOLE_T_DRVDATA + REGSZ)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
typedef struct {
|
||||
console_t console;
|
||||
uintptr_t base;
|
||||
uint32_t size;
|
||||
} console_cbmc_t;
|
||||
|
||||
int console_cbmc_register(uintptr_t base, console_cbmc_t *console);
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* __CBMEM_CONSOLE_H__ */
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef __UART_16550_H__
|
||||
#define __UART_16550_H__
|
||||
|
||||
#include <console.h>
|
||||
|
||||
/* UART16550 Registers */
|
||||
#define UARTTX 0x0
|
||||
#define UARTRX 0x0
|
||||
|
@ -67,4 +69,26 @@
|
|||
#define UARTLSR_RDR_BIT (0) /* Rx Data Ready Bit */
|
||||
#define UARTLSR_RDR (1 << UARTLSR_RDR_BIT) /* Rx Data Ready */
|
||||
|
||||
#define CONSOLE_T_16550_BASE CONSOLE_T_DRVDATA
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
console_t console;
|
||||
uintptr_t base;
|
||||
} console_16550_t;
|
||||
|
||||
/*
|
||||
* Initialize a new 16550 console instance and register it with the console
|
||||
* framework. The |console| pointer must point to storage that will be valid
|
||||
* for the lifetime of the console, such as a global or static local variable.
|
||||
* Its contents will be reinitialized from scratch.
|
||||
*/
|
||||
int console_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
|
||||
console_16550_t *console);
|
||||
|
||||
#endif /*__ASSEMBLY__*/
|
||||
|
||||
#endif /* __UART_16550_H__ */
|
||||
|
|
24
include/lib/coreboot.h
Normal file
24
include/lib/coreboot.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __COREBOOT_H__
|
||||
#define __COREBOOT_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t type; /* always 2 (memory-mapped) on ARM */
|
||||
uint32_t baseaddr;
|
||||
uint32_t baud;
|
||||
uint32_t regwidth; /* in bytes, i.e. usually 4 */
|
||||
uint32_t input_hertz;
|
||||
uint32_t uart_pci_addr; /* unused on current ARM systems */
|
||||
} coreboot_serial_t;
|
||||
extern coreboot_serial_t coreboot_serial;
|
||||
|
||||
void coreboot_table_setup(void *base);
|
||||
|
||||
#endif /* __COREBOOT_H__ */
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#define SIZE_FROM_LOG2_WORDS(n) (4 << (n))
|
||||
|
||||
#define BIT(nr) (1ULL << (nr))
|
||||
#define BIT(nr) (ULL(1) << (nr))
|
||||
|
||||
/*
|
||||
* This variant of div_round_up can be used in macro definition but should not
|
||||
|
@ -84,6 +84,13 @@
|
|||
# define ULL(_x) (_x##ull)
|
||||
#endif
|
||||
|
||||
/* Register size of the current architecture. */
|
||||
#ifdef AARCH32
|
||||
#define REGSZ U(4)
|
||||
#else
|
||||
#define REGSZ U(8)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Test for the current architecture version to be at least the version
|
||||
* expected.
|
||||
|
|
24
lib/coreboot/coreboot.mk
Normal file
24
lib/coreboot/coreboot.mk
Normal file
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
COREBOOT := 0
|
||||
$(eval $(call assert_boolean,COREBOOT))
|
||||
$(eval $(call add_define,COREBOOT))
|
||||
|
||||
ifeq (${COREBOOT},1)
|
||||
|
||||
ifneq (${ARCH},aarch64)
|
||||
$(error "coreboot only supports Trusted Firmware on AArch64.")
|
||||
endif
|
||||
|
||||
BL31_SOURCES += $(addprefix lib/coreboot/, \
|
||||
coreboot_table.c)
|
||||
|
||||
BL31_SOURCES += drivers/coreboot/cbmem_console/${ARCH}/cbmem_console.S
|
||||
|
||||
INCLUDES += -Iinclude/drivers/coreboot
|
||||
|
||||
endif # COREBOOT
|
123
lib/coreboot/coreboot_table.c
Normal file
123
lib/coreboot/coreboot_table.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <cbmem_console.h>
|
||||
#include <coreboot.h>
|
||||
#include <debug.h>
|
||||
#include <mmio.h>
|
||||
#include <string.h>
|
||||
#include <xlat_tables_v2.h>
|
||||
|
||||
/*
|
||||
* Structures describing coreboot's in-memory descriptor tables. See
|
||||
* <coreboot>/src/commonlib/include/commonlib/coreboot_tables.h for
|
||||
* canonical implementation.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char signature[4];
|
||||
uint32_t header_bytes;
|
||||
uint32_t header_checksum;
|
||||
uint32_t table_bytes;
|
||||
uint32_t table_checksum;
|
||||
uint32_t table_entries;
|
||||
} cb_header_t;
|
||||
|
||||
typedef enum {
|
||||
CB_TAG_SERIAL = 0xf,
|
||||
CB_TAG_CBMEM_CONSOLE = 0x17,
|
||||
} cb_tag_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tag;
|
||||
uint32_t size;
|
||||
union {
|
||||
coreboot_serial_t serial;
|
||||
uint64_t uint64;
|
||||
};
|
||||
} cb_entry_t;
|
||||
|
||||
coreboot_serial_t coreboot_serial;
|
||||
|
||||
/*
|
||||
* The coreboot table is parsed before the MMU is enabled (i.e. with strongly
|
||||
* ordered memory), so we cannot make unaligned accesses. The table entries
|
||||
* immediately follow one another without padding, so nothing after the header
|
||||
* is guaranteed to be naturally aligned. Therefore, we need to define safety
|
||||
* functions that can read unaligned integers.
|
||||
*/
|
||||
static uint32_t read_le32(uint32_t *p)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
return mmio_read_8(addr) |
|
||||
mmio_read_8(addr + 1) << 8 |
|
||||
mmio_read_8(addr + 2) << 16 |
|
||||
mmio_read_8(addr + 3) << 24;
|
||||
}
|
||||
static uint64_t read_le64(uint64_t *p)
|
||||
{
|
||||
return read_le32((void *)p) | (uint64_t)read_le32((void *)p + 4) << 32;
|
||||
}
|
||||
|
||||
static void expand_and_mmap(uintptr_t baseaddr, size_t size)
|
||||
{
|
||||
uintptr_t pageaddr = round_down(baseaddr, PAGE_SIZE);
|
||||
size_t expanded = round_up(baseaddr - pageaddr + size, PAGE_SIZE);
|
||||
mmap_add_region(pageaddr, pageaddr, expanded,
|
||||
MT_MEMORY | MT_RW | MT_NS | MT_EXECUTE_NEVER);
|
||||
}
|
||||
|
||||
static void setup_cbmem_console(uintptr_t baseaddr)
|
||||
{
|
||||
static console_cbmc_t console;
|
||||
assert(!console.base); /* should only have one CBMEM console */
|
||||
|
||||
/* CBMEM console structure stores its size in first header field. */
|
||||
uint32_t size = *(uint32_t *)baseaddr;
|
||||
expand_and_mmap(baseaddr, size);
|
||||
console_cbmc_register(baseaddr, &console);
|
||||
console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
|
||||
CONSOLE_FLAG_RUNTIME |
|
||||
CONSOLE_FLAG_CRASH);
|
||||
}
|
||||
|
||||
void coreboot_table_setup(void *base)
|
||||
{
|
||||
cb_header_t *header = base;
|
||||
void *ptr;
|
||||
int i;
|
||||
|
||||
if (strncmp(header->signature, "LBIO", 4)) {
|
||||
ERROR("coreboot table signature corrupt!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = base + header->header_bytes;
|
||||
for (i = 0; i < header->table_entries; i++) {
|
||||
cb_entry_t *entry = ptr;
|
||||
|
||||
if (ptr - base >= header->header_bytes + header->table_bytes) {
|
||||
ERROR("coreboot table exceeds its bounds!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (read_le32(&entry->tag)) {
|
||||
case CB_TAG_SERIAL:
|
||||
memcpy(&coreboot_serial, &entry->serial,
|
||||
sizeof(coreboot_serial));
|
||||
break;
|
||||
case CB_TAG_CBMEM_CONSOLE:
|
||||
setup_cbmem_console(read_le64(&entry->uint64));
|
||||
break;
|
||||
default:
|
||||
/* There are many tags TF doesn't need to care about. */
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += read_le32(&entry->size);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,10 @@ BL2_AT_EL3 := 0
|
|||
# The platform Makefile is free to override this value.
|
||||
COLD_BOOT_SINGLE_CPU := 0
|
||||
|
||||
# Flag to compile in coreboot support code. Exclude by default. The coreboot
|
||||
# Makefile system will set this when compiling TF as part of a coreboot image.
|
||||
COREBOOT := 0
|
||||
|
||||
# For Chain of Trust
|
||||
CREATE_KEYS := 1
|
||||
|
||||
|
@ -94,6 +98,10 @@ KEY_ALG := rsa
|
|||
# Flag to enable new version of image loading
|
||||
LOAD_IMAGE_V2 := 0
|
||||
|
||||
# Use the new console API that allows registering more than one console instance
|
||||
# at once. Use = instead of := to dynamically default to ERROR_DEPRECATED.
|
||||
MULTI_CONSOLE_API = $(ERROR_DEPRECATED)
|
||||
|
||||
# NS timer register save and restore
|
||||
NS_TIMER_SWITCH := 0
|
||||
|
||||
|
|
|
@ -39,11 +39,11 @@ void bl32_plat_enable_mmu(uint32_t flags)
|
|||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
/*
|
||||
* Finish the use of console driver in BL31 so that any runtime logs
|
||||
* from BL31 will be suppressed.
|
||||
*/
|
||||
#if MULTI_CONSOLE_API
|
||||
console_switch_state(CONSOLE_FLAG_RUNTIME);
|
||||
#else
|
||||
console_uninit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !ENABLE_PLAT_COMPAT
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <console.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
.weak plat_report_exception
|
||||
|
@ -56,9 +57,63 @@ func plat_report_exception
|
|||
ret
|
||||
endfunc plat_report_exception
|
||||
|
||||
#if MULTI_CONSOLE_API
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
* each platform.
|
||||
* int plat_crash_console_init(void)
|
||||
* Use normal console by default. Switch it to crash
|
||||
* mode so serial consoles become active again.
|
||||
* NOTE: This default implementation will only work for
|
||||
* crashes that occur after a normal console (marked
|
||||
* valid for the crash state) has been registered with
|
||||
* the console framework. To debug crashes that occur
|
||||
* earlier, the platform has to override these functions
|
||||
* with an implementation that initializes a console
|
||||
* driver with hardcoded parameters. See
|
||||
* docs/porting-guide.rst for more information.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
#if defined(IMAGE_BL1)
|
||||
/*
|
||||
* BL1 code can possibly crash so early that the data segment is not yet
|
||||
* accessible. Don't risk undefined behavior by trying to run the normal
|
||||
* console framework. Platforms that want to debug BL1 will need to
|
||||
* override this with custom functions that can run from registers only.
|
||||
*/
|
||||
mov x0, #0
|
||||
ret
|
||||
#else /* IMAGE_BL1 */
|
||||
mov x3, x30
|
||||
mov x0, #CONSOLE_FLAG_CRASH
|
||||
bl console_switch_state
|
||||
mov x0, #1
|
||||
ret x3
|
||||
#endif
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_crash_console_putc(int character)
|
||||
* Output through the normal console by default.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
b console_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_crash_console_flush(void)
|
||||
* Flush normal console by default.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
b console_flush
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
#else /* MULTI_CONSOLE_API */
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* In the old API these are all no-op stubs that need to
|
||||
* be overridden by the platform to be useful.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
|
@ -66,23 +121,14 @@ func plat_crash_console_init
|
|||
ret
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
* each platform.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
ret
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
* each platform.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
ret
|
||||
endfunc plat_crash_console_flush
|
||||
#endif
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_report_exception
|
||||
.globl platform_is_primary_cpu
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl plat_my_core_pos
|
||||
.globl plat_reset_handler
|
||||
.globl plat_panic_handler
|
||||
|
||||
/*
|
||||
* void plat_reset_handler(void);
|
||||
|
@ -82,30 +81,17 @@ func platform_is_primary_cpu
|
|||
endfunc platform_is_primary_cpu
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* int plat_crash_console_init(void)
|
||||
* Function to initialize the crash console
|
||||
* without a C Runtime to print crash report.
|
||||
* Clobber list : x0, x1, x2
|
||||
* void plat_panic_handler(void)
|
||||
* Call system reset function on panic. Set up an emergency stack so we
|
||||
* can run C functions (it only needs to last for a few calls until we
|
||||
* reboot anyway).
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, PLAT_RK_UART_BASE
|
||||
mov_imm x1, PLAT_RK_UART_CLOCK
|
||||
mov_imm x2, PLAT_RK_UART_BAUDRATE
|
||||
b console_core_init
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* int plat_crash_console_putc(void)
|
||||
* Function to print a character on the crash
|
||||
* console without a C Runtime.
|
||||
* Clobber list : x1, x2
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, PLAT_RK_UART_BASE
|
||||
b console_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
func plat_panic_handler
|
||||
msr spsel, #0
|
||||
bl plat_set_my_stack
|
||||
b rockchip_soc_soft_reset
|
||||
endfunc plat_panic_handler
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* void platform_cpu_warmboot (void);
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <coreboot.h>
|
||||
#include <debug.h>
|
||||
#include <generic_delay_timer.h>
|
||||
#include <mmio.h>
|
||||
#include <plat_private.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <uart_16550.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Declarations of linker defined symbols which will help us find the layout
|
||||
|
@ -69,8 +71,20 @@ void params_early_setup(void *plat_param_from_bl2)
|
|||
void bl31_early_platform_setup(bl31_params_t *from_bl2,
|
||||
void *plat_params_from_bl2)
|
||||
{
|
||||
console_init(PLAT_RK_UART_BASE, PLAT_RK_UART_CLOCK,
|
||||
PLAT_RK_UART_BAUDRATE);
|
||||
static console_16550_t console;
|
||||
|
||||
params_early_setup(plat_params_from_bl2);
|
||||
|
||||
#if COREBOOT
|
||||
if (coreboot_serial.type)
|
||||
console_16550_register(coreboot_serial.baseaddr,
|
||||
coreboot_serial.input_hertz,
|
||||
coreboot_serial.baud,
|
||||
&console);
|
||||
#else
|
||||
console_16550_register(PLAT_RK_UART_BASE, PLAT_RK_UART_CLOCK,
|
||||
PLAT_RK_UART_BAUDRATE, &console);
|
||||
#endif
|
||||
|
||||
VERBOSE("bl31_setup\n");
|
||||
|
||||
|
@ -82,9 +96,6 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
|
|||
|
||||
bl32_ep_info = *from_bl2->bl32_ep_info;
|
||||
bl33_ep_info = *from_bl2->bl33_ep_info;
|
||||
|
||||
/* there may have some board sepcific message need to initialize */
|
||||
params_early_setup(plat_params_from_bl2);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -38,14 +38,14 @@ cci_iface_regs:
|
|||
* The below utility macro prints out relevant GIC
|
||||
* and CCI registers whenever an unhandled
|
||||
* exception is taken in BL31.
|
||||
* Expects: GICD base in x16, GICC base in x17
|
||||
* Expects: GICD base in x26, GICC base in x27
|
||||
* Clobbers: x0 - x10, sp
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
|
||||
mov_imm x16, PLAT_RK_GICD_BASE
|
||||
mov_imm x17, PLAT_RK_GICC_BASE
|
||||
mov_imm x26, PLAT_RK_GICD_BASE
|
||||
mov_imm x27, PLAT_RK_GICC_BASE
|
||||
|
||||
/* Check for GICv3 system register access */
|
||||
mrs x7, id_aa64pfr0_el1
|
||||
|
@ -72,19 +72,19 @@ print_gicv2:
|
|||
/* Load the gicc reg list to x6 */
|
||||
adr x6, gicc_regs
|
||||
/* Load the gicc regs to gp regs used by str_in_crash_buf_print */
|
||||
ldr w8, [x17, #GICC_HPPIR]
|
||||
ldr w9, [x17, #GICC_AHPPIR]
|
||||
ldr w10, [x17, #GICC_CTLR]
|
||||
ldr w8, [x27, #GICC_HPPIR]
|
||||
ldr w9, [x27, #GICC_AHPPIR]
|
||||
ldr w10, [x27, #GICC_CTLR]
|
||||
/* Store to the crash buf and print to console */
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
print_gic_common:
|
||||
/* Print the GICD_ISPENDR regs */
|
||||
add x7, x16, #GICD_ISPENDR
|
||||
add x7, x26, #GICD_ISPENDR
|
||||
adr x4, gicd_pend_reg
|
||||
bl asm_print_str
|
||||
gicd_ispendr_loop:
|
||||
sub x4, x7, x16
|
||||
sub x4, x7, x26
|
||||
cmp x4, #0x280
|
||||
b.eq exit_print_gic_regs
|
||||
bl asm_print_hex
|
||||
|
|
|
@ -56,6 +56,7 @@ enum {
|
|||
PARAM_POWEROFF,
|
||||
PARAM_SUSPEND_GPIO,
|
||||
PARAM_SUSPEND_APIO,
|
||||
PARAM_COREBOOT_TABLE,
|
||||
};
|
||||
|
||||
struct apio_info {
|
||||
|
@ -89,4 +90,9 @@ struct bl31_apio_param {
|
|||
struct apio_info apio;
|
||||
};
|
||||
|
||||
struct bl31_u64_param {
|
||||
struct bl31_plat_param h;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
#endif /* __PLAT_PARAMS_H__ */
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <coreboot.h>
|
||||
#include <debug.h>
|
||||
#include <gpio.h>
|
||||
#include <mmio.h>
|
||||
|
@ -84,6 +85,12 @@ void params_early_setup(void *plat_param_from_bl2)
|
|||
sizeof(struct bl31_apio_param));
|
||||
suspend_apio = ¶m_apio.apio;
|
||||
break;
|
||||
#if COREBOOT
|
||||
case PARAM_COREBOOT_TABLE:
|
||||
coreboot_table_setup((void *)
|
||||
((struct bl31_u64_param *)bl2_param)->value);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERROR("not expected type found %ld\n",
|
||||
bl2_param->type);
|
||||
|
|
|
@ -49,6 +49,9 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \
|
|||
${RK_PLAT_SOC}/drivers/soc/soc.c
|
||||
|
||||
ENABLE_PLAT_COMPAT := 0
|
||||
MULTI_CONSOLE_API := 1
|
||||
|
||||
include lib/coreboot/coreboot.mk
|
||||
|
||||
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
|
||||
$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))
|
||||
|
|
|
@ -49,6 +49,9 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \
|
|||
${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \
|
||||
|
||||
ENABLE_PLAT_COMPAT := 0
|
||||
MULTI_CONSOLE_API := 1
|
||||
|
||||
include lib/coreboot/coreboot.mk
|
||||
|
||||
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
|
||||
|
||||
|
|
|
@ -64,6 +64,9 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \
|
|||
${RK_PLAT_SOC}/drivers/dram/suspend.c
|
||||
|
||||
ENABLE_PLAT_COMPAT := 0
|
||||
MULTI_CONSOLE_API := 1
|
||||
|
||||
include lib/coreboot/coreboot.mk
|
||||
|
||||
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue