diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst index 0ba564d..fbf753b 100644 --- a/docs/plat/rpi3.rst +++ b/docs/plat/rpi3.rst @@ -7,8 +7,7 @@ .. contents:: The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four -Arm Cortex-A53 cores, which makes it possible to have a port of Trusted -Firmware-A (TF-A). +Arm Cortex-A53 cores. The following instructions explain how to use this port of the TF-A with the default distribution of `Raspbian`_ because that's the distribution officially @@ -66,7 +65,7 @@ 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 TF-A. +when compiling TF-A. This is done automatically by the build system. 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``. @@ -108,13 +107,13 @@ | ... | | | 0x01000000 +-----------------+ - | Kernel | + | DTB | (Loaded by the VideoCore) +-----------------+ | | | ... | | | 0x02000000 +-----------------+ - | DTB | + | Kernel | (Loaded by the VideoCore) +-----------------+ | | | ... | @@ -123,9 +122,9 @@ | Secure SRAM | BL2, BL31 0x10100000 +-----------------+ | Secure DRAM | BL32 (Secure payload) - 0x10C00000 +-----------------+ - | Non-secure DRAM | BL33 0x11000000 +-----------------+ + | Non-secure DRAM | BL33 + +-----------------+ | | | ... | | | @@ -133,10 +132,10 @@ | 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=16M$256M`` to the -command line passed to the kernel. See the `Setup SD card`_ instructions to see -how to do it. +The area between **0x10000000** and **0x11000000** has to be manually protected +so that the kernel doesn't use it. That is done by adding ``memmap=16M$256M`` 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 @@ -159,14 +158,24 @@ in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The bootstrap should take care of this. +This port support a direct boot of the Linux kernel from the firmware (as a BL33 +image). Alternatively, U-Boot or other bootloaders may be used. + Secondary cores ~~~~~~~~~~~~~~~ +This port of the Trusted Firmware-A supports ``PSCI_CPU_ON``, +`PSCI_SYSTEM_RESET`` and ``PSCI_SYSTEM_OFF``. The last one doesn't really turn +the system off, it simply reboots it and asks the VideoCore firmware to keep it +in a low power mode permanently. + 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. +Kernels with PSCI support can use the PSCI calls instead for a cleaner boot. + Also, this port of TF-A 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``). @@ -187,46 +196,38 @@ AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit kernel. -First, clone and compile `Raspberry Pi 3 TF-A bootstrap`_. Choose the one -needed for the architecture of your kernel. - -Then compile TF-A. 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 - -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 - The build system concatenates BL1 and the FIP so that the addresses match the ones in the memory map. The resulting file is ``armstub8.bin``, located in the -build folder (e.g. ``build/rpi3/debug/armstub8.bin``). Now, follow the -instructions in `Setup SD card`_. +build folder (e.g. ``build/rpi3/debug/armstub8.bin``). To know how to use this +file, 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 TF-A will jump to BL33 in EL2 in AArch64 mode. If set to 1, it will jump to BL33 in Hypervisor in AArch32 mode. +- ``PRELOADED_BL33_BASE``: Used to specify the address of a BL33 binary that has + been preloaded by any other system than using the firmware. ``BL33`` isn't + needed in the build command line if this option is used. 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. + +- ``RPI3_DIRECT_LINUX_BOOT``: Disabled by default. Set to 1 to enable the direct + boot of the Linux kernel from the firmware. Option ``RPI3_PRELOADED_DTB_BASE`` + is mandatory when the direct Linux kernel boot is used. Options + ``PRELOADED_BL33_BASE`` will most likely be needed as well because it is + unlikely that the kernel image will fit in the space reserved for BL33 images. + This option can be combined with ``RPI3_BL33_IN_AARCH32`` in order to boot a + 32-bit kernel. The only thing this option does is to set the arguments in + registers x0-x3 or r0-r2 as expected by the kernel. + +- ``RPI3_PRELOADED_DTB_BASE``: Auxiliary build option needed when using + ``RPI3_DIRECT_LINUX_BOOT=1``. This option allows to specify the location of a + DTB in memory. + - ``BL32``: This port can load and run OP-TEE. The OP-TEE image is optional. Please use the code from `here `__. Build the Trusted Firmware with option ``BL32=tee-header_v2.bin @@ -239,15 +240,16 @@ This will unfortunately reduce the performance of the USB driver. It is needed when using Raspbian, for example. -- ``TRUSTED_BOARD_BOOT``: This port supports TBB. Set this option - ``TRUSTED_BOARD_BOOT=1`` to enable it. In order to use TBB, you might - want to set ``GENERATE_COT=1`` to let the contents of the FIP automatically - signed by the build process. The ROT key will be generated and output to - ``rot_key.pem`` in the build directory. It is able to set ROT_KEY to - your own key in PEM format. - Also in order to build, you need to clone mbedtls from - `here `__. - And set MBEDTLS_DIR to mbedtls source directory. +- ``TRUSTED_BOARD_BOOT``: This port supports TBB. Set this option to 1 to enable + it. In order to use TBB, you might want to set ``GENERATE_COT=1`` to let the + contents of the FIP automatically signed by the build process. The ROT key + will be generated and output to ``rot_key.pem`` in the build directory. It is + able to set ROT_KEY to your own key in PEM format. Also in order to build, + you need to clone mbed TLS from `here `__. + ``MBEDTLS_DIR`` must point at the mbed TLS source directory. + +- ``ENABLE_STACK_PROTECTOR``: Disabled by default. It uses the hardware RNG of + the board. The following is not currently supported: @@ -257,13 +259,65 @@ address by changing the file ``armstub8.bin``, so there's no point in using TF-A in this case. -- ``LOAD_IMAGE_V2=0``: Only version 2 is supported. - - ``MULTI_CONSOLE_API=0``: The multi console API must be enabled. Note that the crash console uses the internal 16550 driver functions directly in order to be able to print error messages during early crashes before setting up the multi console API. +Building the firmware for kernels that don't support PSCI +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the case for the 32-bit image of Raspbian, for example. 64-bit kernels +always support PSCI, but they may not know that the system understands PSCI due +to an incorrect DTB file. + +First, clone and compile the 32-bit version of the `Raspberry Pi 3 TF-A +bootstrap`_. Choose the one needed for the architecture of your kernel. + +Then compile TF-A. For a 32-bit 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 + +For a 64-bit 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 + +However, enabling PSCI support in a 64-bit kernel is really easy. In the +repository `Raspberry Pi 3 TF-A bootstrap`_ there is a patch that can be applied +to the Linux kernel tree maintained by the Raspberry Pi foundation. It modifes +the DTS to tell the kernel to use PSCI. Once this patch is applied, follow the +instructions in `AArch64 kernel build instructions`_ to get a working 64-bit +kernel image and supporting files. + +Building the firmware for kernels that support PSCI +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For a 64-bit kernel: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + PRELOADED_BL33_BASE=0x02000000 \ + RPI3_PRELOADED_DTB_BASE=0x01000000 \ + RPI3_DIRECT_LINUX_BOOT=1 + +For a 32-bit kernel: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + PRELOADED_BL33_BASE=0x02000000 \ + RPI3_PRELOADED_DTB_BASE=0x01000000 \ + RPI3_DIRECT_LINUX_BOOT=1 \ + RPI3_BL33_IN_AARCH32=1 + AArch64 kernel build instructions --------------------------------- @@ -280,7 +334,7 @@ .. code:: shell - git clone --depth=1 -b rpi-4.14.y https://github.com/raspberrypi/linux + git clone --depth=1 -b rpi-4.18.y https://github.com/raspberrypi/linux cd linux 2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is @@ -300,6 +354,7 @@ cp arch/arm64/boot/Image /path/to/boot/kernel8.img cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/ + cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.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. @@ -343,8 +398,8 @@ :: enable_uart=1 - kernel_address=0x01000000 - device_tree_address=0x02000000 + kernel_address=0x02000000 + device_tree_address=0x01000000 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 diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S index 65c1bf2..7974b60 100644 --- a/plat/rpi3/aarch64/plat_helpers.S +++ b/plat/rpi3/aarch64/plat_helpers.S @@ -175,9 +175,5 @@ 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/include/platform_def.h b/plat/rpi3/include/platform_def.h index 5b84aa6..4674bfb 100644 --- a/plat/rpi3/include/platform_def.h +++ b/plat/rpi3/include/platform_def.h @@ -70,17 +70,17 @@ #define PLAT_RPI3_FIP_BASE ULL(0x00020000) #define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001E0000) -/* We have 16M of memory reserved at at 256M */ +/* We have 16M of memory reserved starting 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(0x00B00000) - -#define NS_DRAM0_BASE ULL(0x10C00000) -#define NS_DRAM0_SIZE ULL(0x00400000) +#define SEC_DRAM0_SIZE ULL(0x00F00000) /* End of reserved memory */ +#define NS_DRAM0_BASE ULL(0x11000000) +#define NS_DRAM0_SIZE ULL(0x01000000) + /* * BL33 entrypoint. */ @@ -117,9 +117,11 @@ */ #define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE +/* The secure entry point to be used on warm reset by all CPUs. */ #define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE #define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8) +/* Hold entries for each CPU. */ #define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \ PLAT_RPI3_TM_ENTRYPOINT_SIZE) #define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8) diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk index 5990f27..4276c84 100644 --- a/plat/rpi3/platform.mk +++ b/plat/rpi3/platform.mk @@ -90,8 +90,11 @@ # Disable the PSCI platform compatibility layer by default ENABLE_PLAT_COMPAT := 0 -# Enable reset to BL31 by default -RESET_TO_BL31 := 1 +# Disable stack protector by default +ENABLE_STACK_PROTECTOR := 0 + +# Reset to BL31 isn't supported +RESET_TO_BL31 := 0 # Have different sections for code and rodata SEPARATE_CODE_AND_RODATA := 1 @@ -111,6 +114,9 @@ # BL33 images are in AArch64 by default RPI3_BL33_IN_AARCH32 := 0 +# Assume that BL33 isn't the Linux kernel by default +RPI3_DIRECT_LINUX_BOOT := 0 + # BL32 location RPI3_BL32_RAM_LOCATION := tdram ifeq (${RPI3_BL32_RAM_LOCATION}, tsram) @@ -126,9 +132,17 @@ $(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID)) $(eval $(call add_define,RPI3_BL33_IN_AARCH32)) +$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT)) +$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE)) # Verify build config # ------------------- +# +ifneq (${RPI3_DIRECT_LINUX_BOOT}, 0) + ifndef RPI3_PRELOADED_DTB_BASE + $(error Error: RPI3_PRELOADED_DTB_BASE needed if RPI3_DIRECT_LINUX_BOOT=1) + endif +endif ifneq (${LOAD_IMAGE_V2}, 1) $(error Error: rpi3 needs LOAD_IMAGE_V2=1) @@ -138,10 +152,19 @@ $(error Error: rpi3 needs MULTI_CONSOLE_API=1) endif +ifneq (${RESET_TO_BL31}, 0) + $(error Error: rpi3 needs RESET_TO_BL31=0) +endif + ifeq (${ARCH},aarch32) $(error Error: AArch32 not supported on rpi3) endif +ifneq ($(ENABLE_STACK_PROTECTOR), 0) +PLAT_BL_COMMON_SOURCES += plat/rpi3/rpi3_rng.c \ + plat/rpi3/rpi3_stack_protector.c +endif + ifeq (${SPD},opteed) BL2_SOURCES += \ lib/optee/optee_utils.c diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c index 58344ae..5bbb13c 100644 --- a/plat/rpi3/rpi3_bl31_setup.c +++ b/plat/rpi3/rpi3_bl31_setup.c @@ -59,39 +59,6 @@ /* Initialize the console to provide early debug support */ rpi3_console_init(); -#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. @@ -130,7 +97,33 @@ panic(); } -#endif /* RESET_TO_BL31 */ +#if RPI3_DIRECT_LINUX_BOOT +# if RPI3_BL33_IN_AARCH32 + /* + * According to the file ``Documentation/arm/Booting`` of the Linux + * kernel tree, Linux expects: + * r0 = 0 + * r1 = machine type number, optional in DT-only platforms (~0 if so) + * r2 = Physical address of the device tree blob + */ + VERBOSE("rpi3: Preparing to boot 32-bit Linux kernel\n"); + bl33_image_ep_info.args.arg0 = 0U; + bl33_image_ep_info.args.arg1 = ~0U; + bl33_image_ep_info.args.arg2 = (u_register_t) RPI3_PRELOADED_DTB_BASE; +# else + /* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + */ + VERBOSE("rpi3: Preparing to boot 64-bit Linux kernel\n"); + bl33_image_ep_info.args.arg0 = (u_register_t) RPI3_PRELOADED_DTB_BASE; + bl33_image_ep_info.args.arg1 = 0ULL; + bl33_image_ep_info.args.arg2 = 0ULL; + bl33_image_ep_info.args.arg3 = 0ULL; +# endif /* RPI3_BL33_IN_AARCH32 */ +#endif /* RPI3_DIRECT_LINUX_BOOT */ } void bl31_plat_arch_setup(void) @@ -148,12 +141,10 @@ 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; } diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h index a83a0ad..1a26053 100644 --- a/plat/rpi3/rpi3_hw.h +++ b/plat/rpi3/rpi3_hw.h @@ -59,6 +59,24 @@ #define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) /* + * Hardware random number generator. + */ +#define RPI3_IO_RNG_OFFSET ULL(0x00104000) +#define RPI3_RNG_BASE (RPI3_IO_BASE + RPI3_IO_RNG_OFFSET) +#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000) +#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004) +#define RPI3_RNG_DATA_OFFSET ULL(0x00000008) +#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010) +/* Enable/disable RNG */ +#define RPI3_RNG_CTRL_ENABLE U(0x1) +#define RPI3_RNG_CTRL_DISABLE U(0x0) +/* Number of currently available words */ +#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24) +#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF) +/* Value to mask interrupts caused by the RNG */ +#define RPI3_RNG_INT_MASK_DISABLE U(0x1) + +/* * Serial port (called 'Mini UART' in the BCM docucmentation). */ #define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040) diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c index 9694858..b6adc8a 100644 --- a/plat/rpi3/rpi3_pm.c +++ b/plat/rpi3/rpi3_pm.c @@ -15,11 +15,6 @@ #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 @@ -220,10 +215,9 @@ 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; + uintptr_t *entrypoint = (void *) PLAT_RPI3_TM_ENTRYPOINT; - *mailbox = sec_entrypoint; - secure_entrypoint = (uintptr_t)sec_entrypoint; + *entrypoint = 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 index 9d1744e..91b7add 100644 --- a/plat/rpi3/rpi3_private.h +++ b/plat/rpi3/rpi3_private.h @@ -33,6 +33,9 @@ /* IO storage utility functions */ void plat_rpi3_io_setup(void); +/* Hardware RNG functions */ +void rpi3_rng_read(void *buf, size_t len); + /* VideoCore firmware commands */ int rpi3_vc_hardware_get_board_revision(uint32_t *revision); diff --git a/plat/rpi3/rpi3_rng.c b/plat/rpi3/rpi3_rng.c new file mode 100644 index 0000000..111b3b6 --- /dev/null +++ b/plat/rpi3/rpi3_rng.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "rpi3_hw.h" + +/* Initial amount of values to discard */ +#define RNG_WARMUP_COUNT U(0x40000) + +static void rpi3_rng_initialize(void) +{ + uint32_t int_mask, ctrl; + + /* Return if it is already enabled */ + ctrl = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET); + if ((ctrl & RPI3_RNG_CTRL_ENABLE) != 0U) { + return; + } + + /* Mask interrupts */ + int_mask = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET); + int_mask |= RPI3_RNG_INT_MASK_DISABLE; + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET, int_mask); + + /* Discard several values when initializing to give it time to warmup */ + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET, RNG_WARMUP_COUNT); + + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET, + RPI3_RNG_CTRL_ENABLE); +} + +static uint32_t rpi3_rng_get_word(void) +{ + size_t nwords; + + do { + /* Get number of available words to read */ + nwords = (mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET) + >> RPI3_RNG_STATUS_NUM_WORDS_SHIFT) + & RPI3_RNG_STATUS_NUM_WORDS_MASK; + } while (nwords == 0U); + + return mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_DATA_OFFSET); +} + +void rpi3_rng_read(void *buf, size_t len) +{ + uint32_t data; + size_t left = len; + uint32_t *dst = buf; + + assert(buf != NULL); + assert(len != 0U); + assert(check_uptr_overflow((uintptr_t) buf, (uintptr_t) len) == 0); + + rpi3_rng_initialize(); + + while (left >= sizeof(uint32_t)) { + data = rpi3_rng_get_word(); + *dst++ = data; + left -= sizeof(uint32_t); + } + + if (left > 0U) { + data = rpi3_rng_get_word(); + memcpy(dst, &data, left); + } +} diff --git a/plat/rpi3/rpi3_stack_protector.c b/plat/rpi3/rpi3_stack_protector.c new file mode 100644 index 0000000..d939cd3 --- /dev/null +++ b/plat/rpi3/rpi3_stack_protector.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "rpi3_private.h" + +/* Get 128 bits of entropy and fuse the values together to form the canary. */ +#define TRNG_NBYTES 16U + +u_register_t plat_get_stack_protector_canary(void) +{ + size_t i; + u_register_t buf[TRNG_NBYTES / sizeof(u_register_t)]; + u_register_t ret = 0U; + + rpi3_rng_read(buf, sizeof(buf)); + + for (i = 0U; i < ARRAY_SIZE(buf); i++) + ret ^= buf[i]; + + return ret; +}