GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.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_crash_console_flush
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
|
||||
|
||||
func plat_my_core_pos
|
||||
ldcopr r0, MPIDR
|
||||
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 r1, r0, #MPIDR_CPU_MASK
|
||||
and r0, r0, #MPIDR_CLUSTER_MASK
|
||||
add r0, r1, r0, LSR #6
|
||||
bx lr
|
||||
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
|
||||
ldcopr r0, MPIDR
|
||||
ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
|
||||
and r0, r1
|
||||
cmp r0, #QEMU_PRIMARY_CPU
|
||||
moveq r0, #1
|
||||
movne r0, #0
|
||||
bx lr
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* This function performs any platform specific actions
|
||||
* needed for a secondary cpu after a cold reset e.g
|
||||
* mark the cpu's presence, mechanism to place it in a
|
||||
* holding pen etc.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
/* Calculate address of our hold entry */
|
||||
bl plat_my_core_pos
|
||||
lsl r0, r0, #PLAT_QEMU_HOLD_ENTRY_SHIFT
|
||||
mov_imm r2, PLAT_QEMU_HOLD_BASE
|
||||
|
||||
/* Wait until we have a go */
|
||||
poll_mailbox:
|
||||
ldr r1, [r2, r0]
|
||||
cmp r1, #PLAT_QEMU_HOLD_STATE_WAIT
|
||||
beq 1f
|
||||
|
||||
/* Clear the mailbox again ready for next time. */
|
||||
mov r1, #PLAT_QEMU_HOLD_STATE_WAIT
|
||||
str r1, [r2, r0]
|
||||
|
||||
/* Jump to the provided entrypoint. */
|
||||
mov_imm r0, PLAT_QEMU_TRUSTED_MAILBOX_BASE
|
||||
ldr r1, [r0]
|
||||
bx r1
|
||||
1:
|
||||
wfe
|
||||
b poll_mailbox
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
func plat_get_my_entrypoint
|
||||
/* TODO support warm boot */
|
||||
mov r0, #0
|
||||
bx lr
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
func platform_mem_init
|
||||
bx lr
|
||||
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 r0, PLAT_QEMU_CRASH_UART_BASE
|
||||
mov_imm r1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ
|
||||
mov_imm r2, PLAT_QEMU_CONSOLE_BAUDRATE
|
||||
b console_pl011_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 r1, PLAT_QEMU_CRASH_UART_BASE
|
||||
b console_pl011_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void plat_crash_console_flush(int c)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* Out : void.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
mov_imm r0, PLAT_QEMU_CRASH_UART_BASE
|
||||
b console_pl011_core_flush
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.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_crash_console_flush
|
||||
.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 #(MPIDR_AFFINITY_BITS -\
|
||||
PLATFORM_CPU_PER_CLUSTER_SHIFT)
|
||||
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
|
||||
lsl x0, x0, #PLAT_QEMU_HOLD_ENTRY_SHIFT
|
||||
mov_imm x2, PLAT_QEMU_HOLD_BASE
|
||||
|
||||
/* Wait until we have a go */
|
||||
poll_mailbox:
|
||||
ldr x1, [x2, x0]
|
||||
cbz x1, 1f
|
||||
|
||||
/* Clear the mailbox again ready for next time. */
|
||||
mov x1, #PLAT_QEMU_HOLD_STATE_WAIT
|
||||
str x1, [x2, x0]
|
||||
|
||||
/* Jump to the provided entrypoint. */
|
||||
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_pl011_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_pl011_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void plat_crash_console_flush(int c)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* Out : void.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
mov_imm x0, PLAT_QEMU_CRASH_UART_BASE
|
||||
b console_pl011_core_flush
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
#include <arm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below required platform porting macro
|
||||
* prints out relevant 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,62 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
|
||||
#include "qemu_private.h"
|
||||
|
||||
/* Data structure which holds the extents of the trusted SRAM for BL1*/
|
||||
static meminfo_t bl1_tzram_layout;
|
||||
|
||||
|
||||
meminfo_t *bl1_plat_sec_mem_layout(void)
|
||||
{
|
||||
return &bl1_tzram_layout;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL1 specific platform actions.
|
||||
******************************************************************************/
|
||||
void bl1_early_platform_setup(void)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
qemu_console_init();
|
||||
|
||||
/* Allow BL1 to see the whole Trusted RAM */
|
||||
bl1_tzram_layout.total_base = BL_RAM_BASE;
|
||||
bl1_tzram_layout.total_size = BL_RAM_SIZE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Perform the very early platform specific architecture setup. This only
|
||||
* does basic initialization. Later architectural setup (bl1_arch_setup())
|
||||
* does not do anything platform specific.
|
||||
*****************************************************************************/
|
||||
#ifdef __aarch64__
|
||||
#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_el3(__VA_ARGS__)
|
||||
#else
|
||||
#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_svc_mon(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
void bl1_plat_arch_setup(void)
|
||||
{
|
||||
QEMU_CONFIGURE_BL1_MMU(bl1_tzram_layout.total_base,
|
||||
bl1_tzram_layout.total_size,
|
||||
BL_CODE_BASE, BL1_CODE_END,
|
||||
BL1_RO_DATA_BASE, BL1_RO_DATA_END,
|
||||
BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
|
||||
}
|
||||
|
||||
void bl1_platform_setup(void)
|
||||
{
|
||||
plat_qemu_io_setup();
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/desc_image_load.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Following descriptor provides BL image/ep information that gets used
|
||||
* by BL2 to load the images and also subset of this information is
|
||||
* passed to next BL image. The image loading sequence is managed by
|
||||
* populating the images in required loading order. The image execution
|
||||
* sequence is managed by populating the `next_handoff_image_id` with
|
||||
* the next executable image id.
|
||||
******************************************************************************/
|
||||
static bl_mem_params_node_t bl2_mem_params_descs[] = {
|
||||
#ifdef EL3_PAYLOAD_BASE
|
||||
/* Fill EL3 payload related information (BL31 is EL3 payload) */
|
||||
{ .image_id = BL31_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
|
||||
entry_point_info_t,
|
||||
SECURE | EXECUTABLE | EP_FIRST_EXE),
|
||||
.ep_info.pc = EL3_PAYLOAD_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
|
||||
IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
#else /* EL3_PAYLOAD_BASE */
|
||||
#ifdef __aarch64__
|
||||
/* Fill BL31 related information */
|
||||
{ .image_id = BL31_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
|
||||
entry_point_info_t,
|
||||
SECURE | EXECUTABLE | EP_FIRST_EXE),
|
||||
.ep_info.pc = BL31_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
# if DEBUG
|
||||
.ep_info.args.arg1 = QEMU_BL31_PLAT_PARAM_VAL,
|
||||
# endif
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
|
||||
IMAGE_ATTRIB_PLAT_SETUP),
|
||||
.image_info.image_base = BL31_BASE,
|
||||
.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
|
||||
|
||||
# ifdef QEMU_LOAD_BL32
|
||||
.next_handoff_image_id = BL32_IMAGE_ID,
|
||||
# else
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
# endif
|
||||
},
|
||||
#endif /* __aarch64__ */
|
||||
# ifdef QEMU_LOAD_BL32
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE)
|
||||
#define BL32_IMG_ATTRIBS 0
|
||||
#else
|
||||
#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE | EP_FIRST_EXE)
|
||||
#define BL32_IMG_ATTRIBS IMAGE_ATTRIB_PLAT_SETUP
|
||||
#endif
|
||||
|
||||
/* Fill BL32 related information */
|
||||
{ .image_id = BL32_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
|
||||
entry_point_info_t, BL32_EP_ATTRIBS),
|
||||
.ep_info.pc = BL32_BASE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
|
||||
image_info_t, BL32_IMG_ATTRIBS),
|
||||
|
||||
.image_info.image_base = BL32_BASE,
|
||||
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
|
||||
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
},
|
||||
|
||||
/*
|
||||
* Fill BL32 external 1 related information.
|
||||
* A typical use for extra1 image is with OP-TEE where it is the
|
||||
* pager image.
|
||||
*/
|
||||
{ .image_id = BL32_EXTRA1_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
|
||||
entry_point_info_t, SECURE | NON_EXECUTABLE),
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
|
||||
image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
|
||||
.image_info.image_base = BL32_BASE,
|
||||
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
|
||||
/*
|
||||
* Fill BL32 external 2 related information.
|
||||
* A typical use for extra2 image is with OP-TEE where it is the
|
||||
* paged image.
|
||||
*/
|
||||
{ .image_id = BL32_EXTRA2_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
|
||||
entry_point_info_t, SECURE | NON_EXECUTABLE),
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
|
||||
image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
|
||||
#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
|
||||
.image_info.image_base = QEMU_OPTEE_PAGEABLE_LOAD_BASE,
|
||||
.image_info.image_max_size = QEMU_OPTEE_PAGEABLE_LOAD_SIZE,
|
||||
#endif
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
# endif /* QEMU_LOAD_BL32 */
|
||||
|
||||
/* Fill BL33 related information */
|
||||
{ .image_id = BL33_IMAGE_ID,
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
|
||||
entry_point_info_t, NON_SECURE | EXECUTABLE),
|
||||
# ifdef PRELOADED_BL33_BASE
|
||||
.ep_info.pc = PRELOADED_BL33_BASE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
|
||||
IMAGE_ATTRIB_SKIP_LOADING),
|
||||
# else /* PRELOADED_BL33_BASE */
|
||||
.ep_info.pc = NS_IMAGE_OFFSET,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
|
||||
0),
|
||||
.image_info.image_base = NS_IMAGE_OFFSET,
|
||||
.image_info.image_max_size = NS_IMAGE_MAX_SIZE,
|
||||
# endif /* !PRELOADED_BL33_BASE */
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
}
|
||||
#endif /* !EL3_PAYLOAD_BASE */
|
||||
};
|
||||
|
||||
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/desc_image_load.h>
|
||||
#include <common/fdt_fixup.h>
|
||||
#include <lib/optee_utils.h>
|
||||
#include <lib/utils.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "qemu_private.h"
|
||||
|
||||
|
||||
/* Data structure which holds the extents of the trusted SRAM for BL2 */
|
||||
static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
|
||||
|
||||
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
meminfo_t *mem_layout = (void *)arg1;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
qemu_console_init();
|
||||
|
||||
/* 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)ARM_PRELOADED_DTB_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 */
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_el1(__VA_ARGS__)
|
||||
#else
|
||||
#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_svc_mon(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
void bl2_plat_arch_setup(void)
|
||||
{
|
||||
QEMU_CONFIGURE_BL2_MMU(bl2_tzram_layout.total_base,
|
||||
bl2_tzram_layout.total_size,
|
||||
BL_CODE_BASE, BL_CODE_END,
|
||||
BL_RO_DATA_BASE, BL_RO_DATA_END,
|
||||
BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Gets SPSR for BL32 entry
|
||||
******************************************************************************/
|
||||
static uint32_t qemu_get_spsr_for_bl32_entry(void)
|
||||
{
|
||||
#ifdef __aarch64__
|
||||
/*
|
||||
* The Secure Payload Dispatcher service is responsible for
|
||||
* setting the SPSR prior to entry into the BL3-2 image.
|
||||
*/
|
||||
return 0;
|
||||
#else
|
||||
return SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Gets SPSR for BL33 entry
|
||||
******************************************************************************/
|
||||
static uint32_t qemu_get_spsr_for_bl33_entry(void)
|
||||
{
|
||||
uint32_t spsr;
|
||||
#ifdef __aarch64__
|
||||
unsigned int mode;
|
||||
|
||||
/* Figure out what mode we enter the non-secure world in */
|
||||
mode = (el_implemented(2) != EL_IMPL_NONE) ? 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);
|
||||
#else
|
||||
spsr = SPSR_MODE32(MODE32_svc,
|
||||
plat_get_ns_image_entrypoint() & 0x1,
|
||||
SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
|
||||
#endif
|
||||
return spsr;
|
||||
}
|
||||
|
||||
static int qemu_bl2_handle_post_image_load(unsigned int image_id)
|
||||
{
|
||||
int err = 0;
|
||||
bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
|
||||
#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
|
||||
bl_mem_params_node_t *pager_mem_params = NULL;
|
||||
bl_mem_params_node_t *paged_mem_params = NULL;
|
||||
#endif
|
||||
#if defined(SPD_spmd)
|
||||
unsigned int mode_rw = MODE_RW_64;
|
||||
uint64_t pagable_part = 0;
|
||||
#endif
|
||||
|
||||
assert(bl_mem_params);
|
||||
|
||||
switch (image_id) {
|
||||
case BL32_IMAGE_ID:
|
||||
#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
|
||||
pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
|
||||
assert(pager_mem_params);
|
||||
|
||||
paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
|
||||
assert(paged_mem_params);
|
||||
|
||||
err = parse_optee_header(&bl_mem_params->ep_info,
|
||||
&pager_mem_params->image_info,
|
||||
&paged_mem_params->image_info);
|
||||
if (err != 0) {
|
||||
WARN("OPTEE header parse error.\n");
|
||||
}
|
||||
#if defined(SPD_spmd)
|
||||
mode_rw = bl_mem_params->ep_info.args.arg0;
|
||||
pagable_part = bl_mem_params->ep_info.args.arg1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SPD_spmd)
|
||||
bl_mem_params->ep_info.args.arg0 = ARM_PRELOADED_DTB_BASE;
|
||||
bl_mem_params->ep_info.args.arg1 = pagable_part;
|
||||
bl_mem_params->ep_info.args.arg2 = mode_rw;
|
||||
bl_mem_params->ep_info.args.arg3 = 0;
|
||||
#elif defined(SPD_opteed)
|
||||
/*
|
||||
* OP-TEE expect to receive DTB address in x2.
|
||||
* This will be copied into x2 by dispatcher.
|
||||
*/
|
||||
bl_mem_params->ep_info.args.arg3 = ARM_PRELOADED_DTB_BASE;
|
||||
#elif defined(AARCH32_SP_OPTEE)
|
||||
bl_mem_params->ep_info.args.arg0 =
|
||||
bl_mem_params->ep_info.args.arg1;
|
||||
bl_mem_params->ep_info.args.arg1 = 0;
|
||||
bl_mem_params->ep_info.args.arg2 = ARM_PRELOADED_DTB_BASE;
|
||||
bl_mem_params->ep_info.args.arg3 = 0;
|
||||
#endif
|
||||
bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl32_entry();
|
||||
break;
|
||||
|
||||
case BL33_IMAGE_ID:
|
||||
#ifdef AARCH32_SP_OPTEE
|
||||
/* AArch32 only core: OP-TEE expects NSec EP in register LR */
|
||||
pager_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
|
||||
assert(pager_mem_params);
|
||||
pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
|
||||
#endif
|
||||
|
||||
#if ARM_LINUX_KERNEL_AS_BL33
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
bl_mem_params->ep_info.args.arg0 =
|
||||
(u_register_t)ARM_PRELOADED_DTB_BASE;
|
||||
bl_mem_params->ep_info.args.arg1 = 0U;
|
||||
bl_mem_params->ep_info.args.arg2 = 0U;
|
||||
bl_mem_params->ep_info.args.arg3 = 0U;
|
||||
#else
|
||||
/* BL33 expects to receive the primary CPU MPID (through r0) */
|
||||
bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
|
||||
#endif
|
||||
|
||||
bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry();
|
||||
break;
|
||||
default:
|
||||
/* Do nothing in default case */
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function can be used by the platforms to update/use image
|
||||
* information for given `image_id`.
|
||||
******************************************************************************/
|
||||
int bl2_plat_handle_post_image_load(unsigned int image_id)
|
||||
{
|
||||
return qemu_bl2_handle_post_image_load(image_id);
|
||||
}
|
||||
|
||||
uintptr_t plat_get_ns_image_entrypoint(void)
|
||||
{
|
||||
return NS_IMAGE_OFFSET;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <drivers/arm/pl061_gpio.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "qemu_private.h"
|
||||
|
||||
/*
|
||||
* 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 & 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_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
qemu_console_init();
|
||||
|
||||
/*
|
||||
* Check params passed from BL2
|
||||
*/
|
||||
bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
|
||||
|
||||
assert(params_from_bl2);
|
||||
assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
|
||||
assert(params_from_bl2->h.version >= VERSION_2);
|
||||
|
||||
bl_params_node_t *bl_params = params_from_bl2->head;
|
||||
|
||||
/*
|
||||
* Copy BL33 and BL32 (if present), entry point information.
|
||||
* They are stored in Secure RAM, in BL2's address space.
|
||||
*/
|
||||
while (bl_params) {
|
||||
if (bl_params->image_id == BL32_IMAGE_ID)
|
||||
bl32_image_ep_info = *bl_params->ep_info;
|
||||
|
||||
if (bl_params->image_id == BL33_IMAGE_ID)
|
||||
bl33_image_ep_info = *bl_params->ep_info;
|
||||
|
||||
bl_params = bl_params->next_params_info;
|
||||
}
|
||||
|
||||
if (!bl33_image_ep_info.pc)
|
||||
panic();
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
qemu_configure_mmu_el3(BL31_BASE, (BL31_END - BL31_BASE),
|
||||
BL_CODE_BASE, BL_CODE_END,
|
||||
BL_RO_DATA_BASE, BL_RO_DATA_END,
|
||||
BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
|
||||
}
|
||||
|
||||
static void qemu_gpio_init(void)
|
||||
{
|
||||
#ifdef SECURE_GPIO_BASE
|
||||
pl061_gpio_init();
|
||||
pl061_gpio_register(SECURE_GPIO_BASE, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
plat_qemu_gic_init();
|
||||
qemu_gpio_init();
|
||||
}
|
||||
|
||||
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,169 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
#include "qemu_private.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_RW | 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)
|
||||
|
||||
#define MAP_FLASH1 MAP_REGION_FLAT(QEMU_FLASH1_BASE, QEMU_FLASH1_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,
|
||||
*/
|
||||
#ifdef IMAGE_BL1
|
||||
static const mmap_region_t plat_qemu_mmap[] = {
|
||||
MAP_FLASH0,
|
||||
MAP_FLASH1,
|
||||
MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
#ifdef MAP_DEVICE1
|
||||
MAP_DEVICE1,
|
||||
#endif
|
||||
#ifdef MAP_DEVICE2
|
||||
MAP_DEVICE2,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL2
|
||||
static const mmap_region_t plat_qemu_mmap[] = {
|
||||
MAP_FLASH0,
|
||||
MAP_FLASH1,
|
||||
MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
#ifdef MAP_DEVICE1
|
||||
MAP_DEVICE1,
|
||||
#endif
|
||||
#ifdef MAP_DEVICE2
|
||||
MAP_DEVICE2,
|
||||
#endif
|
||||
MAP_NS_DRAM0,
|
||||
#if SPM_MM
|
||||
QEMU_SP_IMAGE_MMAP,
|
||||
#else
|
||||
MAP_BL32_MEM,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL31
|
||||
static const mmap_region_t plat_qemu_mmap[] = {
|
||||
MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
#ifdef MAP_DEVICE1
|
||||
MAP_DEVICE1,
|
||||
#endif
|
||||
#ifdef MAP_DEVICE2
|
||||
MAP_DEVICE2,
|
||||
#endif
|
||||
#if SPM_MM
|
||||
MAP_NS_DRAM0,
|
||||
QEMU_SPM_BUF_EL3_MMAP,
|
||||
#else
|
||||
MAP_BL32_MEM,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL32
|
||||
static const mmap_region_t plat_qemu_mmap[] = {
|
||||
MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
#ifdef MAP_DEVICE1
|
||||
MAP_DEVICE1,
|
||||
#endif
|
||||
#ifdef MAP_DEVICE2
|
||||
MAP_DEVICE2,
|
||||
#endif
|
||||
{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(unsigned long total_base, \
|
||||
unsigned long total_size, \
|
||||
unsigned long code_start, \
|
||||
unsigned long code_limit, \
|
||||
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(code_start, code_start, \
|
||||
code_limit - code_start, \
|
||||
MT_CODE | MT_SECURE); \
|
||||
mmap_add_region(ro_start, ro_start, \
|
||||
ro_limit - ro_start, \
|
||||
MT_RO_DATA | 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(0); \
|
||||
}
|
||||
|
||||
/* Define EL1 and EL3 variants of the function initialising the MMU */
|
||||
#ifdef __aarch64__
|
||||
DEFINE_CONFIGURE_MMU_EL(el1)
|
||||
DEFINE_CONFIGURE_MMU_EL(el3)
|
||||
#else
|
||||
DEFINE_CONFIGURE_MMU_EL(svc_mon)
|
||||
#endif
|
||||
|
||||
#if MEASURED_BOOT || TRUSTED_BOARD_BOOT
|
||||
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
|
||||
{
|
||||
return get_mbedtls_heap_helper(heap_addr, heap_size);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/arm/pl011.h>
|
||||
|
||||
static console_t console;
|
||||
|
||||
void qemu_console_init(void)
|
||||
{
|
||||
(void)console_pl011_register(PLAT_QEMU_BOOT_UART_BASE,
|
||||
PLAT_QEMU_BOOT_UART_CLK_IN_HZ,
|
||||
PLAT_QEMU_CONSOLE_BAUDRATE, &console);
|
||||
|
||||
console_set_scope(&console, CONSOLE_FLAG_BOOT |
|
||||
CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static const interrupt_prop_t qemu_interrupt_props[] = {
|
||||
PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
|
||||
PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
|
||||
};
|
||||
|
||||
static const struct gicv2_driver_data plat_gicv2_driver_data = {
|
||||
.gicd_base = GICD_BASE,
|
||||
.gicc_base = GICC_BASE,
|
||||
.interrupt_props = qemu_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(qemu_interrupt_props),
|
||||
};
|
||||
|
||||
void plat_qemu_gic_init(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();
|
||||
}
|
||||
|
||||
void qemu_pwr_gic_on_finish(void)
|
||||
{
|
||||
/* TODO: This setup is needed only after a cold boot */
|
||||
gicv2_pcpu_distif_init();
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
void qemu_pwr_gic_off(void)
|
||||
{
|
||||
gicv2_cpuif_disable();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Linaro Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
#include <platform_def.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
static const interrupt_prop_t qemu_interrupt_props[] = {
|
||||
PLATFORM_G1S_PROPS(INTR_GROUP1S),
|
||||
PLATFORM_G0_PROPS(INTR_GROUP0)
|
||||
};
|
||||
|
||||
static uintptr_t qemu_rdistif_base_addrs[PLATFORM_CORE_COUNT];
|
||||
|
||||
static unsigned int qemu_mpidr_to_core_pos(unsigned long mpidr)
|
||||
{
|
||||
return (unsigned int)plat_core_pos_by_mpidr(mpidr);
|
||||
}
|
||||
|
||||
static const gicv3_driver_data_t qemu_gicv3_driver_data = {
|
||||
.gicd_base = GICD_BASE,
|
||||
.gicr_base = GICR_BASE,
|
||||
.interrupt_props = qemu_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(qemu_interrupt_props),
|
||||
.rdistif_num = PLATFORM_CORE_COUNT,
|
||||
.rdistif_base_addrs = qemu_rdistif_base_addrs,
|
||||
.mpidr_to_core_pos = qemu_mpidr_to_core_pos
|
||||
};
|
||||
|
||||
void plat_qemu_gic_init(void)
|
||||
{
|
||||
gicv3_driver_init(&qemu_gicv3_driver_data);
|
||||
gicv3_distif_init();
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void qemu_pwr_gic_on_finish(void)
|
||||
{
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void qemu_pwr_gic_off(void)
|
||||
{
|
||||
gicv3_cpuif_disable(plat_my_core_pos());
|
||||
gicv3_rdistif_off(plat_my_core_pos());
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/desc_image_load.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is a wrapper of a common function which flushes the data
|
||||
* structures so that they are visible in memory for the next BL image.
|
||||
******************************************************************************/
|
||||
void plat_flush_next_bl_params(void)
|
||||
{
|
||||
flush_bl_params_desc();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is a wrapper of a common function which returns the list of
|
||||
* loadable images.
|
||||
******************************************************************************/
|
||||
bl_load_info_t *plat_get_bl_image_load_info(void)
|
||||
{
|
||||
return get_bl_load_info_from_mem_params_desc();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is a wrapper of a common function which returns the data
|
||||
* structures of the next BL image.
|
||||
******************************************************************************/
|
||||
bl_params_t *plat_get_next_bl_params(void)
|
||||
{
|
||||
return get_next_bl_params_from_mem_params_desc();
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/io/io_driver.h>
|
||||
#include <drivers/io/io_encrypted.h>
|
||||
#include <drivers/io/io_fip.h>
|
||||
#include <drivers/io/io_memmap.h>
|
||||
#include <drivers/io/io_semihosting.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <lib/semihosting.h>
|
||||
#include <tools_share/firmware_image_package.h>
|
||||
|
||||
/* Semihosting filenames */
|
||||
#define BL2_IMAGE_NAME "bl2.bin"
|
||||
#define BL31_IMAGE_NAME "bl31.bin"
|
||||
#define BL32_IMAGE_NAME "bl32.bin"
|
||||
#define BL32_EXTRA1_IMAGE_NAME "bl32_extra1.bin"
|
||||
#define BL32_EXTRA2_IMAGE_NAME "bl32_extra2.bin"
|
||||
#define BL33_IMAGE_NAME "bl33.bin"
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt"
|
||||
#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
|
||||
#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt"
|
||||
#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt"
|
||||
#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt"
|
||||
#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt"
|
||||
#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt"
|
||||
#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.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;
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
static const io_dev_connector_t *enc_dev_con;
|
||||
static uintptr_t enc_dev_handle;
|
||||
#endif
|
||||
|
||||
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 bl32_extra1_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl32_extra2_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
|
||||
};
|
||||
|
||||
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 tb_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_BOOT_FW_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
|
||||
.uuid = UUID_SOC_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_SOC_FW_CONTENT_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FW_CONTENT_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
|
||||
},
|
||||
[BL32_EXTRA1_IMAGE_ID] = {
|
||||
.path = BL32_EXTRA1_IMAGE_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[BL32_EXTRA2_IMAGE_ID] = {
|
||||
.path = BL32_EXTRA2_IMAGE_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[BL33_IMAGE_ID] = {
|
||||
.path = BL33_IMAGE_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
[TRUSTED_BOOT_FW_CERT_ID] = {
|
||||
.path = TRUSTED_BOOT_FW_CERT_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[TRUSTED_KEY_CERT_ID] = {
|
||||
.path = TRUSTED_KEY_CERT_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[SOC_FW_KEY_CERT_ID] = {
|
||||
.path = SOC_FW_KEY_CERT_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[TRUSTED_OS_FW_KEY_CERT_ID] = {
|
||||
.path = TOS_FW_KEY_CERT_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[NON_TRUSTED_FW_KEY_CERT_ID] = {
|
||||
.path = NT_FW_KEY_CERT_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[SOC_FW_CONTENT_CERT_ID] = {
|
||||
.path = SOC_FW_CONTENT_CERT_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
|
||||
.path = TOS_FW_CONTENT_CERT_NAME,
|
||||
.mode = FOPEN_MODE_RB
|
||||
},
|
||||
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
|
||||
.path = NT_FW_CONTENT_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);
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
static int open_enc_fip(const uintptr_t spec);
|
||||
#endif
|
||||
|
||||
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
|
||||
},
|
||||
[ENC_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)NULL,
|
||||
open_fip
|
||||
},
|
||||
[BL2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl2_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#if ENCRYPT_BL31 && !defined(DECRYPTION_SUPPORT_none)
|
||||
[BL31_IMAGE_ID] = {
|
||||
&enc_dev_handle,
|
||||
(uintptr_t)&bl31_uuid_spec,
|
||||
open_enc_fip
|
||||
},
|
||||
#else
|
||||
[BL31_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl31_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#endif
|
||||
#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none)
|
||||
[BL32_IMAGE_ID] = {
|
||||
&enc_dev_handle,
|
||||
(uintptr_t)&bl32_uuid_spec,
|
||||
open_enc_fip
|
||||
},
|
||||
[BL32_EXTRA1_IMAGE_ID] = {
|
||||
&enc_dev_handle,
|
||||
(uintptr_t)&bl32_extra1_uuid_spec,
|
||||
open_enc_fip
|
||||
},
|
||||
[BL32_EXTRA2_IMAGE_ID] = {
|
||||
&enc_dev_handle,
|
||||
(uintptr_t)&bl32_extra2_uuid_spec,
|
||||
open_enc_fip
|
||||
},
|
||||
#else
|
||||
[BL32_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_EXTRA1_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_extra1_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_EXTRA2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_extra2_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#endif
|
||||
[BL33_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl33_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
[TRUSTED_BOOT_FW_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tb_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&trusted_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&soc_fw_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_OS_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tos_fw_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[NON_TRUSTED_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&nt_fw_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&soc_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tos_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&nt_fw_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 && spec != (uintptr_t)NULL) {
|
||||
result = io_open(fip_dev_handle, spec, &local_image_handle);
|
||||
if (result == 0) {
|
||||
VERBOSE("Using FIP\n");
|
||||
io_close(local_image_handle);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
static int open_enc_fip(const uintptr_t spec)
|
||||
{
|
||||
int result;
|
||||
uintptr_t local_image_handle;
|
||||
|
||||
/* See if an encrypted FIP is available */
|
||||
result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
|
||||
if (result == 0) {
|
||||
result = io_open(enc_dev_handle, spec, &local_image_handle);
|
||||
if (result == 0) {
|
||||
VERBOSE("Using encrypted FIP\n");
|
||||
io_close(local_image_handle);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
#ifndef DECRYPTION_SUPPORT_none
|
||||
io_result = register_io_dev_enc(&enc_dev_con);
|
||||
assert(io_result == 0);
|
||||
|
||||
io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
|
||||
&enc_dev_handle);
|
||||
assert(io_result == 0);
|
||||
#endif
|
||||
|
||||
/* 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,257 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/semihosting.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <drivers/gpio.h>
|
||||
|
||||
#include "qemu_private.h"
|
||||
|
||||
#define ADP_STOPPED_APPLICATION_EXIT 0x20026
|
||||
|
||||
/*
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
static void qemu_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
qemu_pwr_gic_off();
|
||||
}
|
||||
|
||||
void __dead2 plat_secondary_cold_boot_setup(void);
|
||||
|
||||
static void __dead2
|
||||
qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
|
||||
{
|
||||
disable_mmu_el3();
|
||||
plat_secondary_cold_boot_setup();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
|
||||
qemu_pwr_gic_on_finish();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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)
|
||||
{
|
||||
#ifdef SECURE_GPIO_BASE
|
||||
ERROR("QEMU System Power off: with GPIO.\n");
|
||||
gpio_set_direction(SECURE_GPIO_POWEROFF, GPIO_DIR_OUT);
|
||||
gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_LOW);
|
||||
gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_HIGH);
|
||||
#else
|
||||
semihosting_exit(ADP_STOPPED_APPLICATION_EXIT, 0);
|
||||
ERROR("QEMU System Off: semihosting call unexpectedly returned.\n");
|
||||
#endif
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 qemu_system_reset(void)
|
||||
{
|
||||
ERROR("QEMU System Reset: with GPIO.\n");
|
||||
#ifdef SECURE_GPIO_BASE
|
||||
gpio_set_direction(SECURE_GPIO_RESET, GPIO_DIR_OUT);
|
||||
gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_LOW);
|
||||
gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_HIGH);
|
||||
#else
|
||||
ERROR("QEMU System Reset: operation not handled.\n");
|
||||
#endif
|
||||
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_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi,
|
||||
.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,51 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef QEMU_PRIVATE_H
|
||||
#define QEMU_PRIVATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void qemu_configure_mmu_svc_mon(unsigned long total_base,
|
||||
unsigned long total_size,
|
||||
unsigned long code_start, unsigned long code_limit,
|
||||
unsigned long ro_start, unsigned long ro_limit,
|
||||
unsigned long coh_start, unsigned long coh_limit);
|
||||
|
||||
void qemu_configure_mmu_el1(unsigned long total_base, unsigned long total_size,
|
||||
unsigned long code_start, unsigned long code_limit,
|
||||
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 code_start, unsigned long code_limit,
|
||||
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);
|
||||
|
||||
void qemu_console_init(void);
|
||||
|
||||
void plat_qemu_gic_init(void);
|
||||
void qemu_pwr_gic_on_finish(void);
|
||||
void qemu_pwr_gic_off(void);
|
||||
|
||||
int qemu_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
|
||||
size_t log_size);
|
||||
|
||||
int qemu_set_nt_fw_info(
|
||||
/*
|
||||
* Currently OP-TEE does not support reading DTBs from Secure memory
|
||||
* and this option should be removed when feature is supported.
|
||||
*/
|
||||
#ifdef SPD_opteed
|
||||
uintptr_t log_addr,
|
||||
#endif
|
||||
size_t log_size,
|
||||
uintptr_t *ns_log_addr);
|
||||
|
||||
#endif /* QEMU_PRIVATE_H */
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
.global qemu_rotpk_hash
|
||||
.global qemu_rotpk_hash_end
|
||||
qemu_rotpk_hash:
|
||||
/* DER header */
|
||||
.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
|
||||
.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
/* SHA256 */
|
||||
.incbin ROTPK_HASH
|
||||
qemu_rotpk_hash_end:
|
||||
@@ -0,0 +1,147 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <bl31/ehf.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_fixup.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <lib/xlat_tables/xlat_tables_compat.h>
|
||||
#include <services/spm_mm_partition.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* Region equivalent to MAP_DEVICE1 suitable for mapping at EL0 */
|
||||
#define MAP_DEVICE1_EL0 MAP_REGION_FLAT(DEVICE1_BASE, \
|
||||
DEVICE1_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
|
||||
|
||||
mmap_region_t plat_qemu_secure_partition_mmap[] = {
|
||||
QEMU_SP_IMAGE_NS_BUF_MMAP, /* must be placed at first entry */
|
||||
MAP_DEVICE1_EL0, /* for the UART */
|
||||
QEMU_SP_IMAGE_MMAP,
|
||||
QEMU_SPM_BUF_EL0_MMAP,
|
||||
QEMU_SP_IMAGE_RW_MMAP,
|
||||
MAP_SECURE_VARSTORE,
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Boot information passed to a secure partition during initialisation. */
|
||||
static spm_mm_mp_info_t sp_mp_info[PLATFORM_CORE_COUNT];
|
||||
|
||||
spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = {
|
||||
.h.type = PARAM_SP_IMAGE_BOOT_INFO,
|
||||
.h.version = VERSION_1,
|
||||
.h.size = sizeof(spm_mm_boot_info_t),
|
||||
.h.attr = 0,
|
||||
.sp_mem_base = PLAT_QEMU_SP_IMAGE_BASE,
|
||||
.sp_mem_limit = BL32_LIMIT,
|
||||
.sp_image_base = PLAT_QEMU_SP_IMAGE_BASE,
|
||||
.sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
|
||||
.sp_heap_base = PLAT_QEMU_SP_IMAGE_HEAP_BASE,
|
||||
.sp_ns_comm_buf_base = PLAT_QEMU_SP_IMAGE_NS_BUF_BASE,
|
||||
.sp_shared_buf_base = PLAT_SPM_BUF_BASE,
|
||||
.sp_image_size = PLAT_QEMU_SP_IMAGE_SIZE,
|
||||
.sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
|
||||
.sp_heap_size = PLAT_QEMU_SP_IMAGE_HEAP_SIZE,
|
||||
.sp_ns_comm_buf_size = PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE,
|
||||
.sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
|
||||
.num_sp_mem_regions = PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS,
|
||||
.num_cpus = PLATFORM_CORE_COUNT,
|
||||
.mp_info = sp_mp_info
|
||||
};
|
||||
|
||||
/* Enumeration of priority levels on QEMU platforms. */
|
||||
ehf_pri_desc_t qemu_exceptions[] = {
|
||||
EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI)
|
||||
};
|
||||
|
||||
static void qemu_initialize_mp_info(spm_mm_mp_info_t *mp_info)
|
||||
{
|
||||
unsigned int i, j;
|
||||
spm_mm_mp_info_t *tmp = mp_info;
|
||||
|
||||
for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) {
|
||||
for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) {
|
||||
tmp->mpidr = (0x80000000 | (i << MPIDR_AFF1_SHIFT)) + j;
|
||||
/*
|
||||
* Linear indices and flags will be filled
|
||||
* in the spm_mm service.
|
||||
*/
|
||||
tmp->linear_id = 0;
|
||||
tmp->flags = 0;
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int dt_add_ns_buf_node(uintptr_t *base)
|
||||
{
|
||||
uintptr_t addr;
|
||||
size_t size;
|
||||
uintptr_t ns_buf_addr;
|
||||
int node;
|
||||
int err;
|
||||
void *fdt = (void *)ARM_PRELOADED_DTB_BASE;
|
||||
|
||||
err = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
|
||||
if (err < 0) {
|
||||
ERROR("Invalid Device Tree at %p: error %d\n", fdt, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* reserved-memory for standaloneMM non-secure buffer
|
||||
* is allocated at the top of the first system memory region.
|
||||
*/
|
||||
node = fdt_path_offset(fdt, "/memory");
|
||||
|
||||
err = fdt_get_reg_props_by_index(fdt, node, 0, &addr, &size);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to get the memory node information\n");
|
||||
return err;
|
||||
}
|
||||
INFO("System RAM @ 0x%lx - 0x%lx\n", addr, addr + size - 1);
|
||||
|
||||
ns_buf_addr = addr + (size - PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
|
||||
INFO("reserved-memory for spm-mm @ 0x%lx - 0x%llx\n", ns_buf_addr,
|
||||
ns_buf_addr + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE - 1);
|
||||
|
||||
err = fdt_add_reserved_memory(fdt, "ns-buf-spm-mm", ns_buf_addr,
|
||||
PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to add the reserved-memory node\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
*base = ns_buf_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Plug in QEMU exceptions to Exception Handling Framework. */
|
||||
EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions),
|
||||
QEMU_PRI_BITS);
|
||||
|
||||
const mmap_region_t *plat_get_secure_partition_mmap(void *cookie)
|
||||
{
|
||||
uintptr_t ns_buf_base;
|
||||
|
||||
dt_add_ns_buf_node(&ns_buf_base);
|
||||
|
||||
plat_qemu_secure_partition_mmap[0].base_pa = ns_buf_base;
|
||||
plat_qemu_secure_partition_mmap[0].base_va = ns_buf_base;
|
||||
plat_qemu_secure_partition_boot_info.sp_ns_comm_buf_base = ns_buf_base;
|
||||
|
||||
return plat_qemu_secure_partition_mmap;
|
||||
}
|
||||
|
||||
const spm_mm_boot_info_t *
|
||||
plat_get_secure_partition_boot_info(void *cookie)
|
||||
{
|
||||
qemu_initialize_mp_info(sp_mp_info);
|
||||
|
||||
return &plat_qemu_secure_partition_boot_info;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <services/spm_core_manifest.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
|
||||
const void *pm_addr)
|
||||
{
|
||||
entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE);
|
||||
|
||||
assert(ep_info != NULL);
|
||||
assert(manifest != NULL);
|
||||
|
||||
manifest->major_version = 1;
|
||||
manifest->minor_version = 0;
|
||||
manifest->exec_state = ep_info->args.arg2;
|
||||
manifest->load_address = BL32_BASE;
|
||||
manifest->entrypoint = BL32_BASE;
|
||||
manifest->binary_size = BL32_LIMIT - BL32_BASE;
|
||||
manifest->spmc_id = 0x8000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <arch_features.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
|
||||
|
||||
u_register_t plat_get_stack_protector_canary(void)
|
||||
{
|
||||
#if ENABLE_FEAT_RNG
|
||||
/* Use the RNDR instruction if the CPU supports it */
|
||||
if (is_armv8_5_rng_present()) {
|
||||
return read_rndr();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ideally, a random number should be returned above. If a random
|
||||
* number generator is not supported, return instead a
|
||||
* combination of a timer's value and a compile-time constant.
|
||||
* This is better than nothing but not necessarily really secure.
|
||||
*/
|
||||
return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
extern char qemu_rotpk_hash[], qemu_rotpk_hash_end[];
|
||||
|
||||
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
*key_ptr = qemu_rotpk_hash;
|
||||
*key_len = qemu_rotpk_hash_end - qemu_rotpk_hash;
|
||||
*flags = ROTPK_IS_HASH;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
|
||||
{
|
||||
*nv_ctr = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
BL32_SOURCES += plat/qemu/sp_min/sp_min_setup.c \
|
||||
plat/qemu/aarch32/plat_helpers.S \
|
||||
plat/qemu/qemu_pm.c \
|
||||
plat/qemu/topology.c
|
||||
|
||||
BL32_SOURCES += lib/cpus/aarch32/aem_generic.S \
|
||||
lib/cpus/aarch32/cortex_a15.S
|
||||
|
||||
BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
plat/common/plat_gicv2.c
|
||||
|
||||
|
||||
BL32_SOURCES += drivers/arm/gic/v2/gicv2_helpers.c \
|
||||
drivers/arm/gic/v2/gicv2_main.c \
|
||||
drivers/arm/gic/common/gic_common.c
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_tables.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "../qemu_private.h"
|
||||
|
||||
#if RESET_TO_SP_MIN
|
||||
#error qemu does not support RESET_TO_SP_MIN
|
||||
#endif
|
||||
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
|
||||
/******************************************************************************
|
||||
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
|
||||
* interrupts.
|
||||
*****************************************************************************/
|
||||
#define PLATFORM_G1S_PROPS(grp) \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLATFORM_G0_PROPS(grp)
|
||||
|
||||
static const interrupt_prop_t stih410_interrupt_props[] = {
|
||||
PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
|
||||
PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
|
||||
};
|
||||
|
||||
static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
|
||||
|
||||
static const struct gicv2_driver_data plat_gicv2_driver_data = {
|
||||
.gicd_base = GICD_BASE,
|
||||
.gicc_base = GICC_BASE,
|
||||
.interrupt_props = stih410_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(stih410_interrupt_props),
|
||||
.target_masks = target_mask_array,
|
||||
.target_masks_num = ARRAY_SIZE(target_mask_array),
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Return a pointer to the 'entry_point_info' structure of the next image for
|
||||
* the security state specified. BL33 corresponds to the non-secure image type
|
||||
* while BL32 corresponds to the secure image type. A NULL pointer is returned
|
||||
* if the image does not exist.
|
||||
******************************************************************************/
|
||||
entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
|
||||
{
|
||||
entry_point_info_t *next_image_info = &bl33_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;
|
||||
}
|
||||
|
||||
void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
qemu_console_init();
|
||||
|
||||
ERROR("qemu sp_min, console init\n");
|
||||
/*
|
||||
* Check params passed from BL2
|
||||
*/
|
||||
assert(params_from_bl2);
|
||||
assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
|
||||
assert(params_from_bl2->h.version >= VERSION_2);
|
||||
|
||||
bl_params_node_t *bl_params = params_from_bl2->head;
|
||||
|
||||
/*
|
||||
* Copy BL33 entry point information from BL2's address space.
|
||||
*/
|
||||
while (bl_params) {
|
||||
if (bl_params->image_id == BL33_IMAGE_ID)
|
||||
bl33_image_ep_info = *bl_params->ep_info;
|
||||
|
||||
bl_params = bl_params->next_params_info;
|
||||
}
|
||||
|
||||
if (!bl33_image_ep_info.pc)
|
||||
panic();
|
||||
}
|
||||
|
||||
void sp_min_plat_arch_setup(void)
|
||||
{
|
||||
qemu_configure_mmu_svc_mon(BL32_RO_BASE, BL32_END - BL32_RO_BASE,
|
||||
BL_CODE_BASE, BL_CODE_END,
|
||||
BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
|
||||
|
||||
}
|
||||
|
||||
void sp_min_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;
|
||||
}
|
||||
|
||||
void sp_min_plat_fiq_handler(uint32_t id)
|
||||
{
|
||||
VERBOSE("[sp_min] interrupt #%d\n", id);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch.h>
|
||||
|
||||
#include "qemu_private.h"
|
||||
|
||||
/* The power domain tree descriptor */
|
||||
static unsigned char power_domain_tree_desc[] = {
|
||||
/* Number of root nodes */
|
||||
PLATFORM_CLUSTER_COUNT,
|
||||
/* Number of children for the first node */
|
||||
PLATFORM_CLUSTER0_CORE_COUNT,
|
||||
/* 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);
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <plat/common/common_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
|
||||
|
||||
#if ARM_ARCH_MAJOR == 7
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
|
||||
#else
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
/*
|
||||
* Define the number of cores per cluster used in calculating core position.
|
||||
* The cluster number is shifted by this value and added to the core ID,
|
||||
* so its value represents log2(cores/cluster).
|
||||
* Default is 2**(2) = 4 cores per cluster.
|
||||
*/
|
||||
#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(2)
|
||||
|
||||
#define PLATFORM_CLUSTER_COUNT U(2)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#endif
|
||||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \
|
||||
PLATFORM_CLUSTER1_CORE_COUNT)
|
||||
|
||||
#define QEMU_PRIMARY_CPU U(0)
|
||||
|
||||
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(2)
|
||||
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define PLAT_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define PLAT_LOCAL_STATE_RET U(1)
|
||||
/*
|
||||
* Local power state for OFF/power-down. Valid for CPU and cluster power
|
||||
* domains.
|
||||
*/
|
||||
#define PLAT_LOCAL_STATE_OFF 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 ULL(0x40000000)
|
||||
#define NS_DRAM0_SIZE ULL(0xc0000000)
|
||||
|
||||
#define SEC_SRAM_BASE 0x0e000000
|
||||
#define SEC_SRAM_SIZE 0x00100000
|
||||
|
||||
#define SEC_DRAM_BASE 0x0e100000
|
||||
#define SEC_DRAM_SIZE 0x00f00000
|
||||
|
||||
#define SECURE_GPIO_BASE 0x090b0000
|
||||
#define SECURE_GPIO_SIZE 0x00001000
|
||||
#define SECURE_GPIO_POWEROFF 0
|
||||
#define SECURE_GPIO_RESET 1
|
||||
|
||||
/* Load pageable part of OP-TEE 2MB above secure DRAM base */
|
||||
#define QEMU_OPTEE_PAGEABLE_LOAD_BASE (SEC_DRAM_BASE + 0x00200000)
|
||||
#define QEMU_OPTEE_PAGEABLE_LOAD_SIZE 0x00400000
|
||||
|
||||
/*
|
||||
* 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_SHIFT 3
|
||||
#define PLAT_QEMU_HOLD_ENTRY_SIZE (1 << PLAT_QEMU_HOLD_ENTRY_SHIFT)
|
||||
#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 - 0x25000)
|
||||
#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 - 0x60000)
|
||||
#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 NS_IMAGE_OFFSET (NS_DRAM0_BASE + 0x20000000)
|
||||
#define NS_IMAGE_MAX_SIZE (NS_DRAM0_SIZE - 0x20000000)
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define MAX_MMAP_REGIONS 11
|
||||
#define MAX_XLAT_TABLES 6
|
||||
#define MAX_IO_DEVICES 4
|
||||
#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 0x00000000
|
||||
#define QEMU_FLASH0_SIZE 0x04000000
|
||||
#define QEMU_FLASH1_BASE 0x04000000
|
||||
#define QEMU_FLASH1_SIZE 0x04000000
|
||||
|
||||
#define PLAT_QEMU_FIP_BASE 0x00040000
|
||||
#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000
|
||||
|
||||
#define DEVICE0_BASE 0x08000000
|
||||
#define DEVICE0_SIZE 0x01000000
|
||||
#define DEVICE1_BASE 0x09000000
|
||||
#define DEVICE1_SIZE 0x00c00000
|
||||
|
||||
/*
|
||||
* GIC related constants
|
||||
*/
|
||||
|
||||
#define GICD_BASE 0x8000000
|
||||
#define GICC_BASE 0x8010000
|
||||
#define GICR_BASE 0x80A0000
|
||||
|
||||
|
||||
#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
|
||||
|
||||
/******************************************************************************
|
||||
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
|
||||
* interrupts.
|
||||
*****************************************************************************/
|
||||
#define PLATFORM_G1S_PROPS(grp) \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define PLATFORM_G0_PROPS(grp)
|
||||
|
||||
/*
|
||||
* DT related constants
|
||||
*/
|
||||
#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE
|
||||
#define PLAT_QEMU_DT_MAX_SIZE 0x100000
|
||||
|
||||
/*
|
||||
* System counter
|
||||
*/
|
||||
#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16)
|
||||
|
||||
/*
|
||||
* Maximum size of Event Log buffer used in Measured Boot Event Log driver
|
||||
*/
|
||||
#define PLAT_EVENT_LOG_MAX_SIZE UL(0x400)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,266 @@
|
||||
#
|
||||
# Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Use the GICv2 driver on QEMU by default
|
||||
QEMU_USE_GIC_DRIVER := QEMU_GICV2
|
||||
|
||||
ifeq (${ARM_ARCH_MAJOR},7)
|
||||
# ARMv7 Qemu support in trusted firmware expects the Cortex-A15 model.
|
||||
# Qemu Cortex-A15 model does not implement the virtualization extension.
|
||||
# For this reason, we cannot set ARM_CORTEX_A15=yes and must define all
|
||||
# the ARMv7 build directives.
|
||||
MARCH32_DIRECTIVE := -mcpu=cortex-a15
|
||||
$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING))
|
||||
$(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER))
|
||||
$(eval $(call add_define,ARMV7_SUPPORTS_VFP))
|
||||
# Qemu expects a BL32 boot stage.
|
||||
NEED_BL32 := yes
|
||||
endif # ARMv7
|
||||
|
||||
ifeq (${SPD},opteed)
|
||||
add-lib-optee := yes
|
||||
endif
|
||||
ifeq ($(AARCH32_SP),optee)
|
||||
add-lib-optee := yes
|
||||
endif
|
||||
ifeq ($(SPMC_OPTEE),1)
|
||||
$(eval $(call add_define,SPMC_OPTEE))
|
||||
add-lib-optee := yes
|
||||
endif
|
||||
|
||||
include lib/libfdt/libfdt.mk
|
||||
|
||||
ifeq ($(NEED_BL32),yes)
|
||||
$(eval $(call add_define,QEMU_LOAD_BL32))
|
||||
endif
|
||||
|
||||
PLAT_QEMU_PATH := plat/qemu/qemu
|
||||
PLAT_QEMU_COMMON_PATH := plat/qemu/common
|
||||
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
|
||||
-I${PLAT_QEMU_COMMON_PATH}/include \
|
||||
-I${PLAT_QEMU_PATH}/include \
|
||||
-Iinclude/common/tbbr
|
||||
|
||||
ifeq (${ARM_ARCH_MAJOR},8)
|
||||
PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH}
|
||||
endif
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := ${PLAT_QEMU_COMMON_PATH}/qemu_common.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_console.c \
|
||||
drivers/arm/pl011/${ARCH}/pl011_console.S
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
|
||||
|
||||
ifneq (${TRUSTED_BOARD_BOOT},0)
|
||||
|
||||
AUTH_SOURCES := drivers/auth/auth_mod.c \
|
||||
drivers/auth/img_parser_mod.c \
|
||||
drivers/auth/tbbr/tbbr_cot_common.c
|
||||
|
||||
BL1_SOURCES += ${AUTH_SOURCES} \
|
||||
bl1/tbbr/tbbr_img_desc.c \
|
||||
plat/common/tbbr/plat_tbbr.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \
|
||||
$(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \
|
||||
drivers/auth/tbbr/tbbr_cot_bl1.c
|
||||
|
||||
BL2_SOURCES += ${AUTH_SOURCES} \
|
||||
plat/common/tbbr/plat_tbbr.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \
|
||||
$(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \
|
||||
drivers/auth/tbbr/tbbr_cot_bl2.c
|
||||
|
||||
include drivers/auth/mbedtls/mbedtls_x509.mk
|
||||
|
||||
ROT_KEY = $(BUILD_PLAT)/rot_key.pem
|
||||
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
|
||||
|
||||
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
|
||||
|
||||
$(BUILD_PLAT)/bl1/qemu_rotpk.o: $(ROTPK_HASH)
|
||||
$(BUILD_PLAT)/bl2/qemu_rotpk.o: $(ROTPK_HASH)
|
||||
|
||||
certificates: $(ROT_KEY)
|
||||
|
||||
$(ROT_KEY): | $(BUILD_PLAT)
|
||||
@echo " OPENSSL $@"
|
||||
$(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
|
||||
|
||||
$(ROTPK_HASH): $(ROT_KEY)
|
||||
@echo " OPENSSL $@"
|
||||
$(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
|
||||
${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
|
||||
endif
|
||||
|
||||
# Include Measured Boot makefile before any Crypto library makefile.
|
||||
# Crypto library makefile may need default definitions of Measured Boot build
|
||||
# flags present in Measured Boot makefile.
|
||||
ifeq (${MEASURED_BOOT},1)
|
||||
MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
|
||||
$(info Including ${MEASURED_BOOT_MK})
|
||||
include ${MEASURED_BOOT_MK}
|
||||
|
||||
ifneq (${MBOOT_EL_HASH_ALG}, sha256)
|
||||
$(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
|
||||
endif
|
||||
|
||||
BL2_SOURCES += plat/qemu/qemu/qemu_measured_boot.c \
|
||||
plat/qemu/qemu/qemu_common_measured_boot.c \
|
||||
plat/qemu/qemu/qemu_helpers.c \
|
||||
${EVENT_LOG_SOURCES}
|
||||
|
||||
BL1_SOURCES += plat/qemu/qemu/qemu_bl1_measured_boot.c
|
||||
|
||||
endif
|
||||
|
||||
ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),)
|
||||
CRYPTO_SOURCES := drivers/auth/crypto_mod.c
|
||||
|
||||
BL1_SOURCES += ${CRYPTO_SOURCES}
|
||||
BL2_SOURCES += ${CRYPTO_SOURCES}
|
||||
|
||||
# We expect to locate the *.mk files under the directories specified below
|
||||
#
|
||||
include drivers/auth/mbedtls/mbedtls_crypto.mk
|
||||
endif
|
||||
|
||||
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/${ARCH}/semihosting_call.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c
|
||||
|
||||
ifeq (${ARM_ARCH_MAJOR},8)
|
||||
BL1_SOURCES += lib/cpus/aarch64/aem_generic.S \
|
||||
lib/cpus/aarch64/cortex_a53.S \
|
||||
lib/cpus/aarch64/cortex_a57.S \
|
||||
lib/cpus/aarch64/cortex_a72.S \
|
||||
lib/cpus/aarch64/qemu_max.S \
|
||||
|
||||
else
|
||||
BL1_SOURCES += lib/cpus/${ARCH}/cortex_a15.S
|
||||
endif
|
||||
|
||||
BL2_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/${ARCH}/semihosting_call.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_bl2_setup.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_image_load.c \
|
||||
common/fdt_fixup.c \
|
||||
common/fdt_wrappers.c \
|
||||
common/desc_image_load.c
|
||||
|
||||
ifeq ($(add-lib-optee),yes)
|
||||
BL2_SOURCES += lib/optee/optee_utils.c
|
||||
endif
|
||||
|
||||
ifneq (${DECRYPTION_SUPPORT},none)
|
||||
BL1_SOURCES += drivers/io/io_encrypted.c
|
||||
BL2_SOURCES += drivers/io/io_encrypted.c
|
||||
endif
|
||||
|
||||
# Include GICv2 driver files
|
||||
include drivers/arm/gic/v2/gicv2.mk
|
||||
QEMU_GICV2_SOURCES := ${GICV2_SOURCES} \
|
||||
plat/common/plat_gicv2.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_gicv2.c
|
||||
|
||||
# Include GICv3 driver files
|
||||
include drivers/arm/gic/v3/gicv3.mk
|
||||
|
||||
QEMU_GICV3_SOURCES := ${GICV3_SOURCES} \
|
||||
plat/common/plat_gicv3.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c
|
||||
|
||||
ifeq (${QEMU_USE_GIC_DRIVER}, QEMU_GICV2)
|
||||
QEMU_GIC_SOURCES := ${QEMU_GICV2_SOURCES}
|
||||
else ifeq (${QEMU_USE_GIC_DRIVER}, QEMU_GICV3)
|
||||
QEMU_GIC_SOURCES := ${QEMU_GICV3_SOURCES}
|
||||
else
|
||||
$(error "Incorrect GIC driver chosen for QEMU platform")
|
||||
endif
|
||||
|
||||
ifeq (${ARM_ARCH_MAJOR},8)
|
||||
BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
|
||||
lib/cpus/aarch64/cortex_a53.S \
|
||||
lib/cpus/aarch64/cortex_a57.S \
|
||||
lib/cpus/aarch64/cortex_a72.S \
|
||||
lib/cpus/aarch64/qemu_max.S \
|
||||
lib/semihosting/semihosting.c \
|
||||
lib/semihosting/${ARCH}/semihosting_call.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
drivers/arm/pl061/pl061_gpio.c \
|
||||
drivers/gpio/gpio.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/topology.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \
|
||||
${QEMU_GIC_SOURCES}
|
||||
|
||||
ifeq (${SPD},spmd)
|
||||
BL31_SOURCES += plat/qemu/common/qemu_spmd_manifest.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
|
||||
# in the FIP if the platform requires.
|
||||
ifneq ($(BL32_EXTRA1),)
|
||||
ifneq (${DECRYPTION_SUPPORT},none)
|
||||
$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
|
||||
else
|
||||
$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
|
||||
endif
|
||||
endif
|
||||
ifneq ($(BL32_EXTRA2),)
|
||||
ifneq (${DECRYPTION_SUPPORT},none)
|
||||
$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
|
||||
else
|
||||
$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
|
||||
endif
|
||||
endif
|
||||
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
ENABLE_STACK_PROTECTOR := 0
|
||||
ifneq ($(ENABLE_STACK_PROTECTOR), 0)
|
||||
PLAT_BL_COMMON_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_stack_protector.c
|
||||
endif
|
||||
|
||||
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))
|
||||
|
||||
# Don't have the Linux kernel as a BL33 image by default
|
||||
ARM_LINUX_KERNEL_AS_BL33 := 0
|
||||
$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
|
||||
$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
|
||||
|
||||
ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE
|
||||
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
|
||||
|
||||
# Later QEMU versions support SME and SVE.
|
||||
ifneq (${ARCH},aarch32)
|
||||
ENABLE_SVE_FOR_NS := 1
|
||||
ENABLE_SME_FOR_NS := 1
|
||||
endif
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2022, Linaro.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <common/desc_image_load.h>
|
||||
|
||||
/*
|
||||
* Add dummy functions for measured boot for BL1.
|
||||
* In most of the SoC's, ROM/BL1 code is pre-built. So we are assumimg that
|
||||
* it doesn't have the capability to do measurements and extend eventlog.
|
||||
* hence these are dummy functions.
|
||||
*/
|
||||
void bl1_plat_mboot_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void bl1_plat_mboot_finish(void)
|
||||
{
|
||||
}
|
||||
|
||||
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Linaro.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/desc_image_load.h>
|
||||
#include <drivers/measured_boot/event_log/event_log.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
extern event_log_metadata_t qemu_event_log_metadata[];
|
||||
|
||||
const event_log_metadata_t *plat_event_log_get_metadata(void)
|
||||
{
|
||||
return qemu_event_log_metadata;
|
||||
}
|
||||
|
||||
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
|
||||
{
|
||||
/* Calculate image hash and record data in Event Log */
|
||||
int err = event_log_measure_and_record(image_data->image_base,
|
||||
image_data->image_size,
|
||||
image_id);
|
||||
if (err != 0) {
|
||||
ERROR("%s%s image id %u (%i)\n",
|
||||
"Failed to ", "record", image_id, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Linaro.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#if MEASURED_BOOT
|
||||
#include <common/desc_image_load.h>
|
||||
#endif
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#ifdef SPD_opteed
|
||||
/*
|
||||
* Currently OP-TEE does not support reading DTBs from Secure memory
|
||||
* and this property should be removed when this feature is supported.
|
||||
*/
|
||||
#define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr"
|
||||
#endif
|
||||
|
||||
#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
|
||||
#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
|
||||
|
||||
#if MEASURED_BOOT
|
||||
|
||||
#ifdef SPD_opteed
|
||||
int qemu_set_tee_fw_info(uintptr_t config_base, uintptr_t log_addr,
|
||||
size_t log_size)
|
||||
{
|
||||
int offs, err = 0;
|
||||
void *dtb = (void *)config_base;
|
||||
const char *compatible = "arm,tpm_event_log";
|
||||
uint64_t sec_base = cpu_to_fdt64(log_addr);
|
||||
uint32_t sz = cpu_to_fdt32(log_size);
|
||||
|
||||
offs = fdtw_find_or_add_subnode(dtb, 0, "tpm-event-log");
|
||||
if (offs < 0) {
|
||||
ERROR("Failed to add node tpm-event-log %d\n", offs);
|
||||
return offs;
|
||||
}
|
||||
|
||||
if (fdt_appendprop(dtb, offs, "compatible", compatible,
|
||||
strlen(compatible) + 1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = fdt_setprop(dtb, offs, DTB_PROP_HW_SM_LOG_ADDR, &sec_base, 8);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to add log addr err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = fdt_setprop(dtb, offs, DTB_PROP_HW_LOG_SIZE, &sz, 4);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to add log addr err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Write the Event Log address and its size in the DTB.
|
||||
*
|
||||
* This function is supposed to be called only by BL2.
|
||||
*
|
||||
* Returns:
|
||||
* 0 = success
|
||||
* < 0 = error
|
||||
*/
|
||||
static int qemu_set_event_log_info(uintptr_t config_base,
|
||||
#ifdef SPD_opteed
|
||||
uintptr_t sm_log_addr,
|
||||
#endif
|
||||
uintptr_t log_addr, size_t log_size)
|
||||
{
|
||||
/* As libfdt uses void *, we can't avoid this cast */
|
||||
void *dtb = (void *)config_base;
|
||||
const char *compatible_tpm = "tcg,tpm-tis-mmio";
|
||||
uint64_t base = cpu_to_fdt64(log_addr);
|
||||
uint32_t sz = cpu_to_fdt32(log_size);
|
||||
int err, node;
|
||||
|
||||
err = fdt_open_into(dtb, dtb, PLAT_QEMU_DT_MAX_SIZE);
|
||||
if (err < 0) {
|
||||
ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the DTB is valid, before attempting to write to it,
|
||||
* and get the DTB root node.
|
||||
*/
|
||||
|
||||
/* Check if the pointer to DT is correct */
|
||||
err = fdt_check_header(dtb);
|
||||
if (err < 0) {
|
||||
WARN("Invalid DTB file passed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the TPM node in device tree. On qemu, we assume it will
|
||||
* be sw-tpm.
|
||||
*/
|
||||
node = fdt_node_offset_by_compatible(dtb, -1, compatible_tpm);
|
||||
if (node < 0) {
|
||||
ERROR("The compatible property '%s' not%s", compatible_tpm,
|
||||
" found in the config\n");
|
||||
return node;
|
||||
}
|
||||
|
||||
err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_ADDR, &base, 8);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to add log addr err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_SIZE, &sz, 4);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to add log addr err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef SPD_opteed
|
||||
err = qemu_set_tee_fw_info(config_base, sm_log_addr, log_size);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to add tpm-event-node at %p: err %d\n", dtb, err);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = fdt_pack(dtb);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to pack Device Tree at %p: err %d\n", dtb, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the info written to the DTB is visible
|
||||
* to other images.
|
||||
*/
|
||||
flush_dcache_range(config_base, fdt_totalsize(dtb));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function writes the Event Log address and its size
|
||||
* in the TOS_FW_CONFIG DTB.
|
||||
*
|
||||
* This function is supposed to be called only by BL2.
|
||||
*
|
||||
* Returns:
|
||||
* 0 = success
|
||||
* < 0 = error
|
||||
*/
|
||||
int qemu_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
|
||||
size_t log_size)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
assert(config_base != 0UL);
|
||||
assert(log_addr != 0UL);
|
||||
|
||||
/*
|
||||
* FIXME - add code to add/update Log address and it's
|
||||
* size in TOS FW CONFIG.
|
||||
* For now we don't have support for TOS FW config in OP-TEE.
|
||||
* So leave this function blank
|
||||
*/
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function writes the Event Log address and its size
|
||||
* in the QEMU DTB.
|
||||
*
|
||||
* This function is supposed to be called only by BL2.
|
||||
*
|
||||
* Returns:
|
||||
* 0 = success
|
||||
* < 0 = error
|
||||
*/
|
||||
int qemu_set_nt_fw_info(
|
||||
#ifdef SPD_opteed
|
||||
uintptr_t log_addr,
|
||||
#endif
|
||||
size_t log_size, uintptr_t *ns_log_addr)
|
||||
{
|
||||
uintptr_t ns_addr;
|
||||
int err;
|
||||
|
||||
assert(ns_log_addr != NULL);
|
||||
|
||||
ns_addr = PLAT_QEMU_DT_BASE + PLAT_QEMU_DT_MAX_SIZE;
|
||||
|
||||
/* Write the Event Log address and its size in the DTB */
|
||||
err = qemu_set_event_log_info(PLAT_QEMU_DT_BASE,
|
||||
#ifdef SPD_opteed
|
||||
log_addr,
|
||||
#endif
|
||||
ns_addr, log_size);
|
||||
|
||||
/* Return Event Log address in Non-secure memory */
|
||||
*ns_log_addr = (err < 0) ? 0UL : ns_addr;
|
||||
return err;
|
||||
}
|
||||
#endif /* MEASURED_BOOT */
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2022, Linaro.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <drivers/measured_boot/event_log/event_log.h>
|
||||
#include <plat/common/common_def.h>
|
||||
#include <tools_share/tbbr_oid.h>
|
||||
|
||||
#include "../common/qemu_private.h"
|
||||
|
||||
/* Event Log data */
|
||||
static uint8_t event_log[PLAT_EVENT_LOG_MAX_SIZE];
|
||||
static uint64_t event_log_base;
|
||||
|
||||
/* FVP table with platform specific image IDs, names and PCRs */
|
||||
const event_log_metadata_t qemu_event_log_metadata[] = {
|
||||
{ BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 },
|
||||
{ BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 },
|
||||
{ BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 },
|
||||
{ BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 },
|
||||
{ BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 },
|
||||
{ HW_CONFIG_ID, EVLOG_HW_CONFIG_STRING, PCR_0 },
|
||||
{ NT_FW_CONFIG_ID, EVLOG_NT_FW_CONFIG_STRING, PCR_0 },
|
||||
{ SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 },
|
||||
{ SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 },
|
||||
{ TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 },
|
||||
|
||||
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
|
||||
};
|
||||
|
||||
void bl2_plat_mboot_init(void)
|
||||
{
|
||||
/*
|
||||
* Here we assume that BL1/ROM code doesn't have the driver
|
||||
* to measure the BL2 code which is a common case for
|
||||
* already existing platforms
|
||||
*/
|
||||
event_log_init(event_log, event_log + sizeof(event_log));
|
||||
event_log_write_header();
|
||||
|
||||
/*
|
||||
* TBD - Add code to do self measurement of BL2 code and add an
|
||||
* event for BL2 measurement
|
||||
*/
|
||||
|
||||
event_log_base = (uintptr_t)event_log;
|
||||
}
|
||||
|
||||
void bl2_plat_mboot_finish(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Event Log address in Non-Secure memory */
|
||||
uintptr_t ns_log_addr;
|
||||
|
||||
/* Event Log filled size */
|
||||
size_t event_log_cur_size;
|
||||
|
||||
event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
|
||||
|
||||
rc = qemu_set_nt_fw_info(
|
||||
#ifdef SPD_opteed
|
||||
(uintptr_t)event_log_base,
|
||||
#endif
|
||||
event_log_cur_size, &ns_log_addr);
|
||||
if (rc != 0) {
|
||||
ERROR("%s(): Unable to update %s_FW_CONFIG\n",
|
||||
__func__, "NT");
|
||||
/*
|
||||
* It is a fatal error because on QEMU secure world software
|
||||
* assumes that a valid event log exists and will use it to
|
||||
* record the measurements into the fTPM or sw-tpm.
|
||||
* Note: In QEMU platform, OP-TEE uses nt_fw_config to get the
|
||||
* secure Event Log buffer address.
|
||||
*/
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Copy Event Log to Non-secure memory */
|
||||
(void)memcpy((void *)ns_log_addr, (const void *)event_log_base,
|
||||
event_log_cur_size);
|
||||
|
||||
/* Ensure that the Event Log is visible in Non-secure memory */
|
||||
flush_dcache_range(ns_log_addr, event_log_cur_size);
|
||||
|
||||
#if defined(SPD_tspd) || defined(SPD_spmd)
|
||||
/* Set Event Log data in TOS_FW_CONFIG */
|
||||
rc = qemu_set_tos_fw_info((uintptr_t)event_log_base,
|
||||
event_log_cur_size);
|
||||
if (rc != 0) {
|
||||
ERROR("%s(): Unable to update %s_FW_CONFIG\n",
|
||||
__func__, "TOS");
|
||||
panic();
|
||||
}
|
||||
#endif /* defined(SPD_tspd) || defined(SPD_spmd) */
|
||||
|
||||
dump_event_log((uint8_t *)event_log_base, event_log_cur_size);
|
||||
}
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 2019-2020, Linaro Limited and Contributors.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <plat/common/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 U(8)
|
||||
/*
|
||||
* Define the number of cores per cluster used in calculating core position.
|
||||
* The cluster number is shifted by this value and added to the core ID,
|
||||
* so its value represents log2(cores/cluster).
|
||||
* Default is 2**(3) = 8 cores per cluster.
|
||||
*/
|
||||
#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(3)
|
||||
#define PLATFORM_CLUSTER_COUNT U(64)
|
||||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||
#define QEMU_PRIMARY_CPU U(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 0x10000000000ULL
|
||||
#define NS_DRAM0_SIZE 0x00020000000
|
||||
|
||||
#define SEC_SRAM_BASE 0x20000000
|
||||
#define SEC_SRAM_SIZE 0x20000000
|
||||
|
||||
/*
|
||||
* RAD just placeholders, need to be chosen after finalizing mem map
|
||||
*/
|
||||
#define SEC_DRAM_BASE 0x1000
|
||||
#define SEC_DRAM_SIZE 0x1000
|
||||
|
||||
/* Load pageable part of OP-TEE 2MB above secure DRAM base */
|
||||
#define QEMU_OPTEE_PAGEABLE_LOAD_BASE (SEC_DRAM_BASE + 0x00200000)
|
||||
#define QEMU_OPTEE_PAGEABLE_LOAD_SIZE 0x00400000
|
||||
|
||||
/*
|
||||
* ARM-TF lives in SRAM, partition it here
|
||||
*/
|
||||
|
||||
#define SHARED_RAM_BASE SEC_SRAM_BASE
|
||||
#define SHARED_RAM_SIZE 0x00002000
|
||||
|
||||
#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_SHIFT 3
|
||||
#define PLAT_QEMU_HOLD_ENTRY_SIZE (1 << PLAT_QEMU_HOLD_ENTRY_SHIFT)
|
||||
#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_SIZE 0x12000
|
||||
#define BL1_RO_BASE SEC_ROM_BASE
|
||||
#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
|
||||
#define BL1_RW_BASE (BL1_RW_LIMIT - BL1_SIZE)
|
||||
#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_SIZE 0x1D000
|
||||
#define BL2_BASE (BL31_BASE - BL2_SIZE)
|
||||
#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_SIZE 0x300000
|
||||
#define BL31_BASE (BL31_LIMIT - BL31_SIZE)
|
||||
#define BL31_LIMIT (BL1_RW_BASE)
|
||||
#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 BL2_BASE
|
||||
|
||||
#define BL32_MEM_BASE BL_RAM_BASE
|
||||
#define BL32_MEM_SIZE (BL_RAM_SIZE - BL1_SIZE - \
|
||||
BL2_SIZE - BL31_SIZE)
|
||||
#define BL32_BASE BL32_SRAM_BASE
|
||||
#define BL32_LIMIT BL32_SRAM_LIMIT
|
||||
|
||||
#define NS_IMAGE_OFFSET (NS_DRAM0_BASE + 0x20000000)
|
||||
#define NS_IMAGE_MAX_SIZE (NS_DRAM0_SIZE - 0x20000000)
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 42)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 42)
|
||||
#if SPM_MM
|
||||
#define MAX_MMAP_REGIONS 12
|
||||
#define MAX_XLAT_TABLES 12
|
||||
#else
|
||||
#define MAX_MMAP_REGIONS 11
|
||||
#define MAX_XLAT_TABLES 11
|
||||
#endif
|
||||
#define MAX_IO_DEVICES 3
|
||||
#define MAX_IO_HANDLES 4
|
||||
|
||||
#if SPM_MM && defined(IMAGE_BL31)
|
||||
# define PLAT_SP_IMAGE_MMAP_REGIONS 30
|
||||
# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 50
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PL011 related constants
|
||||
*/
|
||||
#define UART0_BASE 0x60000000
|
||||
#define UART1_BASE 0x60030000
|
||||
#define UART0_CLK_IN_HZ 1
|
||||
#define UART1_CLK_IN_HZ 1
|
||||
|
||||
/* Secure UART */
|
||||
#define UART2_BASE 0x60040000
|
||||
#define UART2_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 0x00000000
|
||||
#define QEMU_FLASH0_SIZE 0x10000000
|
||||
#define QEMU_FLASH1_BASE 0x10000000
|
||||
#define QEMU_FLASH1_SIZE 0x10000000
|
||||
|
||||
#define PLAT_QEMU_FIP_BASE 0x00008000
|
||||
#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000
|
||||
|
||||
/* This is map from GIC_DIST up to last CPU (255) GIC_REDISTR */
|
||||
#define DEVICE0_BASE 0x40000000
|
||||
#define DEVICE0_SIZE 0x04080000
|
||||
/* This is map from NORMAL_UART up to SECURE_UART_MM */
|
||||
#define DEVICE1_BASE 0x60000000
|
||||
#define DEVICE1_SIZE 0x10041000
|
||||
/* This is a map for SECURE_EC */
|
||||
#define DEVICE2_BASE 0x50000000
|
||||
#define DEVICE2_SIZE 0x00001000
|
||||
|
||||
/*
|
||||
* GIC related constants
|
||||
* We use GICv3 where CPU Interface registers are not memory mapped
|
||||
*/
|
||||
#define GICD_BASE 0x40060000
|
||||
#define GICR_BASE 0x40080000
|
||||
#define GICC_BASE 0x0
|
||||
|
||||
#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
|
||||
|
||||
/******************************************************************************
|
||||
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
|
||||
* interrupts.
|
||||
*****************************************************************************/
|
||||
#define PLATFORM_G1S_PROPS(grp) \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
grp, GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define PLATFORM_G0_PROPS(grp)
|
||||
|
||||
/*
|
||||
* DT related constants
|
||||
*/
|
||||
#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE
|
||||
#define PLAT_QEMU_DT_MAX_SIZE 0x100000
|
||||
|
||||
/*
|
||||
* System counter
|
||||
*/
|
||||
#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16)
|
||||
|
||||
#if SPM_MM
|
||||
#define PLAT_QEMU_SP_IMAGE_BASE BL_RAM_BASE
|
||||
#define PLAT_QEMU_SP_IMAGE_SIZE ULL(0x300000)
|
||||
|
||||
#ifdef IMAGE_BL2
|
||||
/* In BL2 all memory allocated to the SPM Payload image is marked as RW. */
|
||||
# define QEMU_SP_IMAGE_MMAP MAP_REGION_FLAT( \
|
||||
PLAT_QEMU_SP_IMAGE_BASE, \
|
||||
PLAT_QEMU_SP_IMAGE_SIZE, \
|
||||
MT_MEMORY | MT_RW | \
|
||||
MT_SECURE)
|
||||
#elif IMAGE_BL31
|
||||
/* All SPM Payload memory is marked as code in S-EL0 */
|
||||
# define QEMU_SP_IMAGE_MMAP MAP_REGION2(PLAT_QEMU_SP_IMAGE_BASE, \
|
||||
PLAT_QEMU_SP_IMAGE_BASE, \
|
||||
PLAT_QEMU_SP_IMAGE_SIZE, \
|
||||
MT_CODE | MT_SECURE | \
|
||||
MT_USER, \
|
||||
PAGE_SIZE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* EL3 -> S-EL0 secure shared memory
|
||||
*/
|
||||
#define PLAT_SPM_BUF_PCPU_SIZE ULL(0x10000)
|
||||
#define PLAT_SPM_BUF_SIZE (PLATFORM_CORE_COUNT * \
|
||||
PLAT_SPM_BUF_PCPU_SIZE)
|
||||
#define PLAT_SPM_BUF_BASE (BL32_LIMIT - PLAT_SPM_BUF_SIZE)
|
||||
|
||||
#define QEMU_SPM_BUF_EL3_MMAP MAP_REGION_FLAT(PLAT_SPM_BUF_BASE, \
|
||||
PLAT_SPM_BUF_SIZE, \
|
||||
MT_RW_DATA | MT_SECURE)
|
||||
|
||||
#define QEMU_SPM_BUF_EL0_MMAP MAP_REGION2(PLAT_SPM_BUF_BASE, \
|
||||
PLAT_SPM_BUF_BASE, \
|
||||
PLAT_SPM_BUF_SIZE, \
|
||||
MT_RO_DATA | MT_SECURE | \
|
||||
MT_USER, \
|
||||
PAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Shared memory between Normal world and S-EL0 for
|
||||
* passing data during service requests. It will be marked as RW and NS.
|
||||
* This buffer is allocated at the top of NS_DRAM, the base address is
|
||||
* overridden in SPM initialization.
|
||||
*/
|
||||
#define PLAT_QEMU_SP_IMAGE_NS_BUF_BASE (PLAT_QEMU_DT_BASE + \
|
||||
PLAT_QEMU_DT_MAX_SIZE)
|
||||
#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE ULL(0x200000)
|
||||
|
||||
#define QEMU_SP_IMAGE_NS_BUF_MMAP MAP_REGION2( \
|
||||
PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
|
||||
PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
|
||||
PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE, \
|
||||
MT_RW_DATA | MT_NS | \
|
||||
MT_USER, \
|
||||
PAGE_SIZE)
|
||||
|
||||
#define PLAT_SP_IMAGE_NS_BUF_BASE PLAT_QEMU_SP_IMAGE_NS_BUF_BASE
|
||||
#define PLAT_SP_IMAGE_NS_BUF_SIZE PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE
|
||||
|
||||
#define PLAT_QEMU_SP_IMAGE_HEAP_BASE (PLAT_QEMU_SP_IMAGE_BASE + \
|
||||
PLAT_QEMU_SP_IMAGE_SIZE)
|
||||
#define PLAT_QEMU_SP_IMAGE_HEAP_SIZE ULL(0x800000)
|
||||
|
||||
#define PLAT_SP_IMAGE_STACK_BASE (PLAT_QEMU_SP_IMAGE_HEAP_BASE + \
|
||||
PLAT_QEMU_SP_IMAGE_HEAP_SIZE)
|
||||
#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x10000)
|
||||
#define QEMU_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \
|
||||
PLAT_SP_IMAGE_STACK_PCPU_SIZE)
|
||||
|
||||
#define QEMU_SP_IMAGE_RW_MMAP MAP_REGION2( \
|
||||
PLAT_QEMU_SP_IMAGE_HEAP_BASE, \
|
||||
PLAT_QEMU_SP_IMAGE_HEAP_BASE, \
|
||||
(QEMU_SP_IMAGE_STACK_TOTAL_SIZE + \
|
||||
PLAT_QEMU_SP_IMAGE_HEAP_SIZE), \
|
||||
MT_RW_DATA | MT_SECURE | \
|
||||
MT_USER, \
|
||||
PAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Secure variable storage is located at Secure Flash.
|
||||
*/
|
||||
#if SPM_MM
|
||||
#define QEMU_SECURE_VARSTORE_BASE 0x01000000
|
||||
#define QEMU_SECURE_VARSTORE_SIZE 0x00100000
|
||||
#define MAP_SECURE_VARSTORE MAP_REGION_FLAT( \
|
||||
QEMU_SECURE_VARSTORE_BASE, \
|
||||
QEMU_SECURE_VARSTORE_SIZE, \
|
||||
MT_DEVICE | MT_RW | \
|
||||
MT_SECURE | MT_USER)
|
||||
#endif
|
||||
|
||||
/* Total number of memory regions with distinct properties */
|
||||
#define PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS 6
|
||||
|
||||
/*
|
||||
* Name of the section to put the translation tables used by the S-EL1/S-EL0
|
||||
* context of a Secure Partition.
|
||||
*/
|
||||
#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "qemu_sp_xlat_table"
|
||||
#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME "qemu_sp_xlat_table"
|
||||
|
||||
/* Cookies passed to the Secure Partition at boot. Not used by QEMU platforms.*/
|
||||
#define PLAT_SPM_COOKIE_0 ULL(0)
|
||||
#define PLAT_SPM_COOKIE_1 ULL(0)
|
||||
#endif
|
||||
|
||||
#define QEMU_PRI_BITS 2
|
||||
#define PLAT_SP_PRI 0x20
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,127 @@
|
||||
#
|
||||
# Copyright (c) 2019-2021, Linaro Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include common/fdt_wrappers.mk
|
||||
|
||||
CRASH_REPORTING := 1
|
||||
|
||||
include lib/libfdt/libfdt.mk
|
||||
|
||||
ifeq (${SPM_MM},1)
|
||||
NEED_BL32 := yes
|
||||
EL3_EXCEPTION_HANDLING := 1
|
||||
GICV2_G0_FOR_EL3 := 1
|
||||
endif
|
||||
|
||||
# Enable new version of image loading on QEMU platforms
|
||||
LOAD_IMAGE_V2 := 1
|
||||
|
||||
ifeq ($(NEED_BL32),yes)
|
||||
$(eval $(call add_define,QEMU_LOAD_BL32))
|
||||
endif
|
||||
|
||||
PLAT_QEMU_PATH := plat/qemu/qemu_sbsa
|
||||
PLAT_QEMU_COMMON_PATH := plat/qemu/common
|
||||
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
|
||||
-I${PLAT_QEMU_COMMON_PATH}/include \
|
||||
-I${PLAT_QEMU_PATH}/include \
|
||||
-Iinclude/common/tbbr
|
||||
|
||||
PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH}
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := ${PLAT_QEMU_COMMON_PATH}/qemu_common.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_console.c \
|
||||
drivers/arm/pl011/${ARCH}/pl011_console.S
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
|
||||
|
||||
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/${ARCH}/semihosting_call.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c
|
||||
|
||||
BL1_SOURCES += lib/cpus/aarch64/cortex_a57.S \
|
||||
lib/cpus/aarch64/cortex_a72.S \
|
||||
lib/cpus/aarch64/qemu_max.S \
|
||||
|
||||
BL2_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/${ARCH}/semihosting_call.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_bl2_setup.c \
|
||||
common/fdt_fixup.c \
|
||||
$(LIBFDT_SRCS)
|
||||
ifeq (${LOAD_IMAGE_V2},1)
|
||||
BL2_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_image_load.c \
|
||||
common/desc_image_load.c
|
||||
endif
|
||||
|
||||
# Include GICv3 driver files
|
||||
include drivers/arm/gic/v3/gicv3.mk
|
||||
|
||||
QEMU_GIC_SOURCES := ${GICV3_SOURCES} \
|
||||
plat/common/plat_gicv3.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a57.S \
|
||||
lib/cpus/aarch64/cortex_a72.S \
|
||||
lib/cpus/aarch64/qemu_max.S \
|
||||
lib/semihosting/semihosting.c \
|
||||
lib/semihosting/${ARCH}/semihosting_call.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
${PLAT_QEMU_PATH}/sbsa_pm.c \
|
||||
${PLAT_QEMU_PATH}/sbsa_topology.c \
|
||||
${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \
|
||||
${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \
|
||||
common/fdt_fixup.c \
|
||||
${QEMU_GIC_SOURCES}
|
||||
|
||||
BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
|
||||
ifeq (${SPM_MM},1)
|
||||
BL31_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_spm.c
|
||||
endif
|
||||
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
ENABLE_STACK_PROTECTOR := 0
|
||||
ifneq ($(ENABLE_STACK_PROTECTOR), 0)
|
||||
PLAT_BL_COMMON_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_stack_protector.c
|
||||
endif
|
||||
|
||||
MULTI_CONSOLE_API := 1
|
||||
|
||||
# Disable the PSCI platform compatibility layer
|
||||
ENABLE_PLAT_COMPAT := 0
|
||||
|
||||
# Use known base for UEFI if not given from command line
|
||||
# By default BL33 is at FLASH1 base
|
||||
PRELOADED_BL33_BASE ?= 0x10000000
|
||||
|
||||
# Qemu SBSA plafrom only support SEC_SRAM
|
||||
BL32_RAM_LOCATION_ID = SEC_SRAM_ID
|
||||
$(eval $(call add_define,BL32_RAM_LOCATION_ID))
|
||||
|
||||
# Don't have the Linux kernel as a BL33 image by default
|
||||
ARM_LINUX_KERNEL_AS_BL33 := 0
|
||||
$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
|
||||
$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
|
||||
|
||||
ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE
|
||||
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
|
||||
|
||||
# Do not enable SVE
|
||||
ENABLE_SVE_FOR_NS := 0
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Nuvia Inc
|
||||
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
#include "sbsa_private.h"
|
||||
|
||||
#define ADP_STOPPED_APPLICATION_EXIT 0x20026
|
||||
|
||||
/*
|
||||
* Define offset and commands for the fake EC device
|
||||
*/
|
||||
#define SBSA_SECURE_EC_OFFSET 0x50000000
|
||||
|
||||
#define SBSA_SECURE_EC_CMD_SHUTDOWN 0x01
|
||||
#define SBSA_SECURE_EC_CMD_REBOOT 0x02
|
||||
|
||||
/*
|
||||
* 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;
|
||||
unsigned int i;
|
||||
|
||||
assert(req_state != NULL);
|
||||
|
||||
/*
|
||||
* 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 justifies the additional complexity.
|
||||
*/
|
||||
for (i = 0U; qemu_pm_idle_states[i] != 0U; 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] == 0U) {
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
i = 0U;
|
||||
state_id = psci_get_pstate_id(power_state);
|
||||
|
||||
/* Parse the State ID and populate the state info parameter */
|
||||
while (state_id != 0U) {
|
||||
req_state->pwr_domain_state[i++] = state_id &
|
||||
PLAT_LOCAL_PSTATE_MASK;
|
||||
state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a CPU is about to enter standby.
|
||||
******************************************************************************/
|
||||
static void 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 pos = plat_core_pos_by_mpidr(mpidr);
|
||||
uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE;
|
||||
|
||||
if (pos < 0) {
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO;
|
||||
dsb();
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
static void qemu_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
qemu_pwr_gic_off();
|
||||
}
|
||||
|
||||
void __dead2 plat_secondary_cold_boot_setup(void);
|
||||
|
||||
static void __dead2
|
||||
qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
|
||||
{
|
||||
disable_mmu_el3();
|
||||
plat_secondary_cold_boot_setup();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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(false);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
|
||||
qemu_pwr_gic_on_finish();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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(false);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handlers to shutdown/reboot the system
|
||||
******************************************************************************/
|
||||
static void __dead2 qemu_system_off(void)
|
||||
{
|
||||
mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_SHUTDOWN);
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 qemu_system_reset(void)
|
||||
{
|
||||
mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_REBOOT);
|
||||
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_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi,
|
||||
.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
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
uintptr_t *mailbox = (uintptr_t *)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,17 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Nuvia Inc
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SBSA_PRIVATE_H
|
||||
#define SBSA_PRIVATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
|
||||
|
||||
void qemu_pwr_gic_on_finish(void);
|
||||
void qemu_pwr_gic_off(void);
|
||||
|
||||
#endif /* SBSA_PRIVATE_H */
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Nuvia Inc
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
#include "sbsa_private.h"
|
||||
|
||||
/* The power domain tree descriptor */
|
||||
static unsigned char power_domain_tree_desc[PLATFORM_CLUSTER_COUNT + 1];
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the sbsa-ref default topology tree information.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
power_domain_tree_desc[0] = PLATFORM_CLUSTER_COUNT;
|
||||
|
||||
for (i = 0U; i < PLATFORM_CLUSTER_COUNT; i++) {
|
||||
power_domain_tree_desc[i + 1] = PLATFORM_MAX_CPUS_PER_CLUSTER;
|
||||
}
|
||||
|
||||
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)) != 0U) {
|
||||
ERROR("Invalid MPIDR\n");
|
||||
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) {
|
||||
ERROR("cluster_id >= PLATFORM_CLUSTER_COUNT define\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
|
||||
ERROR("cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER define\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return plat_qemu_calc_core_pos(mpidr);
|
||||
}
|
||||
Reference in New Issue
Block a user