diff options
55 files changed, 2634 insertions, 348 deletions
@@ -383,6 +383,17 @@ ifdef SCP_BL2 NEED_SCP_BL2 := yes endif +# For AArch32, BL31 is not currently supported. +ifneq (${ARCH},aarch32) + ifdef BL31_SOURCES + # When booting an EL3 payload, there is no need to compile the BL31 image nor + # put it in the FIP. + ifndef EL3_PAYLOAD_BASE + NEED_BL31 := yes + endif + endif +endif + # Process TBB related flags ifneq (${GENERATE_COT},0) # Common cert_create options @@ -434,17 +445,11 @@ NEED_BL2U := yes include bl2u/bl2u.mk endif -# For AArch32, BL31 is not currently supported. -ifneq (${ARCH},aarch32) +ifeq (${NEED_BL31},yes) ifdef BL31_SOURCES -# When booting an EL3 payload, there is no need to compile the BL31 image nor -# put it in the FIP. -ifndef EL3_PAYLOAD_BASE -NEED_BL31 := yes include bl31/bl31.mk endif endif -endif ################################################################################ # Build options checks diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S index 2c453bd2..e4c454b3 100644 --- a/bl1/bl1.ld.S +++ b/bl1/bl1.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL1_RO_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL1_RO_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,7 +28,7 @@ SECTIONS *bl1_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >ROM @@ -88,7 +89,7 @@ SECTIONS "cpu_ops not defined for this platform.") . = BL1_RW_BASE; - ASSERT(BL1_RW_BASE == ALIGN(4096), + ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE), "BL1_RW_BASE address is not aligned on a page boundary.") /* @@ -141,7 +142,7 @@ SECTIONS * 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(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -150,7 +151,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S index f3ab7061..4fe78f9e 100644 --- a/bl2/bl2.ld.S +++ b/bl2/bl2.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL2_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL2_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,7 +28,7 @@ SECTIONS *bl2_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM @@ -41,7 +42,7 @@ SECTIONS KEEP(*(.img_parser_lib_descs)) __PARSER_LIB_DESCS_END__ = .; - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -64,7 +65,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -120,7 +121,7 @@ SECTIONS * 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(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -129,7 +130,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S index efae293d..da587172 100644 --- a/bl2u/bl2u.ld.S +++ b/bl2u/bl2u.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL2U_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL2U_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,14 +28,14 @@ SECTIONS *bl2u_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM .rodata . : { __RODATA_START__ = .; *(.rodata*) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -51,7 +52,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -107,7 +108,7 @@ SECTIONS * 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(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -116,7 +117,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S index 7f442d00..dd046c43 100644 --- a/bl31/bl31.ld.S +++ b/bl31/bl31.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -22,7 +23,7 @@ MEMORY { SECTIONS { . = BL31_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -31,7 +32,7 @@ SECTIONS *bl31_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM @@ -66,7 +67,7 @@ SECTIONS . = ALIGN(8); #include <pubsub_events.h> - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -110,7 +111,7 @@ SECTIONS * executable. No RW data from the next section must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -127,10 +128,10 @@ SECTIONS * There's no need to include this into the RO section of BL31 because it * doesn't need to be accessed by BL31. */ - spm_shim_exceptions : ALIGN(4096) { + spm_shim_exceptions : ALIGN(PAGE_SIZE) { __SPM_SHIM_EXCEPTIONS_START__ = .; *(.spm_shim_exceptions) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __SPM_SHIM_EXCEPTIONS_END__ = .; } >RAM #endif @@ -223,7 +224,7 @@ SECTIONS __SP_IMAGE_XLAT_TABLES_START__ = .; *secure_partition*.o(xlat_table) /* Make sure that the rest of the page is empty. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __SP_IMAGE_XLAT_TABLES_END__ = .; #endif *(xlat_table) @@ -236,7 +237,7 @@ SECTIONS * 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(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; /* * Bakery locks are stored in coherent memory @@ -251,7 +252,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S index fc44d524..e798a0d3 100644 --- a/bl32/sp_min/sp_min.ld.S +++ b/bl32/sp_min/sp_min.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(elf32-littlearm) OUTPUT_ARCH(arm) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL32_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL32_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,7 +28,7 @@ SECTIONS *entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM @@ -54,7 +55,7 @@ SECTIONS . = ALIGN(8); #include <pubsub_events.h> - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -91,7 +92,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory block is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -110,6 +111,10 @@ SECTIONS __DATA_END__ = .; } >RAM +#ifdef BL32_PROGBITS_LIMIT + ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.") +#endif + stacks (NOLOAD) : { __STACKS_START__ = .; *(tzfw_normal_stacks) @@ -186,7 +191,7 @@ SECTIONS * 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(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; /* * Bakery locks are stored in coherent memory @@ -201,7 +206,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S index 2b672efe..d256b46c 100644 --- a/bl32/tsp/tsp.ld.S +++ b/bl32/tsp/tsp.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -19,7 +20,7 @@ MEMORY { SECTIONS { . = BL32_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL32_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -28,14 +29,14 @@ SECTIONS *tsp_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM .rodata . : { __RODATA_START__ = .; *(.rodata*) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -51,7 +52,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -106,7 +107,7 @@ SECTIONS * 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(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -115,7 +116,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/common/bl_common.c b/common/bl_common.c index e4473ed3..b0d1bfa7 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -200,14 +200,14 @@ size_t image_size(unsigned int image_id) #if LOAD_IMAGE_V2 /******************************************************************************* - * Generic function to load an image at a specific address given + * Internal function to load an image at a specific address given * an image ID and extents of free memory. * * If the load is successful then the image information is updated. * * Returns 0 on success, a negative error code otherwise. ******************************************************************************/ -int load_image(unsigned int image_id, image_info_t *image_data) +static int load_image(unsigned int image_id, image_info_t *image_data) { uintptr_t dev_handle; uintptr_t image_handle; @@ -266,17 +266,6 @@ int load_image(unsigned int image_id, image_info_t *image_data) goto exit; } -#if !TRUSTED_BOARD_BOOT - /* - * File has been successfully loaded. - * Flush the image to main memory so that it can be executed later by - * any CPU, regardless of cache and MMU state. - * When TBB is enabled the image is flushed later, after image - * authentication. - */ - flush_dcache_range(image_base, image_size); -#endif /* TRUSTED_BOARD_BOOT */ - INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base, (void *) (image_base + image_size)); @@ -329,18 +318,19 @@ static int load_auth_image_internal(unsigned int image_id, image_data->image_size); return -EAUTH; } +#endif /* TRUSTED_BOARD_BOOT */ /* - * File has been successfully loaded and authenticated. * Flush the image to main memory so that it can be executed later by - * any CPU, regardless of cache and MMU state. - * Do it only for child images, not for the parents (certificates). + * any CPU, regardless of cache and MMU state. If TBB is enabled, then + * the file has been successfully loaded and authenticated and flush + * only for child images, not for the parents (certificates). */ if (!is_parent_image) { flush_dcache_range(image_data->image_base, image_data->image_size); } -#endif /* TRUSTED_BOARD_BOOT */ + return 0; } diff --git a/docs/plat/poplar.rst b/docs/plat/poplar.rst index d7f1fe06..01294783 100644 --- a/docs/plat/poplar.rst +++ b/docs/plat/poplar.rst @@ -11,6 +11,8 @@ of running any commercial set-top solution based on Linux or Android. It supports a premium user experience with up to H.265 HEVC decoding of 4K video at 60 frames per second. +:: + SOC Hisilicon Hi3798CV200 CPU Quad-core ARM Cortex-A53 64 bit DRAM DDR3/3L/4 SDRAM interface, maximum 32-bit data width 2 GB @@ -28,6 +30,8 @@ At the start of the boot sequence, the bootROM executes the so called l-loader binary whose main role is to change the processor state to 64bit mode. This must happen prior invoking the arm trusted firmware: +:: + l-loader --> arm_trusted_firmware --> u-boot How to build @@ -54,10 +58,16 @@ Build Procedure - Prepare the AARCH64 toolchain. - Build u-boot using poplar_defconfig + +.. code:: bash + make CROSS_COMPILE=aarch64-linux-gnu- poplar_defconfig make CROSS_COMPILE=aarch64-linux-gnu- - Build atf providing the previously generated u-boot.bin as the BL33 image + +.. code:: bash + make CROSS_COMPILE=aarch64-linux-gnu- all fip SPD=none PLAT=poplar BL33=u-boot.bin @@ -81,85 +91,86 @@ working firmware to eMMC. Boot trace ========== -Bootrom start -Boot Media: eMMC -Decrypt auxiliary code ...OK - -lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000 - -Entry boot auxiliary code - -Auxiliary code - v1.00 -DDR code - V1.1.2 20160205 -Build: Mar 24 2016 - 17:09:44 -Reg Version: v134 -Reg Time: 2016/03/18 09:44:55 -Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg - -Boot auxiliary code success -Bootrom success - -LOADER: Switched to aarch64 mode -LOADER: Entering ARM TRUSTED FIRMWARE -LOADER: CPU0 executes at 0x000ce000 - -INFO: BL1: 0xe1000 - 0xe7000 [size = 24576] -NOTICE: Booting Trusted Firmware -NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60 -NOTICE: BL1: Built : 17:51:33, Apr 30 2017 -INFO: BL1: RAM 0xe1000 - 0xe7000 -INFO: BL1: Loading BL2 -INFO: Loading image id=1 at address 0xe9000 -INFO: Image id=1 loaded at address 0xe9000, size = 0x5008 -NOTICE: BL1: Booting BL2 -INFO: Entry point address = 0xe9000 -INFO: SPSR = 0x3c5 -NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60 -NOTICE: BL2: Built : 17:51:33, Apr 30 2017 -INFO: BL2: Loading BL31 -INFO: Loading image id=3 at address 0x129000 -INFO: Image id=3 loaded at address 0x129000, size = 0x8038 -INFO: BL2: Loading BL33 -INFO: Loading image id=5 at address 0x37000000 -INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17 -NOTICE: BL1: Booting BL31 -INFO: Entry point address = 0x129000 -INFO: SPSR = 0x3cd -INFO: Boot bl33 from 0x37000000 for 364311 Bytes -NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60 -NOTICE: BL31: Built : 17:51:33, Apr 30 2017 -INFO: BL31: Initializing runtime services -INFO: BL31: Preparing for EL3 exit to normal world -INFO: Entry point address = 0x37000000 -INFO: SPSR = 0x3c9 - - -U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar - -Model: HiSilicon Poplar Development Board -BOARD: Hisilicon HI3798cv200 Poplar -DRAM: 1 GiB -MMC: Hisilicon DWMMC: 0 -In: serial@f8b00000 -Out: serial@f8b00000 -Err: serial@f8b00000 -Net: Net Initialization Skipped -No ethernet found. - -Hit any key to stop autoboot: 0 -starting USB... -USB0: USB EHCI 1.00 -scanning bus 0 for devices... 1 USB Device(s) found -USB1: USB EHCI 1.00 -scanning bus 1 for devices... 4 USB Device(s) found - scanning usb for storage devices... 1 Storage Device(s) found - scanning usb for ethernet devices... 1 Ethernet Device(s) found - -USB device 0: - Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade - Type: Removable Hard Disk - Capacity: 7632.0 MB = 7.4 GB (15630336 x 512) -... is now current device -Scanning usb 0:1... -=> - +:: + + Bootrom start + Boot Media: eMMC + Decrypt auxiliary code ...OK + + lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000 + + Entry boot auxiliary code + + Auxiliary code - v1.00 + DDR code - V1.1.2 20160205 + Build: Mar 24 2016 - 17:09:44 + Reg Version: v134 + Reg Time: 2016/03/18 09:44:55 + Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg + + Boot auxiliary code success + Bootrom success + + LOADER: Switched to aarch64 mode + LOADER: Entering ARM TRUSTED FIRMWARE + LOADER: CPU0 executes at 0x000ce000 + + INFO: BL1: 0xe1000 - 0xe7000 [size = 24576] + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL1: Built : 17:51:33, Apr 30 2017 + INFO: BL1: RAM 0xe1000 - 0xe7000 + INFO: BL1: Loading BL2 + INFO: Loading image id=1 at address 0xe9000 + INFO: Image id=1 loaded at address 0xe9000, size = 0x5008 + NOTICE: BL1: Booting BL2 + INFO: Entry point address = 0xe9000 + INFO: SPSR = 0x3c5 + NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL2: Built : 17:51:33, Apr 30 2017 + INFO: BL2: Loading BL31 + INFO: Loading image id=3 at address 0x129000 + INFO: Image id=3 loaded at address 0x129000, size = 0x8038 + INFO: BL2: Loading BL33 + INFO: Loading image id=5 at address 0x37000000 + INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17 + NOTICE: BL1: Booting BL31 + INFO: Entry point address = 0x129000 + INFO: SPSR = 0x3cd + INFO: Boot bl33 from 0x37000000 for 364311 Bytes + NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL31: Built : 17:51:33, Apr 30 2017 + INFO: BL31: Initializing runtime services + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x37000000 + INFO: SPSR = 0x3c9 + + + U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar + + Model: HiSilicon Poplar Development Board + BOARD: Hisilicon HI3798cv200 Poplar + DRAM: 1 GiB + MMC: Hisilicon DWMMC: 0 + In: serial@f8b00000 + Out: serial@f8b00000 + Err: serial@f8b00000 + Net: Net Initialization Skipped + No ethernet found. + + Hit any key to stop autoboot: 0 + starting USB... + USB0: USB EHCI 1.00 + scanning bus 0 for devices... 1 USB Device(s) found + USB1: USB EHCI 1.00 + scanning bus 1 for devices... 4 USB Device(s) found + scanning usb for storage devices... 1 Storage Device(s) found + scanning usb for ethernet devices... 1 Ethernet Device(s) found + + USB device 0: + Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade + Type: Removable Hard Disk + Capacity: 7632.0 MB = 7.4 GB (15630336 x 512) + ... is now current device + Scanning usb 0:1... + => diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst new file mode 100644 index 00000000..219faaff --- /dev/null +++ b/docs/plat/rpi3.rst @@ -0,0 +1,364 @@ +Arm Trusted Firmware for Raspberry Pi 3 +======================================= + +.. section-numbering:: + :suffix: . + +.. contents:: + +The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four +Cortex-A53 cores, which makes it possible to have a port of the Arm Trusted +Firmware. + +The following instructions explain how to use this port of the Trusted Firmware +with the default distribution of `Raspbian`_ because that's the distribution +officially supported by the Raspberry Pi Foundation. At the moment of writing +this, the officially supported kernel is a AArch32 kernel. This doesn't mean +that this port of the Trusted Firmware can't boot a AArch64 kernel. The `Linux +tree fork`_ maintained by the Foundation can be compiled for AArch64 by +following the steps in `AArch64 kernel build instructions`_. + +**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM, +which is available from both the Non-secure and Secure worlds. This port +shouldn't be considered more than a prototype to play with and implement +elements like PSCI to support the Linux kernel. + +Design +------ + +The SoC used by the Raspberry Pi 3 is the Broadcom BCM2837. It is a SoC with a +VideoCore IV that acts as primary processor (and loads everything from the SD +card) and is located between all Arm cores and the DRAM. Check the `Raspberry Pi +3 documentation`_ for more information. + +This explains why it is possible to change the execution state (AArch64/AArch32) +depending on a few files on the SD card. We only care about the cases in which +the cores boot in AArch64 mode. + +The rules are simple: + +- If a file called ``kernel8.img`` is located on the ``boot`` partition of the + SD card, it will load it and execute in EL2 in AArch64. Basically, it executes + a `default AArch64 stub`_ at address **0x0** that jumps to the kernel. + +- If there is also a file called ``armstub8.bin``, it will load it at address + **0x0** (instead of the default stub) and execute it in EL3 in AArch64. All + the cores are powered on at the same time and start at address **0x0**. + +This means that we can use the default AArch32 kernel provided in the official +`Raspbian`_ distribution by renaming it to ``kernel8.img``, while the Trusted +Firmware and anything else we need is in ``armstub8.bin``. This way we can +forget about the default bootstrap code. When using a AArch64 kernel, it is only +needed to make sure that the name on the SD card is ``kernel8.img``. + +Ideally, we want to load the kernel and have all cores available, which means +that we need to make the secondary cores work in the way the kernel expects, as +explained in `Secondary cores`_. In practice, a small bootstrap is needed +between the Trusted Firmware and the kernel. + +To get the most out of a AArch32 kernel, we want to boot it in Hypervisor mode +in AArch32. This means that BL33 can't be in EL2 in AArch64 mode. The +architecture specifies that AArch32 Hypervisor mode isn't present when AArch64 +is used for EL2. When using a AArch64 kernel, it should simply start in EL2. + +Placement of images +~~~~~~~~~~~~~~~~~~~ + +The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding +between them so that the addresses they are loaded to match the ones specified +when compiling the Trusted Firmware. + +The device tree block is loaded by the VideoCore loader from an appropriate +file, but we can specify the address it is loaded to in ``config.txt``. + +The file ``kernel8.img`` contains a kernel image that is loaded to the address +specified in ``config.txt``. The `Linux kernel tree`_ has information about how +a AArch32 Linux kernel image is loaded in ``Documentation/arm/Booting``: + +:: + + The zImage may also be placed in system RAM and called there. The + kernel should be placed in the first 128MiB of RAM. It is recommended + that it is loaded above 32MiB in order to avoid the need to relocate + prior to decompression, which will make the boot process slightly + faster. + +There are no similar restrictions for AArch64 kernels, as specified in the file +``Documentation/arm64/booting.txt``. + +This means that we need to avoid the first 128 MiB of RAM when placing the +Trusted Firmware images (and specially the first 32 MiB, as they are directly +used to place the uncompressed AArch32 kernel image. This way, both AArch32 and +AArch64 kernels can be placed at the same address. + +In the end, the images look like the following diagram when placed in memory. +All addresses are Physical Addresses from the point of view of the Arm cores. +Again, note that this is all just part of the same DRAM that goes from +**0x00000000** to **0x3F000000**, it just has different names to simulate a real +secure platform! + +:: + + 0x00000000 +-----------------+ + | ROM | BL1 + 0x00010000 +-----------------+ + | FIP | + 0x00200000 +-----------------+ + | | + | ... | + | | + 0x01000000 +-----------------+ + | Kernel | + +-----------------+ + | | + | ... | + | | + 0x02000000 +-----------------+ + | DTB | + +-----------------+ + | | + | ... | + | | + 0x10000000 +-----------------+ + | Secure SRAM | BL2, BL31 + 0x10100000 +-----------------+ + | Secure DRAM | + 0x10300000 +-----------------+ + | Non-secure DRAM | BL33 + 0x11000000 +-----------------+ + | | + | ... | + | | + 0x3F000000 +-----------------+ + | I/O | + 0x40000000 +-----------------+ + +The area between **0x10000000** and **0x11000000** has to be protected so that +the kernel doesn't use it. That is done by adding ``memmap=256M$16M`` to the +command line passed to the kernel. See the `Setup SD card`_ instructions to see +how to do it. + +The last 16 MiB of DRAM can only be accessed by the VideoCore, that has +different mappings than the Arm cores in which the I/O addresses don't overlap +the DRAM. The memory reserved to be used by the VideoCore is always placed at +the end of the DRAM, so this space isn't wasted. + +Considering the 128 MiB allocated to the GPU and the 16 MiB allocated for the +Trusted Firmware, there are 880 MiB available for Linux. + +Boot sequence +~~~~~~~~~~~~~ + +The boot sequence of the Trusted Firmware is the usual one except when booting +a AArch32 kernel. In that case, BL33 is booted in AArch32 Hypervisor mode so +that it can jump to the kernel in the same mode and let it take over that +privilege level. If BL33 was running in EL2 in AArch64 (as in the default +bootflow of the Trusted Firmware) it could only jump to the kernel in AArch32 in +Supervisor mode. + +The `Linux kernel tree`_ has instructions on how to jump to the Linux kernel +in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The +bootstrap should take care of this. + +Secondary cores +~~~~~~~~~~~~~~~ + +The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to +use mailboxes to trap the secondary cores until they are ready to jump to the +kernel. This mailbox is located at a different address in the AArch32 default +kernel than in the AArch64 kernel. + +Also, this port of the Trusted Firmware has another Trusted Mailbox in Shared BL +RAM. During cold boot, all secondary cores wait in a loop until they are given +given an address to jump to in this Mailbox (``bl31_warm_entrypoint``). + +Once BL31 has finished and the primary core has jumped to the BL33 payload, it +has to call ``PSCI_CPU_ON`` to release the secondary CPUs from the wait loop. +The payload then makes them wait in another waitloop listening from messages +from the kernel. When the primary CPU jumps into the kernel, it will send an +address to the mailbox so that the secondary CPUs jump to it and are recognised +by the kernel. + +Build Instructions +------------------ + +To boot a AArch64 kernel, only the AArch64 toolchain is required. + +To boot a AArch32 kernel, both AArch64 and AArch32 toolchains are required. The +AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit +kernel. + +First, clone and compile `Raspberry Pi 3 Arm Trusted Firmware bootstrap`_. +Choose the one needed for the architecture of your kernel. + +Then compile the Arm Trusted Firmware. For a AArch32 kernel, use the following +command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + RPI3_BL33_IN_AARCH32=1 \ + BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin \ + all fip + +For a AArch64 kernel, use this other command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin \ + all fip + +Then, join BL1 and the FIP with the following instructions (replace ``release`` +by ``debug`` if you set the build option ``DEBUG=1``): + +.. code:: shell + + cp build/rpi3/release/bl1.bin bl1.pad.bin + truncate --size=65536 bl1.pad.bin + cat bl1.pad.bin build/rpi3/release/fip.bin > armstub8.bin + +The resulting file, ``armstub8.bin``, contains BL1 and the FIP in the place they +need to be for the Trusted Firmware to boot correctly. Now, follow the +instructions in `Setup SD card`_. + +The following build options are supported: + +- ``PRELOADED_BL33_BASE``: Specially useful because the file ``kernel8.img`` can + be loaded anywhere by modifying the file ``config.txt``. It doesn't have to + contain a kernel, it could have any arbitrary payload. + +- ``RESET_TO_BL31``: Set to 1 by default. If using a 32-bit kernel like + `Raspbian`_, the space used by BL1 can overwritten by the kernel when it is + being loaded. Even when using a AArch64 kernel the region used by + BL1 isn't protected and the kernel could overwrite it. The space used by BL31 + is reserved by the command line passed to the kernel. + +- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image. + By default this option is 0, which means that the Trusted Firmware will jump + to BL33 in EL2 in AArch64 mode. If set to 1, it will jump to BL33 in + Hypervisor in AArch32 mode. + +The following is not currently supported: + +- AArch32 for the Trusted Firmware itself. + +- ``EL3_PAYLOAD_BASE``: The reason is that you can already load anything to any + address by changing the file ``armstub8.bin``, so there's no point in using + the Trusted Firmware in this case. + +- ``LOAD_IMAGE_V2=0``: Only version 2 is supported. + +AArch64 kernel build instructions +--------------------------------- + +The following instructions show how to install and run a AArch64 kernel by +using a SD card with the default `Raspbian`_ install as base. Skip them if you +want to use the default 32-bit kernel. + +Note that this system won't be fully 64-bit because all the tools in the +filesystem are 32-bit binaries, but it's a quick way to get it working, and it +allows the user to run 64-bit binaries in addition to 32-bit binaries. + +1. Clone the `Linux tree fork`_ maintained by the Raspberry Pi Foundation. To + speed things up, do a shallow clone of the desired branch. + +.. code:: shell + + git clone --depth=1 -b rpi-4.14.y https://github.com/raspberrypi/linux + cd linux + +2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is + 1.5 times the number of CPUs in your computer. This may take some time to + finish. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig + make -j 6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- + +3. Copy the kernel image and the device tree to the SD card. Replace the path + by the corresponding path in your computers to the ``boot`` partition of the + SD card. + +.. code:: shell + + cp arch/arm64/boot/Image /path/to/boot/kernel8.img + cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/ + +4. Install the kernel modules. Replace the path by the corresponding path to the + filesystem partition of the SD card on your computer. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ + INSTALL_MOD_PATH=/path/to/filesystem modules_install + +5. Follow the instructions in `Setup SD card`_ except for the step of renaming + the existing ``kernel7.img`` (we have already copied a AArch64 kernel). + +Setup SD card +------------- + +The instructions assume that you have an SD card with a fresh install of +`Raspbian`_ (or that, at least, the ``boot`` partition is untouched, or nearly +untouched). They have been tested with the image available in 2017-09-07. + +1. Insert the SD card and open the ``boot`` partition. + +2. Rename ``kernel7.img`` to ``kernel8.img``. This tricks the VideoCore + bootloader into booting the Arm cores in AArch64 mode, like the Trusted + Firmware needs, even though the kernel is not compiled for AArch64. + +3. Copy ``armstub8.bin`` here. When ``kernel8.img`` is available, The VideoCore + bootloader will look for a file called ``armstub8.bin`` and load it at + address **0x0** instead of a predefined one. + +4. Open ``cmdline.txt`` and add ``memmap=256M$16M`` to prevent the kernel from + using the memory needed by the Trusted Firmware. If you want to enable the + serial port "Mini UART", make sure that this file also contains + ``console=serial0,115200 console=tty1``. + + Note that the 16 MiB reserved this way won't be available for Linux, the same + way as the memory reserved in DRAM for the GPU isn't available. + +5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1`` + is only needed to enable debugging through the Mini UART): + +:: + + enable_uart=1 + kernel_address=0x01000000 + device_tree_address=0x02000000 + +If you connect a serial cable to the Mini UART and your computer, and connect +to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some +text. In the case of an AArch32 kernel, you should see something like this: + +:: + + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL1: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL2 + NOTICE: BL2: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL2: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL31 + NOTICE: BL31: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL31: Built : 00:09:25, Nov 6 2017 + [ 0.266484] bcm2835-aux-uart 3f215040.serial: could not get clk: -517 + + Raspbian GNU/Linux 9 raspberrypi ttyS0 + raspberrypi login: + +Just enter your credentials, everything should work as expected. Note that the +HDMI output won't show any text during boot. + +.. _default Arm stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub7.S +.. _default AArch64 stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S +.. _Linux kernel tree: https://github.com/torvalds/linux +.. _Linux tree fork: https://github.com/raspberrypi/linux +.. _Raspberry Pi 3: https://www.raspberrypi.org/products/raspberry-pi-3-model-b/ +.. _Raspberry Pi 3 Arm Trusted Firmware bootstrap: https://github.com/AntonioND/rpi3-arm-tf-bootstrap +.. _Raspberry Pi 3 documentation: https://www.raspberrypi.org/documentation/ +.. _Raspbian: https://www.raspberrypi.org/downloads/raspbian/ diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 04acbe7f..13f09641 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -1223,7 +1223,7 @@ corrupted binaries. make ARCH=aarch64 PLAT=juno LOAD_IMAGE_V2=1 JUNO_AARCH32_EL3_RUNTIME=1 \ BL33=<path-to-juno32-oe-uboot>/SOFTWARE/bl33-uboot.bin \ - SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin SPD=tspd \ + SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin \ BL32=<path-to-bl32>/bl32.bin all fip The resulting BL1 and FIP images may be found in: diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 15ffc578..8915ba06 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -205,7 +205,6 @@ int is_mem_free(uintptr_t free_base, size_t free_size, #if LOAD_IMAGE_V2 -int load_image(unsigned int image_id, image_info_t *image_data); int load_auth_image(unsigned int image_id, image_info_t *image_data); #else diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h index 73a9c533..ba3e3603 100644 --- a/include/lib/xlat_tables/xlat_tables_v2.h +++ b/include/lib/xlat_tables/xlat_tables_v2.h @@ -168,21 +168,28 @@ typedef struct xlat_ctx xlat_ctx_t; _xlat_tables_count, \ _virt_addr_space_size, \ _phy_addr_space_size, \ - IMAGE_XLAT_DEFAULT_REGIME) + IMAGE_XLAT_DEFAULT_REGIME, \ + "xlat_table") /* - * Same as REGISTER_XLAT_CONTEXT plus the additional parameter _xlat_regime to - * specify the translation regime managed by this xlat_ctx_t instance. The - * values are the one from xlat_regime_t enumeration. + * Same as REGISTER_XLAT_CONTEXT plus the additional parameters: + * + * _xlat_regime: + * Specify the translation regime managed by this xlat_ctx_t instance. The + * values are the one from xlat_regime_t enumeration. + * + * _section_name: + * Specify the name of the section where the translation tables have to be + * placed by the linker. */ #define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \ _virt_addr_space_size, _phy_addr_space_size, \ - _xlat_regime) \ + _xlat_regime, _section_name) \ _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \ _xlat_tables_count, \ _virt_addr_space_size, \ _phy_addr_space_size, \ - _xlat_regime) + _xlat_regime, _section_name) /****************************************************************************** * Generic translation table APIs. diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h index 96dee1a0..1be99b71 100644 --- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h +++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h @@ -123,7 +123,7 @@ struct xlat_ctx { #define _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, _xlat_tables_count, \ _virt_addr_space_size, _phy_addr_space_size, \ - _xlat_regime) \ + _xlat_regime, _section_name) \ CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size), \ assert_invalid_virtual_addr_space_size_for_##_ctx_name); \ \ @@ -134,7 +134,7 @@ struct xlat_ctx { \ static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \ [XLAT_TABLE_ENTRIES] \ - __aligned(XLAT_TABLE_SIZE) __section("xlat_table"); \ + __aligned(XLAT_TABLE_SIZE) __section(_section_name); \ \ static uint64_t _ctx_name##_base_xlat_table \ [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \ diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index 97a1af4b..69eb727f 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -90,10 +90,14 @@ * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a * little space for growth. */ -#if ENABLE_SPM -#define PLAT_ARM_MAX_BL31_SIZE 0x28000 -#else #define PLAT_ARM_MAX_BL31_SIZE 0x1D000 + +#ifdef AARCH32 +/* + * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure + * Payload. + */ +# define PLAT_ARM_MAX_BL32_SIZE 0x1D000 #endif #endif /* ARM_BOARD_OPTIMISE_MEM */ diff --git a/include/plat/arm/common/arm_common.ld.S b/include/plat/arm/common/arm_common.ld.S index 478b08c2..6edfa099 100644 --- a/include/plat/arm/common/arm_common.ld.S +++ b/include/plat/arm/common/arm_common.ld.S @@ -6,6 +6,8 @@ #ifndef __ARM_COMMON_LD_S__ #define __ARM_COMMON_LD_S__ +#include <xlat_tables_defs.h> + MEMORY { EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE } @@ -13,14 +15,14 @@ MEMORY { SECTIONS { . = ARM_EL3_TZC_DRAM1_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.") - el3_tzc_dram (NOLOAD) : ALIGN(4096) { + el3_tzc_dram (NOLOAD) : ALIGN(PAGE_SIZE) { __EL3_SEC_DRAM_START__ = .; *(arm_el3_tzc_dram) __EL3_SEC_DRAM_UNALIGNED_END__ = .; - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __EL3_SEC_DRAM_END__ = .; } >EL3_SEC_DRAM } diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index b8955afc..78875259 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -326,14 +326,21 @@ /******************************************************************************* * BL2 specific defines. ******************************************************************************/ -#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME)) +#if ARM_BL31_IN_DRAM /* - * For AArch32 BL31 is not applicable. * For AArch64 BL31 is loaded in the DRAM. * Put BL2 just below BL1. */ #define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE) #define BL2_LIMIT BL1_RW_BASE + +#elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME +/* + * Put BL2 just below BL32. + */ +#define BL2_BASE (BL32_BASE - PLAT_ARM_MAX_BL2_SIZE) +#define BL2_LIMIT BL32_BASE + #else /* * Put BL2 just below BL31. @@ -370,76 +377,86 @@ #define BL31_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) #endif +#if defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME /******************************************************************************* - * BL32 specific defines. + * BL32 specific defines for EL3 runtime in AArch32 mode + ******************************************************************************/ +# if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME +/* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM to BL32 */ +# define BL32_BASE ARM_BL_RAM_BASE +# define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +# else +/* Put BL32 at the top of the Trusted SRAM.*/ +# define BL32_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + PLAT_ARM_MAX_BL32_SIZE) +# define BL32_PROGBITS_LIMIT BL1_RW_BASE +# define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +# endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */ + +#else +/******************************************************************************* + * BL32 specific defines for EL3 runtime in AArch64 mode ******************************************************************************/ /* * On ARM standard platforms, the TSP can execute from Trusted SRAM, * Trusted DRAM (if available) or the DRAM region secured by the TrustZone * controller. */ -#if ENABLE_SPM -# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) -# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) -# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) -# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ +# if ENABLE_SPM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ ARM_AP_TZC_DRAM1_SIZE) -#elif ARM_BL31_IN_DRAM -# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \ +# elif ARM_BL31_IN_DRAM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \ PLAT_ARM_MAX_BL31_SIZE) -# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \ +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \ PLAT_ARM_MAX_BL31_SIZE) -# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + \ +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + \ PLAT_ARM_MAX_BL31_SIZE) -# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ ARM_AP_TZC_DRAM1_SIZE) -#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID -# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE -# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE -# define TSP_PROGBITS_LIMIT BL2_BASE -# define BL32_BASE ARM_BL_RAM_BASE -# define BL32_LIMIT BL31_BASE -#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID -# define TSP_SEC_MEM_BASE PLAT_ARM_TRUSTED_DRAM_BASE -# define TSP_SEC_MEM_SIZE PLAT_ARM_TRUSTED_DRAM_SIZE -# define BL32_BASE PLAT_ARM_TRUSTED_DRAM_BASE -# define BL32_LIMIT (PLAT_ARM_TRUSTED_DRAM_BASE \ +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID +# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE +# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE +# define TSP_PROGBITS_LIMIT BL2_BASE +# define BL32_BASE ARM_BL_RAM_BASE +# define BL32_LIMIT BL31_BASE +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID +# define TSP_SEC_MEM_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define TSP_SEC_MEM_SIZE PLAT_ARM_TRUSTED_DRAM_SIZE +# define BL32_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define BL32_LIMIT (PLAT_ARM_TRUSTED_DRAM_BASE \ + (1 << 21)) -#elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID -# define TSP_SEC_MEM_BASE ARM_AP_TZC_DRAM1_BASE -# define TSP_SEC_MEM_SIZE ARM_AP_TZC_DRAM1_SIZE -# define BL32_BASE ARM_AP_TZC_DRAM1_BASE -# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ +# elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID +# define TSP_SEC_MEM_BASE ARM_AP_TZC_DRAM1_BASE +# define TSP_SEC_MEM_SIZE ARM_AP_TZC_DRAM1_SIZE +# define BL32_BASE ARM_AP_TZC_DRAM1_BASE +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ ARM_AP_TZC_DRAM1_SIZE) -#else -# error "Unsupported ARM_TSP_RAM_LOCATION_ID value" -#endif +# else +# error "Unsupported ARM_TSP_RAM_LOCATION_ID value" +# endif +#endif /* AARCH32 || JUNO_AARCH32_EL3_RUNTIME */ /* * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no * SPD and no SPM, as they are the only ones that can be used as BL32. */ -#ifndef AARCH32 +#if !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME) # if defined(SPD_none) && !ENABLE_SPM # undef BL32_BASE -# endif -#endif +# endif /* defined(SPD_none) && !ENABLE_SPM */ +#endif /* !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME) */ /******************************************************************************* * FWU Images: NS_BL1U, BL2U & NS_BL2U defines. ******************************************************************************/ #define BL2U_BASE BL2_BASE -#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME)) -/* - * For AArch32 BL31 is not applicable. - * For AArch64 BL31 is loaded in the DRAM. - * BL2U extends up to BL1. - */ -#define BL2U_LIMIT BL1_RW_BASE -#else -/* BL2U extends up to BL31. */ -#define BL2U_LIMIT BL31_BASE -#endif +#define BL2U_LIMIT BL2_LIMIT + #define NS_BL2U_BASE ARM_NS_DRAM1_BASE #define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + 0x03EB8000) diff --git a/include/plat/arm/common/arm_spm_def.h b/include/plat/arm/common/arm_spm_def.h index 83277a6c..3f5c958d 100644 --- a/include/plat/arm/common/arm_spm_def.h +++ b/include/plat/arm/common/arm_spm_def.h @@ -98,6 +98,12 @@ /* Total number of memory regions with distinct properties */ #define ARM_SP_IMAGE_NUM_MEM_REGIONS 6 +/* + * Name of the section to put the translation tables used by the S-EL1/S-EL0 + * context of a Secure Partition. + */ +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "arm_el3_tzc_dram" + /* Cookies passed to the Secure Partition at boot. Not used by ARM platforms. */ #define PLAT_SPM_COOKIE_0 ULL(0) #define PLAT_SPM_COOKIE_1 ULL(0) diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h index 2c8c7cd8..738979eb 100644 --- a/include/services/spm_svc.h +++ b/include/services/spm_svc.h @@ -32,24 +32,24 @@ * Manager from the Secure Partition(s). These services enable a partition to * handle delegated events and request privileged operations from the manager. */ -#define SPM_VERSION_AARCH32 U(0x84000060) -#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061) -#define SP_MEM_ATTRIBUTES_GET_AARCH64 U(0xC4000064) -#define SP_MEM_ATTRIBUTES_SET_AARCH64 U(0xC4000065) +#define SPM_VERSION_AARCH32 U(0x84000060) +#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061) +#define SP_MEMORY_ATTRIBUTES_GET_AARCH64 U(0xC4000064) +#define SP_MEMORY_ATTRIBUTES_SET_AARCH64 U(0xC4000065) /* - * Macros used by SP_MEM_ATTRIBUTES_SET_AARCH64. + * Macros used by SP_MEMORY_ATTRIBUTES_SET_AARCH64. */ -#define SP_MEM_ATTR_ACCESS_NOACCESS U(0) -#define SP_MEM_ATTR_ACCESS_RW U(1) +#define SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS U(0) +#define SP_MEMORY_ATTRIBUTES_ACCESS_RW U(1) /* Value U(2) is reserved. */ -#define SP_MEM_ATTR_ACCESS_RO U(3) -#define SP_MEM_ATTR_ACCESS_MASK U(3) -#define SP_MEM_ATTR_ACCESS_SHIFT 0 +#define SP_MEMORY_ATTRIBUTES_ACCESS_RO U(3) +#define SP_MEMORY_ATTRIBUTES_ACCESS_MASK U(3) +#define SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT 0 -#define SP_MEM_ATTR_EXEC (U(0) << 2) -#define SP_MEM_ATTR_NON_EXEC (U(1) << 2) +#define SP_MEMORY_ATTRIBUTES_EXEC (U(0) << 2) +#define SP_MEMORY_ATTRIBUTES_NON_EXEC (U(1) << 2) /* * SMC IDs defined in [1] for accessing secure partition services from the @@ -59,8 +59,8 @@ #define SP_VERSION_AARCH64 U(0xC4000040) #define SP_VERSION_AARCH32 U(0x84000040) -#define SP_COMMUNICATE_AARCH64 U(0xC4000041) -#define SP_COMMUNICATE_AARCH32 U(0x84000041) +#define MM_COMMUNICATE_AARCH64 U(0xC4000041) +#define MM_COMMUNICATE_AARCH32 U(0x84000041) /* SPM error codes. */ #define SPM_SUCCESS 0 diff --git a/lib/cpus/aarch32/cortex_a53.S b/lib/cpus/aarch32/cortex_a53.S index 74cedc35..1647e169 100644 --- a/lib/cpus/aarch32/cortex_a53.S +++ b/lib/cpus/aarch32/cortex_a53.S @@ -174,7 +174,7 @@ func cortex_a53_core_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) @@ -204,7 +204,7 @@ func cortex_a53_cluster_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S index b5189e77..64a6d674 100644 --- a/lib/cpus/aarch32/cortex_a57.S +++ b/lib/cpus/aarch32/cortex_a57.S @@ -406,7 +406,7 @@ func cortex_a57_core_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) @@ -448,7 +448,7 @@ func cortex_a57_cluster_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S index 69cc2ea5..75505206 100644 --- a/lib/cpus/aarch32/cortex_a72.S +++ b/lib/cpus/aarch32/cortex_a72.S @@ -120,7 +120,7 @@ func cortex_a72_core_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) @@ -167,7 +167,7 @@ func cortex_a72_cluster_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) diff --git a/maintainers.rst b/maintainers.rst index 701ea17e..04ab695e 100644 --- a/maintainers.rst +++ b/maintainers.rst @@ -21,8 +21,8 @@ Jens Wiklander (jens.wiklander@linaro.org, `jenswi-linaro`_) Files: -- docs/spd/optee-dispatcher.md -- docs/plat/qemu.md +- docs/plat/qemu.rst +- docs/spd/optee-dispatcher.rst - services/spd/opteed/\* - plat/qemu/\* @@ -33,8 +33,9 @@ Varun Wadekar (vwadekar@nvidia.com, `vwadekar`_) Files: -- docs/spd/tlk-dispatcher.md -- docs/spd/trusty-dispatcher.md +- docs/plat/nvidia-tegra.rst +- docs/spd/tlk-dispatcher.rst +- docs/spd/trusty-dispatcher.rst - include/bl32/payloads/tlk.h - include/lib/cpus/aarch64/denver.h - lib/cpus/aarch64/denver.S @@ -49,8 +50,9 @@ Haojian Zhuang (haojian.zhuang@linaro.org, `hzhuang1`_) Files: -- docs/plat/hikey.md -- docs/plat/hikey960.md +- docs/plat/hikey.rst +- docs/plat/hikey960.rst +- docs/plat/poplar.rst - drivers/emmc/\* - drivers/partition/\* - drivers/synopsys/emmc/\* @@ -71,24 +73,44 @@ Files: - plat/mediatek/\* +Raspberry Pi 3 platform sub-maintainer +-------------------------------------- + +Antonio Niño DÃaz (antonio.ninodiaz@arm.com, `antonio-nino-diaz-arm`_) + +Files: + +- docs/plat/rpi3.rst +- plat/rpi3/\* + RockChip platform sub-maintainer -------------------------------- Tony Xie (tony.xie@rock-chips.com, `TonyXie06`_ -or `rkchrome`_) +or `rockchip-linux`_) Files: - plat/rockchip/\* +UniPhier platform sub-maintainer +-------------------------------- + +Masahiro Yamada (yamada.masahiro@socionext.com, `masahir0y`_) + +Files: + +- docs/plat/socionext-uniphier.rst +- plat/socionext/\* + Xilinx platform sub-maintainer ------------------------------ -Sören Brinkmann (soren.brinkmann@xilinx.com, `sorenb-xlnx`_) +Siva Durga Prasad Paladugu (siva.durga.paladugu@xilinx.com, `sivadur`_) Files: -- docs/plat/xilinx-zynqmp.md +- docs/plat/xilinx-zynqmp.rst - plat/xilinx/\* ARMv7 architecture sub-maintainer @@ -96,13 +118,15 @@ ARMv7 architecture sub-maintainer Etienne Carriere (etienne.carriere@linaro.org, `etienne-lms`_) +.. _antonio-nino-diaz-arm: https://github.com/antonio-nino-diaz-arm .. _danh-arm: https://github.com/danh-arm .. _davidcunado-arm: https://github.com/davidcunado-arm .. _jenswi-linaro: https://github.com/jenswi-linaro .. _vwadekar: https://github.com/vwadekar .. _hzhuang1: https://github.com/hzhuang1 +.. _masahir0y: https://github.com/masahir0y .. _mtk09422: https://github.com/mtk09422 .. _TonyXie06: https://github.com/TonyXie06 -.. _rkchrome: https://github.com/rkchrome -.. _sorenb-xlnx: https://github.com/sorenb-xlnx +.. _sivadur: https://github.com/sivadur +.. _rockchip-linux: https://github.com/rockchip-linux .. _etienne-lms: https://github.com/etienne-lms diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 1d20080e..fa0d17de 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -24,9 +24,6 @@ ARM_ARCH_MINOR := 0 # in EL3. The platform port can change this value if needed. ARM_GIC_ARCH := 2 -# Flag used to indicate if ASM_ASSERTION should be enabled for the build. -ASM_ASSERTION := 0 - # Base commit to perform code check on BASE_COMMIT := origin/master diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk index b13afe48..6e6e2739 100644 --- a/make_helpers/tbbr/tbbr_tools.mk +++ b/make_helpers/tbbr/tbbr_tools.mk @@ -77,6 +77,7 @@ ifneq (${SCP_BL2},) endif ifeq (${ARCH},aarch64) +ifeq (${NEED_BL31},yes) # Add the BL31 CoT (key cert + img cert + image) $(if ${BL31},$(eval $(call CERT_ADD_CMD_OPT,${BL31},--soc-fw,true)),\ $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,31),--soc-fw,true))) @@ -86,6 +87,7 @@ $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert)) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) endif +endif # Add the BL32 CoT (key cert + img cert + image) ifeq (${NEED_BL32},yes) diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c index 13bd8f23..72845843 100644 --- a/plat/arm/board/fvp/fvp_pm.c +++ b/plat/arm/board/fvp/fvp_pm.c @@ -402,12 +402,20 @@ plat_psci_ops_t plat_arm_psci_pm_ops = { .validate_ns_entrypoint = arm_validate_psci_entrypoint, .translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr, .get_node_hw_state = fvp_node_hw_state, +#if !ARM_BL31_IN_DRAM + /* + * The TrustZone Controller is set up during the warmboot sequence after + * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM + * this is not a problem but, if it is in TZC-secured DRAM, it tries to + * reconfigure the same memory it is running on, causing an exception. + */ .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state, -/* - * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN, - * as that would require mapping in all of NS DRAM into BL31 or BL32. - */ +#endif #if !RESET_TO_BL31 && !RESET_TO_SP_MIN + /* + * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN, + * as that would require mapping in all of NS DRAM into BL31 or BL32. + */ .mem_protect_chk = arm_psci_mem_protect_chk, .read_mem_protect = arm_psci_read_mem_protect, .write_mem_protect = arm_nor_psci_write_mem_protect, diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 310db7b6..7080fc30 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -8,6 +8,7 @@ #define __PLATFORM_DEF_H__ #include <arm_def.h> +#include <arm_spm_def.h> #include <board_arm_def.h> #include <common_def.h> #include <tzc400.h> diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h index ccc7771e..e475ece5 100644 --- a/plat/arm/board/juno/include/platform_def.h +++ b/plat/arm/board/juno/include/platform_def.h @@ -128,6 +128,15 @@ */ #define PLAT_ARM_MAX_BL31_SIZE 0x1E000 +#if JUNO_AARCH32_EL3_RUNTIME +/* + * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure + * Payload. We also need to take care of SCP_BL2 size as well, as the SCP_BL2 + * is loaded into the space BL32 -> BL1_RW_BASE + */ +# define PLAT_ARM_MAX_BL32_SIZE 0x1E000 +#endif + /* * Since free SRAM space is scant, enable the ASSERTION message size * optimization by fixing the PLAT_LOG_LEVEL_ASSERT to LOG_LEVEL_INFO (40). diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c index 2771e0f3..cedef66c 100644 --- a/plat/arm/board/juno/juno_bl2_setup.c +++ b/plat/arm/board/juno/juno_bl2_setup.c @@ -29,33 +29,4 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) return err; } - -#if !CSS_USE_SCMI_SDS_DRIVER -/* - * We need to override some of the platform functions when booting SP_MIN - * on Juno AArch32. These needs to be done only for SCPI/BOM SCP systems as - * in case of SDS, the structures remain in memory and doesn't need to be - * overwritten. - */ - -static unsigned int scp_boot_config; - -void bl2_early_platform_setup(meminfo_t *mem_layout) -{ - arm_bl2_early_platform_setup(mem_layout); - - /* Save SCP Boot config before it gets overwritten by SCP_BL2 loading */ - VERBOSE("BL2: Saving SCP Boot config = 0x%x\n", scp_boot_config); - scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR); -} - -void bl2_platform_setup(void) -{ - arm_bl2_platform_setup(); - - mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config); - VERBOSE("BL2: Restored SCP Boot config = 0x%x\n", scp_boot_config); -} -#endif - #endif /* JUNO_AARCH32_EL3_RUNTIME */ diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 8018b92c..fee4391d 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -31,6 +31,19 @@ JUNO_AARCH32_EL3_RUNTIME := 0 $(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME)) $(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME)) +ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1) +# Include BL32 in FIP +NEED_BL32 := yes +# BL31 is not required +override BL31_SOURCES = + +# The BL32 needs to be built separately invoking the AARCH32 compiler and +# be specifed via `BL32` build option. + ifneq (${ARCH}, aarch32) + override BL32_SOURCES = + endif +endif + ifeq (${ARCH},aarch64) BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S \ diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c index 23c03173..cf133268 100644 --- a/plat/arm/common/arm_tzc400.c +++ b/plat/arm/common/arm_tzc400.c @@ -74,8 +74,8 @@ void arm_tzc400_setup(void) #else /* if defined(EL3_PAYLOAD_BASE) */ - /* Allow secure access only to DRAM for EL3 payloads. */ - tzc400_configure_region0(TZC_REGION_S_RDWR, 0); + /* Allow Secure and Non-secure access to DRAM for EL3 payloads */ + tzc400_configure_region0(TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS); #endif /* EL3_PAYLOAD_BASE */ diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c index 9b4800e3..b4aafd46 100644 --- a/plat/arm/css/common/css_bl2_setup.c +++ b/plat/arm/css/common/css_bl2_setup.c @@ -49,13 +49,13 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) } #if !CSS_USE_SCMI_SDS_DRIVER -# ifdef EL3_PAYLOAD_BASE +# if defined(EL3_PAYLOAD_BASE) || JUNO_AARCH32_EL3_RUNTIME /* * We need to override some of the platform functions when booting an EL3 - * payload. These needs to be done only for SCPI/BOM SCP systems as - * in case of SDS, the structures remain in memory and doesn't need to be - * overwritten. + * payload or SP_MIN on Juno AArch32. This needs to be done only for + * SCPI/BOM SCP systems as in case of SDS, the structures remain in memory and + * don't need to be overwritten. */ static unsigned int scp_boot_config; diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c index 348cdba5..078f0d81 100644 --- a/plat/hisilicon/hikey960/hikey960_pm.c +++ b/plat/hisilicon/hikey960/hikey960_pm.c @@ -26,6 +26,38 @@ #define SYSTEM_PWR_STATE(state) \ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) +#define PSTATE_WIDTH 4 +#define PSTATE_MASK ((1 << PSTATE_WIDTH) - 1) + +#define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \ + ((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \ + ((lvl0_state) << (PSTATE_ID_SHIFT)) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +const unsigned int hikey960_pwr_idle_states[] = { + /* State-id - 0x001 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, + PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x002 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, + PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x003 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, + PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x033 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE, + PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0, +}; + #define DMAC_GLB_REG_SEC 0x694 #define AXI_CONF_BASE 0x820 @@ -36,16 +68,21 @@ static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state) unsigned long scr; unsigned int val = 0; - assert(cpu_state == PLAT_MAX_RET_STATE); + assert(cpu_state == PLAT_MAX_STB_STATE || + cpu_state == PLAT_MAX_RET_STATE); scr = read_scr_el3(); /* Enable Physical IRQ and FIQ to wake the CPU*/ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); - set_retention_ticks(val); + if (cpu_state == PLAT_MAX_RET_STATE) + set_retention_ticks(val); + wfi(); - clr_retention_ticks(val); + + if (cpu_state == PLAT_MAX_RET_STATE) + clr_retention_ticks(val); /* * Restore SCR to the original value, synchronisazion of @@ -124,38 +161,34 @@ static void __dead2 hikey960_system_reset(void) int hikey960_validate_power_state(unsigned int power_state, psci_power_state_t *req_state) { - int pstate = psci_get_pstate_type(power_state); - int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int state_id; int i; assert(req_state); - if (pwr_lvl > PLAT_MAX_PWR_LVL) - return PSCI_E_INVALID_PARAMS; - - /* Sanity check the requested state */ - if (pstate == PSTATE_TYPE_STANDBY) { - /* - * It's possible to enter standby only on power level 0 - * Ignore any other power level. - */ - if (pwr_lvl != MPIDR_AFFLVL0) - return PSCI_E_INVALID_PARAMS; - - req_state->pwr_domain_state[MPIDR_AFFLVL0] = - PLAT_MAX_RET_STATE; - } else { - for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) - req_state->pwr_domain_state[i] = - PLAT_MAX_OFF_STATE; - } - /* - * We expect the 'state id' to be zero. + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. */ - if (psci_get_pstate_id(power_state)) + for (i = 0; !!hikey960_pwr_idle_states[i]; i++) { + if (power_state == hikey960_pwr_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!hikey960_pwr_idle_states[i]) return PSCI_E_INVALID_PARAMS; + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & PSTATE_MASK; + state_id >>= PSTATE_WIDTH; + } + return PSCI_E_SUCCESS; } diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h index cb760907..2ac7f2a7 100644 --- a/plat/hisilicon/hikey960/include/platform_def.h +++ b/plat/hisilicon/hikey960/include/platform_def.h @@ -31,8 +31,10 @@ #define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ PLATFORM_CLUSTER_COUNT + 1) -#define PLAT_MAX_RET_STATE 1 -#define PLAT_MAX_OFF_STATE 2 +#define PLAT_MAX_RUN_STATE 0 +#define PLAT_MAX_STB_STATE 1 +#define PLAT_MAX_RET_STATE 2 +#define PLAT_MAX_OFF_STATE 3 #define MAX_IO_DEVICES 3 #define MAX_IO_HANDLES 4 diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S index 0f60a0c6..eacb1b27 100644 --- a/plat/mediatek/mt6795/bl31.ld.S +++ b/plat/mediatek/mt6795/bl31.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -29,7 +30,7 @@ SECTIONS *(.vectors) } >RAM - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE address is not aligned on a page boundary.") ro . : { @@ -58,7 +59,7 @@ SECTIONS * executable. No RW data from the next section must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM @@ -144,7 +145,7 @@ SECTIONS * 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(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; /* * Bakery locks are stored in coherent memory @@ -159,7 +160,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM2 #endif diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S index c42d9a9a..85f4dc33 100644 --- a/plat/rockchip/rk3399/include/plat.ld.S +++ b/plat/rockchip/rk3399/include/plat.ld.S @@ -6,6 +6,8 @@ #ifndef __ROCKCHIP_PLAT_LD_S__ #define __ROCKCHIP_PLAT_LD_S__ +#include <xlat_tables_defs.h> + MEMORY { SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE @@ -14,7 +16,7 @@ MEMORY { SECTIONS { . = SRAM_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "SRAM_BASE address is not aligned on a page boundary.") /* @@ -27,40 +29,40 @@ SECTIONS * | sram data * ---------------- */ - .incbin_sram : ALIGN(4096) { + .incbin_sram : ALIGN(PAGE_SIZE) { __sram_incbin_start = .; *(.sram.incbin) __sram_incbin_real_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __sram_incbin_end = .; } >SRAM ASSERT((__sram_incbin_real_end - __sram_incbin_start) <= SRAM_BIN_LIMIT, ".incbin_sram has exceeded its limit") - .text_sram : ALIGN(4096) { + .text_sram : ALIGN(PAGE_SIZE) { __bl31_sram_text_start = .; *(.sram.text) *(.sram.rodata) __bl31_sram_text_real_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __bl31_sram_text_end = .; } >SRAM ASSERT((__bl31_sram_text_real_end - __bl31_sram_text_start) <= SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit") - .data_sram : ALIGN(4096) { + .data_sram : ALIGN(PAGE_SIZE) { __bl31_sram_data_start = .; *(.sram.data) __bl31_sram_data_real_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __bl31_sram_data_end = .; } >SRAM ASSERT((__bl31_sram_data_real_end - __bl31_sram_data_start) <= SRAM_DATA_LIMIT, ".data_sram has exceeded its limit") - .stack_sram : ALIGN(4096) { + .stack_sram : ALIGN(PAGE_SIZE) { __bl31_sram_stack_start = .; - . += 4096; + . += PAGE_SIZE; __bl31_sram_stack_end = .; } >SRAM diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c index 074dc193..2fbda673 100644 --- a/plat/rockchip/rk3399/plat_sip_calls.c +++ b/plat/rockchip/rk3399/plat_sip_calls.c @@ -11,6 +11,7 @@ #include <plat_sip_calls.h> #include <rockchip_sip_svc.h> #include <runtime_svc.h> +#include <stdint.h> #define RK_SIP_DDR_CFG 0x82000008 #define DRAM_INIT 0x00 diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S new file mode 100644 index 00000000..76a542f5 --- /dev/null +++ b/plat/rpi3/aarch64/plat_helpers.S @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <platform_def.h> + +#include "../rpi3_hw.h" + + .globl plat_crash_console_flush + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl platform_mem_init + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_rpi3_calc_core_pos + .globl plat_secondary_cold_boot_setup + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * + * This function uses the plat_rpi3_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_rpi3_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); + * + * CorePos = (ClusterId * 4) + CoreId + * ----------------------------------------------------- + */ +func plat_rpi3_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_rpi3_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #RPI3_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Calculate address of our hold entry */ + bl plat_my_core_pos + lsl x0, x0, #3 + mov_imm x2, PLAT_RPI3_TM_HOLD_BASE + add x0, x0, x2 + + /* + * This code runs way before requesting the warmboot of this core, + * so it is possible to clear the mailbox before getting a request + * to boot. + */ + mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT + str x1,[x0] + + /* Wait until we have a go */ +poll_mailbox: + wfe + ldr x1, [x0] + cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO + bne poll_mailbox + + /* Jump to the provided entrypoint */ + mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT + ldr x1, [x0] + br x1 +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. + * + * This functions returns: + * - 0 for a cold boot. + * - Any other value for a warm boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO: support warm boot */ + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * void platform_mem_init (void); + * + * No need to carry out any memory initialization. + * --------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x3 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_RPI3_UART_BASE + mov_imm x1, PLAT_RPI3_UART_CLK_IN_HZ + mov_imm x2, PLAT_RPI3_UART_BAUDRATE + b console_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * 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_RPI3_UART_BASE + b console_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * int plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x1, PLAT_RPI3_UART_BASE + b console_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_reset_handler(void); + * --------------------------------------------- + */ +func plat_reset_handler + /* use the 19.2 MHz clock for the architected timer */ + mov x0, #RPI3_INTC_BASE_ADDRESS + mov w1, #0x80000000 + str wzr, [x0, #RPI3_INTC_CONTROL_OFFSET] + str w1, [x0, #RPI3_INTC_PRESCALER_OFFSET] + + /* wire mailbox 3 to the FIQ line */ + mov w1, RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ + str w1, [x0, #RPI3_INTC_MBOX_CONTROL_OFFSET] + ret +endfunc plat_reset_handler diff --git a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c new file mode 100644 index 00000000..e3acfe9f --- /dev/null +++ b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bl_common.h> +#include <desc_image_load.h> +#include <platform.h> +#include <platform_def.h> + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = RPI3_BL31_PLAT_PARAM_VAL, +#endif + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager + * image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged + * image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = PLAT_RPI3_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_RPI3_NS_IMAGE_OFFSET, + .image_info.image_max_size = PLAT_RPI3_NS_IMAGE_MAX_SIZE, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/rpi3/include/plat_macros.S b/plat/rpi3/include/plat_macros.S new file mode 100644 index 00000000..f5e057ed --- /dev/null +++ b/plat/rpi3/include/plat_macros.S @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + +#include <arm_macros.S> +#include <platform_def.h> + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* __PLAT_MACROS_S__ */ diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h new file mode 100644 index 00000000..5e2f1da5 --- /dev/null +++ b/plat/rpi3/include/platform_def.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include <arch.h> +#include <common_def.h> +#include <tbbr_img_def.h> +#include <utils_def.h> + +#include "../rpi3_hw.h" + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978) + +#define PLATFORM_STACK_SIZE ULL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define RPI3_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* + * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", and + * secure DRAM. Note that this is all actually DRAM with different names, + * there is no Secure RAM in the Raspberry Pi 3. + */ +#define SEC_ROM_BASE ULL(0x00000000) +#define SEC_ROM_SIZE ULL(0x00010000) + +/* FIP placed after ROM to append it to BL1 with very little padding. */ +#define PLAT_RPI3_FIP_BASE ULL(0x00010000) +#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001F0000) + +/* We have 16M of memory reserved at at 256M */ +#define SEC_SRAM_BASE ULL(0x10000000) +#define SEC_SRAM_SIZE ULL(0x00100000) + +#define SEC_DRAM0_BASE ULL(0x10100000) +#define SEC_DRAM0_SIZE ULL(0x00200000) + +#define NS_DRAM0_BASE ULL(0x10300000) +#define NS_DRAM0_SIZE ULL(0x00D00000) +/* End of reserved memory */ + +/* + * BL33 entrypoint. + */ +#define PLAT_RPI3_NS_IMAGE_OFFSET NS_DRAM0_BASE +#define PLAT_RPI3_NS_IMAGE_MAX_SIZE NS_DRAM0_SIZE + +/* + * I/O registers. + */ +#define DEVICE0_BASE RPI3_IO_BASE +#define DEVICE0_SIZE RPI3_IO_SIZE + +/* + * Arm TF lives in SRAM, partition it here + */ +#define SHARED_RAM_BASE SEC_SRAM_BASE +#define SHARED_RAM_SIZE ULL(0x00001000) + +#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE) +#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE) + +/* + * Mailbox to control the secondary cores.All secondary cores are held in a wait + * loop in cold boot. To release them perform the following steps (plus any + * additional barriers that may be needed): + * + * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT; + * *entrypoint = ADDRESS_TO_JUMP_TO; + * + * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO; + * + * sev(); + */ +#define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE + +#define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE +#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8) + +#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \ + PLAT_RPI3_TM_ENTRYPOINT_SIZE) +#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8) +#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \ + PLATFORM_CORE_COUNT) + +#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \ + PLAT_RPI3_TM_HOLD_SIZE) + +#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0) +#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1) + +/* + * BL1 specific defines. + * + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + * + * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using + * the current BL1 RW debug size plus a little space for growth. + */ +#define PLAT_MAX_BL1_RW_SIZE ULL(0x12000) + +#define BL1_RO_BASE SEC_ROM_BASE +#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE) +#define BL1_RW_BASE (BL1_RW_LIMIT - PLAT_MAX_BL1_RW_SIZE) +#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) + +/* + * BL2 specific defines. + * + * Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define PLAT_MAX_BL2_SIZE ULL(0x2C000) + +#define BL2_BASE (BL2_LIMIT - PLAT_MAX_BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/* + * BL31 specific defines. + * + * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL31 debug size plus a little space for growth. + */ +#define PLAT_MAX_BL31_SIZE ULL(0x20000) + +#define BL31_BASE (BL31_LIMIT - PLAT_MAX_BL31_SIZE) +#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE + +/* + * BL32 specific defines. + * + * BL32 can execute from Secure SRAM or Secure DRAM. + */ +#define BL32_SRAM_BASE BL_RAM_BASE +#define BL32_SRAM_LIMIT BL31_BASE +#define BL32_DRAM_BASE SEC_DRAM0_BASE +#define BL32_DRAM_LIMIT (SEC_DRAM0_BASE + SEC_DRAM0_SIZE) + +#define SEC_SRAM_ID 0 +#define SEC_DRAM_ID 1 + +#if RPI3_BL32_RAM_LOCATION_ID == SEC_SRAM_ID +# define BL32_MEM_BASE BL_RAM_BASE +# define BL32_MEM_SIZE BL_RAM_SIZE +# define BL32_BASE BL32_SRAM_BASE +# define BL32_LIMIT BL32_SRAM_LIMIT +#elif RPI3_BL32_RAM_LOCATION_ID == SEC_DRAM_ID +# define BL32_MEM_BASE SEC_DRAM0_BASE +# define BL32_MEM_SIZE SEC_DRAM0_SIZE +# define BL32_BASE BL32_DRAM_BASE +# define BL32_LIMIT BL32_DRAM_LIMIT +#else +# error "Unsupported RPI3_BL32_RAM_LOCATION_ID value" +#endif +#define BL32_SIZE (BL32_LIMIT - BL32_BASE) + +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ + +/* + * Other memory-related defines. + */ +#define ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS U(8) +#define MAX_XLAT_TABLES U(4) + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +/* + * Serial-related constants. + */ +#define PLAT_RPI3_UART_BASE RPI3_MINI_UART_BASE +#define PLAT_RPI3_UART_CLK_IN_HZ RPI3_MINI_UART_CLK_IN_HZ +#define PLAT_RPI3_UART_BAUDRATE ULL(115200) + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS ULL(19200000) + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk new file mode 100644 index 00000000..821f8015 --- /dev/null +++ b/plat/rpi3/platform.mk @@ -0,0 +1,113 @@ +# +# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iinclude/common/tbbr \ + -Iinclude/plat/arm/common/ \ + -Iinclude/plat/arm/common/aarch64/ \ + -Iplat/rpi3/include + +PLAT_BL_COMMON_SOURCES := drivers/console/aarch64/console.S \ + drivers/ti/uart/aarch64/16550_console.S \ + plat/rpi3/rpi3_common.c + +BL1_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/aarch64/platform_mp_stack.S \ + plat/rpi3/aarch64/plat_helpers.S \ + plat/rpi3/rpi3_bl1_setup.c \ + plat/rpi3/rpi3_io_storage.c + +BL2_SOURCES += common/desc_image_load.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/common/aarch64/platform_mp_stack.S \ + plat/rpi3/aarch64/plat_helpers.S \ + plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \ + plat/rpi3/rpi3_bl2_setup.c \ + plat/rpi3/rpi3_image_load.c \ + plat/rpi3/rpi3_io_storage.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/aarch64/plat_psci_common.c \ + plat/rpi3/aarch64/plat_helpers.S \ + plat/rpi3/rpi3_bl31_setup.c \ + plat/rpi3/rpi3_pm.c \ + plat/rpi3/rpi3_topology.c + +# Translation tables library +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_826319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +# Disable the PSCI platform compatibility layer by default +ENABLE_PLAT_COMPAT := 0 + +# Enable reset to BL31 by default +RESET_TO_BL31 := 1 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Enable new version of image loading +LOAD_IMAGE_V2 := 1 + +# Platform build flags +# -------------------- + +# BL33 images are in AArch64 by default +RPI3_BL33_IN_AARCH32 := 0 + +# BL32 location +RPI3_BL32_RAM_LOCATION := tdram +ifeq (${RPI3_BL32_RAM_LOCATION}, tsram) + RPI3_BL32_RAM_LOCATION_ID = SEC_SRAM_ID +else ifeq (${RPI3_BL32_RAM_LOCATION}, tdram) + RPI3_BL32_RAM_LOCATION_ID = SEC_DRAM_ID +else + $(error "Unsupported RPI3_BL32_RAM_LOCATION value") +endif + +# Process platform flags +# ---------------------- + +$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID)) +$(eval $(call add_define,RPI3_BL33_IN_AARCH32)) + +# Verify build config +# ------------------- + +ifneq (${LOAD_IMAGE_V2}, 1) + $(error Error: rpi3 needs LOAD_IMAGE_V2=1) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on rpi3) +endif diff --git a/plat/rpi3/rpi3_bl1_setup.c b/plat/rpi3/rpi3_bl1_setup.c new file mode 100644 index 00000000..11c0f4af --- /dev/null +++ b/plat/rpi3/rpi3_bl1_setup.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <bl_common.h> +#include <console.h> +#include <platform_def.h> +#include <xlat_mmu_helpers.h> +#include <xlat_tables_defs.h> + +#include "../../bl1/bl1_private.h" +#include "rpi3_private.h" + +/* Data structure which holds the extents of the trusted SRAM for BL1 */ +static meminfo_t bl1_tzram_layout; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL_RAM_BASE; + bl1_tzram_layout.total_size = BL_RAM_SIZE; +} + +/****************************************************************************** + * Perform the very early platform specific architecture setup. This only + * does basic initialization. Later architectural setup (bl1_arch_setup()) + * does not do anything platform specific. + *****************************************************************************/ +void bl1_plat_arch_setup(void) +{ + rpi3_setup_page_tables(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL_CODE_BASE, BL1_CODE_END, + BL1_RO_DATA_BASE, BL1_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el3(0); +} + +void bl1_platform_setup(void) +{ + /* Initialise the IO layer and register platform IO devices */ + plat_rpi3_io_setup(); +} diff --git a/plat/rpi3/rpi3_bl2_setup.c b/plat/rpi3/rpi3_bl2_setup.c new file mode 100644 index 00000000..1fd822e9 --- /dev/null +++ b/plat/rpi3/rpi3_bl2_setup.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015-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 <console.h> +#include <debug.h> +#include <desc_image_load.h> +#include <platform_def.h> +#include <xlat_mmu_helpers.h> +#include <xlat_tables_defs.h> + +#include "rpi3_private.h" + +/* Data structure which holds the extents of the trusted SRAM for BL2 */ +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/******************************************************************************* + * BL1 has passed the extents of the trusted SRAM that should be visible to BL2 + * in x0. This memory layout is sitting at the base of the free trusted SRAM. + * Copy it to a safe location before its reclaimed by later BL2 functionality. + ******************************************************************************/ +void bl2_early_platform_setup(meminfo_t *mem_layout) +{ + /* Initialize the console to provide early debug support */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + plat_rpi3_io_setup(); +} + +void bl2_platform_setup(void) +{ + /* + * This is where a TrustZone address space controller and other + * security related peripherals, would be configured. + */ +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. + ******************************************************************************/ +void bl2_plat_arch_setup(void) +{ + rpi3_setup_page_tables(bl2_tzram_layout.total_base, + bl2_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 + ); + + enable_mmu_el1(0); +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + assert(bl_mem_params != NULL); + + switch (image_id) { + case BL32_IMAGE_ID: + bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry(); + break; + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl33_entry(); + break; + + } + + return err; +} diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c new file mode 100644 index 00000000..39133564 --- /dev/null +++ b/plat/rpi3/rpi3_bl31_setup.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <bl_common.h> +#include <console.h> +#include <platform.h> +#include <platform_def.h> +#include <xlat_mmu_helpers.h> +#include <xlat_tables_defs.h> + +#include "rpi3_private.h" + +#define BL31_END (uintptr_t)(&__BL31_END__) + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type) != 0); + + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup(void *from_bl2, + void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); + +#if RESET_TO_BL31 + + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = rpi3_get_spsr_for_bl32_entry(); +#endif /* BL32_BASE */ + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + + bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#else /* RESET_TO_BL31 */ + + /* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL31. + * In release builds, it's not used. + */ + assert(((uintptr_t)plat_params_from_bl2) == RPI3_BL31_PLAT_PARAM_VAL); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) { + bl32_image_ep_info = *bl_params->ep_info; + } + + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + } + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0) { + panic(); + } + +#endif /* RESET_TO_BL31 */ +} + +void bl31_plat_arch_setup(void) +{ + rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE, + 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 + ); + + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ +#if RESET_TO_BL31 + /* + * Do initial security configuration to allow DRAM/device access + * (if earlier BL has not already done so). + */ +#endif /* RESET_TO_BL31 */ + + return; +} + +void bl31_plat_runtime_setup(void) +{ + /* Initialize the runtime console */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); +} diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c new file mode 100644 index 00000000..97dce091 --- /dev/null +++ b/plat/rpi3/rpi3_common.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <bl_common.h> +#include <debug.h> +#include <interrupt_mgmt.h> +#include <platform_def.h> +#include <xlat_tables_v2.h> + +#include "rpi3_hw.h" +#include "rpi3_private.h" + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ + SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_FIP MAP_REGION_FLAT(PLAT_RPI3_FIP_BASE, \ + PLAT_RPI3_FIP_MAX_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Table of regions for various BL stages to map using the MMU. + */ +#ifdef IMAGE_BL1 +static const mmap_region_t plat_rpi3_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, + MAP_FIP, + {0} +}; +#endif + +#ifdef IMAGE_BL2 +static const mmap_region_t plat_rpi3_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, + MAP_FIP, + MAP_NS_DRAM0, +#ifdef BL32_BASE + MAP_BL32_MEM, +#endif + {0} +}; +#endif + +#ifdef IMAGE_BL31 +static const mmap_region_t plat_rpi3_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, +#ifdef BL32_BASE + MAP_BL32_MEM, +#endif + {0} +}; +#endif + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, + uintptr_t code_start, uintptr_t code_limit, + uintptr_t rodata_start, uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, uintptr_t coh_limit +#endif + ) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n", + (void *) total_base, (void *) (total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_MEMORY | MT_RW | MT_SECURE); + + /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *) code_start, (void *) code_limit); + mmap_add_region(code_start, code_start, + code_limit - code_start, + MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *) rodata_start, (void *) rodata_limit); + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, + MT_RO_DATA | MT_SECURE); + +#if USE_COHERENT_MEM + /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *) coh_start, (void *) coh_limit); + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + mmap_add(plat_rpi3_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Return entrypoint of BL33. + ******************************************************************************/ +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_RPI3_NS_IMAGE_OFFSET; +#endif +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t rpi3_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +uint32_t rpi3_get_spsr_for_bl33_entry(void) +{ +#if RPI3_BL33_IN_AARCH32 + INFO("BL33 will boot in Non-secure AArch32 Hypervisor mode\n"); + return SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS); +#else + return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +#endif +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + return INTR_TYPE_INVAL; +} diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h new file mode 100644 index 00000000..70272e00 --- /dev/null +++ b/plat/rpi3/rpi3_hw.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RPI3_HW__ +#define __RPI3_HW__ + +#include <utils_def.h> + +/* + * Peripherals + */ + +#define RPI3_IO_BASE ULL(0x3F000000) +#define RPI3_IO_SIZE ULL(0x01000000) + +/* + * Serial port (called 'Mini UART' in the BCM docucmentation). + */ +#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040) +#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET) +#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000) + +/* + * Power management, reset controller, watchdog. + */ +#define RPI3_IO_PM_OFFSET ULL(0x00100000) +#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET) +/* Registers on top of RPI3_PM_BASE. */ +#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) +#define RPI3_PM_WDOG_OFFSET ULL(0x00000024) +/* Watchdog constants */ +#define RPI3_PM_PASSWORD ULL(0x5A000000) +#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030) +#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020) + +/* + * Local interrupt controller + */ +#define RPI3_INTC_BASE_ADDRESS ULL(0x40000000) +/* Registers on top of RPI3_INTC_BASE_ADDRESS */ +#define RPI3_INTC_CONTROL_OFFSET ULL(0x00000000) +#define RPI3_INTC_PRESCALER_OFFSET ULL(0x00000008) +#define RPI3_INTC_MBOX_CONTROL_OFFSET ULL(0x00000050) +#define RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ ULL(0x00000080) +#define RPI3_INTC_PENDING_FIQ_OFFSET ULL(0x00000070) +#define RPI3_INTC_PENDING_FIQ_MBOX3 ULL(0x00000080) + +#endif /* __RPI3_HW__ */ diff --git a/plat/rpi3/rpi3_image_load.c b/plat/rpi3/rpi3_image_load.c new file mode 100644 index 00000000..fad9e4f3 --- /dev/null +++ b/plat/rpi3/rpi3_image_load.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bl_common.h> +#include <desc_image_load.h> +#include <platform.h> +#include <platform_def.h> + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c new file mode 100644 index 00000000..7ac45ef6 --- /dev/null +++ b/plat/rpi3/rpi3_io_storage.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <bl_common.h> +#include <debug.h> +#include <firmware_image_package.h> +#include <io_driver.h> +#include <io_fip.h> +#include <io_memmap.h> +#include <platform_def.h> +#include <string.h> + +/* Semihosting filenames */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL31_IMAGE_NAME "bl31.bin" +#define BL32_IMAGE_NAME "bl32.bin" +#define BL33_IMAGE_NAME "bl33.bin" + +#if TRUSTED_BOARD_BOOT +#define BL2_CERT_NAME "bl2.crt" +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define BL31_KEY_CERT_NAME "bl31_key.crt" +#define BL32_KEY_CERT_NAME "bl32_key.crt" +#define BL33_KEY_CERT_NAME "bl33_key.crt" +#define BL31_CERT_NAME "bl31.crt" +#define BL32_CERT_NAME "bl32.crt" +#define BL33_CERT_NAME "bl33.crt" +#endif /* TRUSTED_BOARD_BOOT */ + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_handle; + +static const io_block_spec_t fip_block_spec = { + .offset = PLAT_RPI3_FIP_BASE, + .length = PLAT_RPI3_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t bl2_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t bl31_key_cert_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT, +}; + +static const io_uuid_spec_t bl32_key_cert_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT, +}; + +static const io_uuid_spec_t bl33_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT, +}; + +static const io_uuid_spec_t bl31_cert_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT, +}; + +static const io_uuid_spec_t bl32_cert_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_CERT, +}; + +static const io_uuid_spec_t bl33_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [BL2_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [BL31_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_key_cert_uuid_spec, + open_fip + }, + [BL32_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_key_cert_uuid_spec, + open_fip + }, + [BL33_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_key_cert_uuid_spec, + open_fip + }, + [BL31_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_cert_uuid_spec, + open_fip + }, + [BL32_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_cert_uuid_spec, + open_fip + }, + [BL33_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +static int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_rpi3_io_setup(void) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + assert(io_result == 0); + + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + assert(io_result == 0); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + + return result; +} diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c new file mode 100644 index 00000000..1d067fb1 --- /dev/null +++ b/plat/rpi3/rpi3_pm.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <console.h> +#include <debug.h> +#include <mmio.h> +#include <platform_def.h> +#include <platform.h> +#include <psci.h> + +#include "rpi3_hw.h" + +/* + * The secure entry point to be used on warm reset. + */ +static uintptr_t secure_entrypoint; + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) + +#else + +#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) + +#endif /* PSCI_EXTENDED_STATE_ID */ + +#define rpi3_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int rpi3_pm_idle_states[] = { + /* State-id - 0x01 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0, +}; + +/******************************************************************************* + * Platform handler called to check the validity of the power state + * parameter. The power state parameter has to be a composite power state. + ******************************************************************************/ +static int rpi3_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state != 0); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; rpi3_pm_idle_states[i] != 0; i++) { + if (power_state == rpi3_pm_idle_states[i]) { + break; + } + } + + /* Return error if entry not found in the idle state array */ + if (!rpi3_pm_idle_states[i]) { + return PSCI_E_INVALID_PARAMS; + } + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void rpi3_cpu_standby(plat_local_state_t cpu_state) +{ + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + /* + * Enter standby state. + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int rpi3_pwr_domain_on(u_register_t mpidr) +{ + int rc = PSCI_E_SUCCESS; + unsigned int pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + + assert(pos < PLATFORM_CORE_COUNT); + + hold_base[pos] = PLAT_RPI3_TM_HOLD_STATE_GO; + + /* Make sure that the write has completed */ + dsb(); + isb(); + + sev(); + + return rc; +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); +} + +/******************************************************************************* + * Platform handler to reboot the system + ******************************************************************************/ +#define RESET_TIMEOUT 10 + +static void __dead2 rpi3_system_reset(void) +{ + /* Setup watchdog for reset */ + + static const uintptr_t base = RPI3_PM_BASE; + uint32_t rstc; + + INFO("rpi3: PSCI System Reset: invoking watchdog reset\n"); + + console_flush(); + + rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET); + rstc &= ~RPI3_PM_RSTC_WRCFG_MASK; + rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET; + + dmbst(); + + /* + * Watchdog timer = Timer clock / 16 + * Password (31:16) | Value (11:0) + */ + mmio_write_32(base + RPI3_PM_WDOG_OFFSET, + RPI3_PM_PASSWORD | RESET_TIMEOUT); + mmio_write_32(base + RPI3_PM_RSTC_OFFSET, + RPI3_PM_PASSWORD | rstc); + + for (;;) { + wfi(); + } +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t plat_rpi3_psci_pm_ops = { + .cpu_standby = rpi3_cpu_standby, + .pwr_domain_on = rpi3_pwr_domain_on, + .pwr_domain_on_finish = rpi3_pwr_domain_on_finish, + .system_reset = rpi3_system_reset, + .validate_power_state = rpi3_validate_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (void *)PLAT_RPI3_TRUSTED_MAILBOX_BASE; + + *mailbox = sec_entrypoint; + secure_entrypoint = (uintptr_t)sec_entrypoint; + *psci_ops = &plat_rpi3_psci_pm_ops; + + return 0; +} diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h new file mode 100644 index 00000000..01c4055f --- /dev/null +++ b/plat/rpi3/rpi3_private.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RPI3_PRIVATE_H__ +#define __RPI3_PRIVATE_H__ + +#include <sys/types.h> + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +/* Utility functions */ +void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, + uintptr_t code_start, uintptr_t code_limit, + uintptr_t rodata_start, uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, uintptr_t coh_limit +#endif + ); + +/* Optional functions required in the Raspberry Pi 3 port */ +unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); + +/* BL2 utility functions */ +uint32_t rpi3_get_spsr_for_bl32_entry(void); +uint32_t rpi3_get_spsr_for_bl33_entry(void); + +/* IO storage utility functions */ +void plat_rpi3_io_setup(void); + +#endif /*__RPI3_PRIVATE_H__ */ diff --git a/plat/rpi3/rpi3_topology.c b/plat/rpi3/rpi3_topology.c new file mode 100644 index 00000000..0e03ec32 --- /dev/null +++ b/plat/rpi3/rpi3_topology.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <platform_def.h> +#include <sys/types.h> + +#include "rpi3_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the ARM default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return plat_rpi3_calc_core_pos(mpidr); +} diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c index 2f08c8ba..1969307f 100644 --- a/services/std_svc/sdei/sdei_main.c +++ b/services/std_svc/sdei/sdei_main.c @@ -795,7 +795,7 @@ static int sdei_private_reset(void) */ ret = sdei_event_unregister(map->ev_num); if ((ret == SDEI_EPEND) && (final_ret == 0)) - final_ret = ret; + final_ret = SDEI_EDENY; } return final_ret; @@ -817,7 +817,7 @@ static int sdei_shared_reset(void) */ ret = sdei_event_unregister(map->ev_num); if ((ret == SDEI_EPEND) && (final_ret == 0)) - final_ret = ret; + final_ret = SDEI_EDENY; } if (final_ret != 0) diff --git a/services/std_svc/spm/secure_partition_setup.c b/services/std_svc/spm/secure_partition_setup.c index 6f4b0571..c1f0edf6 100644 --- a/services/std_svc/spm/secure_partition_setup.c +++ b/services/std_svc/spm/secure_partition_setup.c @@ -6,7 +6,6 @@ #include <arch.h> #include <arch_helpers.h> -#include <arm_spm_def.h> #include <assert.h> #include <common_def.h> #include <context.h> @@ -22,12 +21,17 @@ #include "spm_private.h" #include "spm_shim_private.h" +/* Place translation tables by default along with the ones used by BL31. */ +#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" +#endif + /* Allocate and initialise the translation context for the secure partition. */ REGISTER_XLAT_CONTEXT2(secure_partition, PLAT_SP_IMAGE_MMAP_REGIONS, PLAT_SP_IMAGE_MAX_XLAT_TABLES, PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE, - EL1_EL0_REGIME); + EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME); /* Export a handle on the secure partition translation context */ xlat_ctx_t *secure_partition_xlat_ctx_handle = &secure_partition_xlat_ctx; diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c index de657a2f..00f3a30c 100644 --- a/services/std_svc/spm/spm_main.c +++ b/services/std_svc/spm/spm_main.c @@ -132,7 +132,7 @@ int32_t spm_init(void) rc = spm_synchronous_sp_entry(&sp_ctx); assert(rc == 0); sp_init_in_progress = 0; - VERBOSE("SP_MEM_ATTRIBUTES_SET_AARCH64 availability has been revoked\n"); + VERBOSE("SP_MEMORY_ATTRIBUTES_SET_AARCH64 availability has been revoked\n"); return rc; } @@ -228,21 +228,21 @@ static mmap_attr_t smc_attr_to_mmap_attr(unsigned int attributes) { mmap_attr_t tf_attr = 0; - unsigned int access = (attributes & SP_MEM_ATTR_ACCESS_MASK) - >> SP_MEM_ATTR_ACCESS_SHIFT; + unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + >> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; - if (access == SP_MEM_ATTR_ACCESS_RW) { + if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RW) { tf_attr |= MT_RW | MT_USER; - } else if (access == SP_MEM_ATTR_ACCESS_RO) { + } else if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RO) { tf_attr |= MT_RO | MT_USER; } else { /* Other values are reserved. */ - assert(access == SP_MEM_ATTR_ACCESS_NOACCESS); + assert(access == SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS); /* The only requirement is that there's no access from EL0 */ tf_attr |= MT_RO | MT_PRIVILEGED; } - if ((attributes & SP_MEM_ATTR_NON_EXEC) == 0) { + if ((attributes & SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) { tf_attr |= MT_EXECUTE; } else { tf_attr |= MT_EXECUTE_NEVER; @@ -263,20 +263,21 @@ static int smc_mmap_to_smc_attr(mmap_attr_t attr) if ((attr & MT_USER) == 0) { /* No access from EL0. */ - data_access = SP_MEM_ATTR_ACCESS_NOACCESS; + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS; } else { if ((attr & MT_RW) != 0) { assert(MT_TYPE(attr) != MT_DEVICE); - data_access = SP_MEM_ATTR_ACCESS_RW; + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RW; } else { - data_access = SP_MEM_ATTR_ACCESS_RO; + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RO; } } - smc_attr |= (data_access & SP_MEM_ATTR_ACCESS_MASK) << SP_MEM_ATTR_ACCESS_SHIFT; + smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + << SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; if (attr & MT_EXECUTE_NEVER) { - smc_attr |= SP_MEM_ATTR_NON_EXEC; + smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC; } return smc_attr; @@ -387,20 +388,20 @@ uint64_t spm_smc_handler(uint32_t smc_fid, /* Return to normal world */ SMC_RET1(ns_cpu_context, x1); - case SP_MEM_ATTRIBUTES_GET_AARCH64: - INFO("Received SP_MEM_ATTRIBUTES_GET_AARCH64 SMC\n"); + case SP_MEMORY_ATTRIBUTES_GET_AARCH64: + INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); if (!sp_init_in_progress) { - WARN("SP_MEM_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); + WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); SMC_RET1(handle, SPM_NOT_SUPPORTED); } SMC_RET1(handle, spm_memory_attributes_get_smc_handler(x1)); - case SP_MEM_ATTRIBUTES_SET_AARCH64: - INFO("Received SP_MEM_ATTRIBUTES_SET_AARCH64 SMC\n"); + case SP_MEMORY_ATTRIBUTES_SET_AARCH64: + INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); if (!sp_init_in_progress) { - WARN("SP_MEM_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); + WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); SMC_RET1(handle, SPM_NOT_SUPPORTED); } SMC_RET1(handle, spm_memory_attributes_set_smc_handler(x1, x2, x3)); @@ -417,8 +418,8 @@ uint64_t spm_smc_handler(uint32_t smc_fid, case SP_VERSION_AARCH32: SMC_RET1(handle, SP_VERSION_COMPILED); - case SP_COMMUNICATE_AARCH32: - case SP_COMMUNICATE_AARCH64: + case MM_COMMUNICATE_AARCH32: + case MM_COMMUNICATE_AARCH64: /* Save the Normal world context */ cm_el1_sysregs_context_save(NON_SECURE); @@ -435,13 +436,13 @@ uint64_t spm_smc_handler(uint32_t smc_fid, assert(x1 == 0); if (x3 != 0) { - VERBOSE("SP_COMMUNICATE_AARCH32/64: X3 is not 0 as recommended.\n"); + VERBOSE("MM_COMMUNICATE_AARCH32/64: X3 is not 0 as recommended.\n"); } SMC_RET4(&sp_ctx.cpu_ctx, smc_fid, x1, x2, x3); - case SP_MEM_ATTRIBUTES_GET_AARCH64: - case SP_MEM_ATTRIBUTES_SET_AARCH64: + case SP_MEMORY_ATTRIBUTES_GET_AARCH64: + case SP_MEMORY_ATTRIBUTES_SET_AARCH64: /* SMC interfaces reserved for secure callers. */ SMC_RET1(handle, SPM_NOT_SUPPORTED); |