davidcunado-arm
7 years ago
committed by
GitHub
33 changed files with 1583 additions and 327 deletions
@ -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 |
|||
|
@ -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 |
@ -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 |
@ -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 |
@ -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__ */ |
@ -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__ */ |
|||
|
@ -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__ */ |
@ -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__ */ |
@ -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
|
@ -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); |
|||
} |
|||
} |
Loading…
Reference in new issue