firmware/coreboot: Subtree merged arm-trusted-firmware
Signed-off-by: David Hendricks <dhendricks@fb.com>
95
firmware/coreboot/3rdparty/arm-trusted-firmware/.checkpatch.conf
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
#
|
||||
# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of ARM nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
# Configure how the Linux checkpatch script should be invoked in the context of
|
||||
# the Trusted Firmware source tree.
|
||||
#
|
||||
|
||||
# This is not Linux so don't expect a Linux tree!
|
||||
--no-tree
|
||||
|
||||
# The Linux kernel expects the SPDX license tag in the first line of each file.
|
||||
# We don't follow this in the Trusted Firmware.
|
||||
--ignore SPDX_LICENSE_TAG
|
||||
|
||||
# This clarifes the lines indications in the report.
|
||||
#
|
||||
# E.g.:
|
||||
# Without this option, we have the following output:
|
||||
# #333: FILE: drivers/arm/gic/arm_gic.c:160:
|
||||
# So we have 2 lines indications (333 and 160), which is confusing.
|
||||
# We only care about the position in the source file.
|
||||
#
|
||||
# With this option, it becomes:
|
||||
# drivers/arm/gic/arm_gic.c:160:
|
||||
--showfile
|
||||
|
||||
# Don't show some messages like the list of ignored types or the suggestion to
|
||||
# use "--fix" or report changes to the maintainers.
|
||||
--quiet
|
||||
|
||||
#
|
||||
# Ignore the following message types, as they don't necessarily make sense in
|
||||
# the context of the Trusted Firmware.
|
||||
#
|
||||
|
||||
# COMPLEX_MACRO generates false positives.
|
||||
--ignore COMPLEX_MACRO
|
||||
|
||||
# Commit messages might contain a Gerrit Change-Id.
|
||||
--ignore GERRIT_CHANGE_ID
|
||||
|
||||
# Do not check the format of commit messages, as Github's merge commits do not
|
||||
# observe it.
|
||||
--ignore GIT_COMMIT_ID
|
||||
|
||||
# FILE_PATH_CHANGES reports this kind of message:
|
||||
# "added, moved or deleted file(s), does MAINTAINERS need updating?"
|
||||
# We do not use this MAINTAINERS file process in TF.
|
||||
--ignore FILE_PATH_CHANGES
|
||||
|
||||
# AVOID_EXTERNS reports this kind of messages:
|
||||
# "externs should be avoided in .c files"
|
||||
# We don't follow this convention in TF.
|
||||
--ignore AVOID_EXTERNS
|
||||
|
||||
# NEW_TYPEDEFS reports this kind of messages:
|
||||
# "do not add new typedefs"
|
||||
# We allow adding new typedefs in TF.
|
||||
--ignore NEW_TYPEDEFS
|
||||
|
||||
# Avoid "Does not appear to be a unified-diff format patch" message
|
||||
--ignore NOT_UNIFIED_DIFF
|
||||
|
||||
# VOLATILE reports this kind of messages:
|
||||
# "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt"
|
||||
# We allow the usage of the volatile keyword in TF.
|
||||
--ignore VOLATILE
|
||||
62
firmware/coreboot/3rdparty/arm-trusted-firmware/.editorconfig
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
#
|
||||
# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# ARM Trusted Firmware Coding style spec for editors.
|
||||
|
||||
# References:
|
||||
# [EC] http://editorconfig.org/
|
||||
# [CONT] contributing.rst
|
||||
# [LCS] Linux Coding Style
|
||||
# (https://www.kernel.org/doc/html/v4.10/process/coding-style.html)
|
||||
|
||||
|
||||
root = true
|
||||
|
||||
# set default to match [LCS] .c/.h settings.
|
||||
# This will also apply to .S, .mk, .sh, Makefile, .dts, etc.
|
||||
[*]
|
||||
# Not specified, but fits current ARM-TF sources.
|
||||
charset = utf-8
|
||||
|
||||
# Not specified, but implicit for "LINUX coding style".
|
||||
end_of_line = lf
|
||||
|
||||
# [LCS] Chapter 1: Indentation
|
||||
# "and thus indentations are also 8 characters"
|
||||
indent_size = 8
|
||||
|
||||
# [LCS] Chapter 1: Indentation
|
||||
# "Outside of comments,...spaces are never used for indentation"
|
||||
indent_style = tab
|
||||
|
||||
# Not specified by [LCS], but sensible
|
||||
insert_final_newline = true
|
||||
|
||||
# [LCS] Chapter 2: Breaking long lines and strings
|
||||
# "The limit on the length of lines is 80 columns"
|
||||
# This is a "soft" requirement for Arm-TF, and should not be the sole
|
||||
# reason for changes.
|
||||
max_line_length = 80
|
||||
|
||||
# [LCS] Chapter 1: Indentation
|
||||
# "Tabs are 8 characters"
|
||||
tab_width = 8
|
||||
|
||||
# [LCS] Chapter 1: Indentation
|
||||
# "Get a decent editor and don't leave whitespace at the end of lines."
|
||||
# [LCS] Chapter 3.1: Spaces
|
||||
# "Do not leave trailing whitespace at the ends of lines."
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
|
||||
# Adjustment for existing .rst files with different format
|
||||
[*.{rst,md}]
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
max_line_length = 180
|
||||
# 180 only selected to prevent changes to existing text.
|
||||
tab_width = 4
|
||||
|
||||
26
firmware/coreboot/3rdparty/arm-trusted-firmware/.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Ignore miscellaneous files
|
||||
cscope.*
|
||||
*.swp
|
||||
*.patch
|
||||
*~
|
||||
.project
|
||||
.cproject
|
||||
|
||||
# Ignore build directory
|
||||
build/
|
||||
|
||||
# Ignore build products from tools
|
||||
tools/**/*.o
|
||||
tools/fip_create/
|
||||
tools/fiptool/fiptool
|
||||
tools/fiptool/fiptool.exe
|
||||
tools/cert_create/src/*.o
|
||||
tools/cert_create/src/**/*.o
|
||||
tools/cert_create/cert_create
|
||||
tools/cert_create/cert_create.exe
|
||||
|
||||
# GNU GLOBAL files
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
845
firmware/coreboot/3rdparty/arm-trusted-firmware/Makefile
vendored
Normal file
@@ -0,0 +1,845 @@
|
||||
#
|
||||
# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
#
|
||||
# Trusted Firmware Version
|
||||
#
|
||||
VERSION_MAJOR := 1
|
||||
VERSION_MINOR := 5
|
||||
|
||||
# Default goal is build all images
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
# Avoid any implicit propagation of command line variable definitions to
|
||||
# sub-Makefiles, like CFLAGS that we reserved for the firmware images'
|
||||
# usage. Other command line options like "-s" are still propagated as usual.
|
||||
MAKEOVERRIDES =
|
||||
|
||||
MAKE_HELPERS_DIRECTORY := make_helpers/
|
||||
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
|
||||
include ${MAKE_HELPERS_DIRECTORY}build_env.mk
|
||||
|
||||
################################################################################
|
||||
# Default values for build configurations, and their dependencies
|
||||
################################################################################
|
||||
|
||||
ifdef ASM_ASSERTION
|
||||
$(warning ASM_ASSERTION is removed, use ENABLE_ASSERTIONS instead.)
|
||||
endif
|
||||
|
||||
include ${MAKE_HELPERS_DIRECTORY}defaults.mk
|
||||
|
||||
# Assertions enabled for DEBUG builds by default
|
||||
ENABLE_ASSERTIONS := ${DEBUG}
|
||||
ENABLE_PMF := ${ENABLE_RUNTIME_INSTRUMENTATION}
|
||||
PLAT := ${DEFAULT_PLAT}
|
||||
|
||||
################################################################################
|
||||
# Checkpatch script options
|
||||
################################################################################
|
||||
|
||||
CHECKCODE_ARGS := --no-patch
|
||||
# Do not check the coding style on imported library files or documentation files
|
||||
INC_LIB_DIRS_TO_CHECK := $(sort $(filter-out \
|
||||
include/lib/libfdt \
|
||||
include/lib/stdlib, \
|
||||
$(wildcard include/lib/*)))
|
||||
INC_DIRS_TO_CHECK := $(sort $(filter-out \
|
||||
include/lib, \
|
||||
$(wildcard include/*)))
|
||||
LIB_DIRS_TO_CHECK := $(sort $(filter-out \
|
||||
lib/compiler-rt \
|
||||
lib/libfdt% \
|
||||
lib/stdlib, \
|
||||
$(wildcard lib/*)))
|
||||
ROOT_DIRS_TO_CHECK := $(sort $(filter-out \
|
||||
lib \
|
||||
include \
|
||||
docs \
|
||||
%.md, \
|
||||
$(wildcard *)))
|
||||
CHECK_PATHS := ${ROOT_DIRS_TO_CHECK} \
|
||||
${INC_DIRS_TO_CHECK} \
|
||||
${INC_LIB_DIRS_TO_CHECK} \
|
||||
${LIB_DIRS_TO_CHECK}
|
||||
|
||||
|
||||
################################################################################
|
||||
# Process build options
|
||||
################################################################################
|
||||
|
||||
# Verbose flag
|
||||
ifeq (${V},0)
|
||||
Q:=@
|
||||
CHECKCODE_ARGS += --no-summary --terse
|
||||
else
|
||||
Q:=
|
||||
endif
|
||||
export Q
|
||||
|
||||
# Process Debug flag
|
||||
$(eval $(call add_define,DEBUG))
|
||||
ifneq (${DEBUG}, 0)
|
||||
BUILD_TYPE := debug
|
||||
TF_CFLAGS += -g
|
||||
ASFLAGS += -g -Wa,--gdwarf-2
|
||||
# Use LOG_LEVEL_INFO by default for debug builds
|
||||
LOG_LEVEL := 40
|
||||
else
|
||||
BUILD_TYPE := release
|
||||
# Use LOG_LEVEL_NOTICE by default for release builds
|
||||
LOG_LEVEL := 20
|
||||
endif
|
||||
|
||||
# Default build string (git branch and commit)
|
||||
ifeq (${BUILD_STRING},)
|
||||
BUILD_STRING := $(shell git describe --always --dirty --tags 2> /dev/null)
|
||||
endif
|
||||
VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}(${BUILD_TYPE}):${BUILD_STRING}
|
||||
|
||||
# The cert_create tool cannot generate certificates individually, so we use the
|
||||
# target 'certificates' to create them all
|
||||
ifneq (${GENERATE_COT},0)
|
||||
FIP_DEPS += certificates
|
||||
FWU_FIP_DEPS += fwu_certificates
|
||||
endif
|
||||
|
||||
|
||||
################################################################################
|
||||
# Toolchain
|
||||
################################################################################
|
||||
|
||||
HOSTCC := gcc
|
||||
export HOSTCC
|
||||
|
||||
CC := ${CROSS_COMPILE}gcc
|
||||
CPP := ${CROSS_COMPILE}cpp
|
||||
AS := ${CROSS_COMPILE}gcc
|
||||
AR := ${CROSS_COMPILE}ar
|
||||
LD := ${CROSS_COMPILE}ld
|
||||
OC := ${CROSS_COMPILE}objcopy
|
||||
OD := ${CROSS_COMPILE}objdump
|
||||
NM := ${CROSS_COMPILE}nm
|
||||
PP := ${CROSS_COMPILE}gcc -E
|
||||
DTC := dtc
|
||||
|
||||
# Use ${LD}.bfd instead if it exists (as absolute path or together with $PATH).
|
||||
ifneq ($(strip $(wildcard ${LD}.bfd) \
|
||||
$(foreach dir,$(subst :, ,${PATH}),$(wildcard ${dir}/${LD}.bfd))),)
|
||||
LD := ${LD}.bfd
|
||||
endif
|
||||
|
||||
ifeq (${ARM_ARCH_MAJOR},7)
|
||||
target32-directive = -target arm-none-eabi
|
||||
# Will set march32-directive from platform configuration
|
||||
else
|
||||
target32-directive = -target armv8a-none-eabi
|
||||
march32-directive = -march=armv8-a
|
||||
endif
|
||||
|
||||
ifeq ($(notdir $(CC)),armclang)
|
||||
TF_CFLAGS_aarch32 = -target arm-arm-none-eabi $(march32-directive)
|
||||
TF_CFLAGS_aarch64 = -target aarch64-arm-none-eabi -march=armv8-a
|
||||
else ifneq ($(findstring clang,$(notdir $(CC))),)
|
||||
TF_CFLAGS_aarch32 = $(target32-directive)
|
||||
TF_CFLAGS_aarch64 = -target aarch64-elf
|
||||
else
|
||||
TF_CFLAGS_aarch32 = $(march32-directive)
|
||||
TF_CFLAGS_aarch64 = -march=armv8-a
|
||||
endif
|
||||
|
||||
TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align
|
||||
|
||||
ASFLAGS_aarch32 = $(march32-directive)
|
||||
ASFLAGS_aarch64 = -march=armv8-a
|
||||
|
||||
CPPFLAGS = ${DEFINES} ${INCLUDES} -nostdinc \
|
||||
-Wmissing-include-dirs -Werror
|
||||
ASFLAGS += $(CPPFLAGS) $(ASFLAGS_$(ARCH)) \
|
||||
-D__ASSEMBLY__ -ffreestanding \
|
||||
-Wa,--fatal-warnings
|
||||
TF_CFLAGS += $(CPPFLAGS) $(TF_CFLAGS_$(ARCH)) \
|
||||
-ffreestanding -fno-builtin -Wall -std=gnu99 \
|
||||
-Os -ffunction-sections -fdata-sections
|
||||
|
||||
GCC_V_OUTPUT := $(shell $(CC) -v 2>&1)
|
||||
PIE_FOUND := $(findstring --enable-default-pie,${GCC_V_OUTPUT})
|
||||
|
||||
ifneq ($(PIE_FOUND),)
|
||||
TF_CFLAGS += -fno-PIE
|
||||
endif
|
||||
|
||||
TF_LDFLAGS += --fatal-warnings -O1
|
||||
TF_LDFLAGS += --gc-sections
|
||||
TF_LDFLAGS += $(TF_LDFLAGS_$(ARCH))
|
||||
|
||||
DTC_FLAGS += -I dts -O dtb
|
||||
|
||||
################################################################################
|
||||
# Common sources and include directories
|
||||
################################################################################
|
||||
include lib/compiler-rt/compiler-rt.mk
|
||||
include lib/stdlib/stdlib.mk
|
||||
|
||||
BL_COMMON_SOURCES += common/bl_common.c \
|
||||
common/tf_log.c \
|
||||
common/tf_printf.c \
|
||||
common/tf_snprintf.c \
|
||||
common/${ARCH}/debug.S \
|
||||
lib/${ARCH}/cache_helpers.S \
|
||||
lib/${ARCH}/misc_helpers.S \
|
||||
plat/common/plat_bl_common.c \
|
||||
plat/common/plat_log_common.c \
|
||||
plat/common/${ARCH}/plat_common.c \
|
||||
plat/common/${ARCH}/platform_helpers.S \
|
||||
${COMPILER_RT_SRCS} \
|
||||
${STDLIB_SRCS}
|
||||
|
||||
INCLUDES += -Iinclude/bl1 \
|
||||
-Iinclude/bl2 \
|
||||
-Iinclude/bl2u \
|
||||
-Iinclude/bl31 \
|
||||
-Iinclude/common \
|
||||
-Iinclude/common/${ARCH} \
|
||||
-Iinclude/drivers \
|
||||
-Iinclude/drivers/arm \
|
||||
-Iinclude/drivers/auth \
|
||||
-Iinclude/drivers/io \
|
||||
-Iinclude/drivers/ti/uart \
|
||||
-Iinclude/lib \
|
||||
-Iinclude/lib/${ARCH} \
|
||||
-Iinclude/lib/cpus \
|
||||
-Iinclude/lib/cpus/${ARCH} \
|
||||
-Iinclude/lib/el3_runtime \
|
||||
-Iinclude/lib/el3_runtime/${ARCH} \
|
||||
-Iinclude/lib/extensions \
|
||||
-Iinclude/lib/pmf \
|
||||
-Iinclude/lib/psci \
|
||||
-Iinclude/lib/xlat_tables \
|
||||
-Iinclude/plat/common \
|
||||
-Iinclude/services \
|
||||
${PLAT_INCLUDES} \
|
||||
${SPD_INCLUDES} \
|
||||
-Iinclude/tools_share
|
||||
|
||||
|
||||
################################################################################
|
||||
# Generic definitions
|
||||
################################################################################
|
||||
|
||||
include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
|
||||
|
||||
BUILD_BASE := ./build
|
||||
BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${BUILD_TYPE}
|
||||
|
||||
SPDS := $(sort $(filter-out none, $(patsubst services/spd/%,%,$(wildcard services/spd/*))))
|
||||
|
||||
# Platforms providing their own TBB makefile may override this value
|
||||
INCLUDE_TBBR_MK := 1
|
||||
|
||||
|
||||
################################################################################
|
||||
# Include SPD Makefile if one has been specified
|
||||
################################################################################
|
||||
|
||||
ifneq (${SPD},none)
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error "Error: SPD is incompatible with AArch32.")
|
||||
endif
|
||||
ifdef EL3_PAYLOAD_BASE
|
||||
$(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
|
||||
$(warning "The SPD and its BL32 companion will be present but ignored.")
|
||||
endif
|
||||
# We expect to locate an spd.mk under the specified SPD directory
|
||||
SPD_MAKE := $(wildcard services/spd/${SPD}/${SPD}.mk)
|
||||
|
||||
ifeq (${SPD_MAKE},)
|
||||
$(error Error: No services/spd/${SPD}/${SPD}.mk located)
|
||||
endif
|
||||
$(info Including ${SPD_MAKE})
|
||||
include ${SPD_MAKE}
|
||||
|
||||
# If there's BL32 companion for the chosen SPD, we expect that the SPD's
|
||||
# Makefile would set NEED_BL32 to "yes". In this case, the build system
|
||||
# supports two mutually exclusive options:
|
||||
# * BL32 is built from source: then BL32_SOURCES must contain the list
|
||||
# of source files to build BL32
|
||||
# * BL32 is a prebuilt binary: then BL32 must point to the image file
|
||||
# that will be included in the FIP
|
||||
# If both BL32_SOURCES and BL32 are defined, the binary takes precedence
|
||||
# over the sources.
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Include the platform specific Makefile after the SPD Makefile (the platform
|
||||
# makefile may use all previous definitions in this file)
|
||||
################################################################################
|
||||
|
||||
include ${PLAT_MAKEFILE_FULL}
|
||||
|
||||
$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT}))
|
||||
|
||||
ifeq (${ARM_ARCH_MAJOR},7)
|
||||
include make_helpers/armv7-a-cpus.mk
|
||||
endif
|
||||
|
||||
# Platform compatibility is not supported in AArch32
|
||||
ifneq (${ARCH},aarch32)
|
||||
# If the platform has not defined ENABLE_PLAT_COMPAT, then enable it by default
|
||||
ifndef ENABLE_PLAT_COMPAT
|
||||
ENABLE_PLAT_COMPAT := 1
|
||||
endif
|
||||
|
||||
# Include the platform compatibility helpers for PSCI
|
||||
ifneq (${ENABLE_PLAT_COMPAT}, 0)
|
||||
include plat/compat/plat_compat.mk
|
||||
endif
|
||||
endif
|
||||
|
||||
# Include the CPU specific operations makefile, which provides default
|
||||
# values for all CPU errata workarounds and CPU specific optimisations.
|
||||
# This can be overridden by the platform.
|
||||
include lib/cpus/cpu-ops.mk
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
NEED_BL32 := yes
|
||||
|
||||
################################################################################
|
||||
# Build `AARCH32_SP` as BL32 image for AArch32
|
||||
################################################################################
|
||||
ifneq (${AARCH32_SP},none)
|
||||
# We expect to locate an sp.mk under the specified AARCH32_SP directory
|
||||
AARCH32_SP_MAKE := $(wildcard bl32/${AARCH32_SP}/${AARCH32_SP}.mk)
|
||||
|
||||
ifeq (${AARCH32_SP_MAKE},)
|
||||
$(error Error: No bl32/${AARCH32_SP}/${AARCH32_SP}.mk located)
|
||||
endif
|
||||
|
||||
$(info Including ${AARCH32_SP_MAKE})
|
||||
include ${AARCH32_SP_MAKE}
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Check incompatible options
|
||||
################################################################################
|
||||
|
||||
ifdef EL3_PAYLOAD_BASE
|
||||
ifdef PRELOADED_BL33_BASE
|
||||
$(warning "PRELOADED_BL33_BASE and EL3_PAYLOAD_BASE are \
|
||||
incompatible build options. EL3_PAYLOAD_BASE has priority.")
|
||||
endif
|
||||
ifneq (${GENERATE_COT},0)
|
||||
$(error "GENERATE_COT and EL3_PAYLOAD_BASE are incompatible build options.")
|
||||
endif
|
||||
ifneq (${TRUSTED_BOARD_BOOT},0)
|
||||
$(error "TRUSTED_BOARD_BOOT and EL3_PAYLOAD_BASE are incompatible build options.")
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${NEED_BL33},yes)
|
||||
ifdef EL3_PAYLOAD_BASE
|
||||
$(warning "BL33 image is not needed when option \
|
||||
BL33_PAYLOAD_BASE is used and won't be added to the FIP file.")
|
||||
endif
|
||||
ifdef PRELOADED_BL33_BASE
|
||||
$(warning "BL33 image is not needed when option \
|
||||
PRELOADED_BL33_BASE is used and won't be added to the FIP \
|
||||
file.")
|
||||
endif
|
||||
endif
|
||||
|
||||
# For AArch32, LOAD_IMAGE_V2 must be enabled.
|
||||
ifeq (${ARCH},aarch32)
|
||||
ifeq (${LOAD_IMAGE_V2}, 0)
|
||||
$(error "For AArch32, LOAD_IMAGE_V2 must be enabled.")
|
||||
endif
|
||||
endif
|
||||
|
||||
# When building for systems with hardware-assisted coherency, there's no need to
|
||||
# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
|
||||
ifeq ($(HW_ASSISTED_COHERENCY)-$(USE_COHERENT_MEM),1-1)
|
||||
$(error USE_COHERENT_MEM cannot be enabled with HW_ASSISTED_COHERENCY)
|
||||
endif
|
||||
|
||||
ifneq ($(MULTI_CONSOLE_API), 0)
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error "Error: MULTI_CONSOLE_API is not supported for AArch32")
|
||||
endif
|
||||
endif
|
||||
|
||||
#For now, BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is 1.
|
||||
ifeq ($(BL2_AT_EL3)-$(BL2_IN_XIP_MEM),0-1)
|
||||
$(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled")
|
||||
endif
|
||||
|
||||
# SMC Calling Convention checks
|
||||
ifneq (${SMCCC_MAJOR_VERSION},1)
|
||||
ifneq (${SPD},none)
|
||||
$(error "SMC Calling Convention 1.X must be used with SPDs")
|
||||
endif
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error "Only SMCCC 1.X is supported in AArch32 mode.")
|
||||
endif
|
||||
endif
|
||||
|
||||
# For RAS_EXTENSION, require that EAs are handled in EL3 first
|
||||
ifeq ($(RAS_EXTENSION),1)
|
||||
ifneq ($(HANDLE_EA_EL3_FIRST),1)
|
||||
$(error For RAS_EXTENSION, HANDLE_EA_EL3_FIRST must also be 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
# When FAULT_INJECTION_SUPPORT is used, require that RAS_EXTENSION is enabled
|
||||
ifeq ($(FAULT_INJECTION_SUPPORT),1)
|
||||
ifneq ($(RAS_EXTENSION),1)
|
||||
$(error For FAULT_INJECTION_SUPPORT, RAS_EXTENSION must also be 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
# DYN_DISABLE_AUTH can be set only when TRUSTED_BOARD_BOOT=1 and LOAD_IMAGE_V2=1
|
||||
ifeq ($(DYN_DISABLE_AUTH), 1)
|
||||
ifeq (${TRUSTED_BOARD_BOOT}, 0)
|
||||
$(error "TRUSTED_BOARD_BOOT must be enabled for DYN_DISABLE_AUTH to be set.")
|
||||
endif
|
||||
ifeq (${LOAD_IMAGE_V2}, 0)
|
||||
$(error "DYN_DISABLE_AUTH is only supported for LOAD_IMAGE_V2.")
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Process platform overrideable behaviour
|
||||
################################################################################
|
||||
|
||||
# Using the ARM Trusted Firmware BL2 implies that a BL33 image also needs to be
|
||||
# supplied for the FIP and Certificate generation tools. This flag can be
|
||||
# overridden by the platform.
|
||||
ifdef BL2_SOURCES
|
||||
ifdef EL3_PAYLOAD_BASE
|
||||
# If booting an EL3 payload there is no need for a BL33 image
|
||||
# in the FIP file.
|
||||
NEED_BL33 := no
|
||||
else
|
||||
ifdef PRELOADED_BL33_BASE
|
||||
# If booting a BL33 preloaded image there is no need of
|
||||
# another one in the FIP file.
|
||||
NEED_BL33 := no
|
||||
else
|
||||
NEED_BL33 ?= yes
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# If SCP_BL2 is given, we always want FIP to include it.
|
||||
ifdef SCP_BL2
|
||||
NEED_SCP_BL2 := yes
|
||||
endif
|
||||
|
||||
# For AArch32, BL31 is not currently supported.
|
||||
ifneq (${ARCH},aarch32)
|
||||
ifdef BL31_SOURCES
|
||||
# When booting an EL3 payload, there is no need to compile the BL31 image nor
|
||||
# put it in the FIP.
|
||||
ifndef EL3_PAYLOAD_BASE
|
||||
NEED_BL31 := yes
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Process TBB related flags
|
||||
ifneq (${GENERATE_COT},0)
|
||||
# Common cert_create options
|
||||
ifneq (${CREATE_KEYS},0)
|
||||
$(eval CRT_ARGS += -n)
|
||||
$(eval FWU_CRT_ARGS += -n)
|
||||
ifneq (${SAVE_KEYS},0)
|
||||
$(eval CRT_ARGS += -k)
|
||||
$(eval FWU_CRT_ARGS += -k)
|
||||
endif
|
||||
endif
|
||||
# Include TBBR makefile (unless the platform indicates otherwise)
|
||||
ifeq (${INCLUDE_TBBR_MK},1)
|
||||
include make_helpers/tbbr/tbbr_tools.mk
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (${FIP_ALIGN},0)
|
||||
FIP_ARGS += --align ${FIP_ALIGN}
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Include libraries' Makefile that are used in all BL
|
||||
################################################################################
|
||||
|
||||
include lib/stack_protector/stack_protector.mk
|
||||
|
||||
################################################################################
|
||||
# Auxiliary tools (fiptool, cert_create, etc)
|
||||
################################################################################
|
||||
|
||||
# Variables for use with Certificate Generation Tool
|
||||
CRTTOOLPATH ?= tools/cert_create
|
||||
CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT}
|
||||
|
||||
# Variables for use with Firmware Image Package
|
||||
FIPTOOLPATH ?= tools/fiptool
|
||||
FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT}
|
||||
|
||||
################################################################################
|
||||
# Include BL specific makefiles
|
||||
################################################################################
|
||||
ifdef BL1_SOURCES
|
||||
NEED_BL1 := yes
|
||||
include bl1/bl1.mk
|
||||
endif
|
||||
|
||||
ifdef BL2_SOURCES
|
||||
NEED_BL2 := yes
|
||||
include bl2/bl2.mk
|
||||
endif
|
||||
|
||||
ifdef BL2U_SOURCES
|
||||
NEED_BL2U := yes
|
||||
include bl2u/bl2u.mk
|
||||
endif
|
||||
|
||||
ifeq (${NEED_BL31},yes)
|
||||
ifdef BL31_SOURCES
|
||||
include bl31/bl31.mk
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef FDT_SOURCES
|
||||
NEED_FDT := yes
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Build options checks
|
||||
################################################################################
|
||||
|
||||
$(eval $(call assert_boolean,COLD_BOOT_SINGLE_CPU))
|
||||
$(eval $(call assert_boolean,CREATE_KEYS))
|
||||
$(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS))
|
||||
$(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
|
||||
$(eval $(call assert_boolean,DEBUG))
|
||||
$(eval $(call assert_boolean,DISABLE_PEDANTIC))
|
||||
$(eval $(call assert_boolean,DYN_DISABLE_AUTH))
|
||||
$(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING))
|
||||
$(eval $(call assert_boolean,ENABLE_AMU))
|
||||
$(eval $(call assert_boolean,ENABLE_ASSERTIONS))
|
||||
$(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
|
||||
$(eval $(call assert_boolean,ENABLE_PMF))
|
||||
$(eval $(call assert_boolean,ENABLE_PSCI_STAT))
|
||||
$(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION))
|
||||
$(eval $(call assert_boolean,ENABLE_SPE_FOR_LOWER_ELS))
|
||||
$(eval $(call assert_boolean,ENABLE_SPM))
|
||||
$(eval $(call assert_boolean,ENABLE_SVE_FOR_NS))
|
||||
$(eval $(call assert_boolean,ERROR_DEPRECATED))
|
||||
$(eval $(call assert_boolean,FAULT_INJECTION_SUPPORT))
|
||||
$(eval $(call assert_boolean,GENERATE_COT))
|
||||
$(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
|
||||
$(eval $(call assert_boolean,HANDLE_EA_EL3_FIRST))
|
||||
$(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
|
||||
$(eval $(call assert_boolean,LOAD_IMAGE_V2))
|
||||
$(eval $(call assert_boolean,MULTI_CONSOLE_API))
|
||||
$(eval $(call assert_boolean,NS_TIMER_SWITCH))
|
||||
$(eval $(call assert_boolean,PL011_GENERIC_UART))
|
||||
$(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
|
||||
$(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
|
||||
$(eval $(call assert_boolean,RAS_EXTENSION))
|
||||
$(eval $(call assert_boolean,RESET_TO_BL31))
|
||||
$(eval $(call assert_boolean,SAVE_KEYS))
|
||||
$(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA))
|
||||
$(eval $(call assert_boolean,SPIN_ON_BL1_EXIT))
|
||||
$(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
|
||||
$(eval $(call assert_boolean,USE_COHERENT_MEM))
|
||||
$(eval $(call assert_boolean,USE_TBBR_DEFS))
|
||||
$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
|
||||
$(eval $(call assert_boolean,BL2_AT_EL3))
|
||||
$(eval $(call assert_boolean,BL2_IN_XIP_MEM))
|
||||
|
||||
$(eval $(call assert_numeric,ARM_ARCH_MAJOR))
|
||||
$(eval $(call assert_numeric,ARM_ARCH_MINOR))
|
||||
$(eval $(call assert_numeric,SMCCC_MAJOR_VERSION))
|
||||
|
||||
################################################################################
|
||||
# Add definitions to the cpp preprocessor based on the current build options.
|
||||
# This is done after including the platform specific makefile to allow the
|
||||
# platform to overwrite the default options
|
||||
################################################################################
|
||||
|
||||
$(eval $(call add_define,ARM_ARCH_MAJOR))
|
||||
$(eval $(call add_define,ARM_ARCH_MINOR))
|
||||
$(eval $(call add_define,ARM_GIC_ARCH))
|
||||
$(eval $(call add_define,COLD_BOOT_SINGLE_CPU))
|
||||
$(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS))
|
||||
$(eval $(call add_define,CTX_INCLUDE_FPREGS))
|
||||
$(eval $(call add_define,EL3_EXCEPTION_HANDLING))
|
||||
$(eval $(call add_define,ENABLE_AMU))
|
||||
$(eval $(call add_define,ENABLE_ASSERTIONS))
|
||||
$(eval $(call add_define,ENABLE_PLAT_COMPAT))
|
||||
$(eval $(call add_define,ENABLE_PMF))
|
||||
$(eval $(call add_define,ENABLE_PSCI_STAT))
|
||||
$(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
|
||||
$(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
|
||||
$(eval $(call add_define,ENABLE_SPM))
|
||||
$(eval $(call add_define,ENABLE_SVE_FOR_NS))
|
||||
$(eval $(call add_define,ERROR_DEPRECATED))
|
||||
$(eval $(call add_define,FAULT_INJECTION_SUPPORT))
|
||||
$(eval $(call add_define,GICV2_G0_FOR_EL3))
|
||||
$(eval $(call add_define,HANDLE_EA_EL3_FIRST))
|
||||
$(eval $(call add_define,HW_ASSISTED_COHERENCY))
|
||||
$(eval $(call add_define,LOAD_IMAGE_V2))
|
||||
$(eval $(call add_define,LOG_LEVEL))
|
||||
$(eval $(call add_define,MULTI_CONSOLE_API))
|
||||
$(eval $(call add_define,NS_TIMER_SWITCH))
|
||||
$(eval $(call add_define,PL011_GENERIC_UART))
|
||||
$(eval $(call add_define,PLAT_${PLAT}))
|
||||
$(eval $(call add_define,PROGRAMMABLE_RESET_ADDRESS))
|
||||
$(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
|
||||
$(eval $(call add_define,RAS_EXTENSION))
|
||||
$(eval $(call add_define,RESET_TO_BL31))
|
||||
$(eval $(call add_define,SEPARATE_CODE_AND_RODATA))
|
||||
$(eval $(call add_define,SMCCC_MAJOR_VERSION))
|
||||
$(eval $(call add_define,SPD_${SPD}))
|
||||
$(eval $(call add_define,SPIN_ON_BL1_EXIT))
|
||||
$(eval $(call add_define,TRUSTED_BOARD_BOOT))
|
||||
$(eval $(call add_define,USE_COHERENT_MEM))
|
||||
$(eval $(call add_define,USE_TBBR_DEFS))
|
||||
$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
|
||||
$(eval $(call add_define,BL2_AT_EL3))
|
||||
$(eval $(call add_define,BL2_IN_XIP_MEM))
|
||||
|
||||
# Define the EL3_PAYLOAD_BASE flag only if it is provided.
|
||||
ifdef EL3_PAYLOAD_BASE
|
||||
$(eval $(call add_define,EL3_PAYLOAD_BASE))
|
||||
else
|
||||
# Define the PRELOADED_BL33_BASE flag only if it is provided and
|
||||
# EL3_PAYLOAD_BASE is not defined, as it has priority.
|
||||
ifdef PRELOADED_BL33_BASE
|
||||
$(eval $(call add_define,PRELOADED_BL33_BASE))
|
||||
endif
|
||||
endif
|
||||
# Define the AARCH32/AARCH64 flag based on the ARCH flag
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(eval $(call add_define,AARCH32))
|
||||
else
|
||||
$(eval $(call add_define,AARCH64))
|
||||
endif
|
||||
|
||||
# Define the DYN_DISABLE_AUTH flag only if set.
|
||||
ifeq (${DYN_DISABLE_AUTH},1)
|
||||
$(eval $(call add_define,DYN_DISABLE_AUTH))
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Build targets
|
||||
################################################################################
|
||||
|
||||
.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool dtbs
|
||||
.SUFFIXES:
|
||||
|
||||
all: msg_start
|
||||
|
||||
msg_start:
|
||||
@echo "Building ${PLAT}"
|
||||
|
||||
# Check if deprecated declarations and cpp warnings should be treated as error or not.
|
||||
ifeq (${ERROR_DEPRECATED},0)
|
||||
CPPFLAGS += -Wno-error=deprecated-declarations -Wno-error=cpp
|
||||
endif
|
||||
|
||||
# Expand build macros for the different images
|
||||
ifeq (${NEED_BL1},yes)
|
||||
$(eval $(call MAKE_BL,1))
|
||||
endif
|
||||
|
||||
ifeq (${NEED_BL2},yes)
|
||||
ifeq (${BL2_AT_EL3}, 0)
|
||||
FIP_BL2_ARGS := tb-fw
|
||||
endif
|
||||
|
||||
$(if ${BL2}, $(eval $(call TOOL_ADD_IMG,bl2,--${FIP_BL2_ARGS})),\
|
||||
$(eval $(call MAKE_BL,2,${FIP_BL2_ARGS})))
|
||||
endif
|
||||
|
||||
ifeq (${NEED_SCP_BL2},yes)
|
||||
$(eval $(call TOOL_ADD_IMG,scp_bl2,--scp-fw))
|
||||
endif
|
||||
|
||||
ifeq (${NEED_BL31},yes)
|
||||
BL31_SOURCES += ${SPD_SOURCES}
|
||||
$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\
|
||||
$(eval $(call MAKE_BL,31,soc-fw)))
|
||||
endif
|
||||
|
||||
# If a BL32 image is needed but neither BL32 nor BL32_SOURCES is defined, the
|
||||
# build system will call TOOL_ADD_IMG to print a warning message and abort the
|
||||
# process. Note that the dependency on BL32 applies to the FIP only.
|
||||
ifeq (${NEED_BL32},yes)
|
||||
|
||||
BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1))
|
||||
|
||||
$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw)),\
|
||||
$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw)))
|
||||
endif
|
||||
|
||||
# Add the BL33 image if required by the platform
|
||||
ifeq (${NEED_BL33},yes)
|
||||
$(eval $(call TOOL_ADD_IMG,bl33,--nt-fw))
|
||||
endif
|
||||
|
||||
ifeq (${NEED_BL2U},yes)
|
||||
$(if ${BL2U}, $(eval $(call TOOL_ADD_IMG,bl2u,--ap-fwu-cfg,FWU_)),\
|
||||
$(eval $(call MAKE_BL,2u,ap-fwu-cfg,FWU_)))
|
||||
endif
|
||||
|
||||
# Expand build macros for the different images
|
||||
ifeq (${NEED_FDT},yes)
|
||||
$(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES)))
|
||||
endif
|
||||
|
||||
locate-checkpatch:
|
||||
ifndef CHECKPATCH
|
||||
$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl")
|
||||
else
|
||||
ifeq (,$(wildcard ${CHECKPATCH}))
|
||||
$(error "The file CHECKPATCH points to cannot be found, use eg: CHECKPATCH=../linux/scripts/checkpatch.pl")
|
||||
endif
|
||||
endif
|
||||
|
||||
clean:
|
||||
@echo " CLEAN"
|
||||
$(call SHELL_REMOVE_DIR,${BUILD_PLAT})
|
||||
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
|
||||
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
|
||||
|
||||
realclean distclean:
|
||||
@echo " REALCLEAN"
|
||||
$(call SHELL_REMOVE_DIR,${BUILD_BASE})
|
||||
$(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*)
|
||||
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
|
||||
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
|
||||
|
||||
checkcodebase: locate-checkpatch
|
||||
@echo " CHECKING STYLE"
|
||||
@if test -d .git ; then \
|
||||
git ls-files | grep -E -v 'libfdt|stdlib|docs|\.md' | \
|
||||
while read GIT_FILE ; \
|
||||
do ${CHECKPATCH} ${CHECKCODE_ARGS} -f $$GIT_FILE ; \
|
||||
done ; \
|
||||
else \
|
||||
find . -type f -not -iwholename "*.git*" \
|
||||
-not -iwholename "*build*" \
|
||||
-not -iwholename "*libfdt*" \
|
||||
-not -iwholename "*stdlib*" \
|
||||
-not -iwholename "*docs*" \
|
||||
-not -iwholename "*.md" \
|
||||
-exec ${CHECKPATCH} ${CHECKCODE_ARGS} -f {} \; ; \
|
||||
fi
|
||||
|
||||
checkpatch: locate-checkpatch
|
||||
@echo " CHECKING STYLE"
|
||||
${Q}COMMON_COMMIT=$$(git merge-base HEAD ${BASE_COMMIT}); \
|
||||
for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \
|
||||
printf "\n[*] Checking style of '$$commit'\n\n"; \
|
||||
git log --format=email "$$commit~..$$commit" \
|
||||
-- ${CHECK_PATHS} | ${CHECKPATCH} - || true; \
|
||||
git diff --format=email "$$commit~..$$commit" \
|
||||
-- ${CHECK_PATHS} | ${CHECKPATCH} - || true; \
|
||||
done
|
||||
|
||||
certtool: ${CRTTOOL}
|
||||
|
||||
.PHONY: ${CRTTOOL}
|
||||
${CRTTOOL}:
|
||||
${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} --no-print-directory -C ${CRTTOOLPATH}
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@${ECHO_BLANK_LINE}
|
||||
|
||||
ifneq (${GENERATE_COT},0)
|
||||
certificates: ${CRT_DEPS} ${CRTTOOL}
|
||||
${Q}${CRTTOOL} ${CRT_ARGS}
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@echo "Certificates can be found in ${BUILD_PLAT}"
|
||||
@${ECHO_BLANK_LINE}
|
||||
endif
|
||||
|
||||
${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL}
|
||||
${Q}${FIPTOOL} create ${FIP_ARGS} $@
|
||||
${Q}${FIPTOOL} info $@
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@${ECHO_BLANK_LINE}
|
||||
|
||||
ifneq (${GENERATE_COT},0)
|
||||
fwu_certificates: ${FWU_CRT_DEPS} ${CRTTOOL}
|
||||
${Q}${CRTTOOL} ${FWU_CRT_ARGS}
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@echo "FWU certificates can be found in ${BUILD_PLAT}"
|
||||
@${ECHO_BLANK_LINE}
|
||||
endif
|
||||
|
||||
${BUILD_PLAT}/${FWU_FIP_NAME}: ${FWU_FIP_DEPS} ${FIPTOOL}
|
||||
${Q}${FIPTOOL} create ${FWU_FIP_ARGS} $@
|
||||
${Q}${FIPTOOL} info $@
|
||||
@${ECHO_BLANK_LINE}
|
||||
@echo "Built $@ successfully"
|
||||
@${ECHO_BLANK_LINE}
|
||||
|
||||
fiptool: ${FIPTOOL}
|
||||
fip: ${BUILD_PLAT}/${FIP_NAME}
|
||||
fwu_fip: ${BUILD_PLAT}/${FWU_FIP_NAME}
|
||||
|
||||
.PHONY: ${FIPTOOL}
|
||||
${FIPTOOL}:
|
||||
${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${FIPTOOLPATH}
|
||||
|
||||
cscope:
|
||||
@echo " CSCOPE"
|
||||
${Q}find ${CURDIR} -name "*.[chsS]" > cscope.files
|
||||
${Q}cscope -b -q -k
|
||||
|
||||
help:
|
||||
@echo "usage: ${MAKE} PLAT=<${PLATFORM_LIST}> [OPTIONS] [TARGET]"
|
||||
@echo ""
|
||||
@echo "PLAT is used to specify which platform you wish to build."
|
||||
@echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}"
|
||||
@echo ""
|
||||
@echo "Please refer to the User Guide for a list of all supported options."
|
||||
@echo "Note that the build system doesn't track dependencies for build "
|
||||
@echo "options. Therefore, if any of the build options are changed "
|
||||
@echo "from a previous build, a clean build must be performed."
|
||||
@echo ""
|
||||
@echo "Supported Targets:"
|
||||
@echo " all Build all individual bootloader binaries"
|
||||
@echo " bl1 Build the BL1 binary"
|
||||
@echo " bl2 Build the BL2 binary"
|
||||
@echo " bl2u Build the BL2U binary"
|
||||
@echo " bl31 Build the BL31 binary"
|
||||
@echo " bl32 Build the BL32 binary. If ARCH=aarch32, then "
|
||||
@echo " this builds secure payload specified by AARCH32_SP"
|
||||
@echo " certificates Build the certificates (requires 'GENERATE_COT=1')"
|
||||
@echo " fip Build the Firmware Image Package (FIP)"
|
||||
@echo " fwu_fip Build the FWU Firmware Image Package (FIP)"
|
||||
@echo " checkcodebase Check the coding style of the entire source tree"
|
||||
@echo " checkpatch Check the coding style on changes in the current"
|
||||
@echo " branch against BASE_COMMIT (default origin/master)"
|
||||
@echo " clean Clean the build for the selected platform"
|
||||
@echo " cscope Generate cscope index"
|
||||
@echo " distclean Remove all build artifacts for all platforms"
|
||||
@echo " certtool Build the Certificate generation tool"
|
||||
@echo " fiptool Build the Firmware Image Package (FIP) creation tool"
|
||||
@echo " dtbs Build the Device Tree Blobs (if required for the platform)"
|
||||
@echo ""
|
||||
@echo "Note: most build targets require PLAT to be set to a specific platform."
|
||||
@echo ""
|
||||
@echo "example: build all targets for the FVP platform:"
|
||||
@echo " CROSS_COMPILE=aarch64-none-elf- make PLAT=fvp all"
|
||||
18
firmware/coreboot/3rdparty/arm-trusted-firmware/acknowledgements.rst
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Contributor Acknowledgements
|
||||
============================
|
||||
|
||||
Companies
|
||||
---------
|
||||
|
||||
Linaro Limited
|
||||
|
||||
NVIDIA Corporation
|
||||
|
||||
Socionext Inc.
|
||||
|
||||
Xilinx, Inc.
|
||||
|
||||
NXP Semiconductors
|
||||
|
||||
Individuals
|
||||
-----------
|
||||
15
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "../bl1_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* TODO: Function that does the first bit of architectural setup.
|
||||
******************************************************************************/
|
||||
void bl1_arch_setup(void)
|
||||
{
|
||||
|
||||
}
|
||||
177
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <context.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <smccc_helpers.h>
|
||||
#include "../bl1_private.h"
|
||||
|
||||
/*
|
||||
* Following arrays will be used for context management.
|
||||
* There are 2 instances, for the Secure and Non-Secure contexts.
|
||||
*/
|
||||
static cpu_context_t bl1_cpu_context[2];
|
||||
static smc_ctx_t bl1_smc_context[2];
|
||||
|
||||
/* Following contains the next cpu context pointer. */
|
||||
static void *bl1_next_cpu_context_ptr;
|
||||
|
||||
/* Following contains the next smc context pointer. */
|
||||
static void *bl1_next_smc_context_ptr;
|
||||
|
||||
/* Following functions are used for SMC context handling */
|
||||
void *smc_get_ctx(unsigned int security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
return &bl1_smc_context[security_state];
|
||||
}
|
||||
|
||||
void smc_set_next_ctx(unsigned int security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
bl1_next_smc_context_ptr = &bl1_smc_context[security_state];
|
||||
}
|
||||
|
||||
void *smc_get_next_ctx(void)
|
||||
{
|
||||
return bl1_next_smc_context_ptr;
|
||||
}
|
||||
|
||||
/* Following functions are used for CPU context handling */
|
||||
void *cm_get_context(uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
return &bl1_cpu_context[security_state];
|
||||
}
|
||||
|
||||
void cm_set_next_context(void *cpu_context)
|
||||
{
|
||||
assert(cpu_context);
|
||||
bl1_next_cpu_context_ptr = cpu_context;
|
||||
}
|
||||
|
||||
void *cm_get_next_context(void)
|
||||
{
|
||||
return bl1_next_cpu_context_ptr;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Following function copies GP regs r0-r4, lr and spsr,
|
||||
* from the CPU context to the SMC context structures.
|
||||
******************************************************************************/
|
||||
static void copy_cpu_ctx_to_smc_ctx(const regs_t *cpu_reg_ctx,
|
||||
smc_ctx_t *next_smc_ctx)
|
||||
{
|
||||
next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0);
|
||||
next_smc_ctx->r1 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R1);
|
||||
next_smc_ctx->r2 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R2);
|
||||
next_smc_ctx->r3 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R3);
|
||||
next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR);
|
||||
next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR);
|
||||
next_smc_ctx->scr = read_ctx_reg(cpu_reg_ctx, CTX_SCR);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Following function flushes the SMC & CPU context pointer and its data.
|
||||
******************************************************************************/
|
||||
static void flush_smc_and_cpu_ctx(void)
|
||||
{
|
||||
flush_dcache_range((uintptr_t)&bl1_next_smc_context_ptr,
|
||||
sizeof(bl1_next_smc_context_ptr));
|
||||
flush_dcache_range((uintptr_t)bl1_next_smc_context_ptr,
|
||||
sizeof(smc_ctx_t));
|
||||
|
||||
flush_dcache_range((uintptr_t)&bl1_next_cpu_context_ptr,
|
||||
sizeof(bl1_next_cpu_context_ptr));
|
||||
flush_dcache_range((uintptr_t)bl1_next_cpu_context_ptr,
|
||||
sizeof(cpu_context_t));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function prepares the context for Secure/Normal world images.
|
||||
* Normal world images are transitioned to HYP(if supported) else SVC.
|
||||
******************************************************************************/
|
||||
void bl1_prepare_next_image(unsigned int image_id)
|
||||
{
|
||||
unsigned int security_state;
|
||||
image_desc_t *image_desc;
|
||||
entry_point_info_t *next_bl_ep;
|
||||
|
||||
/* Get the image descriptor. */
|
||||
image_desc = bl1_plat_get_image_desc(image_id);
|
||||
assert(image_desc);
|
||||
|
||||
/* Get the entry point info. */
|
||||
next_bl_ep = &image_desc->ep_info;
|
||||
|
||||
/* Get the image security state. */
|
||||
security_state = GET_SECURITY_STATE(next_bl_ep->h.attr);
|
||||
|
||||
/* Prepare the SPSR for the next BL image. */
|
||||
if (security_state == SECURE) {
|
||||
next_bl_ep->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
|
||||
SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
|
||||
} else {
|
||||
/* Use HYP mode if supported else use SVC. */
|
||||
if (GET_VIRT_EXT(read_id_pfr1())) {
|
||||
next_bl_ep->spsr = SPSR_MODE32(MODE32_hyp, SPSR_T_ARM,
|
||||
SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
|
||||
} else {
|
||||
next_bl_ep->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
|
||||
SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow platform to make change */
|
||||
bl1_plat_set_ep_info(image_id, next_bl_ep);
|
||||
|
||||
/* Prepare the cpu context for the next BL image. */
|
||||
cm_init_my_context(next_bl_ep);
|
||||
cm_prepare_el3_exit(security_state);
|
||||
cm_set_next_context(cm_get_context(security_state));
|
||||
|
||||
/* Prepare the smc context for the next BL image. */
|
||||
smc_set_next_ctx(security_state);
|
||||
copy_cpu_ctx_to_smc_ctx(get_regs_ctx(cm_get_next_context()),
|
||||
smc_get_next_ctx());
|
||||
|
||||
/*
|
||||
* If the next image is non-secure, then we need to program the banked
|
||||
* non secure sctlr. This is not required when the next image is secure
|
||||
* because in AArch32, we expect the secure world to have the same
|
||||
* SCTLR settings.
|
||||
*/
|
||||
if (security_state == NON_SECURE) {
|
||||
cpu_context_t *ctx = cm_get_context(security_state);
|
||||
u_register_t ns_sctlr;
|
||||
|
||||
/* Temporarily set the NS bit to access NS SCTLR */
|
||||
write_scr(read_scr() | SCR_NS_BIT);
|
||||
isb();
|
||||
|
||||
ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR);
|
||||
write_sctlr(ns_sctlr);
|
||||
isb();
|
||||
|
||||
write_scr(read_scr() & ~SCR_NS_BIT);
|
||||
isb();
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush the SMC & CPU context and the (next)pointers,
|
||||
* to access them after caches are disabled.
|
||||
*/
|
||||
flush_smc_and_cpu_ctx();
|
||||
|
||||
/* Indicate that image is in execution state. */
|
||||
image_desc->state = IMAGE_STATE_EXECUTED;
|
||||
|
||||
print_entry_point_info(next_bl_ep);
|
||||
}
|
||||
100
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
#include <context.h>
|
||||
#include <el3_common_macros.S>
|
||||
#include <smccc_helpers.h>
|
||||
#include <smccc_macros.S>
|
||||
|
||||
.globl bl1_vector_table
|
||||
.globl bl1_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Setup the vector table to support SVC & MON mode.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_base bl1_vector_table
|
||||
b bl1_entrypoint
|
||||
b report_exception /* Undef */
|
||||
b bl1_aarch32_smc_handler /* SMC call */
|
||||
b report_exception /* Prefetch abort */
|
||||
b report_exception /* Data abort */
|
||||
b report_exception /* Reserved */
|
||||
b report_exception /* IRQ */
|
||||
b report_exception /* FIQ */
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* bl1_entrypoint() is the entry point into the trusted
|
||||
* firmware code when a cpu is released from warm or
|
||||
* cold reset.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
func bl1_entrypoint
|
||||
/* ---------------------------------------------------------------------
|
||||
* If the reset address is programmable then bl1_entrypoint() is
|
||||
* executed only on the cold boot path. Therefore, we can skip the warm
|
||||
* boot mailbox mechanism.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=1 \
|
||||
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
|
||||
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
|
||||
_init_memory=1 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=bl1_vector_table
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Perform early platform setup & platform
|
||||
* specific early arch. setup e.g. mmu setup
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
bl bl1_early_platform_setup
|
||||
bl bl1_plat_arch_setup
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Jump to main function.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
bl bl1_main
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Jump to next image.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get the smc_context for next BL image,
|
||||
* program the gp/system registers and save it in `r4`.
|
||||
*/
|
||||
bl smc_get_next_ctx
|
||||
mov r4, r0
|
||||
|
||||
/* Only turn-off MMU if going to secure world */
|
||||
ldr r5, [r4, #SMC_CTX_SCR]
|
||||
tst r5, #SCR_NS_BIT
|
||||
bne skip_mmu_off
|
||||
|
||||
/*
|
||||
* MMU needs to be disabled because both BL1 and BL2/BL2U execute
|
||||
* in PL1, and therefore share the same address space.
|
||||
* BL2/BL2U will initialize the address space according to its
|
||||
* own requirement.
|
||||
*/
|
||||
bl disable_mmu_icache_secure
|
||||
stcopr r0, TLBIALL
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
skip_mmu_off:
|
||||
/* Restore smc_context from `r4` and exit secure monitor mode. */
|
||||
mov r0, r4
|
||||
monitor_exit
|
||||
endfunc bl1_entrypoint
|
||||
157
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl1.h>
|
||||
#include <bl_common.h>
|
||||
#include <context.h>
|
||||
#include <smccc_helpers.h>
|
||||
#include <smccc_macros.S>
|
||||
#include <xlat_tables.h>
|
||||
|
||||
.globl bl1_aarch32_smc_handler
|
||||
|
||||
|
||||
func bl1_aarch32_smc_handler
|
||||
/* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */
|
||||
str lr, [sp, #SMC_CTX_LR_MON]
|
||||
|
||||
/* ------------------------------------------------
|
||||
* SMC in BL1 is handled assuming that the MMU is
|
||||
* turned off by BL2.
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Detect if this is a RUN_IMAGE or other SMC.
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
mov lr, #BL1_SMC_RUN_IMAGE
|
||||
cmp lr, r0
|
||||
bne smc_handler
|
||||
|
||||
/* ------------------------------------------------
|
||||
* Make sure only Secure world reaches here.
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
ldcopr r8, SCR
|
||||
tst r8, #SCR_NS_BIT
|
||||
blne report_exception
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Pass control to next secure image.
|
||||
* Here it expects r1 to contain the address of a entry_point_info_t
|
||||
* structure describing the BL entrypoint.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov r8, r1
|
||||
mov r0, r1
|
||||
bl bl1_print_next_bl_ep_info
|
||||
|
||||
#if SPIN_ON_BL1_EXIT
|
||||
bl print_debug_loop_message
|
||||
debug_loop:
|
||||
b debug_loop
|
||||
#endif
|
||||
|
||||
mov r0, r8
|
||||
bl bl1_plat_prepare_exit
|
||||
|
||||
stcopr r0, TLBIALL
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
/*
|
||||
* Extract PC and SPSR based on struct `entry_point_info_t`
|
||||
* and load it in LR and SPSR registers respectively.
|
||||
*/
|
||||
ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
|
||||
ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
|
||||
msr spsr, r1
|
||||
|
||||
/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
|
||||
cps #MODE32_svc
|
||||
ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
|
||||
cps #MODE32_mon
|
||||
|
||||
add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
|
||||
ldm r8, {r0, r1, r2, r3}
|
||||
eret
|
||||
endfunc bl1_aarch32_smc_handler
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Save Secure/Normal world context and jump to
|
||||
* BL1 SMC handler.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func smc_handler
|
||||
/* -----------------------------------------------------
|
||||
* Save the GP registers.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
smccc_save_gp_mode_regs
|
||||
|
||||
/*
|
||||
* `sp` still points to `smc_ctx_t`. Save it to a register
|
||||
* and restore the C runtime stack pointer to `sp`.
|
||||
*/
|
||||
mov r6, sp
|
||||
ldr sp, [r6, #SMC_CTX_SP_MON]
|
||||
|
||||
ldr r0, [r6, #SMC_CTX_SCR]
|
||||
and r7, r0, #SCR_NS_BIT /* flags */
|
||||
|
||||
/* Switch to Secure Mode */
|
||||
bic r0, #SCR_NS_BIT
|
||||
stcopr r0, SCR
|
||||
isb
|
||||
|
||||
/* If caller is from Secure world then turn on the MMU */
|
||||
tst r7, #SCR_NS_BIT
|
||||
bne skip_mmu_on
|
||||
|
||||
/* Turn on the MMU */
|
||||
mov r0, #DISABLE_DCACHE
|
||||
bl enable_mmu_secure
|
||||
|
||||
/* Enable the data cache. */
|
||||
ldcopr r9, SCTLR
|
||||
orr r9, r9, #SCTLR_C_BIT
|
||||
stcopr r9, SCTLR
|
||||
isb
|
||||
|
||||
skip_mmu_on:
|
||||
/* Prepare arguments for BL1 SMC wrapper. */
|
||||
ldr r0, [r6, #SMC_CTX_GPREG_R0] /* smc_fid */
|
||||
mov r1, #0 /* cookie */
|
||||
mov r2, r6 /* handle */
|
||||
mov r3, r7 /* flags */
|
||||
bl bl1_smc_wrapper
|
||||
|
||||
/* Get the smc_context for next BL image */
|
||||
bl smc_get_next_ctx
|
||||
mov r4, r0
|
||||
|
||||
/* Only turn-off MMU if going to secure world */
|
||||
ldr r5, [r4, #SMC_CTX_SCR]
|
||||
tst r5, #SCR_NS_BIT
|
||||
bne skip_mmu_off
|
||||
|
||||
/* Disable the MMU */
|
||||
bl disable_mmu_icache_secure
|
||||
stcopr r0, TLBIALL
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
skip_mmu_off:
|
||||
/* -----------------------------------------------------
|
||||
* Do the transition to next BL image.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
mov r0, r4
|
||||
monitor_exit
|
||||
endfunc smc_handler
|
||||
35
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include "../bl1_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that does the first bit of architectural setup that affects
|
||||
* execution in the non-secure address space.
|
||||
******************************************************************************/
|
||||
void bl1_arch_setup(void)
|
||||
{
|
||||
/* Set the next EL to be AArch64 */
|
||||
write_scr_el3(read_scr_el3() | SCR_RW_BIT);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Set the Secure EL1 required architectural state
|
||||
******************************************************************************/
|
||||
void bl1_arch_next_el_setup(void)
|
||||
{
|
||||
unsigned long next_sctlr;
|
||||
|
||||
/* Use the same endianness than the current BL */
|
||||
next_sctlr = (read_sctlr_el3() & SCTLR_EE_BIT);
|
||||
|
||||
/* Set SCTLR Secure EL1 */
|
||||
next_sctlr |= SCTLR_EL1_RES1;
|
||||
|
||||
write_sctlr_el1(next_sctlr);
|
||||
}
|
||||
99
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <context.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include "../bl1_private.h"
|
||||
|
||||
/*
|
||||
* Following array will be used for context management.
|
||||
* There are 2 instances, for the Secure and Non-Secure contexts.
|
||||
*/
|
||||
static cpu_context_t bl1_cpu_context[2];
|
||||
|
||||
/* Following contains the cpu context pointers. */
|
||||
static void *bl1_cpu_context_ptr[2];
|
||||
|
||||
|
||||
void *cm_get_context(uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
return bl1_cpu_context_ptr[security_state];
|
||||
}
|
||||
|
||||
void cm_set_context(void *context, uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
bl1_cpu_context_ptr[security_state] = context;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function prepares the context for Secure/Normal world images.
|
||||
* Normal world images are transitioned to EL2(if supported) else EL1.
|
||||
******************************************************************************/
|
||||
void bl1_prepare_next_image(unsigned int image_id)
|
||||
{
|
||||
unsigned int security_state;
|
||||
image_desc_t *image_desc;
|
||||
entry_point_info_t *next_bl_ep;
|
||||
|
||||
#if CTX_INCLUDE_AARCH32_REGS
|
||||
/*
|
||||
* Ensure that the build flag to save AArch32 system registers in CPU
|
||||
* context is not set for AArch64-only platforms.
|
||||
*/
|
||||
if (EL_IMPLEMENTED(1) == EL_IMPL_A64ONLY) {
|
||||
ERROR("EL1 supports AArch64-only. Please set build flag "
|
||||
"CTX_INCLUDE_AARCH32_REGS = 0");
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the image descriptor. */
|
||||
image_desc = bl1_plat_get_image_desc(image_id);
|
||||
assert(image_desc);
|
||||
|
||||
/* Get the entry point info. */
|
||||
next_bl_ep = &image_desc->ep_info;
|
||||
|
||||
/* Get the image security state. */
|
||||
security_state = GET_SECURITY_STATE(next_bl_ep->h.attr);
|
||||
|
||||
/* Setup the Secure/Non-Secure context if not done already. */
|
||||
if (!cm_get_context(security_state))
|
||||
cm_set_context(&bl1_cpu_context[security_state], security_state);
|
||||
|
||||
/* Prepare the SPSR for the next BL image. */
|
||||
if (security_state == SECURE) {
|
||||
next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
} else {
|
||||
/* Use EL2 if supported; else use EL1. */
|
||||
if (EL_IMPLEMENTED(2)) {
|
||||
next_bl_ep->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
} else {
|
||||
next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow platform to make change */
|
||||
bl1_plat_set_ep_info(image_id, next_bl_ep);
|
||||
|
||||
/* Prepare the context for the next BL image. */
|
||||
cm_init_my_context(next_bl_ep);
|
||||
cm_prepare_el3_exit(security_state);
|
||||
|
||||
/* Indicate that image is in execution state. */
|
||||
image_desc->state = IMAGE_STATE_EXECUTED;
|
||||
|
||||
print_entry_point_info(next_bl_ep);
|
||||
}
|
||||
58
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <el3_common_macros.S>
|
||||
|
||||
.globl bl1_entrypoint
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* bl1_entrypoint() is the entry point into the trusted
|
||||
* firmware code when a cpu is released from warm or
|
||||
* cold reset.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
func bl1_entrypoint
|
||||
/* ---------------------------------------------------------------------
|
||||
* If the reset address is programmable then bl1_entrypoint() is
|
||||
* executed only on the cold boot path. Therefore, we can skip the warm
|
||||
* boot mailbox mechanism.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=1 \
|
||||
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
|
||||
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
|
||||
_init_memory=1 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=bl1_exceptions
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Architectural init. can be generic e.g.
|
||||
* enabling stack alignment and platform spec-
|
||||
* ific e.g. MMU & page table setup as per the
|
||||
* platform memory map. Perform the latter here
|
||||
* and the former in bl1_main.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl1_early_platform_setup
|
||||
bl bl1_plat_arch_setup
|
||||
|
||||
/* --------------------------------------------------
|
||||
* Initialize platform and jump to our c-entry point
|
||||
* for this type of reset.
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
bl bl1_main
|
||||
|
||||
/* --------------------------------------------------
|
||||
* Do the transition to next boot image.
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
b el3_exit
|
||||
endfunc bl1_entrypoint
|
||||
277
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl1.h>
|
||||
#include <bl_common.h>
|
||||
#include <context.h>
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Very simple stackless exception handlers used by BL1.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
.globl bl1_exceptions
|
||||
|
||||
vector_base bl1_exceptions
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SP0 : 0x0 - 0x200
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSP0
|
||||
mov x0, #SYNC_EXCEPTION_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionSP0
|
||||
|
||||
vector_entry IrqSP0
|
||||
mov x0, #IRQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqSP0
|
||||
|
||||
vector_entry FiqSP0
|
||||
mov x0, #FIQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqSP0
|
||||
|
||||
vector_entry SErrorSP0
|
||||
mov x0, #SERROR_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorSP0
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SPx: 0x200 - 0x400
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSPx
|
||||
mov x0, #SYNC_EXCEPTION_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionSPx
|
||||
|
||||
vector_entry IrqSPx
|
||||
mov x0, #IRQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqSPx
|
||||
|
||||
vector_entry FiqSPx
|
||||
mov x0, #FIQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqSPx
|
||||
|
||||
vector_entry SErrorSPx
|
||||
mov x0, #SERROR_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorSPx
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch64 : 0x400 - 0x600
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionA64
|
||||
/* Enable the SError interrupt */
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
|
||||
/* Expect only SMC exceptions */
|
||||
mrs x30, esr_el3
|
||||
ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
|
||||
cmp x30, #EC_AARCH64_SMC
|
||||
b.ne unexpected_sync_exception
|
||||
|
||||
b smc_handler64
|
||||
check_vector_size SynchronousExceptionA64
|
||||
|
||||
vector_entry IrqA64
|
||||
mov x0, #IRQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqA64
|
||||
|
||||
vector_entry FiqA64
|
||||
mov x0, #FIQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqA64
|
||||
|
||||
vector_entry SErrorA64
|
||||
mov x0, #SERROR_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorA64
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch32 : 0x600 - 0x800
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionA32
|
||||
mov x0, #SYNC_EXCEPTION_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionA32
|
||||
|
||||
vector_entry IrqA32
|
||||
mov x0, #IRQ_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqA32
|
||||
|
||||
vector_entry FiqA32
|
||||
mov x0, #FIQ_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqA32
|
||||
|
||||
vector_entry SErrorA32
|
||||
mov x0, #SERROR_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorA32
|
||||
|
||||
|
||||
func smc_handler64
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Detect if this is a RUN_IMAGE or other SMC.
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
mov x30, #BL1_SMC_RUN_IMAGE
|
||||
cmp x30, x0
|
||||
b.ne smc_handler
|
||||
|
||||
/* ------------------------------------------------
|
||||
* Make sure only Secure world reaches here.
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
mrs x30, scr_el3
|
||||
tst x30, #SCR_NS_BIT
|
||||
b.ne unexpected_sync_exception
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Handling RUN_IMAGE SMC. First switch back to
|
||||
* SP_EL0 for the C runtime stack.
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
|
||||
msr spsel, #0
|
||||
mov sp, x30
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Pass EL3 control to next BL image.
|
||||
* Here it expects X1 with the address of a entry_point_info_t
|
||||
* structure describing the next BL image entrypoint.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov x20, x1
|
||||
|
||||
mov x0, x20
|
||||
bl bl1_print_next_bl_ep_info
|
||||
|
||||
ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
|
||||
msr elr_el3, x0
|
||||
msr spsr_el3, x1
|
||||
ubfx x0, x1, #MODE_EL_SHIFT, #2
|
||||
cmp x0, #MODE_EL3
|
||||
b.ne unexpected_sync_exception
|
||||
|
||||
bl disable_mmu_icache_el3
|
||||
tlbi alle3
|
||||
dsb ish /* ERET implies ISB, so it is not needed here */
|
||||
|
||||
#if SPIN_ON_BL1_EXIT
|
||||
bl print_debug_loop_message
|
||||
debug_loop:
|
||||
b debug_loop
|
||||
#endif
|
||||
|
||||
mov x0, x20
|
||||
bl bl1_plat_prepare_exit
|
||||
|
||||
ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
|
||||
ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
|
||||
ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
|
||||
ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
|
||||
eret
|
||||
endfunc smc_handler64
|
||||
|
||||
unexpected_sync_exception:
|
||||
mov x0, #SYNC_EXCEPTION_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Save Secure/Normal world context and jump to
|
||||
* BL1 SMC handler.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
smc_handler:
|
||||
/* -----------------------------------------------------
|
||||
* Save the GP registers x0-x29.
|
||||
* TODO: Revisit to store only SMCCC specified registers.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
bl save_gp_registers
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Populate the parameters for the SMC handler. We
|
||||
* already have x0-x4 in place. x5 will point to a
|
||||
* cookie (not used now). x6 will point to the context
|
||||
* structure (SP_EL3) and x7 will contain flags we need
|
||||
* to pass to the handler.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
mov x5, xzr
|
||||
mov x6, sp
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Restore the saved C runtime stack value which will
|
||||
* become the new SP_EL0 i.e. EL3 runtime stack. It was
|
||||
* saved in the 'cpu_context' structure prior to the last
|
||||
* ERET from EL3.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Switch back to SP_EL0 for the C runtime stack.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
msr spsel, #0
|
||||
mov sp, x12
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there
|
||||
* is a world switch during SMC handling.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
mrs x16, spsr_el3
|
||||
mrs x17, elr_el3
|
||||
mrs x18, scr_el3
|
||||
stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
|
||||
str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
|
||||
|
||||
/* Copy SCR_EL3.NS bit to the flag to indicate caller's security */
|
||||
bfi x7, x18, #0, #1
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Go to BL1 SMC handler.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
bl bl1_smc_handler
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Do the transition to next BL image.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
b el3_exit
|
||||
182
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/bl1.ld.S
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
||||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
||||
ENTRY(bl1_entrypoint)
|
||||
|
||||
MEMORY {
|
||||
ROM (rx): ORIGIN = BL1_RO_BASE, LENGTH = BL1_RO_LIMIT - BL1_RO_BASE
|
||||
RAM (rwx): ORIGIN = BL1_RW_BASE, LENGTH = BL1_RW_LIMIT - BL1_RW_BASE
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BL1_RO_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL1_RO_BASE address is not aligned on a page boundary.")
|
||||
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
.text . : {
|
||||
__TEXT_START__ = .;
|
||||
*bl1_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.vectors)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__TEXT_END__ = .;
|
||||
} >ROM
|
||||
|
||||
.rodata . : {
|
||||
__RODATA_START__ = .;
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PARSER_LIB_DESCS_START__ = .;
|
||||
KEEP(*(.img_parser_lib_descs))
|
||||
__PARSER_LIB_DESCS_END__ = .;
|
||||
|
||||
/*
|
||||
* Ensure 8-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(8);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
/*
|
||||
* No need to pad out the .rodata section to a page boundary. Next is
|
||||
* the .data section, which can mapped in ROM with the same memory
|
||||
* attributes as the .rodata section.
|
||||
*/
|
||||
__RODATA_END__ = .;
|
||||
} >ROM
|
||||
#else
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
*bl1_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PARSER_LIB_DESCS_START__ = .;
|
||||
KEEP(*(.img_parser_lib_descs))
|
||||
__PARSER_LIB_DESCS_END__ = .;
|
||||
|
||||
/*
|
||||
* Ensure 8-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(8);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
*(.vectors)
|
||||
__RO_END__ = .;
|
||||
} >ROM
|
||||
#endif
|
||||
|
||||
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
|
||||
"cpu_ops not defined for this platform.")
|
||||
|
||||
. = BL1_RW_BASE;
|
||||
ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE),
|
||||
"BL1_RW_BASE address is not aligned on a page boundary.")
|
||||
|
||||
/*
|
||||
* The .data section gets copied from ROM to RAM at runtime.
|
||||
* Its LMA should be 16-byte aligned to allow efficient copying of 16-bytes
|
||||
* aligned regions in it.
|
||||
* Its VMA must be page-aligned as it marks the first read/write page.
|
||||
*
|
||||
* It must be placed at a lower address than the stacks if the stack
|
||||
* protector is enabled. Alternatively, the .data.stack_protector_canary
|
||||
* section can be placed independently of the main .data section.
|
||||
*/
|
||||
.data . : ALIGN(16) {
|
||||
__DATA_RAM_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_RAM_END__ = .;
|
||||
} >RAM AT>ROM
|
||||
|
||||
stacks . (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The .bss section gets initialised to 0 at runtime.
|
||||
* Its base address should be 16-byte aligned for better performance of the
|
||||
* zero-initialization code.
|
||||
*/
|
||||
.bss : ALIGN(16) {
|
||||
__BSS_START__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The xlat_table section is for full, aligned page tables (4K).
|
||||
* Removing them from .bss avoids forcing 4K alignment on
|
||||
* the .bss section. The tables are initialized to zero by the translation
|
||||
* tables library.
|
||||
*/
|
||||
xlat_table (NOLOAD) : {
|
||||
*(xlat_table)
|
||||
} >RAM
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/*
|
||||
* The base address of the coherent memory section must be page-aligned (4K)
|
||||
* to guarantee that the coherent data are stored on their own pages and
|
||||
* are not mixed with normal data. This is required to set up the correct
|
||||
* memory attributes for the coherent data page tables.
|
||||
*/
|
||||
coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
__COHERENT_RAM_START__ = .;
|
||||
*(tzfw_coherent_mem)
|
||||
__COHERENT_RAM_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked
|
||||
* as device memory. No other unexpected data must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__COHERENT_RAM_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
__BL1_RAM_START__ = ADDR(.data);
|
||||
__BL1_RAM_END__ = .;
|
||||
|
||||
__DATA_ROM_START__ = LOADADDR(.data);
|
||||
__DATA_SIZE__ = SIZEOF(.data);
|
||||
|
||||
/*
|
||||
* The .data section is the last PROGBITS section so its end marks the end
|
||||
* of BL1's actual content in Trusted ROM.
|
||||
*/
|
||||
__BL1_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__;
|
||||
ASSERT(__BL1_ROM_END__ <= BL1_RO_LIMIT,
|
||||
"BL1's ROM content has exceeded its limit.")
|
||||
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
__COHERENT_RAM_UNALIGNED_SIZE__ =
|
||||
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
|
||||
#endif
|
||||
|
||||
ASSERT(. <= BL1_RW_LIMIT, "BL1's RW section has exceeded its limit.")
|
||||
}
|
||||
29
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/bl1.mk
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
BL1_SOURCES += bl1/bl1_main.c \
|
||||
bl1/${ARCH}/bl1_arch_setup.c \
|
||||
bl1/${ARCH}/bl1_context_mgmt.c \
|
||||
bl1/${ARCH}/bl1_entrypoint.S \
|
||||
bl1/${ARCH}/bl1_exceptions.S \
|
||||
lib/cpus/${ARCH}/cpu_helpers.S \
|
||||
lib/cpus/errata_report.c \
|
||||
lib/el3_runtime/${ARCH}/context_mgmt.c \
|
||||
plat/common/plat_bl1_common.c \
|
||||
plat/common/${ARCH}/platform_up_stack.S \
|
||||
${MBEDTLS_COMMON_SOURCES} \
|
||||
${MBEDTLS_CRYPTO_SOURCES} \
|
||||
${MBEDTLS_X509_SOURCES}
|
||||
|
||||
ifeq (${ARCH},aarch64)
|
||||
BL1_SOURCES += lib/el3_runtime/aarch64/context.S
|
||||
endif
|
||||
|
||||
ifeq (${TRUSTED_BOARD_BOOT},1)
|
||||
BL1_SOURCES += bl1/bl1_fwu.c
|
||||
endif
|
||||
|
||||
BL1_LINKERFILE := bl1/bl1.ld.S
|
||||
755
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/bl1_fwu.c
vendored
Normal file
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl1.h>
|
||||
#include <bl_common.h>
|
||||
#include <context.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <smccc_helpers.h>
|
||||
#include <string.h>
|
||||
#include <utils.h>
|
||||
#include "bl1_private.h"
|
||||
|
||||
/*
|
||||
* Function declarations.
|
||||
*/
|
||||
static int bl1_fwu_image_copy(unsigned int image_id,
|
||||
uintptr_t image_src,
|
||||
unsigned int block_size,
|
||||
unsigned int image_size,
|
||||
unsigned int flags);
|
||||
static int bl1_fwu_image_auth(unsigned int image_id,
|
||||
uintptr_t image_src,
|
||||
unsigned int image_size,
|
||||
unsigned int flags);
|
||||
static int bl1_fwu_image_execute(unsigned int image_id,
|
||||
void **handle,
|
||||
unsigned int flags);
|
||||
static register_t bl1_fwu_image_resume(register_t image_param,
|
||||
void **handle,
|
||||
unsigned int flags);
|
||||
static int bl1_fwu_sec_image_done(void **handle,
|
||||
unsigned int flags);
|
||||
static int bl1_fwu_image_reset(unsigned int image_id,
|
||||
unsigned int flags);
|
||||
__dead2 static void bl1_fwu_done(void *client_cookie, void *reserved);
|
||||
|
||||
/*
|
||||
* This keeps track of last executed secure image id.
|
||||
*/
|
||||
static unsigned int sec_exec_image_id = INVALID_IMAGE_ID;
|
||||
|
||||
/* Authentication status of each image. */
|
||||
extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
|
||||
|
||||
/*******************************************************************************
|
||||
* Top level handler for servicing FWU SMCs.
|
||||
******************************************************************************/
|
||||
register_t bl1_fwu_smc_handler(unsigned int smc_fid,
|
||||
register_t x1,
|
||||
register_t x2,
|
||||
register_t x3,
|
||||
register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
unsigned int flags)
|
||||
{
|
||||
|
||||
switch (smc_fid) {
|
||||
case FWU_SMC_IMAGE_COPY:
|
||||
SMC_RET1(handle, bl1_fwu_image_copy(x1, x2, x3, x4, flags));
|
||||
|
||||
case FWU_SMC_IMAGE_AUTH:
|
||||
SMC_RET1(handle, bl1_fwu_image_auth(x1, x2, x3, flags));
|
||||
|
||||
case FWU_SMC_IMAGE_EXECUTE:
|
||||
SMC_RET1(handle, bl1_fwu_image_execute(x1, &handle, flags));
|
||||
|
||||
case FWU_SMC_IMAGE_RESUME:
|
||||
SMC_RET1(handle, bl1_fwu_image_resume(x1, &handle, flags));
|
||||
|
||||
case FWU_SMC_SEC_IMAGE_DONE:
|
||||
SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags));
|
||||
|
||||
case FWU_SMC_IMAGE_RESET:
|
||||
SMC_RET1(handle, bl1_fwu_image_reset(x1, flags));
|
||||
|
||||
case FWU_SMC_UPDATE_DONE:
|
||||
bl1_fwu_done((void *)x1, NULL);
|
||||
/* We should never return from bl1_fwu_done() */
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Utility functions to keep track of the images that are loaded at any time.
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef PLAT_FWU_MAX_SIMULTANEOUS_IMAGES
|
||||
#define FWU_MAX_SIMULTANEOUS_IMAGES PLAT_FWU_MAX_SIMULTANEOUS_IMAGES
|
||||
#else
|
||||
#define FWU_MAX_SIMULTANEOUS_IMAGES 10
|
||||
#endif
|
||||
|
||||
static int bl1_fwu_loaded_ids[FWU_MAX_SIMULTANEOUS_IMAGES] = {
|
||||
[0 ... FWU_MAX_SIMULTANEOUS_IMAGES-1] = INVALID_IMAGE_ID
|
||||
};
|
||||
|
||||
/*
|
||||
* Adds an image_id to the bl1_fwu_loaded_ids array.
|
||||
* Returns 0 on success, 1 on error.
|
||||
*/
|
||||
static int bl1_fwu_add_loaded_id(int image_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check if the ID is already in the list */
|
||||
for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) {
|
||||
if (bl1_fwu_loaded_ids[i] == image_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find an empty slot */
|
||||
for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) {
|
||||
if (bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) {
|
||||
bl1_fwu_loaded_ids[i] = image_id;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes an image_id from the bl1_fwu_loaded_ids array.
|
||||
* Returns 0 on success, 1 on error.
|
||||
*/
|
||||
static int bl1_fwu_remove_loaded_id(int image_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Find the ID */
|
||||
for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) {
|
||||
if (bl1_fwu_loaded_ids[i] == image_id) {
|
||||
bl1_fwu_loaded_ids[i] = INVALID_IMAGE_ID;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function checks if the specified image overlaps another image already
|
||||
* loaded. It returns 0 if there is no overlap, a negative error code otherwise.
|
||||
******************************************************************************/
|
||||
static int bl1_fwu_image_check_overlaps(int image_id)
|
||||
{
|
||||
const image_desc_t *image_desc, *checked_image_desc;
|
||||
const image_info_t *info, *checked_info;
|
||||
|
||||
uintptr_t image_base, image_end;
|
||||
uintptr_t checked_image_base, checked_image_end;
|
||||
|
||||
checked_image_desc = bl1_plat_get_image_desc(image_id);
|
||||
checked_info = &checked_image_desc->image_info;
|
||||
|
||||
/* Image being checked mustn't be empty. */
|
||||
assert(checked_info->image_size != 0);
|
||||
|
||||
checked_image_base = checked_info->image_base;
|
||||
checked_image_end = checked_image_base + checked_info->image_size - 1;
|
||||
/* No need to check for overflows, it's done in bl1_fwu_image_copy(). */
|
||||
|
||||
for (int i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) {
|
||||
|
||||
/* Skip INVALID_IMAGE_IDs and don't check image against itself */
|
||||
if ((bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) ||
|
||||
(bl1_fwu_loaded_ids[i] == image_id))
|
||||
continue;
|
||||
|
||||
image_desc = bl1_plat_get_image_desc(bl1_fwu_loaded_ids[i]);
|
||||
|
||||
/* Only check images that are loaded or being loaded. */
|
||||
assert (image_desc && image_desc->state != IMAGE_STATE_RESET);
|
||||
|
||||
info = &image_desc->image_info;
|
||||
|
||||
/* There cannot be overlaps with an empty image. */
|
||||
if (info->image_size == 0)
|
||||
continue;
|
||||
|
||||
image_base = info->image_base;
|
||||
image_end = image_base + info->image_size - 1;
|
||||
/*
|
||||
* Overflows cannot happen. It is checked in
|
||||
* bl1_fwu_image_copy() when the image goes from RESET to
|
||||
* COPYING or COPIED.
|
||||
*/
|
||||
assert (image_end > image_base);
|
||||
|
||||
/* Check if there are overlaps. */
|
||||
if (!(image_end < checked_image_base ||
|
||||
checked_image_end < image_base)) {
|
||||
VERBOSE("Image with ID %d overlaps existing image with ID %d",
|
||||
checked_image_desc->image_id, image_desc->image_id);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible for copying secure images in AP Secure RAM.
|
||||
******************************************************************************/
|
||||
static int bl1_fwu_image_copy(unsigned int image_id,
|
||||
uintptr_t image_src,
|
||||
unsigned int block_size,
|
||||
unsigned int image_size,
|
||||
unsigned int flags)
|
||||
{
|
||||
uintptr_t dest_addr;
|
||||
unsigned int remaining;
|
||||
|
||||
/* Get the image descriptor. */
|
||||
image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
|
||||
if (!image_desc) {
|
||||
WARN("BL1-FWU: Invalid image ID %u\n", image_id);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The request must originate from a non-secure caller and target a
|
||||
* secure image. Any other scenario is invalid.
|
||||
*/
|
||||
if (GET_SECURITY_STATE(flags) == SECURE) {
|
||||
WARN("BL1-FWU: Copy not allowed from secure world.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
if (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE) {
|
||||
WARN("BL1-FWU: Copy not allowed for non-secure images.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* Check whether the FWU state machine is in the correct state. */
|
||||
if ((image_desc->state != IMAGE_STATE_RESET) &&
|
||||
(image_desc->state != IMAGE_STATE_COPYING)) {
|
||||
WARN("BL1-FWU: Copy not allowed at this point of the FWU"
|
||||
" process.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if ((!image_src) || (!block_size) ||
|
||||
check_uptr_overflow(image_src, block_size - 1)) {
|
||||
WARN("BL1-FWU: Copy not allowed due to invalid image source"
|
||||
" or block size\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (image_desc->state == IMAGE_STATE_COPYING) {
|
||||
/*
|
||||
* There must have been at least 1 copy operation for this image
|
||||
* previously.
|
||||
*/
|
||||
assert(image_desc->copied_size != 0);
|
||||
/*
|
||||
* The image size must have been recorded in the 1st copy
|
||||
* operation.
|
||||
*/
|
||||
image_size = image_desc->image_info.image_size;
|
||||
assert(image_size != 0);
|
||||
assert(image_desc->copied_size < image_size);
|
||||
|
||||
INFO("BL1-FWU: Continuing image copy in blocks\n");
|
||||
} else { /* image_desc->state == IMAGE_STATE_RESET */
|
||||
INFO("BL1-FWU: Initial call to copy an image\n");
|
||||
|
||||
/*
|
||||
* image_size is relevant only for the 1st copy request, it is
|
||||
* then ignored for subsequent calls for this image.
|
||||
*/
|
||||
if (!image_size) {
|
||||
WARN("BL1-FWU: Copy not allowed due to invalid image"
|
||||
" size\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if LOAD_IMAGE_V2
|
||||
/* Check that the image size to load is within limit */
|
||||
if (image_size > image_desc->image_info.image_max_size) {
|
||||
WARN("BL1-FWU: Image size out of bounds\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Check the image will fit into the free trusted RAM after BL1
|
||||
* load.
|
||||
*/
|
||||
const meminfo_t *mem_layout = bl1_plat_sec_mem_layout();
|
||||
if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
|
||||
image_desc->image_info.image_base,
|
||||
image_size)) {
|
||||
WARN("BL1-FWU: Copy not allowed due to insufficient"
|
||||
" resources.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Save the given image size. */
|
||||
image_desc->image_info.image_size = image_size;
|
||||
|
||||
/* Make sure the image doesn't overlap other images. */
|
||||
if (bl1_fwu_image_check_overlaps(image_id)) {
|
||||
image_desc->image_info.image_size = 0;
|
||||
WARN("BL1-FWU: This image overlaps another one\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* copied_size must be explicitly initialized here because the
|
||||
* FWU code doesn't necessarily do it when it resets the state
|
||||
* machine.
|
||||
*/
|
||||
image_desc->copied_size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the given block size is more than the total image size
|
||||
* then clip the former to the latter.
|
||||
*/
|
||||
remaining = image_size - image_desc->copied_size;
|
||||
if (block_size > remaining) {
|
||||
WARN("BL1-FWU: Block size is too big, clipping it.\n");
|
||||
block_size = remaining;
|
||||
}
|
||||
|
||||
/* Make sure the source image is mapped in memory. */
|
||||
if (bl1_plat_mem_check(image_src, block_size, flags)) {
|
||||
WARN("BL1-FWU: Source image is not mapped.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (bl1_fwu_add_loaded_id(image_id)) {
|
||||
WARN("BL1-FWU: Too many images loaded at the same time.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Allow the platform to handle pre-image load before copying */
|
||||
if (image_desc->state == IMAGE_STATE_RESET) {
|
||||
if (bl1_plat_handle_pre_image_load(image_id) != 0) {
|
||||
ERROR("BL1-FWU: Failure in pre-image load of image id %d\n",
|
||||
image_id);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Everything looks sane. Go ahead and copy the block of data. */
|
||||
dest_addr = image_desc->image_info.image_base + image_desc->copied_size;
|
||||
memcpy((void *) dest_addr, (const void *) image_src, block_size);
|
||||
flush_dcache_range(dest_addr, block_size);
|
||||
|
||||
image_desc->copied_size += block_size;
|
||||
image_desc->state = (block_size == remaining) ?
|
||||
IMAGE_STATE_COPIED : IMAGE_STATE_COPYING;
|
||||
|
||||
INFO("BL1-FWU: Copy operation successful.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible for authenticating Normal/Secure images.
|
||||
******************************************************************************/
|
||||
static int bl1_fwu_image_auth(unsigned int image_id,
|
||||
uintptr_t image_src,
|
||||
unsigned int image_size,
|
||||
unsigned int flags)
|
||||
{
|
||||
int result;
|
||||
uintptr_t base_addr;
|
||||
unsigned int total_size;
|
||||
|
||||
/* Get the image descriptor. */
|
||||
image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
|
||||
if (!image_desc)
|
||||
return -EPERM;
|
||||
|
||||
if (GET_SECURITY_STATE(flags) == SECURE) {
|
||||
if (image_desc->state != IMAGE_STATE_RESET) {
|
||||
WARN("BL1-FWU: Authentication from secure world "
|
||||
"while in invalid state\n");
|
||||
return -EPERM;
|
||||
}
|
||||
} else {
|
||||
if (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE) {
|
||||
if (image_desc->state != IMAGE_STATE_COPIED) {
|
||||
WARN("BL1-FWU: Authentication of secure image "
|
||||
"from non-secure world while not in copied state\n");
|
||||
return -EPERM;
|
||||
}
|
||||
} else {
|
||||
if (image_desc->state != IMAGE_STATE_RESET) {
|
||||
WARN("BL1-FWU: Authentication of non-secure image "
|
||||
"from non-secure world while in invalid state\n");
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (image_desc->state == IMAGE_STATE_COPIED) {
|
||||
/*
|
||||
* Image is in COPIED state.
|
||||
* Use the stored address and size.
|
||||
*/
|
||||
base_addr = image_desc->image_info.image_base;
|
||||
total_size = image_desc->image_info.image_size;
|
||||
} else {
|
||||
if ((!image_src) || (!image_size) ||
|
||||
check_uptr_overflow(image_src, image_size - 1)) {
|
||||
WARN("BL1-FWU: Auth not allowed due to invalid"
|
||||
" image source/size\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Image is in RESET state.
|
||||
* Check the parameters and authenticate the source image in place.
|
||||
*/
|
||||
if (bl1_plat_mem_check(image_src, image_size, \
|
||||
image_desc->ep_info.h.attr)) {
|
||||
WARN("BL1-FWU: Authentication arguments source/size not mapped\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (bl1_fwu_add_loaded_id(image_id)) {
|
||||
WARN("BL1-FWU: Too many images loaded at the same time.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
base_addr = image_src;
|
||||
total_size = image_size;
|
||||
|
||||
/* Update the image size in the descriptor. */
|
||||
image_desc->image_info.image_size = total_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticate the image.
|
||||
*/
|
||||
INFO("BL1-FWU: Authenticating image_id:%d\n", image_id);
|
||||
result = auth_mod_verify_img(image_id, (void *)base_addr, total_size);
|
||||
if (result != 0) {
|
||||
WARN("BL1-FWU: Authentication Failed err=%d\n", result);
|
||||
|
||||
/*
|
||||
* Authentication has failed.
|
||||
* Clear the memory if the image was copied.
|
||||
* This is to prevent an attack where this contains
|
||||
* some malicious code that can somehow be executed later.
|
||||
*/
|
||||
if (image_desc->state == IMAGE_STATE_COPIED) {
|
||||
/* Clear the memory.*/
|
||||
zero_normalmem((void *)base_addr, total_size);
|
||||
flush_dcache_range(base_addr, total_size);
|
||||
|
||||
/* Indicate that image can be copied again*/
|
||||
image_desc->state = IMAGE_STATE_RESET;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if this fails it's ok because the ID isn't in the array.
|
||||
* The image cannot be in RESET state here, it is checked at the
|
||||
* beginning of the function.
|
||||
*/
|
||||
bl1_fwu_remove_loaded_id(image_id);
|
||||
return -EAUTH;
|
||||
}
|
||||
|
||||
/* Indicate that image is in authenticated state. */
|
||||
image_desc->state = IMAGE_STATE_AUTHENTICATED;
|
||||
|
||||
/* Allow the platform to handle post-image load */
|
||||
result = bl1_plat_handle_post_image_load(image_id);
|
||||
if (result != 0) {
|
||||
ERROR("BL1-FWU: Failure %d in post-image load of image id %d\n",
|
||||
result, image_id);
|
||||
/*
|
||||
* Panic here as the platform handling of post-image load is
|
||||
* not correct.
|
||||
*/
|
||||
plat_error_handler(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush image_info to memory so that other
|
||||
* secure world images can see changes.
|
||||
*/
|
||||
flush_dcache_range((unsigned long)&image_desc->image_info,
|
||||
sizeof(image_info_t));
|
||||
|
||||
INFO("BL1-FWU: Authentication was successful\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible for executing Secure images.
|
||||
******************************************************************************/
|
||||
static int bl1_fwu_image_execute(unsigned int image_id,
|
||||
void **handle,
|
||||
unsigned int flags)
|
||||
{
|
||||
/* Get the image descriptor. */
|
||||
image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
|
||||
|
||||
/*
|
||||
* Execution is NOT allowed if:
|
||||
* image_id is invalid OR
|
||||
* Caller is from Secure world OR
|
||||
* Image is Non-Secure OR
|
||||
* Image is Non-Executable OR
|
||||
* Image is NOT in AUTHENTICATED state.
|
||||
*/
|
||||
if ((!image_desc) ||
|
||||
(GET_SECURITY_STATE(flags) == SECURE) ||
|
||||
(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE) ||
|
||||
(EP_GET_EXE(image_desc->ep_info.h.attr) == NON_EXECUTABLE) ||
|
||||
(image_desc->state != IMAGE_STATE_AUTHENTICATED)) {
|
||||
WARN("BL1-FWU: Execution not allowed due to invalid state/args\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
INFO("BL1-FWU: Executing Secure image\n");
|
||||
|
||||
#ifdef AARCH64
|
||||
/* Save NS-EL1 system registers. */
|
||||
cm_el1_sysregs_context_save(NON_SECURE);
|
||||
#endif
|
||||
|
||||
/* Prepare the image for execution. */
|
||||
bl1_prepare_next_image(image_id);
|
||||
|
||||
/* Update the secure image id. */
|
||||
sec_exec_image_id = image_id;
|
||||
|
||||
#ifdef AARCH64
|
||||
*handle = cm_get_context(SECURE);
|
||||
#else
|
||||
*handle = smc_get_ctx(SECURE);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible for resuming execution in the other security
|
||||
* world
|
||||
******************************************************************************/
|
||||
static register_t bl1_fwu_image_resume(register_t image_param,
|
||||
void **handle,
|
||||
unsigned int flags)
|
||||
{
|
||||
image_desc_t *image_desc;
|
||||
unsigned int resume_sec_state;
|
||||
unsigned int caller_sec_state = GET_SECURITY_STATE(flags);
|
||||
|
||||
/* Get the image descriptor for last executed secure image id. */
|
||||
image_desc = bl1_plat_get_image_desc(sec_exec_image_id);
|
||||
if (caller_sec_state == NON_SECURE) {
|
||||
if (!image_desc) {
|
||||
WARN("BL1-FWU: Resume not allowed due to no available"
|
||||
"secure image\n");
|
||||
return -EPERM;
|
||||
}
|
||||
} else {
|
||||
/* image_desc must be valid for secure world callers */
|
||||
assert(image_desc);
|
||||
}
|
||||
|
||||
assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE);
|
||||
assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE);
|
||||
|
||||
if (caller_sec_state == SECURE) {
|
||||
assert(image_desc->state == IMAGE_STATE_EXECUTED);
|
||||
|
||||
/* Update the flags. */
|
||||
image_desc->state = IMAGE_STATE_INTERRUPTED;
|
||||
resume_sec_state = NON_SECURE;
|
||||
} else {
|
||||
assert(image_desc->state == IMAGE_STATE_INTERRUPTED);
|
||||
|
||||
/* Update the flags. */
|
||||
image_desc->state = IMAGE_STATE_EXECUTED;
|
||||
resume_sec_state = SECURE;
|
||||
}
|
||||
|
||||
INFO("BL1-FWU: Resuming %s world context\n",
|
||||
(resume_sec_state == SECURE) ? "secure" : "normal");
|
||||
|
||||
#ifdef AARCH64
|
||||
/* Save the EL1 system registers of calling world. */
|
||||
cm_el1_sysregs_context_save(caller_sec_state);
|
||||
|
||||
/* Restore the EL1 system registers of resuming world. */
|
||||
cm_el1_sysregs_context_restore(resume_sec_state);
|
||||
|
||||
/* Update the next context. */
|
||||
cm_set_next_eret_context(resume_sec_state);
|
||||
|
||||
*handle = cm_get_context(resume_sec_state);
|
||||
#else
|
||||
/* Update the next context. */
|
||||
cm_set_next_context(cm_get_context(resume_sec_state));
|
||||
|
||||
/* Prepare the smc context for the next BL image. */
|
||||
smc_set_next_ctx(resume_sec_state);
|
||||
|
||||
*handle = smc_get_ctx(resume_sec_state);
|
||||
#endif
|
||||
return image_param;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible for resuming normal world context.
|
||||
******************************************************************************/
|
||||
static int bl1_fwu_sec_image_done(void **handle, unsigned int flags)
|
||||
{
|
||||
image_desc_t *image_desc;
|
||||
|
||||
/* Make sure caller is from the secure world */
|
||||
if (GET_SECURITY_STATE(flags) == NON_SECURE) {
|
||||
WARN("BL1-FWU: Image done not allowed from normal world\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* Get the image descriptor for last executed secure image id */
|
||||
image_desc = bl1_plat_get_image_desc(sec_exec_image_id);
|
||||
|
||||
/* image_desc must correspond to a valid secure executing image */
|
||||
assert(image_desc);
|
||||
assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE);
|
||||
assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE);
|
||||
assert(image_desc->state == IMAGE_STATE_EXECUTED);
|
||||
|
||||
#if ENABLE_ASSERTIONS
|
||||
int rc = bl1_fwu_remove_loaded_id(sec_exec_image_id);
|
||||
assert(rc == 0);
|
||||
#else
|
||||
bl1_fwu_remove_loaded_id(sec_exec_image_id);
|
||||
#endif
|
||||
|
||||
/* Update the flags. */
|
||||
image_desc->state = IMAGE_STATE_RESET;
|
||||
sec_exec_image_id = INVALID_IMAGE_ID;
|
||||
|
||||
INFO("BL1-FWU: Resuming Normal world context\n");
|
||||
#ifdef AARCH64
|
||||
/*
|
||||
* Secure world is done so no need to save the context.
|
||||
* Just restore the Non-Secure context.
|
||||
*/
|
||||
cm_el1_sysregs_context_restore(NON_SECURE);
|
||||
|
||||
/* Update the next context. */
|
||||
cm_set_next_eret_context(NON_SECURE);
|
||||
|
||||
*handle = cm_get_context(NON_SECURE);
|
||||
#else
|
||||
/* Update the next context. */
|
||||
cm_set_next_context(cm_get_context(NON_SECURE));
|
||||
|
||||
/* Prepare the smc context for the next BL image. */
|
||||
smc_set_next_ctx(NON_SECURE);
|
||||
|
||||
*handle = smc_get_ctx(NON_SECURE);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function provides the opportunity for users to perform any
|
||||
* platform specific handling after the Firmware update is done.
|
||||
******************************************************************************/
|
||||
__dead2 static void bl1_fwu_done(void *client_cookie, void *reserved)
|
||||
{
|
||||
NOTICE("BL1-FWU: *******FWU Process Completed*******\n");
|
||||
|
||||
/*
|
||||
* Call platform done function.
|
||||
*/
|
||||
bl1_plat_fwu_done(client_cookie, reserved);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function resets an image to IMAGE_STATE_RESET. It fails if the image is
|
||||
* being executed.
|
||||
******************************************************************************/
|
||||
static int bl1_fwu_image_reset(unsigned int image_id, unsigned int flags)
|
||||
{
|
||||
image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
|
||||
|
||||
if ((!image_desc) || (GET_SECURITY_STATE(flags) == SECURE)) {
|
||||
WARN("BL1-FWU: Reset not allowed due to invalid args\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
switch (image_desc->state) {
|
||||
|
||||
case IMAGE_STATE_RESET:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
|
||||
case IMAGE_STATE_INTERRUPTED:
|
||||
case IMAGE_STATE_AUTHENTICATED:
|
||||
case IMAGE_STATE_COPIED:
|
||||
case IMAGE_STATE_COPYING:
|
||||
|
||||
if (bl1_fwu_remove_loaded_id(image_id)) {
|
||||
WARN("BL1-FWU: Image reset couldn't find the image ID\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (image_desc->copied_size) {
|
||||
/* Clear the memory if the image is copied */
|
||||
assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE);
|
||||
|
||||
zero_normalmem((void *)image_desc->image_info.image_base,
|
||||
image_desc->copied_size);
|
||||
flush_dcache_range(image_desc->image_info.image_base,
|
||||
image_desc->copied_size);
|
||||
}
|
||||
|
||||
/* Reset status variables */
|
||||
image_desc->copied_size = 0;
|
||||
image_desc->image_info.image_size = 0;
|
||||
image_desc->state = IMAGE_STATE_RESET;
|
||||
|
||||
/* Clear authentication state */
|
||||
auth_img_flags[image_id] = 0;
|
||||
|
||||
break;
|
||||
|
||||
case IMAGE_STATE_EXECUTED:
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
302
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/bl1_main.c
vendored
Normal file
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl1.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <errata_report.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <smccc_helpers.h>
|
||||
#include <utils.h>
|
||||
#include <uuid.h>
|
||||
#include "bl1_private.h"
|
||||
|
||||
/* BL1 Service UUID */
|
||||
DEFINE_SVC_UUID(bl1_svc_uid,
|
||||
0xfd3967d4, 0x72cb, 0x4d9a, 0xb5, 0x75,
|
||||
0x67, 0x15, 0xd6, 0xf4, 0xbb, 0x4a);
|
||||
|
||||
static void bl1_load_bl2(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Helper utility to calculate the BL2 memory layout taking into consideration
|
||||
* the BL1 RW data assuming that it is at the top of the memory layout.
|
||||
******************************************************************************/
|
||||
void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
|
||||
meminfo_t *bl2_mem_layout)
|
||||
{
|
||||
assert(bl1_mem_layout != NULL);
|
||||
assert(bl2_mem_layout != NULL);
|
||||
|
||||
#if LOAD_IMAGE_V2
|
||||
/*
|
||||
* Remove BL1 RW data from the scope of memory visible to BL2.
|
||||
* This is assuming BL1 RW data is at the top of bl1_mem_layout.
|
||||
*/
|
||||
assert(BL1_RW_BASE > bl1_mem_layout->total_base);
|
||||
bl2_mem_layout->total_base = bl1_mem_layout->total_base;
|
||||
bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base;
|
||||
#else
|
||||
/* Check that BL1's memory is lying outside of the free memory */
|
||||
assert((BL1_RAM_LIMIT <= bl1_mem_layout->free_base) ||
|
||||
(BL1_RAM_BASE >= bl1_mem_layout->free_base +
|
||||
bl1_mem_layout->free_size));
|
||||
|
||||
/* Remove BL1 RW data from the scope of memory visible to BL2 */
|
||||
*bl2_mem_layout = *bl1_mem_layout;
|
||||
reserve_mem(&bl2_mem_layout->total_base,
|
||||
&bl2_mem_layout->total_size,
|
||||
BL1_RAM_BASE,
|
||||
BL1_RAM_LIMIT - BL1_RAM_BASE);
|
||||
#endif /* LOAD_IMAGE_V2 */
|
||||
|
||||
flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t));
|
||||
}
|
||||
|
||||
#if !ERROR_DEPRECATED
|
||||
/*******************************************************************************
|
||||
* Compatibility default implementation for deprecated API. This has a weak
|
||||
* definition. Platform specific code can override it if it wishes to.
|
||||
******************************************************************************/
|
||||
#pragma weak bl1_init_bl2_mem_layout
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that takes a memory layout into which BL2 has been loaded and
|
||||
* populates a new memory layout for BL2 that ensures that BL1's data sections
|
||||
* resident in secure RAM are not visible to BL2.
|
||||
******************************************************************************/
|
||||
void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
|
||||
meminfo_t *bl2_mem_layout)
|
||||
{
|
||||
bl1_calc_bl2_mem_layout(bl1_mem_layout, bl2_mem_layout);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Function to perform late architectural and platform specific initialization.
|
||||
* It also queries the platform to load and run next BL image. Only called
|
||||
* by the primary cpu after a cold boot.
|
||||
******************************************************************************/
|
||||
void bl1_main(void)
|
||||
{
|
||||
unsigned int image_id;
|
||||
|
||||
/* Announce our arrival */
|
||||
NOTICE(FIRMWARE_WELCOME_STR);
|
||||
NOTICE("BL1: %s\n", version_string);
|
||||
NOTICE("BL1: %s\n", build_message);
|
||||
|
||||
INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE,
|
||||
(void *)BL1_RAM_LIMIT);
|
||||
|
||||
print_errata_status();
|
||||
|
||||
#if ENABLE_ASSERTIONS
|
||||
u_register_t val;
|
||||
/*
|
||||
* Ensure that MMU/Caches and coherency are turned on
|
||||
*/
|
||||
#ifdef AARCH32
|
||||
val = read_sctlr();
|
||||
#else
|
||||
val = read_sctlr_el3();
|
||||
#endif
|
||||
assert(val & SCTLR_M_BIT);
|
||||
assert(val & SCTLR_C_BIT);
|
||||
assert(val & SCTLR_I_BIT);
|
||||
/*
|
||||
* Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
|
||||
* provided platform value
|
||||
*/
|
||||
val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
|
||||
/*
|
||||
* If CWG is zero, then no CWG information is available but we can
|
||||
* at least check the platform value is less than the architectural
|
||||
* maximum.
|
||||
*/
|
||||
if (val != 0)
|
||||
assert(CACHE_WRITEBACK_GRANULE == SIZE_FROM_LOG2_WORDS(val));
|
||||
else
|
||||
assert(CACHE_WRITEBACK_GRANULE <= MAX_CACHE_LINE_SIZE);
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Perform remaining generic architectural setup from EL3 */
|
||||
bl1_arch_setup();
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
/* Initialize authentication module */
|
||||
auth_mod_init();
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
/* Perform platform setup in BL1. */
|
||||
bl1_platform_setup();
|
||||
|
||||
/* Get the image id of next image to load and run. */
|
||||
image_id = bl1_plat_get_next_image_id();
|
||||
|
||||
/*
|
||||
* We currently interpret any image id other than
|
||||
* BL2_IMAGE_ID as the start of firmware update.
|
||||
*/
|
||||
if (image_id == BL2_IMAGE_ID)
|
||||
bl1_load_bl2();
|
||||
else
|
||||
NOTICE("BL1-FWU: *******FWU Process Started*******\n");
|
||||
|
||||
bl1_prepare_next_image(image_id);
|
||||
|
||||
console_flush();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function locates and loads the BL2 raw binary image in the trusted SRAM.
|
||||
* Called by the primary cpu after a cold boot.
|
||||
* TODO: Add support for alternative image load mechanism e.g using virtio/elf
|
||||
* loader etc.
|
||||
******************************************************************************/
|
||||
static void bl1_load_bl2(void)
|
||||
{
|
||||
image_desc_t *image_desc;
|
||||
image_info_t *image_info;
|
||||
int err;
|
||||
|
||||
/* Get the image descriptor */
|
||||
image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
|
||||
assert(image_desc);
|
||||
|
||||
/* Get the image info */
|
||||
image_info = &image_desc->image_info;
|
||||
INFO("BL1: Loading BL2\n");
|
||||
|
||||
err = bl1_plat_handle_pre_image_load(BL2_IMAGE_ID);
|
||||
if (err) {
|
||||
ERROR("Failure in pre image load handling of BL2 (%d)\n", err);
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
#if LOAD_IMAGE_V2
|
||||
err = load_auth_image(BL2_IMAGE_ID, image_info);
|
||||
#else
|
||||
entry_point_info_t *ep_info;
|
||||
meminfo_t *bl1_tzram_layout;
|
||||
|
||||
/* Get the entry point info */
|
||||
ep_info = &image_desc->ep_info;
|
||||
|
||||
/* Find out how much free trusted ram remains after BL1 load */
|
||||
bl1_tzram_layout = bl1_plat_sec_mem_layout();
|
||||
|
||||
/* Load the BL2 image */
|
||||
err = load_auth_image(bl1_tzram_layout,
|
||||
BL2_IMAGE_ID,
|
||||
image_info->image_base,
|
||||
image_info,
|
||||
ep_info);
|
||||
|
||||
#endif /* LOAD_IMAGE_V2 */
|
||||
|
||||
if (err) {
|
||||
ERROR("Failed to load BL2 firmware.\n");
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
/* Allow platform to handle image information. */
|
||||
err = bl1_plat_handle_post_image_load(BL2_IMAGE_ID);
|
||||
if (err) {
|
||||
ERROR("Failure in post image load handling of BL2 (%d)\n", err);
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
NOTICE("BL1: Booting BL2\n");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function called just before handing over to the next BL to inform the user
|
||||
* about the boot progress. In debug mode, also print details about the BL
|
||||
* image's execution context.
|
||||
******************************************************************************/
|
||||
void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info)
|
||||
{
|
||||
#ifdef AARCH32
|
||||
NOTICE("BL1: Booting BL32\n");
|
||||
#else
|
||||
NOTICE("BL1: Booting BL31\n");
|
||||
#endif /* AARCH32 */
|
||||
print_entry_point_info(bl_ep_info);
|
||||
}
|
||||
|
||||
#if SPIN_ON_BL1_EXIT
|
||||
void print_debug_loop_message(void)
|
||||
{
|
||||
NOTICE("BL1: Debug loop, spinning forever\n");
|
||||
NOTICE("BL1: Please connect the debugger to continue\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Top level handler for servicing BL1 SMCs.
|
||||
******************************************************************************/
|
||||
register_t bl1_smc_handler(unsigned int smc_fid,
|
||||
register_t x1,
|
||||
register_t x2,
|
||||
register_t x3,
|
||||
register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
unsigned int flags)
|
||||
{
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
/*
|
||||
* Dispatch FWU calls to FWU SMC handler and return its return
|
||||
* value
|
||||
*/
|
||||
if (is_fwu_fid(smc_fid)) {
|
||||
return bl1_fwu_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
|
||||
handle, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (smc_fid) {
|
||||
case BL1_SMC_CALL_COUNT:
|
||||
SMC_RET1(handle, BL1_NUM_SMC_CALLS);
|
||||
|
||||
case BL1_SMC_UID:
|
||||
SMC_UUID_RET(handle, bl1_svc_uid);
|
||||
|
||||
case BL1_SMC_VERSION:
|
||||
SMC_RET1(handle, BL1_SMC_MAJOR_VER | BL1_SMC_MINOR_VER);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
WARN("Unimplemented BL1 SMC Call: 0x%x \n", smc_fid);
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* BL1 SMC wrapper. This function is only used in AArch32 mode to ensure ABI
|
||||
* compliance when invoking bl1_smc_handler.
|
||||
******************************************************************************/
|
||||
register_t bl1_smc_wrapper(uint32_t smc_fid,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
unsigned int flags)
|
||||
{
|
||||
register_t x1, x2, x3, x4;
|
||||
|
||||
assert(handle);
|
||||
|
||||
get_smc_params_from_ctx(handle, x1, x2, x3, x4);
|
||||
return bl1_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
|
||||
}
|
||||
38
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/bl1_private.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __BL1_PRIVATE_H__
|
||||
#define __BL1_PRIVATE_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Declarations of linker defined symbols which will tell us where BL1 lives
|
||||
* in Trusted ROM and RAM
|
||||
******************************************************************************/
|
||||
IMPORT_SYM(uintptr_t, __BL1_ROM_END__, BL1_ROM_END);
|
||||
|
||||
IMPORT_SYM(uintptr_t, __BL1_RAM_START__, BL1_RAM_BASE);
|
||||
IMPORT_SYM(uintptr_t, __BL1_RAM_END__, BL1_RAM_LIMIT);
|
||||
|
||||
/******************************************
|
||||
* Function prototypes
|
||||
*****************************************/
|
||||
void bl1_arch_setup(void);
|
||||
void bl1_arch_next_el_setup(void);
|
||||
|
||||
void bl1_prepare_next_image(unsigned int image_id);
|
||||
|
||||
register_t bl1_fwu_smc_handler(unsigned int smc_fid,
|
||||
register_t x1,
|
||||
register_t x2,
|
||||
register_t x3,
|
||||
register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
unsigned int flags);
|
||||
#endif /* __BL1_PRIVATE_H__ */
|
||||
71
firmware/coreboot/3rdparty/arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <bl1.h>
|
||||
#include <bl_common.h>
|
||||
#include <platform_def.h>
|
||||
#include <tbbr/tbbr_img_desc.h>
|
||||
|
||||
image_desc_t bl1_tbbr_image_descs[] = {
|
||||
{
|
||||
.image_id = FWU_CERT_ID,
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
|
||||
VERSION_1, image_info_t, 0),
|
||||
.image_info.image_base = BL2_BASE,
|
||||
#if LOAD_IMAGE_V2
|
||||
.image_info.image_max_size = BL2_LIMIT - BL2_BASE,
|
||||
#endif
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
|
||||
VERSION_1, entry_point_info_t, SECURE),
|
||||
},
|
||||
#if NS_BL1U_BASE
|
||||
{
|
||||
.image_id = NS_BL1U_IMAGE_ID,
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_1, entry_point_info_t, NON_SECURE | EXECUTABLE),
|
||||
.ep_info.pc = NS_BL1U_BASE,
|
||||
},
|
||||
#endif
|
||||
#if SCP_BL2U_BASE
|
||||
{
|
||||
.image_id = SCP_BL2U_IMAGE_ID,
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
|
||||
VERSION_1, image_info_t, 0),
|
||||
.image_info.image_base = SCP_BL2U_BASE,
|
||||
#if LOAD_IMAGE_V2
|
||||
.image_info.image_max_size = SCP_BL2U_LIMIT - SCP_BL2U_BASE,
|
||||
#endif
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
|
||||
VERSION_1, entry_point_info_t, SECURE),
|
||||
},
|
||||
#endif
|
||||
#if BL2U_BASE
|
||||
{
|
||||
.image_id = BL2U_IMAGE_ID,
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_1, image_info_t, 0),
|
||||
.image_info.image_base = BL2U_BASE,
|
||||
#if LOAD_IMAGE_V2
|
||||
.image_info.image_max_size = BL2U_LIMIT - BL2U_BASE,
|
||||
#endif
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_1, entry_point_info_t, SECURE | EXECUTABLE),
|
||||
.ep_info.pc = BL2U_BASE,
|
||||
},
|
||||
#endif
|
||||
#if NS_BL2U_BASE
|
||||
{
|
||||
.image_id = NS_BL2U_IMAGE_ID,
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_1, entry_point_info_t, NON_SECURE),
|
||||
},
|
||||
#endif
|
||||
BL2_IMAGE_DESC,
|
||||
|
||||
{
|
||||
.image_id = INVALID_IMAGE_ID,
|
||||
}
|
||||
};
|
||||
15
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Place holder function to perform any Secure SVC specific architectural
|
||||
* setup. At the moment there is nothing to do.
|
||||
******************************************************************************/
|
||||
void bl2_arch_setup(void)
|
||||
{
|
||||
|
||||
}
|
||||
89
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
#include <el3_common_macros.S>
|
||||
|
||||
|
||||
.globl bl2_entrypoint
|
||||
.globl bl2_run_next_image
|
||||
|
||||
|
||||
func bl2_entrypoint
|
||||
/* Save arguments x0-x3 from previous Boot loader */
|
||||
mov r9, r0
|
||||
mov r10, r1
|
||||
mov r11, r2
|
||||
mov r12, r3
|
||||
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=1 \
|
||||
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
|
||||
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
|
||||
_init_memory=1 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=bl2_vector_table
|
||||
|
||||
/*
|
||||
* Restore parameters of boot rom
|
||||
*/
|
||||
mov r0, r9
|
||||
mov r1, r10
|
||||
mov r2, r11
|
||||
mov r3, r12
|
||||
|
||||
bl bl2_el3_early_platform_setup
|
||||
bl bl2_el3_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl2_main
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Should never reach this point.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
no_ret plat_panic_handler
|
||||
|
||||
endfunc bl2_entrypoint
|
||||
|
||||
func bl2_run_next_image
|
||||
mov r8,r0
|
||||
|
||||
/*
|
||||
* MMU needs to be disabled because both BL2 and BL32 execute
|
||||
* in PL1, and therefore share the same address space.
|
||||
* BL32 will initialize the address space according to its
|
||||
* own requirement.
|
||||
*/
|
||||
bl disable_mmu_icache_secure
|
||||
stcopr r0, TLBIALL
|
||||
dsb sy
|
||||
isb
|
||||
mov r0, r8
|
||||
bl bl2_el3_plat_prepare_exit
|
||||
|
||||
/*
|
||||
* Extract PC and SPSR based on struct `entry_point_info_t`
|
||||
* and load it in LR and SPSR registers respectively.
|
||||
*/
|
||||
ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
|
||||
ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
|
||||
msr spsr, r1
|
||||
|
||||
/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
|
||||
cps #MODE32_svc
|
||||
ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
|
||||
cps #MODE32_mon
|
||||
|
||||
add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
|
||||
ldm r8, {r0, r1, r2, r3}
|
||||
eret
|
||||
endfunc bl2_run_next_image
|
||||
21
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
|
||||
.globl bl2_vector_table
|
||||
|
||||
vector_base bl2_vector_table
|
||||
b bl2_entrypoint
|
||||
b report_exception /* Undef */
|
||||
b report_exception /* SVC call */
|
||||
b report_exception /* Prefetch abort */
|
||||
b report_exception /* Data abort */
|
||||
b report_exception /* Reserved */
|
||||
b report_exception /* IRQ */
|
||||
b report_exception /* FIQ */
|
||||
135
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
|
||||
|
||||
.globl bl2_vector_table
|
||||
.globl bl2_entrypoint
|
||||
|
||||
|
||||
vector_base bl2_vector_table
|
||||
b bl2_entrypoint
|
||||
b report_exception /* Undef */
|
||||
b report_exception /* SVC call */
|
||||
b report_exception /* Prefetch abort */
|
||||
b report_exception /* Data abort */
|
||||
b report_exception /* Reserved */
|
||||
b report_exception /* IRQ */
|
||||
b report_exception /* FIQ */
|
||||
|
||||
|
||||
func bl2_entrypoint
|
||||
/*---------------------------------------------
|
||||
* Save arguments x0 - x3 from BL1 for future
|
||||
* use.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov r9, r0
|
||||
mov r10, r1
|
||||
mov r11, r2
|
||||
mov r12, r3
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector to something sane.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr r0, =bl2_vector_table
|
||||
stcopr r0, VBAR
|
||||
isb
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Enable the instruction cache
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
ldcopr r0, SCTLR
|
||||
orr r0, r0, #SCTLR_I_BIT
|
||||
stcopr r0, SCTLR
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Since BL2 executes after BL1, it is assumed
|
||||
* here that BL1 has already has done the
|
||||
* necessary register initializations.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Invalidate the RW memory used by the BL2
|
||||
* image. This includes the data and NOBITS
|
||||
* sections. This is done to safeguard against
|
||||
* possible corruption of this memory by dirty
|
||||
* cache lines in a system cache as a result of
|
||||
* use by an earlier boot loader stage.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr r0, =__RW_START__
|
||||
ldr r1, =__RW_END__
|
||||
sub r1, r1, r0
|
||||
bl inv_dcache_range
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Zero out NOBITS sections. There are 2 of them:
|
||||
* - the .bss section;
|
||||
* - the coherent memory section.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr r0, =__BSS_START__
|
||||
ldr r1, =__BSS_SIZE__
|
||||
bl zeromem
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
ldr r0, =__COHERENT_RAM_START__
|
||||
ldr r1, =__COHERENT_RAM_UNALIGNED_SIZE__
|
||||
bl zeromem
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------
|
||||
* Allocate a stack whose memory will be marked
|
||||
* as Normal-IS-WBWA when the MMU is enabled.
|
||||
* There is no risk of reading stale stack
|
||||
* memory after enabling the MMU as only the
|
||||
* primary cpu is running at the moment.
|
||||
* --------------------------------------------
|
||||
*/
|
||||
bl plat_set_my_stack
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Initialize the stack protector canary before
|
||||
* any C code is called.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
bl update_stack_protector_canary
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Perform early platform setup & platform
|
||||
* specific early arch. setup e.g. mmu setup
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov r0, r9
|
||||
mov r1, r10
|
||||
mov r2, r11
|
||||
mov r3, r12
|
||||
bl bl2_early_platform_setup2
|
||||
bl bl2_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl2_main
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Should never reach this point.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
no_ret plat_panic_handler
|
||||
|
||||
endfunc bl2_entrypoint
|
||||
19
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include "../bl2_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Place holder function to perform any S-EL1 specific architectural setup. At
|
||||
* the moment there is nothing to do.
|
||||
******************************************************************************/
|
||||
void bl2_arch_setup(void)
|
||||
{
|
||||
/* Give access to FP/SIMD registers */
|
||||
write_cpacr(CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
|
||||
}
|
||||
77
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
#include <el3_common_macros.S>
|
||||
|
||||
.globl bl2_entrypoint
|
||||
.globl bl2_vector_table
|
||||
.globl bl2_el3_run_image
|
||||
.globl bl2_run_next_image
|
||||
|
||||
func bl2_entrypoint
|
||||
/* Save arguments x0-x3 from previous Boot loader */
|
||||
mov x20, x0
|
||||
mov x21, x1
|
||||
mov x22, x2
|
||||
mov x23, x3
|
||||
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=1 \
|
||||
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
|
||||
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
|
||||
_init_memory=1 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=bl2_el3_exceptions
|
||||
|
||||
/*
|
||||
* Restore parameters of boot rom
|
||||
*/
|
||||
mov x0, x20
|
||||
mov x1, x21
|
||||
mov x2, x22
|
||||
mov x3, x23
|
||||
|
||||
bl bl2_el3_early_platform_setup
|
||||
bl bl2_el3_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl2_main
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Should never reach this point.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
no_ret plat_panic_handler
|
||||
endfunc bl2_entrypoint
|
||||
|
||||
func bl2_run_next_image
|
||||
mov x20,x0
|
||||
/*
|
||||
* MMU needs to be disabled because both BL2 and BL31 execute
|
||||
* in EL3, and therefore share the same address space.
|
||||
* BL31 will initialize the address space according to its
|
||||
* own requirement.
|
||||
*/
|
||||
bl disable_mmu_icache_el3
|
||||
tlbi alle3
|
||||
bl bl2_el3_plat_prepare_exit
|
||||
|
||||
ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
|
||||
msr elr_el3, x0
|
||||
msr spsr_el3, x1
|
||||
|
||||
ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
|
||||
ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
|
||||
ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
|
||||
ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
|
||||
eret
|
||||
endfunc bl2_run_next_image
|
||||
131
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl1.h>
|
||||
#include <bl_common.h>
|
||||
#include <context.h>
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Very simple stackless exception handlers used by BL2.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
.globl bl2_el3_exceptions
|
||||
|
||||
vector_base bl2_el3_exceptions
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SP0 : 0x0 - 0x200
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSP0
|
||||
mov x0, #SYNC_EXCEPTION_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionSP0
|
||||
|
||||
vector_entry IrqSP0
|
||||
mov x0, #IRQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqSP0
|
||||
|
||||
vector_entry FiqSP0
|
||||
mov x0, #FIQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqSP0
|
||||
|
||||
vector_entry SErrorSP0
|
||||
mov x0, #SERROR_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorSP0
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SPx: 0x200 - 0x400
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSPx
|
||||
mov x0, #SYNC_EXCEPTION_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionSPx
|
||||
|
||||
vector_entry IrqSPx
|
||||
mov x0, #IRQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqSPx
|
||||
|
||||
vector_entry FiqSPx
|
||||
mov x0, #FIQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqSPx
|
||||
|
||||
vector_entry SErrorSPx
|
||||
mov x0, #SERROR_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorSPx
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch64 : 0x400 - 0x600
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionA64
|
||||
mov x0, #SYNC_EXCEPTION_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionA64
|
||||
|
||||
vector_entry IrqA64
|
||||
mov x0, #IRQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqA64
|
||||
|
||||
vector_entry FiqA64
|
||||
mov x0, #FIQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqA64
|
||||
|
||||
vector_entry SErrorA64
|
||||
mov x0, #SERROR_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorA64
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch32 : 0x600 - 0x800
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionA32
|
||||
mov x0, #SYNC_EXCEPTION_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionA32
|
||||
|
||||
vector_entry IrqA32
|
||||
mov x0, #IRQ_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqA32
|
||||
|
||||
vector_entry FiqA32
|
||||
mov x0, #FIQ_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqA32
|
||||
|
||||
vector_entry SErrorA32
|
||||
mov x0, #SERROR_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorA32
|
||||
127
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
|
||||
|
||||
.globl bl2_entrypoint
|
||||
|
||||
|
||||
|
||||
func bl2_entrypoint
|
||||
/*---------------------------------------------
|
||||
* Save arguments x0 - x3 from BL1 for future
|
||||
* use.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x20, x0
|
||||
mov x21, x1
|
||||
mov x22, x2
|
||||
mov x23, x3
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector to something sane.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x0, early_exceptions
|
||||
msr vbar_el1, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the SError interrupt now that the
|
||||
* exception vectors have been setup.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the instruction cache, stack pointer
|
||||
* and data access alignment checks
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
|
||||
mrs x0, sctlr_el1
|
||||
orr x0, x0, x1
|
||||
msr sctlr_el1, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Invalidate the RW memory used by the BL2
|
||||
* image. This includes the data and NOBITS
|
||||
* sections. This is done to safeguard against
|
||||
* possible corruption of this memory by dirty
|
||||
* cache lines in a system cache as a result of
|
||||
* use by an earlier boot loader stage.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x0, __RW_START__
|
||||
adr x1, __RW_END__
|
||||
sub x1, x1, x0
|
||||
bl inv_dcache_range
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Zero out NOBITS sections. There are 2 of them:
|
||||
* - the .bss section;
|
||||
* - the coherent memory section.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr x0, =__BSS_START__
|
||||
ldr x1, =__BSS_SIZE__
|
||||
bl zeromem
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
ldr x0, =__COHERENT_RAM_START__
|
||||
ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__
|
||||
bl zeromem
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------
|
||||
* Allocate a stack whose memory will be marked
|
||||
* as Normal-IS-WBWA when the MMU is enabled.
|
||||
* There is no risk of reading stale stack
|
||||
* memory after enabling the MMU as only the
|
||||
* primary cpu is running at the moment.
|
||||
* --------------------------------------------
|
||||
*/
|
||||
bl plat_set_my_stack
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Initialize the stack protector canary before
|
||||
* any C code is called.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
bl update_stack_protector_canary
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Perform early platform setup & platform
|
||||
* specific early arch. setup e.g. mmu setup
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x0, x20
|
||||
mov x1, x21
|
||||
mov x2, x22
|
||||
mov x3, x23
|
||||
bl bl2_early_platform_setup2
|
||||
|
||||
bl bl2_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl2_main
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Should never reach this point.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
no_ret plat_panic_handler
|
||||
|
||||
endfunc bl2_entrypoint
|
||||
154
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/bl2.ld.S
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
||||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
||||
ENTRY(bl2_entrypoint)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BL2_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL2_BASE address is not aligned on a page boundary.")
|
||||
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
.text . : {
|
||||
__TEXT_START__ = .;
|
||||
*bl2_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.vectors)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__TEXT_END__ = .;
|
||||
} >RAM
|
||||
|
||||
.rodata . : {
|
||||
__RODATA_START__ = .;
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PARSER_LIB_DESCS_START__ = .;
|
||||
KEEP(*(.img_parser_lib_descs))
|
||||
__PARSER_LIB_DESCS_END__ = .;
|
||||
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RODATA_END__ = .;
|
||||
} >RAM
|
||||
#else
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
*bl2_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PARSER_LIB_DESCS_START__ = .;
|
||||
KEEP(*(.img_parser_lib_descs))
|
||||
__PARSER_LIB_DESCS_END__ = .;
|
||||
|
||||
*(.vectors)
|
||||
__RO_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked as
|
||||
* read-only, executable. No RW data from the next section must
|
||||
* creep in. Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RO_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark start of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_START__ = . ;
|
||||
|
||||
/*
|
||||
* .data must be placed at a lower address than the stacks if the stack
|
||||
* protector is enabled. Alternatively, the .data.stack_protector_canary
|
||||
* section can be placed independently of the main .data section.
|
||||
*/
|
||||
.data . : {
|
||||
__DATA_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_END__ = .;
|
||||
} >RAM
|
||||
|
||||
stacks (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The .bss section gets initialised to 0 at runtime.
|
||||
* Its base address should be 16-byte aligned for better performance of the
|
||||
* zero-initialization code.
|
||||
*/
|
||||
.bss : ALIGN(16) {
|
||||
__BSS_START__ = .;
|
||||
*(SORT_BY_ALIGNMENT(.bss*))
|
||||
*(COMMON)
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The xlat_table section is for full, aligned page tables (4K).
|
||||
* Removing them from .bss avoids forcing 4K alignment on
|
||||
* the .bss section. The tables are initialized to zero by the translation
|
||||
* tables library.
|
||||
*/
|
||||
xlat_table (NOLOAD) : {
|
||||
*(xlat_table)
|
||||
} >RAM
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/*
|
||||
* The base address of the coherent memory section must be page-aligned (4K)
|
||||
* to guarantee that the coherent data are stored on their own pages and
|
||||
* are not mixed with normal data. This is required to set up the correct
|
||||
* memory attributes for the coherent data page tables.
|
||||
*/
|
||||
coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
__COHERENT_RAM_START__ = .;
|
||||
*(tzfw_coherent_mem)
|
||||
__COHERENT_RAM_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked
|
||||
* as device memory. No other unexpected data must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__COHERENT_RAM_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark end of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_END__ = .;
|
||||
__BL2_END__ = .;
|
||||
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
__COHERENT_RAM_UNALIGNED_SIZE__ =
|
||||
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
|
||||
#endif
|
||||
|
||||
ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.")
|
||||
}
|
||||
35
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/bl2.mk
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
BL2_SOURCES += bl2/bl2_main.c \
|
||||
bl2/${ARCH}/bl2_arch_setup.c \
|
||||
lib/locks/exclusive/${ARCH}/spinlock.S \
|
||||
plat/common/${ARCH}/platform_up_stack.S \
|
||||
${MBEDTLS_COMMON_SOURCES} \
|
||||
${MBEDTLS_CRYPTO_SOURCES} \
|
||||
${MBEDTLS_X509_SOURCES}
|
||||
|
||||
ifeq (${ARCH},aarch64)
|
||||
BL2_SOURCES += common/aarch64/early_exceptions.S
|
||||
endif
|
||||
|
||||
ifeq (${LOAD_IMAGE_V2},1)
|
||||
BL2_SOURCES += bl2/bl2_image_load_v2.c
|
||||
else
|
||||
BL2_SOURCES += bl2/bl2_image_load.c
|
||||
endif
|
||||
|
||||
ifeq (${BL2_AT_EL3},0)
|
||||
BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S
|
||||
BL2_LINKERFILE := bl2/bl2.ld.S
|
||||
|
||||
else
|
||||
BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \
|
||||
bl2/${ARCH}/bl2_el3_exceptions.S \
|
||||
lib/cpus/${ARCH}/cpu_helpers.S \
|
||||
lib/cpus/errata_report.c
|
||||
BL2_LINKERFILE := bl2/bl2_el3.ld.S
|
||||
endif
|
||||
238
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/bl2_el3.ld.S
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
||||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
||||
ENTRY(bl2_entrypoint)
|
||||
|
||||
MEMORY {
|
||||
#if BL2_IN_XIP_MEM
|
||||
ROM (rx): ORIGIN = BL2_RO_BASE, LENGTH = BL2_RO_LIMIT - BL2_RO_BASE
|
||||
RAM (rwx): ORIGIN = BL2_RW_BASE, LENGTH = BL2_RW_LIMIT - BL2_RW_BASE
|
||||
#else
|
||||
RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
#if BL2_IN_XIP_MEM
|
||||
. = BL2_RO_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL2_RO_BASE address is not aligned on a page boundary.")
|
||||
#else
|
||||
. = BL2_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL2_BASE address is not aligned on a page boundary.")
|
||||
#endif
|
||||
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
.text . : {
|
||||
__TEXT_START__ = .;
|
||||
__TEXT_RESIDENT_START__ = .;
|
||||
*bl2_el3_entrypoint.o(.text*)
|
||||
*(.text.asm.*)
|
||||
__TEXT_RESIDENT_END__ = .;
|
||||
*(.text*)
|
||||
*(.vectors)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__TEXT_END__ = .;
|
||||
#if BL2_IN_XIP_MEM
|
||||
} >ROM
|
||||
#else
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
.rodata . : {
|
||||
__RODATA_START__ = .;
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PARSER_LIB_DESCS_START__ = .;
|
||||
KEEP(*(.img_parser_lib_descs))
|
||||
__PARSER_LIB_DESCS_END__ = .;
|
||||
|
||||
/*
|
||||
* Ensure 8-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(8);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RODATA_END__ = .;
|
||||
#if BL2_IN_XIP_MEM
|
||||
} >ROM
|
||||
#else
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE,
|
||||
"Resident part of BL2 has exceeded its limit.")
|
||||
#else
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
__TEXT_RESIDENT_START__ = .;
|
||||
*bl2_el3_entrypoint.o(.text*)
|
||||
*(.text.asm.*)
|
||||
__TEXT_RESIDENT_END__ = .;
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
|
||||
/*
|
||||
* Ensure 8-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(8);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PARSER_LIB_DESCS_START__ = .;
|
||||
KEEP(*(.img_parser_lib_descs))
|
||||
__PARSER_LIB_DESCS_END__ = .;
|
||||
|
||||
*(.vectors)
|
||||
__RO_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked as
|
||||
* read-only, executable. No RW data from the next section must
|
||||
* creep in. Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
|
||||
__RO_END__ = .;
|
||||
#if BL2_IN_XIP_MEM
|
||||
} >ROM
|
||||
#else
|
||||
} >RAM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
|
||||
"cpu_ops not defined for this platform.")
|
||||
|
||||
#if BL2_IN_XIP_MEM
|
||||
. = BL2_RW_BASE;
|
||||
ASSERT(BL2_RW_BASE == ALIGN(PAGE_SIZE),
|
||||
"BL2_RW_BASE address is not aligned on a page boundary.")
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark start of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_START__ = . ;
|
||||
|
||||
/*
|
||||
* .data must be placed at a lower address than the stacks if the stack
|
||||
* protector is enabled. Alternatively, the .data.stack_protector_canary
|
||||
* section can be placed independently of the main .data section.
|
||||
*/
|
||||
.data . : {
|
||||
__DATA_RAM_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_RAM_END__ = .;
|
||||
#if BL2_IN_XIP_MEM
|
||||
} >RAM AT>ROM
|
||||
#else
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
stacks (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The .bss section gets initialised to 0 at runtime.
|
||||
* Its base address should be 16-byte aligned for better performance of the
|
||||
* zero-initialization code.
|
||||
*/
|
||||
.bss : ALIGN(16) {
|
||||
__BSS_START__ = .;
|
||||
*(SORT_BY_ALIGNMENT(.bss*))
|
||||
*(COMMON)
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The xlat_table section is for full, aligned page tables (4K).
|
||||
* Removing them from .bss avoids forcing 4K alignment on
|
||||
* the .bss section. The tables are initialized to zero by the translation
|
||||
* tables library.
|
||||
*/
|
||||
xlat_table (NOLOAD) : {
|
||||
*(xlat_table)
|
||||
} >RAM
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/*
|
||||
* The base address of the coherent memory section must be page-aligned (4K)
|
||||
* to guarantee that the coherent data are stored on their own pages and
|
||||
* are not mixed with normal data. This is required to set up the correct
|
||||
* memory attributes for the coherent data page tables.
|
||||
*/
|
||||
coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
__COHERENT_RAM_START__ = .;
|
||||
*(tzfw_coherent_mem)
|
||||
__COHERENT_RAM_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked
|
||||
* as device memory. No other unexpected data must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__COHERENT_RAM_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark end of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_END__ = .;
|
||||
__BL2_END__ = .;
|
||||
|
||||
#if BL2_IN_XIP_MEM
|
||||
__BL2_RAM_START__ = ADDR(.data);
|
||||
__BL2_RAM_END__ = .;
|
||||
|
||||
__DATA_ROM_START__ = LOADADDR(.data);
|
||||
__DATA_SIZE__ = SIZEOF(.data);
|
||||
|
||||
/*
|
||||
* The .data section is the last PROGBITS section so its end marks the end
|
||||
* of BL2's RO content in XIP memory..
|
||||
*/
|
||||
__BL2_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__;
|
||||
ASSERT(__BL2_ROM_END__ <= BL2_RO_LIMIT,
|
||||
"BL2's RO content has exceeded its limit.")
|
||||
#endif
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
__COHERENT_RAM_UNALIGNED_SIZE__ =
|
||||
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
|
||||
#endif
|
||||
|
||||
#if BL2_IN_XIP_MEM
|
||||
ASSERT(. <= BL2_RW_LIMIT, "BL2's RW content has exceeded its limit.")
|
||||
#else
|
||||
ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.")
|
||||
#endif
|
||||
}
|
||||
261
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/bl2_image_load.c
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Check for platforms that use obsolete image terminology
|
||||
*/
|
||||
#ifdef BL30_BASE
|
||||
# error "BL30_BASE platform define no longer used - please use SCP_BL2_BASE"
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Load the SCP_BL2 image if there's one.
|
||||
* If a platform does not want to attempt to load SCP_BL2 image it must leave
|
||||
* SCP_BL2_BASE undefined.
|
||||
* Return 0 on success or if there's no SCP_BL2 image to load, a negative error
|
||||
* code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_scp_bl2(void)
|
||||
{
|
||||
int e = 0;
|
||||
#ifdef SCP_BL2_BASE
|
||||
meminfo_t scp_bl2_mem_info;
|
||||
image_info_t scp_bl2_image_info;
|
||||
|
||||
/*
|
||||
* It is up to the platform to specify where SCP_BL2 should be loaded if
|
||||
* it exists. It could create space in the secure sram or point to a
|
||||
* completely different memory.
|
||||
*
|
||||
* The entry point information is not relevant in this case as the AP
|
||||
* won't execute the SCP_BL2 image.
|
||||
*/
|
||||
INFO("BL2: Loading SCP_BL2\n");
|
||||
bl2_plat_get_scp_bl2_meminfo(&scp_bl2_mem_info);
|
||||
scp_bl2_image_info.h.version = VERSION_1;
|
||||
e = load_auth_image(&scp_bl2_mem_info,
|
||||
SCP_BL2_IMAGE_ID,
|
||||
SCP_BL2_BASE,
|
||||
&scp_bl2_image_info,
|
||||
NULL);
|
||||
|
||||
if (e == 0) {
|
||||
/* The subsequent handling of SCP_BL2 is platform specific */
|
||||
e = bl2_plat_handle_scp_bl2(&scp_bl2_image_info);
|
||||
if (e) {
|
||||
ERROR("Failure in platform-specific handling of SCP_BL2 image.\n");
|
||||
}
|
||||
}
|
||||
#endif /* SCP_BL2_BASE */
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
#ifndef EL3_PAYLOAD_BASE
|
||||
/*******************************************************************************
|
||||
* Load the BL31 image.
|
||||
* The bl2_to_bl31_params and bl31_ep_info params will be updated with the
|
||||
* relevant BL31 information.
|
||||
* Return 0 on success, a negative error code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_bl31(bl31_params_t *bl2_to_bl31_params,
|
||||
entry_point_info_t *bl31_ep_info)
|
||||
{
|
||||
meminfo_t *bl2_tzram_layout;
|
||||
int e;
|
||||
|
||||
INFO("BL2: Loading BL31\n");
|
||||
assert(bl2_to_bl31_params != NULL);
|
||||
assert(bl31_ep_info != NULL);
|
||||
|
||||
/* Find out how much free trusted ram remains after BL2 load */
|
||||
bl2_tzram_layout = bl2_plat_sec_mem_layout();
|
||||
|
||||
/* Set the X0 parameter to BL31 */
|
||||
bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params;
|
||||
|
||||
/* Load the BL31 image */
|
||||
e = load_auth_image(bl2_tzram_layout,
|
||||
BL31_IMAGE_ID,
|
||||
BL31_BASE,
|
||||
bl2_to_bl31_params->bl31_image_info,
|
||||
bl31_ep_info);
|
||||
|
||||
if (e == 0) {
|
||||
bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info,
|
||||
bl31_ep_info);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Load the BL32 image if there's one.
|
||||
* The bl2_to_bl31_params param will be updated with the relevant BL32
|
||||
* information.
|
||||
* If a platform does not want to attempt to load BL32 image it must leave
|
||||
* BL32_BASE undefined.
|
||||
* Return 0 on success or if there's no BL32 image to load, a negative error
|
||||
* code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_bl32(bl31_params_t *bl2_to_bl31_params)
|
||||
{
|
||||
int e = 0;
|
||||
#ifdef BL32_BASE
|
||||
meminfo_t bl32_mem_info;
|
||||
|
||||
INFO("BL2: Loading BL32\n");
|
||||
assert(bl2_to_bl31_params != NULL);
|
||||
|
||||
/*
|
||||
* It is up to the platform to specify where BL32 should be loaded if
|
||||
* it exists. It could create space in the secure sram or point to a
|
||||
* completely different memory.
|
||||
*/
|
||||
bl2_plat_get_bl32_meminfo(&bl32_mem_info);
|
||||
e = load_auth_image(&bl32_mem_info,
|
||||
BL32_IMAGE_ID,
|
||||
BL32_BASE,
|
||||
bl2_to_bl31_params->bl32_image_info,
|
||||
bl2_to_bl31_params->bl32_ep_info);
|
||||
|
||||
if (e == 0) {
|
||||
bl2_plat_set_bl32_ep_info(
|
||||
bl2_to_bl31_params->bl32_image_info,
|
||||
bl2_to_bl31_params->bl32_ep_info);
|
||||
}
|
||||
#endif /* BL32_BASE */
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
#ifndef PRELOADED_BL33_BASE
|
||||
/*******************************************************************************
|
||||
* Load the BL33 image.
|
||||
* The bl2_to_bl31_params param will be updated with the relevant BL33
|
||||
* information.
|
||||
* Return 0 on success, a negative error code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_bl33(bl31_params_t *bl2_to_bl31_params)
|
||||
{
|
||||
meminfo_t bl33_mem_info;
|
||||
int e;
|
||||
|
||||
INFO("BL2: Loading BL33\n");
|
||||
assert(bl2_to_bl31_params != NULL);
|
||||
|
||||
bl2_plat_get_bl33_meminfo(&bl33_mem_info);
|
||||
|
||||
/* Load the BL33 image in non-secure memory provided by the platform */
|
||||
e = load_auth_image(&bl33_mem_info,
|
||||
BL33_IMAGE_ID,
|
||||
plat_get_ns_image_entrypoint(),
|
||||
bl2_to_bl31_params->bl33_image_info,
|
||||
bl2_to_bl31_params->bl33_ep_info);
|
||||
|
||||
if (e == 0) {
|
||||
bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info,
|
||||
bl2_to_bl31_params->bl33_ep_info);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
#endif /* PRELOADED_BL33_BASE */
|
||||
|
||||
#endif /* EL3_PAYLOAD_BASE */
|
||||
|
||||
/*******************************************************************************
|
||||
* This function loads SCP_BL2/BL3x images and returns the ep_info for
|
||||
* the next executable image.
|
||||
******************************************************************************/
|
||||
struct entry_point_info *bl2_load_images(void)
|
||||
{
|
||||
bl31_params_t *bl2_to_bl31_params;
|
||||
entry_point_info_t *bl31_ep_info;
|
||||
int e;
|
||||
|
||||
e = load_scp_bl2();
|
||||
if (e) {
|
||||
ERROR("Failed to load SCP_BL2 (%i)\n", e);
|
||||
plat_error_handler(e);
|
||||
}
|
||||
|
||||
/* Perform platform setup in BL2 after loading SCP_BL2 */
|
||||
bl2_platform_setup();
|
||||
|
||||
/*
|
||||
* Get a pointer to the memory the platform has set aside to pass
|
||||
* information to BL31.
|
||||
*/
|
||||
bl2_to_bl31_params = bl2_plat_get_bl31_params();
|
||||
bl31_ep_info = bl2_plat_get_bl31_ep_info();
|
||||
|
||||
#ifdef EL3_PAYLOAD_BASE
|
||||
/*
|
||||
* In the case of an EL3 payload, we don't need to load any further
|
||||
* images. Just update the BL31 entrypoint info structure to make BL1
|
||||
* jump to the EL3 payload.
|
||||
* The pointer to the memory the platform has set aside to pass
|
||||
* information to BL31 in the normal boot flow is reused here, even
|
||||
* though only a fraction of the information contained in the
|
||||
* bl31_params_t structure makes sense in the context of EL3 payloads.
|
||||
* This will be refined in the future.
|
||||
*/
|
||||
INFO("BL2: Populating the entrypoint info for the EL3 payload\n");
|
||||
bl31_ep_info->pc = EL3_PAYLOAD_BASE;
|
||||
bl31_ep_info->args.arg0 = (unsigned long) bl2_to_bl31_params;
|
||||
bl2_plat_set_bl31_ep_info(NULL, bl31_ep_info);
|
||||
#else
|
||||
e = load_bl31(bl2_to_bl31_params, bl31_ep_info);
|
||||
if (e) {
|
||||
ERROR("Failed to load BL31 (%i)\n", e);
|
||||
plat_error_handler(e);
|
||||
}
|
||||
|
||||
e = load_bl32(bl2_to_bl31_params);
|
||||
if (e) {
|
||||
if (e == -EAUTH) {
|
||||
ERROR("Failed to authenticate BL32\n");
|
||||
plat_error_handler(e);
|
||||
} else {
|
||||
WARN("Failed to load BL32 (%i)\n", e);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PRELOADED_BL33_BASE
|
||||
/*
|
||||
* In this case, don't load the BL33 image as it's already loaded in
|
||||
* memory. Update BL33 entrypoint information.
|
||||
*/
|
||||
INFO("BL2: Populating the entrypoint info for the preloaded BL33\n");
|
||||
bl2_to_bl31_params->bl33_ep_info->pc = PRELOADED_BL33_BASE;
|
||||
bl2_plat_set_bl33_ep_info(NULL, bl2_to_bl31_params->bl33_ep_info);
|
||||
#else
|
||||
e = load_bl33(bl2_to_bl31_params);
|
||||
if (e) {
|
||||
ERROR("Failed to load BL33 (%i)\n", e);
|
||||
plat_error_handler(e);
|
||||
}
|
||||
#endif /* PRELOADED_BL33_BASE */
|
||||
|
||||
#endif /* EL3_PAYLOAD_BASE */
|
||||
|
||||
/* Flush the params to be passed to memory */
|
||||
bl2_plat_flush_bl31_params();
|
||||
|
||||
return bl31_ep_info;
|
||||
}
|
||||
106
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/bl2_image_load_v2.c
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <desc_image_load.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
#include "bl2_private.h"
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* This function loads SCP_BL2/BL3x images and returns the ep_info for
|
||||
* the next executable image.
|
||||
******************************************************************************/
|
||||
struct entry_point_info *bl2_load_images(void)
|
||||
{
|
||||
bl_params_t *bl2_to_next_bl_params;
|
||||
bl_load_info_t *bl2_load_info;
|
||||
const bl_load_info_node_t *bl2_node_info;
|
||||
int plat_setup_done = 0;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Get information about the images to load.
|
||||
*/
|
||||
bl2_load_info = plat_get_bl_image_load_info();
|
||||
assert(bl2_load_info);
|
||||
assert(bl2_load_info->head);
|
||||
assert(bl2_load_info->h.type == PARAM_BL_LOAD_INFO);
|
||||
assert(bl2_load_info->h.version >= VERSION_2);
|
||||
bl2_node_info = bl2_load_info->head;
|
||||
|
||||
while (bl2_node_info) {
|
||||
/*
|
||||
* Perform platform setup before loading the image,
|
||||
* if indicated in the image attributes AND if NOT
|
||||
* already done before.
|
||||
*/
|
||||
if (bl2_node_info->image_info->h.attr & IMAGE_ATTRIB_PLAT_SETUP) {
|
||||
if (plat_setup_done) {
|
||||
WARN("BL2: Platform setup already done!!\n");
|
||||
} else {
|
||||
INFO("BL2: Doing platform setup\n");
|
||||
bl2_platform_setup();
|
||||
plat_setup_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
err = bl2_plat_handle_pre_image_load(bl2_node_info->image_id);
|
||||
if (err) {
|
||||
ERROR("BL2: Failure in pre image load handling (%i)\n", err);
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
if (!(bl2_node_info->image_info->h.attr & IMAGE_ATTRIB_SKIP_LOADING)) {
|
||||
INFO("BL2: Loading image id %d\n", bl2_node_info->image_id);
|
||||
err = load_auth_image(bl2_node_info->image_id,
|
||||
bl2_node_info->image_info);
|
||||
if (err) {
|
||||
ERROR("BL2: Failed to load image (%i)\n", err);
|
||||
plat_error_handler(err);
|
||||
}
|
||||
} else {
|
||||
INFO("BL2: Skip loading image id %d\n", bl2_node_info->image_id);
|
||||
}
|
||||
|
||||
/* Allow platform to handle image information. */
|
||||
err = bl2_plat_handle_post_image_load(bl2_node_info->image_id);
|
||||
if (err) {
|
||||
ERROR("BL2: Failure in post image load handling (%i)\n", err);
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
/* Go to next image */
|
||||
bl2_node_info = bl2_node_info->next_load_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get information to pass to the next image.
|
||||
*/
|
||||
bl2_to_next_bl_params = plat_get_next_bl_params();
|
||||
assert(bl2_to_next_bl_params);
|
||||
assert(bl2_to_next_bl_params->head);
|
||||
assert(bl2_to_next_bl_params->h.type == PARAM_BL_PARAMS);
|
||||
assert(bl2_to_next_bl_params->h.version >= VERSION_2);
|
||||
assert(bl2_to_next_bl_params->head->ep_info);
|
||||
|
||||
/* Populate arg0 for the next BL image if not already provided */
|
||||
if (bl2_to_next_bl_params->head->ep_info->args.arg0 == (u_register_t)0)
|
||||
bl2_to_next_bl_params->head->ep_info->args.arg0 =
|
||||
(u_register_t)bl2_to_next_bl_params;
|
||||
|
||||
/* Flush the parameters to be passed to next image */
|
||||
plat_flush_next_bl_params();
|
||||
|
||||
return bl2_to_next_bl_params->head->ep_info;
|
||||
}
|
||||
74
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/bl2_main.c
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl1.h>
|
||||
#include <bl2.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include "bl2_private.h"
|
||||
|
||||
#ifdef AARCH32
|
||||
#define NEXT_IMAGE "BL32"
|
||||
#else
|
||||
#define NEXT_IMAGE "BL31"
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* The only thing to do in BL2 is to load further images and pass control to
|
||||
* next BL. The memory occupied by BL2 will be reclaimed by BL3x stages. BL2
|
||||
* runs entirely in S-EL1.
|
||||
******************************************************************************/
|
||||
void bl2_main(void)
|
||||
{
|
||||
entry_point_info_t *next_bl_ep_info;
|
||||
|
||||
NOTICE("BL2: %s\n", version_string);
|
||||
NOTICE("BL2: %s\n", build_message);
|
||||
|
||||
/* Perform remaining generic architectural setup in S-EL1 */
|
||||
bl2_arch_setup();
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
/* Initialize authentication module */
|
||||
auth_mod_init();
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
/* initialize boot source */
|
||||
bl2_plat_preload_setup();
|
||||
|
||||
/* Load the subsequent bootloader images. */
|
||||
next_bl_ep_info = bl2_load_images();
|
||||
|
||||
#if !BL2_AT_EL3
|
||||
#ifdef AARCH32
|
||||
/*
|
||||
* For AArch32 state BL1 and BL2 share the MMU setup.
|
||||
* Given that BL2 does not map BL1 regions, MMU needs
|
||||
* to be disabled in order to go back to BL1.
|
||||
*/
|
||||
disable_mmu_icache_secure();
|
||||
#endif /* AARCH32 */
|
||||
|
||||
console_flush();
|
||||
|
||||
/*
|
||||
* Run next BL image via an SMC to BL1. Information on how to pass
|
||||
* control to the BL32 (if present) and BL33 software images will
|
||||
* be passed to next BL image as an argument.
|
||||
*/
|
||||
smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0);
|
||||
#else
|
||||
NOTICE("BL2: Booting " NEXT_IMAGE "\n");
|
||||
print_entry_point_info(next_bl_ep_info);
|
||||
console_flush();
|
||||
|
||||
bl2_run_next_image(next_bl_ep_info);
|
||||
#endif
|
||||
}
|
||||
36
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2/bl2_private.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __BL2_PRIVATE_H__
|
||||
#define __BL2_PRIVATE_H__
|
||||
|
||||
#if BL2_IN_XIP_MEM
|
||||
/*******************************************************************************
|
||||
* Declarations of linker defined symbols which will tell us where BL2 lives
|
||||
* in Trusted ROM and RAM
|
||||
******************************************************************************/
|
||||
extern uintptr_t __BL2_ROM_END__;
|
||||
#define BL2_ROM_END (uintptr_t)(&__BL2_ROM_END__)
|
||||
|
||||
extern uintptr_t __BL2_RAM_START__;
|
||||
extern uintptr_t __BL2_RAM_END__;
|
||||
#define BL2_RAM_BASE (uintptr_t)(&__BL2_RAM_START__)
|
||||
#define BL2_RAM_LIMIT (uintptr_t)(&__BL2_RAM_END__)
|
||||
#endif
|
||||
|
||||
/******************************************
|
||||
* Forward declarations
|
||||
*****************************************/
|
||||
struct entry_point_info;
|
||||
|
||||
/******************************************
|
||||
* Function prototypes
|
||||
*****************************************/
|
||||
void bl2_arch_setup(void);
|
||||
struct entry_point_info *bl2_load_images(void);
|
||||
void bl2_run_next_image(const struct entry_point_info *bl_ep_info);
|
||||
|
||||
#endif /* __BL2_PRIVATE_H__ */
|
||||
126
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
|
||||
|
||||
.globl bl2u_vector_table
|
||||
.globl bl2u_entrypoint
|
||||
|
||||
|
||||
vector_base bl2u_vector_table
|
||||
b bl2u_entrypoint
|
||||
b report_exception /* Undef */
|
||||
b report_exception /* SVC call */
|
||||
b report_exception /* Prefetch abort */
|
||||
b report_exception /* Data abort */
|
||||
b report_exception /* Reserved */
|
||||
b report_exception /* IRQ */
|
||||
b report_exception /* FIQ */
|
||||
|
||||
|
||||
func bl2u_entrypoint
|
||||
/*---------------------------------------------
|
||||
* Save from r1 the extents of the trusted ram
|
||||
* available to BL2U for future use.
|
||||
* r0 is not currently used.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov r11, r1
|
||||
mov r10, r2
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector to something sane.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr r0, =bl2u_vector_table
|
||||
stcopr r0, VBAR
|
||||
isb
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Enable the instruction cache
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
ldcopr r0, SCTLR
|
||||
orr r0, r0, #SCTLR_I_BIT
|
||||
stcopr r0, SCTLR
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Since BL2U executes after BL1, it is assumed
|
||||
* here that BL1 has already has done the
|
||||
* necessary register initializations.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Invalidate the RW memory used by the BL2U
|
||||
* image. This includes the data and NOBITS
|
||||
* sections. This is done to safeguard against
|
||||
* possible corruption of this memory by dirty
|
||||
* cache lines in a system cache as a result of
|
||||
* use by an earlier boot loader stage.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr r0, =__RW_START__
|
||||
ldr r1, =__RW_END__
|
||||
sub r1, r1, r0
|
||||
bl inv_dcache_range
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Zero out NOBITS sections. There are 2 of them:
|
||||
* - the .bss section;
|
||||
* - the coherent memory section.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr r0, =__BSS_START__
|
||||
ldr r1, =__BSS_SIZE__
|
||||
bl zeromem
|
||||
|
||||
/* --------------------------------------------
|
||||
* Allocate a stack whose memory will be marked
|
||||
* as Normal-IS-WBWA when the MMU is enabled.
|
||||
* There is no risk of reading stale stack
|
||||
* memory after enabling the MMU as only the
|
||||
* primary cpu is running at the moment.
|
||||
* --------------------------------------------
|
||||
*/
|
||||
bl plat_set_my_stack
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Initialize the stack protector canary before
|
||||
* any C code is called.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
bl update_stack_protector_canary
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Perform early platform setup & platform
|
||||
* specific early arch. setup e.g. mmu setup
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov r0, r11
|
||||
mov r1, r10
|
||||
bl bl2u_early_platform_setup
|
||||
bl bl2u_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl2u_main
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Should never reach this point.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
no_ret plat_panic_handler
|
||||
|
||||
endfunc bl2u_entrypoint
|
||||
116
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
|
||||
|
||||
.globl bl2u_entrypoint
|
||||
|
||||
|
||||
func bl2u_entrypoint
|
||||
/*---------------------------------------------
|
||||
* Store the extents of the tzram available to
|
||||
* BL2U and other platform specific information
|
||||
* for future use. x0 is currently not used.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x20, x1
|
||||
mov x21, x2
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector to something sane.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x0, early_exceptions
|
||||
msr vbar_el1, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the SError interrupt now that the
|
||||
* exception vectors have been setup.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the instruction cache, stack pointer
|
||||
* and data access alignment checks
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
|
||||
mrs x0, sctlr_el1
|
||||
orr x0, x0, x1
|
||||
msr sctlr_el1, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Invalidate the RW memory used by the BL2U
|
||||
* image. This includes the data and NOBITS
|
||||
* sections. This is done to safeguard against
|
||||
* possible corruption of this memory by dirty
|
||||
* cache lines in a system cache as a result of
|
||||
* use by an earlier boot loader stage.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x0, __RW_START__
|
||||
adr x1, __RW_END__
|
||||
sub x1, x1, x0
|
||||
bl inv_dcache_range
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Zero out NOBITS sections. There are 2 of them:
|
||||
* - the .bss section;
|
||||
* - the coherent memory section.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr x0, =__BSS_START__
|
||||
ldr x1, =__BSS_SIZE__
|
||||
bl zeromem
|
||||
|
||||
/* --------------------------------------------
|
||||
* Allocate a stack whose memory will be marked
|
||||
* as Normal-IS-WBWA when the MMU is enabled.
|
||||
* There is no risk of reading stale stack
|
||||
* memory after enabling the MMU as only the
|
||||
* primary cpu is running at the moment.
|
||||
* --------------------------------------------
|
||||
*/
|
||||
bl plat_set_my_stack
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Initialize the stack protector canary before
|
||||
* any C code is called.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
bl update_stack_protector_canary
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Perform early platform setup & platform
|
||||
* specific early arch. setup e.g. mmu setup
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x0, x20
|
||||
mov x1, x21
|
||||
bl bl2u_early_platform_setup
|
||||
bl bl2u_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to bl2u_main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl2u_main
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Should never reach this point.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
no_ret plat_panic_handler
|
||||
|
||||
endfunc bl2u_entrypoint
|
||||
136
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2u/bl2u.ld.S
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
||||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
||||
ENTRY(bl2u_entrypoint)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = BL2U_BASE, LENGTH = BL2U_LIMIT - BL2U_BASE
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BL2U_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL2U_BASE address is not aligned on a page boundary.")
|
||||
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
.text . : {
|
||||
__TEXT_START__ = .;
|
||||
*bl2u_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.vectors)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__TEXT_END__ = .;
|
||||
} >RAM
|
||||
|
||||
.rodata . : {
|
||||
__RODATA_START__ = .;
|
||||
*(.rodata*)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RODATA_END__ = .;
|
||||
} >RAM
|
||||
#else
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
*bl2u_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
|
||||
*(.vectors)
|
||||
__RO_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked as
|
||||
* read-only, executable. No RW data from the next section must
|
||||
* creep in. Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RO_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark start of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_START__ = . ;
|
||||
|
||||
/*
|
||||
* .data must be placed at a lower address than the stacks if the stack
|
||||
* protector is enabled. Alternatively, the .data.stack_protector_canary
|
||||
* section can be placed independently of the main .data section.
|
||||
*/
|
||||
.data . : {
|
||||
__DATA_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_END__ = .;
|
||||
} >RAM
|
||||
|
||||
stacks (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The .bss section gets initialised to 0 at runtime.
|
||||
* Its base address should be 16-byte aligned for better performance of the
|
||||
* zero-initialization code.
|
||||
*/
|
||||
.bss : ALIGN(16) {
|
||||
__BSS_START__ = .;
|
||||
*(SORT_BY_ALIGNMENT(.bss*))
|
||||
*(COMMON)
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The xlat_table section is for full, aligned page tables (4K).
|
||||
* Removing them from .bss avoids forcing 4K alignment on
|
||||
* the .bss section. The tables are initialized to zero by the translation
|
||||
* tables library.
|
||||
*/
|
||||
xlat_table (NOLOAD) : {
|
||||
*(xlat_table)
|
||||
} >RAM
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/*
|
||||
* The base address of the coherent memory section must be page-aligned (4K)
|
||||
* to guarantee that the coherent data are stored on their own pages and
|
||||
* are not mixed with normal data. This is required to set up the correct
|
||||
* memory attributes for the coherent data page tables.
|
||||
*/
|
||||
coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
__COHERENT_RAM_START__ = .;
|
||||
*(tzfw_coherent_mem)
|
||||
__COHERENT_RAM_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked
|
||||
* as device memory. No other unexpected data must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__COHERENT_RAM_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark end of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_END__ = .;
|
||||
__BL2U_END__ = .;
|
||||
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
|
||||
ASSERT(. <= BL2U_LIMIT, "BL2U image has exceeded its limit.")
|
||||
}
|
||||
15
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2u/bl2u.mk
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
BL2U_SOURCES += bl2u/bl2u_main.c \
|
||||
bl2u/${ARCH}/bl2u_entrypoint.S \
|
||||
plat/common/${ARCH}/platform_up_stack.S
|
||||
|
||||
ifeq (${ARCH},aarch64)
|
||||
BL2U_SOURCES += common/aarch64/early_exceptions.S
|
||||
endif
|
||||
|
||||
BL2U_LINKERFILE := bl2u/bl2u.ld.S
|
||||
63
firmware/coreboot/3rdparty/arm-trusted-firmware/bl2u/bl2u_main.c
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl1.h>
|
||||
#include <bl2u.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible to:
|
||||
* Load SCP_BL2U if platform has defined SCP_BL2U_BASE
|
||||
* Perform platform setup.
|
||||
* Go back to EL3.
|
||||
******************************************************************************/
|
||||
void bl2u_main(void)
|
||||
{
|
||||
NOTICE("BL2U: %s\n", version_string);
|
||||
NOTICE("BL2U: %s\n", build_message);
|
||||
|
||||
#if SCP_BL2U_BASE
|
||||
int rc;
|
||||
/* Load the subsequent bootloader images */
|
||||
rc = bl2u_plat_handle_scp_bl2u();
|
||||
if (rc) {
|
||||
ERROR("Failed to load SCP_BL2U (%i)\n", rc);
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Perform platform setup in BL2U after loading SCP_BL2U */
|
||||
bl2u_platform_setup();
|
||||
|
||||
console_flush();
|
||||
|
||||
#ifdef AARCH32
|
||||
/*
|
||||
* For AArch32 state BL1 and BL2U share the MMU setup.
|
||||
* Given that BL2U does not map BL1 regions, MMU needs
|
||||
* to be disabled in order to go back to BL1.
|
||||
*/
|
||||
disable_mmu_icache_secure();
|
||||
#endif /* AARCH32 */
|
||||
|
||||
/*
|
||||
* Indicate that BL2U is done and resume back to
|
||||
* normal world via an SMC to BL1.
|
||||
* x1 could be passed to Normal world,
|
||||
* so DO NOT pass any secret information.
|
||||
*/
|
||||
smc(FWU_SMC_SEC_IMAGE_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
wfi();
|
||||
}
|
||||
204
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <bl_common.h>
|
||||
#include <el3_common_macros.S>
|
||||
#include <pmf_asm_macros.S>
|
||||
#include <runtime_instr.h>
|
||||
#include <xlat_mmu_helpers.h>
|
||||
|
||||
.globl bl31_entrypoint
|
||||
.globl bl31_warm_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* bl31_entrypoint() is the cold boot entrypoint,
|
||||
* executed only by the primary cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
func bl31_entrypoint
|
||||
#if !RESET_TO_BL31
|
||||
/* ---------------------------------------------------------------
|
||||
* Stash the previous bootloader arguments x0 - x3 for later use.
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
mov x20, x0
|
||||
mov x21, x1
|
||||
mov x22, x2
|
||||
mov x23, x3
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* For !RESET_TO_BL31 systems, only the primary CPU ever reaches
|
||||
* bl31_entrypoint() during the cold boot flow, so the cold/warm boot
|
||||
* and primary/secondary CPU logic should not be executed in this case.
|
||||
*
|
||||
* Also, assume that the previous bootloader has already initialised the
|
||||
* SCTLR_EL3, including the endianness, and has initialised the memory.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=0 \
|
||||
_warm_boot_mailbox=0 \
|
||||
_secondary_cold_boot=0 \
|
||||
_init_memory=0 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=runtime_exceptions
|
||||
#else
|
||||
/* ---------------------------------------------------------------------
|
||||
* For RESET_TO_BL31 systems which have a programmable reset address,
|
||||
* bl31_entrypoint() is executed only on the cold boot path so we can
|
||||
* skip the warm boot mailbox mechanism.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=1 \
|
||||
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
|
||||
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
|
||||
_init_memory=1 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=runtime_exceptions
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* For RESET_TO_BL31 systems, BL31 is the first bootloader to run so
|
||||
* there's no argument to relay from a previous bootloader. Zero the
|
||||
* arguments passed to the platform layer to reflect that.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov x20, 0
|
||||
mov x21, 0
|
||||
mov x22, 0
|
||||
mov x23, 0
|
||||
#endif /* RESET_TO_BL31 */
|
||||
/* ---------------------------------------------
|
||||
* Perform platform specific early arch. setup
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x0, x20
|
||||
mov x1, x21
|
||||
mov x2, x22
|
||||
mov x3, x23
|
||||
bl bl31_early_platform_setup2
|
||||
bl bl31_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl bl31_main
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* Clean the .data & .bss sections to main memory. This ensures
|
||||
* that any global data which was initialised by the primary CPU
|
||||
* is visible to secondary CPUs before they enable their data
|
||||
* caches and participate in coherency.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
adr x0, __DATA_START__
|
||||
adr x1, __DATA_END__
|
||||
sub x1, x1, x0
|
||||
bl clean_dcache_range
|
||||
|
||||
adr x0, __BSS_START__
|
||||
adr x1, __BSS_END__
|
||||
sub x1, x1, x0
|
||||
bl clean_dcache_range
|
||||
|
||||
b el3_exit
|
||||
endfunc bl31_entrypoint
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* This CPU has been physically powered up. It is either resuming from
|
||||
* suspend or has simply been turned on. In both cases, call the BL31
|
||||
* warmboot entrypoint
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func bl31_warm_entrypoint
|
||||
#if ENABLE_RUNTIME_INSTRUMENTATION
|
||||
|
||||
/*
|
||||
* This timestamp update happens with cache off. The next
|
||||
* timestamp collection will need to do cache maintenance prior
|
||||
* to timestamp update.
|
||||
*/
|
||||
pmf_calc_timestamp_addr rt_instr_svc RT_INSTR_EXIT_HW_LOW_PWR
|
||||
mrs x1, cntpct_el0
|
||||
str x1, [x0]
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On the warm boot path, most of the EL3 initialisations performed by
|
||||
* 'el3_entrypoint_common' must be skipped:
|
||||
*
|
||||
* - Only when the platform bypasses the BL1/BL31 entrypoint by
|
||||
* programming the reset address do we need to initialise SCTLR_EL3.
|
||||
* In other cases, we assume this has been taken care by the
|
||||
* entrypoint code.
|
||||
*
|
||||
* - No need to determine the type of boot, we know it is a warm boot.
|
||||
*
|
||||
* - Do not try to distinguish between primary and secondary CPUs, this
|
||||
* notion only exists for a cold boot.
|
||||
*
|
||||
* - No need to initialise the memory or the C runtime environment,
|
||||
* it has been done once and for all on the cold boot path.
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=PROGRAMMABLE_RESET_ADDRESS \
|
||||
_warm_boot_mailbox=0 \
|
||||
_secondary_cold_boot=0 \
|
||||
_init_memory=0 \
|
||||
_init_c_runtime=0 \
|
||||
_exception_vectors=runtime_exceptions
|
||||
|
||||
/*
|
||||
* We're about to enable MMU and participate in PSCI state coordination.
|
||||
*
|
||||
* The PSCI implementation invokes platform routines that enable CPUs to
|
||||
* participate in coherency. On a system where CPUs are not
|
||||
* cache-coherent without appropriate platform specific programming,
|
||||
* having caches enabled until such time might lead to coherency issues
|
||||
* (resulting from stale data getting speculatively fetched, among
|
||||
* others). Therefore we keep data caches disabled even after enabling
|
||||
* the MMU for such platforms.
|
||||
*
|
||||
* On systems with hardware-assisted coherency, or on single cluster
|
||||
* platforms, such platform specific programming is not required to
|
||||
* enter coherency (as CPUs already are); and there's no reason to have
|
||||
* caches disabled either.
|
||||
*/
|
||||
mov x0, #DISABLE_DCACHE
|
||||
bl bl31_plat_enable_mmu
|
||||
|
||||
#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY
|
||||
mrs x0, sctlr_el3
|
||||
orr x0, x0, #SCTLR_C_BIT
|
||||
msr sctlr_el3, x0
|
||||
isb
|
||||
#endif
|
||||
|
||||
bl psci_warmboot_entrypoint
|
||||
|
||||
#if ENABLE_RUNTIME_INSTRUMENTATION
|
||||
pmf_calc_timestamp_addr rt_instr_svc RT_INSTR_EXIT_PSCI
|
||||
mov x19, x0
|
||||
|
||||
/*
|
||||
* Invalidate before updating timestamp to ensure previous timestamp
|
||||
* updates on the same cache line with caches disabled are properly
|
||||
* seen by the same core. Without the cache invalidate, the core might
|
||||
* write into a stale cache line.
|
||||
*/
|
||||
mov x1, #PMF_TS_SIZE
|
||||
mov x20, x30
|
||||
bl inv_dcache_range
|
||||
mov x30, x20
|
||||
|
||||
mrs x0, cntpct_el0
|
||||
str x0, [x19]
|
||||
#endif
|
||||
b el3_exit
|
||||
endfunc bl31_warm_entrypoint
|
||||
342
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/aarch64/crash_reporting.S
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <context.h>
|
||||
#include <cpu_data.h>
|
||||
#include <plat_macros.S>
|
||||
#include <platform_def.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
.globl report_unhandled_exception
|
||||
.globl report_unhandled_interrupt
|
||||
.globl el3_panic
|
||||
|
||||
#if CRASH_REPORTING
|
||||
|
||||
/* ------------------------------------------------------
|
||||
* The below section deals with dumping the system state
|
||||
* when an unhandled exception is taken in EL3.
|
||||
* The layout and the names of the registers which will
|
||||
* be dumped during a unhandled exception is given below.
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
.section .rodata.crash_prints, "aS"
|
||||
print_spacer:
|
||||
.asciz " =\t\t0x"
|
||||
|
||||
gp_regs:
|
||||
.asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
|
||||
"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\
|
||||
"x16", "x17", "x18", "x19", "x20", "x21", "x22",\
|
||||
"x23", "x24", "x25", "x26", "x27", "x28", "x29", ""
|
||||
el3_sys_regs:
|
||||
.asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
|
||||
"daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\
|
||||
"esr_el3", "far_el3", ""
|
||||
|
||||
non_el3_sys_regs:
|
||||
.asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
|
||||
"spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
|
||||
"csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
|
||||
"mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\
|
||||
"tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
|
||||
"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
|
||||
"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
|
||||
"cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", ""
|
||||
|
||||
panic_msg:
|
||||
.asciz "PANIC in EL3 at x30 = 0x"
|
||||
excpt_msg:
|
||||
.asciz "Unhandled Exception in EL3.\nx30 =\t\t0x"
|
||||
intr_excpt_msg:
|
||||
.asciz "Unhandled Interrupt Exception in EL3.\nx30 =\t\t0x"
|
||||
|
||||
/*
|
||||
* Helper function to print newline to console.
|
||||
*/
|
||||
func print_newline
|
||||
mov x0, '\n'
|
||||
b plat_crash_console_putc
|
||||
endfunc print_newline
|
||||
|
||||
/*
|
||||
* Helper function to print from crash buf.
|
||||
* The print loop is controlled by the buf size and
|
||||
* ascii reg name list which is passed in x6. The
|
||||
* function returns the crash buf address in x0.
|
||||
* Clobbers : x0 - x7, sp
|
||||
*/
|
||||
func size_controlled_print
|
||||
/* Save the lr */
|
||||
mov sp, x30
|
||||
/* load the crash buf address */
|
||||
mrs x7, tpidr_el3
|
||||
test_size_list:
|
||||
/* Calculate x5 always as it will be clobbered by asm_print_hex */
|
||||
mrs x5, tpidr_el3
|
||||
add x5, x5, #CPU_DATA_CRASH_BUF_SIZE
|
||||
/* Test whether we have reached end of crash buf */
|
||||
cmp x7, x5
|
||||
b.eq exit_size_print
|
||||
ldrb w4, [x6]
|
||||
/* Test whether we are at end of list */
|
||||
cbz w4, exit_size_print
|
||||
mov x4, x6
|
||||
/* asm_print_str updates x4 to point to next entry in list */
|
||||
bl asm_print_str
|
||||
/* update x6 with the updated list pointer */
|
||||
mov x6, x4
|
||||
adr x4, print_spacer
|
||||
bl asm_print_str
|
||||
ldr x4, [x7], #REGSZ
|
||||
bl asm_print_hex
|
||||
bl print_newline
|
||||
b test_size_list
|
||||
exit_size_print:
|
||||
mov x30, sp
|
||||
ret
|
||||
endfunc size_controlled_print
|
||||
|
||||
/*
|
||||
* Helper function to store x8 - x15 registers to
|
||||
* the crash buf. The system registers values are
|
||||
* copied to x8 to x15 by the caller which are then
|
||||
* copied to the crash buf by this function.
|
||||
* x0 points to the crash buf. It then calls
|
||||
* size_controlled_print to print to console.
|
||||
* Clobbers : x0 - x7, sp
|
||||
*/
|
||||
func str_in_crash_buf_print
|
||||
/* restore the crash buf address in x0 */
|
||||
mrs x0, tpidr_el3
|
||||
stp x8, x9, [x0]
|
||||
stp x10, x11, [x0, #REGSZ * 2]
|
||||
stp x12, x13, [x0, #REGSZ * 4]
|
||||
stp x14, x15, [x0, #REGSZ * 6]
|
||||
b size_controlled_print
|
||||
endfunc str_in_crash_buf_print
|
||||
|
||||
/* ------------------------------------------------------
|
||||
* This macro calculates the offset to crash buf from
|
||||
* cpu_data and stores it in tpidr_el3. It also saves x0
|
||||
* and x1 in the crash buf by using sp as a temporary
|
||||
* register.
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
.macro prepare_crash_buf_save_x0_x1
|
||||
/* we can corrupt this reg to free up x0 */
|
||||
mov sp, x0
|
||||
/* tpidr_el3 contains the address to cpu_data structure */
|
||||
mrs x0, tpidr_el3
|
||||
/* Calculate the Crash buffer offset in cpu_data */
|
||||
add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
|
||||
/* Store crash buffer address in tpidr_el3 */
|
||||
msr tpidr_el3, x0
|
||||
str x1, [x0, #REGSZ]
|
||||
mov x1, sp
|
||||
str x1, [x0]
|
||||
.endm
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* This function allows to report a crash (if crash
|
||||
* reporting is enabled) when an unhandled exception
|
||||
* occurs. It prints the CPU state via the crash console
|
||||
* making use of the crash buf. This function will
|
||||
* not return.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func report_unhandled_exception
|
||||
prepare_crash_buf_save_x0_x1
|
||||
adr x0, excpt_msg
|
||||
mov sp, x0
|
||||
/* This call will not return */
|
||||
b do_crash_reporting
|
||||
endfunc report_unhandled_exception
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* This function allows to report a crash (if crash
|
||||
* reporting is enabled) when an unhandled interrupt
|
||||
* occurs. It prints the CPU state via the crash console
|
||||
* making use of the crash buf. This function will
|
||||
* not return.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func report_unhandled_interrupt
|
||||
prepare_crash_buf_save_x0_x1
|
||||
adr x0, intr_excpt_msg
|
||||
mov sp, x0
|
||||
/* This call will not return */
|
||||
b do_crash_reporting
|
||||
endfunc report_unhandled_interrupt
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* This function allows to report a crash (if crash
|
||||
* reporting is enabled) when panic() is invoked from
|
||||
* C Runtime. It prints the CPU state via the crash
|
||||
* console making use of the crash buf. This function
|
||||
* will not return.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func el3_panic
|
||||
msr spsel, #1
|
||||
prepare_crash_buf_save_x0_x1
|
||||
adr x0, panic_msg
|
||||
mov sp, x0
|
||||
/* This call will not return */
|
||||
b do_crash_reporting
|
||||
endfunc el3_panic
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
* The common crash reporting functionality. It requires x0
|
||||
* and x1 has already been stored in crash buf, sp points to
|
||||
* crash message and tpidr_el3 contains the crash buf address.
|
||||
* The function does the following:
|
||||
* - Retrieve the crash buffer from tpidr_el3
|
||||
* - Store x2 to x6 in the crash buffer
|
||||
* - Initialise the crash console.
|
||||
* - Print the crash message by using the address in sp.
|
||||
* - Print x30 value to the crash console.
|
||||
* - Print x0 - x7 from the crash buf to the crash console.
|
||||
* - Print x8 - x29 (in groups of 8 registers) using the
|
||||
* crash buf to the crash console.
|
||||
* - Print el3 sys regs (in groups of 8 registers) using the
|
||||
* crash buf to the crash console.
|
||||
* - Print non el3 sys regs (in groups of 8 registers) using
|
||||
* the crash buf to the crash console.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
func do_crash_reporting
|
||||
/* Retrieve the crash buf from tpidr_el3 */
|
||||
mrs x0, tpidr_el3
|
||||
/* Store x2 - x6, x30 in the crash buffer */
|
||||
stp x2, x3, [x0, #REGSZ * 2]
|
||||
stp x4, x5, [x0, #REGSZ * 4]
|
||||
stp x6, x30, [x0, #REGSZ * 6]
|
||||
/* Initialize the crash console */
|
||||
bl plat_crash_console_init
|
||||
/* Verify the console is initialized */
|
||||
cbz x0, crash_panic
|
||||
/* Print the crash message. sp points to the crash message */
|
||||
mov x4, sp
|
||||
bl asm_print_str
|
||||
/* load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* report x30 first from the crash buf */
|
||||
ldr x4, [x0, #REGSZ * 7]
|
||||
bl asm_print_hex
|
||||
bl print_newline
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* Now mov x7 into crash buf */
|
||||
str x7, [x0, #REGSZ * 7]
|
||||
|
||||
/* Report x0 - x29 values stored in crash buf*/
|
||||
/* Store the ascii list pointer in x6 */
|
||||
adr x6, gp_regs
|
||||
/* Print x0 to x7 from the crash buf */
|
||||
bl size_controlled_print
|
||||
/* Store x8 - x15 in crash buf and print */
|
||||
bl str_in_crash_buf_print
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
/* Store the rest of gp regs and print */
|
||||
stp x16, x17, [x0]
|
||||
stp x18, x19, [x0, #REGSZ * 2]
|
||||
stp x20, x21, [x0, #REGSZ * 4]
|
||||
stp x22, x23, [x0, #REGSZ * 6]
|
||||
bl size_controlled_print
|
||||
/* Load the crash buf address */
|
||||
mrs x0, tpidr_el3
|
||||
stp x24, x25, [x0]
|
||||
stp x26, x27, [x0, #REGSZ * 2]
|
||||
stp x28, x29, [x0, #REGSZ * 4]
|
||||
bl size_controlled_print
|
||||
|
||||
/* Print the el3 sys registers */
|
||||
adr x6, el3_sys_regs
|
||||
mrs x8, scr_el3
|
||||
mrs x9, sctlr_el3
|
||||
mrs x10, cptr_el3
|
||||
mrs x11, tcr_el3
|
||||
mrs x12, daif
|
||||
mrs x13, mair_el3
|
||||
mrs x14, spsr_el3
|
||||
mrs x15, elr_el3
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, ttbr0_el3
|
||||
mrs x9, esr_el3
|
||||
mrs x10, far_el3
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
/* Print the non el3 sys registers */
|
||||
adr x6, non_el3_sys_regs
|
||||
mrs x8, spsr_el1
|
||||
mrs x9, elr_el1
|
||||
mrs x10, spsr_abt
|
||||
mrs x11, spsr_und
|
||||
mrs x12, spsr_irq
|
||||
mrs x13, spsr_fiq
|
||||
mrs x14, sctlr_el1
|
||||
mrs x15, actlr_el1
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, cpacr_el1
|
||||
mrs x9, csselr_el1
|
||||
mrs x10, sp_el1
|
||||
mrs x11, esr_el1
|
||||
mrs x12, ttbr0_el1
|
||||
mrs x13, ttbr1_el1
|
||||
mrs x14, mair_el1
|
||||
mrs x15, amair_el1
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, tcr_el1
|
||||
mrs x9, tpidr_el1
|
||||
mrs x10, tpidr_el0
|
||||
mrs x11, tpidrro_el0
|
||||
mrs x12, dacr32_el2
|
||||
mrs x13, ifsr32_el2
|
||||
mrs x14, par_el1
|
||||
mrs x15, mpidr_el1
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, afsr0_el1
|
||||
mrs x9, afsr1_el1
|
||||
mrs x10, contextidr_el1
|
||||
mrs x11, vbar_el1
|
||||
mrs x12, cntp_ctl_el0
|
||||
mrs x13, cntp_cval_el0
|
||||
mrs x14, cntv_ctl_el0
|
||||
mrs x15, cntv_cval_el0
|
||||
bl str_in_crash_buf_print
|
||||
mrs x8, cntkctl_el1
|
||||
mrs x9, sp_el0
|
||||
mrs x10, isr_el1
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
/* Get the cpu specific registers to report */
|
||||
bl do_cpu_reg_dump
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
/* Print some platform registers */
|
||||
plat_crash_print_regs
|
||||
|
||||
bl plat_crash_console_flush
|
||||
|
||||
/* Done reporting */
|
||||
no_ret plat_panic_handler
|
||||
endfunc do_crash_reporting
|
||||
|
||||
#else /* CRASH_REPORTING */
|
||||
func report_unhandled_exception
|
||||
report_unhandled_interrupt:
|
||||
no_ret plat_panic_handler
|
||||
endfunc report_unhandled_exception
|
||||
#endif /* CRASH_REPORTING */
|
||||
|
||||
|
||||
func crash_panic
|
||||
no_ret plat_panic_handler
|
||||
endfunc crash_panic
|
||||
586
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S
vendored
Normal file
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <context.h>
|
||||
#include <cpu_data.h>
|
||||
#include <ea_handle.h>
|
||||
#include <interrupt_mgmt.h>
|
||||
#include <platform_def.h>
|
||||
#include <runtime_svc.h>
|
||||
#include <smccc.h>
|
||||
|
||||
.globl runtime_exceptions
|
||||
|
||||
.globl sync_exception_sp_el0
|
||||
.globl irq_sp_el0
|
||||
.globl fiq_sp_el0
|
||||
.globl serror_sp_el0
|
||||
|
||||
.globl sync_exception_sp_elx
|
||||
.globl irq_sp_elx
|
||||
.globl fiq_sp_elx
|
||||
.globl serror_sp_elx
|
||||
|
||||
.globl sync_exception_aarch64
|
||||
.globl irq_aarch64
|
||||
.globl fiq_aarch64
|
||||
.globl serror_aarch64
|
||||
|
||||
.globl sync_exception_aarch32
|
||||
.globl irq_aarch32
|
||||
.globl fiq_aarch32
|
||||
.globl serror_aarch32
|
||||
|
||||
/*
|
||||
* Macro that prepares entry to EL3 upon taking an exception.
|
||||
*
|
||||
* With RAS_EXTENSION, this macro synchronizes pending errors with an ESB
|
||||
* instruction. When an error is thus synchronized, the handling is
|
||||
* delegated to platform EA handler.
|
||||
*
|
||||
* Without RAS_EXTENSION, this macro just saves x30, and unmasks
|
||||
* Asynchronous External Aborts.
|
||||
*/
|
||||
.macro check_and_unmask_ea
|
||||
#if RAS_EXTENSION
|
||||
/* Synchronize pending External Aborts */
|
||||
esb
|
||||
|
||||
/* Unmask the SError interrupt */
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/*
|
||||
* Explicitly save x30 so as to free up a register and to enable
|
||||
* branching
|
||||
*/
|
||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
|
||||
/* Check for SErrors synchronized by the ESB instruction */
|
||||
mrs x30, DISR_EL1
|
||||
tbz x30, #DISR_A_BIT, 1f
|
||||
|
||||
/* Save GP registers and restore them afterwards */
|
||||
bl save_gp_registers
|
||||
mov x0, #ERROR_EA_ESB
|
||||
mrs x1, DISR_EL1
|
||||
bl delegate_ea
|
||||
bl restore_gp_registers
|
||||
|
||||
1:
|
||||
#else
|
||||
/* Unmask the SError interrupt */
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Handle External Abort by delegating to the platform's EA handler.
|
||||
* Once the platform handler returns, the macro exits EL3 and returns to
|
||||
* where the abort was taken from.
|
||||
*
|
||||
* This macro assumes that x30 is available for use.
|
||||
*
|
||||
* 'abort_type' is a constant passed to the platform handler, indicating
|
||||
* the cause of the External Abort.
|
||||
*/
|
||||
.macro handle_ea abort_type
|
||||
/* Save GP registers */
|
||||
bl save_gp_registers
|
||||
|
||||
/* Setup exception class and syndrome arguments for platform handler */
|
||||
mov x0, \abort_type
|
||||
mrs x1, esr_el3
|
||||
adr x30, el3_exit
|
||||
b delegate_ea
|
||||
.endm
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* This macro handles Synchronous exceptions.
|
||||
* Only SMC exceptions are supported.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
.macro handle_sync_exception
|
||||
#if ENABLE_RUNTIME_INSTRUMENTATION
|
||||
/*
|
||||
* Read the timestamp value and store it in per-cpu data. The value
|
||||
* will be extracted from per-cpu data by the C level SMC handler and
|
||||
* saved to the PMF timestamp region.
|
||||
*/
|
||||
mrs x30, cntpct_el0
|
||||
str x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
|
||||
mrs x29, tpidr_el3
|
||||
str x30, [x29, #CPU_DATA_PMF_TS0_OFFSET]
|
||||
ldr x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
|
||||
#endif
|
||||
|
||||
mrs x30, esr_el3
|
||||
ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
|
||||
|
||||
/* Handle SMC exceptions separately from other synchronous exceptions */
|
||||
cmp x30, #EC_AARCH32_SMC
|
||||
b.eq smc_handler32
|
||||
|
||||
cmp x30, #EC_AARCH64_SMC
|
||||
b.eq smc_handler64
|
||||
|
||||
/* Check for I/D aborts from lower EL */
|
||||
cmp x30, #EC_IABORT_LOWER_EL
|
||||
b.eq 1f
|
||||
|
||||
cmp x30, #EC_DABORT_LOWER_EL
|
||||
b.ne 2f
|
||||
|
||||
1:
|
||||
/* Test for EA bit in the instruction syndrome */
|
||||
mrs x30, esr_el3
|
||||
tbz x30, #ESR_ISS_EABORT_EA_BIT, 2f
|
||||
handle_ea #ERROR_EA_SYNC
|
||||
|
||||
2:
|
||||
/* Other kinds of synchronous exceptions are not handled */
|
||||
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
b report_unhandled_exception
|
||||
.endm
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* This macro handles FIQ or IRQ interrupts i.e. EL3, S-EL1 and NS
|
||||
* interrupts.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
.macro handle_interrupt_exception label
|
||||
bl save_gp_registers
|
||||
/* Save the EL3 system registers needed to return from this exception */
|
||||
mrs x0, spsr_el3
|
||||
mrs x1, elr_el3
|
||||
stp x0, x1, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
|
||||
|
||||
/* Switch to the runtime stack i.e. SP_EL0 */
|
||||
ldr x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
|
||||
mov x20, sp
|
||||
msr spsel, #0
|
||||
mov sp, x2
|
||||
|
||||
/*
|
||||
* Find out whether this is a valid interrupt type.
|
||||
* If the interrupt controller reports a spurious interrupt then return
|
||||
* to where we came from.
|
||||
*/
|
||||
bl plat_ic_get_pending_interrupt_type
|
||||
cmp x0, #INTR_TYPE_INVAL
|
||||
b.eq interrupt_exit_\label
|
||||
|
||||
/*
|
||||
* Get the registered handler for this interrupt type.
|
||||
* A NULL return value could be 'cause of the following conditions:
|
||||
*
|
||||
* a. An interrupt of a type was routed correctly but a handler for its
|
||||
* type was not registered.
|
||||
*
|
||||
* b. An interrupt of a type was not routed correctly so a handler for
|
||||
* its type was not registered.
|
||||
*
|
||||
* c. An interrupt of a type was routed correctly to EL3, but was
|
||||
* deasserted before its pending state could be read. Another
|
||||
* interrupt of a different type pended at the same time and its
|
||||
* type was reported as pending instead. However, a handler for this
|
||||
* type was not registered.
|
||||
*
|
||||
* a. and b. can only happen due to a programming error. The
|
||||
* occurrence of c. could be beyond the control of Trusted Firmware.
|
||||
* It makes sense to return from this exception instead of reporting an
|
||||
* error.
|
||||
*/
|
||||
bl get_interrupt_type_handler
|
||||
cbz x0, interrupt_exit_\label
|
||||
mov x21, x0
|
||||
|
||||
mov x0, #INTR_ID_UNAVAILABLE
|
||||
|
||||
/* Set the current security state in the 'flags' parameter */
|
||||
mrs x2, scr_el3
|
||||
ubfx x1, x2, #0, #1
|
||||
|
||||
/* Restore the reference to the 'handle' i.e. SP_EL3 */
|
||||
mov x2, x20
|
||||
|
||||
/* x3 will point to a cookie (not used now) */
|
||||
mov x3, xzr
|
||||
|
||||
/* Call the interrupt type handler */
|
||||
blr x21
|
||||
|
||||
interrupt_exit_\label:
|
||||
/* Return from exception, possibly in a different security state */
|
||||
b el3_exit
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
vector_base runtime_exceptions
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Current EL with SP_EL0 : 0x0 - 0x200
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_sp_el0
|
||||
/* We don't expect any synchronous exceptions from EL3 */
|
||||
b report_unhandled_exception
|
||||
check_vector_size sync_exception_sp_el0
|
||||
|
||||
vector_entry irq_sp_el0
|
||||
/*
|
||||
* EL3 code is non-reentrant. Any asynchronous exception is a serious
|
||||
* error. Loop infinitely.
|
||||
*/
|
||||
b report_unhandled_interrupt
|
||||
check_vector_size irq_sp_el0
|
||||
|
||||
|
||||
vector_entry fiq_sp_el0
|
||||
b report_unhandled_interrupt
|
||||
check_vector_size fiq_sp_el0
|
||||
|
||||
|
||||
vector_entry serror_sp_el0
|
||||
b report_unhandled_exception
|
||||
check_vector_size serror_sp_el0
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Current EL with SP_ELx: 0x200 - 0x400
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_sp_elx
|
||||
/*
|
||||
* This exception will trigger if anything went wrong during a previous
|
||||
* exception entry or exit or while handling an earlier unexpected
|
||||
* synchronous exception. There is a high probability that SP_EL3 is
|
||||
* corrupted.
|
||||
*/
|
||||
b report_unhandled_exception
|
||||
check_vector_size sync_exception_sp_elx
|
||||
|
||||
vector_entry irq_sp_elx
|
||||
b report_unhandled_interrupt
|
||||
check_vector_size irq_sp_elx
|
||||
|
||||
vector_entry fiq_sp_elx
|
||||
b report_unhandled_interrupt
|
||||
check_vector_size fiq_sp_elx
|
||||
|
||||
vector_entry serror_sp_elx
|
||||
b report_unhandled_exception
|
||||
check_vector_size serror_sp_elx
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Lower EL using AArch64 : 0x400 - 0x600
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_aarch64
|
||||
/*
|
||||
* This exception vector will be the entry point for SMCs and traps
|
||||
* that are unhandled at lower ELs most commonly. SP_EL3 should point
|
||||
* to a valid cpu context where the general purpose and system register
|
||||
* state can be saved.
|
||||
*/
|
||||
check_and_unmask_ea
|
||||
handle_sync_exception
|
||||
check_vector_size sync_exception_aarch64
|
||||
|
||||
vector_entry irq_aarch64
|
||||
check_and_unmask_ea
|
||||
handle_interrupt_exception irq_aarch64
|
||||
check_vector_size irq_aarch64
|
||||
|
||||
vector_entry fiq_aarch64
|
||||
check_and_unmask_ea
|
||||
handle_interrupt_exception fiq_aarch64
|
||||
check_vector_size fiq_aarch64
|
||||
|
||||
vector_entry serror_aarch64
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/*
|
||||
* Explicitly save x30 so as to free up a register and to enable
|
||||
* branching
|
||||
*/
|
||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
handle_ea #ERROR_EA_ASYNC
|
||||
check_vector_size serror_aarch64
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Lower EL using AArch32 : 0x600 - 0x800
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_aarch32
|
||||
/*
|
||||
* This exception vector will be the entry point for SMCs and traps
|
||||
* that are unhandled at lower ELs most commonly. SP_EL3 should point
|
||||
* to a valid cpu context where the general purpose and system register
|
||||
* state can be saved.
|
||||
*/
|
||||
check_and_unmask_ea
|
||||
handle_sync_exception
|
||||
check_vector_size sync_exception_aarch32
|
||||
|
||||
vector_entry irq_aarch32
|
||||
check_and_unmask_ea
|
||||
handle_interrupt_exception irq_aarch32
|
||||
check_vector_size irq_aarch32
|
||||
|
||||
vector_entry fiq_aarch32
|
||||
check_and_unmask_ea
|
||||
handle_interrupt_exception fiq_aarch32
|
||||
check_vector_size fiq_aarch32
|
||||
|
||||
vector_entry serror_aarch32
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/*
|
||||
* Explicitly save x30 so as to free up a register and to enable
|
||||
* branching
|
||||
*/
|
||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
handle_ea #ERROR_EA_ASYNC
|
||||
check_vector_size serror_aarch32
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* This macro takes an argument in x16 that is the index in the
|
||||
* 'rt_svc_descs_indices' array, checks that the value in the array is
|
||||
* valid, and loads in x15 the pointer to the handler of that service.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
.macro load_rt_svc_desc_pointer
|
||||
/* Load descriptor index from array of indices */
|
||||
adr x14, rt_svc_descs_indices
|
||||
ldrb w15, [x14, x16]
|
||||
|
||||
#if SMCCC_MAJOR_VERSION == 1
|
||||
/* Any index greater than 127 is invalid. Check bit 7. */
|
||||
tbnz w15, 7, smc_unknown
|
||||
#elif SMCCC_MAJOR_VERSION == 2
|
||||
/* Verify that the top 3 bits of the loaded index are 0 (w15 <= 31) */
|
||||
cmp w15, #31
|
||||
b.hi smc_unknown
|
||||
#endif /* SMCCC_MAJOR_VERSION */
|
||||
|
||||
/*
|
||||
* Get the descriptor using the index
|
||||
* x11 = (base + off), w15 = index
|
||||
*
|
||||
* handler = (base + off) + (index << log2(size))
|
||||
*/
|
||||
adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
|
||||
lsl w10, w15, #RT_SVC_SIZE_LOG2
|
||||
ldr x15, [x11, w10, uxtw]
|
||||
.endm
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* The following code handles secure monitor calls.
|
||||
* Depending upon the execution state from where the SMC has been
|
||||
* invoked, it frees some general purpose registers to perform the
|
||||
* remaining tasks. They involve finding the runtime service handler
|
||||
* that is the target of the SMC & switching to runtime stacks (SP_EL0)
|
||||
* before calling the handler.
|
||||
*
|
||||
* Note that x30 has been explicitly saved and can be used here
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func smc_handler
|
||||
smc_handler32:
|
||||
/* Check whether aarch32 issued an SMC64 */
|
||||
tbnz x0, #FUNCID_CC_SHIFT, smc_prohibited
|
||||
|
||||
smc_handler64:
|
||||
/*
|
||||
* Populate the parameters for the SMC handler.
|
||||
* We already have x0-x4 in place. x5 will point to a cookie (not used
|
||||
* now). x6 will point to the context structure (SP_EL3) and x7 will
|
||||
* contain flags we need to pass to the handler.
|
||||
*
|
||||
* Save x4-x29 and sp_el0.
|
||||
*/
|
||||
stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
|
||||
stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
|
||||
stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
|
||||
stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
|
||||
stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
|
||||
stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
|
||||
stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
|
||||
stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
|
||||
stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
|
||||
stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
|
||||
stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
|
||||
stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
|
||||
stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
|
||||
mrs x18, sp_el0
|
||||
str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0]
|
||||
|
||||
mov x5, xzr
|
||||
mov x6, sp
|
||||
|
||||
#if SMCCC_MAJOR_VERSION == 1
|
||||
|
||||
/* Get the unique owning entity number */
|
||||
ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH
|
||||
ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH
|
||||
orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH
|
||||
|
||||
load_rt_svc_desc_pointer
|
||||
|
||||
#elif SMCCC_MAJOR_VERSION == 2
|
||||
|
||||
/* Bit 31 must be set */
|
||||
tbz x0, #FUNCID_TYPE_SHIFT, smc_unknown
|
||||
|
||||
/*
|
||||
* Check MSB of namespace to decide between compatibility/vendor and
|
||||
* SPCI/SPRT
|
||||
*/
|
||||
tbz x0, #(FUNCID_NAMESPACE_SHIFT + 1), compat_or_vendor
|
||||
|
||||
/* Namespaces SPRT and SPCI currently unimplemented */
|
||||
b smc_unknown
|
||||
|
||||
compat_or_vendor:
|
||||
|
||||
/* Namespace is b'00 (compatibility) or b'01 (vendor) */
|
||||
|
||||
/*
|
||||
* Add the LSB of the namespace (bit [28]) to the OEN [27:24] to create
|
||||
* a 5-bit index into the rt_svc_descs_indices array.
|
||||
*
|
||||
* The low 16 entries of the rt_svc_descs_indices array correspond to
|
||||
* OENs of the compatibility namespace and the top 16 entries of the
|
||||
* array are assigned to the vendor namespace descriptor.
|
||||
*/
|
||||
ubfx x16, x0, #FUNCID_OEN_SHIFT, #(FUNCID_OEN_WIDTH + 1)
|
||||
|
||||
load_rt_svc_desc_pointer
|
||||
|
||||
#endif /* SMCCC_MAJOR_VERSION */
|
||||
|
||||
/*
|
||||
* Restore the saved C runtime stack value which will become the new
|
||||
* SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context'
|
||||
* structure prior to the last ERET from EL3.
|
||||
*/
|
||||
ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
|
||||
|
||||
/* Switch to SP_EL0 */
|
||||
msr spsel, #0
|
||||
|
||||
/*
|
||||
* Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there is a world
|
||||
* switch during SMC handling.
|
||||
* TODO: Revisit if all system registers can be saved later.
|
||||
*/
|
||||
mrs x16, spsr_el3
|
||||
mrs x17, elr_el3
|
||||
mrs x18, scr_el3
|
||||
stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
|
||||
str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
|
||||
|
||||
/* Copy SCR_EL3.NS bit to the flag to indicate caller's security */
|
||||
bfi x7, x18, #0, #1
|
||||
|
||||
mov sp, x12
|
||||
|
||||
/*
|
||||
* Call the Secure Monitor Call handler and then drop directly into
|
||||
* el3_exit() which will program any remaining architectural state
|
||||
* prior to issuing the ERET to the desired lower EL.
|
||||
*/
|
||||
#if DEBUG
|
||||
cbz x15, rt_svc_fw_critical_error
|
||||
#endif
|
||||
blr x15
|
||||
|
||||
b el3_exit
|
||||
|
||||
smc_unknown:
|
||||
/*
|
||||
* Unknown SMC call. Populate return value with SMC_UNK, restore
|
||||
* GP registers, and return to caller.
|
||||
*/
|
||||
mov x0, #SMC_UNK
|
||||
str x0, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
|
||||
b restore_gp_registers_eret
|
||||
|
||||
smc_prohibited:
|
||||
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
mov x0, #SMC_UNK
|
||||
eret
|
||||
|
||||
rt_svc_fw_critical_error:
|
||||
/* Switch to SP_ELx */
|
||||
msr spsel, #1
|
||||
no_ret report_unhandled_exception
|
||||
endfunc smc_handler
|
||||
|
||||
/*
|
||||
* Delegate External Abort handling to platform's EA handler. This function
|
||||
* assumes that all GP registers have been saved by the caller.
|
||||
*
|
||||
* x0: EA reason
|
||||
* x1: EA syndrome
|
||||
*/
|
||||
func delegate_ea
|
||||
/* Save EL3 state */
|
||||
mrs x2, spsr_el3
|
||||
mrs x3, elr_el3
|
||||
stp x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
|
||||
|
||||
/*
|
||||
* Save ESR as handling might involve lower ELs, and returning back to
|
||||
* EL3 from there would trample the original ESR.
|
||||
*/
|
||||
mrs x4, scr_el3
|
||||
mrs x5, esr_el3
|
||||
stp x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
|
||||
|
||||
/*
|
||||
* Setup rest of arguments, and call platform External Abort handler.
|
||||
*
|
||||
* x0: EA reason (already in place)
|
||||
* x1: Exception syndrome (already in place).
|
||||
* x2: Cookie (unused for now).
|
||||
* x3: Context pointer.
|
||||
* x4: Flags (security state from SCR for now).
|
||||
*/
|
||||
mov x2, xzr
|
||||
mov x3, sp
|
||||
ubfx x4, x4, #0, #1
|
||||
|
||||
/* Switch to runtime stack */
|
||||
ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
|
||||
msr spsel, #0
|
||||
mov sp, x5
|
||||
|
||||
mov x29, x30
|
||||
bl plat_ea_handler
|
||||
mov x30, x29
|
||||
|
||||
/* Make SP point to context */
|
||||
msr spsel, #1
|
||||
|
||||
/* Restore EL3 state */
|
||||
ldp x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
|
||||
msr spsr_el3, x1
|
||||
msr elr_el3, x2
|
||||
|
||||
/* Restore ESR_EL3 and SCR_EL3 */
|
||||
ldp x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
|
||||
msr scr_el3, x3
|
||||
msr esr_el3, x4
|
||||
|
||||
ret
|
||||
endfunc delegate_ea
|
||||
268
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/bl31.ld.S
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
||||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
||||
ENTRY(bl31_entrypoint)
|
||||
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE
|
||||
}
|
||||
|
||||
#ifdef PLAT_EXTRA_LD_SCRIPT
|
||||
#include <plat.ld.S>
|
||||
#endif
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BL31_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL31_BASE address is not aligned on a page boundary.")
|
||||
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
.text . : {
|
||||
__TEXT_START__ = .;
|
||||
*bl31_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.vectors)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__TEXT_END__ = .;
|
||||
} >RAM
|
||||
|
||||
.rodata . : {
|
||||
__RODATA_START__ = .;
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__RT_SVC_DESCS_START__ = .;
|
||||
KEEP(*(rt_svc_descs))
|
||||
__RT_SVC_DESCS_END__ = .;
|
||||
|
||||
#if ENABLE_PMF
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PMF_SVC_DESCS_START__ = .;
|
||||
KEEP(*(pmf_svc_descs))
|
||||
__PMF_SVC_DESCS_END__ = .;
|
||||
#endif /* ENABLE_PMF */
|
||||
|
||||
/*
|
||||
* Ensure 8-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(8);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
/* Place pubsub sections for events */
|
||||
. = ALIGN(8);
|
||||
#include <pubsub_events.h>
|
||||
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RODATA_END__ = .;
|
||||
} >RAM
|
||||
#else
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
*bl31_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__RT_SVC_DESCS_START__ = .;
|
||||
KEEP(*(rt_svc_descs))
|
||||
__RT_SVC_DESCS_END__ = .;
|
||||
|
||||
#if ENABLE_PMF
|
||||
/* Ensure 8-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(8);
|
||||
__PMF_SVC_DESCS_START__ = .;
|
||||
KEEP(*(pmf_svc_descs))
|
||||
__PMF_SVC_DESCS_END__ = .;
|
||||
#endif /* ENABLE_PMF */
|
||||
|
||||
/*
|
||||
* Ensure 8-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(8);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
/* Place pubsub sections for events */
|
||||
. = ALIGN(8);
|
||||
#include <pubsub_events.h>
|
||||
|
||||
*(.vectors)
|
||||
__RO_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked as read-only,
|
||||
* executable. No RW data from the next section must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RO_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
|
||||
"cpu_ops not defined for this platform.")
|
||||
|
||||
#if ENABLE_SPM
|
||||
/*
|
||||
* Exception vectors of the SPM shim layer. They must be aligned to a 2K
|
||||
* address, but we need to place them in a separate page so that we can set
|
||||
* individual permissions to them, so the actual alignment needed is 4K.
|
||||
*
|
||||
* There's no need to include this into the RO section of BL31 because it
|
||||
* doesn't need to be accessed by BL31.
|
||||
*/
|
||||
spm_shim_exceptions : ALIGN(PAGE_SIZE) {
|
||||
__SPM_SHIM_EXCEPTIONS_START__ = .;
|
||||
*(.spm_shim_exceptions)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__SPM_SHIM_EXCEPTIONS_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark start of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_START__ = . ;
|
||||
|
||||
/*
|
||||
* .data must be placed at a lower address than the stacks if the stack
|
||||
* protector is enabled. Alternatively, the .data.stack_protector_canary
|
||||
* section can be placed independently of the main .data section.
|
||||
*/
|
||||
.data . : {
|
||||
__DATA_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_END__ = .;
|
||||
} >RAM
|
||||
|
||||
#ifdef BL31_PROGBITS_LIMIT
|
||||
ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.")
|
||||
#endif
|
||||
|
||||
stacks (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The .bss section gets initialised to 0 at runtime.
|
||||
* Its base address should be 16-byte aligned for better performance of the
|
||||
* zero-initialization code.
|
||||
*/
|
||||
.bss (NOLOAD) : ALIGN(16) {
|
||||
__BSS_START__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
#if !USE_COHERENT_MEM
|
||||
/*
|
||||
* Bakery locks are stored in normal .bss memory
|
||||
*
|
||||
* Each lock's data is spread across multiple cache lines, one per CPU,
|
||||
* but multiple locks can share the same cache line.
|
||||
* The compiler will allocate enough memory for one CPU's bakery locks,
|
||||
* the remaining cache lines are allocated by the linker script
|
||||
*/
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__BAKERY_LOCK_START__ = .;
|
||||
*(bakery_lock)
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(. - __BAKERY_LOCK_START__);
|
||||
. = . + (__PERCPU_BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1));
|
||||
__BAKERY_LOCK_END__ = .;
|
||||
#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE
|
||||
ASSERT(__PERCPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE,
|
||||
"PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLE_PMF
|
||||
/*
|
||||
* Time-stamps are stored in normal .bss memory
|
||||
*
|
||||
* The compiler will allocate enough memory for one CPU's time-stamps,
|
||||
* the remaining memory for other CPU's is allocated by the
|
||||
* linker script
|
||||
*/
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__PMF_TIMESTAMP_START__ = .;
|
||||
KEEP(*(pmf_timestamp_array))
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__PMF_PERCPU_TIMESTAMP_END__ = .;
|
||||
__PERCPU_TIMESTAMP_SIZE__ = ABSOLUTE(. - __PMF_TIMESTAMP_START__);
|
||||
. = . + (__PERCPU_TIMESTAMP_SIZE__ * (PLATFORM_CORE_COUNT - 1));
|
||||
__PMF_TIMESTAMP_END__ = .;
|
||||
#endif /* ENABLE_PMF */
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The xlat_table section is for full, aligned page tables (4K).
|
||||
* Removing them from .bss avoids forcing 4K alignment on
|
||||
* the .bss section. The tables are initialized to zero by the translation
|
||||
* tables library.
|
||||
*/
|
||||
xlat_table (NOLOAD) : {
|
||||
*(xlat_table)
|
||||
} >RAM
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/*
|
||||
* The base address of the coherent memory section must be page-aligned (4K)
|
||||
* to guarantee that the coherent data are stored on their own pages and
|
||||
* are not mixed with normal data. This is required to set up the correct
|
||||
* memory attributes for the coherent data page tables.
|
||||
*/
|
||||
coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
__COHERENT_RAM_START__ = .;
|
||||
/*
|
||||
* Bakery locks are stored in coherent memory
|
||||
*
|
||||
* Each lock's data is contiguous and fully allocated by the compiler
|
||||
*/
|
||||
*(bakery_lock)
|
||||
*(tzfw_coherent_mem)
|
||||
__COHERENT_RAM_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked
|
||||
* as device memory. No other unexpected data must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__COHERENT_RAM_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark end of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_END__ = .;
|
||||
__BL31_END__ = .;
|
||||
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
#if USE_COHERENT_MEM
|
||||
__COHERENT_RAM_UNALIGNED_SIZE__ =
|
||||
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
|
||||
#endif
|
||||
|
||||
ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.")
|
||||
}
|
||||
82
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/bl31.mk
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
#
|
||||
# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
################################################################################
|
||||
# Include SPM Makefile
|
||||
################################################################################
|
||||
ifeq (${ENABLE_SPM},1)
|
||||
$(info Including SPM makefile)
|
||||
include services/std_svc/spm/spm.mk
|
||||
endif
|
||||
|
||||
|
||||
include lib/psci/psci_lib.mk
|
||||
|
||||
BL31_SOURCES += bl31/bl31_main.c \
|
||||
bl31/interrupt_mgmt.c \
|
||||
bl31/aarch64/bl31_entrypoint.S \
|
||||
bl31/aarch64/runtime_exceptions.S \
|
||||
bl31/aarch64/crash_reporting.S \
|
||||
bl31/bl31_context_mgmt.c \
|
||||
common/runtime_svc.c \
|
||||
plat/common/aarch64/platform_mp_stack.S \
|
||||
services/arm_arch_svc/arm_arch_svc_setup.c \
|
||||
services/std_svc/std_svc_setup.c \
|
||||
${PSCI_LIB_SOURCES} \
|
||||
${SPM_SOURCES} \
|
||||
|
||||
|
||||
ifeq (${ENABLE_PMF}, 1)
|
||||
BL31_SOURCES += lib/pmf/pmf_main.c
|
||||
endif
|
||||
|
||||
ifeq (${EL3_EXCEPTION_HANDLING},1)
|
||||
BL31_SOURCES += bl31/ehf.c
|
||||
endif
|
||||
|
||||
ifeq (${SDEI_SUPPORT},1)
|
||||
ifeq (${EL3_EXCEPTION_HANDLING},0)
|
||||
$(error EL3_EXCEPTION_HANDLING must be 1 for SDEI support)
|
||||
endif
|
||||
BL31_SOURCES += services/std_svc/sdei/sdei_event.c \
|
||||
services/std_svc/sdei/sdei_intr_mgmt.c \
|
||||
services/std_svc/sdei/sdei_main.c \
|
||||
services/std_svc/sdei/sdei_state.c
|
||||
endif
|
||||
|
||||
ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1)
|
||||
BL31_SOURCES += lib/extensions/spe/spe.c
|
||||
endif
|
||||
|
||||
ifeq (${ENABLE_AMU},1)
|
||||
BL31_SOURCES += lib/extensions/amu/aarch64/amu.c \
|
||||
lib/extensions/amu/aarch64/amu_helpers.S
|
||||
endif
|
||||
|
||||
ifeq (${ENABLE_SVE_FOR_NS},1)
|
||||
BL31_SOURCES += lib/extensions/sve/sve.c
|
||||
endif
|
||||
|
||||
ifeq (${WORKAROUND_CVE_2017_5715},1)
|
||||
BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \
|
||||
lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
|
||||
endif
|
||||
|
||||
BL31_LINKERFILE := bl31/bl31.ld.S
|
||||
|
||||
# Flag used to indicate if Crash reporting via console should be included
|
||||
# in BL31. This defaults to being present in DEBUG builds only
|
||||
ifndef CRASH_REPORTING
|
||||
CRASH_REPORTING := $(DEBUG)
|
||||
endif
|
||||
|
||||
$(eval $(call assert_boolean,CRASH_REPORTING))
|
||||
$(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING))
|
||||
$(eval $(call assert_boolean,SDEI_SUPPORT))
|
||||
|
||||
$(eval $(call add_define,CRASH_REPORTING))
|
||||
$(eval $(call add_define,EL3_EXCEPTION_HANDLING))
|
||||
$(eval $(call add_define,SDEI_SUPPORT))
|
||||
130
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/bl31_context_mgmt.c
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl31.h>
|
||||
#include <bl_common.h>
|
||||
#include <context.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <cpu_data.h>
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns a pointer to the most recent 'cpu_context' structure
|
||||
* for the calling CPU that was set as the context for the specified security
|
||||
* state. NULL is returned if no such structure has been specified.
|
||||
******************************************************************************/
|
||||
void *cm_get_context(uint32_t security_state)
|
||||
{
|
||||
assert(security_state <= NON_SECURE);
|
||||
|
||||
return get_cpu_data(cpu_context[security_state]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function sets the pointer to the current 'cpu_context' structure for the
|
||||
* specified security state for the calling CPU
|
||||
******************************************************************************/
|
||||
void cm_set_context(void *context, uint32_t security_state)
|
||||
{
|
||||
assert(security_state <= NON_SECURE);
|
||||
|
||||
set_cpu_data(cpu_context[security_state], context);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns a pointer to the most recent 'cpu_context' structure
|
||||
* for the CPU identified by `cpu_idx` that was set as the context for the
|
||||
* specified security state. NULL is returned if no such structure has been
|
||||
* specified.
|
||||
******************************************************************************/
|
||||
void *cm_get_context_by_index(unsigned int cpu_idx,
|
||||
unsigned int security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
|
||||
return get_cpu_data_by_index(cpu_idx, cpu_context[security_state]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function sets the pointer to the current 'cpu_context' structure for the
|
||||
* specified security state for the CPU identified by CPU index.
|
||||
******************************************************************************/
|
||||
void cm_set_context_by_index(unsigned int cpu_idx, void *context,
|
||||
unsigned int security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
|
||||
set_cpu_data_by_index(cpu_idx, cpu_context[security_state], context);
|
||||
}
|
||||
|
||||
#if !ERROR_DEPRECATED
|
||||
/*
|
||||
* These context management helpers are deprecated but are maintained for use
|
||||
* by SPDs which have not migrated to the new API. If ERROR_DEPRECATED
|
||||
* is enabled, these are excluded from the build so as to force users to
|
||||
* migrate to the new API.
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns a pointer to the most recent 'cpu_context' structure
|
||||
* for the CPU identified by MPIDR that was set as the context for the specified
|
||||
* security state. NULL is returned if no such structure has been specified.
|
||||
******************************************************************************/
|
||||
void *cm_get_context_by_mpidr(uint64_t mpidr, uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
|
||||
/*
|
||||
* Suppress deprecated declaration warning in compatibility function
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
return cm_get_context_by_index(platform_get_core_pos(mpidr), security_state);
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function sets the pointer to the current 'cpu_context' structure for the
|
||||
* specified security state for the CPU identified by MPIDR
|
||||
******************************************************************************/
|
||||
void cm_set_context_by_mpidr(uint64_t mpidr, void *context, uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
|
||||
/*
|
||||
* Suppress deprecated declaration warning in compatibility function
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
cm_set_context_by_index(platform_get_core_pos(mpidr),
|
||||
context, security_state);
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* The following function provides a compatibility function for SPDs using the
|
||||
* existing cm library routines. This function is expected to be invoked for
|
||||
* initializing the cpu_context for the CPU specified by MPIDR for first use.
|
||||
******************************************************************************/
|
||||
void cm_init_context(uint64_t mpidr, const entry_point_info_t *ep)
|
||||
{
|
||||
if ((mpidr & MPIDR_AFFINITY_MASK) ==
|
||||
(read_mpidr_el1() & MPIDR_AFFINITY_MASK))
|
||||
cm_init_my_context(ep);
|
||||
else {
|
||||
/*
|
||||
* Suppress deprecated declaration warning in compatibility
|
||||
* function
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
cm_init_context_by_index(platform_get_core_pos(mpidr), ep);
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
}
|
||||
#endif /* ERROR_DEPRECATED */
|
||||
187
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/bl31_main.c
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <bl31.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <debug.h>
|
||||
#include <ehf.h>
|
||||
#include <platform.h>
|
||||
#include <pmf.h>
|
||||
#include <runtime_instr.h>
|
||||
#include <runtime_svc.h>
|
||||
#include <std_svc.h>
|
||||
#include <string.h>
|
||||
|
||||
#if ENABLE_RUNTIME_INSTRUMENTATION
|
||||
PMF_REGISTER_SERVICE_SMC(rt_instr_svc, PMF_RT_INSTR_SVC_ID,
|
||||
RT_INSTR_TOTAL_IDS, PMF_STORE_ENABLE)
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* This function pointer is used to initialise the BL32 image. It's initialized
|
||||
* by SPD calling bl31_register_bl32_init after setting up all things necessary
|
||||
* for SP execution. In cases where both SPD and SP are absent, or when SPD
|
||||
* finds it impossible to execute SP, this pointer is left as NULL
|
||||
******************************************************************************/
|
||||
static int32_t (*bl32_init)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variable to indicate whether next image to execute after BL31 is BL33
|
||||
* (non-secure & default) or BL32 (secure).
|
||||
******************************************************************************/
|
||||
static uint32_t next_image_type = NON_SECURE;
|
||||
|
||||
/*
|
||||
* Implement the ARM Standard Service function to get arguments for a
|
||||
* particular service.
|
||||
*/
|
||||
uintptr_t get_arm_std_svc_args(unsigned int svc_mask)
|
||||
{
|
||||
/* Setup the arguments for PSCI Library */
|
||||
DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, bl31_warm_entrypoint);
|
||||
|
||||
/* PSCI is the only ARM Standard Service implemented */
|
||||
assert(svc_mask == PSCI_FID_MASK);
|
||||
|
||||
return (uintptr_t)&psci_args;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Simple function to initialise all BL31 helper libraries.
|
||||
******************************************************************************/
|
||||
void bl31_lib_init(void)
|
||||
{
|
||||
cm_init();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* BL31 is responsible for setting up the runtime services for the primary cpu
|
||||
* before passing control to the bootloader or an Operating System. This
|
||||
* function calls runtime_svc_init() which initializes all registered runtime
|
||||
* services. The run time services would setup enough context for the core to
|
||||
* swtich to the next exception level. When this function returns, the core will
|
||||
* switch to the programmed exception level via. an ERET.
|
||||
******************************************************************************/
|
||||
void bl31_main(void)
|
||||
{
|
||||
NOTICE("BL31: %s\n", version_string);
|
||||
NOTICE("BL31: %s\n", build_message);
|
||||
|
||||
/* Perform platform setup in BL31 */
|
||||
bl31_platform_setup();
|
||||
|
||||
/* Initialise helper libraries */
|
||||
bl31_lib_init();
|
||||
|
||||
#if EL3_EXCEPTION_HANDLING
|
||||
INFO("BL31: Initialising Exception Handling Framework\n");
|
||||
ehf_init();
|
||||
#endif
|
||||
|
||||
/* Initialize the runtime services e.g. psci. */
|
||||
INFO("BL31: Initializing runtime services\n");
|
||||
runtime_svc_init();
|
||||
|
||||
/*
|
||||
* All the cold boot actions on the primary cpu are done. We now need to
|
||||
* decide which is the next image (BL32 or BL33) and how to execute it.
|
||||
* If the SPD runtime service is present, it would want to pass control
|
||||
* to BL32 first in S-EL1. In that case, SPD would have registered a
|
||||
* function to intialize bl32 where it takes responsibility of entering
|
||||
* S-EL1 and returning control back to bl31_main. Once this is done we
|
||||
* can prepare entry into BL33 as normal.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If SPD had registerd an init hook, invoke it.
|
||||
*/
|
||||
if (bl32_init) {
|
||||
INFO("BL31: Initializing BL32\n");
|
||||
(*bl32_init)();
|
||||
}
|
||||
/*
|
||||
* We are ready to enter the next EL. Prepare entry into the image
|
||||
* corresponding to the desired security state after the next ERET.
|
||||
*/
|
||||
bl31_prepare_next_image_entry();
|
||||
|
||||
console_flush();
|
||||
|
||||
/*
|
||||
* Perform any platform specific runtime setup prior to cold boot exit
|
||||
* from BL31
|
||||
*/
|
||||
bl31_plat_runtime_setup();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Accessor functions to help runtime services decide which image should be
|
||||
* executed after BL31. This is BL33 or the non-secure bootloader image by
|
||||
* default but the Secure payload dispatcher could override this by requesting
|
||||
* an entry into BL32 (Secure payload) first. If it does so then it should use
|
||||
* the same API to program an entry into BL33 once BL32 initialisation is
|
||||
* complete.
|
||||
******************************************************************************/
|
||||
void bl31_set_next_image_type(uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
next_image_type = security_state;
|
||||
}
|
||||
|
||||
uint32_t bl31_get_next_image_type(void)
|
||||
{
|
||||
return next_image_type;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function programs EL3 registers and performs other setup to enable entry
|
||||
* into the next image after BL31 at the next ERET.
|
||||
******************************************************************************/
|
||||
void bl31_prepare_next_image_entry(void)
|
||||
{
|
||||
entry_point_info_t *next_image_info;
|
||||
uint32_t image_type;
|
||||
|
||||
#if CTX_INCLUDE_AARCH32_REGS
|
||||
/*
|
||||
* Ensure that the build flag to save AArch32 system registers in CPU
|
||||
* context is not set for AArch64-only platforms.
|
||||
*/
|
||||
if (EL_IMPLEMENTED(1) == EL_IMPL_A64ONLY) {
|
||||
ERROR("EL1 supports AArch64-only. Please set build flag "
|
||||
"CTX_INCLUDE_AARCH32_REGS = 0");
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine which image to execute next */
|
||||
image_type = bl31_get_next_image_type();
|
||||
|
||||
/* Program EL3 registers to enable entry into the next EL */
|
||||
next_image_info = bl31_plat_get_next_image_ep_info(image_type);
|
||||
assert(next_image_info);
|
||||
assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));
|
||||
|
||||
INFO("BL31: Preparing for EL3 exit to %s world\n",
|
||||
(image_type == SECURE) ? "secure" : "normal");
|
||||
print_entry_point_info(next_image_info);
|
||||
cm_init_my_context(next_image_info);
|
||||
cm_prepare_el3_exit(image_type);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function initializes the pointer to BL32 init function. This is expected
|
||||
* to be called by the SPD after it finishes all its initialization
|
||||
******************************************************************************/
|
||||
void bl31_register_bl32_init(int32_t (*func)(void))
|
||||
{
|
||||
bl32_init = func;
|
||||
}
|
||||
517
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/ehf.c
vendored
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* Exception handlers at EL3, their priority levels, and management.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <context.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <cpu_data.h>
|
||||
#include <debug.h>
|
||||
#include <ehf.h>
|
||||
#include <gic_common.h>
|
||||
#include <interrupt_mgmt.h>
|
||||
#include <platform.h>
|
||||
#include <pubsub_events.h>
|
||||
|
||||
/* Output EHF logs as verbose */
|
||||
#define EHF_LOG(...) VERBOSE("EHF: " __VA_ARGS__)
|
||||
|
||||
#define EHF_INVALID_IDX (-1)
|
||||
|
||||
/* For a valid handler, return the actual function pointer; otherwise, 0. */
|
||||
#define RAW_HANDLER(h) \
|
||||
((ehf_handler_t) ((h & _EHF_PRI_VALID) ? (h & ~_EHF_PRI_VALID) : 0))
|
||||
|
||||
#define PRI_BIT(idx) (((ehf_pri_bits_t) 1) << idx)
|
||||
|
||||
/*
|
||||
* Convert index into secure priority using the platform-defined priority bits
|
||||
* field.
|
||||
*/
|
||||
#define IDX_TO_PRI(idx) \
|
||||
((idx << (7 - exception_data.pri_bits)) & 0x7f)
|
||||
|
||||
/* Check whether a given index is valid */
|
||||
#define IS_IDX_VALID(idx) \
|
||||
((exception_data.ehf_priorities[idx].ehf_handler & _EHF_PRI_VALID) != 0)
|
||||
|
||||
/* Returns whether given priority is in secure priority range */
|
||||
#define IS_PRI_SECURE(pri) ((pri & 0x80) == 0)
|
||||
|
||||
/* To be defined by the platform */
|
||||
extern const ehf_priorities_t exception_data;
|
||||
|
||||
/* Translate priority to the index in the priority array */
|
||||
static int pri_to_idx(unsigned int priority)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = EHF_PRI_TO_IDX(priority, exception_data.pri_bits);
|
||||
assert((idx >= 0) && (idx < exception_data.num_priorities));
|
||||
assert(IS_IDX_VALID(idx));
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* Return whether there are outstanding priority activation */
|
||||
static int has_valid_pri_activations(pe_exc_data_t *pe_data)
|
||||
{
|
||||
return pe_data->active_pri_bits != 0;
|
||||
}
|
||||
|
||||
static pe_exc_data_t *this_cpu_data(void)
|
||||
{
|
||||
return &get_cpu_data(ehf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current priority index of this CPU. If no priority is active,
|
||||
* return EHF_INVALID_IDX.
|
||||
*/
|
||||
static int get_pe_highest_active_idx(pe_exc_data_t *pe_data)
|
||||
{
|
||||
if (!has_valid_pri_activations(pe_data))
|
||||
return EHF_INVALID_IDX;
|
||||
|
||||
/* Current priority is the right-most bit */
|
||||
return __builtin_ctz(pe_data->active_pri_bits);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark priority active by setting the corresponding bit in active_pri_bits and
|
||||
* programming the priority mask.
|
||||
*
|
||||
* This API is to be used as part of delegating to lower ELs other than for
|
||||
* interrupts; e.g. while handling synchronous exceptions.
|
||||
*
|
||||
* This API is expected to be invoked before restoring context (Secure or
|
||||
* Non-secure) in preparation for the respective dispatch.
|
||||
*/
|
||||
void ehf_activate_priority(unsigned int priority)
|
||||
{
|
||||
int idx, cur_pri_idx;
|
||||
unsigned int old_mask, run_pri;
|
||||
pe_exc_data_t *pe_data = this_cpu_data();
|
||||
|
||||
/*
|
||||
* Query interrupt controller for the running priority, or idle priority
|
||||
* if no interrupts are being handled. The requested priority must be
|
||||
* less (higher priority) than the active running priority.
|
||||
*/
|
||||
run_pri = plat_ic_get_running_priority();
|
||||
if (priority >= run_pri) {
|
||||
ERROR("Running priority higher (0x%x) than requested (0x%x)\n",
|
||||
run_pri, priority);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* If there were priority activations already, the requested priority
|
||||
* must be less (higher priority) than the current highest priority
|
||||
* activation so far.
|
||||
*/
|
||||
cur_pri_idx = get_pe_highest_active_idx(pe_data);
|
||||
idx = pri_to_idx(priority);
|
||||
if ((cur_pri_idx != EHF_INVALID_IDX) && (idx >= cur_pri_idx)) {
|
||||
ERROR("Activation priority mismatch: req=0x%x current=0x%x\n",
|
||||
priority, IDX_TO_PRI(cur_pri_idx));
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Set the bit corresponding to the requested priority */
|
||||
pe_data->active_pri_bits |= PRI_BIT(idx);
|
||||
|
||||
/*
|
||||
* Program priority mask for the activated level. Check that the new
|
||||
* priority mask is setting a higher priority level than the existing
|
||||
* mask.
|
||||
*/
|
||||
old_mask = plat_ic_set_priority_mask(priority);
|
||||
if (priority >= old_mask) {
|
||||
ERROR("Requested priority (0x%x) lower than Priority Mask (0x%x)\n",
|
||||
priority, old_mask);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is the first activation, save the priority mask. This will be
|
||||
* restored after the last deactivation.
|
||||
*/
|
||||
if (cur_pri_idx == EHF_INVALID_IDX)
|
||||
pe_data->init_pri_mask = old_mask;
|
||||
|
||||
EHF_LOG("activate prio=%d\n", get_pe_highest_active_idx(pe_data));
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark priority inactive by clearing the corresponding bit in active_pri_bits,
|
||||
* and programming the priority mask.
|
||||
*
|
||||
* This API is expected to be used as part of delegating to to lower ELs other
|
||||
* than for interrupts; e.g. while handling synchronous exceptions.
|
||||
*
|
||||
* This API is expected to be invoked after saving context (Secure or
|
||||
* Non-secure), having concluded the respective dispatch.
|
||||
*/
|
||||
void ehf_deactivate_priority(unsigned int priority)
|
||||
{
|
||||
int idx, cur_pri_idx;
|
||||
pe_exc_data_t *pe_data = this_cpu_data();
|
||||
unsigned int old_mask, run_pri;
|
||||
|
||||
/*
|
||||
* Query interrupt controller for the running priority, or idle priority
|
||||
* if no interrupts are being handled. The requested priority must be
|
||||
* less (higher priority) than the active running priority.
|
||||
*/
|
||||
run_pri = plat_ic_get_running_priority();
|
||||
if (priority >= run_pri) {
|
||||
ERROR("Running priority higher (0x%x) than requested (0x%x)\n",
|
||||
run_pri, priority);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Deactivation is allowed only when there are priority activations, and
|
||||
* the deactivation priority level must match the current activated
|
||||
* priority.
|
||||
*/
|
||||
cur_pri_idx = get_pe_highest_active_idx(pe_data);
|
||||
idx = pri_to_idx(priority);
|
||||
if ((cur_pri_idx == EHF_INVALID_IDX) || (idx != cur_pri_idx)) {
|
||||
ERROR("Deactivation priority mismatch: req=0x%x current=0x%x\n",
|
||||
priority, IDX_TO_PRI(cur_pri_idx));
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Clear bit corresponding to highest priority */
|
||||
pe_data->active_pri_bits &= (pe_data->active_pri_bits - 1);
|
||||
|
||||
/*
|
||||
* Restore priority mask corresponding to the next priority, or the
|
||||
* one stashed earlier if there are no more to deactivate.
|
||||
*/
|
||||
idx = get_pe_highest_active_idx(pe_data);
|
||||
if (idx == EHF_INVALID_IDX)
|
||||
old_mask = plat_ic_set_priority_mask(pe_data->init_pri_mask);
|
||||
else
|
||||
old_mask = plat_ic_set_priority_mask(priority);
|
||||
|
||||
if (old_mask > priority) {
|
||||
ERROR("Deactivation priority (0x%x) lower than Priority Mask (0x%x)\n",
|
||||
priority, old_mask);
|
||||
panic();
|
||||
}
|
||||
|
||||
EHF_LOG("deactivate prio=%d\n", get_pe_highest_active_idx(pe_data));
|
||||
}
|
||||
|
||||
/*
|
||||
* After leaving Non-secure world, stash current Non-secure Priority Mask, and
|
||||
* set Priority Mask to the highest Non-secure priority so that Non-secure
|
||||
* interrupts cannot preempt Secure execution.
|
||||
*
|
||||
* If the current running priority is in the secure range, or if there are
|
||||
* outstanding priority activations, this function does nothing.
|
||||
*
|
||||
* This function subscribes to the 'cm_exited_normal_world' event published by
|
||||
* the Context Management Library.
|
||||
*/
|
||||
static void *ehf_exited_normal_world(const void *arg)
|
||||
{
|
||||
unsigned int run_pri;
|
||||
pe_exc_data_t *pe_data = this_cpu_data();
|
||||
|
||||
/* If the running priority is in the secure range, do nothing */
|
||||
run_pri = plat_ic_get_running_priority();
|
||||
if (IS_PRI_SECURE(run_pri))
|
||||
return 0;
|
||||
|
||||
/* Do nothing if there are explicit activations */
|
||||
if (has_valid_pri_activations(pe_data))
|
||||
return 0;
|
||||
|
||||
assert(pe_data->ns_pri_mask == 0);
|
||||
|
||||
pe_data->ns_pri_mask =
|
||||
plat_ic_set_priority_mask(GIC_HIGHEST_NS_PRIORITY);
|
||||
|
||||
/* The previous Priority Mask is not expected to be in secure range */
|
||||
if (IS_PRI_SECURE(pe_data->ns_pri_mask)) {
|
||||
ERROR("Priority Mask (0x%x) already in secure range\n",
|
||||
pe_data->ns_pri_mask);
|
||||
panic();
|
||||
}
|
||||
|
||||
EHF_LOG("Priority Mask: 0x%x => 0x%x\n", pe_data->ns_pri_mask,
|
||||
GIC_HIGHEST_NS_PRIORITY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conclude Secure execution and prepare for return to Non-secure world. Restore
|
||||
* the Non-secure Priority Mask previously stashed upon leaving Non-secure
|
||||
* world.
|
||||
*
|
||||
* If there the current running priority is in the secure range, or if there are
|
||||
* outstanding priority activations, this function does nothing.
|
||||
*
|
||||
* This function subscribes to the 'cm_entering_normal_world' event published by
|
||||
* the Context Management Library.
|
||||
*/
|
||||
static void *ehf_entering_normal_world(const void *arg)
|
||||
{
|
||||
unsigned int old_pmr, run_pri;
|
||||
pe_exc_data_t *pe_data = this_cpu_data();
|
||||
|
||||
/* If the running priority is in the secure range, do nothing */
|
||||
run_pri = plat_ic_get_running_priority();
|
||||
if (IS_PRI_SECURE(run_pri))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If there are explicit activations, do nothing. The Priority Mask will
|
||||
* be restored upon the last deactivation.
|
||||
*/
|
||||
if (has_valid_pri_activations(pe_data))
|
||||
return 0;
|
||||
|
||||
/* Do nothing if we don't have a valid Priority Mask to restore */
|
||||
if (pe_data->ns_pri_mask == 0)
|
||||
return 0;
|
||||
|
||||
old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask);
|
||||
|
||||
/*
|
||||
* When exiting secure world, the current Priority Mask must be
|
||||
* GIC_HIGHEST_NS_PRIORITY (as set during entry), or the Non-secure
|
||||
* priority mask set upon calling ehf_allow_ns_preemption()
|
||||
*/
|
||||
if ((old_pmr != GIC_HIGHEST_NS_PRIORITY) &&
|
||||
(old_pmr != pe_data->ns_pri_mask)) {
|
||||
ERROR("Invalid Priority Mask (0x%x) restored\n", old_pmr);
|
||||
panic();
|
||||
}
|
||||
|
||||
EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask);
|
||||
|
||||
pe_data->ns_pri_mask = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Program Priority Mask to the original Non-secure priority such that
|
||||
* Non-secure interrupts may preempt Secure execution, viz. during Yielding SMC
|
||||
* calls. The 'preempt_ret_code' parameter indicates the Yielding SMC's return
|
||||
* value in case the call was preempted.
|
||||
*
|
||||
* This API is expected to be invoked before delegating a yielding SMC to Secure
|
||||
* EL1. I.e. within the window of secure execution after Non-secure context is
|
||||
* saved (after entry into EL3) and Secure context is restored (before entering
|
||||
* Secure EL1).
|
||||
*/
|
||||
void ehf_allow_ns_preemption(uint64_t preempt_ret_code)
|
||||
{
|
||||
cpu_context_t *ns_ctx;
|
||||
unsigned int old_pmr __unused;
|
||||
pe_exc_data_t *pe_data = this_cpu_data();
|
||||
|
||||
/*
|
||||
* We should have been notified earlier of entering secure world, and
|
||||
* therefore have stashed the Non-secure priority mask.
|
||||
*/
|
||||
assert(pe_data->ns_pri_mask != 0);
|
||||
|
||||
/* Make sure no priority levels are active when requesting this */
|
||||
if (has_valid_pri_activations(pe_data)) {
|
||||
ERROR("PE %lx has priority activations: 0x%x\n",
|
||||
read_mpidr_el1(), pe_data->active_pri_bits);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Program preempted return code to x0 right away so that, if the
|
||||
* Yielding SMC was indeed preempted before a dispatcher gets a chance
|
||||
* to populate it, the caller would find the correct return value.
|
||||
*/
|
||||
ns_ctx = cm_get_context(NON_SECURE);
|
||||
assert(ns_ctx);
|
||||
write_ctx_reg(get_gpregs_ctx(ns_ctx), CTX_GPREG_X0, preempt_ret_code);
|
||||
|
||||
old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask);
|
||||
|
||||
EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask);
|
||||
|
||||
pe_data->ns_pri_mask = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether Secure execution has explicitly allowed Non-secure interrupts
|
||||
* to preempt itself, viz. during Yielding SMC calls.
|
||||
*/
|
||||
unsigned int ehf_is_ns_preemption_allowed(void)
|
||||
{
|
||||
unsigned int run_pri;
|
||||
pe_exc_data_t *pe_data = this_cpu_data();
|
||||
|
||||
/* If running priority is in secure range, return false */
|
||||
run_pri = plat_ic_get_running_priority();
|
||||
if (IS_PRI_SECURE(run_pri))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If Non-secure preemption was permitted by calling
|
||||
* ehf_allow_ns_preemption() earlier:
|
||||
*
|
||||
* - There wouldn't have been priority activations;
|
||||
* - We would have cleared the stashed the Non-secure Priority Mask.
|
||||
*/
|
||||
if (has_valid_pri_activations(pe_data))
|
||||
return 0;
|
||||
if (pe_data->ns_pri_mask != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Top-level EL3 interrupt handler.
|
||||
*/
|
||||
static uint64_t ehf_el3_interrupt_handler(uint32_t id, uint32_t flags,
|
||||
void *handle, void *cookie)
|
||||
{
|
||||
int pri, idx, intr, intr_raw, ret = 0;
|
||||
ehf_handler_t handler;
|
||||
|
||||
/*
|
||||
* Top-level interrupt type handler from Interrupt Management Framework
|
||||
* doesn't acknowledge the interrupt; so the interrupt ID must be
|
||||
* invalid.
|
||||
*/
|
||||
assert(id == INTR_ID_UNAVAILABLE);
|
||||
|
||||
/*
|
||||
* Acknowledge interrupt. Proceed with handling only for valid interrupt
|
||||
* IDs. This situation may arise because of Interrupt Management
|
||||
* Framework identifying an EL3 interrupt, but before it's been
|
||||
* acknowledged here, the interrupt was either deasserted, or there was
|
||||
* a higher-priority interrupt of another type.
|
||||
*/
|
||||
intr_raw = plat_ic_acknowledge_interrupt();
|
||||
intr = plat_ic_get_interrupt_id(intr_raw);
|
||||
if (intr == INTR_ID_UNAVAILABLE)
|
||||
return 0;
|
||||
|
||||
/* Having acknowledged the interrupt, get the running priority */
|
||||
pri = plat_ic_get_running_priority();
|
||||
|
||||
/* Check EL3 interrupt priority is in secure range */
|
||||
assert(IS_PRI_SECURE(pri));
|
||||
|
||||
/*
|
||||
* Translate the priority to a descriptor index. We do this by masking
|
||||
* and shifting the running priority value (platform-supplied).
|
||||
*/
|
||||
idx = pri_to_idx(pri);
|
||||
|
||||
/* Validate priority */
|
||||
assert(pri == IDX_TO_PRI(idx));
|
||||
|
||||
handler = RAW_HANDLER(exception_data.ehf_priorities[idx].ehf_handler);
|
||||
if (!handler) {
|
||||
ERROR("No EL3 exception handler for priority 0x%x\n",
|
||||
IDX_TO_PRI(idx));
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Call registered handler. Pass the raw interrupt value to registered
|
||||
* handlers.
|
||||
*/
|
||||
ret = handler(intr_raw, flags, handle, cookie);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the EL3 exception handling.
|
||||
*/
|
||||
void ehf_init(void)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
int ret __unused;
|
||||
|
||||
/* Ensure EL3 interrupts are supported */
|
||||
assert(plat_ic_has_interrupt_type(INTR_TYPE_EL3));
|
||||
|
||||
/*
|
||||
* Make sure that priority water mark has enough bits to represent the
|
||||
* whole priority array.
|
||||
*/
|
||||
assert(exception_data.num_priorities <= (sizeof(ehf_pri_bits_t) * 8));
|
||||
|
||||
assert(exception_data.ehf_priorities);
|
||||
|
||||
/*
|
||||
* Bit 7 of GIC priority must be 0 for secure interrupts. This means
|
||||
* platforms must use at least 1 of the remaining 7 bits.
|
||||
*/
|
||||
assert((exception_data.pri_bits >= 1) || (exception_data.pri_bits < 8));
|
||||
|
||||
/* Route EL3 interrupts when in Secure and Non-secure. */
|
||||
set_interrupt_rm_flag(flags, NON_SECURE);
|
||||
set_interrupt_rm_flag(flags, SECURE);
|
||||
|
||||
/* Register handler for EL3 interrupts */
|
||||
ret = register_interrupt_type_handler(INTR_TYPE_EL3,
|
||||
ehf_el3_interrupt_handler, flags);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a handler at the supplied priority. Registration is allowed only if
|
||||
* a handler hasn't been registered before, or one wasn't provided at build
|
||||
* time. The priority for which the handler is being registered must also accord
|
||||
* with the platform-supplied data.
|
||||
*/
|
||||
void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* Sanity check for handler */
|
||||
assert(handler != NULL);
|
||||
|
||||
/* Handler ought to be 4-byte aligned */
|
||||
assert((((uintptr_t) handler) & 3) == 0);
|
||||
|
||||
/* Ensure we register for valid priority */
|
||||
idx = pri_to_idx(pri);
|
||||
assert(idx < exception_data.num_priorities);
|
||||
assert(IDX_TO_PRI(idx) == pri);
|
||||
|
||||
/* Return failure if a handler was already registered */
|
||||
if (exception_data.ehf_priorities[idx].ehf_handler != _EHF_NO_HANDLER) {
|
||||
ERROR("Handler already registered for priority 0x%x\n", pri);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Install handler, and retain the valid bit. We assume that the handler
|
||||
* is 4-byte aligned, which is usually the case.
|
||||
*/
|
||||
exception_data.ehf_priorities[idx].ehf_handler =
|
||||
(((uintptr_t) handler) | _EHF_PRI_VALID);
|
||||
|
||||
EHF_LOG("register pri=0x%x handler=%p\n", pri, handler);
|
||||
}
|
||||
|
||||
SUBSCRIBE_TO_EVENT(cm_entering_normal_world, ehf_entering_normal_world);
|
||||
SUBSCRIBE_TO_EVENT(cm_exited_normal_world, ehf_exited_normal_world);
|
||||
226
firmware/coreboot/3rdparty/arm-trusted-firmware/bl31/interrupt_mgmt.c
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <errno.h>
|
||||
#include <interrupt_mgmt.h>
|
||||
#include <platform.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Local structure and corresponding array to keep track of the state of the
|
||||
* registered interrupt handlers for each interrupt type.
|
||||
* The field descriptions are:
|
||||
*
|
||||
* 'flags' : Bit[0], Routing model for this interrupt type when execution is
|
||||
* not in EL3 in the secure state. '1' implies that this
|
||||
* interrupt will be routed to EL3. '0' implies that this
|
||||
* interrupt will be routed to the current exception level.
|
||||
*
|
||||
* Bit[1], Routing model for this interrupt type when execution is
|
||||
* not in EL3 in the non-secure state. '1' implies that this
|
||||
* interrupt will be routed to EL3. '0' implies that this
|
||||
* interrupt will be routed to the current exception level.
|
||||
*
|
||||
* All other bits are reserved and SBZ.
|
||||
*
|
||||
* 'scr_el3[2]' : Mapping of the routing model in the 'flags' field to the
|
||||
* value of the SCR_EL3.IRQ or FIQ bit for each security state.
|
||||
* There are two instances of this field corresponding to the
|
||||
* two security states.
|
||||
******************************************************************************/
|
||||
typedef struct intr_type_desc {
|
||||
interrupt_type_handler_t handler;
|
||||
uint32_t flags;
|
||||
uint32_t scr_el3[2];
|
||||
} intr_type_desc_t;
|
||||
|
||||
static intr_type_desc_t intr_type_descs[MAX_INTR_TYPES];
|
||||
|
||||
/*******************************************************************************
|
||||
* This function validates the interrupt type.
|
||||
******************************************************************************/
|
||||
static int32_t validate_interrupt_type(uint32_t type)
|
||||
{
|
||||
if (type == INTR_TYPE_S_EL1 || type == INTR_TYPE_NS ||
|
||||
type == INTR_TYPE_EL3)
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function validates the routing model for this type of interrupt
|
||||
******************************************************************************/
|
||||
static int32_t validate_routing_model(uint32_t type, uint32_t flags)
|
||||
{
|
||||
flags >>= INTR_RM_FLAGS_SHIFT;
|
||||
flags &= INTR_RM_FLAGS_MASK;
|
||||
|
||||
if (type == INTR_TYPE_S_EL1)
|
||||
return validate_sel1_interrupt_rm(flags);
|
||||
|
||||
if (type == INTR_TYPE_NS)
|
||||
return validate_ns_interrupt_rm(flags);
|
||||
|
||||
if (type == INTR_TYPE_EL3)
|
||||
return validate_el3_interrupt_rm(flags);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the cached copy of the SCR_EL3 which contains the
|
||||
* routing model (expressed through the IRQ and FIQ bits) for a security state
|
||||
* which was stored through a call to 'set_routing_model()' earlier.
|
||||
******************************************************************************/
|
||||
uint32_t get_scr_el3_from_routing_model(uint32_t security_state)
|
||||
{
|
||||
uint32_t scr_el3;
|
||||
|
||||
assert(sec_state_is_valid(security_state));
|
||||
scr_el3 = intr_type_descs[INTR_TYPE_NS].scr_el3[security_state];
|
||||
scr_el3 |= intr_type_descs[INTR_TYPE_S_EL1].scr_el3[security_state];
|
||||
scr_el3 |= intr_type_descs[INTR_TYPE_EL3].scr_el3[security_state];
|
||||
return scr_el3;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function uses the 'interrupt_type_flags' parameter to obtain the value
|
||||
* of the trap bit (IRQ/FIQ) in the SCR_EL3 for a security state for this
|
||||
* interrupt type. It uses it to update the SCR_EL3 in the cpu context and the
|
||||
* 'intr_type_desc' for that security state.
|
||||
******************************************************************************/
|
||||
static void set_scr_el3_from_rm(uint32_t type,
|
||||
uint32_t interrupt_type_flags,
|
||||
uint32_t security_state)
|
||||
{
|
||||
uint32_t flag, bit_pos;
|
||||
|
||||
flag = get_interrupt_rm_flag(interrupt_type_flags, security_state);
|
||||
bit_pos = plat_interrupt_type_to_line(type, security_state);
|
||||
intr_type_descs[type].scr_el3[security_state] = flag << bit_pos;
|
||||
|
||||
/* Update scr_el3 only if there is a context available. If not, it
|
||||
* will be updated later during context initialization which will obtain
|
||||
* the scr_el3 value to be used via get_scr_el3_from_routing_model() */
|
||||
if (cm_get_context(security_state))
|
||||
cm_write_scr_el3_bit(security_state, bit_pos, flag);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function validates the routing model specified in the 'flags' and
|
||||
* updates internal data structures to reflect the new routing model. It also
|
||||
* updates the copy of SCR_EL3 for each security state with the new routing
|
||||
* model in the 'cpu_context' structure for this cpu.
|
||||
******************************************************************************/
|
||||
int32_t set_routing_model(uint32_t type, uint32_t flags)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
rc = validate_interrupt_type(type);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = validate_routing_model(type, flags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Update the routing model in internal data structures */
|
||||
intr_type_descs[type].flags = flags;
|
||||
set_scr_el3_from_rm(type, flags, SECURE);
|
||||
set_scr_el3_from_rm(type, flags, NON_SECURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* This function disables the routing model of interrupt 'type' from the
|
||||
* specified 'security_state' on the local core. The disable is in effect
|
||||
* till the core powers down or till the next enable for that interrupt
|
||||
* type.
|
||||
*****************************************************************************/
|
||||
int disable_intr_rm_local(uint32_t type, uint32_t security_state)
|
||||
{
|
||||
uint32_t bit_pos, flag;
|
||||
|
||||
assert(intr_type_descs[type].handler);
|
||||
|
||||
flag = get_interrupt_rm_flag(INTR_DEFAULT_RM, security_state);
|
||||
|
||||
bit_pos = plat_interrupt_type_to_line(type, security_state);
|
||||
cm_write_scr_el3_bit(security_state, bit_pos, flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* This function enables the routing model of interrupt 'type' from the
|
||||
* specified 'security_state' on the local core.
|
||||
*****************************************************************************/
|
||||
int enable_intr_rm_local(uint32_t type, uint32_t security_state)
|
||||
{
|
||||
uint32_t bit_pos, flag;
|
||||
|
||||
assert(intr_type_descs[type].handler);
|
||||
|
||||
flag = get_interrupt_rm_flag(intr_type_descs[type].flags,
|
||||
security_state);
|
||||
|
||||
bit_pos = plat_interrupt_type_to_line(type, security_state);
|
||||
cm_write_scr_el3_bit(security_state, bit_pos, flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function registers a handler for the 'type' of interrupt specified. It
|
||||
* also validates the routing model specified in the 'flags' for this type of
|
||||
* interrupt.
|
||||
******************************************************************************/
|
||||
int32_t register_interrupt_type_handler(uint32_t type,
|
||||
interrupt_type_handler_t handler,
|
||||
uint32_t flags)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
/* Validate the 'handler' parameter */
|
||||
if (!handler)
|
||||
return -EINVAL;
|
||||
|
||||
/* Validate the 'flags' parameter */
|
||||
if (flags & INTR_TYPE_FLAGS_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if a handler has already been registered */
|
||||
if (intr_type_descs[type].handler)
|
||||
return -EALREADY;
|
||||
|
||||
rc = set_routing_model(type, flags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Save the handler */
|
||||
intr_type_descs[type].handler = handler;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is called when an interrupt is generated and returns the
|
||||
* handler for the interrupt type (if registered). It returns NULL if the
|
||||
* interrupt type is not supported or its handler has not been registered.
|
||||
******************************************************************************/
|
||||
interrupt_type_handler_t get_interrupt_type_handler(uint32_t type)
|
||||
{
|
||||
if (validate_interrupt_type(type))
|
||||
return NULL;
|
||||
|
||||
return intr_type_descs[type].handler;
|
||||
}
|
||||
|
||||
15
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/optee/optee.mk
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
# This makefile only aims at complying with ARM Trusted Firmware build process so
|
||||
# that "optee" is a valid ARM Trusted Firmware AArch32 Secure Playload identifier.
|
||||
|
||||
ifneq ($(ARCH),aarch32)
|
||||
$(error This directory targets AArch32 support)
|
||||
endif
|
||||
|
||||
$(eval $(call add_define,AARCH32_SP_OPTEE))
|
||||
|
||||
$(info ARM Trusted Firmware built for OP-TEE payload support)
|
||||
330
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
#include <context.h>
|
||||
#include <el3_common_macros.S>
|
||||
#include <runtime_svc.h>
|
||||
#include <smccc_helpers.h>
|
||||
#include <smccc_macros.S>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
.globl sp_min_vector_table
|
||||
.globl sp_min_entrypoint
|
||||
.globl sp_min_warm_entrypoint
|
||||
.globl sp_min_handle_smc
|
||||
.globl sp_min_handle_fiq
|
||||
|
||||
.macro route_fiq_to_sp_min reg
|
||||
/* -----------------------------------------------------
|
||||
* FIQs are secure interrupts trapped by Monitor and non
|
||||
* secure is not allowed to mask the FIQs.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
ldcopr \reg, SCR
|
||||
orr \reg, \reg, #SCR_FIQ_BIT
|
||||
bic \reg, \reg, #SCR_FW_BIT
|
||||
stcopr \reg, SCR
|
||||
.endm
|
||||
|
||||
.macro clrex_on_monitor_entry
|
||||
#if (ARM_ARCH_MAJOR == 7)
|
||||
/*
|
||||
* ARMv7 architectures need to clear the exclusive access when
|
||||
* entering Monitor mode.
|
||||
*/
|
||||
clrex
|
||||
#endif
|
||||
.endm
|
||||
|
||||
vector_base sp_min_vector_table
|
||||
b sp_min_entrypoint
|
||||
b plat_panic_handler /* Undef */
|
||||
b sp_min_handle_smc /* Syscall */
|
||||
b plat_panic_handler /* Prefetch abort */
|
||||
b plat_panic_handler /* Data abort */
|
||||
b plat_panic_handler /* Reserved */
|
||||
b plat_panic_handler /* IRQ */
|
||||
b sp_min_handle_fiq /* FIQ */
|
||||
|
||||
|
||||
/*
|
||||
* The Cold boot/Reset entrypoint for SP_MIN
|
||||
*/
|
||||
func sp_min_entrypoint
|
||||
#if !RESET_TO_SP_MIN
|
||||
/* ---------------------------------------------------------------
|
||||
* Preceding bootloader has populated r0 with a pointer to a
|
||||
* 'bl_params_t' structure & r1 with a pointer to platform
|
||||
* specific structure
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
mov r9, r0
|
||||
mov r10, r1
|
||||
mov r11, r2
|
||||
mov r12, r3
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* For !RESET_TO_SP_MIN systems, only the primary CPU ever reaches
|
||||
* sp_min_entrypoint() during the cold boot flow, so the cold/warm boot
|
||||
* and primary/secondary CPU logic should not be executed in this case.
|
||||
*
|
||||
* Also, assume that the previous bootloader has already initialised the
|
||||
* SCTLR, including the CPU endianness, and has initialised the memory.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=0 \
|
||||
_warm_boot_mailbox=0 \
|
||||
_secondary_cold_boot=0 \
|
||||
_init_memory=0 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=sp_min_vector_table
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Relay the previous bootloader's arguments to the platform layer
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
#else
|
||||
/* ---------------------------------------------------------------------
|
||||
* For RESET_TO_SP_MIN systems which have a programmable reset address,
|
||||
* sp_min_entrypoint() is executed only on the cold boot path so we can
|
||||
* skip the warm boot mailbox mechanism.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=1 \
|
||||
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
|
||||
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
|
||||
_init_memory=1 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=sp_min_vector_table
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* For RESET_TO_SP_MIN systems, BL32 (SP_MIN) is the first bootloader
|
||||
* to run so there's no argument to relay from a previous bootloader.
|
||||
* Zero the arguments passed to the platform layer to reflect that.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov r9, #0
|
||||
mov r10, #0
|
||||
mov r11, #0
|
||||
mov r12, #0
|
||||
|
||||
#endif /* RESET_TO_SP_MIN */
|
||||
|
||||
#if SP_MIN_WITH_SECURE_FIQ
|
||||
route_fiq_to_sp_min r4
|
||||
#endif
|
||||
|
||||
mov r0, r9
|
||||
mov r1, r10
|
||||
mov r2, r11
|
||||
mov r3, r12
|
||||
bl sp_min_early_platform_setup2
|
||||
bl sp_min_plat_arch_setup
|
||||
|
||||
/* Jump to the main function */
|
||||
bl sp_min_main
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* Clean the .data & .bss sections to main memory. This ensures
|
||||
* that any global data which was initialised by the primary CPU
|
||||
* is visible to secondary CPUs before they enable their data
|
||||
* caches and participate in coherency.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =__DATA_START__
|
||||
ldr r1, =__DATA_END__
|
||||
sub r1, r1, r0
|
||||
bl clean_dcache_range
|
||||
|
||||
ldr r0, =__BSS_START__
|
||||
ldr r1, =__BSS_END__
|
||||
sub r1, r1, r0
|
||||
bl clean_dcache_range
|
||||
|
||||
bl smc_get_next_ctx
|
||||
|
||||
/* r0 points to `smc_ctx_t` */
|
||||
/* The PSCI cpu_context registers have been copied to `smc_ctx_t` */
|
||||
b sp_min_exit
|
||||
endfunc sp_min_entrypoint
|
||||
|
||||
|
||||
/*
|
||||
* SMC handling function for SP_MIN.
|
||||
*/
|
||||
func sp_min_handle_smc
|
||||
/* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */
|
||||
str lr, [sp, #SMC_CTX_LR_MON]
|
||||
|
||||
smccc_save_gp_mode_regs
|
||||
|
||||
clrex_on_monitor_entry
|
||||
|
||||
/*
|
||||
* `sp` still points to `smc_ctx_t`. Save it to a register
|
||||
* and restore the C runtime stack pointer to `sp`.
|
||||
*/
|
||||
mov r2, sp /* handle */
|
||||
ldr sp, [r2, #SMC_CTX_SP_MON]
|
||||
|
||||
ldr r0, [r2, #SMC_CTX_SCR]
|
||||
and r3, r0, #SCR_NS_BIT /* flags */
|
||||
|
||||
/* Switch to Secure Mode*/
|
||||
bic r0, #SCR_NS_BIT
|
||||
stcopr r0, SCR
|
||||
isb
|
||||
|
||||
/*
|
||||
* Set PMCR.DP to 1 to prohibit cycle counting whilst in Secure Mode.
|
||||
* Also, the PMCR.LC field has an architecturally UNKNOWN value on reset
|
||||
* and so set to 1 as ARM has deprecated use of PMCR.LC=0.
|
||||
*/
|
||||
ldcopr r0, PMCR
|
||||
orr r0, r0, #(PMCR_LC_BIT | PMCR_DP_BIT)
|
||||
stcopr r0, PMCR
|
||||
|
||||
ldr r0, [r2, #SMC_CTX_GPREG_R0] /* smc_fid */
|
||||
/* Check whether an SMC64 is issued */
|
||||
tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT)
|
||||
beq 1f
|
||||
/* SMC32 is not detected. Return error back to caller */
|
||||
mov r0, #SMC_UNK
|
||||
str r0, [r2, #SMC_CTX_GPREG_R0]
|
||||
mov r0, r2
|
||||
b sp_min_exit
|
||||
1:
|
||||
/* SMC32 is detected */
|
||||
mov r1, #0 /* cookie */
|
||||
bl handle_runtime_svc
|
||||
|
||||
/* `r0` points to `smc_ctx_t` */
|
||||
b sp_min_exit
|
||||
endfunc sp_min_handle_smc
|
||||
|
||||
/*
|
||||
* Secure Interrupts handling function for SP_MIN.
|
||||
*/
|
||||
func sp_min_handle_fiq
|
||||
#if !SP_MIN_WITH_SECURE_FIQ
|
||||
b plat_panic_handler
|
||||
#else
|
||||
/* FIQ has a +4 offset for lr compared to preferred return address */
|
||||
sub lr, lr, #4
|
||||
/* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */
|
||||
str lr, [sp, #SMC_CTX_LR_MON]
|
||||
|
||||
smccc_save_gp_mode_regs
|
||||
|
||||
clrex_on_monitor_entry
|
||||
|
||||
/* load run-time stack */
|
||||
mov r2, sp
|
||||
ldr sp, [r2, #SMC_CTX_SP_MON]
|
||||
|
||||
/* Switch to Secure Mode */
|
||||
ldr r0, [r2, #SMC_CTX_SCR]
|
||||
bic r0, #SCR_NS_BIT
|
||||
stcopr r0, SCR
|
||||
isb
|
||||
|
||||
/*
|
||||
* Set PMCR.DP to 1 to prohibit cycle counting whilst in Secure Mode.
|
||||
* Also, the PMCR.LC field has an architecturally UNKNOWN value on reset
|
||||
* and so set to 1 as ARM has deprecated use of PMCR.LC=0.
|
||||
*/
|
||||
ldcopr r0, PMCR
|
||||
orr r0, r0, #(PMCR_LC_BIT | PMCR_DP_BIT)
|
||||
stcopr r0, PMCR
|
||||
|
||||
push {r2, r3}
|
||||
bl sp_min_fiq
|
||||
pop {r0, r3}
|
||||
|
||||
b sp_min_exit
|
||||
#endif
|
||||
endfunc sp_min_handle_fiq
|
||||
|
||||
/*
|
||||
* The Warm boot entrypoint for SP_MIN.
|
||||
*/
|
||||
func sp_min_warm_entrypoint
|
||||
/*
|
||||
* On the warm boot path, most of the EL3 initialisations performed by
|
||||
* 'el3_entrypoint_common' must be skipped:
|
||||
*
|
||||
* - Only when the platform bypasses the BL1/BL32 (SP_MIN) entrypoint by
|
||||
* programming the reset address do we need to initialied the SCTLR.
|
||||
* In other cases, we assume this has been taken care by the
|
||||
* entrypoint code.
|
||||
*
|
||||
* - No need to determine the type of boot, we know it is a warm boot.
|
||||
*
|
||||
* - Do not try to distinguish between primary and secondary CPUs, this
|
||||
* notion only exists for a cold boot.
|
||||
*
|
||||
* - No need to initialise the memory or the C runtime environment,
|
||||
* it has been done once and for all on the cold boot path.
|
||||
*/
|
||||
el3_entrypoint_common \
|
||||
_init_sctlr=PROGRAMMABLE_RESET_ADDRESS \
|
||||
_warm_boot_mailbox=0 \
|
||||
_secondary_cold_boot=0 \
|
||||
_init_memory=0 \
|
||||
_init_c_runtime=0 \
|
||||
_exception_vectors=sp_min_vector_table
|
||||
|
||||
/*
|
||||
* We're about to enable MMU and participate in PSCI state coordination.
|
||||
*
|
||||
* The PSCI implementation invokes platform routines that enable CPUs to
|
||||
* participate in coherency. On a system where CPUs are not
|
||||
* cache-coherent without appropriate platform specific programming,
|
||||
* having caches enabled until such time might lead to coherency issues
|
||||
* (resulting from stale data getting speculatively fetched, among
|
||||
* others). Therefore we keep data caches disabled even after enabling
|
||||
* the MMU for such platforms.
|
||||
*
|
||||
* On systems with hardware-assisted coherency, or on single cluster
|
||||
* platforms, such platform specific programming is not required to
|
||||
* enter coherency (as CPUs already are); and there's no reason to have
|
||||
* caches disabled either.
|
||||
*/
|
||||
mov r0, #DISABLE_DCACHE
|
||||
bl bl32_plat_enable_mmu
|
||||
|
||||
#if SP_MIN_WITH_SECURE_FIQ
|
||||
route_fiq_to_sp_min r0
|
||||
#endif
|
||||
|
||||
#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY
|
||||
ldcopr r0, SCTLR
|
||||
orr r0, r0, #SCTLR_C_BIT
|
||||
stcopr r0, SCTLR
|
||||
isb
|
||||
#endif
|
||||
|
||||
bl sp_min_warm_boot
|
||||
bl smc_get_next_ctx
|
||||
/* r0 points to `smc_ctx_t` */
|
||||
/* The PSCI cpu_context registers have been copied to `smc_ctx_t` */
|
||||
b sp_min_exit
|
||||
endfunc sp_min_warm_entrypoint
|
||||
|
||||
/*
|
||||
* The function to restore the registers from SMC context and return
|
||||
* to the mode restored to SPSR.
|
||||
*
|
||||
* Arguments : r0 must point to the SMC context to restore from.
|
||||
*/
|
||||
func sp_min_exit
|
||||
monitor_exit
|
||||
endfunc sp_min_exit
|
||||
225
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/sp_min/sp_min.ld.S
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
OUTPUT_FORMAT(elf32-littlearm)
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(sp_min_vector_table)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = BL32_BASE, LENGTH = BL32_LIMIT - BL32_BASE
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BL32_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL32_BASE address is not aligned on a page boundary.")
|
||||
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
.text . : {
|
||||
__TEXT_START__ = .;
|
||||
*entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.vectors)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__TEXT_END__ = .;
|
||||
} >RAM
|
||||
|
||||
.rodata . : {
|
||||
__RODATA_START__ = .;
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 4-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(4);
|
||||
__RT_SVC_DESCS_START__ = .;
|
||||
KEEP(*(rt_svc_descs))
|
||||
__RT_SVC_DESCS_END__ = .;
|
||||
|
||||
/*
|
||||
* Ensure 4-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(4);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
/* Place pubsub sections for events */
|
||||
. = ALIGN(8);
|
||||
#include <pubsub_events.h>
|
||||
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RODATA_END__ = .;
|
||||
} >RAM
|
||||
#else
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
*entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
|
||||
/* Ensure 4-byte alignment for descriptors and ensure inclusion */
|
||||
. = ALIGN(4);
|
||||
__RT_SVC_DESCS_START__ = .;
|
||||
KEEP(*(rt_svc_descs))
|
||||
__RT_SVC_DESCS_END__ = .;
|
||||
|
||||
/*
|
||||
* Ensure 4-byte alignment for cpu_ops so that its fields are also
|
||||
* aligned. Also ensure cpu_ops inclusion.
|
||||
*/
|
||||
. = ALIGN(4);
|
||||
__CPU_OPS_START__ = .;
|
||||
KEEP(*(cpu_ops))
|
||||
__CPU_OPS_END__ = .;
|
||||
|
||||
/* Place pubsub sections for events */
|
||||
. = ALIGN(8);
|
||||
#include <pubsub_events.h>
|
||||
|
||||
*(.vectors)
|
||||
__RO_END_UNALIGNED__ = .;
|
||||
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked as
|
||||
* read-only, executable. No RW data from the next section must
|
||||
* creep in. Ensure the rest of the current memory block is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RO_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
|
||||
"cpu_ops not defined for this platform.")
|
||||
/*
|
||||
* Define a linker symbol to mark start of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_START__ = . ;
|
||||
|
||||
.data . : {
|
||||
__DATA_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_END__ = .;
|
||||
} >RAM
|
||||
|
||||
#ifdef BL32_PROGBITS_LIMIT
|
||||
ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.")
|
||||
#endif
|
||||
|
||||
stacks (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The .bss section gets initialised to 0 at runtime.
|
||||
* Its base address should be 8-byte aligned for better performance of the
|
||||
* zero-initialization code.
|
||||
*/
|
||||
.bss (NOLOAD) : ALIGN(8) {
|
||||
__BSS_START__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
#if !USE_COHERENT_MEM
|
||||
/*
|
||||
* Bakery locks are stored in normal .bss memory
|
||||
*
|
||||
* Each lock's data is spread across multiple cache lines, one per CPU,
|
||||
* but multiple locks can share the same cache line.
|
||||
* The compiler will allocate enough memory for one CPU's bakery locks,
|
||||
* the remaining cache lines are allocated by the linker script
|
||||
*/
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__BAKERY_LOCK_START__ = .;
|
||||
*(bakery_lock)
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(. - __BAKERY_LOCK_START__);
|
||||
. = . + (__PERCPU_BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1));
|
||||
__BAKERY_LOCK_END__ = .;
|
||||
#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE
|
||||
ASSERT(__PERCPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE,
|
||||
"PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLE_PMF
|
||||
/*
|
||||
* Time-stamps are stored in normal .bss memory
|
||||
*
|
||||
* The compiler will allocate enough memory for one CPU's time-stamps,
|
||||
* the remaining memory for other CPU's is allocated by the
|
||||
* linker script
|
||||
*/
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__PMF_TIMESTAMP_START__ = .;
|
||||
KEEP(*(pmf_timestamp_array))
|
||||
. = ALIGN(CACHE_WRITEBACK_GRANULE);
|
||||
__PMF_PERCPU_TIMESTAMP_END__ = .;
|
||||
__PERCPU_TIMESTAMP_SIZE__ = ABSOLUTE(. - __PMF_TIMESTAMP_START__);
|
||||
. = . + (__PERCPU_TIMESTAMP_SIZE__ * (PLATFORM_CORE_COUNT - 1));
|
||||
__PMF_TIMESTAMP_END__ = .;
|
||||
#endif /* ENABLE_PMF */
|
||||
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The xlat_table section is for full, aligned page tables (4K).
|
||||
* Removing them from .bss avoids forcing 4K alignment on
|
||||
* the .bss section. The tables are initialized to zero by the translation
|
||||
* tables library.
|
||||
*/
|
||||
xlat_table (NOLOAD) : {
|
||||
*(xlat_table)
|
||||
} >RAM
|
||||
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/*
|
||||
* The base address of the coherent memory section must be page-aligned (4K)
|
||||
* to guarantee that the coherent data are stored on their own pages and
|
||||
* are not mixed with normal data. This is required to set up the correct
|
||||
* memory attributes for the coherent data page tables.
|
||||
*/
|
||||
coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
__COHERENT_RAM_START__ = .;
|
||||
/*
|
||||
* Bakery locks are stored in coherent memory
|
||||
*
|
||||
* Each lock's data is contiguous and fully allocated by the compiler
|
||||
*/
|
||||
*(bakery_lock)
|
||||
*(tzfw_coherent_mem)
|
||||
__COHERENT_RAM_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked
|
||||
* as device memory. No other unexpected data must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__COHERENT_RAM_END__ = .;
|
||||
} >RAM
|
||||
|
||||
__COHERENT_RAM_UNALIGNED_SIZE__ =
|
||||
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark end of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_END__ = .;
|
||||
|
||||
__BL32_END__ = .;
|
||||
}
|
||||
56
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/sp_min/sp_min.mk
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
ifneq (${ARCH}, aarch32)
|
||||
$(error SP_MIN is only supported on AArch32 platforms)
|
||||
endif
|
||||
|
||||
include lib/psci/psci_lib.mk
|
||||
|
||||
INCLUDES += -Iinclude/bl32/sp_min
|
||||
|
||||
BL32_SOURCES += bl32/sp_min/sp_min_main.c \
|
||||
bl32/sp_min/aarch32/entrypoint.S \
|
||||
common/runtime_svc.c \
|
||||
plat/common/aarch32/plat_sp_min_common.c\
|
||||
services/std_svc/std_svc_setup.c \
|
||||
${PSCI_LIB_SOURCES}
|
||||
|
||||
ifeq (${ENABLE_PMF}, 1)
|
||||
BL32_SOURCES += lib/pmf/pmf_main.c
|
||||
endif
|
||||
|
||||
ifeq (${ENABLE_AMU}, 1)
|
||||
BL32_SOURCES += lib/extensions/amu/aarch32/amu.c\
|
||||
lib/extensions/amu/aarch32/amu_helpers.S
|
||||
endif
|
||||
|
||||
ifeq (${WORKAROUND_CVE_2017_5715},1)
|
||||
BL32_SOURCES += bl32/sp_min/wa_cve_2017_5715_bpiall.S \
|
||||
bl32/sp_min/wa_cve_2017_5715_icache_inv.S
|
||||
endif
|
||||
|
||||
BL32_LINKERFILE := bl32/sp_min/sp_min.ld.S
|
||||
|
||||
# Include the platform-specific SP_MIN Makefile
|
||||
# If no platform-specific SP_MIN Makefile exists, it means SP_MIN is not supported
|
||||
# on this platform.
|
||||
SP_MIN_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/sp_min/sp_min-${PLAT}.mk)
|
||||
ifeq (,${SP_MIN_PLAT_MAKEFILE})
|
||||
$(error SP_MIN is not supported on platform ${PLAT})
|
||||
else
|
||||
include ${SP_MIN_PLAT_MAKEFILE}
|
||||
endif
|
||||
|
||||
RESET_TO_SP_MIN := 0
|
||||
$(eval $(call add_define,RESET_TO_SP_MIN))
|
||||
$(eval $(call assert_boolean,RESET_TO_SP_MIN))
|
||||
|
||||
# Flag to allow SP_MIN to handle FIQ interrupts in monitor mode. The platform
|
||||
# port is free to override this value. It is default disabled.
|
||||
SP_MIN_WITH_SECURE_FIQ ?= 0
|
||||
$(eval $(call add_define,SP_MIN_WITH_SECURE_FIQ))
|
||||
$(eval $(call assert_boolean,SP_MIN_WITH_SECURE_FIQ))
|
||||
237
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/sp_min/sp_min_main.c
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <context.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <platform_sp_min.h>
|
||||
#include <psci.h>
|
||||
#include <runtime_svc.h>
|
||||
#include <smccc_helpers.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <types.h>
|
||||
#include <utils.h>
|
||||
#include "sp_min_private.h"
|
||||
|
||||
/* Pointers to per-core cpu contexts */
|
||||
static void *sp_min_cpu_ctx_ptr[PLATFORM_CORE_COUNT];
|
||||
|
||||
/* SP_MIN only stores the non secure smc context */
|
||||
static smc_ctx_t sp_min_smc_context[PLATFORM_CORE_COUNT];
|
||||
|
||||
/******************************************************************************
|
||||
* Define the smccc helper library API's
|
||||
*****************************************************************************/
|
||||
void *smc_get_ctx(unsigned int security_state)
|
||||
{
|
||||
assert(security_state == NON_SECURE);
|
||||
return &sp_min_smc_context[plat_my_core_pos()];
|
||||
}
|
||||
|
||||
void smc_set_next_ctx(unsigned int security_state)
|
||||
{
|
||||
assert(security_state == NON_SECURE);
|
||||
/* SP_MIN stores only non secure smc context. Nothing to do here */
|
||||
}
|
||||
|
||||
void *smc_get_next_ctx(void)
|
||||
{
|
||||
return &sp_min_smc_context[plat_my_core_pos()];
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns a pointer to the most recent 'cpu_context' structure
|
||||
* for the calling CPU that was set as the context for the specified security
|
||||
* state. NULL is returned if no such structure has been specified.
|
||||
******************************************************************************/
|
||||
void *cm_get_context(uint32_t security_state)
|
||||
{
|
||||
assert(security_state == NON_SECURE);
|
||||
return sp_min_cpu_ctx_ptr[plat_my_core_pos()];
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function sets the pointer to the current 'cpu_context' structure for the
|
||||
* specified security state for the calling CPU
|
||||
******************************************************************************/
|
||||
void cm_set_context(void *context, uint32_t security_state)
|
||||
{
|
||||
assert(security_state == NON_SECURE);
|
||||
sp_min_cpu_ctx_ptr[plat_my_core_pos()] = context;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns a pointer to the most recent 'cpu_context' structure
|
||||
* for the CPU identified by `cpu_idx` that was set as the context for the
|
||||
* specified security state. NULL is returned if no such structure has been
|
||||
* specified.
|
||||
******************************************************************************/
|
||||
void *cm_get_context_by_index(unsigned int cpu_idx,
|
||||
unsigned int security_state)
|
||||
{
|
||||
assert(security_state == NON_SECURE);
|
||||
return sp_min_cpu_ctx_ptr[cpu_idx];
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function sets the pointer to the current 'cpu_context' structure for the
|
||||
* specified security state for the CPU identified by CPU index.
|
||||
******************************************************************************/
|
||||
void cm_set_context_by_index(unsigned int cpu_idx, void *context,
|
||||
unsigned int security_state)
|
||||
{
|
||||
assert(security_state == NON_SECURE);
|
||||
sp_min_cpu_ctx_ptr[cpu_idx] = context;
|
||||
}
|
||||
|
||||
static void copy_cpu_ctx_to_smc_stx(const regs_t *cpu_reg_ctx,
|
||||
smc_ctx_t *next_smc_ctx)
|
||||
{
|
||||
next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0);
|
||||
next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR);
|
||||
next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR);
|
||||
next_smc_ctx->scr = read_ctx_reg(cpu_reg_ctx, CTX_SCR);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function invokes the PSCI library interface to initialize the
|
||||
* non secure cpu context and copies the relevant cpu context register values
|
||||
* to smc context. These registers will get programmed during `smc_exit`.
|
||||
******************************************************************************/
|
||||
static void sp_min_prepare_next_image_entry(void)
|
||||
{
|
||||
entry_point_info_t *next_image_info;
|
||||
cpu_context_t *ctx = cm_get_context(NON_SECURE);
|
||||
u_register_t ns_sctlr;
|
||||
|
||||
/* Program system registers to proceed to non-secure */
|
||||
next_image_info = sp_min_plat_get_bl33_ep_info();
|
||||
assert(next_image_info);
|
||||
assert(NON_SECURE == GET_SECURITY_STATE(next_image_info->h.attr));
|
||||
|
||||
INFO("SP_MIN: Preparing exit to normal world\n");
|
||||
|
||||
psci_prepare_next_non_secure_ctx(next_image_info);
|
||||
smc_set_next_ctx(NON_SECURE);
|
||||
|
||||
/* Copy r0, lr and spsr from cpu context to SMC context */
|
||||
copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
|
||||
smc_get_next_ctx());
|
||||
|
||||
/* Temporarily set the NS bit to access NS SCTLR */
|
||||
write_scr(read_scr() | SCR_NS_BIT);
|
||||
isb();
|
||||
ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR);
|
||||
write_sctlr(ns_sctlr);
|
||||
isb();
|
||||
|
||||
write_scr(read_scr() & ~SCR_NS_BIT);
|
||||
isb();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Implement the ARM Standard Service function to get arguments for a
|
||||
* particular service.
|
||||
*****************************************************************************/
|
||||
uintptr_t get_arm_std_svc_args(unsigned int svc_mask)
|
||||
{
|
||||
/* Setup the arguments for PSCI Library */
|
||||
DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, sp_min_warm_entrypoint);
|
||||
|
||||
/* PSCI is the only ARM Standard Service implemented */
|
||||
assert(svc_mask == PSCI_FID_MASK);
|
||||
|
||||
return (uintptr_t)&psci_args;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* The SP_MIN main function. Do the platform and PSCI Library setup. Also
|
||||
* initialize the runtime service framework.
|
||||
*****************************************************************************/
|
||||
void sp_min_main(void)
|
||||
{
|
||||
NOTICE("SP_MIN: %s\n", version_string);
|
||||
NOTICE("SP_MIN: %s\n", build_message);
|
||||
|
||||
/* Perform the SP_MIN platform setup */
|
||||
sp_min_platform_setup();
|
||||
|
||||
/* Initialize the runtime services e.g. psci */
|
||||
INFO("SP_MIN: Initializing runtime services\n");
|
||||
runtime_svc_init();
|
||||
|
||||
/*
|
||||
* We are ready to enter the next EL. Prepare entry into the image
|
||||
* corresponding to the desired security state after the next ERET.
|
||||
*/
|
||||
sp_min_prepare_next_image_entry();
|
||||
|
||||
/*
|
||||
* Perform any platform specific runtime setup prior to cold boot exit
|
||||
* from SP_MIN.
|
||||
*/
|
||||
sp_min_plat_runtime_setup();
|
||||
|
||||
console_flush();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* This function is invoked during warm boot. Invoke the PSCI library
|
||||
* warm boot entry point which takes care of Architectural and platform setup/
|
||||
* restore. Copy the relevant cpu_context register values to smc context which
|
||||
* will get programmed during `smc_exit`.
|
||||
*****************************************************************************/
|
||||
void sp_min_warm_boot(void)
|
||||
{
|
||||
smc_ctx_t *next_smc_ctx;
|
||||
cpu_context_t *ctx = cm_get_context(NON_SECURE);
|
||||
u_register_t ns_sctlr;
|
||||
|
||||
psci_warmboot_entrypoint();
|
||||
|
||||
smc_set_next_ctx(NON_SECURE);
|
||||
|
||||
next_smc_ctx = smc_get_next_ctx();
|
||||
zeromem(next_smc_ctx, sizeof(smc_ctx_t));
|
||||
|
||||
copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
|
||||
next_smc_ctx);
|
||||
|
||||
/* Temporarily set the NS bit to access NS SCTLR */
|
||||
write_scr(read_scr() | SCR_NS_BIT);
|
||||
isb();
|
||||
ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR);
|
||||
write_sctlr(ns_sctlr);
|
||||
isb();
|
||||
|
||||
write_scr(read_scr() & ~SCR_NS_BIT);
|
||||
isb();
|
||||
}
|
||||
|
||||
#if SP_MIN_WITH_SECURE_FIQ
|
||||
/******************************************************************************
|
||||
* This function is invoked on secure interrupts. By construction of the
|
||||
* SP_MIN, secure interrupts can only be handled when core executes in non
|
||||
* secure state.
|
||||
*****************************************************************************/
|
||||
void sp_min_fiq(void)
|
||||
{
|
||||
uint32_t id;
|
||||
|
||||
id = plat_ic_acknowledge_interrupt();
|
||||
sp_min_plat_fiq_handler(id);
|
||||
plat_ic_end_of_interrupt(id);
|
||||
}
|
||||
#endif /* SP_MIN_WITH_SECURE_FIQ */
|
||||
15
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/sp_min/sp_min_private.h
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __SP_MIN_H__
|
||||
#define __SP_MIN_H__
|
||||
|
||||
void sp_min_warm_entrypoint(void);
|
||||
void sp_min_main(void);
|
||||
void sp_min_warm_boot(void);
|
||||
void sp_min_fiq(void);
|
||||
|
||||
#endif /* __SP_MIN_H__ */
|
||||
74
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
|
||||
.globl wa_cve_2017_5715_bpiall_vbar
|
||||
|
||||
vector_base wa_cve_2017_5715_bpiall_vbar
|
||||
/* We encode the exception entry in the bottom 3 bits of SP */
|
||||
add sp, sp, #1 /* Reset: 0b111 */
|
||||
add sp, sp, #1 /* Undef: 0b110 */
|
||||
add sp, sp, #1 /* Syscall: 0b101 */
|
||||
add sp, sp, #1 /* Prefetch abort: 0b100 */
|
||||
add sp, sp, #1 /* Data abort: 0b011 */
|
||||
add sp, sp, #1 /* Reserved: 0b010 */
|
||||
add sp, sp, #1 /* IRQ: 0b001 */
|
||||
nop /* FIQ: 0b000 */
|
||||
|
||||
/*
|
||||
* Invalidate the branch predictor, `r0` is a dummy register
|
||||
* and is unused.
|
||||
*/
|
||||
stcopr r0, BPIALL
|
||||
isb
|
||||
|
||||
/*
|
||||
* As we cannot use any temporary registers and cannot
|
||||
* clobber SP, we can decode the exception entry using
|
||||
* an unrolled binary search.
|
||||
*
|
||||
* Note, if this code is re-used by other secure payloads,
|
||||
* the below exception entry vectors must be changed to
|
||||
* the vectors specific to that secure payload.
|
||||
*/
|
||||
|
||||
tst sp, #4
|
||||
bne 1f
|
||||
|
||||
tst sp, #2
|
||||
bne 3f
|
||||
|
||||
/* Expected encoding: 0x1 and 0x0 */
|
||||
tst sp, #1
|
||||
/* Restore original value of SP by clearing the bottom 3 bits */
|
||||
bic sp, sp, #0x7
|
||||
bne plat_panic_handler /* IRQ */
|
||||
b sp_min_handle_fiq /* FIQ */
|
||||
|
||||
1:
|
||||
tst sp, #2
|
||||
bne 2f
|
||||
|
||||
/* Expected encoding: 0x4 and 0x5 */
|
||||
tst sp, #1
|
||||
bic sp, sp, #0x7
|
||||
bne sp_min_handle_smc /* Syscall */
|
||||
b plat_panic_handler /* Prefetch abort */
|
||||
|
||||
2:
|
||||
/* Expected encoding: 0x7 and 0x6 */
|
||||
tst sp, #1
|
||||
bic sp, sp, #0x7
|
||||
bne sp_min_entrypoint /* Reset */
|
||||
b plat_panic_handler /* Undef */
|
||||
|
||||
3:
|
||||
/* Expected encoding: 0x2 and 0x3 */
|
||||
tst sp, #1
|
||||
bic sp, sp, #0x7
|
||||
bne plat_panic_handler /* Data abort */
|
||||
b plat_panic_handler /* Reserved */
|
||||
75
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
|
||||
.globl wa_cve_2017_5715_icache_inv_vbar
|
||||
|
||||
vector_base wa_cve_2017_5715_icache_inv_vbar
|
||||
/* We encode the exception entry in the bottom 3 bits of SP */
|
||||
add sp, sp, #1 /* Reset: 0b111 */
|
||||
add sp, sp, #1 /* Undef: 0b110 */
|
||||
add sp, sp, #1 /* Syscall: 0b101 */
|
||||
add sp, sp, #1 /* Prefetch abort: 0b100 */
|
||||
add sp, sp, #1 /* Data abort: 0b011 */
|
||||
add sp, sp, #1 /* Reserved: 0b010 */
|
||||
add sp, sp, #1 /* IRQ: 0b001 */
|
||||
nop /* FIQ: 0b000 */
|
||||
|
||||
/*
|
||||
* Invalidate the instruction cache, which we assume also
|
||||
* invalidates the branch predictor. This may depend on
|
||||
* other CPU specific changes (e.g. an ACTLR setting).
|
||||
*/
|
||||
stcopr r0, ICIALLU
|
||||
isb
|
||||
|
||||
/*
|
||||
* As we cannot use any temporary registers and cannot
|
||||
* clobber SP, we can decode the exception entry using
|
||||
* an unrolled binary search.
|
||||
*
|
||||
* Note, if this code is re-used by other secure payloads,
|
||||
* the below exception entry vectors must be changed to
|
||||
* the vectors specific to that secure payload.
|
||||
*/
|
||||
|
||||
tst sp, #4
|
||||
bne 1f
|
||||
|
||||
tst sp, #2
|
||||
bne 3f
|
||||
|
||||
/* Expected encoding: 0x1 and 0x0 */
|
||||
tst sp, #1
|
||||
/* Restore original value of SP by clearing the bottom 3 bits */
|
||||
bic sp, sp, #0x7
|
||||
bne plat_panic_handler /* IRQ */
|
||||
b sp_min_handle_fiq /* FIQ */
|
||||
|
||||
1:
|
||||
/* Expected encoding: 0x4 and 0x5 */
|
||||
tst sp, #2
|
||||
bne 2f
|
||||
|
||||
tst sp, #1
|
||||
bic sp, sp, #0x7
|
||||
bne sp_min_handle_smc /* Syscall */
|
||||
b plat_panic_handler /* Prefetch abort */
|
||||
|
||||
2:
|
||||
/* Expected encoding: 0x7 and 0x6 */
|
||||
tst sp, #1
|
||||
bic sp, sp, #0x7
|
||||
bne sp_min_entrypoint /* Reset */
|
||||
b plat_panic_handler /* Undef */
|
||||
|
||||
3:
|
||||
/* Expected encoding: 0x2 and 0x3 */
|
||||
tst sp, #1
|
||||
bic sp, sp, #0x7
|
||||
bne plat_panic_handler /* Data abort */
|
||||
b plat_panic_handler /* Reserved */
|
||||
453
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S
vendored
Normal file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <tsp.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
#include "../tsp_private.h"
|
||||
|
||||
|
||||
.globl tsp_entrypoint
|
||||
.globl tsp_vector_table
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Populate the params in x0-x7 from the pointer
|
||||
* to the smc args structure in x0.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro restore_args_call_smc
|
||||
ldp x6, x7, [x0, #TSP_ARG6]
|
||||
ldp x4, x5, [x0, #TSP_ARG4]
|
||||
ldp x2, x3, [x0, #TSP_ARG2]
|
||||
ldp x0, x1, [x0, #TSP_ARG0]
|
||||
smc #0
|
||||
.endm
|
||||
|
||||
.macro save_eret_context reg1 reg2
|
||||
mrs \reg1, elr_el1
|
||||
mrs \reg2, spsr_el1
|
||||
stp \reg1, \reg2, [sp, #-0x10]!
|
||||
stp x30, x18, [sp, #-0x10]!
|
||||
.endm
|
||||
|
||||
.macro restore_eret_context reg1 reg2
|
||||
ldp x30, x18, [sp], #0x10
|
||||
ldp \reg1, \reg2, [sp], #0x10
|
||||
msr elr_el1, \reg1
|
||||
msr spsr_el1, \reg2
|
||||
.endm
|
||||
|
||||
func tsp_entrypoint _align=3
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector to something sane.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x0, tsp_exceptions
|
||||
msr vbar_el1, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the SError interrupt now that the
|
||||
* exception vectors have been setup.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the instruction cache, stack pointer
|
||||
* and data access alignment checks
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
|
||||
mrs x0, sctlr_el1
|
||||
orr x0, x0, x1
|
||||
msr sctlr_el1, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Invalidate the RW memory used by the BL32
|
||||
* image. This includes the data and NOBITS
|
||||
* sections. This is done to safeguard against
|
||||
* possible corruption of this memory by dirty
|
||||
* cache lines in a system cache as a result of
|
||||
* use by an earlier boot loader stage.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x0, __RW_START__
|
||||
adr x1, __RW_END__
|
||||
sub x1, x1, x0
|
||||
bl inv_dcache_range
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Zero out NOBITS sections. There are 2 of them:
|
||||
* - the .bss section;
|
||||
* - the coherent memory section.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
ldr x0, =__BSS_START__
|
||||
ldr x1, =__BSS_SIZE__
|
||||
bl zeromem
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
ldr x0, =__COHERENT_RAM_START__
|
||||
ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__
|
||||
bl zeromem
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------
|
||||
* Allocate a stack whose memory will be marked
|
||||
* as Normal-IS-WBWA when the MMU is enabled.
|
||||
* There is no risk of reading stale stack
|
||||
* memory after enabling the MMU as only the
|
||||
* primary cpu is running at the moment.
|
||||
* --------------------------------------------
|
||||
*/
|
||||
bl plat_set_my_stack
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Initialize the stack protector canary before
|
||||
* any C code is called.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
bl update_stack_protector_canary
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Perform early platform setup & platform
|
||||
* specific early arch. setup e.g. mmu setup
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl tsp_early_platform_setup
|
||||
bl tsp_plat_arch_setup
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Jump to main function.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl tsp_main
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Tell TSPD that we are done initialising
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x1, x0
|
||||
mov x0, #TSP_ENTRY_DONE
|
||||
smc #0
|
||||
|
||||
tsp_entrypoint_panic:
|
||||
b tsp_entrypoint_panic
|
||||
endfunc tsp_entrypoint
|
||||
|
||||
|
||||
/* -------------------------------------------
|
||||
* Table of entrypoint vectors provided to the
|
||||
* TSPD for the various entrypoints
|
||||
* -------------------------------------------
|
||||
*/
|
||||
func tsp_vector_table
|
||||
b tsp_yield_smc_entry
|
||||
b tsp_fast_smc_entry
|
||||
b tsp_cpu_on_entry
|
||||
b tsp_cpu_off_entry
|
||||
b tsp_cpu_resume_entry
|
||||
b tsp_cpu_suspend_entry
|
||||
b tsp_sel1_intr_entry
|
||||
b tsp_system_off_entry
|
||||
b tsp_system_reset_entry
|
||||
b tsp_abort_yield_smc_entry
|
||||
endfunc tsp_vector_table
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD when this
|
||||
* cpu is to be turned off through a CPU_OFF
|
||||
* psci call to ask the TSP to perform any
|
||||
* bookeeping necessary. In the current
|
||||
* implementation, the TSPD expects the TSP to
|
||||
* re-initialise its state so nothing is done
|
||||
* here except for acknowledging the request.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_cpu_off_entry
|
||||
bl tsp_cpu_off_main
|
||||
restore_args_call_smc
|
||||
endfunc tsp_cpu_off_entry
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD when the
|
||||
* system is about to be switched off (through
|
||||
* a SYSTEM_OFF psci call) to ask the TSP to
|
||||
* perform any necessary bookkeeping.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_system_off_entry
|
||||
bl tsp_system_off_main
|
||||
restore_args_call_smc
|
||||
endfunc tsp_system_off_entry
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD when the
|
||||
* system is about to be reset (through a
|
||||
* SYSTEM_RESET psci call) to ask the TSP to
|
||||
* perform any necessary bookkeeping.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_system_reset_entry
|
||||
bl tsp_system_reset_main
|
||||
restore_args_call_smc
|
||||
endfunc tsp_system_reset_entry
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD when this
|
||||
* cpu is turned on using a CPU_ON psci call to
|
||||
* ask the TSP to initialise itself i.e. setup
|
||||
* the mmu, stacks etc. Minimal architectural
|
||||
* state will be initialised by the TSPD when
|
||||
* this function is entered i.e. Caches and MMU
|
||||
* will be turned off, the execution state
|
||||
* will be aarch64 and exceptions masked.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_cpu_on_entry
|
||||
/* ---------------------------------------------
|
||||
* Set the exception vector to something sane.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
adr x0, tsp_exceptions
|
||||
msr vbar_el1, x0
|
||||
isb
|
||||
|
||||
/* Enable the SError interrupt */
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the instruction cache, stack pointer
|
||||
* and data access alignment checks
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
|
||||
mrs x0, sctlr_el1
|
||||
orr x0, x0, x1
|
||||
msr sctlr_el1, x0
|
||||
isb
|
||||
|
||||
/* --------------------------------------------
|
||||
* Give ourselves a stack whose memory will be
|
||||
* marked as Normal-IS-WBWA when the MMU is
|
||||
* enabled.
|
||||
* --------------------------------------------
|
||||
*/
|
||||
bl plat_set_my_stack
|
||||
|
||||
/* --------------------------------------------
|
||||
* Enable the MMU with the DCache disabled. It
|
||||
* is safe to use stacks allocated in normal
|
||||
* memory as a result. All memory accesses are
|
||||
* marked nGnRnE when the MMU is disabled. So
|
||||
* all the stack writes will make it to memory.
|
||||
* All memory accesses are marked Non-cacheable
|
||||
* when the MMU is enabled but D$ is disabled.
|
||||
* So used stack memory is guaranteed to be
|
||||
* visible immediately after the MMU is enabled
|
||||
* Enabling the DCache at the same time as the
|
||||
* MMU can lead to speculatively fetched and
|
||||
* possibly stale stack memory being read from
|
||||
* other caches. This can lead to coherency
|
||||
* issues.
|
||||
* --------------------------------------------
|
||||
*/
|
||||
mov x0, #DISABLE_DCACHE
|
||||
bl bl32_plat_enable_mmu
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enable the Data cache now that the MMU has
|
||||
* been enabled. The stack has been unwound. It
|
||||
* will be written first before being read. This
|
||||
* will invalidate any stale cache lines resi-
|
||||
* -dent in other caches. We assume that
|
||||
* interconnect coherency has been enabled for
|
||||
* this cluster by EL3 firmware.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mrs x0, sctlr_el1
|
||||
orr x0, x0, #SCTLR_C_BIT
|
||||
msr sctlr_el1, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Enter C runtime to perform any remaining
|
||||
* book keeping
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bl tsp_cpu_on_main
|
||||
restore_args_call_smc
|
||||
|
||||
/* Should never reach here */
|
||||
tsp_cpu_on_entry_panic:
|
||||
b tsp_cpu_on_entry_panic
|
||||
endfunc tsp_cpu_on_entry
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD when this
|
||||
* cpu is to be suspended through a CPU_SUSPEND
|
||||
* psci call to ask the TSP to perform any
|
||||
* bookeeping necessary. In the current
|
||||
* implementation, the TSPD saves and restores
|
||||
* the EL1 state.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_cpu_suspend_entry
|
||||
bl tsp_cpu_suspend_main
|
||||
restore_args_call_smc
|
||||
endfunc tsp_cpu_suspend_entry
|
||||
|
||||
/*-------------------------------------------------
|
||||
* This entrypoint is used by the TSPD to pass
|
||||
* control for `synchronously` handling a S-EL1
|
||||
* Interrupt which was triggered while executing
|
||||
* in normal world. 'x0' contains a magic number
|
||||
* which indicates this. TSPD expects control to
|
||||
* be handed back at the end of interrupt
|
||||
* processing. This is done through an SMC.
|
||||
* The handover agreement is:
|
||||
*
|
||||
* 1. PSTATE.DAIF are set upon entry. 'x1' has
|
||||
* the ELR_EL3 from the non-secure state.
|
||||
* 2. TSP has to preserve the callee saved
|
||||
* general purpose registers, SP_EL1/EL0 and
|
||||
* LR.
|
||||
* 3. TSP has to preserve the system and vfp
|
||||
* registers (if applicable).
|
||||
* 4. TSP can use 'x0-x18' to enable its C
|
||||
* runtime.
|
||||
* 5. TSP returns to TSPD using an SMC with
|
||||
* 'x0' = TSP_HANDLED_S_EL1_INTR
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
func tsp_sel1_intr_entry
|
||||
#if DEBUG
|
||||
mov_imm x2, TSP_HANDLE_SEL1_INTR_AND_RETURN
|
||||
cmp x0, x2
|
||||
b.ne tsp_sel1_int_entry_panic
|
||||
#endif
|
||||
/*-------------------------------------------------
|
||||
* Save any previous context needed to perform
|
||||
* an exception return from S-EL1 e.g. context
|
||||
* from a previous Non secure Interrupt.
|
||||
* Update statistics and handle the S-EL1
|
||||
* interrupt before returning to the TSPD.
|
||||
* IRQ/FIQs are not enabled since that will
|
||||
* complicate the implementation. Execution
|
||||
* will be transferred back to the normal world
|
||||
* in any case. The handler can return 0
|
||||
* if the interrupt was handled or TSP_PREEMPTED
|
||||
* if the expected interrupt was preempted
|
||||
* by an interrupt that should be handled in EL3
|
||||
* e.g. Group 0 interrupt in GICv3. In both
|
||||
* the cases switch to EL3 using SMC with id
|
||||
* TSP_HANDLED_S_EL1_INTR. Any other return value
|
||||
* from the handler will result in panic.
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
save_eret_context x2 x3
|
||||
bl tsp_update_sync_sel1_intr_stats
|
||||
bl tsp_common_int_handler
|
||||
/* Check if the S-EL1 interrupt has been handled */
|
||||
cbnz x0, tsp_sel1_intr_check_preemption
|
||||
b tsp_sel1_intr_return
|
||||
tsp_sel1_intr_check_preemption:
|
||||
/* Check if the S-EL1 interrupt has been preempted */
|
||||
mov_imm x1, TSP_PREEMPTED
|
||||
cmp x0, x1
|
||||
b.ne tsp_sel1_int_entry_panic
|
||||
tsp_sel1_intr_return:
|
||||
mov_imm x0, TSP_HANDLED_S_EL1_INTR
|
||||
restore_eret_context x2 x3
|
||||
smc #0
|
||||
|
||||
/* Should never reach here */
|
||||
tsp_sel1_int_entry_panic:
|
||||
no_ret plat_panic_handler
|
||||
endfunc tsp_sel1_intr_entry
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD when this
|
||||
* cpu resumes execution after an earlier
|
||||
* CPU_SUSPEND psci call to ask the TSP to
|
||||
* restore its saved context. In the current
|
||||
* implementation, the TSPD saves and restores
|
||||
* EL1 state so nothing is done here apart from
|
||||
* acknowledging the request.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_cpu_resume_entry
|
||||
bl tsp_cpu_resume_main
|
||||
restore_args_call_smc
|
||||
|
||||
/* Should never reach here */
|
||||
no_ret plat_panic_handler
|
||||
endfunc tsp_cpu_resume_entry
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD to ask
|
||||
* the TSP to service a fast smc request.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_fast_smc_entry
|
||||
bl tsp_smc_handler
|
||||
restore_args_call_smc
|
||||
|
||||
/* Should never reach here */
|
||||
no_ret plat_panic_handler
|
||||
endfunc tsp_fast_smc_entry
|
||||
|
||||
/*---------------------------------------------
|
||||
* This entrypoint is used by the TSPD to ask
|
||||
* the TSP to service a Yielding SMC request.
|
||||
* We will enable preemption during execution
|
||||
* of tsp_smc_handler.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func tsp_yield_smc_entry
|
||||
msr daifclr, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
|
||||
bl tsp_smc_handler
|
||||
msr daifset, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
|
||||
restore_args_call_smc
|
||||
|
||||
/* Should never reach here */
|
||||
no_ret plat_panic_handler
|
||||
endfunc tsp_yield_smc_entry
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* This entrypoint is used by the TSPD to abort a pre-empted Yielding
|
||||
* SMC. It could be on behalf of non-secure world or because a CPU
|
||||
* suspend/CPU off request needs to abort the preempted SMC.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func tsp_abort_yield_smc_entry
|
||||
|
||||
/*
|
||||
* Exceptions masking is already done by the TSPD when entering this
|
||||
* hook so there is no need to do it here.
|
||||
*/
|
||||
|
||||
/* Reset the stack used by the pre-empted SMC */
|
||||
bl plat_set_my_stack
|
||||
|
||||
/*
|
||||
* Allow some cleanup such as releasing locks.
|
||||
*/
|
||||
bl tsp_abort_smc_handler
|
||||
|
||||
restore_args_call_smc
|
||||
|
||||
/* Should never reach here */
|
||||
bl plat_panic_handler
|
||||
endfunc tsp_abort_yield_smc_entry
|
||||
163
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
#include <tsp.h>
|
||||
|
||||
|
||||
/* ----------------------------------------------------
|
||||
* The caller-saved registers x0-x18 and LR are saved
|
||||
* here.
|
||||
* ----------------------------------------------------
|
||||
*/
|
||||
|
||||
#define SCRATCH_REG_SIZE #(20 * 8)
|
||||
|
||||
.macro save_caller_regs_and_lr
|
||||
sub sp, sp, SCRATCH_REG_SIZE
|
||||
stp x0, x1, [sp]
|
||||
stp x2, x3, [sp, #0x10]
|
||||
stp x4, x5, [sp, #0x20]
|
||||
stp x6, x7, [sp, #0x30]
|
||||
stp x8, x9, [sp, #0x40]
|
||||
stp x10, x11, [sp, #0x50]
|
||||
stp x12, x13, [sp, #0x60]
|
||||
stp x14, x15, [sp, #0x70]
|
||||
stp x16, x17, [sp, #0x80]
|
||||
stp x18, x30, [sp, #0x90]
|
||||
.endm
|
||||
|
||||
.macro restore_caller_regs_and_lr
|
||||
ldp x0, x1, [sp]
|
||||
ldp x2, x3, [sp, #0x10]
|
||||
ldp x4, x5, [sp, #0x20]
|
||||
ldp x6, x7, [sp, #0x30]
|
||||
ldp x8, x9, [sp, #0x40]
|
||||
ldp x10, x11, [sp, #0x50]
|
||||
ldp x12, x13, [sp, #0x60]
|
||||
ldp x14, x15, [sp, #0x70]
|
||||
ldp x16, x17, [sp, #0x80]
|
||||
ldp x18, x30, [sp, #0x90]
|
||||
add sp, sp, SCRATCH_REG_SIZE
|
||||
.endm
|
||||
|
||||
/* ----------------------------------------------------
|
||||
* Common TSP interrupt handling routine
|
||||
* ----------------------------------------------------
|
||||
*/
|
||||
.macro handle_tsp_interrupt label
|
||||
/* Enable the SError interrupt */
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
save_caller_regs_and_lr
|
||||
bl tsp_common_int_handler
|
||||
cbz x0, interrupt_exit_\label
|
||||
|
||||
/*
|
||||
* This interrupt was not targetted to S-EL1 so send it to
|
||||
* the monitor and wait for execution to resume.
|
||||
*/
|
||||
smc #0
|
||||
interrupt_exit_\label:
|
||||
restore_caller_regs_and_lr
|
||||
eret
|
||||
.endm
|
||||
|
||||
.globl tsp_exceptions
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* TSP exception handlers.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_base tsp_exceptions
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with _sp_el0 : 0x0 - 0x200. No exceptions
|
||||
* are expected and treated as irrecoverable errors.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_sp_el0
|
||||
b plat_panic_handler
|
||||
check_vector_size sync_exception_sp_el0
|
||||
|
||||
vector_entry irq_sp_el0
|
||||
b plat_panic_handler
|
||||
check_vector_size irq_sp_el0
|
||||
|
||||
vector_entry fiq_sp_el0
|
||||
b plat_panic_handler
|
||||
check_vector_size fiq_sp_el0
|
||||
|
||||
vector_entry serror_sp_el0
|
||||
b plat_panic_handler
|
||||
check_vector_size serror_sp_el0
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SPx: 0x200 - 0x400. Only IRQs/FIQs
|
||||
* are expected and handled
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_sp_elx
|
||||
b plat_panic_handler
|
||||
check_vector_size sync_exception_sp_elx
|
||||
|
||||
vector_entry irq_sp_elx
|
||||
handle_tsp_interrupt irq_sp_elx
|
||||
check_vector_size irq_sp_elx
|
||||
|
||||
vector_entry fiq_sp_elx
|
||||
handle_tsp_interrupt fiq_sp_elx
|
||||
check_vector_size fiq_sp_elx
|
||||
|
||||
vector_entry serror_sp_elx
|
||||
b plat_panic_handler
|
||||
check_vector_size serror_sp_elx
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch64 : 0x400 - 0x600. No exceptions
|
||||
* are handled since TSP does not implement a lower EL
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_aarch64
|
||||
b plat_panic_handler
|
||||
check_vector_size sync_exception_aarch64
|
||||
|
||||
vector_entry irq_aarch64
|
||||
b plat_panic_handler
|
||||
check_vector_size irq_aarch64
|
||||
|
||||
vector_entry fiq_aarch64
|
||||
b plat_panic_handler
|
||||
check_vector_size fiq_aarch64
|
||||
|
||||
vector_entry serror_aarch64
|
||||
b plat_panic_handler
|
||||
check_vector_size serror_aarch64
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch32 : 0x600 - 0x800. No exceptions
|
||||
* handled since the TSP does not implement a lower EL.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry sync_exception_aarch32
|
||||
b plat_panic_handler
|
||||
check_vector_size sync_exception_aarch32
|
||||
|
||||
vector_entry irq_aarch32
|
||||
b plat_panic_handler
|
||||
check_vector_size irq_aarch32
|
||||
|
||||
vector_entry fiq_aarch32
|
||||
b plat_panic_handler
|
||||
check_vector_size fiq_aarch32
|
||||
|
||||
vector_entry serror_aarch32
|
||||
b plat_panic_handler
|
||||
check_vector_size serror_aarch32
|
||||
39
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <tsp.h>
|
||||
|
||||
.globl tsp_get_magic
|
||||
|
||||
|
||||
/*
|
||||
* This function raises an SMC to retrieve arguments from secure
|
||||
* monitor/dispatcher, saves the returned arguments the array received in x0,
|
||||
* and then returns to the caller
|
||||
*/
|
||||
func tsp_get_magic
|
||||
/* Save address to stack */
|
||||
stp x0, xzr, [sp, #-16]!
|
||||
|
||||
/* Load arguments */
|
||||
ldr w0, _tsp_fid_get_magic
|
||||
|
||||
/* Raise SMC */
|
||||
smc #0
|
||||
|
||||
/* Restore address from stack */
|
||||
ldp x4, xzr, [sp], #16
|
||||
|
||||
/* Store returned arguments to the array */
|
||||
stp x0, x1, [x4, #0]
|
||||
|
||||
ret
|
||||
endfunc tsp_get_magic
|
||||
|
||||
.align 2
|
||||
_tsp_fid_get_magic:
|
||||
.word TSP_GET_ARGS
|
||||
139
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/tsp.ld.S
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
||||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
||||
ENTRY(tsp_entrypoint)
|
||||
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx): ORIGIN = TSP_SEC_MEM_BASE, LENGTH = TSP_SEC_MEM_SIZE
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BL32_BASE;
|
||||
ASSERT(. == ALIGN(PAGE_SIZE),
|
||||
"BL32_BASE address is not aligned on a page boundary.")
|
||||
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
.text . : {
|
||||
__TEXT_START__ = .;
|
||||
*tsp_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.vectors)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__TEXT_END__ = .;
|
||||
} >RAM
|
||||
|
||||
.rodata . : {
|
||||
__RODATA_START__ = .;
|
||||
*(.rodata*)
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RODATA_END__ = .;
|
||||
} >RAM
|
||||
#else
|
||||
ro . : {
|
||||
__RO_START__ = .;
|
||||
*tsp_entrypoint.o(.text*)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
*(.vectors)
|
||||
__RO_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked as
|
||||
* read-only, executable. No RW data from the next section must
|
||||
* creep in. Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__RO_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark start of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_START__ = . ;
|
||||
|
||||
.data . : {
|
||||
__DATA_START__ = .;
|
||||
*(.data*)
|
||||
__DATA_END__ = .;
|
||||
} >RAM
|
||||
|
||||
#ifdef TSP_PROGBITS_LIMIT
|
||||
ASSERT(. <= TSP_PROGBITS_LIMIT, "TSP progbits has exceeded its limit.")
|
||||
#endif
|
||||
|
||||
stacks (NOLOAD) : {
|
||||
__STACKS_START__ = .;
|
||||
*(tzfw_normal_stacks)
|
||||
__STACKS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The .bss section gets initialised to 0 at runtime.
|
||||
* Its base address should be 16-byte aligned for better performance of the
|
||||
* zero-initialization code.
|
||||
*/
|
||||
.bss : ALIGN(16) {
|
||||
__BSS_START__ = .;
|
||||
*(SORT_BY_ALIGNMENT(.bss*))
|
||||
*(COMMON)
|
||||
__BSS_END__ = .;
|
||||
} >RAM
|
||||
|
||||
/*
|
||||
* The xlat_table section is for full, aligned page tables (4K).
|
||||
* Removing them from .bss avoids forcing 4K alignment on
|
||||
* the .bss section. The tables are initialized to zero by the translation
|
||||
* tables library.
|
||||
*/
|
||||
xlat_table (NOLOAD) : {
|
||||
*(xlat_table)
|
||||
} >RAM
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/*
|
||||
* The base address of the coherent memory section must be page-aligned (4K)
|
||||
* to guarantee that the coherent data are stored on their own pages and
|
||||
* are not mixed with normal data. This is required to set up the correct
|
||||
* memory attributes for the coherent data page tables.
|
||||
*/
|
||||
coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
__COHERENT_RAM_START__ = .;
|
||||
*(tzfw_coherent_mem)
|
||||
__COHERENT_RAM_END_UNALIGNED__ = .;
|
||||
/*
|
||||
* Memory page(s) mapped to this section will be marked
|
||||
* as device memory. No other unexpected data must creep in.
|
||||
* Ensure the rest of the current memory page is unused.
|
||||
*/
|
||||
. = NEXT(PAGE_SIZE);
|
||||
__COHERENT_RAM_END__ = .;
|
||||
} >RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a linker symbol to mark the end of the RW memory area for this
|
||||
* image.
|
||||
*/
|
||||
__RW_END__ = .;
|
||||
__BL32_END__ = .;
|
||||
|
||||
__BSS_SIZE__ = SIZEOF(.bss);
|
||||
#if USE_COHERENT_MEM
|
||||
__COHERENT_RAM_UNALIGNED_SIZE__ =
|
||||
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
|
||||
#endif
|
||||
|
||||
ASSERT(. <= BL32_LIMIT, "BL32 image has exceeded its limit.")
|
||||
}
|
||||
36
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/tsp.mk
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
INCLUDES += -Iinclude/bl32/tsp
|
||||
|
||||
BL32_SOURCES += bl32/tsp/tsp_main.c \
|
||||
bl32/tsp/aarch64/tsp_entrypoint.S \
|
||||
bl32/tsp/aarch64/tsp_exceptions.S \
|
||||
bl32/tsp/aarch64/tsp_request.S \
|
||||
bl32/tsp/tsp_interrupt.c \
|
||||
bl32/tsp/tsp_timer.c \
|
||||
common/aarch64/early_exceptions.S \
|
||||
lib/locks/exclusive/aarch64/spinlock.S
|
||||
|
||||
BL32_LINKERFILE := bl32/tsp/tsp.ld.S
|
||||
|
||||
# This flag determines if the TSPD initializes BL32 in tspd_init() (synchronous
|
||||
# method) or configures BL31 to pass control to BL32 instead of BL33
|
||||
# (asynchronous method).
|
||||
TSP_INIT_ASYNC := 0
|
||||
|
||||
$(eval $(call assert_boolean,TSP_INIT_ASYNC))
|
||||
$(eval $(call add_define,TSP_INIT_ASYNC))
|
||||
|
||||
# Include the platform-specific TSP Makefile
|
||||
# If no platform-specific TSP Makefile exists, it means TSP is not supported
|
||||
# on this platform.
|
||||
TSP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/tsp/tsp-${PLAT}.mk)
|
||||
ifeq (,${TSP_PLAT_MAKEFILE})
|
||||
$(error TSP is not supported on platform ${PLAT})
|
||||
else
|
||||
include ${TSP_PLAT_MAKEFILE}
|
||||
endif
|
||||
113
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/tsp_interrupt.c
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <tsp.h>
|
||||
#include "tsp_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* This function updates the TSP statistics for S-EL1 interrupts handled
|
||||
* synchronously i.e the ones that have been handed over by the TSPD. It also
|
||||
* keeps count of the number of times control was passed back to the TSPD
|
||||
* after handling the interrupt. In the future it will be possible that the
|
||||
* TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to
|
||||
* return execution. This statistic will be useful to distinguish between these
|
||||
* two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter
|
||||
* contains the address of the instruction in normal world where this S-EL1
|
||||
* interrupt was generated.
|
||||
******************************************************************************/
|
||||
void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
tsp_stats[linear_id].sync_sel1_intr_count++;
|
||||
if (type == TSP_HANDLE_SEL1_INTR_AND_RETURN)
|
||||
tsp_stats[linear_id].sync_sel1_intr_ret_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
|
||||
spin_lock(&console_lock);
|
||||
VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%llx\n",
|
||||
read_mpidr(), elr_el3);
|
||||
VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
|
||||
" %d sync s-el1 interrupt returns\n",
|
||||
read_mpidr(),
|
||||
tsp_stats[linear_id].sync_sel1_intr_count,
|
||||
tsp_stats[linear_id].sync_sel1_intr_ret_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* This function is invoked when a non S-EL1 interrupt is received and causes
|
||||
* the preemption of TSP. This function returns TSP_PREEMPTED and results
|
||||
* in the control being handed over to EL3 for handling the interrupt.
|
||||
*****************************************************************************/
|
||||
int32_t tsp_handle_preemption(void)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
tsp_stats[linear_id].preempt_intr_count++;
|
||||
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
|
||||
spin_lock(&console_lock);
|
||||
VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n",
|
||||
read_mpidr(), tsp_stats[linear_id].preempt_intr_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
return TSP_PREEMPTED;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* TSP interrupt handler is called as a part of both synchronous and
|
||||
* asynchronous handling of TSP interrupts. Currently the physical timer
|
||||
* interrupt is the only S-EL1 interrupt that this handler expects. It returns
|
||||
* 0 upon successfully handling the expected interrupt and all other
|
||||
* interrupts are treated as normal world or EL3 interrupts.
|
||||
******************************************************************************/
|
||||
int32_t tsp_common_int_handler(void)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos(), id;
|
||||
|
||||
/*
|
||||
* Get the highest priority pending interrupt id and see if it is the
|
||||
* secure physical generic timer interrupt in which case, handle it.
|
||||
* Otherwise throw this interrupt at the EL3 firmware.
|
||||
*
|
||||
* There is a small time window between reading the highest priority
|
||||
* pending interrupt and acknowledging it during which another
|
||||
* interrupt of higher priority could become the highest pending
|
||||
* interrupt. This is not expected to happen currently for TSP.
|
||||
*/
|
||||
id = plat_ic_get_pending_interrupt_id();
|
||||
|
||||
/* TSP can only handle the secure physical timer interrupt */
|
||||
if (id != TSP_IRQ_SEC_PHY_TIMER)
|
||||
return tsp_handle_preemption();
|
||||
|
||||
/*
|
||||
* Acknowledge and handle the secure timer interrupt. Also sanity check
|
||||
* if it has been preempted by another interrupt through an assertion.
|
||||
*/
|
||||
id = plat_ic_acknowledge_interrupt();
|
||||
assert(id == TSP_IRQ_SEC_PHY_TIMER);
|
||||
tsp_generic_timer_handler();
|
||||
plat_ic_end_of_interrupt(id);
|
||||
|
||||
/* Update the statistics and print some messages */
|
||||
tsp_stats[linear_id].sel1_intr_count++;
|
||||
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
|
||||
spin_lock(&console_lock);
|
||||
VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n",
|
||||
read_mpidr(), id);
|
||||
VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n",
|
||||
read_mpidr(), tsp_stats[linear_id].sel1_intr_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
411
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/tsp_main.c
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <platform_tsp.h>
|
||||
#include <spinlock.h>
|
||||
#include <tsp.h>
|
||||
#include "tsp_private.h"
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Lock to control access to the console
|
||||
******************************************************************************/
|
||||
spinlock_t console_lock;
|
||||
|
||||
/*******************************************************************************
|
||||
* Per cpu data structure to populate parameters for an SMC in C code and use
|
||||
* a pointer to this structure in assembler code to populate x0-x7
|
||||
******************************************************************************/
|
||||
static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
|
||||
|
||||
/*******************************************************************************
|
||||
* Per cpu data structure to keep track of TSP activity
|
||||
******************************************************************************/
|
||||
work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
|
||||
|
||||
/*******************************************************************************
|
||||
* The TSP memory footprint starts at address BL32_BASE and ends with the
|
||||
* linker symbol __BL32_END__. Use these addresses to compute the TSP image
|
||||
* size.
|
||||
******************************************************************************/
|
||||
#define BL32_TOTAL_LIMIT (unsigned long)(&__BL32_END__)
|
||||
#define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE)
|
||||
|
||||
static tsp_args_t *set_smc_args(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
uint32_t linear_id;
|
||||
tsp_args_t *pcpu_smc_args;
|
||||
|
||||
/*
|
||||
* Return to Secure Monitor by raising an SMC. The results of the
|
||||
* service are passed as an arguments to the SMC
|
||||
*/
|
||||
linear_id = plat_my_core_pos();
|
||||
pcpu_smc_args = &tsp_smc_args[linear_id];
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
|
||||
write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
|
||||
|
||||
return pcpu_smc_args;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* TSP main entry point where it gets the opportunity to initialize its secure
|
||||
* state/applications. Once the state is initialized, it must return to the
|
||||
* SPD with a pointer to the 'tsp_vector_table' jump table.
|
||||
******************************************************************************/
|
||||
uint64_t tsp_main(void)
|
||||
{
|
||||
NOTICE("TSP: %s\n", version_string);
|
||||
NOTICE("TSP: %s\n", build_message);
|
||||
INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE);
|
||||
INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE);
|
||||
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/* Initialize the platform */
|
||||
tsp_platform_setup();
|
||||
|
||||
/* Initialize secure/applications state here */
|
||||
tsp_generic_timer_start();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
tsp_stats[linear_id].cpu_on_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
spin_lock(&console_lock);
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
|
||||
read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count,
|
||||
tsp_stats[linear_id].cpu_on_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
return (uint64_t) &tsp_vector_table;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function performs any remaining book keeping in the test secure payload
|
||||
* after this cpu's architectural state has been setup in response to an earlier
|
||||
* psci cpu_on request.
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_cpu_on_main(void)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/* Initialize secure/applications state here */
|
||||
tsp_generic_timer_start();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
tsp_stats[linear_id].cpu_on_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
spin_lock(&console_lock);
|
||||
INFO("TSP: cpu 0x%lx turned on\n", read_mpidr());
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
|
||||
read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count,
|
||||
tsp_stats[linear_id].cpu_on_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
/* Indicate to the SPD that we have completed turned ourselves on */
|
||||
return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function performs any remaining book keeping in the test secure payload
|
||||
* before this cpu is turned off in response to a psci cpu_off request.
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/*
|
||||
* This cpu is being turned off, so disable the timer to prevent the
|
||||
* secure timer interrupt from interfering with power down. A pending
|
||||
* interrupt will be lost but we do not care as we are turning off.
|
||||
*/
|
||||
tsp_generic_timer_stop();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
tsp_stats[linear_id].cpu_off_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
spin_lock(&console_lock);
|
||||
INFO("TSP: cpu 0x%lx off request\n", read_mpidr());
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
|
||||
read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count,
|
||||
tsp_stats[linear_id].cpu_off_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
|
||||
/* Indicate to the SPD that we have completed this request */
|
||||
return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function performs any book keeping in the test secure payload before
|
||||
* this cpu's architectural state is saved in response to an earlier psci
|
||||
* cpu_suspend request.
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/*
|
||||
* Save the time context and disable it to prevent the secure timer
|
||||
* interrupt from interfering with wakeup from the suspend state.
|
||||
*/
|
||||
tsp_generic_timer_save();
|
||||
tsp_generic_timer_stop();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
tsp_stats[linear_id].cpu_suspend_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
spin_lock(&console_lock);
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
|
||||
read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count,
|
||||
tsp_stats[linear_id].cpu_suspend_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
|
||||
/* Indicate to the SPD that we have completed this request */
|
||||
return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function performs any book keeping in the test secure payload after this
|
||||
* cpu's architectural state has been restored after wakeup from an earlier psci
|
||||
* cpu_suspend request.
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/* Restore the generic timer context */
|
||||
tsp_generic_timer_restore();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
tsp_stats[linear_id].cpu_resume_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
spin_lock(&console_lock);
|
||||
INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n",
|
||||
read_mpidr(), max_off_pwrlvl);
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
|
||||
read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count,
|
||||
tsp_stats[linear_id].cpu_suspend_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
/* Indicate to the SPD that we have completed this request */
|
||||
return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function performs any remaining bookkeeping in the test secure payload
|
||||
* before the system is switched off (in response to a psci SYSTEM_OFF request)
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_system_off_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
spin_lock(&console_lock);
|
||||
INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr());
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
|
||||
/* Indicate to the SPD that we have completed this request */
|
||||
return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function performs any remaining bookkeeping in the test secure payload
|
||||
* before the system is reset (in response to a psci SYSTEM_RESET request)
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_system_reset_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
spin_lock(&console_lock);
|
||||
INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr());
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count);
|
||||
spin_unlock(&console_lock);
|
||||
#endif
|
||||
|
||||
/* Indicate to the SPD that we have completed this request */
|
||||
return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* TSP fast smc handler. The secure monitor jumps to this function by
|
||||
* doing the ERET after populating X0-X7 registers. The arguments are received
|
||||
* in the function arguments in order. Once the service is rendered, this
|
||||
* function returns to Secure Monitor by raising SMC.
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_smc_handler(uint64_t func,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
uint64_t results[2];
|
||||
uint64_t service_args[2];
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
/* Update this cpu's statistics */
|
||||
tsp_stats[linear_id].smc_count++;
|
||||
tsp_stats[linear_id].eret_count++;
|
||||
|
||||
INFO("TSP: cpu 0x%lx received %s smc 0x%llx\n", read_mpidr(),
|
||||
((func >> 31) & 1) == 1 ? "fast" : "yielding",
|
||||
func);
|
||||
INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
|
||||
tsp_stats[linear_id].smc_count,
|
||||
tsp_stats[linear_id].eret_count);
|
||||
|
||||
/* Render secure services and obtain results here */
|
||||
results[0] = arg1;
|
||||
results[1] = arg2;
|
||||
|
||||
/*
|
||||
* Request a service back from dispatcher/secure monitor. This call
|
||||
* return and thereafter resume exectuion
|
||||
*/
|
||||
tsp_get_magic(service_args);
|
||||
|
||||
/* Determine the function to perform based on the function ID */
|
||||
switch (TSP_BARE_FID(func)) {
|
||||
case TSP_ADD:
|
||||
results[0] += service_args[0];
|
||||
results[1] += service_args[1];
|
||||
break;
|
||||
case TSP_SUB:
|
||||
results[0] -= service_args[0];
|
||||
results[1] -= service_args[1];
|
||||
break;
|
||||
case TSP_MUL:
|
||||
results[0] *= service_args[0];
|
||||
results[1] *= service_args[1];
|
||||
break;
|
||||
case TSP_DIV:
|
||||
results[0] /= service_args[0] ? service_args[0] : 1;
|
||||
results[1] /= service_args[1] ? service_args[1] : 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return set_smc_args(func, 0,
|
||||
results[0],
|
||||
results[1],
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* TSP smc abort handler. This function is called when aborting a preemtped
|
||||
* yielding SMC request. It should cleanup all resources owned by the SMC
|
||||
* handler such as locks or dynamically allocated memory so following SMC
|
||||
* request are executed in a clean environment.
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_abort_smc_handler(uint64_t func,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
153
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/tsp_private.h
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __TSP_PRIVATE_H__
|
||||
#define __TSP_PRIVATE_H__
|
||||
|
||||
/* Definitions to help the assembler access the SMC/ERET args structure */
|
||||
#define TSP_ARGS_SIZE 0x40
|
||||
#define TSP_ARG0 0x0
|
||||
#define TSP_ARG1 0x8
|
||||
#define TSP_ARG2 0x10
|
||||
#define TSP_ARG3 0x18
|
||||
#define TSP_ARG4 0x20
|
||||
#define TSP_ARG5 0x28
|
||||
#define TSP_ARG6 0x30
|
||||
#define TSP_ARG7 0x38
|
||||
#define TSP_ARGS_END 0x40
|
||||
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <cassert.h>
|
||||
#include <platform_def.h> /* For CACHE_WRITEBACK_GRANULE */
|
||||
#include <spinlock.h>
|
||||
#include <stdint.h>
|
||||
#include <tsp.h>
|
||||
|
||||
|
||||
typedef struct work_statistics {
|
||||
/* Number of s-el1 interrupts on this cpu */
|
||||
uint32_t sel1_intr_count;
|
||||
/* Number of non s-el1 interrupts on this cpu which preempted TSP */
|
||||
uint32_t preempt_intr_count;
|
||||
/* Number of sync s-el1 interrupts on this cpu */
|
||||
uint32_t sync_sel1_intr_count;
|
||||
/* Number of s-el1 interrupts returns on this cpu */
|
||||
uint32_t sync_sel1_intr_ret_count;
|
||||
uint32_t smc_count; /* Number of returns on this cpu */
|
||||
uint32_t eret_count; /* Number of entries on this cpu */
|
||||
uint32_t cpu_on_count; /* Number of cpu on requests */
|
||||
uint32_t cpu_off_count; /* Number of cpu off requests */
|
||||
uint32_t cpu_suspend_count; /* Number of cpu suspend requests */
|
||||
uint32_t cpu_resume_count; /* Number of cpu resume requests */
|
||||
} __aligned(CACHE_WRITEBACK_GRANULE) work_statistics_t;
|
||||
|
||||
typedef struct tsp_args {
|
||||
uint64_t _regs[TSP_ARGS_END >> 3];
|
||||
} __aligned(CACHE_WRITEBACK_GRANULE) tsp_args_t;
|
||||
|
||||
/* Macros to access members of the above structure using their offsets */
|
||||
#define read_sp_arg(args, offset) ((args)->_regs[offset >> 3])
|
||||
#define write_sp_arg(args, offset, val) (((args)->_regs[offset >> 3]) \
|
||||
= val)
|
||||
/*
|
||||
* Ensure that the assembler's view of the size of the tsp_args is the
|
||||
* same as the compilers
|
||||
*/
|
||||
CASSERT(TSP_ARGS_SIZE == sizeof(tsp_args_t), assert_sp_args_size_mismatch);
|
||||
|
||||
void tsp_get_magic(uint64_t args[4]);
|
||||
|
||||
tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7);
|
||||
tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7);
|
||||
tsp_args_t *tsp_cpu_on_main(void);
|
||||
tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7);
|
||||
|
||||
/* Generic Timer functions */
|
||||
void tsp_generic_timer_start(void);
|
||||
void tsp_generic_timer_handler(void);
|
||||
void tsp_generic_timer_stop(void);
|
||||
void tsp_generic_timer_save(void);
|
||||
void tsp_generic_timer_restore(void);
|
||||
|
||||
/* S-EL1 interrupt management functions */
|
||||
void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3);
|
||||
|
||||
|
||||
/* Data structure to keep track of TSP statistics */
|
||||
extern spinlock_t console_lock;
|
||||
extern work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
|
||||
|
||||
/* Vector table of jumps */
|
||||
extern tsp_vectors_t tsp_vector_table;
|
||||
|
||||
/* functions */
|
||||
int32_t tsp_common_int_handler(void);
|
||||
int32_t tsp_handle_preemption(void);
|
||||
|
||||
tsp_args_t *tsp_abort_smc_handler(uint64_t func,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7);
|
||||
|
||||
tsp_args_t *tsp_smc_handler(uint64_t func,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7);
|
||||
|
||||
tsp_args_t *tsp_system_reset_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7);
|
||||
|
||||
tsp_args_t *tsp_system_off_main(uint64_t arg0,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7);
|
||||
|
||||
uint64_t tsp_main(void);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __TSP_PRIVATE_H__ */
|
||||
|
||||
88
firmware/coreboot/3rdparty/arm-trusted-firmware/bl32/tsp/tsp_timer.c
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <platform.h>
|
||||
#include "tsp_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Data structure to keep track of per-cpu secure generic timer context across
|
||||
* power management operations.
|
||||
******************************************************************************/
|
||||
typedef struct timer_context {
|
||||
uint64_t cval;
|
||||
uint32_t ctl;
|
||||
} timer_context_t;
|
||||
|
||||
static timer_context_t pcpu_timer_context[PLATFORM_CORE_COUNT];
|
||||
|
||||
/*******************************************************************************
|
||||
* This function initializes the generic timer to fire every 0.5 second
|
||||
******************************************************************************/
|
||||
void tsp_generic_timer_start(void)
|
||||
{
|
||||
uint64_t cval;
|
||||
uint32_t ctl = 0;
|
||||
|
||||
/* The timer will fire every 0.5 second */
|
||||
cval = read_cntpct_el0() + (read_cntfrq_el0() >> 1);
|
||||
write_cntps_cval_el1(cval);
|
||||
|
||||
/* Enable the secure physical timer */
|
||||
set_cntp_ctl_enable(ctl);
|
||||
write_cntps_ctl_el1(ctl);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function deasserts the timer interrupt and sets it up again
|
||||
******************************************************************************/
|
||||
void tsp_generic_timer_handler(void)
|
||||
{
|
||||
/* Ensure that the timer did assert the interrupt */
|
||||
assert(get_cntp_ctl_istatus(read_cntps_ctl_el1()));
|
||||
|
||||
/*
|
||||
* Disable the timer and reprogram it. The barriers ensure that there is
|
||||
* no reordering of instructions around the reprogramming code.
|
||||
*/
|
||||
isb();
|
||||
write_cntps_ctl_el1(0);
|
||||
tsp_generic_timer_start();
|
||||
isb();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function deasserts the timer interrupt prior to cpu power down
|
||||
******************************************************************************/
|
||||
void tsp_generic_timer_stop(void)
|
||||
{
|
||||
/* Disable the timer */
|
||||
write_cntps_ctl_el1(0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function saves the timer context prior to cpu suspension
|
||||
******************************************************************************/
|
||||
void tsp_generic_timer_save(void)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
pcpu_timer_context[linear_id].cval = read_cntps_cval_el1();
|
||||
pcpu_timer_context[linear_id].ctl = read_cntps_ctl_el1();
|
||||
flush_dcache_range((uint64_t) &pcpu_timer_context[linear_id],
|
||||
sizeof(pcpu_timer_context[linear_id]));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function restores the timer context post cpu resummption
|
||||
******************************************************************************/
|
||||
void tsp_generic_timer_restore(void)
|
||||
{
|
||||
uint32_t linear_id = plat_my_core_pos();
|
||||
|
||||
write_cntps_cval_el1(pcpu_timer_context[linear_id].cval);
|
||||
write_cntps_ctl_el1(pcpu_timer_context[linear_id].ctl);
|
||||
}
|
||||
192
firmware/coreboot/3rdparty/arm-trusted-firmware/common/aarch32/debug.S
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
|
||||
.globl asm_assert
|
||||
.globl do_panic
|
||||
.globl report_exception
|
||||
|
||||
/* Since the max decimal input number is 65536 */
|
||||
#define MAX_DEC_DIVISOR 10000
|
||||
|
||||
/* The offset to add to get ascii for numerals '0 - 9' */
|
||||
#define ASCII_OFFSET_NUM '0'
|
||||
|
||||
.section .rodata.panic_str, "aS"
|
||||
panic_msg:
|
||||
.asciz "PANIC at PC : 0x"
|
||||
panic_end:
|
||||
.asciz "\r\n"
|
||||
|
||||
/***********************************************************
|
||||
* The common implementation of do_panic for all BL stages
|
||||
***********************************************************/
|
||||
func do_panic
|
||||
/* Have LR copy point to PC at the time of panic */
|
||||
sub r6, lr, #4
|
||||
|
||||
/* Initialize crash console and verify success */
|
||||
bl plat_crash_console_init
|
||||
cmp r0, #0
|
||||
beq 1f
|
||||
|
||||
/* Print panic message */
|
||||
ldr r4, =panic_msg
|
||||
bl asm_print_str
|
||||
|
||||
/* Print LR in hex */
|
||||
mov r4, r6
|
||||
bl asm_print_hex
|
||||
|
||||
/* Print new line */
|
||||
ldr r4, =panic_end
|
||||
bl asm_print_str
|
||||
|
||||
bl plat_crash_console_flush
|
||||
|
||||
1:
|
||||
mov lr, r6
|
||||
b plat_panic_handler
|
||||
endfunc do_panic
|
||||
|
||||
/***********************************************************
|
||||
* This function is called from the vector table for
|
||||
* unhandled exceptions. It reads the current mode and
|
||||
* passes it to platform.
|
||||
***********************************************************/
|
||||
func report_exception
|
||||
mrs r0, cpsr
|
||||
and r0, #MODE32_MASK
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
endfunc report_exception
|
||||
|
||||
#if ENABLE_ASSERTIONS
|
||||
.section .rodata.assert_str, "aS"
|
||||
assert_msg1:
|
||||
.asciz "ASSERT: File "
|
||||
assert_msg2:
|
||||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
||||
/******************************************************************
|
||||
* Virtualization comes with the UDIV/SDIV instructions. If missing
|
||||
* write file line number in hexadecimal format.
|
||||
******************************************************************/
|
||||
.asciz " Line 0x"
|
||||
#else
|
||||
.asciz " Line "
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Assertion support in assembly.
|
||||
* The below function helps to support assertions in assembly where we do not
|
||||
* have a C runtime stack. Arguments to the function are :
|
||||
* r0 - File name
|
||||
* r1 - Line no
|
||||
* Clobber list : lr, r0 - r6
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
func asm_assert
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
/*
|
||||
* Only print the output if LOG_LEVEL is higher or equal to
|
||||
* LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
|
||||
*/
|
||||
/* Stash the parameters already in r0 and r1 */
|
||||
mov r5, r0
|
||||
mov r6, r1
|
||||
|
||||
/* Initialize crash console and verify success */
|
||||
bl plat_crash_console_init
|
||||
cmp r0, #0
|
||||
beq 1f
|
||||
|
||||
/* Print file name */
|
||||
ldr r4, =assert_msg1
|
||||
bl asm_print_str
|
||||
mov r4, r5
|
||||
bl asm_print_str
|
||||
|
||||
/* Print line number string */
|
||||
ldr r4, =assert_msg2
|
||||
bl asm_print_str
|
||||
|
||||
/* Test for maximum supported line number */
|
||||
ldr r4, =~0xffff
|
||||
tst r6, r4
|
||||
bne 1f
|
||||
mov r4, r6
|
||||
|
||||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
||||
/******************************************************************
|
||||
* Virtualization comes with the UDIV/SDIV instructions. If missing
|
||||
* write file line number in hexadecimal format.
|
||||
******************************************************************/
|
||||
bl asm_print_hex
|
||||
#else
|
||||
/* Print line number in decimal */
|
||||
mov r6, #10 /* Divide by 10 after every loop iteration */
|
||||
ldr r5, =MAX_DEC_DIVISOR
|
||||
dec_print_loop:
|
||||
udiv r0, r4, r5 /* Quotient */
|
||||
mls r4, r0, r5, r4 /* Remainder */
|
||||
add r0, r0, #ASCII_OFFSET_NUM /* Convert to ASCII */
|
||||
bl plat_crash_console_putc
|
||||
udiv r5, r5, r6 /* Reduce divisor */
|
||||
cmp r5, #0
|
||||
bne dec_print_loop
|
||||
#endif
|
||||
|
||||
bl plat_crash_console_flush
|
||||
|
||||
1:
|
||||
#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
|
||||
no_ret plat_panic_handler
|
||||
endfunc asm_assert
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/*
|
||||
* This function prints a string from address in r4
|
||||
* Clobber: lr, r0 - r4
|
||||
*/
|
||||
func asm_print_str
|
||||
mov r3, lr
|
||||
1:
|
||||
ldrb r0, [r4], #0x1
|
||||
cmp r0, #0
|
||||
beq 2f
|
||||
bl plat_crash_console_putc
|
||||
b 1b
|
||||
2:
|
||||
bx r3
|
||||
endfunc asm_print_str
|
||||
|
||||
/*
|
||||
* This function prints a hexadecimal number in r4.
|
||||
* In: r4 = the hexadecimal to print.
|
||||
* Clobber: lr, r0 - r3, r5
|
||||
*/
|
||||
func asm_print_hex
|
||||
mov r3, lr
|
||||
mov r5, #32 /* No of bits to convert to ascii */
|
||||
1:
|
||||
sub r5, r5, #4
|
||||
lsr r0, r4, r5
|
||||
and r0, r0, #0xf
|
||||
cmp r0, #0xa
|
||||
blo 2f
|
||||
/* Add by 0x27 in addition to ASCII_OFFSET_NUM
|
||||
* to get ascii for characters 'a - f'.
|
||||
*/
|
||||
add r0, r0, #0x27
|
||||
2:
|
||||
add r0, r0, #ASCII_OFFSET_NUM
|
||||
bl plat_crash_console_putc
|
||||
cmp r5, #0
|
||||
bne 1b
|
||||
bx r3
|
||||
endfunc asm_print_hex
|
||||
181
firmware/coreboot/3rdparty/arm-trusted-firmware/common/aarch64/debug.S
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <debug.h>
|
||||
|
||||
.globl asm_print_str
|
||||
.globl asm_print_hex
|
||||
.globl asm_assert
|
||||
.globl do_panic
|
||||
|
||||
/* Since the max decimal input number is 65536 */
|
||||
#define MAX_DEC_DIVISOR 10000
|
||||
/* The offset to add to get ascii for numerals '0 - 9' */
|
||||
#define ASCII_OFFSET_NUM 0x30
|
||||
|
||||
#if ENABLE_ASSERTIONS
|
||||
.section .rodata.assert_str, "aS"
|
||||
assert_msg1:
|
||||
.asciz "ASSERT: File "
|
||||
assert_msg2:
|
||||
.asciz " Line "
|
||||
|
||||
/*
|
||||
* This macro is intended to be used to print the
|
||||
* line number in decimal. Used by asm_assert macro.
|
||||
* The max number expected is 65536.
|
||||
* In: x4 = the decimal to print.
|
||||
* Clobber: x30, x0, x1, x2, x5, x6
|
||||
*/
|
||||
.macro asm_print_line_dec
|
||||
mov x6, #10 /* Divide by 10 after every loop iteration */
|
||||
mov x5, #MAX_DEC_DIVISOR
|
||||
dec_print_loop:
|
||||
udiv x0, x4, x5 /* Get the quotient */
|
||||
msub x4, x0, x5, x4 /* Find the remainder */
|
||||
add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */
|
||||
bl plat_crash_console_putc
|
||||
udiv x5, x5, x6 /* Reduce divisor */
|
||||
cbnz x5, dec_print_loop
|
||||
.endm
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Assertion support in assembly.
|
||||
* The below function helps to support assertions in assembly where we do not
|
||||
* have a C runtime stack. Arguments to the function are :
|
||||
* x0 - File name
|
||||
* x1 - Line no
|
||||
* Clobber list : x30, x0, x1, x2, x3, x4, x5, x6.
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
func asm_assert
|
||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
||||
/*
|
||||
* Only print the output if LOG_LEVEL is higher or equal to
|
||||
* LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
|
||||
*/
|
||||
mov x5, x0
|
||||
mov x6, x1
|
||||
/* Ensure the console is initialized */
|
||||
bl plat_crash_console_init
|
||||
/* Check if the console is initialized */
|
||||
cbz x0, _assert_loop
|
||||
/* The console is initialized */
|
||||
adr x4, assert_msg1
|
||||
bl asm_print_str
|
||||
mov x4, x5
|
||||
bl asm_print_str
|
||||
adr x4, assert_msg2
|
||||
bl asm_print_str
|
||||
/* Check if line number higher than max permitted */
|
||||
tst x6, #~0xffff
|
||||
b.ne _assert_loop
|
||||
mov x4, x6
|
||||
asm_print_line_dec
|
||||
bl plat_crash_console_flush
|
||||
_assert_loop:
|
||||
#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
|
||||
no_ret plat_panic_handler
|
||||
endfunc asm_assert
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/*
|
||||
* This function prints a string from address in x4.
|
||||
* In: x4 = pointer to string.
|
||||
* Clobber: x30, x0, x1, x2, x3
|
||||
*/
|
||||
func asm_print_str
|
||||
mov x3, x30
|
||||
1:
|
||||
ldrb w0, [x4], #0x1
|
||||
cbz x0, 2f
|
||||
bl plat_crash_console_putc
|
||||
b 1b
|
||||
2:
|
||||
ret x3
|
||||
endfunc asm_print_str
|
||||
|
||||
/*
|
||||
* This function prints a hexadecimal number in x4.
|
||||
* In: x4 = the hexadecimal to print.
|
||||
* Clobber: x30, x0 - x3, x5
|
||||
*/
|
||||
func asm_print_hex
|
||||
mov x3, x30
|
||||
mov x5, #64 /* No of bits to convert to ascii */
|
||||
1:
|
||||
sub x5, x5, #4
|
||||
lsrv x0, x4, x5
|
||||
and x0, x0, #0xf
|
||||
cmp x0, #0xA
|
||||
b.lo 2f
|
||||
/* Add by 0x27 in addition to ASCII_OFFSET_NUM
|
||||
* to get ascii for characters 'a - f'.
|
||||
*/
|
||||
add x0, x0, #0x27
|
||||
2:
|
||||
add x0, x0, #ASCII_OFFSET_NUM
|
||||
bl plat_crash_console_putc
|
||||
cbnz x5, 1b
|
||||
ret x3
|
||||
endfunc asm_print_hex
|
||||
|
||||
/***********************************************************
|
||||
* The common implementation of do_panic for all BL stages
|
||||
***********************************************************/
|
||||
|
||||
.section .rodata.panic_str, "aS"
|
||||
panic_msg: .asciz "PANIC at PC : 0x"
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* do_panic assumes that it is invoked from a C Runtime Environment ie a
|
||||
* valid stack exists. This call will not return.
|
||||
* Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* This is for the non el3 BL stages to compile through */
|
||||
.weak el3_panic
|
||||
|
||||
func do_panic
|
||||
#if CRASH_REPORTING
|
||||
str x0, [sp, #-0x10]!
|
||||
mrs x0, currentel
|
||||
ubfx x0, x0, #2, #2
|
||||
cmp x0, #0x3
|
||||
ldr x0, [sp], #0x10
|
||||
b.eq el3_panic
|
||||
#endif
|
||||
|
||||
panic_common:
|
||||
/*
|
||||
* el3_panic will be redefined by the BL31
|
||||
* crash reporting mechanism (if enabled)
|
||||
*/
|
||||
el3_panic:
|
||||
mov x6, x30
|
||||
bl plat_crash_console_init
|
||||
/* Check if the console is initialized */
|
||||
cbz x0, _panic_handler
|
||||
/* The console is initialized */
|
||||
adr x4, panic_msg
|
||||
bl asm_print_str
|
||||
mov x4, x6
|
||||
/* The panic location is lr -4 */
|
||||
sub x4, x4, #4
|
||||
bl asm_print_hex
|
||||
|
||||
bl plat_crash_console_flush
|
||||
|
||||
_panic_handler:
|
||||
/* Pass to plat_panic_handler the address from where el3_panic was
|
||||
* called, not the address of the call from el3_panic. */
|
||||
mov x30, x6
|
||||
b plat_panic_handler
|
||||
endfunc do_panic
|
||||
129
firmware/coreboot/3rdparty/arm-trusted-firmware/common/aarch64/early_exceptions.S
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <bl_common.h>
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Very simple stackless exception handlers used by BL2 and BL31 stages.
|
||||
* BL31 uses them before stacks are setup. BL2 uses them throughout.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
.globl early_exceptions
|
||||
|
||||
vector_base early_exceptions
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SP0 : 0x0 - 0x200
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSP0
|
||||
mov x0, #SYNC_EXCEPTION_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionSP0
|
||||
|
||||
vector_entry IrqSP0
|
||||
mov x0, #IRQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqSP0
|
||||
|
||||
vector_entry FiqSP0
|
||||
mov x0, #FIQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqSP0
|
||||
|
||||
vector_entry SErrorSP0
|
||||
mov x0, #SERROR_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorSP0
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SPx: 0x200 - 0x400
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSPx
|
||||
mov x0, #SYNC_EXCEPTION_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionSPx
|
||||
|
||||
vector_entry IrqSPx
|
||||
mov x0, #IRQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqSPx
|
||||
|
||||
vector_entry FiqSPx
|
||||
mov x0, #FIQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqSPx
|
||||
|
||||
vector_entry SErrorSPx
|
||||
mov x0, #SERROR_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorSPx
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch64 : 0x400 - 0x600
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionA64
|
||||
mov x0, #SYNC_EXCEPTION_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionA64
|
||||
|
||||
vector_entry IrqA64
|
||||
mov x0, #IRQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqA64
|
||||
|
||||
vector_entry FiqA64
|
||||
mov x0, #FIQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqA64
|
||||
|
||||
vector_entry SErrorA64
|
||||
mov x0, #SERROR_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorA64
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch32 : 0x600 - 0x800
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionA32
|
||||
mov x0, #SYNC_EXCEPTION_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SynchronousExceptionA32
|
||||
|
||||
vector_entry IrqA32
|
||||
mov x0, #IRQ_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size IrqA32
|
||||
|
||||
vector_entry FiqA32
|
||||
mov x0, #FIQ_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size FiqA32
|
||||
|
||||
vector_entry SErrorA32
|
||||
mov x0, #SERROR_AARCH32
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
check_vector_size SErrorA32
|
||||
620
firmware/coreboot/3rdparty/arm-trusted-firmware/common/bl_common.c
vendored
Normal file
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <io_storage.h>
|
||||
#include <platform.h>
|
||||
#include <string.h>
|
||||
#include <utils.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
# ifdef DYN_DISABLE_AUTH
|
||||
static int disable_auth;
|
||||
|
||||
/******************************************************************************
|
||||
* API to dynamically disable authentication. Only meant for development
|
||||
* systems. This is only invoked if DYN_DISABLE_AUTH is defined. This
|
||||
* capability is restricted to LOAD_IMAGE_V2.
|
||||
*****************************************************************************/
|
||||
void dyn_disable_auth(void)
|
||||
{
|
||||
INFO("Disabling authentication of images dynamically\n");
|
||||
disable_auth = 1;
|
||||
}
|
||||
# endif /* DYN_DISABLE_AUTH */
|
||||
|
||||
/******************************************************************************
|
||||
* Function to determine whether the authentication is disabled dynamically.
|
||||
*****************************************************************************/
|
||||
static int dyn_is_auth_disabled(void)
|
||||
{
|
||||
# ifdef DYN_DISABLE_AUTH
|
||||
return disable_auth;
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
uintptr_t page_align(uintptr_t value, unsigned dir)
|
||||
{
|
||||
/* Round up the limit to the next page boundary */
|
||||
if (value & (PAGE_SIZE - 1)) {
|
||||
value &= ~(PAGE_SIZE - 1);
|
||||
if (dir == UP)
|
||||
value += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Determine whether the memory region delimited by 'addr' and 'size' is free,
|
||||
* given the extents of free memory.
|
||||
* Return 1 if it is free, 0 if it is not free or if the input values are
|
||||
* invalid.
|
||||
*****************************************************************************/
|
||||
int is_mem_free(uintptr_t free_base, size_t free_size,
|
||||
uintptr_t addr, size_t size)
|
||||
{
|
||||
uintptr_t free_end, requested_end;
|
||||
|
||||
/*
|
||||
* Handle corner cases first.
|
||||
*
|
||||
* The order of the 2 tests is important, because if there's no space
|
||||
* left (i.e. free_size == 0) but we don't ask for any memory
|
||||
* (i.e. size == 0) then we should report that the memory is free.
|
||||
*/
|
||||
if (size == 0)
|
||||
return 1; /* A zero-byte region is always free */
|
||||
if (free_size == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check that the end addresses don't overflow.
|
||||
* If they do, consider that this memory region is not free, as this
|
||||
* is an invalid scenario.
|
||||
*/
|
||||
if (check_uptr_overflow(free_base, free_size - 1))
|
||||
return 0;
|
||||
free_end = free_base + (free_size - 1);
|
||||
|
||||
if (check_uptr_overflow(addr, size - 1))
|
||||
return 0;
|
||||
requested_end = addr + (size - 1);
|
||||
|
||||
/*
|
||||
* Finally, check that the requested memory region lies within the free
|
||||
* region.
|
||||
*/
|
||||
return (addr >= free_base) && (requested_end <= free_end);
|
||||
}
|
||||
|
||||
#if !LOAD_IMAGE_V2
|
||||
/******************************************************************************
|
||||
* Inside a given memory region, determine whether a sub-region of memory is
|
||||
* closer from the top or the bottom of the encompassing region. Return the
|
||||
* size of the smallest chunk of free memory surrounding the sub-region in
|
||||
* 'small_chunk_size'.
|
||||
*****************************************************************************/
|
||||
static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end,
|
||||
uintptr_t submem_start, uintptr_t submem_end,
|
||||
size_t *small_chunk_size)
|
||||
{
|
||||
size_t top_chunk_size, bottom_chunk_size;
|
||||
|
||||
assert(mem_start <= submem_start);
|
||||
assert(submem_start <= submem_end);
|
||||
assert(submem_end <= mem_end);
|
||||
assert(small_chunk_size != NULL);
|
||||
|
||||
top_chunk_size = mem_end - submem_end;
|
||||
bottom_chunk_size = submem_start - mem_start;
|
||||
|
||||
if (top_chunk_size < bottom_chunk_size) {
|
||||
*small_chunk_size = top_chunk_size;
|
||||
return TOP;
|
||||
} else {
|
||||
*small_chunk_size = bottom_chunk_size;
|
||||
return BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Reserve the memory region delimited by 'addr' and 'size'. The extents of free
|
||||
* memory are passed in 'free_base' and 'free_size' and they will be updated to
|
||||
* reflect the memory usage.
|
||||
* The caller must ensure the memory to reserve is free and that the addresses
|
||||
* and sizes passed in arguments are sane.
|
||||
*****************************************************************************/
|
||||
void reserve_mem(uintptr_t *free_base, size_t *free_size,
|
||||
uintptr_t addr, size_t size)
|
||||
{
|
||||
size_t discard_size;
|
||||
size_t reserved_size;
|
||||
unsigned int pos;
|
||||
|
||||
assert(free_base != NULL);
|
||||
assert(free_size != NULL);
|
||||
assert(is_mem_free(*free_base, *free_size, addr, size));
|
||||
|
||||
if (size == 0) {
|
||||
WARN("Nothing to allocate, requested size is zero\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pos = choose_mem_pos(*free_base, *free_base + (*free_size - 1),
|
||||
addr, addr + (size - 1),
|
||||
&discard_size);
|
||||
|
||||
reserved_size = size + discard_size;
|
||||
*free_size -= reserved_size;
|
||||
|
||||
if (pos == BOTTOM)
|
||||
*free_base = addr + size;
|
||||
|
||||
VERBOSE("Reserved 0x%zx bytes (discarded 0x%zx bytes %s)\n",
|
||||
reserved_size, discard_size,
|
||||
pos == TOP ? "above" : "below");
|
||||
}
|
||||
|
||||
static void dump_load_info(uintptr_t image_load_addr,
|
||||
size_t image_size,
|
||||
const meminfo_t *mem_layout)
|
||||
{
|
||||
INFO("Trying to load image at address %p, size = 0x%zx\n",
|
||||
(void *)image_load_addr, image_size);
|
||||
INFO("Current memory layout:\n");
|
||||
INFO(" total region = [base = %p, size = 0x%zx]\n",
|
||||
(void *) mem_layout->total_base, mem_layout->total_size);
|
||||
INFO(" free region = [base = %p, size = 0x%zx]\n",
|
||||
(void *) mem_layout->free_base, mem_layout->free_size);
|
||||
}
|
||||
#endif /* LOAD_IMAGE_V2 */
|
||||
|
||||
/* Generic function to return the size of an image */
|
||||
size_t get_image_size(unsigned int image_id)
|
||||
{
|
||||
uintptr_t dev_handle;
|
||||
uintptr_t image_handle;
|
||||
uintptr_t image_spec;
|
||||
size_t image_size = 0;
|
||||
int io_result;
|
||||
|
||||
/* Obtain a reference to the image by querying the platform layer */
|
||||
io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
|
||||
if (io_result != 0) {
|
||||
WARN("Failed to obtain reference to image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attempt to access the image */
|
||||
io_result = io_open(dev_handle, image_spec, &image_handle);
|
||||
if (io_result != 0) {
|
||||
WARN("Failed to access image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the size of the image */
|
||||
io_result = io_size(image_handle, &image_size);
|
||||
if ((io_result != 0) || (image_size == 0)) {
|
||||
WARN("Failed to determine the size of the image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
}
|
||||
io_result = io_close(image_handle);
|
||||
/* Ignore improbable/unrecoverable error in 'close' */
|
||||
|
||||
/* TODO: Consider maintaining open device connection from this
|
||||
* bootloader stage
|
||||
*/
|
||||
io_result = io_dev_close(dev_handle);
|
||||
/* Ignore improbable/unrecoverable error in 'dev_close' */
|
||||
|
||||
return image_size;
|
||||
}
|
||||
|
||||
#if LOAD_IMAGE_V2
|
||||
|
||||
/*******************************************************************************
|
||||
* Internal function to load an image at a specific address given
|
||||
* an image ID and extents of free memory.
|
||||
*
|
||||
* If the load is successful then the image information is updated.
|
||||
*
|
||||
* Returns 0 on success, a negative error code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_image(unsigned int image_id, image_info_t *image_data)
|
||||
{
|
||||
uintptr_t dev_handle;
|
||||
uintptr_t image_handle;
|
||||
uintptr_t image_spec;
|
||||
uintptr_t image_base;
|
||||
size_t image_size;
|
||||
size_t bytes_read;
|
||||
int io_result;
|
||||
|
||||
assert(image_data != NULL);
|
||||
assert(image_data->h.version >= VERSION_2);
|
||||
|
||||
image_base = image_data->image_base;
|
||||
|
||||
/* Obtain a reference to the image by querying the platform layer */
|
||||
io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
|
||||
if (io_result != 0) {
|
||||
WARN("Failed to obtain reference to image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
return io_result;
|
||||
}
|
||||
|
||||
/* Attempt to access the image */
|
||||
io_result = io_open(dev_handle, image_spec, &image_handle);
|
||||
if (io_result != 0) {
|
||||
WARN("Failed to access image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
return io_result;
|
||||
}
|
||||
|
||||
INFO("Loading image id=%u at address %p\n", image_id,
|
||||
(void *) image_base);
|
||||
|
||||
/* Find the size of the image */
|
||||
io_result = io_size(image_handle, &image_size);
|
||||
if ((io_result != 0) || (image_size == 0)) {
|
||||
WARN("Failed to determine the size of the image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check that the image size to load is within limit */
|
||||
if (image_size > image_data->image_max_size) {
|
||||
WARN("Image id=%u size out of bounds\n", image_id);
|
||||
io_result = -EFBIG;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
image_data->image_size = image_size;
|
||||
|
||||
/* We have enough space so load the image now */
|
||||
/* TODO: Consider whether to try to recover/retry a partially successful read */
|
||||
io_result = io_read(image_handle, image_base, image_size, &bytes_read);
|
||||
if ((io_result != 0) || (bytes_read < image_size)) {
|
||||
WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
|
||||
(void *) (image_base + image_size));
|
||||
|
||||
exit:
|
||||
io_close(image_handle);
|
||||
/* Ignore improbable/unrecoverable error in 'close' */
|
||||
|
||||
/* TODO: Consider maintaining open device connection from this bootloader stage */
|
||||
io_dev_close(dev_handle);
|
||||
/* Ignore improbable/unrecoverable error in 'dev_close' */
|
||||
|
||||
return io_result;
|
||||
}
|
||||
|
||||
static int load_auth_image_internal(unsigned int image_id,
|
||||
image_info_t *image_data,
|
||||
int is_parent_image)
|
||||
{
|
||||
int rc;
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
if (dyn_is_auth_disabled() == 0) {
|
||||
unsigned int parent_id;
|
||||
|
||||
/* Use recursion to authenticate parent images */
|
||||
rc = auth_mod_get_parent_id(image_id, &parent_id);
|
||||
if (rc == 0) {
|
||||
rc = load_auth_image_internal(parent_id, image_data, 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
/* Load the image */
|
||||
rc = load_image(image_id, image_data);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
if (dyn_is_auth_disabled() == 0) {
|
||||
/* Authenticate it */
|
||||
rc = auth_mod_verify_img(image_id,
|
||||
(void *)image_data->image_base,
|
||||
image_data->image_size);
|
||||
if (rc != 0) {
|
||||
/* Authentication error, zero memory and flush it right away. */
|
||||
zero_normalmem((void *)image_data->image_base,
|
||||
image_data->image_size);
|
||||
flush_dcache_range(image_data->image_base,
|
||||
image_data->image_size);
|
||||
return -EAUTH;
|
||||
}
|
||||
}
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
/*
|
||||
* Flush the image to main memory so that it can be executed later by
|
||||
* any CPU, regardless of cache and MMU state. If TBB is enabled, then
|
||||
* the file has been successfully loaded and authenticated and flush
|
||||
* only for child images, not for the parents (certificates).
|
||||
*/
|
||||
if (!is_parent_image) {
|
||||
flush_dcache_range(image_data->image_base,
|
||||
image_data->image_size);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Generic function to load and authenticate an image. The image is actually
|
||||
* loaded by calling the 'load_image()' function. Therefore, it returns the
|
||||
* same error codes if the loading operation failed, or -EAUTH if the
|
||||
* authentication failed. In addition, this function uses recursion to
|
||||
* authenticate the parent images up to the root of trust.
|
||||
******************************************************************************/
|
||||
int load_auth_image(unsigned int image_id, image_info_t *image_data)
|
||||
{
|
||||
int err;
|
||||
|
||||
do {
|
||||
err = load_auth_image_internal(image_id, image_data, 0);
|
||||
} while (err != 0 && plat_try_next_boot_source());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#else /* LOAD_IMAGE_V2 */
|
||||
|
||||
/*******************************************************************************
|
||||
* Generic function to load an image at a specific address given an image ID and
|
||||
* extents of free memory.
|
||||
*
|
||||
* If the load is successful then the image information is updated.
|
||||
*
|
||||
* If the entry_point_info argument is not NULL then this function also updates:
|
||||
* - the memory layout to mark the memory as reserved;
|
||||
* - the entry point information.
|
||||
*
|
||||
* The caller might pass a NULL pointer for the entry point if they are not
|
||||
* interested in this information. This is typically the case for non-executable
|
||||
* images (e.g. certificates) and executable images that won't ever be executed
|
||||
* on the application processor (e.g. additional microcontroller firmware).
|
||||
*
|
||||
* Returns 0 on success, a negative error code otherwise.
|
||||
******************************************************************************/
|
||||
int load_image(meminfo_t *mem_layout,
|
||||
unsigned int image_id,
|
||||
uintptr_t image_base,
|
||||
image_info_t *image_data,
|
||||
entry_point_info_t *entry_point_info)
|
||||
{
|
||||
uintptr_t dev_handle;
|
||||
uintptr_t image_handle;
|
||||
uintptr_t image_spec;
|
||||
size_t image_size;
|
||||
size_t bytes_read;
|
||||
int io_result;
|
||||
|
||||
assert(mem_layout != NULL);
|
||||
assert(image_data != NULL);
|
||||
assert(image_data->h.version == VERSION_1);
|
||||
|
||||
/* Obtain a reference to the image by querying the platform layer */
|
||||
io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
|
||||
if (io_result != 0) {
|
||||
WARN("Failed to obtain reference to image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
return io_result;
|
||||
}
|
||||
|
||||
/* Attempt to access the image */
|
||||
io_result = io_open(dev_handle, image_spec, &image_handle);
|
||||
if (io_result != 0) {
|
||||
WARN("Failed to access image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
return io_result;
|
||||
}
|
||||
|
||||
INFO("Loading image id=%u at address %p\n", image_id,
|
||||
(void *) image_base);
|
||||
|
||||
/* Find the size of the image */
|
||||
io_result = io_size(image_handle, &image_size);
|
||||
if ((io_result != 0) || (image_size == 0)) {
|
||||
WARN("Failed to determine the size of the image id=%u (%i)\n",
|
||||
image_id, io_result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check that the memory where the image will be loaded is free */
|
||||
if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
|
||||
image_base, image_size)) {
|
||||
WARN("Failed to reserve region [base = %p, size = 0x%zx]\n",
|
||||
(void *) image_base, image_size);
|
||||
dump_load_info(image_base, image_size, mem_layout);
|
||||
io_result = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* We have enough space so load the image now */
|
||||
/* TODO: Consider whether to try to recover/retry a partially successful read */
|
||||
io_result = io_read(image_handle, image_base, image_size, &bytes_read);
|
||||
if ((io_result != 0) || (bytes_read < image_size)) {
|
||||
WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
image_data->image_base = image_base;
|
||||
image_data->image_size = image_size;
|
||||
|
||||
/*
|
||||
* Update the memory usage info.
|
||||
* This is done after the actual loading so that it is not updated when
|
||||
* the load is unsuccessful.
|
||||
* If the caller does not provide an entry point, bypass the memory
|
||||
* reservation.
|
||||
*/
|
||||
if (entry_point_info != NULL) {
|
||||
reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
|
||||
image_base, image_size);
|
||||
entry_point_info->pc = image_base;
|
||||
} else {
|
||||
INFO("Skip reserving region [base = %p, size = 0x%zx]\n",
|
||||
(void *) image_base, image_size);
|
||||
}
|
||||
|
||||
#if !TRUSTED_BOARD_BOOT
|
||||
/*
|
||||
* File has been successfully loaded.
|
||||
* Flush the image to main memory so that it can be executed later by
|
||||
* any CPU, regardless of cache and MMU state.
|
||||
* When TBB is enabled the image is flushed later, after image
|
||||
* authentication.
|
||||
*/
|
||||
flush_dcache_range(image_base, image_size);
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id,
|
||||
(void *) image_base, image_size);
|
||||
|
||||
exit:
|
||||
io_close(image_handle);
|
||||
/* Ignore improbable/unrecoverable error in 'close' */
|
||||
|
||||
/* TODO: Consider maintaining open device connection from this bootloader stage */
|
||||
io_dev_close(dev_handle);
|
||||
/* Ignore improbable/unrecoverable error in 'dev_close' */
|
||||
|
||||
return io_result;
|
||||
}
|
||||
|
||||
static int load_auth_image_internal(meminfo_t *mem_layout,
|
||||
unsigned int image_id,
|
||||
uintptr_t image_base,
|
||||
image_info_t *image_data,
|
||||
entry_point_info_t *entry_point_info,
|
||||
int is_parent_image)
|
||||
{
|
||||
int rc;
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
unsigned int parent_id;
|
||||
|
||||
/* Use recursion to authenticate parent images */
|
||||
rc = auth_mod_get_parent_id(image_id, &parent_id);
|
||||
if (rc == 0) {
|
||||
rc = load_auth_image_internal(mem_layout, parent_id, image_base,
|
||||
image_data, NULL, 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
/* Load the image */
|
||||
rc = load_image(mem_layout, image_id, image_base, image_data,
|
||||
entry_point_info);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
/* Authenticate it */
|
||||
rc = auth_mod_verify_img(image_id,
|
||||
(void *)image_data->image_base,
|
||||
image_data->image_size);
|
||||
if (rc != 0) {
|
||||
/* Authentication error, zero memory and flush it right away. */
|
||||
zero_normalmem((void *)image_data->image_base,
|
||||
image_data->image_size);
|
||||
flush_dcache_range(image_data->image_base,
|
||||
image_data->image_size);
|
||||
return -EAUTH;
|
||||
}
|
||||
/*
|
||||
* File has been successfully loaded and authenticated.
|
||||
* Flush the image to main memory so that it can be executed later by
|
||||
* any CPU, regardless of cache and MMU state.
|
||||
* Do it only for child images, not for the parents (certificates).
|
||||
*/
|
||||
if (!is_parent_image) {
|
||||
flush_dcache_range(image_data->image_base,
|
||||
image_data->image_size);
|
||||
}
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Generic function to load and authenticate an image. The image is actually
|
||||
* loaded by calling the 'load_image()' function. Therefore, it returns the
|
||||
* same error codes if the loading operation failed, or -EAUTH if the
|
||||
* authentication failed. In addition, this function uses recursion to
|
||||
* authenticate the parent images up to the root of trust.
|
||||
******************************************************************************/
|
||||
int load_auth_image(meminfo_t *mem_layout,
|
||||
unsigned int image_id,
|
||||
uintptr_t image_base,
|
||||
image_info_t *image_data,
|
||||
entry_point_info_t *entry_point_info)
|
||||
{
|
||||
int err;
|
||||
|
||||
do {
|
||||
err = load_auth_image_internal(mem_layout, image_id, image_base,
|
||||
image_data, entry_point_info, 0);
|
||||
} while (err != 0 && plat_try_next_boot_source());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LOAD_IMAGE_V2 */
|
||||
|
||||
/*******************************************************************************
|
||||
* Print the content of an entry_point_info_t structure.
|
||||
******************************************************************************/
|
||||
void print_entry_point_info(const entry_point_info_t *ep_info)
|
||||
{
|
||||
INFO("Entry point address = %p\n", (void *)ep_info->pc);
|
||||
INFO("SPSR = 0x%x\n", ep_info->spsr);
|
||||
|
||||
#define PRINT_IMAGE_ARG(n) \
|
||||
VERBOSE("Argument #" #n " = 0x%llx\n", \
|
||||
(unsigned long long) ep_info->args.arg##n)
|
||||
|
||||
PRINT_IMAGE_ARG(0);
|
||||
PRINT_IMAGE_ARG(1);
|
||||
PRINT_IMAGE_ARG(2);
|
||||
PRINT_IMAGE_ARG(3);
|
||||
#ifndef AARCH32
|
||||
PRINT_IMAGE_ARG(4);
|
||||
PRINT_IMAGE_ARG(5);
|
||||
PRINT_IMAGE_ARG(6);
|
||||
PRINT_IMAGE_ARG(7);
|
||||
#endif
|
||||
#undef PRINT_IMAGE_ARG
|
||||
}
|
||||
261
firmware/coreboot/3rdparty/arm-trusted-firmware/common/desc_image_load.c
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <desc_image_load.h>
|
||||
|
||||
|
||||
|
||||
static bl_load_info_t bl_load_info;
|
||||
static bl_params_t next_bl_params;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* This function flushes the data structures so that they are visible
|
||||
* in memory for the next BL image.
|
||||
******************************************************************************/
|
||||
void flush_bl_params_desc(void)
|
||||
{
|
||||
flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr,
|
||||
sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num);
|
||||
|
||||
flush_dcache_range((uintptr_t)&next_bl_params,
|
||||
sizeof(next_bl_params));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the index for given image_id, within the
|
||||
* image descriptor array provided by bl_image_info_descs_ptr, if the
|
||||
* image is found else it returns -1.
|
||||
******************************************************************************/
|
||||
int get_bl_params_node_index(unsigned int image_id)
|
||||
{
|
||||
int index;
|
||||
assert(image_id != INVALID_IMAGE_ID);
|
||||
|
||||
for (index = 0; index < bl_mem_params_desc_num; index++) {
|
||||
if (bl_mem_params_desc_ptr[index].image_id == image_id)
|
||||
return index;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the pointer to `bl_mem_params_node_t` object for
|
||||
* given image_id, within the image descriptor array provided by
|
||||
* bl_mem_params_desc_ptr, if the image is found else it returns NULL.
|
||||
******************************************************************************/
|
||||
bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id)
|
||||
{
|
||||
int index;
|
||||
assert(image_id != INVALID_IMAGE_ID);
|
||||
|
||||
index = get_bl_params_node_index(image_id);
|
||||
if (index >= 0)
|
||||
return &bl_mem_params_desc_ptr[index];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function creates the list of loadable images, by populating and
|
||||
* linking each `bl_load_info_node_t` type node, using the internal array
|
||||
* of image descriptor provided by bl_mem_params_desc_ptr. It also populates
|
||||
* and returns `bl_load_info_t` type structure that contains head of the list
|
||||
* of loadable images.
|
||||
******************************************************************************/
|
||||
bl_load_info_t *get_bl_load_info_from_mem_params_desc(void)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
/* If there is no image to start with, return NULL */
|
||||
if (!bl_mem_params_desc_num)
|
||||
return NULL;
|
||||
|
||||
/* Assign initial data structures */
|
||||
bl_load_info_node_t *bl_node_info =
|
||||
&bl_mem_params_desc_ptr[index].load_node_mem;
|
||||
bl_load_info.head = bl_node_info;
|
||||
SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0);
|
||||
|
||||
/* Go through the image descriptor array and create the list */
|
||||
for (; index < bl_mem_params_desc_num; index++) {
|
||||
|
||||
/* Populate the image information */
|
||||
bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id;
|
||||
bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info;
|
||||
|
||||
/* Link next image if present */
|
||||
if ((index + 1) < bl_mem_params_desc_num) {
|
||||
/* Get the memory and link the next node */
|
||||
bl_node_info->next_load_info =
|
||||
&bl_mem_params_desc_ptr[index + 1].load_node_mem;
|
||||
bl_node_info = bl_node_info->next_load_info;
|
||||
}
|
||||
}
|
||||
|
||||
return &bl_load_info;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function creates the list of executable images, by populating and
|
||||
* linking each `bl_params_node_t` type node, using the internal array of
|
||||
* image descriptor provided by bl_mem_params_desc_ptr. It also populates
|
||||
* and returns `bl_params_t` type structure that contains head of the list
|
||||
* of executable images.
|
||||
******************************************************************************/
|
||||
bl_params_t *get_next_bl_params_from_mem_params_desc(void)
|
||||
{
|
||||
int count;
|
||||
unsigned int img_id = 0;
|
||||
int link_index = 0;
|
||||
bl_params_node_t *bl_current_exec_node = NULL;
|
||||
bl_params_node_t *bl_last_exec_node = NULL;
|
||||
bl_mem_params_node_t *desc_ptr;
|
||||
|
||||
/* If there is no image to start with, return NULL */
|
||||
if (!bl_mem_params_desc_num)
|
||||
return NULL;
|
||||
|
||||
/* Get the list HEAD */
|
||||
for (count = 0; count < bl_mem_params_desc_num; count++) {
|
||||
|
||||
desc_ptr = &bl_mem_params_desc_ptr[count];
|
||||
|
||||
if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) &&
|
||||
(EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) {
|
||||
next_bl_params.head = &desc_ptr->params_node_mem;
|
||||
link_index = count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure we have a HEAD node */
|
||||
assert(next_bl_params.head != NULL);
|
||||
|
||||
/* Populate the HEAD information */
|
||||
SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0);
|
||||
|
||||
/*
|
||||
* Go through the image descriptor array and create the list.
|
||||
* This bounded loop is to make sure that we are not looping forever.
|
||||
*/
|
||||
for (count = 0 ; count < bl_mem_params_desc_num; count++) {
|
||||
|
||||
desc_ptr = &bl_mem_params_desc_ptr[link_index];
|
||||
|
||||
/* Make sure the image is executable */
|
||||
assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE);
|
||||
|
||||
/* Get the memory for current node */
|
||||
bl_current_exec_node = &desc_ptr->params_node_mem;
|
||||
|
||||
/* Populate the image information */
|
||||
bl_current_exec_node->image_id = desc_ptr->image_id;
|
||||
bl_current_exec_node->image_info = &desc_ptr->image_info;
|
||||
bl_current_exec_node->ep_info = &desc_ptr->ep_info;
|
||||
|
||||
if (bl_last_exec_node) {
|
||||
/* Assert if loop detected */
|
||||
assert(bl_last_exec_node->next_params_info == NULL);
|
||||
|
||||
/* Link the previous node to the current one */
|
||||
bl_last_exec_node->next_params_info = bl_current_exec_node;
|
||||
}
|
||||
|
||||
/* Update the last node */
|
||||
bl_last_exec_node = bl_current_exec_node;
|
||||
|
||||
/* If no next hand-off image then break out */
|
||||
img_id = desc_ptr->next_handoff_image_id;
|
||||
if (img_id == INVALID_IMAGE_ID)
|
||||
break;
|
||||
|
||||
/* Get the index for the next hand-off image */
|
||||
link_index = get_bl_params_node_index(img_id);
|
||||
assert((link_index > 0) &&
|
||||
(link_index < bl_mem_params_desc_num));
|
||||
}
|
||||
|
||||
/* Invalid image is expected to terminate the loop */
|
||||
assert(img_id == INVALID_IMAGE_ID);
|
||||
|
||||
return &next_bl_params;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function populates the entry point information with the corresponding
|
||||
* config file for all executable BL images described in bl_params.
|
||||
******************************************************************************/
|
||||
void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params)
|
||||
{
|
||||
bl_params_node_t *params_node;
|
||||
unsigned int fw_config_id;
|
||||
uintptr_t hw_config_base = 0, fw_config_base;
|
||||
bl_mem_params_node_t *mem_params;
|
||||
|
||||
assert(bl2_to_next_bl_params != NULL);
|
||||
|
||||
/*
|
||||
* Get the `bl_mem_params_node_t` corresponding to HW_CONFIG
|
||||
* if available.
|
||||
*/
|
||||
mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
|
||||
if (mem_params != NULL)
|
||||
hw_config_base = mem_params->image_info.image_base;
|
||||
|
||||
for (params_node = bl2_to_next_bl_params->head; params_node != NULL;
|
||||
params_node = params_node->next_params_info) {
|
||||
|
||||
fw_config_base = 0;
|
||||
|
||||
switch (params_node->image_id) {
|
||||
case BL31_IMAGE_ID:
|
||||
fw_config_id = SOC_FW_CONFIG_ID;
|
||||
break;
|
||||
case BL32_IMAGE_ID:
|
||||
fw_config_id = TOS_FW_CONFIG_ID;
|
||||
break;
|
||||
case BL33_IMAGE_ID:
|
||||
fw_config_id = NT_FW_CONFIG_ID;
|
||||
break;
|
||||
default:
|
||||
fw_config_id = INVALID_IMAGE_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fw_config_id != INVALID_IMAGE_ID) {
|
||||
mem_params = get_bl_mem_params_node(fw_config_id);
|
||||
if (mem_params != NULL)
|
||||
fw_config_base = mem_params->image_info.image_base;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass hw and tb_fw config addresses to next images. NOTE - for
|
||||
* EL3 runtime images (BL31 for AArch64 and BL32 for AArch32),
|
||||
* arg0 is already used by generic code. Take care of not
|
||||
* overwriting the previous initialisations.
|
||||
*/
|
||||
if (params_node == bl2_to_next_bl_params->head) {
|
||||
if (params_node->ep_info->args.arg1 == 0)
|
||||
params_node->ep_info->args.arg1 =
|
||||
fw_config_base;
|
||||
if (params_node->ep_info->args.arg2 == 0)
|
||||
params_node->ep_info->args.arg2 =
|
||||
hw_config_base;
|
||||
} else {
|
||||
if (params_node->ep_info->args.arg0 == 0)
|
||||
params_node->ep_info->args.arg0 =
|
||||
fw_config_base;
|
||||
if (params_node->ep_info->args.arg1 == 0)
|
||||
params_node->ep_info->args.arg1 =
|
||||
hw_config_base;
|
||||
}
|
||||
}
|
||||
}
|
||||
96
firmware/coreboot/3rdparty/arm-trusted-firmware/common/fdt_wrappers.c
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/* Helper functions to offer easier navigation of Device Tree Blob */
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <fdt_wrappers.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
/*
|
||||
* Read cells from a given property of the given node. At most 2 cells of the
|
||||
* property are read, and pointer is updated. Returns 0 on success, and -1 upon
|
||||
* error
|
||||
*/
|
||||
int fdtw_read_cells(const void *dtb, int node, const char *prop,
|
||||
unsigned int cells, void *value)
|
||||
{
|
||||
const uint32_t *value_ptr;
|
||||
uint32_t hi = 0, lo;
|
||||
int value_len;
|
||||
|
||||
assert(dtb != NULL);
|
||||
assert(prop != NULL);
|
||||
assert(value != NULL);
|
||||
assert(node >= 0);
|
||||
|
||||
/* We expect either 1 or 2 cell property */
|
||||
assert(cells <= 2U);
|
||||
|
||||
/* Access property and obtain its length (in bytes) */
|
||||
value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
|
||||
&value_len);
|
||||
if (value_ptr == NULL) {
|
||||
WARN("Couldn't find property %s in dtb\n", prop);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Verify that property length accords with cell length */
|
||||
if (NCELLS((unsigned int)value_len) != cells) {
|
||||
WARN("Property length mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cells == 2U) {
|
||||
hi = fdt32_to_cpu(*value_ptr);
|
||||
value_ptr++;
|
||||
}
|
||||
|
||||
lo = fdt32_to_cpu(*value_ptr);
|
||||
|
||||
if (cells == 2U)
|
||||
*((uint64_t *) value) = ((uint64_t) hi << 32) | lo;
|
||||
else
|
||||
*((uint32_t *) value) = lo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write cells in place to a given property of the given node. At most 2 cells
|
||||
* of the property are written. Returns 0 on success, and -1 upon error.
|
||||
*/
|
||||
int fdtw_write_inplace_cells(void *dtb, int node, const char *prop,
|
||||
unsigned int cells, void *value)
|
||||
{
|
||||
int err, len;
|
||||
|
||||
assert(dtb != NULL);
|
||||
assert(prop != NULL);
|
||||
assert(value != NULL);
|
||||
assert(node >= 0);
|
||||
|
||||
/* We expect either 1 or 2 cell property */
|
||||
assert(cells <= 2U);
|
||||
|
||||
if (cells == 2U)
|
||||
*(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value);
|
||||
else
|
||||
*(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value);
|
||||
|
||||
len = (int)cells * 4;
|
||||
|
||||
/* Set property value in place */
|
||||
err = fdt_setprop_inplace(dtb, node, prop, value, len);
|
||||
if (err != 0) {
|
||||
WARN("Modify property %s failed with error %d\n", prop, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
79
firmware/coreboot/3rdparty/arm-trusted-firmware/common/image_decompress.c
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <image_decompress.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static uintptr_t decompressor_buf_base;
|
||||
static uint32_t decompressor_buf_size;
|
||||
static decompressor_t *decompressor;
|
||||
static struct image_info saved_image_info;
|
||||
|
||||
void image_decompress_init(uintptr_t buf_base, uint32_t buf_size,
|
||||
decompressor_t *_decompressor)
|
||||
{
|
||||
decompressor_buf_base = buf_base;
|
||||
decompressor_buf_size = buf_size;
|
||||
decompressor = _decompressor;
|
||||
}
|
||||
|
||||
void image_decompress_prepare(struct image_info *info)
|
||||
{
|
||||
/*
|
||||
* If the image is compressed, it should be loaded into the temporary
|
||||
* buffer instead of its final destination. We save image_info, then
|
||||
* override ->image_base and ->image_max_size so that load_image() will
|
||||
* transfer the compressed data to the temporary buffer.
|
||||
*/
|
||||
saved_image_info = *info;
|
||||
info->image_base = decompressor_buf_base;
|
||||
info->image_max_size = decompressor_buf_size;
|
||||
}
|
||||
|
||||
int image_decompress(struct image_info *info)
|
||||
{
|
||||
uintptr_t compressed_image_base, image_base, work_base;
|
||||
uint32_t compressed_image_size, work_size;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The size of compressed data has been filled by load_image().
|
||||
* Read it out before restoring image_info.
|
||||
*/
|
||||
compressed_image_size = info->image_size;
|
||||
compressed_image_base = info->image_base;
|
||||
*info = saved_image_info;
|
||||
|
||||
assert(compressed_image_size <= decompressor_buf_size);
|
||||
|
||||
image_base = info->image_base;
|
||||
|
||||
/*
|
||||
* Use the rest of the temporary buffer as workspace of the
|
||||
* decompressor since the decompressor may need additional memory.
|
||||
*/
|
||||
work_base = compressed_image_base + compressed_image_size;
|
||||
work_size = decompressor_buf_size - compressed_image_size;
|
||||
|
||||
ret = decompressor(&compressed_image_base, compressed_image_size,
|
||||
&image_base, info->image_max_size,
|
||||
work_base, work_size);
|
||||
if (ret) {
|
||||
ERROR("Failed to decompress image (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* image_base is updated to the final pos when decompressor() exits. */
|
||||
info->image_size = image_base - info->image_base;
|
||||
|
||||
flush_dcache_range(info->image_base, info->image_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
167
firmware/coreboot/3rdparty/arm-trusted-firmware/common/runtime_svc.c
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <runtime_svc.h>
|
||||
#include <string.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* The 'rt_svc_descs' array holds the runtime service descriptors exported by
|
||||
* services by placing them in the 'rt_svc_descs' linker section.
|
||||
* The 'rt_svc_descs_indices' array holds the index of a descriptor in the
|
||||
* 'rt_svc_descs' array. When an SMC arrives, the OEN[29:24] bits and the call
|
||||
* type[31] bit in the function id are combined to get an index into the
|
||||
* 'rt_svc_descs_indices' array. This gives the index of the descriptor in the
|
||||
* 'rt_svc_descs' array which contains the SMC handler.
|
||||
******************************************************************************/
|
||||
uint8_t rt_svc_descs_indices[MAX_RT_SVCS];
|
||||
static rt_svc_desc_t *rt_svc_descs;
|
||||
|
||||
#define RT_SVC_DECS_NUM ((RT_SVC_DESCS_END - RT_SVC_DESCS_START)\
|
||||
/ sizeof(rt_svc_desc_t))
|
||||
|
||||
/*******************************************************************************
|
||||
* Function to invoke the registered `handle` corresponding to the smc_fid in
|
||||
* AArch32 mode.
|
||||
******************************************************************************/
|
||||
#if SMCCC_MAJOR_VERSION == 1
|
||||
uintptr_t handle_runtime_svc(uint32_t smc_fid,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
unsigned int flags)
|
||||
{
|
||||
u_register_t x1, x2, x3, x4;
|
||||
int index;
|
||||
unsigned int idx;
|
||||
const rt_svc_desc_t *rt_svc_descs;
|
||||
|
||||
assert(handle);
|
||||
idx = get_unique_oen_from_smc_fid(smc_fid);
|
||||
assert(idx < MAX_RT_SVCS);
|
||||
|
||||
index = rt_svc_descs_indices[idx];
|
||||
if (index < 0 || index >= (int)RT_SVC_DECS_NUM)
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
|
||||
rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
|
||||
|
||||
get_smc_params_from_ctx(handle, x1, x2, x3, x4);
|
||||
|
||||
return rt_svc_descs[index].handle(smc_fid, x1, x2, x3, x4, cookie,
|
||||
handle, flags);
|
||||
}
|
||||
#endif /* SMCCC_MAJOR_VERSION */
|
||||
|
||||
/*******************************************************************************
|
||||
* Simple routine to sanity check a runtime service descriptor before using it
|
||||
******************************************************************************/
|
||||
static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc)
|
||||
{
|
||||
if (desc == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->start_oen > desc->end_oen)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->end_oen >= OEN_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
#if SMCCC_MAJOR_VERSION == 1
|
||||
if ((desc->call_type != SMC_TYPE_FAST) &&
|
||||
(desc->call_type != SMC_TYPE_YIELD))
|
||||
return -EINVAL;
|
||||
#elif SMCCC_MAJOR_VERSION == 2
|
||||
if (desc->is_vendor > 1U)
|
||||
return -EINVAL;
|
||||
#endif /* SMCCC_MAJOR_VERSION */
|
||||
|
||||
/* A runtime service having no init or handle function doesn't make sense */
|
||||
if ((desc->init == NULL) && (desc->handle == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function calls the initialisation routine in the descriptor exported by
|
||||
* a runtime service. Once a descriptor has been validated, its start & end
|
||||
* owning entity numbers and the call type are combined to form a unique oen.
|
||||
* The unique oen is used as an index into the 'rt_svc_descs_indices' array.
|
||||
* The index of the runtime service descriptor is stored at this index.
|
||||
******************************************************************************/
|
||||
void runtime_svc_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int index, start_idx, end_idx;
|
||||
|
||||
/* Assert the number of descriptors detected are less than maximum indices */
|
||||
assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) &&
|
||||
(RT_SVC_DECS_NUM < MAX_RT_SVCS));
|
||||
|
||||
/* If no runtime services are implemented then simply bail out */
|
||||
if (RT_SVC_DECS_NUM == 0U)
|
||||
return;
|
||||
|
||||
/* Initialise internal variables to invalid state */
|
||||
memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices));
|
||||
|
||||
rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;
|
||||
for (index = 0; index < RT_SVC_DECS_NUM; index++) {
|
||||
rt_svc_desc_t *service = &rt_svc_descs[index];
|
||||
|
||||
/*
|
||||
* An invalid descriptor is an error condition since it is
|
||||
* difficult to predict the system behaviour in the absence
|
||||
* of this service.
|
||||
*/
|
||||
rc = validate_rt_svc_desc(service);
|
||||
if (rc) {
|
||||
ERROR("Invalid runtime service descriptor %p\n",
|
||||
(void *) service);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* The runtime service may have separate rt_svc_desc_t
|
||||
* for its fast smc and yielding smc. Since the service itself
|
||||
* need to be initialized only once, only one of them will have
|
||||
* an initialisation routine defined. Call the initialisation
|
||||
* routine for this runtime service, if it is defined.
|
||||
*/
|
||||
if (service->init) {
|
||||
rc = service->init();
|
||||
if (rc) {
|
||||
ERROR("Error initializing runtime service %s\n",
|
||||
service->name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the indices corresponding to the start and end
|
||||
* owning entity numbers with the index of the
|
||||
* descriptor which will handle the SMCs for this owning
|
||||
* entity range.
|
||||
*/
|
||||
#if SMCCC_MAJOR_VERSION == 1
|
||||
start_idx = get_unique_oen(service->start_oen,
|
||||
service->call_type);
|
||||
end_idx = get_unique_oen(service->end_oen,
|
||||
service->call_type);
|
||||
#elif SMCCC_MAJOR_VERSION == 2
|
||||
start_idx = get_rt_desc_idx(service->start_oen,
|
||||
service->is_vendor);
|
||||
end_idx = get_rt_desc_idx(service->end_oen,
|
||||
service->is_vendor);
|
||||
#endif
|
||||
assert(start_idx <= end_idx);
|
||||
assert(end_idx < MAX_RT_SVCS);
|
||||
for (; start_idx <= end_idx; start_idx++)
|
||||
rt_svc_descs_indices[start_idx] = index;
|
||||
}
|
||||
}
|
||||
61
firmware/coreboot/3rdparty/arm-trusted-firmware/common/tf_log.c
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
|
||||
/* Set the default maximum log level to the `LOG_LEVEL` build flag */
|
||||
static unsigned int max_log_level = LOG_LEVEL;
|
||||
|
||||
/*
|
||||
* The common log function which is invoked by ARM Trusted Firmware code.
|
||||
* This function should not be directly invoked and is meant to be
|
||||
* only used by the log macros defined in debug.h. The function
|
||||
* expects the first character in the format string to be one of the
|
||||
* LOG_MARKER_* macros defined in debug.h.
|
||||
*/
|
||||
void tf_log(const char *fmt, ...)
|
||||
{
|
||||
unsigned int log_level;
|
||||
va_list args;
|
||||
const char *prefix_str;
|
||||
|
||||
/* We expect the LOG_MARKER_* macro as the first character */
|
||||
log_level = fmt[0];
|
||||
|
||||
/* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */
|
||||
assert(log_level && log_level <= LOG_LEVEL_VERBOSE);
|
||||
assert(log_level % 10 == 0);
|
||||
|
||||
if (log_level > max_log_level)
|
||||
return;
|
||||
|
||||
prefix_str = plat_log_get_prefix(log_level);
|
||||
|
||||
if (prefix_str != NULL)
|
||||
tf_string_print(prefix_str);
|
||||
|
||||
va_start(args, fmt);
|
||||
tf_vprintf(fmt+1, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/*
|
||||
* The helper function to set the log level dynamically by platform. The
|
||||
* maximum log level is determined by `LOG_LEVEL` build flag at compile time
|
||||
* and this helper can set a lower log level than the one at compile.
|
||||
*/
|
||||
void tf_log_set_max_level(unsigned int log_level)
|
||||
{
|
||||
assert(log_level <= LOG_LEVEL_VERBOSE);
|
||||
assert((log_level % 10) == 0);
|
||||
|
||||
/* Cap log_level to the compile time maximum. */
|
||||
if (log_level < LOG_LEVEL)
|
||||
max_log_level = log_level;
|
||||
|
||||
}
|
||||
171
firmware/coreboot/3rdparty/arm-trusted-firmware/common/tf_printf.c
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/***********************************************************
|
||||
* The tf_printf implementation for all BL stages
|
||||
***********************************************************/
|
||||
|
||||
#define get_num_va_args(_args, _lcount) \
|
||||
(((_lcount) > 1) ? va_arg(_args, long long int) : \
|
||||
((_lcount) ? va_arg(_args, long int) : va_arg(_args, int)))
|
||||
|
||||
#define get_unum_va_args(_args, _lcount) \
|
||||
(((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \
|
||||
((_lcount) ? va_arg(_args, unsigned long int) : va_arg(_args, unsigned int)))
|
||||
|
||||
void tf_string_print(const char *str)
|
||||
{
|
||||
assert(str);
|
||||
|
||||
while (*str)
|
||||
putchar(*str++);
|
||||
}
|
||||
|
||||
static void unsigned_num_print(unsigned long long int unum, unsigned int radix,
|
||||
char padc, int padn)
|
||||
{
|
||||
/* Just need enough space to store 64 bit decimal integer */
|
||||
unsigned char num_buf[20];
|
||||
int i = 0, rem;
|
||||
|
||||
do {
|
||||
rem = unum % radix;
|
||||
if (rem < 0xa)
|
||||
num_buf[i++] = '0' + rem;
|
||||
else
|
||||
num_buf[i++] = 'a' + (rem - 0xa);
|
||||
} while (unum /= radix);
|
||||
|
||||
if (padn > 0) {
|
||||
while (i < padn--) {
|
||||
putchar(padc);
|
||||
}
|
||||
}
|
||||
|
||||
while (--i >= 0)
|
||||
putchar(num_buf[i]);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* Reduced format print for Trusted firmware.
|
||||
* The following type specifiers are supported by this print
|
||||
* %x - hexadecimal format
|
||||
* %s - string format
|
||||
* %d or %i - signed decimal format
|
||||
* %u - unsigned decimal format
|
||||
* %p - pointer format
|
||||
*
|
||||
* The following length specifiers are supported by this print
|
||||
* %l - long int (64-bit on AArch64)
|
||||
* %ll - long long int (64-bit on AArch64)
|
||||
* %z - size_t sized integer formats (64 bit on AArch64)
|
||||
*
|
||||
* The following padding specifiers are supported by this print
|
||||
* %0NN - Left-pad the number with 0s (NN is a decimal number)
|
||||
*
|
||||
* The print exits on all other formats specifiers other than valid
|
||||
* combinations of the above specifiers.
|
||||
*******************************************************************/
|
||||
void tf_vprintf(const char *fmt, va_list args)
|
||||
{
|
||||
int l_count;
|
||||
long long int num;
|
||||
unsigned long long int unum;
|
||||
char *str;
|
||||
char padc = 0; /* Padding character */
|
||||
int padn; /* Number of characters to pad */
|
||||
|
||||
while (*fmt) {
|
||||
l_count = 0;
|
||||
padn = 0;
|
||||
|
||||
if (*fmt == '%') {
|
||||
fmt++;
|
||||
/* Check the format specifier */
|
||||
loop:
|
||||
switch (*fmt) {
|
||||
case 'i': /* Fall through to next one */
|
||||
case 'd':
|
||||
num = get_num_va_args(args, l_count);
|
||||
if (num < 0) {
|
||||
putchar('-');
|
||||
unum = (unsigned long long int)-num;
|
||||
padn--;
|
||||
} else
|
||||
unum = (unsigned long long int)num;
|
||||
|
||||
unsigned_num_print(unum, 10, padc, padn);
|
||||
break;
|
||||
case 's':
|
||||
str = va_arg(args, char *);
|
||||
tf_string_print(str);
|
||||
break;
|
||||
case 'p':
|
||||
unum = (uintptr_t)va_arg(args, void *);
|
||||
if (unum) {
|
||||
tf_string_print("0x");
|
||||
padn -= 2;
|
||||
}
|
||||
|
||||
unsigned_num_print(unum, 16, padc, padn);
|
||||
break;
|
||||
case 'x':
|
||||
unum = get_unum_va_args(args, l_count);
|
||||
unsigned_num_print(unum, 16, padc, padn);
|
||||
break;
|
||||
case 'z':
|
||||
if (sizeof(size_t) == 8)
|
||||
l_count = 2;
|
||||
|
||||
fmt++;
|
||||
goto loop;
|
||||
case 'l':
|
||||
l_count++;
|
||||
fmt++;
|
||||
goto loop;
|
||||
case 'u':
|
||||
unum = get_unum_va_args(args, l_count);
|
||||
unsigned_num_print(unum, 10, padc, padn);
|
||||
break;
|
||||
case '0':
|
||||
padc = '0';
|
||||
padn = 0;
|
||||
fmt++;
|
||||
|
||||
while (1) {
|
||||
char ch = *fmt;
|
||||
if (ch < '0' || ch > '9') {
|
||||
goto loop;
|
||||
}
|
||||
padn = (padn * 10) + (ch - '0');
|
||||
fmt++;
|
||||
}
|
||||
default:
|
||||
/* Exit on any other format specifier */
|
||||
return;
|
||||
}
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
putchar(*fmt++);
|
||||
}
|
||||
}
|
||||
|
||||
void tf_printf(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
tf_vprintf(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
108
firmware/coreboot/3rdparty/arm-trusted-firmware/common/tf_snprintf.c
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static void unsigned_dec_print(char **s, size_t n, size_t *chars_printed,
|
||||
unsigned int unum)
|
||||
{
|
||||
/* Enough for a 32-bit unsigned decimal integer (4294967295). */
|
||||
unsigned char num_buf[10];
|
||||
int i = 0, rem;
|
||||
|
||||
do {
|
||||
rem = unum % 10;
|
||||
num_buf[i++] = '0' + rem;
|
||||
} while (unum /= 10);
|
||||
|
||||
while (--i >= 0) {
|
||||
if (*chars_printed < n)
|
||||
*(*s)++ = num_buf[i];
|
||||
(*chars_printed)++;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* Reduced snprintf to be used for Trusted firmware.
|
||||
* The following type specifiers are supported:
|
||||
*
|
||||
* %d or %i - signed decimal format
|
||||
* %u - unsigned decimal format
|
||||
*
|
||||
* The function panics on all other formats specifiers.
|
||||
*
|
||||
* It returns the number of characters that would be written if the
|
||||
* buffer was big enough. If it returns a value lower than n, the
|
||||
* whole string has been written.
|
||||
*******************************************************************/
|
||||
int tf_snprintf(char *s, size_t n, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int num;
|
||||
unsigned int unum;
|
||||
size_t chars_printed = 0;
|
||||
|
||||
if (n == 1) {
|
||||
/* Buffer is too small to actually write anything else. */
|
||||
*s = '\0';
|
||||
n = 0;
|
||||
} else if (n >= 2) {
|
||||
/* Reserve space for the terminator character. */
|
||||
n--;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
while (*fmt) {
|
||||
|
||||
if (*fmt == '%') {
|
||||
fmt++;
|
||||
/* Check the format specifier. */
|
||||
switch (*fmt) {
|
||||
case 'i':
|
||||
case 'd':
|
||||
num = va_arg(args, int);
|
||||
|
||||
if (num < 0) {
|
||||
if (chars_printed < n)
|
||||
*s++ = '-';
|
||||
chars_printed++;
|
||||
|
||||
unum = (unsigned int)-num;
|
||||
} else {
|
||||
unum = (unsigned int)num;
|
||||
}
|
||||
|
||||
unsigned_dec_print(&s, n, &chars_printed, unum);
|
||||
break;
|
||||
case 'u':
|
||||
unum = va_arg(args, unsigned int);
|
||||
unsigned_dec_print(&s, n, &chars_printed, unum);
|
||||
break;
|
||||
default:
|
||||
/* Panic on any other format specifier. */
|
||||
ERROR("tf_snprintf: specifier with ASCII code '%d' not supported.",
|
||||
*fmt);
|
||||
plat_panic_handler();
|
||||
}
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chars_printed < n)
|
||||
*s++ = *fmt;
|
||||
fmt++;
|
||||
chars_printed++;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
if (n > 0)
|
||||
*s = '\0';
|
||||
|
||||
return chars_printed;
|
||||
}
|
||||
129
firmware/coreboot/3rdparty/arm-trusted-firmware/contributing.rst
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
Contributing to Trusted Firmware-A
|
||||
==================================
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
- Make sure you have a `GitHub account`_.
|
||||
- Create an `issue`_ for your work if one does not already exist. This gives
|
||||
everyone visibility of whether others are working on something similar. Arm
|
||||
licensees may contact Arm directly via their partner managers instead if
|
||||
they prefer.
|
||||
|
||||
- Note that the `issue`_ tracker for this project is in a separate
|
||||
`issue tracking repository`_. Please follow the guidelines in that
|
||||
repository.
|
||||
- If you intend to include Third Party IP in your contribution, please
|
||||
raise a separate `issue`_ for this and ensure that the changes that
|
||||
include Third Party IP are made on a separate topic branch.
|
||||
|
||||
- `Fork`_ `arm-trusted-firmware`_ on GitHub.
|
||||
- Clone the fork to your own machine.
|
||||
- Create a local topic branch based on the `arm-trusted-firmware`_ ``master``
|
||||
branch.
|
||||
|
||||
Making Changes
|
||||
--------------
|
||||
|
||||
- Make commits of logical units. See these general `Git guidelines`_ for
|
||||
contributing to a project.
|
||||
- Follow the `Linux coding style`_; this style is enforced for the TF-A
|
||||
project (style errors only, not warnings).
|
||||
|
||||
- Use the checkpatch.pl script provided with the Linux source tree. A
|
||||
Makefile target is provided for convenience (see section 2 in the
|
||||
`User Guide`_).
|
||||
|
||||
- Keep the commits on topic. If you need to fix another bug or make another
|
||||
enhancement, please create a separate `issue`_ and address it on a separate
|
||||
topic branch.
|
||||
- Avoid long commit series. If you do have a long series, consider whether
|
||||
some commits should be squashed together or addressed in a separate topic.
|
||||
- Make sure your commit messages are in the proper format. If a commit fixes
|
||||
a GitHub `issue`_, include a reference (e.g.
|
||||
"fixes arm-software/tf-issues#45"); this ensures the `issue`_ is
|
||||
`automatically closed`_ when merged into the `arm-trusted-firmware`_ ``master``
|
||||
branch.
|
||||
- Where appropriate, please update the documentation.
|
||||
|
||||
- Consider whether the `User Guide`_, `Porting Guide`_, `Firmware Design`_ or
|
||||
other in-source documentation needs updating.
|
||||
- Ensure that each changed file has the correct copyright and license
|
||||
information. Files that entirely consist of contributions to this
|
||||
project should have the copyright notice and BSD-3-Clause SPDX license
|
||||
identifier as shown in `license.rst`_. Files that contain
|
||||
changes to imported Third Party IP should contain a notice as follows,
|
||||
with the original copyright and license text retained:
|
||||
|
||||
::
|
||||
|
||||
Portions copyright (c) [XXXX-]YYYY, Arm Limited and Contributors. All rights reserved.
|
||||
|
||||
where XXXX is the year of first contribution (if different to YYYY) and
|
||||
YYYY is the year of most recent contribution.
|
||||
- If not done previously, you may add your name or your company name to
|
||||
the `Acknowledgements`_ file.
|
||||
- If you are submitting new files that you intend to be the technical
|
||||
sub-maintainer for (for example, a new platform port), then also update
|
||||
the `Maintainers`_ file.
|
||||
- For topics with multiple commits, you should make all documentation
|
||||
changes (and nothing else) in the last commit of the series. Otherwise,
|
||||
include the documentation changes within the single commit.
|
||||
|
||||
- Please test your changes. As a minimum, ensure UEFI boots to the shell on
|
||||
the Foundation FVP. See `Running the software on FVP`_ for more information.
|
||||
|
||||
Submitting Changes
|
||||
------------------
|
||||
|
||||
- Ensure that each commit in the series has at least one ``Signed-off-by:``
|
||||
line, using your real name and email address. The names in the
|
||||
``Signed-off-by:`` and ``Author:`` lines must match. If anyone else contributes
|
||||
to the commit, they must also add their own ``Signed-off-by:`` line.
|
||||
By adding this line the contributor certifies the contribution is made under
|
||||
the terms of the `Developer Certificate of Origin (DCO)`_.
|
||||
- Push your local changes to your fork of the repository.
|
||||
- Submit a `pull request`_ to the `arm-trusted-firmware`_ ``integration`` branch.
|
||||
|
||||
- The changes in the `pull request`_ will then undergo further review and
|
||||
testing by the `Maintainers`_. Any review comments will be made as
|
||||
comments on the `pull request`_. This may require you to do some rework.
|
||||
|
||||
- When the changes are accepted, the `Maintainers`_ will integrate them.
|
||||
|
||||
- Typically, the `Maintainers`_ will merge the `pull request`_ into the
|
||||
``integration`` branch within the GitHub UI, creating a merge commit.
|
||||
- Please avoid creating merge commits in the `pull request`_ itself.
|
||||
- If the `pull request`_ is not based on a recent commit, the `Maintainers`_
|
||||
may rebase it onto the ``master`` branch first, or ask you to do this.
|
||||
- If the `pull request`_ cannot be automatically merged, the `Maintainers`_
|
||||
will ask you to rebase it onto the ``master`` branch.
|
||||
- After final integration testing, the `Maintainers`_ will push your merge
|
||||
commit to the ``master`` branch. If a problem is found during integration,
|
||||
the merge commit will be removed from the ``integration`` branch and the
|
||||
`Maintainers`_ will ask you to create a new pull request to resolve the
|
||||
problem.
|
||||
- Please do not delete your topic branch until it is safely merged into
|
||||
the ``master`` branch.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _GitHub account: https://github.com/signup/free
|
||||
.. _issue: https://github.com/ARM-software/tf-issues/issues
|
||||
.. _issue tracking repository: https://github.com/ARM-software/tf-issues
|
||||
.. _Fork: https://help.github.com/articles/fork-a-repo
|
||||
.. _arm-trusted-firmware: https://github.com/ARM-software/arm-trusted-firmware
|
||||
.. _Git guidelines: http://git-scm.com/book/ch5-2.html
|
||||
.. _Linux coding style: https://www.kernel.org/doc/Documentation/CodingStyle
|
||||
.. _User Guide: ./docs/user-guide.rst
|
||||
.. _automatically closed: https://help.github.com/articles/closing-issues-via-commit-messages
|
||||
.. _Porting Guide: ./docs/porting-guide.rst
|
||||
.. _Firmware Design: ./docs/firmware-design.rst
|
||||
.. _license.rst: ./license.rst
|
||||
.. _Acknowledgements: ./acknowledgements.rst
|
||||
.. _Maintainers: ./maintainers.rst
|
||||
.. _Running the software on FVP: ./docs/user-guide.rst#user-content-running-the-software-on-fvp
|
||||
.. _Developer Certificate of Origin (DCO): ./dco.txt
|
||||
.. _pull request: https://help.github.com/articles/using-pull-requests
|
||||
37
firmware/coreboot/3rdparty/arm-trusted-firmware/dco.txt
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
1 Letterman Drive
|
||||
Suite D4700
|
||||
San Francisco, CA, 94129
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
96
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/arm-sip-service.rst
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
Arm SiP Service
|
||||
===============
|
||||
|
||||
This document enumerates and describes the Arm SiP (Silicon Provider) services.
|
||||
|
||||
SiP services are non-standard, platform-specific services offered by the silicon
|
||||
implementer or platform provider. They are accessed via. ``SMC`` ("SMC calls")
|
||||
instruction executed from Exception Levels below EL3. SMC calls for SiP
|
||||
services:
|
||||
|
||||
- Follow `SMC Calling Convention`_;
|
||||
- Use SMC function IDs that fall in the SiP range, which are ``0xc2000000`` -
|
||||
``0xc200ffff`` for 64-bit calls, and ``0x82000000`` - ``0x8200ffff`` for 32-bit
|
||||
calls.
|
||||
|
||||
The Arm SiP implementation offers the following services:
|
||||
|
||||
- Performance Measurement Framework (PMF)
|
||||
- Execution State Switching service
|
||||
|
||||
Source definitions for Arm SiP service are located in the ``arm_sip_svc.h`` header
|
||||
file.
|
||||
|
||||
Performance Measurement Framework (PMF)
|
||||
---------------------------------------
|
||||
|
||||
The `Performance Measurement Framework`_
|
||||
allows callers to retrieve timestamps captured at various paths in TF-A
|
||||
execution. It's described in detail in `Firmware Design document`_.
|
||||
|
||||
Execution State Switching service
|
||||
---------------------------------
|
||||
|
||||
Execution State Switching service provides a mechanism for a non-secure lower
|
||||
Exception Level (either EL2, or NS EL1 if EL2 isn't implemented) to request to
|
||||
switch its execution state (a.k.a. Register Width), either from AArch64 to
|
||||
AArch32, or from AArch32 to AArch64, for the calling CPU. This service is only
|
||||
available when Trusted Firmware-A (TF-A) is built for AArch64 (i.e. when build
|
||||
option ``ARCH`` is set to ``aarch64``).
|
||||
|
||||
``ARM_SIP_SVC_EXE_STATE_SWITCH``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
Arguments:
|
||||
uint32_t Function ID
|
||||
uint32_t PC hi
|
||||
uint32_t PC lo
|
||||
uint32_t Cookie hi
|
||||
uint32_t Cookie lo
|
||||
|
||||
Return:
|
||||
uint32_t
|
||||
|
||||
The function ID parameter must be ``0x82000020``. It uniquely identifies the
|
||||
Execution State Switching service being requested.
|
||||
|
||||
The parameters *PC hi* and *PC lo* defines upper and lower words, respectively,
|
||||
of the entry point (physical address) at which execution should start, after
|
||||
Execution State has been switched. When calling from AArch64, *PC hi* must be 0.
|
||||
|
||||
When execution starts at the supplied entry point after Execution State has been
|
||||
switched, the parameters *Cookie hi* and *Cookie lo* are passed in CPU registers
|
||||
0 and 1, respectively. When calling from AArch64, *Cookie hi* must be 0.
|
||||
|
||||
This call can only be made on the primary CPU, before any secondaries were
|
||||
brought up with ``CPU_ON`` PSCI call. Otherwise, the call will always fail.
|
||||
|
||||
The effect of switching execution state is as if the Exception Level were
|
||||
entered for the first time, following power on. This means CPU registers that
|
||||
have a defined reset value by the Architecture will assume that value. Other
|
||||
registers should not be expected to hold their values before the call was made.
|
||||
CPU endianness, however, is preserved from the previous execution state. Note
|
||||
that this switches the execution state of the calling CPU only. This is not a
|
||||
substitute for PSCI ``SYSTEM_RESET``.
|
||||
|
||||
The service may return the following error codes:
|
||||
|
||||
- ``STATE_SW_E_PARAM``: If any of the parameters were deemed invalid for
|
||||
a specific request.
|
||||
- ``STATE_SW_E_DENIED``: If the call is not successful, or when TF-A is
|
||||
built for AArch32.
|
||||
|
||||
If the call is successful, the caller wouldn't observe the SMC returning.
|
||||
Instead, execution starts at the supplied entry point, with the CPU registers 0
|
||||
and 1 populated with the supplied *Cookie hi* and *Cookie lo* values,
|
||||
respectively.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
|
||||
.. _Performance Measurement Framework: ./firmware-design.rst#user-content-performance-measurement-framework
|
||||
.. _Firmware Design document: ./firmware-design.rst
|
||||
941
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/auth-framework.rst
vendored
Normal file
@@ -0,0 +1,941 @@
|
||||
Abstracting a Chain of Trust
|
||||
============================
|
||||
|
||||
|
||||
.. section-numbering::
|
||||
:suffix: .
|
||||
|
||||
.. contents::
|
||||
|
||||
The aim of this document is to describe the authentication framework
|
||||
implemented in Trusted Firmware-A (TF-A). This framework fulfills the
|
||||
following requirements:
|
||||
|
||||
#. It should be possible for a platform port to specify the Chain of Trust in
|
||||
terms of certificate hierarchy and the mechanisms used to verify a
|
||||
particular image/certificate.
|
||||
|
||||
#. The framework should distinguish between:
|
||||
|
||||
- The mechanism used to encode and transport information, e.g. DER encoded
|
||||
X.509v3 certificates to ferry Subject Public Keys, hashes and non-volatile
|
||||
counters.
|
||||
|
||||
- The mechanism used to verify the transported information i.e. the
|
||||
cryptographic libraries.
|
||||
|
||||
The framework has been designed following a modular approach illustrated in the
|
||||
next diagram:
|
||||
|
||||
::
|
||||
|
||||
+---------------+---------------+------------+
|
||||
| Trusted | Trusted | Trusted |
|
||||
| Firmware | Firmware | Firmware |
|
||||
| Generic | IO Framework | Platform |
|
||||
| Code i.e. | (IO) | Port |
|
||||
| BL1/BL2 (GEN) | | (PP) |
|
||||
+---------------+---------------+------------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
v v v
|
||||
+-----------+ +-----------+ +-----------+
|
||||
| | | | | Image |
|
||||
| Crypto | | Auth | | Parser |
|
||||
| Module |<->| Module |<->| Module |
|
||||
| (CM) | | (AM) | | (IPM) |
|
||||
| | | | | |
|
||||
+-----------+ +-----------+ +-----------+
|
||||
^ ^
|
||||
| |
|
||||
v v
|
||||
+----------------+ +-----------------+
|
||||
| Cryptographic | | Image Parser |
|
||||
| Libraries (CL) | | Libraries (IPL) |
|
||||
+----------------+ +-----------------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
v v
|
||||
+-----------------+
|
||||
| Misc. Libs e.g. |
|
||||
| ASN.1 decoder |
|
||||
| |
|
||||
+-----------------+
|
||||
|
||||
DIAGRAM 1.
|
||||
|
||||
This document describes the inner details of the authentication framework and
|
||||
the abstraction mechanisms available to specify a Chain of Trust.
|
||||
|
||||
Framework design
|
||||
----------------
|
||||
|
||||
This section describes some aspects of the framework design and the rationale
|
||||
behind them. These aspects are key to verify a Chain of Trust.
|
||||
|
||||
Chain of Trust
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
A CoT is basically a sequence of authentication images which usually starts with
|
||||
a root of trust and culminates in a single data image. The following diagram
|
||||
illustrates how this maps to a CoT for the BL31 image described in the
|
||||
TBBR-Client specification.
|
||||
|
||||
::
|
||||
|
||||
+------------------+ +-------------------+
|
||||
| ROTPK/ROTPK Hash |------>| Trusted Key |
|
||||
+------------------+ | Certificate |
|
||||
| (Auth Image) |
|
||||
/+-------------------+
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
L v
|
||||
+------------------+ +-------------------+
|
||||
| Trusted World |------>| BL31 Key |
|
||||
| Public Key | | Certificate |
|
||||
+------------------+ | (Auth Image) |
|
||||
+-------------------+
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ v
|
||||
+------------------+ L +-------------------+
|
||||
| BL31 Content |------>| BL31 Content |
|
||||
| Certificate PK | | Certificate |
|
||||
+------------------+ | (Auth Image) |
|
||||
+-------------------+
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ v
|
||||
+------------------+ L +-------------------+
|
||||
| BL31 Hash |------>| BL31 Image |
|
||||
| | | (Data Image) |
|
||||
+------------------+ | |
|
||||
+-------------------+
|
||||
|
||||
DIAGRAM 2.
|
||||
|
||||
The root of trust is usually a public key (ROTPK) that has been burnt in the
|
||||
platform and cannot be modified.
|
||||
|
||||
Image types
|
||||
~~~~~~~~~~~
|
||||
|
||||
Images in a CoT are categorised as authentication and data images. An
|
||||
authentication image contains information to authenticate a data image or
|
||||
another authentication image. A data image is usually a boot loader binary, but
|
||||
it could be any other data that requires authentication.
|
||||
|
||||
Component responsibilities
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For every image in a Chain of Trust, the following high level operations are
|
||||
performed to verify it:
|
||||
|
||||
#. Allocate memory for the image either statically or at runtime.
|
||||
|
||||
#. Identify the image and load it in the allocated memory.
|
||||
|
||||
#. Check the integrity of the image as per its type.
|
||||
|
||||
#. Authenticate the image as per the cryptographic algorithms used.
|
||||
|
||||
#. If the image is an authentication image, extract the information that will
|
||||
be used to authenticate the next image in the CoT.
|
||||
|
||||
In Diagram 1, each component is responsible for one or more of these operations.
|
||||
The responsibilities are briefly described below.
|
||||
|
||||
TF-A Generic code and IO framework (GEN/IO)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
These components are responsible for initiating the authentication process for a
|
||||
particular image in BL1 or BL2. For each BL image that requires authentication,
|
||||
the Generic code asks recursively the Authentication module what is the parent
|
||||
image until either an authenticated image or the ROT is reached. Then the
|
||||
Generic code calls the IO framewotk to load the image and calls the
|
||||
Authentication module to authenticate it, following the CoT from ROT to Image.
|
||||
|
||||
TF-A Platform Port (PP)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The platform is responsible for:
|
||||
|
||||
#. Specifying the CoT for each image that needs to be authenticated. Details of
|
||||
how a CoT can be specified by the platform are explained later. The platform
|
||||
also specifies the authentication methods and the parsing method used for
|
||||
each image.
|
||||
|
||||
#. Statically allocating memory for each parameter in each image which is
|
||||
used for verifying the CoT, e.g. memory for public keys, hashes etc.
|
||||
|
||||
#. Providing the ROTPK or a hash of it.
|
||||
|
||||
#. Providing additional information to the IPM to enable it to identify and
|
||||
extract authentication parameters contained in an image, e.g. if the
|
||||
parameters are stored as X509v3 extensions, the corresponding OID must be
|
||||
provided.
|
||||
|
||||
#. Fulfill any other memory requirements of the IPM and the CM (not currently
|
||||
described in this document).
|
||||
|
||||
#. Export functions to verify an image which uses an authentication method that
|
||||
cannot be interpreted by the CM, e.g. if an image has to be verified using a
|
||||
NV counter, then the value of the counter to compare with can only be
|
||||
provided by the platform.
|
||||
|
||||
#. Export a custom IPM if a proprietary image format is being used (described
|
||||
later).
|
||||
|
||||
Authentication Module (AM)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is responsible for:
|
||||
|
||||
#. Providing the necessary abstraction mechanisms to describe a CoT. Amongst
|
||||
other things, the authentication and image parsing methods must be specified
|
||||
by the PP in the CoT.
|
||||
|
||||
#. Verifying the CoT passed by GEN by utilising functionality exported by the
|
||||
PP, IPM and CM.
|
||||
|
||||
#. Tracking which images have been verified. In case an image is a part of
|
||||
multiple CoTs then it should be verified only once e.g. the Trusted World
|
||||
Key Certificate in the TBBR-Client spec. contains information to verify
|
||||
SCP\_BL2, BL31, BL32 each of which have a separate CoT. (This
|
||||
responsibility has not been described in this document but should be
|
||||
trivial to implement).
|
||||
|
||||
#. Reusing memory meant for a data image to verify authentication images e.g.
|
||||
in the CoT described in Diagram 2, each certificate can be loaded and
|
||||
verified in the memory reserved by the platform for the BL31 image. By the
|
||||
time BL31 (the data image) is loaded, all information to authenticate it
|
||||
will have been extracted from the parent image i.e. BL31 content
|
||||
certificate. It is assumed that the size of an authentication image will
|
||||
never exceed the size of a data image. It should be possible to verify this
|
||||
at build time using asserts.
|
||||
|
||||
Cryptographic Module (CM)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The CM is responsible for providing an API to:
|
||||
|
||||
#. Verify a digital signature.
|
||||
#. Verify a hash.
|
||||
|
||||
The CM does not include any cryptography related code, but it relies on an
|
||||
external library to perform the cryptographic operations. A Crypto-Library (CL)
|
||||
linking the CM and the external library must be implemented. The following
|
||||
functions must be provided by the CL:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void (*init)(void);
|
||||
int (*verify_signature)(void *data_ptr, unsigned int data_len,
|
||||
void *sig_ptr, unsigned int sig_len,
|
||||
void *sig_alg, unsigned int sig_alg_len,
|
||||
void *pk_ptr, unsigned int pk_len);
|
||||
int (*verify_hash)(void *data_ptr, unsigned int data_len,
|
||||
void *digest_info_ptr, unsigned int digest_info_len);
|
||||
|
||||
These functions are registered in the CM using the macro:
|
||||
|
||||
.. code:: c
|
||||
|
||||
REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash);
|
||||
|
||||
``_name`` must be a string containing the name of the CL. This name is used for
|
||||
debugging purposes.
|
||||
|
||||
Image Parser Module (IPM)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The IPM is responsible for:
|
||||
|
||||
#. Checking the integrity of each image loaded by the IO framework.
|
||||
#. Extracting parameters used for authenticating an image based upon a
|
||||
description provided by the platform in the CoT descriptor.
|
||||
|
||||
Images may have different formats (for example, authentication images could be
|
||||
x509v3 certificates, signed ELF files or any other platform specific format).
|
||||
The IPM allows to register an Image Parser Library (IPL) for every image format
|
||||
used in the CoT. This library must implement the specific methods to parse the
|
||||
image. The IPM obtains the image format from the CoT and calls the right IPL to
|
||||
check the image integrity and extract the authentication parameters.
|
||||
|
||||
See Section "Describing the image parsing methods" for more details about the
|
||||
mechanism the IPM provides to define and register IPLs.
|
||||
|
||||
Authentication methods
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The AM supports the following authentication methods:
|
||||
|
||||
#. Hash
|
||||
#. Digital signature
|
||||
|
||||
The platform may specify these methods in the CoT in case it decides to define
|
||||
a custom CoT instead of reusing a predefined one.
|
||||
|
||||
If a data image uses multiple methods, then all the methods must be a part of
|
||||
the same CoT. The number and type of parameters are method specific. These
|
||||
parameters should be obtained from the parent image using the IPM.
|
||||
|
||||
#. Hash
|
||||
|
||||
Parameters:
|
||||
|
||||
#. A pointer to data to hash
|
||||
#. Length of the data
|
||||
#. A pointer to the hash
|
||||
#. Length of the hash
|
||||
|
||||
The hash will be represented by the DER encoding of the following ASN.1
|
||||
type:
|
||||
|
||||
::
|
||||
|
||||
DigestInfo ::= SEQUENCE {
|
||||
digestAlgorithm DigestAlgorithmIdentifier,
|
||||
digest Digest
|
||||
}
|
||||
|
||||
This ASN.1 structure makes it possible to remove any assumption about the
|
||||
type of hash algorithm used as this information accompanies the hash. This
|
||||
should allow the Cryptography Library (CL) to support multiple hash
|
||||
algorithm implementations.
|
||||
|
||||
#. Digital Signature
|
||||
|
||||
Parameters:
|
||||
|
||||
#. A pointer to data to sign
|
||||
#. Length of the data
|
||||
#. Public Key Algorithm
|
||||
#. Public Key value
|
||||
#. Digital Signature Algorithm
|
||||
#. Digital Signature value
|
||||
|
||||
The Public Key parameters will be represented by the DER encoding of the
|
||||
following ASN.1 type:
|
||||
|
||||
::
|
||||
|
||||
SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}},
|
||||
subjectPublicKey BIT STRING }
|
||||
|
||||
The Digital Signature Algorithm will be represented by the DER encoding of
|
||||
the following ASN.1 types.
|
||||
|
||||
::
|
||||
|
||||
AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE {
|
||||
algorithm ALGORITHM.&id({IOSet}),
|
||||
parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
|
||||
}
|
||||
|
||||
The digital signature will be represented by:
|
||||
|
||||
::
|
||||
|
||||
signature ::= BIT STRING
|
||||
|
||||
The authentication framework will use the image descriptor to extract all the
|
||||
information related to authentication.
|
||||
|
||||
Specifying a Chain of Trust
|
||||
---------------------------
|
||||
|
||||
A CoT can be described as a set of image descriptors linked together in a
|
||||
particular order. The order dictates the sequence in which they must be
|
||||
verified. Each image has a set of properties which allow the AM to verify it.
|
||||
These properties are described below.
|
||||
|
||||
The PP is responsible for defining a single or multiple CoTs for a data image.
|
||||
Unless otherwise specified, the data structures described in the following
|
||||
sections are populated by the PP statically.
|
||||
|
||||
Describing the image parsing methods
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The parsing method refers to the format of a particular image. For example, an
|
||||
authentication image that represents a certificate could be in the X.509v3
|
||||
format. A data image that represents a boot loader stage could be in raw binary
|
||||
or ELF format. The IPM supports three parsing methods. An image has to use one
|
||||
of the three methods described below. An IPL is responsible for interpreting a
|
||||
single parsing method. There has to be one IPL for every method used by the
|
||||
platform.
|
||||
|
||||
#. Raw format: This format is effectively a nop as an image using this method
|
||||
is treated as being in raw binary format e.g. boot loader images used by
|
||||
TF-A. This method should only be used by data images.
|
||||
|
||||
#. X509V3 method: This method uses industry standards like X.509 to represent
|
||||
PKI certificates (authentication images). It is expected that open source
|
||||
libraries will be available which can be used to parse an image represented
|
||||
by this method. Such libraries can be used to write the corresponding IPL
|
||||
e.g. the X.509 parsing library code in mbed TLS.
|
||||
|
||||
#. Platform defined method: This method caters for platform specific
|
||||
proprietary standards to represent authentication or data images. For
|
||||
example, The signature of a data image could be appended to the data image
|
||||
raw binary. A header could be prepended to the combined blob to specify the
|
||||
extents of each component. The platform will have to implement the
|
||||
corresponding IPL to interpret such a format.
|
||||
|
||||
The following enum can be used to define these three methods.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef enum img_type_enum {
|
||||
IMG_RAW, /* Binary image */
|
||||
IMG_PLAT, /* Platform specific format */
|
||||
IMG_CERT, /* X509v3 certificate */
|
||||
IMG_MAX_TYPES,
|
||||
} img_type_t;
|
||||
|
||||
An IPL must provide functions with the following prototypes:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void init(void);
|
||||
int check_integrity(void *img, unsigned int img_len);
|
||||
int get_auth_param(const auth_param_type_desc_t *type_desc,
|
||||
void *img, unsigned int img_len,
|
||||
void **param, unsigned int *param_len);
|
||||
|
||||
An IPL for each type must be registered using the following macro:
|
||||
|
||||
::
|
||||
|
||||
REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param)
|
||||
|
||||
- ``_type``: one of the types described above.
|
||||
- ``_name``: a string containing the IPL name for debugging purposes.
|
||||
- ``_init``: initialization function pointer.
|
||||
- ``_check_int``: check image integrity function pointer.
|
||||
- ``_get_param``: extract authentication parameter funcion pointer.
|
||||
|
||||
The ``init()`` function will be used to initialize the IPL.
|
||||
|
||||
The ``check_integrity()`` function is passed a pointer to the memory where the
|
||||
image has been loaded by the IO framework and the image length. It should ensure
|
||||
that the image is in the format corresponding to the parsing method and has not
|
||||
been tampered with. For example, RFC-2459 describes a validation sequence for an
|
||||
X.509 certificate.
|
||||
|
||||
The ``get_auth_param()`` function is passed a parameter descriptor containing
|
||||
information about the parameter (``type_desc`` and ``cookie``) to identify and
|
||||
extract the data corresponding to that parameter from an image. This data will
|
||||
be used to verify either the current or the next image in the CoT sequence.
|
||||
|
||||
Each image in the CoT will specify the parsing method it uses. This information
|
||||
will be used by the IPM to find the right parser descriptor for the image.
|
||||
|
||||
Describing the authentication method(s)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As part of the CoT, each image has to specify one or more authentication methods
|
||||
which will be used to verify it. As described in the Section "Authentication
|
||||
methods", there are three methods supported by the AM.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef enum {
|
||||
AUTH_METHOD_NONE,
|
||||
AUTH_METHOD_HASH,
|
||||
AUTH_METHOD_SIG,
|
||||
AUTH_METHOD_NUM
|
||||
} auth_method_type_t;
|
||||
|
||||
The AM defines the type of each parameter used by an authentication method. It
|
||||
uses this information to:
|
||||
|
||||
#. Specify to the ``get_auth_param()`` function exported by the IPM, which
|
||||
parameter should be extracted from an image.
|
||||
|
||||
#. Correctly marshall the parameters while calling the verification function
|
||||
exported by the CM and PP.
|
||||
|
||||
#. Extract authentication parameters from a parent image in order to verify a
|
||||
child image e.g. to verify the certificate image, the public key has to be
|
||||
obtained from the parent image.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef enum {
|
||||
AUTH_PARAM_NONE,
|
||||
AUTH_PARAM_RAW_DATA, /* Raw image data */
|
||||
AUTH_PARAM_SIG, /* The image signature */
|
||||
AUTH_PARAM_SIG_ALG, /* The image signature algorithm */
|
||||
AUTH_PARAM_HASH, /* A hash (including the algorithm) */
|
||||
AUTH_PARAM_PUB_KEY, /* A public key */
|
||||
} auth_param_type_t;
|
||||
|
||||
The AM defines the following structure to identify an authentication parameter
|
||||
required to verify an image.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_param_type_desc_s {
|
||||
auth_param_type_t type;
|
||||
void *cookie;
|
||||
} auth_param_type_desc_t;
|
||||
|
||||
``cookie`` is used by the platform to specify additional information to the IPM
|
||||
which enables it to uniquely identify the parameter that should be extracted
|
||||
from an image. For example, the hash of a BL3x image in its corresponding
|
||||
content certificate is stored in an X509v3 custom extension field. An extension
|
||||
field can only be identified using an OID. In this case, the ``cookie`` could
|
||||
contain the pointer to the OID defined by the platform for the hash extension
|
||||
field while the ``type`` field could be set to ``AUTH_PARAM_HASH``. A value of 0 for
|
||||
the ``cookie`` field means that it is not used.
|
||||
|
||||
For each method, the AM defines a structure with the parameters required to
|
||||
verify the image.
|
||||
|
||||
.. code:: c
|
||||
|
||||
/*
|
||||
* Parameters for authentication by hash matching
|
||||
*/
|
||||
typedef struct auth_method_param_hash_s {
|
||||
auth_param_type_desc_t *data; /* Data to hash */
|
||||
auth_param_type_desc_t *hash; /* Hash to match with */
|
||||
} auth_method_param_hash_t;
|
||||
|
||||
/*
|
||||
* Parameters for authentication by signature
|
||||
*/
|
||||
typedef struct auth_method_param_sig_s {
|
||||
auth_param_type_desc_t *pk; /* Public key */
|
||||
auth_param_type_desc_t *sig; /* Signature to check */
|
||||
auth_param_type_desc_t *alg; /* Signature algorithm */
|
||||
auth_param_type_desc_t *tbs; /* Data signed */
|
||||
} auth_method_param_sig_t;
|
||||
|
||||
The AM defines the following structure to describe an authentication method for
|
||||
verifying an image
|
||||
|
||||
.. code:: c
|
||||
|
||||
/*
|
||||
* Authentication method descriptor
|
||||
*/
|
||||
typedef struct auth_method_desc_s {
|
||||
auth_method_type_t type;
|
||||
union {
|
||||
auth_method_param_hash_t hash;
|
||||
auth_method_param_sig_t sig;
|
||||
} param;
|
||||
} auth_method_desc_t;
|
||||
|
||||
Using the method type specified in the ``type`` field, the AM finds out what field
|
||||
needs to access within the ``param`` union.
|
||||
|
||||
Storing Authentication parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A parameter described by ``auth_param_type_desc_t`` to verify an image could be
|
||||
obtained from either the image itself or its parent image. The memory allocated
|
||||
for loading the parent image will be reused for loading the child image. Hence
|
||||
parameters which are obtained from the parent for verifying a child image need
|
||||
to have memory allocated for them separately where they can be stored. This
|
||||
memory must be statically allocated by the platform port.
|
||||
|
||||
The AM defines the following structure to store the data corresponding to an
|
||||
authentication parameter.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_param_data_desc_s {
|
||||
void *auth_param_ptr;
|
||||
unsigned int auth_param_len;
|
||||
} auth_param_data_desc_t;
|
||||
|
||||
The ``auth_param_ptr`` field is initialized by the platform. The ``auth_param_len``
|
||||
field is used to specify the length of the data in the memory.
|
||||
|
||||
For parameters that can be obtained from the child image itself, the IPM is
|
||||
responsible for populating the ``auth_param_ptr`` and ``auth_param_len`` fields
|
||||
while executing the ``img_get_auth_param()`` function.
|
||||
|
||||
The AM defines the following structure to enable an image to describe the
|
||||
parameters that should be extracted from it and used to verify the next image
|
||||
(child) in a CoT.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_param_desc_s {
|
||||
auth_param_type_desc_t type_desc;
|
||||
auth_param_data_desc_t data;
|
||||
} auth_param_desc_t;
|
||||
|
||||
Describing an image in a CoT
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An image in a CoT is a consolidation of the following aspects of a CoT described
|
||||
above.
|
||||
|
||||
#. A unique identifier specified by the platform which allows the IO framework
|
||||
to locate the image in a FIP and load it in the memory reserved for the data
|
||||
image in the CoT.
|
||||
|
||||
#. A parsing method which is used by the AM to find the appropriate IPM.
|
||||
|
||||
#. Authentication methods and their parameters as described in the previous
|
||||
section. These are used to verify the current image.
|
||||
|
||||
#. Parameters which are used to verify the next image in the current CoT. These
|
||||
parameters are specified only by authentication images and can be extracted
|
||||
from the current image once it has been verified.
|
||||
|
||||
The following data structure describes an image in a CoT.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_img_desc_s {
|
||||
unsigned int img_id;
|
||||
const struct auth_img_desc_s *parent;
|
||||
img_type_t img_type;
|
||||
auth_method_desc_t img_auth_methods[AUTH_METHOD_NUM];
|
||||
auth_param_desc_t authenticated_data[COT_MAX_VERIFIED_PARAMS];
|
||||
} auth_img_desc_t;
|
||||
|
||||
A CoT is defined as an array of ``auth_image_desc_t`` structures linked together
|
||||
by the ``parent`` field. Those nodes with no parent must be authenticated using
|
||||
the ROTPK stored in the platform.
|
||||
|
||||
Implementation example
|
||||
----------------------
|
||||
|
||||
This section is a detailed guide explaining a trusted boot implementation using
|
||||
the authentication framework. This example corresponds to the Applicative
|
||||
Functional Mode (AFM) as specified in the TBBR-Client document. It is
|
||||
recommended to read this guide along with the source code.
|
||||
|
||||
The TBBR CoT
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The CoT can be found in ``drivers/auth/tbbr/tbbr_cot.c``. This CoT consists of an
|
||||
array of image descriptors and it is registered in the framework using the macro
|
||||
``REGISTER_COT(cot_desc)``, where 'cot\_desc' must be the name of the array
|
||||
(passing a pointer or any other type of indirection will cause the registration
|
||||
process to fail).
|
||||
|
||||
The number of images participating in the boot process depends on the CoT. There
|
||||
is, however, a minimum set of images that are mandatory in TF-A and thus all
|
||||
CoTs must present:
|
||||
|
||||
- ``BL2``
|
||||
- ``SCP_BL2`` (platform specific)
|
||||
- ``BL31``
|
||||
- ``BL32`` (optional)
|
||||
- ``BL33``
|
||||
|
||||
The TBBR specifies the additional certificates that must accompany these images
|
||||
for a proper authentication. Details about the TBBR CoT may be found in the
|
||||
`Trusted Board Boot`_ document.
|
||||
|
||||
Following the `Platform Porting Guide`_, a platform must provide unique
|
||||
identifiers for all the images and certificates that will be loaded during the
|
||||
boot process. If a platform is using the TBBR as a reference for trusted boot,
|
||||
these identifiers can be obtained from ``include/common/tbbr/tbbr_img_def.h``.
|
||||
Arm platforms include this file in ``include/plat/arm/common/arm_def.h``. Other
|
||||
platforms may also include this file or provide their own identifiers.
|
||||
|
||||
**Important**: the authentication module uses these identifiers to index the
|
||||
CoT array, so the descriptors location in the array must match the identifiers.
|
||||
|
||||
Each image descriptor must specify:
|
||||
|
||||
- ``img_id``: the corresponding image unique identifier defined by the platform.
|
||||
- ``img_type``: the image parser module uses the image type to call the proper
|
||||
parsing library to check the image integrity and extract the required
|
||||
authentication parameters. Three types of images are currently supported:
|
||||
|
||||
- ``IMG_RAW``: image is a raw binary. No parsing functions are available,
|
||||
other than reading the whole image.
|
||||
- ``IMG_PLAT``: image format is platform specific. The platform may use this
|
||||
type for custom images not directly supported by the authentication
|
||||
framework.
|
||||
- ``IMG_CERT``: image is an x509v3 certificate.
|
||||
|
||||
- ``parent``: pointer to the parent image descriptor. The parent will contain
|
||||
the information required to authenticate the current image. If the parent
|
||||
is NULL, the authentication parameters will be obtained from the platform
|
||||
(i.e. the BL2 and Trusted Key certificates are signed with the ROT private
|
||||
key, whose public part is stored in the platform).
|
||||
- ``img_auth_methods``: this array defines the authentication methods that must
|
||||
be checked to consider an image authenticated. Each method consists of a
|
||||
type and a list of parameter descriptors. A parameter descriptor consists of
|
||||
a type and a cookie which will point to specific information required to
|
||||
extract that parameter from the image (i.e. if the parameter is stored in an
|
||||
x509v3 extension, the cookie will point to the extension OID). Depending on
|
||||
the method type, a different number of parameters must be specified.
|
||||
Supported methods are:
|
||||
|
||||
- ``AUTH_METHOD_HASH``: the hash of the image must match the hash extracted
|
||||
from the parent image. The following parameter descriptors must be
|
||||
specified:
|
||||
|
||||
- ``data``: data to be hashed (obtained from current image)
|
||||
- ``hash``: reference hash (obtained from parent image)
|
||||
|
||||
- ``AUTH_METHOD_SIG``: the image (usually a certificate) must be signed with
|
||||
the private key whose public part is extracted from the parent image (or
|
||||
the platform if the parent is NULL). The following parameter descriptors
|
||||
must be specified:
|
||||
|
||||
- ``pk``: the public key (obtained from parent image)
|
||||
- ``sig``: the digital signature (obtained from current image)
|
||||
- ``alg``: the signature algorithm used (obtained from current image)
|
||||
- ``data``: the data to be signed (obtained from current image)
|
||||
|
||||
- ``authenticated_data``: this array indicates what authentication parameters
|
||||
must be extracted from an image once it has been authenticated. Each
|
||||
parameter consists of a parameter descriptor and the buffer address/size
|
||||
to store the parameter. The CoT is responsible for allocating the required
|
||||
memory to store the parameters.
|
||||
|
||||
In the ``tbbr_cot.c`` file, a set of buffers are allocated to store the parameters
|
||||
extracted from the certificates. In the case of the TBBR CoT, these parameters
|
||||
are hashes and public keys. In DER format, an RSA-2048 public key requires 294
|
||||
bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication
|
||||
process, some of the buffers may be reused at different stages during the boot.
|
||||
|
||||
Next in that file, the parameter descriptors are defined. These descriptors will
|
||||
be used to extract the parameter data from the corresponding image.
|
||||
|
||||
Example: the BL31 Chain of Trust
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Four image descriptors form the BL31 Chain of Trust:
|
||||
|
||||
.. code:: asm
|
||||
|
||||
[TRUSTED_KEY_CERT_ID] = {
|
||||
.img_id = TRUSTED_KEY_CERT_ID,
|
||||
.img_type = IMG_CERT,
|
||||
.parent = NULL,
|
||||
.img_auth_methods = {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_SIG,
|
||||
.param.sig = {
|
||||
.pk = &subject_pk,
|
||||
.sig = &sig,
|
||||
.alg = &sig_alg,
|
||||
.data = &raw_data,
|
||||
}
|
||||
}
|
||||
},
|
||||
.authenticated_data = {
|
||||
[0] = {
|
||||
.type_desc = &trusted_world_pk,
|
||||
.data = {
|
||||
.ptr = (void *)trusted_world_pk_buf,
|
||||
.len = (unsigned int)PK_DER_LEN
|
||||
}
|
||||
},
|
||||
[1] = {
|
||||
.type_desc = &non_trusted_world_pk,
|
||||
.data = {
|
||||
.ptr = (void *)non_trusted_world_pk_buf,
|
||||
.len = (unsigned int)PK_DER_LEN
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[SOC_FW_KEY_CERT_ID] = {
|
||||
.img_id = SOC_FW_KEY_CERT_ID,
|
||||
.img_type = IMG_CERT,
|
||||
.parent = &cot_desc[TRUSTED_KEY_CERT_ID],
|
||||
.img_auth_methods = {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_SIG,
|
||||
.param.sig = {
|
||||
.pk = &trusted_world_pk,
|
||||
.sig = &sig,
|
||||
.alg = &sig_alg,
|
||||
.data = &raw_data,
|
||||
}
|
||||
}
|
||||
},
|
||||
.authenticated_data = {
|
||||
[0] = {
|
||||
.type_desc = &soc_fw_content_pk,
|
||||
.data = {
|
||||
.ptr = (void *)content_pk_buf,
|
||||
.len = (unsigned int)PK_DER_LEN
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[SOC_FW_CONTENT_CERT_ID] = {
|
||||
.img_id = SOC_FW_CONTENT_CERT_ID,
|
||||
.img_type = IMG_CERT,
|
||||
.parent = &cot_desc[SOC_FW_KEY_CERT_ID],
|
||||
.img_auth_methods = {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_SIG,
|
||||
.param.sig = {
|
||||
.pk = &soc_fw_content_pk,
|
||||
.sig = &sig,
|
||||
.alg = &sig_alg,
|
||||
.data = &raw_data,
|
||||
}
|
||||
}
|
||||
},
|
||||
.authenticated_data = {
|
||||
[0] = {
|
||||
.type_desc = &soc_fw_hash,
|
||||
.data = {
|
||||
.ptr = (void *)soc_fw_hash_buf,
|
||||
.len = (unsigned int)HASH_DER_LEN
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[BL31_IMAGE_ID] = {
|
||||
.img_id = BL31_IMAGE_ID,
|
||||
.img_type = IMG_RAW,
|
||||
.parent = &cot_desc[SOC_FW_CONTENT_CERT_ID],
|
||||
.img_auth_methods = {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_HASH,
|
||||
.param.hash = {
|
||||
.data = &raw_data,
|
||||
.hash = &soc_fw_hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The **Trusted Key certificate** is signed with the ROT private key and contains
|
||||
the Trusted World public key and the Non-Trusted World public key as x509v3
|
||||
extensions. This must be specified in the image descriptor using the
|
||||
``img_auth_methods`` and ``authenticated_data`` arrays, respectively.
|
||||
|
||||
The Trusted Key certificate is authenticated by checking its digital signature
|
||||
using the ROTPK. Four parameters are required to check a signature: the public
|
||||
key, the algorithm, the signature and the data that has been signed. Therefore,
|
||||
four parameter descriptors must be specified with the authentication method:
|
||||
|
||||
- ``subject_pk``: parameter descriptor of type ``AUTH_PARAM_PUB_KEY``. This type
|
||||
is used to extract a public key from the parent image. If the cookie is an
|
||||
OID, the key is extracted from the corresponding x509v3 extension. If the
|
||||
cookie is NULL, the subject public key is retrieved. In this case, because
|
||||
the parent image is NULL, the public key is obtained from the platform
|
||||
(this key will be the ROTPK).
|
||||
- ``sig``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to extract
|
||||
the signature from the certificate.
|
||||
- ``sig_alg``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to
|
||||
extract the signature algorithm from the certificate.
|
||||
- ``raw_data``: parameter descriptor of type ``AUTH_PARAM_RAW_DATA``. It is used
|
||||
to extract the data to be signed from the certificate.
|
||||
|
||||
Once the signature has been checked and the certificate authenticated, the
|
||||
Trusted World public key needs to be extracted from the certificate. A new entry
|
||||
is created in the ``authenticated_data`` array for that purpose. In that entry,
|
||||
the corresponding parameter descriptor must be specified along with the buffer
|
||||
address to store the parameter value. In this case, the ``tz_world_pk`` descriptor
|
||||
is used to extract the public key from an x509v3 extension with OID
|
||||
``TRUSTED_WORLD_PK_OID``. The BL31 key certificate will use this descriptor as
|
||||
parameter in the signature authentication method. The key is stored in the
|
||||
``plat_tz_world_pk_buf`` buffer.
|
||||
|
||||
The **BL31 Key certificate** is authenticated by checking its digital signature
|
||||
using the Trusted World public key obtained previously from the Trusted Key
|
||||
certificate. In the image descriptor, we specify a single authentication method
|
||||
by signature whose public key is the ``tz_world_pk``. Once this certificate has
|
||||
been authenticated, we have to extract the BL31 public key, stored in the
|
||||
extension specified by ``bl31_content_pk``. This key will be copied to the
|
||||
``plat_content_pk`` buffer.
|
||||
|
||||
The **BL31 certificate** is authenticated by checking its digital signature
|
||||
using the BL31 public key obtained previously from the BL31 Key certificate.
|
||||
We specify the authentication method using ``bl31_content_pk`` as public key.
|
||||
After authentication, we need to extract the BL31 hash, stored in the extension
|
||||
specified by ``bl31_hash``. This hash will be copied to the ``plat_bl31_hash_buf``
|
||||
buffer.
|
||||
|
||||
The **BL31 image** is authenticated by calculating its hash and matching it
|
||||
with the hash obtained from the BL31 certificate. The image descriptor contains
|
||||
a single authentication method by hash. The parameters to the hash method are
|
||||
the reference hash, ``bl31_hash``, and the data to be hashed. In this case, it is
|
||||
the whole image, so we specify ``raw_data``.
|
||||
|
||||
The image parser library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The image parser module relies on libraries to check the image integrity and
|
||||
extract the authentication parameters. The number and type of parser libraries
|
||||
depend on the images used in the CoT. Raw images do not need a library, so
|
||||
only an x509v3 library is required for the TBBR CoT.
|
||||
|
||||
Arm platforms will use an x509v3 library based on mbed TLS. This library may be
|
||||
found in ``drivers/auth/mbedtls/mbedtls_x509_parser.c``. It exports three
|
||||
functions:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void init(void);
|
||||
int check_integrity(void *img, unsigned int img_len);
|
||||
int get_auth_param(const auth_param_type_desc_t *type_desc,
|
||||
void *img, unsigned int img_len,
|
||||
void **param, unsigned int *param_len);
|
||||
|
||||
The library is registered in the framework using the macro
|
||||
``REGISTER_IMG_PARSER_LIB()``. Each time the image parser module needs to access
|
||||
an image of type ``IMG_CERT``, it will call the corresponding function exported
|
||||
in this file.
|
||||
|
||||
The build system must be updated to include the corresponding library and
|
||||
mbed TLS sources. Arm platforms use the ``arm_common.mk`` file to pull the
|
||||
sources.
|
||||
|
||||
The cryptographic library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The cryptographic module relies on a library to perform the required operations,
|
||||
i.e. verify a hash or a digital signature. Arm platforms will use a library
|
||||
based on mbed TLS, which can be found in
|
||||
``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the
|
||||
authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports
|
||||
three functions:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void init(void);
|
||||
int verify_signature(void *data_ptr, unsigned int data_len,
|
||||
void *sig_ptr, unsigned int sig_len,
|
||||
void *sig_alg, unsigned int sig_alg_len,
|
||||
void *pk_ptr, unsigned int pk_len);
|
||||
int verify_hash(void *data_ptr, unsigned int data_len,
|
||||
void *digest_info_ptr, unsigned int digest_info_len);
|
||||
|
||||
The mbedTLS library algorithm support is configured by the
|
||||
``TF_MBEDTLS_KEY_ALG`` variable which can take in 3 values: `rsa`, `ecdsa` or
|
||||
`rsa+ecdsa`. This variable allows the Makefile to include the corresponding
|
||||
sources in the build for the various algorthms. Setting the variable to
|
||||
`rsa+ecdsa` enables support for both rsa and ecdsa algorithms in the mbedTLS
|
||||
library.
|
||||
|
||||
Note: If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can
|
||||
be defined in the platform Makefile. It will make mbed TLS use an implementation
|
||||
of SHA-256 with smaller memory footprint (~1.5 KB less) but slower (~30%).
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _Trusted Board Boot: ./trusted-board-boot.rst
|
||||
.. _Platform Porting Guide: ./porting-guide.rst
|
||||
1662
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/change-log.rst
vendored
Normal file
173
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/cpu-specific-build-macros.rst
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
Arm CPU Specific Build Macros
|
||||
=============================
|
||||
|
||||
|
||||
.. section-numbering::
|
||||
:suffix: .
|
||||
|
||||
.. contents::
|
||||
|
||||
This document describes the various build options present in the CPU specific
|
||||
operations framework to enable errata workarounds and to enable optimizations
|
||||
for a specific CPU on a platform.
|
||||
|
||||
Security Vulnerability Workarounds
|
||||
----------------------------------
|
||||
|
||||
TF-A exports a series of build flags which control which security
|
||||
vulnerability workarounds should be applied at runtime.
|
||||
|
||||
- ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for
|
||||
`CVE-2017-5715`_. This flag can be set to 0 by the platform if none
|
||||
of the PEs in the system need the workaround. Setting this flag to 0 provides
|
||||
no performance benefit for non-affected platforms, it just helps to comply
|
||||
with the recommendation in the spec regarding workaround discovery.
|
||||
Defaults to 1.
|
||||
|
||||
- ``WORKAROUND_CVE_2018_3639``: Enables the security workaround for
|
||||
`CVE-2018-3639`_. Defaults to 1. The TF-A project recommends to keep
|
||||
the default value of 1 even on platforms that are unaffected by
|
||||
CVE-2018-3639, in order to comply with the recommendation in the spec
|
||||
regarding workaround discovery.
|
||||
|
||||
- ``DYNAMIC_WORKAROUND_CVE_2018_3639``: Enables dynamic mitigation for
|
||||
`CVE-2018-3639`_. This build option should be set to 1 if the target
|
||||
platform contains at least 1 CPU that requires dynamic mitigation.
|
||||
Defaults to 0.
|
||||
|
||||
CPU Errata Workarounds
|
||||
----------------------
|
||||
|
||||
TF-A exports a series of build flags which control the errata workarounds that
|
||||
are applied to each CPU by the reset handler. The errata details can be found
|
||||
in the CPU specific errata documents published by Arm:
|
||||
|
||||
- `Cortex-A53 MPCore Software Developers Errata Notice`_
|
||||
- `Cortex-A57 MPCore Software Developers Errata Notice`_
|
||||
- `Cortex-A72 MPCore Software Developers Errata Notice`_
|
||||
|
||||
The errata workarounds are implemented for a particular revision or a set of
|
||||
processor revisions. This is checked by the reset handler at runtime. Each
|
||||
errata workaround is identified by its ``ID`` as specified in the processor's
|
||||
errata notice document. The format of the define used to enable/disable the
|
||||
errata workaround is ``ERRATA_<Processor name>_<ID>``, where the ``Processor name``
|
||||
is for example ``A57`` for the ``Cortex_A57`` CPU.
|
||||
|
||||
Refer to the section *CPU errata status reporting* in
|
||||
`Firmware Design guide`_ for information on how to write errata workaround
|
||||
functions.
|
||||
|
||||
All workarounds are disabled by default. The platform is responsible for
|
||||
enabling these workarounds according to its requirement by defining the
|
||||
errata workaround build flags in the platform specific makefile. In case
|
||||
these workarounds are enabled for the wrong CPU revision then the errata
|
||||
workaround is not applied. In the DEBUG build, this is indicated by
|
||||
printing a warning to the crash console.
|
||||
|
||||
In the current implementation, a platform which has more than 1 variant
|
||||
with different revisions of a processor has no runtime mechanism available
|
||||
for it to specify which errata workarounds should be enabled or not.
|
||||
|
||||
The value of the build flags are 0 by default, that is, disabled. Any other
|
||||
value will enable it.
|
||||
|
||||
For Cortex-A53, following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A53_826319``: This applies errata 826319 workaround to Cortex-A53
|
||||
CPU. This needs to be enabled only for revision <= r0p2 of the CPU.
|
||||
|
||||
- ``ERRATA_A53_835769``: This applies erratum 835769 workaround at compile and
|
||||
link time to Cortex-A53 CPU. This needs to be enabled for some variants of
|
||||
revision <= r0p4. This workaround can lead the linker to create ``*.stub``
|
||||
sections.
|
||||
|
||||
- ``ERRATA_A53_836870``: This applies errata 836870 workaround to Cortex-A53
|
||||
CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From
|
||||
r0p4 and onwards, this errata is enabled by default in hardware.
|
||||
|
||||
- ``ERRATA_A53_843419``: This applies erratum 843419 workaround at link time
|
||||
to Cortex-A53 CPU. This needs to be enabled for some variants of revision
|
||||
<= r0p4. This workaround can lead the linker to emit ``*.stub`` sections
|
||||
which are 4kB aligned.
|
||||
|
||||
- ``ERRATA_A53_855873``: This applies errata 855873 workaround to Cortex-A53
|
||||
CPUs. Though the erratum is present in every revision of the CPU,
|
||||
this workaround is only applied to CPUs from r0p3 onwards, which feature
|
||||
a chicken bit in CPUACTLR\_EL1 to enable a hardware workaround.
|
||||
Earlier revisions of the CPU have other errata which require the same
|
||||
workaround in software, so they should be covered anyway.
|
||||
|
||||
For Cortex-A57, following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A57_806969``: This applies errata 806969 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_813419``: This applies errata 813419 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_813420``: This applies errata 813420 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_826974``: This applies errata 826974 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_826977``: This applies errata 826977 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_828024``: This applies errata 828024 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_829520``: This applies errata 829520 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p3 of the CPU.
|
||||
|
||||
|
||||
For Cortex-A72, following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72
|
||||
CPU. This needs to be enabled only for revision <= r0p3 of the CPU.
|
||||
|
||||
CPU Specific optimizations
|
||||
--------------------------
|
||||
|
||||
This section describes some of the optimizations allowed by the CPU micro
|
||||
architecture that can be enabled by the platform as desired.
|
||||
|
||||
- ``SKIP_A57_L1_FLUSH_PWR_DWN``: This flag enables an optimization in the
|
||||
Cortex-A57 cluster power down sequence by not flushing the Level 1 data
|
||||
cache. The L1 data cache and the L2 unified cache are inclusive. A flush
|
||||
of the L2 by set/way flushes any dirty lines from the L1 as well. This
|
||||
is a known safe deviation from the Cortex-A57 TRM defined power down
|
||||
sequence. Each Cortex-A57 based platform must make its own decision on
|
||||
whether to use the optimization.
|
||||
|
||||
- ``A53_DISABLE_NON_TEMPORAL_HINT``: This flag disables the cache non-temporal
|
||||
hint. The LDNP/STNP instructions as implemented on Cortex-A53 do not behave
|
||||
in a way most programmers expect, and will most probably result in a
|
||||
significant speed degradation to any code that employs them. The Armv8-A
|
||||
architecture (see Arm DDI 0487A.h, section D3.4.3) allows cores to ignore
|
||||
the non-temporal hint and treat LDNP/STNP as LDP/STP instead. Enabling this
|
||||
flag enforces this behaviour. This needs to be enabled only for revisions
|
||||
<= r0p3 of the CPU and is enabled by default.
|
||||
|
||||
- ``A57_DISABLE_NON_TEMPORAL_HINT``: This flag has the same behaviour as
|
||||
``A53_DISABLE_NON_TEMPORAL_HINT`` but for Cortex-A57. This needs to be
|
||||
enabled only for revisions <= r1p2 of the CPU and is enabled by default,
|
||||
as recommended in section "4.7 Non-Temporal Loads/Stores" of the
|
||||
`Cortex-A57 Software Optimization Guide`_.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _CVE-2017-5715: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2017-5715
|
||||
.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf
|
||||
.. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/cortex_a57_mpcore_software_developers_errata_notice.pdf
|
||||
.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html
|
||||
.. _Firmware Design guide: firmware-design.rst
|
||||
.. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf
|
||||
74
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/Makefile
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
#
|
||||
# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
#
|
||||
# This Makefile generates the image files used in the ARM Trusted Firmware
|
||||
# document from the dia file.
|
||||
#
|
||||
# The PNG files in the present directory have been generated using Dia version
|
||||
# 0.97.2, which can be obtained from https://wiki.gnome.org/Apps/Dia/Download
|
||||
#
|
||||
|
||||
# generate_image use the tool dia generate png from dia file
|
||||
# $(1) = layers
|
||||
# $(2) = image file name
|
||||
# $(3) = image file format
|
||||
# $(4) = addition opts
|
||||
# $(5) = dia source file
|
||||
define generate_image
|
||||
dia --show-layers=$(1) --filter=$(3) --export=$(2) $(4) $(5)
|
||||
endef
|
||||
|
||||
RESET_DIA = reset_code_flow.dia
|
||||
RESET_PNGS = \
|
||||
default_reset_code.png \
|
||||
reset_code_no_cpu_check.png \
|
||||
reset_code_no_boot_type_check.png \
|
||||
reset_code_no_checks.png \
|
||||
|
||||
# The $(RESET_DIA) file is organized in several layers.
|
||||
# Each image is generated by combining and exporting the appropriate set of
|
||||
# layers.
|
||||
default_reset_code_layers = "Frontground,Background,cpu_type_check,boot_type_check"
|
||||
reset_code_no_cpu_check_layers = "Frontground,Background,no_cpu_type_check,boot_type_check"
|
||||
reset_code_no_boot_type_check_layers= "Frontground,Background,cpu_type_check,no_boot_type_check"
|
||||
reset_code_no_checks_layers = "Frontground,Background,no_cpu_type_check,no_boot_type_check"
|
||||
|
||||
default_reset_code_opts =
|
||||
reset_code_no_cpu_check_opts =
|
||||
reset_code_no_boot_type_check_opts =
|
||||
reset_code_no_checks_opts =
|
||||
|
||||
INT_DIA = int_handling.dia
|
||||
INT_PNGS = \
|
||||
sec-int-handling.png \
|
||||
non-sec-int-handling.png
|
||||
|
||||
# The $(INT_DIA) file is organized in several layers.
|
||||
# Each image is generated by combining and exporting the appropriate set of
|
||||
# layers.
|
||||
non-sec-int-handling_layers = "non_sec_int_bg,legend,non_sec_int_note,non_sec_int_handling"
|
||||
sec-int-handling_layers = "sec_int_bg,legend,sec_int_note,sec_int_handling"
|
||||
|
||||
non-sec-int-handling_opts = --size=1692x
|
||||
sec-int-handling_opts = --size=1570x
|
||||
|
||||
XLAT_DIA = xlat_align.dia
|
||||
XLAT_PNG = xlat_align.png
|
||||
|
||||
xlat_align_layers = "bg,translations"
|
||||
xlat_align_opts =
|
||||
|
||||
all:$(RESET_PNGS) $(INT_PNGS) $(XLAT_PNG)
|
||||
|
||||
$(RESET_PNGS):$(RESET_DIA)
|
||||
$(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<)
|
||||
|
||||
$(INT_PNGS):$(INT_DIA)
|
||||
$(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<)
|
||||
|
||||
$(XLAT_PNG):$(XLAT_DIA)
|
||||
$(call generate_image,$($(patsubst %.png,%_layers,$@)),$(patsubst %.png,%.svg,$@),svg,$($(patsubst %.png,%_opts,$@)),$<)
|
||||
inkscape -z $(patsubst %.png,%.svg,$@) -e $@ -d 45
|
||||
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/default_reset_code.png
vendored
Normal file
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/fwu_flow.png
vendored
Normal file
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 163 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/fwu_states.png
vendored
Normal file
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/int_handling.dia
vendored
Normal file
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/non-sec-int-handling.png
vendored
Normal file
|
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 214 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/psci-suspend-sequence.png
vendored
Normal file
|
Before Width: | Height: | Size: 418 KiB After Width: | Height: | Size: 418 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/reset_code_flow.dia
vendored
Normal file
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/reset_code_no_boot_type_check.png
vendored
Normal file
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/reset_code_no_checks.png
vendored
Normal file
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/reset_code_no_cpu_check.png
vendored
Normal file
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/rt-svc-descs-layout.png
vendored
Normal file
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/sec-int-handling.png
vendored
Normal file
|
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 169 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/secure_sw_stack_sp.png
vendored
Normal file
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/secure_sw_stack_tos.png
vendored
Normal file
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/xlat_align.dia
vendored
Normal file
BIN
firmware/coreboot/3rdparty/arm-trusted-firmware/docs/diagrams/xlat_align.png
vendored
Normal file
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |