Merge pull request #1228 from dp-arm/dp/cve_2017_5715
Workarounds for CVE-2017-5715 on A9/A15 and A17 + serial console reporting
diff --git a/Makefile b/Makefile
index 1058b39..c16cad7 100644
--- a/Makefile
+++ b/Makefile
@@ -488,6 +488,7 @@
$(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))
@@ -500,6 +501,7 @@
$(eval $(call assert_boolean,USE_COHERENT_MEM))
$(eval $(call assert_boolean,USE_TBBR_DEFS))
$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
+$(eval $(call assert_boolean,BL2_AT_EL3))
$(eval $(call assert_numeric,ARM_ARCH_MAJOR))
$(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -529,6 +531,7 @@
$(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}))
@@ -543,6 +546,7 @@
$(eval $(call add_define,USE_COHERENT_MEM))
$(eval $(call add_define,USE_TBBR_DEFS))
$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
+$(eval $(call add_define,BL2_AT_EL3))
# Define the EL3_PAYLOAD_BASE flag only if it is provided.
ifdef EL3_PAYLOAD_BASE
@@ -584,8 +588,12 @@
endif
ifeq (${NEED_BL2},yes)
-$(if ${BL2}, $(eval $(call MAKE_TOOL_ARGS,2,${BL2},tb-fw)),\
- $(eval $(call MAKE_BL,2,tb-fw)))
+ifeq (${BL2_AT_EL3}, 0)
+FIP_BL2_ARGS := tb-fw
+endif
+
+$(if ${BL2}, $(eval $(call MAKE_TOOL_ARGS,2,${BL2},${FIP_BL2_ARGS})),\
+ $(eval $(call MAKE_BL,2,${FIP_BL2_ARGS})))
endif
ifeq (${NEED_SCP_BL2},yes)
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index a026499..41ee1a7 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -13,7 +13,10 @@
lib/cpus/errata_report.c \
lib/el3_runtime/${ARCH}/context_mgmt.c \
plat/common/plat_bl1_common.c \
- plat/common/${ARCH}/platform_up_stack.S
+ plat/common/${ARCH}/platform_up_stack.S \
+ ${MBEDTLS_COMMON_SOURCES} \
+ ${MBEDTLS_CRYPTO_SOURCES} \
+ ${MBEDTLS_X509_SOURCES}
ifeq (${ARCH},aarch64)
BL1_SOURCES += lib/el3_runtime/aarch64/context.S
diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S
new file mode 100644
index 0000000..997b069
--- /dev/null
+++ b/bl2/aarch32/bl2_el3_entrypoint.S
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <el3_common_macros.S>
+
+
+ .globl bl2_entrypoint
+ .globl bl2_run_next_image
+
+
+func bl2_entrypoint
+ /* Save arguments x0-x3 from previous Boot loader */
+ mov r9, r0
+ mov r10, r1
+ mov r11, r2
+ mov r12, r3
+
+ el3_entrypoint_common \
+ _init_sctlr=1 \
+ _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
+ _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
+ _init_memory=1 \
+ _init_c_runtime=1 \
+ _exception_vectors=bl2_vector_table
+
+ /*
+ * Restore parameters of boot rom
+ */
+ mov r0, r9
+ mov r1, r10
+ mov r2, r11
+ mov r3, r12
+
+ bl bl2_el3_early_platform_setup
+ bl bl2_el3_plat_arch_setup
+
+ /* ---------------------------------------------
+ * Jump to main function.
+ * ---------------------------------------------
+ */
+ bl bl2_main
+
+ /* ---------------------------------------------
+ * Should never reach this point.
+ * ---------------------------------------------
+ */
+ no_ret plat_panic_handler
+
+endfunc bl2_entrypoint
+
+func bl2_run_next_image
+ mov r8,r0
+
+ /*
+ * MMU needs to be disabled because both BL2 and BL32 execute
+ * in PL1, and therefore share the same address space.
+ * BL32 will initialize the address space according to its
+ * own requirement.
+ */
+ bl disable_mmu_icache_secure
+ stcopr r0, TLBIALL
+ dsb sy
+ isb
+ mov r0, r8
+ bl bl2_el3_plat_prepare_exit
+
+ /*
+ * Extract PC and SPSR based on struct `entry_point_info_t`
+ * and load it in LR and SPSR registers respectively.
+ */
+ ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
+ ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
+ msr spsr, r1
+
+ add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
+ ldm r8, {r0, r1, r2, r3}
+ eret
+endfunc bl2_run_next_image
diff --git a/bl2/aarch32/bl2_el3_exceptions.S b/bl2/aarch32/bl2_el3_exceptions.S
new file mode 100644
index 0000000..11ddf37
--- /dev/null
+++ b/bl2/aarch32/bl2_el3_exceptions.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+
+ .globl bl2_vector_table
+
+vector_base bl2_vector_table
+ b bl2_entrypoint
+ b report_exception /* Undef */
+ b report_exception /* SVC call */
+ b report_exception /* Prefetch abort */
+ b report_exception /* Data abort */
+ b report_exception /* Reserved */
+ b report_exception /* IRQ */
+ b report_exception /* FIQ */
diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S
new file mode 100644
index 0000000..2d3efd1
--- /dev/null
+++ b/bl2/aarch64/bl2_el3_entrypoint.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <el3_common_macros.S>
+
+ .globl bl2_entrypoint
+ .globl bl2_vector_table
+ .globl bl2_el3_run_image
+ .globl bl2_run_next_image
+
+func bl2_entrypoint
+ /* Save arguments x0-x3 from previous Boot loader */
+ mov x20, x0
+ mov x21, x1
+ mov x22, x2
+ mov x23, x3
+
+ el3_entrypoint_common \
+ _init_sctlr=1 \
+ _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
+ _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
+ _init_memory=1 \
+ _init_c_runtime=1 \
+ _exception_vectors=bl2_el3_exceptions
+
+ /*
+ * Restore parameters of boot rom
+ */
+ mov x0, x20
+ mov x1, x21
+ mov x2, x22
+ mov x3, x23
+
+ bl bl2_el3_early_platform_setup
+ bl bl2_el3_plat_arch_setup
+
+ /* ---------------------------------------------
+ * Jump to main function.
+ * ---------------------------------------------
+ */
+ bl bl2_main
+
+ /* ---------------------------------------------
+ * Should never reach this point.
+ * ---------------------------------------------
+ */
+ no_ret plat_panic_handler
+endfunc bl2_entrypoint
+
+func bl2_run_next_image
+ mov x20,x0
+ /*
+ * MMU needs to be disabled because both BL2 and BL31 execute
+ * in EL3, and therefore share the same address space.
+ * BL31 will initialize the address space according to its
+ * own requirement.
+ */
+ bl disable_mmu_icache_el3
+ tlbi alle3
+ bl bl2_el3_plat_prepare_exit
+
+ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+ msr elr_el3, x0
+ msr spsr_el3, x1
+
+ ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
+ ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
+ ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
+ ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
+ eret
+endfunc bl2_run_next_image
diff --git a/bl2/aarch64/bl2_el3_exceptions.S b/bl2/aarch64/bl2_el3_exceptions.S
new file mode 100644
index 0000000..987f6e3
--- /dev/null
+++ b/bl2/aarch64/bl2_el3_exceptions.S
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl1.h>
+#include <bl_common.h>
+#include <context.h>
+
+/* -----------------------------------------------------------------------------
+ * Very simple stackless exception handlers used by BL2.
+ * -----------------------------------------------------------------------------
+ */
+ .globl bl2_el3_exceptions
+
+vector_base bl2_el3_exceptions
+
+ /* -----------------------------------------------------
+ * Current EL with SP0 : 0x0 - 0x200
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionSP0
+ mov x0, #SYNC_EXCEPTION_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SynchronousExceptionSP0
+
+vector_entry IrqSP0
+ mov x0, #IRQ_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size IrqSP0
+
+vector_entry FiqSP0
+ mov x0, #FIQ_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size FiqSP0
+
+vector_entry SErrorSP0
+ mov x0, #SERROR_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SErrorSP0
+
+ /* -----------------------------------------------------
+ * Current EL with SPx: 0x200 - 0x400
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionSPx
+ mov x0, #SYNC_EXCEPTION_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SynchronousExceptionSPx
+
+vector_entry IrqSPx
+ mov x0, #IRQ_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size IrqSPx
+
+vector_entry FiqSPx
+ mov x0, #FIQ_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size FiqSPx
+
+vector_entry SErrorSPx
+ mov x0, #SERROR_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SErrorSPx
+
+ /* -----------------------------------------------------
+ * Lower EL using AArch64 : 0x400 - 0x600
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionA64
+ mov x0, #SYNC_EXCEPTION_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SynchronousExceptionA64
+
+vector_entry IrqA64
+ mov x0, #IRQ_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size IrqA64
+
+vector_entry FiqA64
+ mov x0, #FIQ_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size FiqA64
+
+vector_entry SErrorA64
+ mov x0, #SERROR_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SErrorA64
+
+ /* -----------------------------------------------------
+ * Lower EL using AArch32 : 0x600 - 0x800
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionA32
+ mov x0, #SYNC_EXCEPTION_AARCH32
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SynchronousExceptionA32
+
+vector_entry IrqA32
+ mov x0, #IRQ_AARCH32
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size IrqA32
+
+vector_entry FiqA32
+ mov x0, #FIQ_AARCH32
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size FiqA32
+
+vector_entry SErrorA32
+ mov x0, #SERROR_AARCH32
+ bl plat_report_exception
+ no_ret plat_panic_handler
+ check_vector_size SErrorA32
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
index 32e3284..9d75286 100644
--- a/bl2/bl2.mk
+++ b/bl2/bl2.mk
@@ -5,10 +5,12 @@
#
BL2_SOURCES += bl2/bl2_main.c \
- bl2/${ARCH}/bl2_entrypoint.S \
bl2/${ARCH}/bl2_arch_setup.c \
lib/locks/exclusive/${ARCH}/spinlock.S \
- plat/common/${ARCH}/platform_up_stack.S
+ plat/common/${ARCH}/platform_up_stack.S \
+ ${MBEDTLS_COMMON_SOURCES} \
+ ${MBEDTLS_CRYPTO_SOURCES} \
+ ${MBEDTLS_X509_SOURCES}
ifeq (${ARCH},aarch64)
BL2_SOURCES += common/aarch64/early_exceptions.S
@@ -20,4 +22,15 @@
BL2_SOURCES += bl2/bl2_image_load.c
endif
+ifeq (${BL2_AT_EL3},0)
+BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S
BL2_LINKERFILE := bl2/bl2.ld.S
+
+else
+BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \
+ bl2/${ARCH}/bl2_el3_exceptions.S \
+ plat/common/plat_bl2_el3_common.c \
+ lib/cpus/${ARCH}/cpu_helpers.S \
+ lib/cpus/errata_report.c
+BL2_LINKERFILE := bl2/bl2_el3.ld.S
+endif
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
new file mode 100644
index 0000000..57709e3
--- /dev/null
+++ b/bl2/bl2_el3.ld.S
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+#include <xlat_tables_defs.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+ENTRY(bl2_entrypoint)
+
+MEMORY {
+ RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE
+}
+
+
+SECTIONS
+{
+ . = BL2_BASE;
+ ASSERT(. == ALIGN(PAGE_SIZE),
+ "BL2_BASE address is not aligned on a page boundary.")
+
+#if SEPARATE_CODE_AND_RODATA
+ .text . : {
+ __TEXT_START__ = .;
+ __TEXT_RESIDENT_START__ = .;
+ *bl2_el3_entrypoint.o(.text*)
+ *(.text.asm.*)
+ __TEXT_RESIDENT_END__ = .;
+ *(.text*)
+ *(.vectors)
+ . = NEXT(PAGE_SIZE);
+ __TEXT_END__ = .;
+ } >RAM
+
+ .rodata . : {
+ __RODATA_START__ = .;
+ *(.rodata*)
+
+ /* Ensure 8-byte alignment for descriptors and ensure inclusion */
+ . = ALIGN(8);
+ __PARSER_LIB_DESCS_START__ = .;
+ KEEP(*(.img_parser_lib_descs))
+ __PARSER_LIB_DESCS_END__ = .;
+
+ /*
+ * Ensure 8-byte alignment for cpu_ops so that its fields are also
+ * aligned. Also ensure cpu_ops inclusion.
+ */
+ . = ALIGN(8);
+ __CPU_OPS_START__ = .;
+ KEEP(*(cpu_ops))
+ __CPU_OPS_END__ = .;
+
+ . = NEXT(PAGE_SIZE);
+ __RODATA_END__ = .;
+ } >RAM
+
+ ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE,
+ "Resident part of BL2 has exceeded its limit.")
+#else
+ ro . : {
+ __RO_START__ = .;
+ __TEXT_RESIDENT_START__ = .;
+ *bl2_el3_entrypoint.o(.text*)
+ *(.text.asm.*)
+ __TEXT_RESIDENT_END__ = .;
+ *(.text*)
+ *(.rodata*)
+
+ /*
+ * Ensure 8-byte alignment for cpu_ops so that its fields are also
+ * aligned. Also ensure cpu_ops inclusion.
+ */
+ . = ALIGN(8);
+ __CPU_OPS_START__ = .;
+ KEEP(*(cpu_ops))
+ __CPU_OPS_END__ = .;
+
+ /* Ensure 8-byte alignment for descriptors and ensure inclusion */
+ . = ALIGN(8);
+ __PARSER_LIB_DESCS_START__ = .;
+ KEEP(*(.img_parser_lib_descs))
+ __PARSER_LIB_DESCS_END__ = .;
+
+ *(.vectors)
+ __RO_END_UNALIGNED__ = .;
+ /*
+ * Memory page(s) mapped to this section will be marked as
+ * read-only, executable. No RW data from the next section must
+ * creep in. Ensure the rest of the current memory page is unused.
+ */
+ . = NEXT(PAGE_SIZE);
+
+ __RO_END__ = .;
+ } >RAM
+#endif
+
+ ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
+ "cpu_ops not defined for this platform.")
+
+ /*
+ * Define a linker symbol to mark start of the RW memory area for this
+ * image.
+ */
+ __RW_START__ = . ;
+
+ /*
+ * .data must be placed at a lower address than the stacks if the stack
+ * protector is enabled. Alternatively, the .data.stack_protector_canary
+ * section can be placed independently of the main .data section.
+ */
+ .data . : {
+ __DATA_START__ = .;
+ *(.data*)
+ __DATA_END__ = .;
+ } >RAM
+
+ stacks (NOLOAD) : {
+ __STACKS_START__ = .;
+ *(tzfw_normal_stacks)
+ __STACKS_END__ = .;
+ } >RAM
+
+ /*
+ * The .bss section gets initialised to 0 at runtime.
+ * Its base address should be 16-byte aligned for better performance of the
+ * zero-initialization code.
+ */
+ .bss : ALIGN(16) {
+ __BSS_START__ = .;
+ *(SORT_BY_ALIGNMENT(.bss*))
+ *(COMMON)
+ __BSS_END__ = .;
+ } >RAM
+
+ /*
+ * The xlat_table section is for full, aligned page tables (4K).
+ * Removing them from .bss avoids forcing 4K alignment on
+ * the .bss section and eliminates the unnecessary zero init
+ */
+ xlat_table (NOLOAD) : {
+ *(xlat_table)
+ } >RAM
+
+#if USE_COHERENT_MEM
+ /*
+ * The base address of the coherent memory section must be page-aligned (4K)
+ * to guarantee that the coherent data are stored on their own pages and
+ * are not mixed with normal data. This is required to set up the correct
+ * memory attributes for the coherent data page tables.
+ */
+ coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
+ __COHERENT_RAM_START__ = .;
+ *(tzfw_coherent_mem)
+ __COHERENT_RAM_END_UNALIGNED__ = .;
+ /*
+ * Memory page(s) mapped to this section will be marked
+ * as device memory. No other unexpected data must creep in.
+ * Ensure the rest of the current memory page is unused.
+ */
+ . = NEXT(PAGE_SIZE);
+ __COHERENT_RAM_END__ = .;
+ } >RAM
+#endif
+
+ /*
+ * Define a linker symbol to mark end of the RW memory area for this
+ * image.
+ */
+ __RW_END__ = .;
+ __BL2_END__ = .;
+
+ __BSS_SIZE__ = SIZEOF(.bss);
+
+#if USE_COHERENT_MEM
+ __COHERENT_RAM_UNALIGNED_SIZE__ =
+ __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
+#endif
+
+ ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.")
+}
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 018deb3..c85db2d 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -13,6 +13,11 @@
#include <platform.h>
#include "bl2_private.h"
+#ifdef AARCH32
+#define NEXT_IMAGE "BL32"
+#else
+#define NEXT_IMAGE "BL31"
+#endif
/*******************************************************************************
* The only thing to do in BL2 is to load further images and pass control to
@@ -49,6 +54,8 @@
disable_mmu_icache_secure();
#endif /* AARCH32 */
+
+#if !BL2_AT_EL3
console_flush();
/*
@@ -57,4 +64,11 @@
* be passed to next BL image as an argument.
*/
smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0);
+#else
+ NOTICE("BL2: Booting " NEXT_IMAGE "\n");
+ print_entry_point_info(next_bl_ep_info);
+ console_flush();
+
+ bl2_run_next_image(next_bl_ep_info);
+#endif
}
diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h
index 83b8047..ea2f33a 100644
--- a/bl2/bl2_private.h
+++ b/bl2/bl2_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,5 +17,6 @@
*****************************************/
void bl2_arch_setup(void);
struct entry_point_info *bl2_load_images(void);
+void bl2_run_next_image(const entry_point_info_t *bl_ep_info);
#endif /* __BL2_PRIVATE_H__ */
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index cf32b31..0986a0a 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 @@
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 @@
/* 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 @@
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 @@
/* 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 @@
/* 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 @@
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/docs/firmware-design.rst b/docs/firmware-design.rst
index 3cb004a..1f8fcc8 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -418,6 +418,63 @@
#. BL1 passes control to BL31 at the specified entrypoint at EL3.
+Running BL2 at EL3 execution level
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some platforms have a non-TF Boot ROM that expects the next boot stage
+to execute at EL3. On these platforms, TF BL1 is a waste of memory
+as its only purpose is to ensure TF BL2 is entered at S-EL1. To avoid
+this waste, a special mode enables BL2 to execute at EL3, which allows
+a non-TF Boot ROM to load and jump directly to BL2. This mode is selected
+when the build flag BL2_AT_EL3 is enabled. The main differences in this
+mode are:
+
+#. BL2 includes the reset code and the mailbox mechanism to differentiate
+ cold boot and warm boot. It runs at EL3 doing the arch
+ initialization required for EL3.
+
+#. BL2 does not receive the meminfo information from BL1 anymore. This
+ information can be passed by the Boot ROM or be internal to the
+ BL2 image.
+
+#. Since BL2 executes at EL3, BL2 jumps directly to the next image,
+ instead of invoking the RUN_IMAGE SMC call.
+
+
+We assume 3 different types of BootROM support on the platform:
+
+#. The Boot ROM always jumps to the same address, for both cold
+ and warm boot. In this case, we will need to keep a resident part
+ of BL2 whose memory cannot be reclaimed by any other image. The
+ linker script defines the symbols __TEXT_RESIDENT_START__ and
+ __TEXT_RESIDENT_END__ that allows the platform to configure
+ correctly the memory map.
+#. The platform has some mechanism to indicate the jump address to the
+ Boot ROM. Platform code can then program the jump address with
+ psci_warmboot_entrypoint during cold boot.
+#. The platform has some mechanism to program the reset address using
+ the PROGRAMMABLE_RESET_ADDRESS feature. Platform code can then
+ program the reset address with psci_warmboot_entrypoint during
+ cold boot, bypassing the boot ROM for warm boot.
+
+In the last 2 cases, no part of BL2 needs to remain resident at
+runtime. In the first 2 cases, we expect the Boot ROM to be able to
+differentiate between warm and cold boot, to avoid loading BL2 again
+during warm boot.
+
+This functionality can be tested with FVP loading the image directly
+in memory and changing the address where the system jumps at reset.
+For example:
+
+ -C cluster0.cpu0.RVBAR=0x4014000
+ --data cluster0.cpu0=bl2.bin@0x4014000
+
+With this configuration, FVP is like a platform of the first case,
+where the Boot ROM jumps always to the same address. For simplification,
+BL32 is loaded in DRAM in this case, to avoid other images reclaiming
+BL2 memory.
+
+
AArch64 BL31
~~~~~~~~~~~~
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 2e2cc4f..7683ded 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -1643,6 +1643,70 @@
must return 0, otherwise it must return 1. The default implementation
of this always returns 0.
+Boot Loader Stage 2 (BL2) at EL3
+--------------------------------
+
+When the platform has a non-TF Boot ROM it is desirable to jump
+directly to BL2 instead of TF BL1. In this case BL2 is expected to
+execute at EL3 instead of executing at EL1. Refer to the `Firmware
+Design`_ for more information.
+
+All mandatory functions of BL2 must be implemented, except the functions
+bl2\_early\_platform\_setup and bl2\_el3\_plat\_arch\_setup, because
+their work is done now by bl2\_el3\_early\_platform\_setup and
+bl2\_el3\_plat\_arch\_setup. These functions should generally implement
+the bl1\_plat\_xxx() and bl2\_plat\_xxx() functionality combined.
+
+
+Function : bl2\_el3\_early\_platform\_setup() [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+ Argument : u_register_t, u_register_t, u_register_t, u_register_t
+ Return : void
+
+This function executes with the MMU and data caches disabled. It is only called
+by the primary CPU. This function receives four parameters which can be used
+by the platform to pass any needed information from the Boot ROM to BL2.
+
+On ARM standard platforms, this function does the following:
+
+- Initializes a UART (PL011 console), which enables access to the ``printf``
+ family of functions in BL2.
+
+- Initializes the storage abstraction layer used to load further bootloader
+ images. It is necessary to do this early on platforms with a SCP\_BL2 image,
+ since the later ``bl2_platform_setup`` must be done after SCP\_BL2 is loaded.
+
+- Initializes the private variables that define the memory layout used.
+
+Function : bl2\_el3\_plat\_arch\_setup() [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+ Argument : void
+ Return : void
+
+This function executes with the MMU and data caches disabled. It is only called
+by the primary CPU.
+
+The purpose of this function is to perform any architectural initialization
+that varies across platforms.
+
+On ARM standard platforms, this function enables the MMU.
+
+Function : bl2\_el3\_plat\_prepare\_exit() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+ Argument : void
+ Return : void
+
+This function is called prior to exiting BL2 and run the next image.
+It should be used to perform platform specific clean up or bookkeeping
+operations before transferring control to the next image. This function
+runs with MMU disabled.
+
FWU Boot Loader Stage 2 (BL2U)
------------------------------
@@ -1865,12 +1929,8 @@
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]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2638,14 +2698,20 @@
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2656,9 +2722,30 @@
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2672,6 +2759,12 @@
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2682,9 +2775,15 @@
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/docs/user-guide.rst b/docs/user-guide.rst
index 0647e70..ed5ba18 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -245,6 +245,9 @@
BL2U image. In this case, the BL2U in the ARM Trusted Firmware will not
be built.
+- ``BL2_AT_EL3``: This is an optional build option that enables the use of
+ BL2 at EL3 execution level.
+
- ``BL31``: This is an optional build option which specifies the path to
BL31 image for the ``fip`` target. In this case, the BL31 in the ARM
Trusted Firmware will not be built.
diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S
index 8b15d56..6f2510a 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"
-
- .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_pl011_core_init
+ .globl console_pl011_core_putc
+ .globl console_pl011_core_getc
+ .globl console_pl011_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 @@
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 @@
* 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 @@
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 @@
* 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 @@
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/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index f2b6f6e..8c4123d 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -29,7 +29,4 @@
platform.c \
)
-BL1_SOURCES += ${MBEDTLS_COMMON_SOURCES}
-BL2_SOURCES += ${MBEDTLS_COMMON_SOURCES}
-
endif
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk
index 8eb4873..6b15e71 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.mk
+++ b/drivers/auth/mbedtls/mbedtls_crypto.mk
@@ -89,6 +89,3 @@
# Needs to be set to drive mbed TLS configuration correctly
$(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID))
$(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID))
-
-BL1_SOURCES += ${MBEDTLS_CRYPTO_SOURCES}
-BL2_SOURCES += ${MBEDTLS_CRYPTO_SOURCES}
diff --git a/drivers/auth/mbedtls/mbedtls_x509.mk b/drivers/auth/mbedtls/mbedtls_x509.mk
index 0f28b65..a6f72e6 100644
--- a/drivers/auth/mbedtls/mbedtls_x509.mk
+++ b/drivers/auth/mbedtls/mbedtls_x509.mk
@@ -11,6 +11,3 @@
x509.c \
x509_crt.c \
)
-
-BL1_SOURCES += ${MBEDTLS_X509_SOURCES}
-BL2_SOURCES += ${MBEDTLS_X509_SOURCES}
diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S
index f6a1532..fc357f8 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 @@
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 @@
* 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 @@
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 7cc04dd..f847ed5 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 0000000..c83e246
--- /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 0000000..15c3ba4
--- /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 9db6157..1b5d739 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_xxx_getc
+ /*
+ * Retrieve values we need (e.g. hardware base address) from
+ * console_xxx_t structure pointed to by x0.
+ * Example:
+ */
-func console_core_getc
- cbz x0, getc_error
- /* Insert implementation here */
+ 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_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.
+ */
-func console_core_flush
- cbz x0, flush_error
- /* Insert implementation here */
+
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 0000000..2fc0603
--- /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/emmc/emmc.c b/drivers/emmc/emmc.c
index bcdc82c..92d1e87 100644
--- a/drivers/emmc/emmc.c
+++ b/drivers/emmc/emmc.c
@@ -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
*
@@ -353,7 +353,9 @@
(clk != 0) &&
((width == EMMC_BUS_WIDTH_1) ||
(width == EMMC_BUS_WIDTH_4) ||
- (width == EMMC_BUS_WIDTH_8)));
+ (width == EMMC_BUS_WIDTH_8) ||
+ (width == EMMC_BUS_WIDTH_DDR_4) ||
+ (width == EMMC_BUS_WIDTH_DDR_8)));
ops = ops_ptr;
emmc_flags = flags;
diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S
index f9ccd57..b02209d 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 @@
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 @@
* 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 @@
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 74fb582..5db8854 100644
--- a/include/common/aarch32/el3_common_macros.S
+++ b/include/common/aarch32/el3_common_macros.S
@@ -260,9 +260,9 @@
* ---------------------------------------------------------------------
*/
.if \_init_c_runtime
-#ifdef IMAGE_BL32
+#if defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3)
/* -----------------------------------------------------------------
- * Invalidate the RW memory used by the BL32 (SP_MIN) image. This
+ * Invalidate the RW memory used by the image. This
* includes the data and NOBITS sections. This is done to
* safeguard against possible corruption of this memory by
* dirty cache lines in a system cache as a result of use by
@@ -273,7 +273,7 @@
ldr r1, =__RW_END__
sub r1, r1, r0
bl inv_dcache_range
-#endif /* IMAGE_BL32 */
+#endif
ldr r0, =__BSS_START__
ldr r1, =__BSS_SIZE__
diff --git a/include/common/aarch64/console_macros.S b/include/common/aarch64/console_macros.S
new file mode 100644
index 0000000..0ebea2c
--- /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/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S
index defd4a2..4ebf77b 100644
--- a/include/common/aarch64/el3_common_macros.S
+++ b/include/common/aarch64/el3_common_macros.S
@@ -269,7 +269,7 @@
* ---------------------------------------------------------------------
*/
.if \_init_c_runtime
-#ifdef IMAGE_BL31
+#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
/* -------------------------------------------------------------
* Invalidate the RW memory used by the BL31 image. This
* includes the data and NOBITS sections. This is done to
@@ -282,7 +282,7 @@
adr x1, __RW_END__
sub x1, x1, x0
bl inv_dcache_range
-#endif /* IMAGE_BL31 */
+#endif
ldr x0, =__BSS_START__
ldr x1, =__BSS_SIZE__
diff --git a/include/common/asm_macros_common.S b/include/common/asm_macros_common.S
index 6a02e18..ca8c1ad 100644
--- a/include/common/asm_macros_common.S
+++ b/include/common/asm_macros_common.S
@@ -29,7 +29,7 @@
* debugging experience.
*/
.cfi_sections .debug_frame
- .section .text.\_name, "ax"
+ .section .text.asm.\_name, "ax"
.type \_name, %function
.func \_name
/*
diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h
index cd259c5..06d7543 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 3aadde3..7ab6df0 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 da5cb8f..0629f57 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 0000000..cedce86
--- /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 0000000..4fca36f
--- /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/emmc.h b/include/drivers/emmc.h
index 921f4cf..286c014 100644
--- a/include/drivers/emmc.h
+++ b/include/drivers/emmc.h
@@ -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
*/
@@ -25,6 +25,7 @@
#define EMMC_CMD13 13
#define EMMC_CMD17 17
#define EMMC_CMD18 18
+#define EMMC_CMD21 21
#define EMMC_CMD23 23
#define EMMC_CMD24 24
#define EMMC_CMD25 25
@@ -61,6 +62,8 @@
#define EMMC_BUS_WIDTH_1 0
#define EMMC_BUS_WIDTH_4 1
#define EMMC_BUS_WIDTH_8 2
+#define EMMC_BUS_WIDTH_DDR_4 5
+#define EMMC_BUS_WIDTH_DDR_8 6
#define EMMC_BOOT_MODE_BACKWARD (0 << 3)
#define EMMC_BOOT_MODE_HS_TIMING (1 << 3)
#define EMMC_BOOT_MODE_DDR (2 << 3)
diff --git a/include/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h
index f258d45..9eba41a 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/coreboot.h b/include/lib/coreboot.h
new file mode 100644
index 0000000..4b1f200
--- /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/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S
index e2e4316..0f3a572 100644
--- a/include/lib/cpus/aarch32/cpu_macros.S
+++ b/include/lib/cpus/aarch32/cpu_macros.S
@@ -9,6 +9,10 @@
#include <arch.h>
#include <errata_report.h>
+#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3)
+#define IMAGE_AT_EL3
+#endif
+
#define CPU_IMPL_PN_MASK (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | \
(MIDR_PN_MASK << MIDR_PN_SHIFT)
@@ -38,7 +42,7 @@
CPU_MIDR: /* cpu_ops midr */
.space 4
/* Reset fn is needed during reset */
-#if defined(IMAGE_BL1) || defined(IMAGE_BL32)
+#if defined(IMAGE_AT_EL3)
CPU_RESET_FUNC: /* cpu_ops reset_func */
.space 4
#endif
@@ -54,7 +58,7 @@
#if REPORT_ERRATA
CPU_ERRATA_FUNC: /* CPU errata status printing function */
.space 4
-#ifdef IMAGE_BL32
+#if defined(IMAGE_BL32)
CPU_ERRATA_LOCK:
.space 4
CPU_ERRATA_PRINTED:
@@ -120,7 +124,7 @@
.align 2
.type cpu_ops_\_name, %object
.word \_midr
-#if defined(IMAGE_BL1) || defined(IMAGE_BL32)
+#if defined(IMAGE_AT_EL3)
.word \_resetfunc
#endif
#ifdef IMAGE_BL32
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index a8c23e5..ccf5306 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -21,6 +21,10 @@
/* Word size for 64-bit CPUs */
#define CPU_WORD_SIZE 8
+#if defined(IMAGE_BL1) || defined(IMAGE_BL31) ||(defined(IMAGE_BL2) && BL2_AT_EL3)
+#define IMAGE_AT_EL3
+#endif
+
/*
* Whether errata status needs reporting. Errata status is printed in debug
* builds for both BL1 and BL31 images.
@@ -38,7 +42,7 @@
CPU_MIDR: /* cpu_ops midr */
.space 8
/* Reset fn is needed in BL at reset vector */
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31)
+#if defined(IMAGE_AT_EL3)
CPU_RESET_FUNC: /* cpu_ops reset_func */
.space 8
#endif
@@ -54,7 +58,7 @@
#if REPORT_ERRATA
CPU_ERRATA_FUNC:
.space 8
-#ifdef IMAGE_BL31
+#if defined(IMAGE_BL31)
CPU_ERRATA_LOCK:
.space 8
CPU_ERRATA_PRINTED:
@@ -124,7 +128,7 @@
.align 3
.type cpu_ops_\_name, %object
.quad \_midr
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31)
+#if defined(IMAGE_AT_EL3)
.quad \_resetfunc
#endif
#ifdef IMAGE_BL31
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 185a1c1..bda3b07 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/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index 1be99b7..de1c2d4 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -168,7 +168,7 @@
* This IMAGE_EL macro must not to be used outside the library, and it is only
* used in AArch64.
*/
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31)
+#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
# define IMAGE_EL 3
# define IMAGE_XLAT_DEFAULT_REGIME EL3_REGIME
#else
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index f38c357..697a0b0 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -334,6 +334,11 @@
#define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
#define BL2_LIMIT BL1_RW_BASE
+#elif BL2_AT_EL3
+
+#define BL2_BASE ARM_BL_RAM_BASE
+#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+
#elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
/*
* Put BL2 just below BL32.
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index abd7395..dfd7a20 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -145,6 +145,10 @@
uint32_t arm_get_spsr_for_bl33_entry(void);
int arm_bl2_handle_post_image_load(unsigned int image_id);
+/* BL2 at EL3 functions */
+void arm_bl2_el3_early_platform_setup(void);
+void arm_bl2_el3_plat_arch_setup(void);
+
/* BL2U utility functions */
void arm_bl2u_early_platform_setup(struct meminfo *mem_layout,
void *plat_info);
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index f11bee9..0960105 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -235,6 +235,21 @@
* Optional BL2 functions (may be overridden)
******************************************************************************/
+
+/*******************************************************************************
+ * Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is
+ * supported
+ ******************************************************************************/
+void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3);
+void bl2_el3_plat_arch_setup(void);
+
+
+/*******************************************************************************
+ * Optional BL2 at EL3 functions (may be overridden)
+ ******************************************************************************/
+void bl2_el3_plat_prepare_exit(void);
+
/*******************************************************************************
* Mandatory BL2U functions.
******************************************************************************/
diff --git a/lib/coreboot/coreboot.mk b/lib/coreboot/coreboot.mk
new file mode 100644
index 0000000..bbaa332
--- /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 0000000..64f8879
--- /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_a72.S b/lib/cpus/aarch32/cortex_a72.S
index 878e6b1..56e91f5 100644
--- a/lib/cpus/aarch32/cortex_a72.S
+++ b/lib/cpus/aarch32/cortex_a72.S
@@ -113,7 +113,7 @@
orr64_imm r0, r1, CORTEX_A72_ECTLR_SMP_BIT
stcopr16 r0, r1, CORTEX_A72_ECTLR
isb
- bx lr
+ bx r5
endfunc cortex_a72_reset_func
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch32/cpu_helpers.S b/lib/cpus/aarch32/cpu_helpers.S
index bfdc1e4..72e42c6 100644
--- a/lib/cpus/aarch32/cpu_helpers.S
+++ b/lib/cpus/aarch32/cpu_helpers.S
@@ -10,7 +10,7 @@
#include <cpu_data.h>
#include <cpu_macros.S>
-#if defined(IMAGE_BL1) || defined(IMAGE_BL32)
+#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3)
/*
* The reset handler common to all platforms. After a matching
* cpu_ops structure entry is found, the correponding reset_handler
@@ -42,7 +42,7 @@
bx lr
endfunc reset_handler
-#endif /* IMAGE_BL1 || IMAGE_BL32 */
+#endif
#ifdef IMAGE_BL32 /* The power down core and cluster is needed only in BL32 */
/*
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 2384553..ae1c3c2 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -7,7 +7,7 @@
#include <arch.h>
#include <asm_macros.S>
#include <assert_macros.S>
-#ifdef IMAGE_BL31
+#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
#include <cpu_data.h>
#endif
#include <cpu_macros.S>
@@ -15,7 +15,7 @@
#include <errata_report.h>
/* Reset fn is needed in BL at reset vector */
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31)
+#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
/*
* The reset handler common to all platforms. After a matching
* cpu_ops structure entry is found, the correponding reset_handler
@@ -47,7 +47,7 @@
ret
endfunc reset_handler
-#endif /* IMAGE_BL1 || IMAGE_BL31 */
+#endif
#ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */
/*
diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c
index c030679..c679336 100644
--- a/lib/cpus/errata_report.c
+++ b/lib/cpus/errata_report.c
@@ -20,6 +20,8 @@
# define BL_STRING "BL31"
#elif defined(AARCH32) && defined(IMAGE_BL32)
# define BL_STRING "BL32"
+#elif defined(IMAGE_BL2) && BL2_AT_EL3
+# define BL_STRING "BL2"
#else
# error This image should not be printing errata status
#endif
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index fa0d17d..a80a491 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -27,10 +27,17 @@
# Base commit to perform code check on
BASE_COMMIT := origin/master
+# Execute BL2 at EL3
+BL2_AT_EL3 := 0
+
# By default, consider that the platform may release several CPUs out of reset.
# 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
@@ -91,6 +98,10 @@
# 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/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 6e6e273..cda8d72 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -64,7 +64,9 @@
$(if ${BL2},$(eval $(call CERT_ADD_CMD_OPT,${BL2},--tb-fw,true)),\
$(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,2),--tb-fw,true)))
$(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
+ifeq (${BL2_AT_EL3}, 0)
$(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
+endif
# Add the SCP_BL2 CoT (key cert + img cert + image)
ifneq (${SCP_BL2},)
diff --git a/plat/arm/board/fvp/fvp_bl2_el3_setup.c b/plat/arm/board/fvp/fvp_bl2_el3_setup.c
new file mode 100644
index 0000000..69f2f7a
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl2_el3_setup.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_arm.h>
+#include "fvp_private.h"
+
+void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ arm_bl2_el3_early_platform_setup();
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ fvp_interconnect_init();
+ /*
+ * Enable coherency in Interconnect for the primary CPU's cluster.
+ */
+ fvp_interconnect_enable();
+}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 9d3c5f6..a257784 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -126,6 +126,13 @@
plat/arm/board/fvp/fvp_trusted_boot.c \
${FVP_SECURITY_SOURCES}
+ifeq (${BL2_AT_EL3},1)
+BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
+ plat/arm/board/fvp/fvp_bl2_el3_setup.c \
+ ${FVP_CPU_LIBS} \
+ ${FVP_INTERCONNECT_SOURCES}
+endif
+
ifeq (${FVP_USE_SP804_TIMER},1)
BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
endif
@@ -165,5 +172,9 @@
# Add support for platform supplied linker script for BL31 build
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+ifneq (${BL2_AT_EL3}, 0)
+ override BL1_SOURCES =
+endif
+
include plat/arm/board/common/board_common.mk
include plat/arm/common/arm_common.mk
diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c
new file mode 100644
index 0000000..e70d115
--- /dev/null
+++ b/plat/arm/common/arm_bl2_el3_setup.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <console.h>
+#include <generic_delay_timer.h>
+#include <plat_arm.h>
+#include <platform.h>
+
+#pragma weak bl2_el3_early_platform_setup
+#pragma weak bl2_el3_plat_arch_setup
+#pragma weak bl2_el3_plat_prepare_exit
+
+static meminfo_t bl2_el3_tzram_layout;
+
+/*
+ * Perform arm specific early platform setup. At this moment we only initialize
+ * the console and the memory layout.
+ */
+void arm_bl2_el3_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE);
+
+ /*
+ * Allow BL2 to see the whole Trusted RAM. This is determined
+ * statically since we cannot rely on BL1 passing this information
+ * in the BL2_AT_EL3 case.
+ */
+ bl2_el3_tzram_layout.total_base = ARM_BL_RAM_BASE;
+ bl2_el3_tzram_layout.total_size = ARM_BL_RAM_SIZE;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_arm_io_setup();
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ arm_bl2_el3_early_platform_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_arm_interconnect_init();
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ plat_arm_interconnect_enter_coherency();
+
+ generic_delay_timer_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void arm_bl2_el3_plat_arch_setup(void)
+{
+ arm_setup_page_tables(bl2_el3_tzram_layout.total_base,
+ bl2_el3_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+
+#ifdef AARCH32
+ enable_mmu_secure(0);
+#else
+ enable_mmu_el3(0);
+#endif
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ arm_bl2_el3_plat_arch_setup();
+}
+
+void bl2_el3_plat_prepare_exit(void)
+{
+}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index fab57f1..e6ce18a 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -150,6 +150,11 @@
drivers/io/io_storage.c \
plat/arm/common/arm_bl2_setup.c \
plat/arm/common/arm_io_storage.c
+
+ifeq (${BL2_AT_EL3},1)
+BL2_SOURCES += plat/arm/common/arm_bl2_el3_setup.c
+endif
+
ifeq (${LOAD_IMAGE_V2},1)
# Because BL1/BL2 execute in AArch64 mode but BL32 in AArch32 we need to use
# the AArch32 descriptors.
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index a87e7c6..cfc0c4f 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -39,11 +39,11 @@
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 797a936..8526752 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 @@
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/common/plat_bl2_el3_common.c b/plat/common/plat_bl2_el3_common.c
new file mode 100644
index 0000000..358a02d
--- /dev/null
+++ b/plat/common/plat_bl2_el3_common.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform_def.h>
+
+/*
+ * The following platform functions are weakly defined. They
+ * are default implementations that allow BL2 to compile in
+ * absence of real definitions. The Platforms may override
+ * with more complex definitions.
+ */
+#pragma weak bl2_el3_plat_prepare_exit
+
+void bl2_el3_plat_prepare_exit(void)
+{
+}
diff --git a/plat/hisilicon/poplar/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c
index c65e29e..7d6f10c 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_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 @@
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 db507c3..7edfab7 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_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_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 540d0aa..125b048 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 3d1ad9b..c0f8371 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 e0b5618..9ce0434 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 ab94cba..468e229 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 @@
};
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 @@
},
};
+#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 @@
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 @@
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 @@
{
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 818e311..2dbbac6 100644
--- a/plat/hisilicon/poplar/platform.mk
+++ b/plat/hisilicon/poplar/platform.mk
@@ -15,6 +15,9 @@
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 @@
-Iinclude/plat/arm/common/ \
-Iplat/hisilicon/poplar \
-Iinclude/common/tbbr \
+ -Iinclude/drivers/synopsys \
-Iinclude/drivers/io
PLAT_BL_COMMON_SOURCES := \
@@ -54,6 +58,8 @@
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 @@
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 abfb5a7..f415f87 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 @@
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 292f0dd..6199eda 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 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 @@
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 be1a9fa..6b3cb6a 100644
--- a/plat/rockchip/common/include/plat_macros.S
+++ b/plat/rockchip/common/include/plat_macros.S
@@ -38,14 +38,14 @@
* 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 @@
/* 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 aa13f87..7109907 100644
--- a/plat/rockchip/common/include/plat_params.h
+++ b/plat/rockchip/common/include/plat_params.h
@@ -56,6 +56,7 @@
PARAM_POWEROFF,
PARAM_SUSPEND_GPIO,
PARAM_SUSPEND_APIO,
+ PARAM_COREBOOT_TABLE,
};
struct apio_info {
@@ -89,4 +90,9 @@
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 b37acb7..65afe87 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 @@
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 5de4680..6e4d5b4 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -49,6 +49,9 @@
${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 d3c6eef..ad204e9 100644
--- a/plat/rockchip/rk3368/platform.mk
+++ b/plat/rockchip/rk3368/platform.mk
@@ -49,6 +49,9 @@
${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 33b9723..9e369e4 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -64,6 +64,9 @@
${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))
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index f99bbf5..e0ddfa8 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -6,7 +6,6 @@
override COLD_BOOT_SINGLE_CPU := 1
override ENABLE_PLAT_COMPAT := 0
-override ERROR_DEPRECATED := 1
override LOAD_IMAGE_V2 := 1
override USE_COHERENT_MEM := 1
override USE_TBBR_DEFS := 1