diff options
60 files changed, 2199 insertions, 393 deletions
@@ -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})) diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S index cf32b31d7..0986a0a19 100644 --- a/bl31/aarch64/crash_reporting.S +++ b/bl31/aarch64/crash_reporting.S @@ -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 */ diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S index b2b7953f8..e7528d38e 100644 --- a/bl32/sp_min/aarch32/entrypoint.S +++ b/bl32/sp_min/aarch32/entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,6 +17,8 @@ .globl sp_min_vector_table .globl sp_min_entrypoint .globl sp_min_warm_entrypoint + .globl sp_min_handle_smc + .globl sp_min_handle_fiq .macro route_fiq_to_sp_min reg /* ----------------------------------------------------- @@ -43,12 +45,12 @@ vector_base sp_min_vector_table b sp_min_entrypoint b plat_panic_handler /* Undef */ - b handle_smc /* Syscall */ + b sp_min_handle_smc /* Syscall */ b plat_panic_handler /* Prefetch abort */ b plat_panic_handler /* Data abort */ b plat_panic_handler /* Reserved */ b plat_panic_handler /* IRQ */ - b handle_fiq /* FIQ */ + b sp_min_handle_fiq /* FIQ */ /* @@ -151,7 +153,7 @@ endfunc sp_min_entrypoint /* * SMC handling function for SP_MIN. */ -func handle_smc +func sp_min_handle_smc /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ str lr, [sp, #SMC_CTX_LR_MON] @@ -199,12 +201,12 @@ func handle_smc /* `r0` points to `smc_ctx_t` */ b sp_min_exit -endfunc handle_smc +endfunc sp_min_handle_smc /* * Secure Interrupts handling function for SP_MIN. */ -func handle_fiq +func sp_min_handle_fiq #if !SP_MIN_WITH_SECURE_FIQ b plat_panic_handler #else @@ -242,7 +244,7 @@ func handle_fiq b sp_min_exit #endif -endfunc handle_fiq +endfunc sp_min_handle_fiq /* * The Warm boot entrypoint for SP_MIN. diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk index 56489a3c5..67a1981e0 100644 --- a/bl32/sp_min/sp_min.mk +++ b/bl32/sp_min/sp_min.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -26,6 +26,11 @@ ifeq (${ENABLE_AMU}, 1) BL32_SOURCES += lib/extensions/amu/aarch32/amu.c endif +ifeq (${WORKAROUND_CVE_2017_5715},1) +BL32_SOURCES += bl32/sp_min/workaround_cve_2017_5715_bpiall.S \ + bl32/sp_min/workaround_cve_2017_5715_icache_inv.S +endif + BL32_LINKERFILE := bl32/sp_min/sp_min.ld.S # Include the platform-specific SP_MIN Makefile diff --git a/bl32/sp_min/workaround_cve_2017_5715_bpiall.S b/bl32/sp_min/workaround_cve_2017_5715_bpiall.S new file mode 100644 index 000000000..5387cefc9 --- /dev/null +++ b/bl32/sp_min/workaround_cve_2017_5715_bpiall.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> + + .globl workaround_bpiall_runtime_exceptions + +vector_base workaround_bpiall_runtime_exceptions + /* We encode the exception entry in the bottom 3 bits of SP */ + add sp, sp, #1 /* Reset: 0b111 */ + add sp, sp, #1 /* Undef: 0b110 */ + add sp, sp, #1 /* Syscall: 0b101 */ + add sp, sp, #1 /* Prefetch abort: 0b100 */ + add sp, sp, #1 /* Data abort: 0b011 */ + add sp, sp, #1 /* Reserved: 0b010 */ + add sp, sp, #1 /* IRQ: 0b001 */ + nop /* FIQ: 0b000 */ + + /* + * Invalidate the branch predictor, `r0` is a dummy register + * and is unused. + */ + stcopr r0, BPIALL + isb + + /* + * As we cannot use any temporary registers and cannot + * clobber SP, we can decode the exception entry using + * an unrolled binary search. + * + * Note, if this code is re-used by other secure payloads, + * the below exception entry vectors must be changed to + * the vectors specific to that secure payload. + */ + + tst sp, #4 + bne 1f + + tst sp, #2 + bne 3f + + /* Expected encoding: 0x1 and 0x0 */ + tst sp, #1 + /* Restore original value of SP by clearing the bottom 3 bits */ + bic sp, sp, #0x7 + bne plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + +1: + tst sp, #2 + bne 2f + + /* Expected encoding: 0x4 and 0x5 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + +2: + /* Expected encoding: 0x7 and 0x6 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_entrypoint /* Reset */ + b plat_panic_handler /* Undef */ + +3: + /* Expected encoding: 0x2 and 0x3 */ + tst sp, #1 + bic sp, sp, #0x7 + bne plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ diff --git a/bl32/sp_min/workaround_cve_2017_5715_icache_inv.S b/bl32/sp_min/workaround_cve_2017_5715_icache_inv.S new file mode 100644 index 000000000..9102b02f9 --- /dev/null +++ b/bl32/sp_min/workaround_cve_2017_5715_icache_inv.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> + + .globl workaround_icache_inv_runtime_exceptions + +vector_base workaround_icache_inv_runtime_exceptions + /* We encode the exception entry in the bottom 3 bits of SP */ + add sp, sp, #1 /* Reset: 0b111 */ + add sp, sp, #1 /* Undef: 0b110 */ + add sp, sp, #1 /* Syscall: 0b101 */ + add sp, sp, #1 /* Prefetch abort: 0b100 */ + add sp, sp, #1 /* Data abort: 0b011 */ + add sp, sp, #1 /* Reserved: 0b010 */ + add sp, sp, #1 /* IRQ: 0b001 */ + nop /* FIQ: 0b000 */ + + /* + * Invalidate the instruction cache, which we assume also + * invalidates the branch predictor. This may depend on + * other CPU specific changes (e.g. an ACTLR setting). + */ + stcopr r0, ICIALLU + isb + + /* + * As we cannot use any temporary registers and cannot + * clobber SP, we can decode the exception entry using + * an unrolled binary search. + * + * Note, if this code is re-used by other secure payloads, + * the below exception entry vectors must be changed to + * the vectors specific to that secure payload. + */ + + tst sp, #4 + bne 1f + + tst sp, #2 + bne 3f + + /* Expected encoding: 0x1 and 0x0 */ + tst sp, #1 + /* Restore original value of SP by clearing the bottom 3 bits */ + bic sp, sp, #0x7 + bne plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + +1: + /* Expected encoding: 0x4 and 0x5 */ + tst sp, #2 + bne 2f + + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + +2: + /* Expected encoding: 0x7 and 0x6 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_entrypoint /* Reset */ + b plat_panic_handler /* Undef */ + +3: + /* Expected encoding: 0x2 and 0x3 */ + tst sp, #1 + bic sp, sp, #0x7 + bne plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 84bd2cd48..7683ded0e 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -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) ----------------------------------- +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. + 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. +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. -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. +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 ----------- diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S index 8b15d565d..6f2510ad4 100644 --- a/drivers/arm/pl011/aarch64/pl011_console.S +++ b/drivers/arm/pl011/aarch64/pl011_console.S @@ -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_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_core_flush(uintptr_t base_addr) + * 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 diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S index f6a1532c9..fc357f8a4 100644 --- a/drivers/cadence/uart/aarch64/cdns_console.S +++ b/drivers/cadence/uart/aarch64/cdns_console.S @@ -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 diff --git a/drivers/console/aarch64/console.S b/drivers/console/aarch64/console.S index 7cc04ddd7..f847ed597 100644 --- a/drivers/console/aarch64/console.S +++ b/drivers/console/aarch64/console.S @@ -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 diff --git a/drivers/console/aarch64/deprecated_console.S b/drivers/console/aarch64/deprecated_console.S new file mode 100644 index 000000000..c83e2467b --- /dev/null +++ b/drivers/console/aarch64/deprecated_console.S @@ -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 diff --git a/drivers/console/aarch64/multi_console.S b/drivers/console/aarch64/multi_console.S new file mode 100644 index 000000000..15c3ba43d --- /dev/null +++ b/drivers/console/aarch64/multi_console.S @@ -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 diff --git a/drivers/console/aarch64/skeleton_console.S b/drivers/console/aarch64/skeleton_console.S index 9db6157de..1b5d7393c 100644 --- a/drivers/console/aarch64/skeleton_console.S +++ b/drivers/console/aarch64/skeleton_console.S @@ -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 - ret -core_init_fail: - mov w0, wzr +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 -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 diff --git a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S new file mode 100644 index 000000000..2fc060334 --- /dev/null +++ b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S @@ -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 diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S index f9ccd5773..b02209dfb 100644 --- a/drivers/ti/uart/aarch64/16550_console.S +++ b/drivers/ti/uart/aarch64/16550_console.S @@ -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 + ret init_fail: + mov w0, #0 ret -endfunc console_core_init +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 diff --git a/include/common/aarch32/el3_common_macros.S b/include/common/aarch32/el3_common_macros.S index d654b6523..5db885448 100644 --- a/include/common/aarch32/el3_common_macros.S +++ b/include/common/aarch32/el3_common_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,7 +14,7 @@ /* * Helper macro to initialise EL3 registers we care about. */ - .macro el3_arch_init_common _exception_vectors + .macro el3_arch_init_common /* --------------------------------------------------------------------- * SCTLR has already been initialised - read current value before * modifying. @@ -34,15 +34,6 @@ isb /* --------------------------------------------------------------------- - * Set the exception vectors (VBAR/MVBAR). - * --------------------------------------------------------------------- - */ - ldr r0, =\_exception_vectors - stcopr r0, VBAR - stcopr r0, MVBAR - isb - - /* --------------------------------------------------------------------- * Initialise SCR, setting all fields rather than relying on the hw. * * SCR.SIF: Enabled so that Secure state instruction fetches from @@ -211,6 +202,15 @@ .endif /* _warm_boot_mailbox */ /* --------------------------------------------------------------------- + * Set the exception vectors (VBAR/MVBAR). + * --------------------------------------------------------------------- + */ + ldr r0, =\_exception_vectors + stcopr r0, VBAR + stcopr r0, MVBAR + isb + + /* --------------------------------------------------------------------- * It is a cold boot. * Perform any processor specific actions upon reset e.g. cache, TLB * invalidations etc. @@ -218,7 +218,7 @@ */ bl reset_handler - el3_arch_init_common \_exception_vectors + el3_arch_init_common .if \_secondary_cold_boot /* ------------------------------------------------------------- diff --git a/include/common/aarch64/console_macros.S b/include/common/aarch64/console_macros.S new file mode 100644 index 000000000..0ebea2c1b --- /dev/null +++ b/include/common/aarch64/console_macros.S @@ -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__ */ diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h index cd259c5e1..06d754353 100644 --- a/include/drivers/arm/pl011.h +++ b/include/drivers/arm/pl011.h @@ -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__ */ diff --git a/include/drivers/cadence/cdns_uart.h b/include/drivers/cadence/cdns_uart.h index 3aadde32e..7ab6df047 100644 --- a/include/drivers/cadence/cdns_uart.h +++ b/include/drivers/cadence/cdns_uart.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 diff --git a/include/drivers/console.h b/include/drivers/console.h index da5cb8f7b..0629f5717 100644 --- a/include/drivers/console.h +++ b/include/drivers/console.h @@ -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__ */ diff --git a/include/drivers/console_assertions.h b/include/drivers/console_assertions.h new file mode 100644 index 000000000..cedce8679 --- /dev/null +++ b/include/drivers/console_assertions.h @@ -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__ */ + diff --git a/include/drivers/coreboot/cbmem_console.h b/include/drivers/coreboot/cbmem_console.h new file mode 100644 index 000000000..4fca36f61 --- /dev/null +++ b/include/drivers/coreboot/cbmem_console.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__ */ diff --git a/include/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h index f258d45bd..9eba41aa6 100644 --- a/include/drivers/ti/uart/uart_16550.h +++ b/include/drivers/ti/uart/uart_16550.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__ */ diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h index 4d2a5fc9f..134d53468 100644 --- a/include/lib/aarch32/arch.h +++ b/include/lib/aarch32/arch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -426,6 +426,8 @@ #define TLBIMVAA p15, 0, c8, c7, 3 #define TLBIMVAAIS p15, 0, c8, c3, 3 #define BPIALLIS p15, 0, c7, c1, 6 +#define BPIALL p15, 0, c7, c5, 6 +#define ICIALLU p15, 0, c7, c5, 0 #define HSCTLR p15, 4, c1, c0, 0 #define HCR p15, 4, c1, c1, 0 #define HCPTR p15, 4, c1, c1, 2 diff --git a/include/lib/aarch32/smcc_helpers.h b/include/lib/aarch32/smcc_helpers.h index 53f1aa4ab..ed3b722fe 100644 --- a/include/lib/aarch32/smcc_helpers.h +++ b/include/lib/aarch32/smcc_helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -22,7 +22,7 @@ #define SMC_CTX_LR_MON 0x80 #define SMC_CTX_SCR 0x84 #define SMC_CTX_PMCR 0x88 -#define SMC_CTX_SIZE 0x8C +#define SMC_CTX_SIZE 0x90 #ifndef __ASSEMBLY__ #include <cassert.h> @@ -75,7 +75,13 @@ typedef struct smc_ctx { u_register_t lr_mon; u_register_t scr; u_register_t pmcr; -} smc_ctx_t; + /* + * The workaround for CVE-2017-5715 requires storing information in + * the bottom 3 bits of the stack pointer. Add a padding field to + * force the size of the struct to be a multiple of 8. + */ + u_register_t pad; +} smc_ctx_t __aligned(8); /* * Compile time assertions related to the 'smc_context' structure to @@ -99,6 +105,7 @@ CASSERT(SMC_CTX_LR_MON == __builtin_offsetof(smc_ctx_t, lr_mon), \ CASSERT(SMC_CTX_SPSR_MON == __builtin_offsetof(smc_ctx_t, spsr_mon), \ assert_smc_ctx_spsr_mon_offset_mismatch); +CASSERT((sizeof(smc_ctx_t) & 0x7) == 0, assert_smc_ctx_not_aligned); CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch); /* Convenience macros to return from SMC handler */ diff --git a/include/lib/coreboot.h b/include/lib/coreboot.h new file mode 100644 index 000000000..4b1f200a2 --- /dev/null +++ b/include/lib/coreboot.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__ */ diff --git a/include/lib/cpus/aarch32/cortex_a15.h b/include/lib/cpus/aarch32/cortex_a15.h index 905c139da..0f01a4336 100644 --- a/include/lib/cpus/aarch32/cortex_a15.h +++ b/include/lib/cpus/aarch32/cortex_a15.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,6 +15,7 @@ /******************************************************************************* * CPU Auxiliary Control register specific definitions. ******************************************************************************/ +#define CORTEX_A15_ACTLR_INV_BTB_BIT (1 << 0) #define CORTEX_A15_ACTLR_SMP_BIT (1 << 6) #endif /* __CORTEX_A15_H__ */ diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h index 185a1c129..bda3b0735 100644 --- a/include/lib/utils_def.h +++ b/include/lib/utils_def.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. diff --git a/include/services/secure_partition.h b/include/services/secure_partition.h index 334f76107..93df2a137 100644 --- a/include/services/secure_partition.h +++ b/include/services/secure_partition.h @@ -35,27 +35,27 @@ extern uintptr_t __SP_IMAGE_XLAT_TABLES_END__; * partition. */ typedef struct secure_partition_mp_info { - u_register_t mpidr; - unsigned int linear_id; - unsigned int flags; + uint64_t mpidr; + uint32_t linear_id; + uint32_t flags; } secure_partition_mp_info_t; typedef struct secure_partition_boot_info { param_header_t h; - uintptr_t sp_mem_base; - uintptr_t sp_mem_limit; - uintptr_t sp_image_base; - uintptr_t sp_stack_base; - uintptr_t sp_heap_base; - uintptr_t sp_ns_comm_buf_base; - uintptr_t sp_shared_buf_base; - size_t sp_image_size; - size_t sp_pcpu_stack_size; - size_t sp_heap_size; - size_t sp_ns_comm_buf_size; - size_t sp_shared_buf_size; - unsigned int num_sp_mem_regions; - unsigned int num_cpus; + uint64_t sp_mem_base; + uint64_t sp_mem_limit; + uint64_t sp_image_base; + uint64_t sp_stack_base; + uint64_t sp_heap_base; + uint64_t sp_ns_comm_buf_base; + uint64_t sp_shared_buf_base; + uint64_t sp_image_size; + uint64_t sp_pcpu_stack_size; + uint64_t sp_heap_size; + uint64_t sp_ns_comm_buf_size; + uint64_t sp_shared_buf_size; + uint32_t num_sp_mem_regions; + uint32_t num_cpus; secure_partition_mp_info_t *mp_info; } secure_partition_boot_info_t; diff --git a/lib/coreboot/coreboot.mk b/lib/coreboot/coreboot.mk new file mode 100644 index 000000000..bbaa33294 --- /dev/null +++ b/lib/coreboot/coreboot.mk @@ -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 diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c new file mode 100644 index 000000000..64f8879e4 --- /dev/null +++ b/lib/coreboot/coreboot_table.c @@ -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); + } +} diff --git a/lib/cpus/aarch32/cortex_a15.S b/lib/cpus/aarch32/cortex_a15.S index 0d5a11658..b6c61ab7f 100644 --- a/lib/cpus/aarch32/cortex_a15.S +++ b/lib/cpus/aarch32/cortex_a15.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -41,7 +41,46 @@ func cortex_a15_enable_smp bx lr endfunc cortex_a15_enable_smp +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A15. Must follow AAPCS. + */ +func cortex_a15_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, cortex_a15, cve_2017_5715 + + pop {r12, lr} + bx lr +endfunc cortex_a15_errata_report +#endif + func cortex_a15_reset_func +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldcopr r0, ACTLR + orr r0, #CORTEX_A15_ACTLR_INV_BTB_BIT + stcopr r0, ACTLR + ldr r0, =workaround_icache_inv_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif b cortex_a15_enable_smp endfunc cortex_a15_reset_func diff --git a/lib/cpus/aarch32/cortex_a17.S b/lib/cpus/aarch32/cortex_a17.S index 316d4f053..b84c12671 100644 --- a/lib/cpus/aarch32/cortex_a17.S +++ b/lib/cpus/aarch32/cortex_a17.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -35,7 +35,43 @@ func cortex_a17_enable_smp bx lr endfunc cortex_a17_enable_smp +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A17. Must follow AAPCS. + */ +func cortex_a17_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, cortex_a17, cve_2017_5715 + + pop {r12, lr} + bx lr +endfunc cortex_a17_errata_report +#endif + func cortex_a17_reset_func +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldr r0, =workaround_bpiall_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif b cortex_a17_enable_smp endfunc cortex_a17_reset_func diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S index 64a6d6745..f446bfffa 100644 --- a/lib/cpus/aarch32/cortex_a57.S +++ b/lib/cpus/aarch32/cortex_a57.S @@ -332,6 +332,11 @@ func check_errata_859972 b cpu_rev_var_ls endfunc check_errata_859972 +func check_errata_cve_2017_5715 + mov r0, #ERRATA_MISSING + bx lr +endfunc check_errata_cve_2017_5715 + /* ------------------------------------------------- * The CPU Ops reset function for Cortex-A57. * Shall clobber: r0-r6 @@ -519,6 +524,7 @@ func cortex_a57_errata_report report_errata ERRATA_A57_829520, cortex_a57, 829520 report_errata ERRATA_A57_833471, cortex_a57, 833471 report_errata ERRATA_A57_859972, cortex_a57, 859972 + report_errata WORKAROUND_CVE_2017_5715, cortex_a57, cve_2017_5715 pop {r12, lr} bx lr diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S index 35b9bc2e6..56e91f5c0 100644 --- a/lib/cpus/aarch32/cortex_a72.S +++ b/lib/cpus/aarch32/cortex_a72.S @@ -87,6 +87,10 @@ func check_errata_859971 b cpu_rev_var_ls endfunc check_errata_859971 +func check_errata_cve_2017_5715 + mov r0, #ERRATA_MISSING + bx lr +endfunc check_errata_cve_2017_5715 /* ------------------------------------------------- * The CPU Ops reset function for Cortex-A72. @@ -236,6 +240,7 @@ func cortex_a72_errata_report * checking functions of each errata. */ report_errata ERRATA_A72_859971, cortex_a72, 859971 + report_errata WORKAROUND_CVE_2017_5715, cortex_a72, cve_2017_5715 pop {r12, lr} bx lr diff --git a/lib/cpus/aarch32/cortex_a9.S b/lib/cpus/aarch32/cortex_a9.S index 4f30f84a9..1fb10b205 100644 --- a/lib/cpus/aarch32/cortex_a9.S +++ b/lib/cpus/aarch32/cortex_a9.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -35,7 +35,43 @@ func cortex_a9_enable_smp bx lr endfunc cortex_a9_enable_smp +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A9. Must follow AAPCS. + */ +func cortex_a9_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, cortex_a9, cve_2017_5715 + + pop {r12, lr} + bx lr +endfunc cortex_a9_errata_report +#endif + func cortex_a9_reset_func +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldr r0, =workaround_bpiall_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif b cortex_a9_enable_smp endfunc cortex_a9_reset_func diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S index 683be47e5..c82ebfc95 100644 --- a/lib/cpus/aarch64/cortex_a57.S +++ b/lib/cpus/aarch64/cortex_a57.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -328,6 +328,15 @@ func check_errata_859972 b cpu_rev_var_ls endfunc check_errata_859972 +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2017_5715 + /* ------------------------------------------------- * The CPU Ops reset function for Cortex-A57. * Shall clobber: x0-x19 @@ -518,7 +527,7 @@ func cortex_a57_errata_report report_errata ERRATA_A57_829520, cortex_a57, 829520 report_errata ERRATA_A57_833471, cortex_a57, 833471 report_errata ERRATA_A57_859972, cortex_a57, 859972 - + report_errata WORKAROUND_CVE_2017_5715, cortex_a57, cve_2017_5715 ldp x8, x30, [sp], #16 ret diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S index 93821b749..9633aa8f5 100644 --- a/lib/cpus/aarch64/cortex_a72.S +++ b/lib/cpus/aarch64/cortex_a72.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -97,6 +97,15 @@ func check_errata_859971 b cpu_rev_var_ls endfunc check_errata_859971 +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2017_5715 + /* ------------------------------------------------- * The CPU Ops reset function for Cortex-A72. * ------------------------------------------------- @@ -249,6 +258,7 @@ func cortex_a72_errata_report * checking functions of each errata. */ report_errata ERRATA_A72_859971, cortex_a72, 859971 + report_errata WORKAROUND_CVE_2017_5715, cortex_a72, cve_2017_5715 ldp x8, x30, [sp], #16 ret diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S index c43f07ec1..11680a09d 100644 --- a/lib/cpus/aarch64/cortex_a73.S +++ b/lib/cpus/aarch64/cortex_a73.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -114,6 +114,36 @@ func cortex_a73_cluster_pwr_dwn b cortex_a73_disable_smp endfunc cortex_a73_cluster_pwr_dwn +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A75. Must follow AAPCS. + */ +func cortex_a73_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, cortex_a73, cve_2017_5715 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a73_errata_report +#endif + /* --------------------------------------------- * This function provides cortex_a73 specific * register information for crash reporting. diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S index e66ad0667..946f98843 100644 --- a/lib/cpus/aarch64/cortex_a75.S +++ b/lib/cpus/aarch64/cortex_a75.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -151,6 +151,27 @@ func cortex_a75_reset_func ret endfunc cortex_a75_reset_func +func check_errata_cve_2017_5715 + mrs x0, id_aa64pfr0_el1 + ubfx x0, x0, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH + /* + * If the field equals to 1 then branch targets trained in one + * context cannot affect speculative execution in a different context. + */ + cmp x0, #1 + beq 1f + +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_errata_cve_2017_5715 + /* --------------------------------------------- * HW will do the cache maintenance while powering down * --------------------------------------------- @@ -167,6 +188,27 @@ func cortex_a75_core_pwr_dwn ret endfunc cortex_a75_core_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A75. Must follow AAPCS. + */ +func cortex_a75_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, cortex_a75, cve_2017_5715 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a75_errata_report +#endif + /* --------------------------------------------- * This function provides cortex_a75 specific * register information for crash reporting. diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c index 182679d13..c679336c1 100644 --- a/lib/cpus/errata_report.c +++ b/lib/cpus/errata_report.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -27,7 +27,7 @@ #endif /* Errata format: BL stage, CPU, errata ID, message */ -#define ERRATA_FORMAT "%s: %s: errata workaround for %s was %s\n" +#define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n" /* * Returns whether errata needs to be reported. Passed arguments are private to diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 643890f6c..a80a4915a 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -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 diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c index a87e7c673..cfc0c4f41 100644 --- a/plat/common/aarch64/plat_common.c +++ b/plat/common/aarch64/plat_common.c @@ -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 diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S index 797a93639..852675277 100644 --- a/plat/common/aarch64/platform_helpers.S +++ b/plat/common/aarch64/platform_helpers.S @@ -6,6 +6,7 @@ #include <arch.h> #include <asm_macros.S> +#include <console.h> #include <platform_def.h> .weak plat_report_exception @@ -56,33 +57,78 @@ 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 /* ----------------------------------------------------- - * Placeholder function which should be redefined by - * each platform. + * void plat_crash_console_putc(int character) + * Output through the normal console by default. * ----------------------------------------------------- */ func plat_crash_console_putc - ret + b console_putc endfunc plat_crash_console_putc /* ----------------------------------------------------- - * Placeholder function which should be redefined by - * each platform. + * 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 + mov x0, #0 + ret +endfunc plat_crash_console_init + +func plat_crash_console_putc + ret +endfunc plat_crash_console_putc + func plat_crash_console_flush ret endfunc plat_crash_console_flush +#endif /* ----------------------------------------------------- * Placeholder function which should be redefined by diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c index f685f9cfa..f0d15a358 100644 --- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c +++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c @@ -16,6 +16,8 @@ #include <gicv2.h> #include <hi3660.h> #include <hisi_ipc.h> +#include <interrupt_mgmt.h> +#include <platform.h> #include <platform_def.h> #include "hikey960_def.h" @@ -167,6 +169,37 @@ void bl31_platform_setup(void) hisi_ipc_init(); } +#ifdef SPD_none +static uint64_t hikey_debug_fiq_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + int intr, intr_raw; + + /* Acknowledge interrupt */ + intr_raw = plat_ic_acknowledge_interrupt(); + intr = plat_ic_get_interrupt_id(intr_raw); + ERROR("Invalid interrupt: intr=%d\n", intr); + console_flush(); + panic(); + + return 0; +} +#endif + void bl31_plat_runtime_setup(void) { +#ifdef SPD_none + uint32_t flags; + int32_t rc; + + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + hikey_debug_fiq_handler, + flags); + if (rc != 0) + panic(); +#endif } diff --git a/plat/hisilicon/poplar/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c index c65e29e97..7d6f10c2c 100644 --- a/plat/hisilicon/poplar/bl1_plat_setup.c +++ b/plat/hisilicon/poplar/bl1_plat_setup.c @@ -9,6 +9,8 @@ #include <bl_common.h> #include <console.h> #include <debug.h> +#include <dw_mmc.h> +#include <emmc.h> #include <errno.h> #include <generic_delay_timer.h> #include <mmio.h> @@ -71,6 +73,9 @@ void bl1_plat_arch_setup(void) void bl1_platform_setup(void) { int i; +#if !POPLAR_RECOVERY + dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE); +#endif generic_delay_timer_init(); @@ -78,6 +83,12 @@ void bl1_platform_setup(void) for (i = 0; i < GPIO_MAX; i++) pl061_gpio_register(GPIO_BASE(i), i); +#if !POPLAR_RECOVERY + /* SoC-specific emmc register are initialized/configured by bootrom */ + INFO("BL1: initializing emmc\n"); + dw_mmc_init(¶ms); +#endif + plat_io_setup(); } diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c index db507c327..7edfab7ff 100644 --- a/plat/hisilicon/poplar/bl2_plat_setup.c +++ b/plat/hisilicon/poplar/bl2_plat_setup.c @@ -9,6 +9,8 @@ #include <bl_common.h> #include <console.h> #include <debug.h> +#include <dw_mmc.h> +#include <emmc.h> #include <errno.h> #include <generic_delay_timer.h> #include <mmio.h> @@ -181,12 +183,24 @@ void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) void bl2_early_platform_setup(meminfo_t *mem_layout) { +#if !POPLAR_RECOVERY + dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE); +#endif + console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE); /* Enable arch timer */ generic_delay_timer_init(); bl2_tzram_layout = *mem_layout; + +#if !POPLAR_RECOVERY + /* SoC-specific emmc register are initialized/configured by bootrom */ + INFO("BL2: initializing emmc\n"); + dw_mmc_init(¶ms); +#endif + + plat_io_setup(); } void bl2_plat_arch_setup(void) @@ -201,7 +215,6 @@ void bl2_plat_arch_setup(void) void bl2_platform_setup(void) { - plat_io_setup(); } unsigned long plat_get_ns_image_entrypoint(void) diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h index 540d0aa18..125b04841 100644 --- a/plat/hisilicon/poplar/include/hi3798cv200.h +++ b/plat/hisilicon/poplar/include/hi3798cv200.h @@ -7,6 +7,8 @@ #ifndef __HI3798cv200_H__ #define __HI3798cv200_H__ +#include <utils_def.h> + /* PL011 */ #define PL011_UART0_BASE (0xF8B00000) #define PL011_BAUDRATE (115200) @@ -63,11 +65,11 @@ #define EMMC_CLK_50M (1 << 8) #define EMMC_CLK_25M (2 << 8) -#define EMMC_DESC_SIZE (0xF0000) +#define EMMC_DESC_SIZE U(0x00100000) /* 1MB */ #define EMMC_INIT_PARAMS(base) \ { .bus_width = EMMC_BUS_WIDTH_8, \ .clk_rate = 25 * 1000 * 1000, \ - .desc_base = (base) - EMMC_DESC_SIZE, \ + .desc_base = (base), \ .desc_size = EMMC_DESC_SIZE, \ .flags = EMMC_FLAG_CMD23, \ .reg_base = REG_BASE_MCI, \ diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h index 3d1ad9b99..c0f83711c 100644 --- a/plat/hisilicon/poplar/include/platform_def.h +++ b/plat/hisilicon/poplar/include/platform_def.h @@ -12,6 +12,7 @@ #include <gic_common.h> #include <interrupt_props.h> #include <tbbr/tbbr_img_def.h> +#include <utils_def.h> #include "hi3798cv200.h" #include "poplar_layout.h" /* BL memory region sizes, etc */ @@ -53,13 +54,12 @@ #define POPLAR_DRAM_ID 1 /* - * DDR for OP-TEE (28MB from 0x02200000 -0x04000000) is divided in several + * DDR for OP-TEE (26MB from 0x02400000 -0x04000000) is divided in several * regions: * - Secure DDR (default is the top 16MB) used by OP-TEE * - Non-secure DDR (4MB) reserved for OP-TEE's future use * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) - * - Non-secure DDR (2MB) reserved for OP-TEE's future use */ #define DDR_SEC_SIZE 0x01000000 #define DDR_SEC_BASE 0x03000000 @@ -96,6 +96,11 @@ #endif /* SPD_none */ #endif +#define POPLAR_EMMC_DATA_BASE U(0x02200000) +#define POPLAR_EMMC_DATA_SIZE EMMC_DESC_SIZE +#define POPLAR_EMMC_DESC_BASE (POPLAR_EMMC_DATA_BASE + POPLAR_EMMC_DATA_SIZE) +#define POPLAR_EMMC_DESC_SIZE EMMC_DESC_SIZE + #define PLAT_POPLAR_NS_IMAGE_OFFSET 0x37000000 /* Page table and MMU setup constants */ diff --git a/plat/hisilicon/poplar/include/poplar_layout.h b/plat/hisilicon/poplar/include/poplar_layout.h index e0b5618ef..9ce043423 100644 --- a/plat/hisilicon/poplar/include/poplar_layout.h +++ b/plat/hisilicon/poplar/include/poplar_layout.h @@ -12,8 +12,8 @@ */ /* - * When Poplar is powered on, boot ROM loads the initial content of - * boot media into low memory, verifies it, and begins executing it + * When Poplar is powered on, boot ROM verifies the initial content of + * boot media, loads it into low memory, and begins executing it * in 32-bit mode. The image loaded is "l-loader.bin", which contains * a small amount code along with an embedded ARM Trusted Firmware * BL1 image. The main purpose of "l-loader" is to prepare the @@ -78,12 +78,36 @@ #define BL1_OFFSET 0x0000D000 /* page multiple */ #define FIP_BASE 0x02040000 +/* + * FIP_BASE_EMMC = 0x40000 - 0x1000 + * = fip.bin offset - l-loader text offset + * in l-loader.bin + */ +#define FIP_BASE_EMMC 0x0003f000 + #define BL1_RO_SIZE 0x00008000 /* page multiple */ #define BL1_RW_SIZE 0x00008000 /* page multiple */ #define BL1_SIZE (BL1_RO_SIZE + BL1_RW_SIZE) #define BL2_SIZE 0x0000c000 /* page multiple */ #define BL31_SIZE 0x00014000 +#if !POPLAR_RECOVERY +/* + * emmc partition1 4096KB + * - l-loader.bin 1984KB + * |- l-loader + bl1.bin 256KB + * |- fip.bin 1728KB (0x001b0000) + * - u-boot persistent data 64KB + * - uefi persistent data 2048KB + */ +#define FIP_SIZE 0x001b0000 /* absolute max */ +#else +/* + * same as above, but bootrom can only load an image (l-loader.bin) of + * 1024KB max, so after deducting the size of l-loader + bl1.bin (256KB), + * that leaves 768KB (0x000c0000) for fip.bin + */ #define FIP_SIZE 0x000c0000 /* absolute max */ +#endif /* BL1_OFFSET */ /* (Defined above) */ #define BL1_BASE (LLOADER_TEXT_BASE + BL1_OFFSET) diff --git a/plat/hisilicon/poplar/plat_storage.c b/plat/hisilicon/poplar/plat_storage.c index ab94cba33..468e22926 100644 --- a/plat/hisilicon/poplar/plat_storage.c +++ b/plat/hisilicon/poplar/plat_storage.c @@ -7,6 +7,7 @@ #include <arch_helpers.h> #include <assert.h> #include <debug.h> +#include <emmc.h> #include <firmware_image_package.h> #include <io_block.h> #include <io_driver.h> @@ -21,19 +22,41 @@ #include <utils.h> #include "platform_def.h" -static const io_dev_connector_t *mmap_dev_con; -static const io_dev_connector_t *fip_dev_con; +#if !POPLAR_RECOVERY +static const io_dev_connector_t *emmc_dev_con; +static uintptr_t emmc_dev_handle; +static int open_emmc(const uintptr_t spec); -static uintptr_t mmap_dev_handle; -static uintptr_t fip_dev_handle; +static const io_block_spec_t emmc_fip_spec = { + .offset = FIP_BASE_EMMC, + .length = FIP_SIZE +}; +static const io_block_dev_spec_t emmc_dev_spec = { + .buffer = { + .offset = POPLAR_EMMC_DATA_BASE, + .length = POPLAR_EMMC_DATA_SIZE, + }, + .ops = { + .read = emmc_read_blocks, + .write = emmc_write_blocks, + }, + .block_size = EMMC_BLOCK_SIZE, +}; +#else +static const io_dev_connector_t *mmap_dev_con; +static uintptr_t mmap_dev_handle; static int open_mmap(const uintptr_t spec); -static int open_fip(const uintptr_t spec); static const io_block_spec_t loader_fip_spec = { .offset = FIP_BASE, .length = FIP_SIZE }; +#endif + +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static int open_fip(const uintptr_t spec); static const io_uuid_spec_t bl2_uuid_spec = { .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, @@ -58,11 +81,19 @@ struct plat_io_policy { }; static const struct plat_io_policy policies[] = { +#if !POPLAR_RECOVERY + [FIP_IMAGE_ID] = { + &emmc_dev_handle, + (uintptr_t)&emmc_fip_spec, + open_emmc + }, +#else [FIP_IMAGE_ID] = { &mmap_dev_handle, (uintptr_t)&loader_fip_spec, open_mmap }, +#endif [BL2_IMAGE_ID] = { &fip_dev_handle, (uintptr_t)&bl2_uuid_spec, @@ -85,6 +116,28 @@ static const struct plat_io_policy policies[] = { }, }; +#if !POPLAR_RECOVERY +static int open_emmc(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(emmc_dev_handle, spec, &local_image_handle); + if (result == 0) { + INFO("Using eMMC\n"); + io_close(local_image_handle); + } else { + ERROR("error opening emmc\n"); + } + } else { + ERROR("error initializing emmc\n"); + } + + return result; +} +#else static int open_mmap(const uintptr_t spec) { int result; @@ -94,11 +147,18 @@ static int open_mmap(const uintptr_t spec) if (result == 0) { result = io_open(mmap_dev_handle, spec, &local_image_handle); if (result == 0) { + INFO("Using mmap\n"); io_close(local_image_handle); + } else { + ERROR("error opening mmap\n"); } + } else { + ERROR("error initializing mmap\n"); } + return result; } +#endif static int open_fip(const uintptr_t spec) { @@ -109,12 +169,13 @@ static int open_fip(const uintptr_t spec) if (result == 0) { result = io_open(fip_dev_handle, spec, &local_image_handle); if (result == 0) { + INFO("Using FIP\n"); io_close(local_image_handle); } else { - VERBOSE("error opening fip\n"); + ERROR("error opening fip\n"); } } else { - VERBOSE("error initializing fip\n"); + ERROR("error initializing fip\n"); } return result; @@ -142,17 +203,31 @@ void plat_io_setup(void) { int result; +#if !POPLAR_RECOVERY + result = register_io_dev_block(&emmc_dev_con); +#else result = register_io_dev_memmap(&mmap_dev_con); +#endif assert(result == 0); result = register_io_dev_fip(&fip_dev_con); assert(result == 0); +#if !POPLAR_RECOVERY + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); +#else result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec, &fip_dev_handle); +#endif assert(result == 0); +#if !POPLAR_RECOVERY + result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec, + &emmc_dev_handle); +#else result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle); +#endif assert(result == 0); (void) result; diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk index 818e3115f..2dbbac6e7 100644 --- a/plat/hisilicon/poplar/platform.mk +++ b/plat/hisilicon/poplar/platform.mk @@ -15,6 +15,9 @@ else endif $(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID)) +POPLAR_RECOVERY := 0 +$(eval $(call add_define,POPLAR_RECOVERY)) + NEED_BL33 := yes COLD_BOOT_SINGLE_CPU := 1 @@ -36,6 +39,7 @@ PLAT_INCLUDES := -Iplat/hisilicon/poplar/include \ -Iinclude/plat/arm/common/ \ -Iplat/hisilicon/poplar \ -Iinclude/common/tbbr \ + -Iinclude/drivers/synopsys \ -Iinclude/drivers/io PLAT_BL_COMMON_SOURCES := \ @@ -54,6 +58,8 @@ PLAT_BL_COMMON_SOURCES := \ BL1_SOURCES += \ lib/cpus/aarch64/cortex_a53.S \ drivers/arm/pl061/pl061_gpio.c \ + drivers/emmc/emmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ drivers/io/io_storage.c \ drivers/io/io_block.c \ drivers/gpio/gpio.c \ @@ -65,6 +71,8 @@ BL1_SOURCES += \ BL2_SOURCES += \ drivers/arm/pl061/pl061_gpio.c \ + drivers/emmc/emmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ drivers/io/io_storage.c \ drivers/io/io_block.c \ drivers/io/io_fip.c \ diff --git a/plat/rockchip/common/aarch64/plat_helpers.S b/plat/rockchip/common/aarch64/plat_helpers.S index abfb5a795..f415f8772 100644 --- a/plat/rockchip/common/aarch64/plat_helpers.S +++ b/plat/rockchip/common/aarch64/plat_helpers.S @@ -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); diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c index 292f0dd7d..6199edae2 100644 --- a/plat/rockchip/common/bl31_plat_setup.c +++ b/plat/rockchip/common/bl31_plat_setup.c @@ -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); } /******************************************************************************* diff --git a/plat/rockchip/common/include/plat_macros.S b/plat/rockchip/common/include/plat_macros.S index be1a9fa5d..6b3cb6a72 100644 --- a/plat/rockchip/common/include/plat_macros.S +++ b/plat/rockchip/common/include/plat_macros.S @@ -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 diff --git a/plat/rockchip/common/include/plat_params.h b/plat/rockchip/common/include/plat_params.h index aa13f878c..710990760 100644 --- a/plat/rockchip/common/include/plat_params.h +++ b/plat/rockchip/common/include/plat_params.h @@ -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__ */ diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c index b37acb76b..65afe8769 100644 --- a/plat/rockchip/common/params_setup.c +++ b/plat/rockchip/common/params_setup.c @@ -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); diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk index 5de4680e0..6e4d5b4dc 100644 --- a/plat/rockchip/rk3328/platform.mk +++ b/plat/rockchip/rk3328/platform.mk @@ -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)) diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk index d3c6eeffb..ad204e9eb 100644 --- a/plat/rockchip/rk3368/platform.mk +++ b/plat/rockchip/rk3368/platform.mk @@ -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)) diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 33b9723d7..9e369e482 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -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)) |