Browse Source
This patch adds support for the QEMU virt ARMv8-A target. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>pull/635/head
Jens Wiklander
9 years ago
15 changed files with 2331 additions and 0 deletions
@ -0,0 +1,44 @@ |
|||
ARM Trusted Firmware for QEMU virt ARMv8-A |
|||
========================================== |
|||
|
|||
ARM Trusted Firmware implements the EL3 firmware layer for QEMU virt |
|||
ARMv8-A. BL1 is used as the BootROM, supplied with the -bios argument. |
|||
When QEMU starts all CPUs are released simultaneously, BL1 selects a |
|||
primary CPU to handle the boot and the secondaries are placed in a polling |
|||
loop to be released by normal world via PSCI. |
|||
|
|||
BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to |
|||
add a node describing PSCI and also enable methods for the CPUs. |
|||
|
|||
An ARM64 defonfig v4.5 Linux kernel is known to boot, FTD doesn't need to be |
|||
provided as it's generated by QEMU. |
|||
|
|||
Current limitations: |
|||
* Only cold boot is supported |
|||
* No build instructions for QEMU_EFI.fd and rootfs-arm64.cpio.gz |
|||
* No instructions for how to load a BL32 (Secure Payload) |
|||
|
|||
`QEMU_EFI.fd` can be dowloaded from |
|||
http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC49/QEMU_EFI.fd |
|||
|
|||
Boot binaries, except BL1, are primarily loaded via semi-hosting so all |
|||
binaries has to reside in the same directory as QEMU is started from. This |
|||
is conveniently achieved with symlinks the local names as: |
|||
* `bl2.bin` -> BL2 |
|||
* `bl31.bin` -> BL31 |
|||
* `bl33.bin` -> BL33 (`QEMU_EFI.fd`) |
|||
* `Image` -> linux/Image |
|||
|
|||
To build: |
|||
``` |
|||
make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu |
|||
``` |
|||
|
|||
To start (QEMU v2.6.0): |
|||
``` |
|||
qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \ |
|||
-kernel Image \ |
|||
-append console=ttyAMA0,38400 keep_bootcon root=/dev/vda2 \ |
|||
-initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios bl1.bin \ |
|||
-d unimp -semihosting-config enable,target=native |
|||
``` |
@ -0,0 +1,140 @@ |
|||
/* |
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <arch.h> |
|||
#include <asm_macros.S> |
|||
#include <assert_macros.S> |
|||
#include <platform_def.h> |
|||
|
|||
.globl plat_my_core_pos |
|||
.globl plat_get_my_entrypoint |
|||
.globl platform_mem_init |
|||
.globl plat_qemu_calc_core_pos |
|||
.globl plat_crash_console_init |
|||
.globl plat_crash_console_putc |
|||
.globl plat_secondary_cold_boot_setup |
|||
.globl plat_get_my_entrypoint |
|||
.globl plat_is_my_cpu_primary |
|||
|
|||
|
|||
func plat_my_core_pos |
|||
mrs x0, mpidr_el1 |
|||
b plat_qemu_calc_core_pos |
|||
endfunc plat_my_core_pos |
|||
|
|||
/* |
|||
* unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); |
|||
* With this function: CorePos = (ClusterId * 4) + CoreId |
|||
*/ |
|||
func plat_qemu_calc_core_pos |
|||
and x1, x0, #MPIDR_CPU_MASK |
|||
and x0, x0, #MPIDR_CLUSTER_MASK |
|||
add x0, x1, x0, LSR #6 |
|||
ret |
|||
endfunc plat_qemu_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, #QEMU_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 |
|||
mov_imm x2, PLAT_QEMU_HOLD_BASE |
|||
|
|||
/* Wait until we have a go */ |
|||
poll_mailbox: |
|||
ldr x1, [x2, x0] |
|||
cbz x1, 1f |
|||
mov_imm x0, PLAT_QEMU_TRUSTED_MAILBOX_BASE |
|||
ldr x1, [x0] |
|||
br x1 |
|||
1: |
|||
wfe |
|||
b poll_mailbox |
|||
endfunc plat_secondary_cold_boot_setup |
|||
|
|||
func plat_get_my_entrypoint |
|||
/* TODO support warm boot */ |
|||
mov x0, #0 |
|||
ret |
|||
endfunc plat_get_my_entrypoint |
|||
|
|||
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, x1, x2 |
|||
* --------------------------------------------- |
|||
*/ |
|||
func plat_crash_console_init |
|||
mov_imm x0, PLAT_QEMU_CRASH_UART_BASE |
|||
mov_imm x1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ |
|||
mov_imm x2, PLAT_QEMU_CONSOLE_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_QEMU_CRASH_UART_BASE |
|||
b console_core_putc |
|||
endfunc plat_crash_console_putc |
|||
|
|||
|
@ -0,0 +1,119 @@ |
|||
/*
|
|||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#include <console.h> |
|||
#include <debug.h> |
|||
#include <libfdt.h> |
|||
#include <psci.h> |
|||
#include "qemu_private.h" |
|||
#include <string.h> |
|||
|
|||
static int append_psci_compatible(void *fdt, int offs, const char *str) |
|||
{ |
|||
return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1); |
|||
} |
|||
|
|||
int dt_add_psci_node(void *fdt) |
|||
{ |
|||
int offs; |
|||
|
|||
if (fdt_path_offset(fdt, "/psci") >= 0) { |
|||
WARN("PSCI Device Tree node already exists!\n"); |
|||
return 0; |
|||
} |
|||
|
|||
offs = fdt_path_offset(fdt, "/"); |
|||
if (offs < 0) |
|||
return -1; |
|||
offs = fdt_add_subnode(fdt, offs, "psci"); |
|||
if (offs < 0) |
|||
return -1; |
|||
if (append_psci_compatible(fdt, offs, "arm,psci-1.0")) |
|||
return -1; |
|||
if (append_psci_compatible(fdt, offs, "arm,psci-0.2")) |
|||
return -1; |
|||
if (append_psci_compatible(fdt, offs, "arm,psci")) |
|||
return -1; |
|||
if (fdt_setprop_string(fdt, offs, "method", "smc")) |
|||
return -1; |
|||
if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_AARCH64)) |
|||
return -1; |
|||
if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF)) |
|||
return -1; |
|||
if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_AARCH64)) |
|||
return -1; |
|||
if (fdt_setprop_u32(fdt, offs, "sys_poweroff", PSCI_SYSTEM_OFF)) |
|||
return -1; |
|||
if (fdt_setprop_u32(fdt, offs, "sys_reset", PSCI_SYSTEM_RESET)) |
|||
return -1; |
|||
return 0; |
|||
} |
|||
|
|||
static int check_node_compat_prefix(void *fdt, int offs, const char *prefix) |
|||
{ |
|||
const size_t prefix_len = strlen(prefix); |
|||
size_t l; |
|||
int plen; |
|||
const char *prop; |
|||
|
|||
prop = fdt_getprop(fdt, offs, "compatible", &plen); |
|||
if (!prop) |
|||
return -1; |
|||
|
|||
while (plen > 0) { |
|||
if (memcmp(prop, prefix, prefix_len) == 0) |
|||
return 0; /* match */ |
|||
|
|||
l = strlen(prop) + 1; |
|||
prop += l; |
|||
plen -= l; |
|||
} |
|||
|
|||
return -1; |
|||
} |
|||
|
|||
int dt_add_psci_cpu_enable_methods(void *fdt) |
|||
{ |
|||
int offs = 0; |
|||
|
|||
while (1) { |
|||
offs = fdt_next_node(fdt, offs, NULL); |
|||
if (offs < 0) |
|||
break; |
|||
if (fdt_getprop(fdt, offs, "enable-method", NULL)) |
|||
continue; /* already set */ |
|||
if (check_node_compat_prefix(fdt, offs, "arm,cortex-a")) |
|||
continue; /* no compatible */ |
|||
if (fdt_setprop_string(fdt, offs, "enable-method", "psci")) |
|||
return -1; |
|||
/* Need to restart scanning as offsets may have changed */ |
|||
offs = 0; |
|||
} |
|||
return 0; |
|||
} |
@ -0,0 +1,50 @@ |
|||
/* |
|||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#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 GIC and CCI registers |
|||
* whenever an unhandled exception is taken in |
|||
* BL31. |
|||
* Clobbers: x0 - x10, x16, x17, sp |
|||
* --------------------------------------------- |
|||
*/ |
|||
.macro plat_crash_print_regs |
|||
mov_imm x17, GICC_BASE |
|||
mov_imm x16, GICD_BASE |
|||
arm_print_gic_regs |
|||
.endm |
|||
|
|||
#endif /* __PLAT_MACROS_S__ */ |
@ -0,0 +1,244 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef __PLATFORM_DEF_H__ |
|||
#define __PLATFORM_DEF_H__ |
|||
|
|||
#include <arch.h> |
|||
#include <common_def.h> |
|||
#include <tbbr_img_def.h> |
|||
|
|||
/* Special value used to verify platform parameters from BL2 to BL3-1 */ |
|||
#define QEMU_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL |
|||
|
|||
#define PLATFORM_STACK_SIZE 0x1000 |
|||
|
|||
#define PLATFORM_MAX_CPUS_PER_CLUSTER 4 |
|||
#define PLATFORM_CLUSTER_COUNT 2 |
|||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER |
|||
#define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER |
|||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ |
|||
PLATFORM_CLUSTER1_CORE_COUNT) |
|||
|
|||
#define QEMU_PRIMARY_CPU 0 |
|||
|
|||
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ |
|||
PLATFORM_CORE_COUNT) |
|||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 |
|||
|
|||
#define PLAT_MAX_RET_STATE 1 |
|||
#define PLAT_MAX_OFF_STATE 2 |
|||
|
|||
/* Local power state for power domains in Run state. */ |
|||
#define PLAT_LOCAL_STATE_RUN 0 |
|||
/* Local power state for retention. Valid only for CPU power domains */ |
|||
#define PLAT_LOCAL_STATE_RET 1 |
|||
/*
|
|||
* Local power state for OFF/power-down. Valid for CPU and cluster power |
|||
* domains. |
|||
*/ |
|||
#define PLAT_LOCAL_STATE_OFF 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 4 |
|||
#define PLAT_LOCAL_PSTATE_MASK ((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 6 |
|||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) |
|||
|
|||
/*
|
|||
* Partition memory into secure ROM, non-secure DRAM, secure "SRAM", |
|||
* and secure DRAM. |
|||
*/ |
|||
#define SEC_ROM_BASE 0x00000000 |
|||
#define SEC_ROM_SIZE 0x00020000 |
|||
|
|||
#define NS_DRAM0_BASE 0x40000000 |
|||
#define NS_DRAM0_SIZE 0x3de00000 |
|||
|
|||
#define SEC_SRAM_BASE 0x0e000000 |
|||
#define SEC_SRAM_SIZE 0x00040000 |
|||
|
|||
#define SEC_DRAM_BASE 0x0e100000 |
|||
#define SEC_DRAM_SIZE 0x00f00000 |
|||
|
|||
/*
|
|||
* ARM-TF lives in SRAM, partition it here |
|||
*/ |
|||
|
|||
#define SHARED_RAM_BASE SEC_SRAM_BASE |
|||
#define SHARED_RAM_SIZE 0x00001000 |
|||
|
|||
#define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE |
|||
#define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE) |
|||
#define PLAT_QEMU_HOLD_BASE (PLAT_QEMU_TRUSTED_MAILBOX_BASE + 8) |
|||
#define PLAT_QEMU_HOLD_SIZE (PLATFORM_CORE_COUNT * \ |
|||
PLAT_QEMU_HOLD_ENTRY_SIZE) |
|||
#define PLAT_QEMU_HOLD_ENTRY_SIZE 8 |
|||
#define PLAT_QEMU_HOLD_STATE_WAIT 0 |
|||
#define PLAT_QEMU_HOLD_STATE_GO 1 |
|||
|
|||
#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE) |
|||
#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE) |
|||
|
|||
/*
|
|||
* 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 BL1_RO_BASE SEC_ROM_BASE |
|||
#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE) |
|||
#define BL1_RW_BASE (BL1_RW_LIMIT - 0x12000) |
|||
#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) |
|||
|
|||
/*
|
|||
* BL2 specific defines. |
|||
* |
|||
* Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug |
|||
* size plus a little space for growth. |
|||
*/ |
|||
#define BL2_BASE (BL31_BASE - 0x1D000) |
|||
#define BL2_LIMIT BL31_BASE |
|||
|
|||
/*
|
|||
* BL3-1 specific defines. |
|||
* |
|||
* Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the |
|||
* current BL3-1 debug size plus a little space for growth. |
|||
*/ |
|||
#define BL31_BASE (BL31_LIMIT - 0x20000) |
|||
#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) |
|||
#define BL31_PROGBITS_LIMIT BL1_RW_BASE |
|||
|
|||
|
|||
/*
|
|||
* BL3-2 specific defines. |
|||
* |
|||
* BL3-2 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_DRAM_BASE |
|||
#define BL32_DRAM_LIMIT (SEC_DRAM_BASE + SEC_DRAM_SIZE) |
|||
|
|||
#define SEC_SRAM_ID 0 |
|||
#define SEC_DRAM_ID 1 |
|||
|
|||
#if 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 BL32_RAM_LOCATION_ID == SEC_DRAM_ID |
|||
# define BL32_MEM_BASE SEC_DRAM_BASE |
|||
# define BL32_MEM_SIZE SEC_DRAM_SIZE |
|||
# define BL32_BASE BL32_DRAM_BASE |
|||
# define BL32_LIMIT BL32_DRAM_LIMIT |
|||
#else |
|||
# error "Unsupported BL32_RAM_LOCATION_ID value" |
|||
#endif |
|||
#define BL32_SIZE (BL32_LIMIT - BL32_BASE) |
|||
|
|||
#define NS_IMAGE_OFFSET 0x60000000 |
|||
|
|||
#define ADDR_SPACE_SIZE (1ull << 32) |
|||
#define MAX_MMAP_REGIONS 8 |
|||
#define MAX_XLAT_TABLES 6 |
|||
#define MAX_IO_DEVICES 3 |
|||
#define MAX_IO_HANDLES 4 |
|||
|
|||
/*
|
|||
* PL011 related constants |
|||
*/ |
|||
#define UART0_BASE 0x09000000 |
|||
#define UART1_BASE 0x09040000 |
|||
#define UART0_CLK_IN_HZ 1 |
|||
#define UART1_CLK_IN_HZ 1 |
|||
|
|||
#define PLAT_QEMU_BOOT_UART_BASE UART0_BASE |
|||
#define PLAT_QEMU_BOOT_UART_CLK_IN_HZ UART0_CLK_IN_HZ |
|||
|
|||
#define PLAT_QEMU_CRASH_UART_BASE UART1_BASE |
|||
#define PLAT_QEMU_CRASH_UART_CLK_IN_HZ UART1_CLK_IN_HZ |
|||
|
|||
#define PLAT_QEMU_CONSOLE_BAUDRATE 115200 |
|||
|
|||
#define QEMU_FLASH0_BASE 0x04000000 |
|||
#define QEMU_FLASH0_SIZE 0x04000000 |
|||
|
|||
#define PLAT_QEMU_FIP_BASE QEMU_FLASH0_BASE |
|||
#define PLAT_QEMU_FIP_MAX_SIZE QEMU_FLASH0_SIZE |
|||
|
|||
#define DEVICE0_BASE 0x08000000 |
|||
#define DEVICE0_SIZE 0x00021000 |
|||
#define DEVICE1_BASE 0x09000000 |
|||
#define DEVICE1_SIZE 0x00011000 |
|||
|
|||
/*
|
|||
* GIC related constants |
|||
*/ |
|||
|
|||
#define GICD_BASE 0x8000000 |
|||
#define GICC_BASE 0x8010000 |
|||
#define GICR_BASE 0 |
|||
|
|||
|
|||
#define QEMU_IRQ_SEC_SGI_0 8 |
|||
#define QEMU_IRQ_SEC_SGI_1 9 |
|||
#define QEMU_IRQ_SEC_SGI_2 10 |
|||
#define QEMU_IRQ_SEC_SGI_3 11 |
|||
#define QEMU_IRQ_SEC_SGI_4 12 |
|||
#define QEMU_IRQ_SEC_SGI_5 13 |
|||
#define QEMU_IRQ_SEC_SGI_6 14 |
|||
#define QEMU_IRQ_SEC_SGI_7 15 |
|||
|
|||
/*
|
|||
* DT related constants |
|||
*/ |
|||
#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE |
|||
#define PLAT_QEMU_DT_MAX_SIZE 0x10000 |
|||
|
|||
/*
|
|||
* System counter |
|||
*/ |
|||
#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16) |
|||
|
|||
#endif /* __PLATFORM_DEF_H__ */ |
@ -0,0 +1,99 @@ |
|||
#
|
|||
# Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
|
|||
#
|
|||
# Redistribution and use in source and binary forms, with or without
|
|||
# modification, are permitted provided that the following conditions are met:
|
|||
#
|
|||
# Redistributions of source code must retain the above copyright notice, this
|
|||
# list of conditions and the following disclaimer.
|
|||
#
|
|||
# Redistributions in binary form must reproduce the above copyright notice,
|
|||
# this list of conditions and the following disclaimer in the documentation
|
|||
# and/or other materials provided with the distribution.
|
|||
#
|
|||
# Neither the name of ARM nor the names of its contributors may be used
|
|||
# to endorse or promote products derived from this software without specific
|
|||
# prior written permission.
|
|||
#
|
|||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|||
# POSSIBILITY OF SUCH DAMAGE.
|
|||
#
|
|||
|
|||
include lib/libfdt/libfdt.mk |
|||
|
|||
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
|
|||
-Iinclude/plat/arm/common/aarch64/ \
|
|||
-Iplat/qemu/include \
|
|||
-Iinclude/common/tbbr |
|||
|
|||
|
|||
PLAT_BL_COMMON_SOURCES := plat/qemu/qemu_common.c \
|
|||
drivers/arm/pl011/pl011_console.S \
|
|||
lib/xlat_tables/xlat_tables_common.c \
|
|||
lib/xlat_tables/aarch64/xlat_tables.c |
|||
|
|||
BL1_SOURCES += drivers/io/io_semihosting.c \
|
|||
drivers/io/io_storage.c \
|
|||
drivers/io/io_fip.c \
|
|||
drivers/io/io_memmap.c \
|
|||
lib/semihosting/semihosting.c \
|
|||
lib/semihosting/aarch64/semihosting_call.S \
|
|||
plat/qemu/qemu_io_storage.c \
|
|||
lib/cpus/aarch64/aem_generic.S \
|
|||
lib/cpus/aarch64/cortex_a53.S \
|
|||
lib/cpus/aarch64/cortex_a57.S \
|
|||
plat/common/aarch64/platform_mp_stack.S \
|
|||
plat/qemu/aarch64/plat_helpers.S \
|
|||
plat/qemu/qemu_bl1_setup.c |
|||
|
|||
BL2_SOURCES += drivers/io/io_semihosting.c \
|
|||
drivers/io/io_storage.c \
|
|||
drivers/io/io_fip.c \
|
|||
drivers/io/io_memmap.c \
|
|||
plat/common/aarch64/platform_mp_stack.S \
|
|||
lib/semihosting/semihosting.c \
|
|||
lib/semihosting/aarch64/semihosting_call.S\
|
|||
plat/qemu/qemu_io_storage.c \
|
|||
plat/qemu/aarch64/plat_helpers.S \
|
|||
plat/qemu/qemu_bl2_setup.c \
|
|||
plat/qemu/dt.c \
|
|||
$(LIBFDT_SRCS) |
|||
|
|||
BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
|
|||
lib/cpus/aarch64/cortex_a53.S \
|
|||
lib/cpus/aarch64/cortex_a57.S \
|
|||
drivers/arm/gic/v2/gicv2_helpers.c \
|
|||
drivers/arm/gic/v2/gicv2_main.c \
|
|||
drivers/arm/gic/common/gic_common.c \
|
|||
plat/common/aarch64/platform_mp_stack.S \
|
|||
plat/common/aarch64/plat_psci_common.c \
|
|||
plat/common/aarch64/plat_common.c \
|
|||
plat/qemu/qemu_pm.c \
|
|||
plat/qemu/topology.c \
|
|||
plat/qemu/aarch64/plat_helpers.S \
|
|||
plat/qemu/qemu_bl31_setup.c \
|
|||
plat/qemu/qemu_gic.c |
|||
|
|||
# Disable the PSCI platform compatibility layer
|
|||
ENABLE_PLAT_COMPAT := 0 |
|||
|
|||
BL32_RAM_LOCATION := tdram |
|||
ifeq (${BL32_RAM_LOCATION}, tsram) |
|||
BL32_RAM_LOCATION_ID = SEC_SRAM_ID |
|||
else ifeq (${BL32_RAM_LOCATION}, tdram) |
|||
BL32_RAM_LOCATION_ID = SEC_DRAM_ID |
|||
else |
|||
$(error "Unsupported BL32_RAM_LOCATION value") |
|||
endif |
|||
|
|||
# Process flags
|
|||
$(eval $(call add_define,BL32_RAM_LOCATION_ID)) |
@ -0,0 +1,148 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <arch.h> |
|||
#include <arch_helpers.h> |
|||
#include <assert.h> |
|||
#include <bl_common.h> |
|||
#include <console.h> |
|||
#include <platform_def.h> |
|||
#include "qemu_private.h" |
|||
|
|||
|
|||
/*
|
|||
* The next 2 constants identify the extents of the coherent memory region. |
|||
* These addresses are used by the MMU setup code and therefore they must be |
|||
* page-aligned. It is the responsibility of the linker script to ensure that |
|||
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to |
|||
* page-aligned addresses. |
|||
*/ |
|||
#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) |
|||
#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) |
|||
|
|||
|
|||
/*******************************************************************************
|
|||
* Declarations of linker defined symbols which will tell us where BL1 lives |
|||
* in Trusted RAM |
|||
******************************************************************************/ |
|||
extern uint64_t __BL1_RAM_START__; |
|||
extern uint64_t __BL1_RAM_END__; |
|||
#define BL1_RAM_BASE (uint64_t)(&__BL1_RAM_START__) |
|||
#define BL1_RAM_LIMIT (uint64_t)(&__BL1_RAM_END__) |
|||
|
|||
/* 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) |
|||
{ |
|||
const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE; |
|||
|
|||
/* Initialize the console to provide early debug support */ |
|||
console_init(PLAT_QEMU_BOOT_UART_BASE, PLAT_QEMU_BOOT_UART_CLK_IN_HZ, |
|||
PLAT_QEMU_CONSOLE_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; |
|||
|
|||
/* Calculate how much RAM BL1 is using and how much remains free */ |
|||
bl1_tzram_layout.free_base = BL_RAM_BASE; |
|||
bl1_tzram_layout.free_size = BL_RAM_SIZE; |
|||
reserve_mem(&bl1_tzram_layout.free_base, &bl1_tzram_layout.free_size, |
|||
BL1_RAM_BASE, bl1_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) |
|||
{ |
|||
qemu_configure_mmu_el3(bl1_tzram_layout.total_base, |
|||
bl1_tzram_layout.total_size, |
|||
BL1_RO_BASE, BL1_RO_LIMIT, |
|||
BL1_COHERENT_RAM_BASE, BL1_COHERENT_RAM_LIMIT); |
|||
} |
|||
|
|||
void bl1_platform_setup(void) |
|||
{ |
|||
plat_qemu_io_setup(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Function that takes a memory layout into which BL2 has been loaded and |
|||
* populates a new memory layout for BL2 that ensures that BL1's data sections |
|||
* resident in secure RAM are not visible to BL2. |
|||
******************************************************************************/ |
|||
void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout, |
|||
meminfo_t *bl2_mem_layout) |
|||
{ |
|||
const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE; |
|||
|
|||
assert(bl1_mem_layout != NULL); |
|||
assert(bl2_mem_layout != NULL); |
|||
|
|||
/* Check that BL1's memory is lying outside of the free memory */ |
|||
assert((BL1_RAM_LIMIT <= bl1_mem_layout->free_base) || |
|||
(BL1_RAM_BASE >= (bl1_mem_layout->free_base + |
|||
bl1_mem_layout->free_size))); |
|||
|
|||
/* Remove BL1 RW data from the scope of memory visible to BL2 */ |
|||
*bl2_mem_layout = *bl1_mem_layout; |
|||
reserve_mem(&bl2_mem_layout->total_base, |
|||
&bl2_mem_layout->total_size, |
|||
BL1_RAM_BASE, |
|||
bl1_size); |
|||
|
|||
flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t)); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Before calling this function BL2 is loaded in memory and its entrypoint |
|||
* is set by load_image. This is a placeholder for the platform to change |
|||
* the entrypoint of BL2 and set SPSR and security state. |
|||
* On ARM standard platforms we only set the security state of the entrypoint |
|||
******************************************************************************/ |
|||
void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image, |
|||
entry_point_info_t *bl2_ep) |
|||
{ |
|||
SET_SECURITY_STATE(bl2_ep->h.attr, SECURE); |
|||
bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); |
|||
} |
@ -0,0 +1,327 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#include <arch_helpers.h> |
|||
#include <bl_common.h> |
|||
#include <console.h> |
|||
#include <debug.h> |
|||
#include <libfdt.h> |
|||
#include <platform_def.h> |
|||
#include "qemu_private.h" |
|||
#include <string.h> |
|||
|
|||
|
|||
/*
|
|||
* The next 2 constants identify the extents of the code & RO data region. |
|||
* These addresses are used by the MMU setup code and therefore they must be |
|||
* page-aligned. It is the responsibility of the linker script to ensure that |
|||
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. |
|||
*/ |
|||
#define BL2_RO_BASE (unsigned long)(&__RO_START__) |
|||
#define BL2_RO_LIMIT (unsigned long)(&__RO_END__) |
|||
|
|||
/*
|
|||
* The next 2 constants identify the extents of the coherent memory region. |
|||
* These addresses are used by the MMU setup code and therefore they must be |
|||
* page-aligned. It is the responsibility of the linker script to ensure that |
|||
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to |
|||
* page-aligned addresses. |
|||
*/ |
|||
#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) |
|||
#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) |
|||
|
|||
/*******************************************************************************
|
|||
* This structure represents the superset of information that is passed to |
|||
* BL3-1, e.g. while passing control to it from BL2, bl31_params |
|||
* and other platform specific params |
|||
******************************************************************************/ |
|||
typedef struct bl2_to_bl31_params_mem { |
|||
bl31_params_t bl31_params; |
|||
image_info_t bl31_image_info; |
|||
image_info_t bl32_image_info; |
|||
image_info_t bl33_image_info; |
|||
entry_point_info_t bl33_ep_info; |
|||
entry_point_info_t bl32_ep_info; |
|||
entry_point_info_t bl31_ep_info; |
|||
} bl2_to_bl31_params_mem_t; |
|||
|
|||
|
|||
static bl2_to_bl31_params_mem_t bl31_params_mem; |
|||
|
|||
|
|||
|
|||
/* Data structure which holds the extents of the trusted SRAM for BL2 */ |
|||
static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); |
|||
|
|||
meminfo_t *bl2_plat_sec_mem_layout(void) |
|||
{ |
|||
return &bl2_tzram_layout; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function assigns a pointer to the memory that the platform has kept |
|||
* aside to pass platform specific and trusted firmware related information |
|||
* to BL31. This memory is allocated by allocating memory to |
|||
* bl2_to_bl31_params_mem_t structure which is a superset of all the |
|||
* structure whose information is passed to BL31 |
|||
* NOTE: This function should be called only once and should be done |
|||
* before generating params to BL31 |
|||
******************************************************************************/ |
|||
bl31_params_t *bl2_plat_get_bl31_params(void) |
|||
{ |
|||
bl31_params_t *bl2_to_bl31_params; |
|||
|
|||
/*
|
|||
* Initialise the memory for all the arguments that needs to |
|||
* be passed to BL3-1 |
|||
*/ |
|||
memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t)); |
|||
|
|||
/* Assign memory for TF related information */ |
|||
bl2_to_bl31_params = &bl31_params_mem.bl31_params; |
|||
SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); |
|||
|
|||
/* Fill BL3-1 related information */ |
|||
bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; |
|||
SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, |
|||
VERSION_1, 0); |
|||
|
|||
/* Fill BL3-2 related information */ |
|||
bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; |
|||
SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, |
|||
VERSION_1, 0); |
|||
bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; |
|||
SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, |
|||
VERSION_1, 0); |
|||
|
|||
/* Fill BL3-3 related information */ |
|||
bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; |
|||
SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, |
|||
PARAM_EP, VERSION_1, 0); |
|||
|
|||
/* BL3-3 expects to receive the primary CPU MPID (through x0) */ |
|||
bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); |
|||
|
|||
bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; |
|||
SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, |
|||
VERSION_1, 0); |
|||
|
|||
return bl2_to_bl31_params; |
|||
} |
|||
|
|||
/* Flush the TF params and the TF plat params */ |
|||
void bl2_plat_flush_bl31_params(void) |
|||
{ |
|||
flush_dcache_range((unsigned long)&bl31_params_mem, |
|||
sizeof(bl2_to_bl31_params_mem_t)); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function returns a pointer to the shared memory that the platform |
|||
* has kept to point to entry point information of BL31 to BL2 |
|||
******************************************************************************/ |
|||
struct entry_point_info *bl2_plat_get_bl31_ep_info(void) |
|||
{ |
|||
#if DEBUG |
|||
bl31_params_mem.bl31_ep_info.args.arg1 = QEMU_BL31_PLAT_PARAM_VAL; |
|||
#endif |
|||
|
|||
return &bl31_params_mem.bl31_ep_info; |
|||
} |
|||
|
|||
|
|||
|
|||
void bl2_early_platform_setup(meminfo_t *mem_layout) |
|||
{ |
|||
/* Initialize the console to provide early debug support */ |
|||
console_init(PLAT_QEMU_BOOT_UART_BASE, PLAT_QEMU_BOOT_UART_CLK_IN_HZ, |
|||
PLAT_QEMU_CONSOLE_BAUDRATE); |
|||
|
|||
/* Setup the BL2 memory layout */ |
|||
bl2_tzram_layout = *mem_layout; |
|||
|
|||
plat_qemu_io_setup(); |
|||
} |
|||
|
|||
static void security_setup(void) |
|||
{ |
|||
/*
|
|||
* This is where a TrustZone address space controller and other |
|||
* security related peripherals, would be configured. |
|||
*/ |
|||
} |
|||
|
|||
static void update_dt(void) |
|||
{ |
|||
int ret; |
|||
void *fdt = (void *)(uintptr_t)PLAT_QEMU_DT_BASE; |
|||
|
|||
ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE); |
|||
if (ret < 0) { |
|||
ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret); |
|||
return; |
|||
} |
|||
|
|||
if (dt_add_psci_node(fdt)) { |
|||
ERROR("Failed to add PSCI Device Tree node\n"); |
|||
return; |
|||
} |
|||
|
|||
if (dt_add_psci_cpu_enable_methods(fdt)) { |
|||
ERROR("Failed to add PSCI cpu enable methods in Device Tree\n"); |
|||
return; |
|||
} |
|||
|
|||
ret = fdt_pack(fdt); |
|||
if (ret < 0) |
|||
ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, ret); |
|||
} |
|||
|
|||
void bl2_platform_setup(void) |
|||
{ |
|||
security_setup(); |
|||
update_dt(); |
|||
|
|||
/* TODO Initialize timer */ |
|||
} |
|||
|
|||
void bl2_plat_arch_setup(void) |
|||
{ |
|||
qemu_configure_mmu_el1(bl2_tzram_layout.total_base, |
|||
bl2_tzram_layout.total_size, |
|||
BL2_RO_BASE, BL2_RO_LIMIT, |
|||
BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Gets SPSR for BL32 entry |
|||
******************************************************************************/ |
|||
static uint32_t qemu_get_spsr_for_bl32_entry(void) |
|||
{ |
|||
/*
|
|||
* The Secure Payload Dispatcher service is responsible for |
|||
* setting the SPSR prior to entry into the BL3-2 image. |
|||
*/ |
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Gets SPSR for BL33 entry |
|||
******************************************************************************/ |
|||
static uint32_t qemu_get_spsr_for_bl33_entry(void) |
|||
{ |
|||
unsigned long el_status; |
|||
unsigned int mode; |
|||
uint32_t spsr; |
|||
|
|||
/* Figure out what mode we enter the non-secure world in */ |
|||
el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; |
|||
el_status &= ID_AA64PFR0_ELX_MASK; |
|||
|
|||
mode = (el_status) ? MODE_EL2 : MODE_EL1; |
|||
|
|||
/*
|
|||
* TODO: Consider the possibility of specifying the SPSR in |
|||
* the FIP ToC and allowing the platform to have a say as |
|||
* well. |
|||
*/ |
|||
spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); |
|||
return spsr; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Before calling this function BL3-1 is loaded in memory and its entrypoint |
|||
* is set by load_image. This is a placeholder for the platform to change |
|||
* the entrypoint of BL3-1 and set SPSR and security state. |
|||
* On ARM standard platforms we only set the security state of the entrypoint |
|||
******************************************************************************/ |
|||
void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info, |
|||
entry_point_info_t *bl31_ep_info) |
|||
{ |
|||
SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE); |
|||
bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, |
|||
DISABLE_ALL_EXCEPTIONS); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Before calling this function BL3-2 is loaded in memory and its entrypoint |
|||
* is set by load_image. This is a placeholder for the platform to change |
|||
* the entrypoint of BL3-2 and set SPSR and security state. |
|||
* On ARM standard platforms we only set the security state of the entrypoint |
|||
******************************************************************************/ |
|||
void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info, |
|||
entry_point_info_t *bl32_ep_info) |
|||
{ |
|||
SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE); |
|||
bl32_ep_info->spsr = qemu_get_spsr_for_bl32_entry(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Before calling this function BL3-3 is loaded in memory and its entrypoint |
|||
* is set by load_image. This is a placeholder for the platform to change |
|||
* the entrypoint of BL3-3 and set SPSR and security state. |
|||
* On ARM standard platforms we only set the security state of the entrypoint |
|||
******************************************************************************/ |
|||
void bl2_plat_set_bl33_ep_info(image_info_t *image, |
|||
entry_point_info_t *bl33_ep_info) |
|||
{ |
|||
|
|||
SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE); |
|||
bl33_ep_info->spsr = qemu_get_spsr_for_bl33_entry(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Populate the extents of memory available for loading BL32 |
|||
******************************************************************************/ |
|||
void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) |
|||
{ |
|||
/*
|
|||
* Populate the extents of memory available for loading BL32. |
|||
*/ |
|||
bl32_meminfo->total_base = BL32_BASE; |
|||
bl32_meminfo->free_base = BL32_BASE; |
|||
bl32_meminfo->total_size = (BL32_MEM_BASE + BL32_MEM_SIZE) - BL32_BASE; |
|||
bl32_meminfo->free_size = (BL32_MEM_BASE + BL32_MEM_SIZE) - BL32_BASE; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Populate the extents of memory available for loading BL33 |
|||
******************************************************************************/ |
|||
void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) |
|||
{ |
|||
bl33_meminfo->total_base = NS_DRAM0_BASE; |
|||
bl33_meminfo->total_size = NS_DRAM0_SIZE; |
|||
bl33_meminfo->free_base = NS_DRAM0_BASE; |
|||
bl33_meminfo->free_size = NS_DRAM0_SIZE; |
|||
} |
|||
|
|||
unsigned long plat_get_ns_image_entrypoint(void) |
|||
{ |
|||
return NS_IMAGE_OFFSET; |
|||
} |
@ -0,0 +1,164 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include <bl_common.h> |
|||
#include <console.h> |
|||
#include <gicv2.h> |
|||
#include <platform_def.h> |
|||
#include "qemu_private.h" |
|||
|
|||
/*
|
|||
* The next 3 constants identify the extents of the code, RO data region and the |
|||
* limit of the BL3-1 image. These addresses are used by the MMU setup code and |
|||
* therefore they must be page-aligned. It is the responsibility of the linker |
|||
* script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols |
|||
* refer to page-aligned addresses. |
|||
*/ |
|||
#define BL31_RO_BASE (unsigned long)(&__RO_START__) |
|||
#define BL31_RO_LIMIT (unsigned long)(&__RO_END__) |
|||
#define BL31_END (unsigned long)(&__BL31_END__) |
|||
|
|||
/*
|
|||
* The next 2 constants identify the extents of the coherent memory region. |
|||
* These addresses are used by the MMU setup code and therefore they must be |
|||
* page-aligned. It is the responsibility of the linker script to ensure that |
|||
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols |
|||
* refer to page-aligned addresses. |
|||
*/ |
|||
#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) |
|||
#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) |
|||
|
|||
/*
|
|||
* Placeholder variables for copying the arguments that have been passed to |
|||
* BL3-1 from BL2. |
|||
*/ |
|||
static entry_point_info_t bl32_image_ep_info; |
|||
static entry_point_info_t bl33_image_ep_info; |
|||
|
|||
/*******************************************************************************
|
|||
* Perform any BL3-1 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(bl31_params_t *from_bl2, |
|||
void *plat_params_from_bl2) |
|||
{ |
|||
/* Initialize the console to provide early debug support */ |
|||
console_init(PLAT_QEMU_BOOT_UART_BASE, PLAT_QEMU_BOOT_UART_CLK_IN_HZ, |
|||
PLAT_QEMU_CONSOLE_BAUDRATE); |
|||
|
|||
/*
|
|||
* Check params passed from BL2 should not be NULL, |
|||
*/ |
|||
assert(from_bl2 != NULL); |
|||
assert(from_bl2->h.type == PARAM_BL31); |
|||
assert(from_bl2->h.version >= VERSION_1); |
|||
/*
|
|||
* In debug builds, we pass a special value in 'plat_params_from_bl2' |
|||
* to verify platform parameters from BL2 to BL3-1. |
|||
* In release builds, it's not used. |
|||
*/ |
|||
assert(((unsigned long long)plat_params_from_bl2) == |
|||
QEMU_BL31_PLAT_PARAM_VAL); |
|||
|
|||
/*
|
|||
* Copy BL3-2 (if populated by BL2) and BL3-3 entry point information. |
|||
* They are stored in Secure RAM, in BL2's address space. |
|||
*/ |
|||
if (from_bl2->bl32_ep_info) |
|||
bl32_image_ep_info = *from_bl2->bl32_ep_info; |
|||
bl33_image_ep_info = *from_bl2->bl33_ep_info; |
|||
} |
|||
|
|||
void bl31_plat_arch_setup(void) |
|||
{ |
|||
qemu_configure_mmu_el3(BL31_RO_BASE, (BL31_END - BL31_RO_BASE), |
|||
BL31_RO_BASE, BL31_RO_LIMIT, |
|||
BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT); |
|||
} |
|||
|
|||
static const unsigned int irq_sec_array[] = { |
|||
QEMU_IRQ_SEC_SGI_0, |
|||
QEMU_IRQ_SEC_SGI_1, |
|||
QEMU_IRQ_SEC_SGI_2, |
|||
QEMU_IRQ_SEC_SGI_3, |
|||
QEMU_IRQ_SEC_SGI_4, |
|||
QEMU_IRQ_SEC_SGI_5, |
|||
QEMU_IRQ_SEC_SGI_6, |
|||
QEMU_IRQ_SEC_SGI_7, |
|||
}; |
|||
|
|||
static const struct gicv2_driver_data plat_gicv2_driver_data = { |
|||
.gicd_base = GICD_BASE, |
|||
.gicc_base = GICC_BASE, |
|||
.g0_interrupt_num = ARRAY_SIZE(irq_sec_array), |
|||
.g0_interrupt_array = irq_sec_array, |
|||
}; |
|||
|
|||
void bl31_platform_setup(void) |
|||
{ |
|||
/* Initialize the gic cpu and distributor interfaces */ |
|||
gicv2_driver_init(&plat_gicv2_driver_data); |
|||
gicv2_distif_init(); |
|||
gicv2_pcpu_distif_init(); |
|||
gicv2_cpuif_enable(); |
|||
} |
|||
|
|||
unsigned int plat_get_syscnt_freq2(void) |
|||
{ |
|||
return SYS_COUNTER_FREQ_IN_TICKS; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Return a pointer to the 'entry_point_info' structure of the next image |
|||
* for the security state specified. BL3-3 corresponds to the non-secure |
|||
* image type while BL3-2 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)); |
|||
next_image_info = (type == NON_SECURE) |
|||
? &bl33_image_ep_info : &bl32_image_ep_info; |
|||
/*
|
|||
* None of the images on the ARM development platforms can have 0x0 |
|||
* as the entrypoint |
|||
*/ |
|||
if (next_image_info->pc) |
|||
return next_image_info; |
|||
else |
|||
return NULL; |
|||
} |
@ -0,0 +1,145 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <bl_common.h> |
|||
#include <platform_def.h> |
|||
#include "qemu_private.h" |
|||
#include <xlat_tables.h> |
|||
|
|||
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ |
|||
DEVICE0_SIZE, \ |
|||
MT_DEVICE | MT_RW | MT_SECURE) |
|||
|
|||
#ifdef DEVICE1_BASE |
|||
#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ |
|||
DEVICE1_SIZE, \ |
|||
MT_DEVICE | MT_RW | MT_SECURE) |
|||
#endif |
|||
|
|||
#ifdef DEVICE2_BASE |
|||
#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ |
|||
DEVICE2_SIZE, \ |
|||
MT_DEVICE | MT_RO | MT_SECURE) |
|||
#endif |
|||
|
|||
#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ |
|||
SHARED_RAM_SIZE, \ |
|||
MT_DEVICE | MT_RW | MT_SECURE) |
|||
|
|||
#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \ |
|||
MT_MEMORY | 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_FLASH0 MAP_REGION_FLAT(QEMU_FLASH0_BASE, QEMU_FLASH0_SIZE, \ |
|||
MT_MEMORY | MT_RO | MT_SECURE) |
|||
|
|||
/*
|
|||
* Table of regions for various BL stages to map using the MMU. |
|||
* This doesn't include TZRAM as the 'mem_layout' argument passed to |
|||
* arm_configure_mmu_elx() will give the available subset of that, |
|||
*/ |
|||
#if IMAGE_BL1 |
|||
static const mmap_region_t plat_qemu_mmap[] = { |
|||
MAP_FLASH0, |
|||
MAP_SHARED_RAM, |
|||
MAP_DEVICE0, |
|||
#ifdef MAP_DEVICE1 |
|||
MAP_DEVICE1, |
|||
#endif |
|||
#ifdef MAP_DEVICE2 |
|||
MAP_DEVICE2, |
|||
#endif |
|||
{0} |
|||
}; |
|||
#endif |
|||
#if IMAGE_BL2 |
|||
static const mmap_region_t plat_qemu_mmap[] = { |
|||
MAP_FLASH0, |
|||
MAP_SHARED_RAM, |
|||
MAP_DEVICE0, |
|||
#ifdef MAP_DEVICE1 |
|||
MAP_DEVICE1, |
|||
#endif |
|||
#ifdef MAP_DEVICE2 |
|||
MAP_DEVICE2, |
|||
#endif |
|||
MAP_NS_DRAM0, |
|||
MAP_BL32_MEM, |
|||
{0} |
|||
}; |
|||
#endif |
|||
#if IMAGE_BL31 |
|||
static const mmap_region_t plat_qemu_mmap[] = { |
|||
MAP_SHARED_RAM, |
|||
MAP_DEVICE0, |
|||
#ifdef MAP_DEVICE1 |
|||
MAP_DEVICE1, |
|||
#endif |
|||
MAP_BL32_MEM, |
|||
{0} |
|||
}; |
|||
#endif |
|||
|
|||
/*******************************************************************************
|
|||
* Macro generating the code for the function setting up the pagetables as per |
|||
* the platform memory map & initialize the mmu, for the given exception level |
|||
******************************************************************************/ |
|||
|
|||
#define DEFINE_CONFIGURE_MMU_EL(_el) \ |
|||
void qemu_configure_mmu_el##_el(unsigned long total_base, \ |
|||
unsigned long total_size, \ |
|||
unsigned long ro_start, \ |
|||
unsigned long ro_limit, \ |
|||
unsigned long coh_start, \ |
|||
unsigned long coh_limit) \ |
|||
{ \ |
|||
mmap_add_region(total_base, total_base, \ |
|||
total_size, \ |
|||
MT_MEMORY | MT_RW | MT_SECURE); \ |
|||
mmap_add_region(ro_start, ro_start, \ |
|||
ro_limit - ro_start, \ |
|||
MT_MEMORY | MT_RO | MT_SECURE); \ |
|||
mmap_add_region(coh_start, coh_start, \ |
|||
coh_limit - coh_start, \ |
|||
MT_DEVICE | MT_RW | MT_SECURE); \ |
|||
mmap_add(plat_qemu_mmap); \ |
|||
init_xlat_tables(); \ |
|||
\ |
|||
enable_mmu_el##_el(0); \ |
|||
} |
|||
|
|||
/* Define EL1 and EL3 variants of the function initialising the MMU */ |
|||
DEFINE_CONFIGURE_MMU_EL(1) |
|||
DEFINE_CONFIGURE_MMU_EL(3) |
|||
|
|||
|
@ -0,0 +1,92 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include <bl_common.h> |
|||
#include <gicv2.h> |
|||
#include <interrupt_mgmt.h> |
|||
|
|||
uint32_t plat_ic_get_pending_interrupt_id(void) |
|||
{ |
|||
return gicv2_get_pending_interrupt_id(); |
|||
} |
|||
|
|||
uint32_t plat_ic_get_pending_interrupt_type(void) |
|||
{ |
|||
return gicv2_get_pending_interrupt_type(); |
|||
} |
|||
|
|||
uint32_t plat_ic_acknowledge_interrupt(void) |
|||
{ |
|||
return gicv2_acknowledge_interrupt(); |
|||
} |
|||
|
|||
uint32_t plat_ic_get_interrupt_type(uint32_t id) |
|||
{ |
|||
uint32_t group; |
|||
|
|||
group = gicv2_get_interrupt_group(id); |
|||
|
|||
/* Assume that all secure interrupts are S-EL1 interrupts */ |
|||
if (!group) |
|||
return INTR_TYPE_S_EL1; |
|||
else |
|||
return INTR_TYPE_NS; |
|||
|
|||
} |
|||
|
|||
void plat_ic_end_of_interrupt(uint32_t id) |
|||
{ |
|||
gicv2_end_of_interrupt(id); |
|||
} |
|||
|
|||
uint32_t plat_interrupt_type_to_line(uint32_t type, |
|||
uint32_t security_state) |
|||
{ |
|||
assert(type == INTR_TYPE_S_EL1 || |
|||
type == INTR_TYPE_EL3 || |
|||
type == INTR_TYPE_NS); |
|||
|
|||
assert(sec_state_is_valid(security_state)); |
|||
|
|||
/* Non-secure interrupts are signalled on the IRQ line always */ |
|||
if (type == INTR_TYPE_NS) |
|||
return __builtin_ctz(SCR_IRQ_BIT); |
|||
|
|||
/*
|
|||
* Secure interrupts are signalled using the IRQ line if the FIQ_EN |
|||
* bit is not set else they are signalled using the FIQ line. |
|||
*/ |
|||
if (gicv2_is_fiq_enabled()) |
|||
return __builtin_ctz(SCR_FIQ_BIT); |
|||
else |
|||
return __builtin_ctz(SCR_IRQ_BIT); |
|||
} |
|||
|
@ -0,0 +1,378 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include <bl_common.h> /* For ARRAY_SIZE */ |
|||
#include <debug.h> |
|||
#include <firmware_image_package.h> |
|||
#include <io_driver.h> |
|||
#include <io_fip.h> |
|||
#include <io_memmap.h> |
|||
#include <io_semihosting.h> |
|||
#include <io_storage.h> |
|||
#include <platform_def.h> |
|||
#include <semihosting.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_dev_connector_t *sh_dev_con; |
|||
static uintptr_t sh_dev_handle; |
|||
|
|||
static const io_block_spec_t fip_block_spec = { |
|||
.offset = PLAT_QEMU_FIP_BASE, |
|||
.length = PLAT_QEMU_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 const io_file_spec_t sh_file_spec[] = { |
|||
[BL2_IMAGE_ID] = { |
|||
.path = BL2_IMAGE_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL31_IMAGE_ID] = { |
|||
.path = BL31_IMAGE_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL32_IMAGE_ID] = { |
|||
.path = BL32_IMAGE_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL33_IMAGE_ID] = { |
|||
.path = BL33_IMAGE_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
#if TRUSTED_BOARD_BOOT |
|||
[BL2_CERT_ID] = { |
|||
.path = BL2_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[TRUSTED_KEY_CERT_ID] = { |
|||
.path = TRUSTED_KEY_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL31_KEY_CERT_ID] = { |
|||
.path = BL31_KEY_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL32_KEY_CERT_ID] = { |
|||
.path = BL32_KEY_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL33_KEY_CERT_ID] = { |
|||
.path = BL33_KEY_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL31_CERT_ID] = { |
|||
.path = BL31_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL32_CERT_ID] = { |
|||
.path = BL32_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
[BL33_CERT_ID] = { |
|||
.path = BL33_CERT_NAME, |
|||
.mode = FOPEN_MODE_RB |
|||
}, |
|||
#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, ARM platforms 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; |
|||
} |
|||
|
|||
static int open_semihosting(const uintptr_t spec) |
|||
{ |
|||
int result; |
|||
uintptr_t local_image_handle; |
|||
|
|||
/* See if the file exists on semi-hosting.*/ |
|||
result = io_dev_init(sh_dev_handle, (uintptr_t)NULL); |
|||
if (result == 0) { |
|||
result = io_open(sh_dev_handle, spec, &local_image_handle); |
|||
if (result == 0) { |
|||
VERBOSE("Using Semi-hosting IO\n"); |
|||
io_close(local_image_handle); |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
void plat_qemu_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); |
|||
|
|||
/* Register the additional IO devices on this platform */ |
|||
io_result = register_io_dev_sh(&sh_dev_con); |
|||
assert(io_result == 0); |
|||
|
|||
/* Open connections to devices and cache the handles */ |
|||
io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle); |
|||
assert(io_result == 0); |
|||
|
|||
/* Ignore improbable errors in release builds */ |
|||
(void)io_result; |
|||
} |
|||
|
|||
static int get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle, |
|||
uintptr_t *image_spec) |
|||
{ |
|||
int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]); |
|||
|
|||
if (result == 0) { |
|||
*dev_handle = sh_dev_handle; |
|||
*image_spec = (uintptr_t)&sh_file_spec[image_id]; |
|||
} |
|||
|
|||
return 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); |
|||
} else { |
|||
VERBOSE("Trying alternative IO\n"); |
|||
result = get_alt_image_source(image_id, dev_handle, image_spec); |
|||
} |
|||
|
|||
return result; |
|||
} |
@ -0,0 +1,253 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <assert.h> |
|||
#include <debug.h> |
|||
#include <gicv2.h> |
|||
#include <platform_def.h> |
|||
#include <platform.h> |
|||
#include <psci.h> |
|||
|
|||
/*
|
|||
* The secure entry point to be used on warm reset. |
|||
*/ |
|||
static unsigned long secure_entrypoint; |
|||
|
|||
/* Make composite power state parameter till power level 0 */ |
|||
#if PSCI_EXTENDED_STATE_ID |
|||
|
|||
#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ |
|||
(((lvl0_state) << PSTATE_ID_SHIFT) | \ |
|||
((type) << PSTATE_TYPE_SHIFT)) |
|||
#else |
|||
#define qemu_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 qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ |
|||
(((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ |
|||
qemu_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 qemu_pm_idle_states[] = { |
|||
/* State-id - 0x01 */ |
|||
qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, |
|||
MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), |
|||
/* State-id - 0x02 */ |
|||
qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, |
|||
MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), |
|||
/* State-id - 0x22 */ |
|||
qemu_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 qemu_validate_power_state(unsigned int power_state, |
|||
psci_power_state_t *req_state) |
|||
{ |
|||
unsigned int state_id; |
|||
int i; |
|||
|
|||
assert(req_state); |
|||
|
|||
/*
|
|||
* 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; !!qemu_pm_idle_states[i]; i++) { |
|||
if (power_state == qemu_pm_idle_states[i]) |
|||
break; |
|||
} |
|||
|
|||
/* Return error if entry not found in the idle state array */ |
|||
if (!qemu_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 to check the validity of the non secure |
|||
* entrypoint. |
|||
******************************************************************************/ |
|||
static int qemu_validate_ns_entrypoint(uintptr_t entrypoint) |
|||
{ |
|||
/*
|
|||
* Check if the non secure entrypoint lies within the non |
|||
* secure DRAM. |
|||
*/ |
|||
if ((entrypoint >= NS_DRAM0_BASE) && |
|||
(entrypoint < (NS_DRAM0_BASE + NS_DRAM0_SIZE))) |
|||
return PSCI_E_SUCCESS; |
|||
return PSCI_E_INVALID_ADDRESS; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Platform handler called when a CPU is about to enter standby. |
|||
******************************************************************************/ |
|||
static void qemu_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 qemu_pwr_domain_on(u_register_t mpidr) |
|||
{ |
|||
int rc = PSCI_E_SUCCESS; |
|||
unsigned pos = plat_core_pos_by_mpidr(mpidr); |
|||
uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE; |
|||
|
|||
hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO; |
|||
sev(); |
|||
|
|||
return rc; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Platform handler called when a power domain is about to be turned off. The |
|||
* target_state encodes the power state that each level should transition to. |
|||
******************************************************************************/ |
|||
void qemu_pwr_domain_off(const psci_power_state_t *target_state) |
|||
{ |
|||
assert(0); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Platform handler called when a power domain is about to be suspended. The |
|||
* target_state encodes the power state that each level should transition to. |
|||
******************************************************************************/ |
|||
void qemu_pwr_domain_suspend(const psci_power_state_t *target_state) |
|||
{ |
|||
assert(0); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* 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 qemu_pwr_domain_on_finish(const psci_power_state_t *target_state) |
|||
{ |
|||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == |
|||
PLAT_LOCAL_STATE_OFF); |
|||
|
|||
/* TODO: This setup is needed only after a cold boot */ |
|||
gicv2_pcpu_distif_init(); |
|||
|
|||
/* Enable the gic cpu interface */ |
|||
gicv2_cpuif_enable(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Platform handler called when a power domain has just been powered on after |
|||
* having been suspended earlier. The target_state encodes the low power state |
|||
* that each level has woken up from. |
|||
******************************************************************************/ |
|||
void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state) |
|||
{ |
|||
assert(0); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Platform handlers to shutdown/reboot the system |
|||
******************************************************************************/ |
|||
static void __dead2 qemu_system_off(void) |
|||
{ |
|||
ERROR("QEMU System Off: operation not handled.\n"); |
|||
panic(); |
|||
} |
|||
|
|||
static void __dead2 qemu_system_reset(void) |
|||
{ |
|||
ERROR("QEMU System Reset: operation not handled.\n"); |
|||
panic(); |
|||
} |
|||
|
|||
static const plat_psci_ops_t plat_qemu_psci_pm_ops = { |
|||
.cpu_standby = qemu_cpu_standby, |
|||
.pwr_domain_on = qemu_pwr_domain_on, |
|||
.pwr_domain_off = qemu_pwr_domain_off, |
|||
.pwr_domain_suspend = qemu_pwr_domain_suspend, |
|||
.pwr_domain_on_finish = qemu_pwr_domain_on_finish, |
|||
.pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish, |
|||
.system_off = qemu_system_off, |
|||
.system_reset = qemu_system_reset, |
|||
.validate_power_state = qemu_validate_power_state, |
|||
.validate_ns_entrypoint = qemu_validate_ns_entrypoint |
|||
}; |
|||
|
|||
int plat_setup_psci_ops(uintptr_t sec_entrypoint, |
|||
const plat_psci_ops_t **psci_ops) |
|||
{ |
|||
uintptr_t *mailbox = (void *) PLAT_QEMU_TRUSTED_MAILBOX_BASE; |
|||
|
|||
*mailbox = sec_entrypoint; |
|||
secure_entrypoint = (unsigned long) sec_entrypoint; |
|||
*psci_ops = &plat_qemu_psci_pm_ops; |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,50 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifndef __QEMU_PRIVATE_H |
|||
#define __QEMU_PRIVATE_H |
|||
|
|||
#include <sys/types.h> |
|||
|
|||
void qemu_configure_mmu_el1(unsigned long total_base, unsigned long total_size, |
|||
unsigned long ro_start, unsigned long ro_limit, |
|||
unsigned long coh_start, unsigned long coh_limit); |
|||
|
|||
void qemu_configure_mmu_el3(unsigned long total_base, unsigned long total_size, |
|||
unsigned long ro_start, unsigned long ro_limit, |
|||
unsigned long coh_start, unsigned long coh_limit); |
|||
|
|||
void plat_qemu_io_setup(void); |
|||
unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); |
|||
|
|||
int dt_add_psci_node(void *fdt); |
|||
int dt_add_psci_cpu_enable_methods(void *fdt); |
|||
|
|||
#endif /*__QEMU_PRIVATE_H*/ |
@ -0,0 +1,78 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
* list of conditions and the following disclaimer. |
|||
* |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
* this list of conditions and the following disclaimer in the documentation |
|||
* and/or other materials provided with the distribution. |
|||
* |
|||
* Neither the name of ARM nor the names of its contributors may be used |
|||
* to endorse or promote products derived from this software without specific |
|||
* prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include <arch.h> |
|||
#include <platform_def.h> |
|||
#include "qemu_private.h" |
|||
#include <sys/types.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, |
|||
/* Number of children for the second node */ |
|||
PLATFORM_CLUSTER1_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_qemu_calc_core_pos(mpidr); |
|||
} |
Loading…
Reference in new issue